Initial code.

This commit is contained in:
gibbed
2017-11-07 21:49:37 -06:00
parent 1010ccdc9b
commit b6b737f84c
94 changed files with 6804 additions and 0 deletions

BIN
SAM.Game/Blank.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

View File

@@ -0,0 +1,34 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System.Windows.Forms;
namespace SAM.Game
{
internal class DoubleBufferedListView : ListView
{
public DoubleBufferedListView()
{
base.DoubleBuffered = true;
}
}
}

333
SAM.Game/KeyValue.cs Normal file
View File

@@ -0,0 +1,333 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace SAM.Game
{
internal class KeyValue
{
private static readonly KeyValue _Invalid = new KeyValue();
public string Name = "<root>";
public KeyValueType Type = KeyValueType.None;
public object Value;
public bool Valid;
public List<KeyValue> Children = null;
public KeyValue this[string key]
{
get
{
if (this.Children == null)
{
return _Invalid;
}
var child = this.Children.SingleOrDefault(
c => c.Name.ToLowerInvariant() == key.ToLowerInvariant());
if (child == null)
{
return _Invalid;
}
return child;
}
}
public string AsString(string defaultValue)
{
if (this.Valid == false)
{
return defaultValue;
}
if (this.Value == null)
{
return defaultValue;
}
return this.Value.ToString();
}
public int AsInteger(int defaultValue)
{
if (this.Valid == false)
{
return defaultValue;
}
switch (this.Type)
{
case KeyValueType.String:
case KeyValueType.WideString:
{
int value;
if (int.TryParse((string)this.Value, out value) == false)
{
return defaultValue;
}
return value;
}
case KeyValueType.Int32:
{
return (int)this.Value;
}
case KeyValueType.Float32:
{
return (int)((float)this.Value);
}
case KeyValueType.UInt64:
{
return (int)((ulong)this.Value & 0xFFFFFFFF);
}
}
return defaultValue;
}
public float AsFloat(float defaultValue)
{
if (this.Valid == false)
{
return defaultValue;
}
switch (this.Type)
{
case KeyValueType.String:
case KeyValueType.WideString:
{
float value;
if (float.TryParse((string)this.Value, out value) == false)
{
return defaultValue;
}
return value;
}
case KeyValueType.Int32:
{
return (int)this.Value;
}
case KeyValueType.Float32:
{
return (float)this.Value;
}
case KeyValueType.UInt64:
{
return (ulong)this.Value & 0xFFFFFFFF;
}
}
return defaultValue;
}
public bool AsBoolean(bool defaultValue)
{
if (this.Valid == false)
{
return defaultValue;
}
switch (this.Type)
{
case KeyValueType.String:
case KeyValueType.WideString:
{
int value;
if (int.TryParse((string)this.Value, out value) == false)
{
return defaultValue;
}
return value != 0;
}
case KeyValueType.Int32:
{
return ((int)this.Value) != 0;
}
case KeyValueType.Float32:
{
return ((int)((float)this.Value)) != 0;
}
case KeyValueType.UInt64:
{
return ((ulong)this.Value) != 0;
}
}
return defaultValue;
}
public override string ToString()
{
if (this.Valid == false)
{
return "<invalid>";
}
if (this.Type == KeyValueType.None)
{
return this.Name;
}
return string.Format("{0} = {1}", this.Name, this.Value);
}
public static KeyValue LoadAsBinary(string path)
{
if (File.Exists(path) == false)
{
return null;
}
try
{
var input = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
var kv = new KeyValue();
if (kv.ReadAsBinary(input) == false)
{
return null;
}
input.Close();
return kv;
}
catch (Exception)
{
return null;
}
}
public bool ReadAsBinary(Stream input)
{
this.Children = new List<KeyValue>();
try
{
while (true)
{
var type = (KeyValueType)input.ReadValueU8();
if (type == KeyValueType.End)
{
break;
}
var current = new KeyValue
{
Type = type,
Name = input.ReadStringUnicode(),
};
switch (type)
{
case KeyValueType.None:
{
current.ReadAsBinary(input);
break;
}
case KeyValueType.String:
{
current.Valid = true;
current.Value = input.ReadStringUnicode();
break;
}
case KeyValueType.WideString:
{
throw new FormatException("wstring is unsupported");
}
case KeyValueType.Int32:
{
current.Valid = true;
current.Value = input.ReadValueS32();
break;
}
case KeyValueType.UInt64:
{
current.Valid = true;
current.Value = input.ReadValueU64();
break;
}
case KeyValueType.Float32:
{
current.Valid = true;
current.Value = input.ReadValueF32();
break;
}
case KeyValueType.Color:
{
current.Valid = true;
current.Value = input.ReadValueU32();
break;
}
case KeyValueType.Pointer:
{
current.Valid = true;
current.Value = input.ReadValueU32();
break;
}
default:
{
throw new FormatException();
}
}
if (input.Position >= input.Length)
{
throw new FormatException();
}
this.Children.Add(current);
}
this.Valid = true;
return input.Position == input.Length;
}
catch (Exception)
{
return false;
}
}
}
}

37
SAM.Game/KeyValueType.cs Normal file
View File

@@ -0,0 +1,37 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game
{
internal enum KeyValueType : byte
{
None = 0,
String = 1,
Int32 = 2,
Float32 = 3,
Pointer = 4,
WideString = 5,
Color = 6,
UInt64 = 7,
End = 8,
}
}

22
SAM.Game/LICENSE.txt Normal file
View File

@@ -0,0 +1,22 @@
zlib License
Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

359
SAM.Game/Manager.Designer.cs generated Normal file
View File

@@ -0,0 +1,359 @@
namespace SAM.Game
{
partial class Manager
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Windows.Forms.ToolStripSeparator _ToolStripSeparator1;
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Manager));
this._MainToolStrip = new System.Windows.Forms.ToolStrip();
this._StoreButton = new System.Windows.Forms.ToolStripButton();
this._ReloadButton = new System.Windows.Forms.ToolStripButton();
this._ResetButton = new System.Windows.Forms.ToolStripButton();
this._AchievementImageList = new System.Windows.Forms.ImageList(this.components);
this._MainStatusStrip = new System.Windows.Forms.StatusStrip();
this._CountryStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this._GameStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this._DownloadStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this._CallbackTimer = new System.Windows.Forms.Timer(this.components);
this._MainTabControl = new System.Windows.Forms.TabControl();
this._AchievementsTabPage = new System.Windows.Forms.TabPage();
this._AchievementListView = new SAM.Game.DoubleBufferedListView();
this._AchievementNameColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this._AchievementDescriptionColumnHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this._AchievementsToolStrip = new System.Windows.Forms.ToolStrip();
this._LockAllButton = new System.Windows.Forms.ToolStripButton();
this._InvertAllButton = new System.Windows.Forms.ToolStripButton();
this._UnlockAllButton = new System.Windows.Forms.ToolStripButton();
this._StatisticsTabPage = new System.Windows.Forms.TabPage();
this._EnableStatsEditingCheckBox = new System.Windows.Forms.CheckBox();
this._StatisticsDataGridView = new System.Windows.Forms.DataGridView();
_ToolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
this._MainToolStrip.SuspendLayout();
this._MainStatusStrip.SuspendLayout();
this._MainTabControl.SuspendLayout();
this._AchievementsTabPage.SuspendLayout();
this._AchievementsToolStrip.SuspendLayout();
this._StatisticsTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this._StatisticsDataGridView)).BeginInit();
this.SuspendLayout();
//
// _MainToolStrip
//
this._MainToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this._StoreButton,
this._ReloadButton,
_ToolStripSeparator1,
this._ResetButton});
this._MainToolStrip.Location = new System.Drawing.Point(0, 0);
this._MainToolStrip.Name = "_MainToolStrip";
this._MainToolStrip.Size = new System.Drawing.Size(632, 25);
this._MainToolStrip.TabIndex = 1;
//
// _StoreButton
//
this._StoreButton.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
this._StoreButton.Enabled = false;
this._StoreButton.Image = global::SAM.Game.Properties.Resources.Save;
this._StoreButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._StoreButton.Name = "_StoreButton";
this._StoreButton.Size = new System.Drawing.Size(54, 22);
this._StoreButton.Text = "Store";
this._StoreButton.ToolTipText = "Store achievements and statistics for active game.";
this._StoreButton.Click += new System.EventHandler(this.OnStore);
//
// _ReloadButton
//
this._ReloadButton.Enabled = false;
this._ReloadButton.Image = global::SAM.Game.Properties.Resources.Refresh;
this._ReloadButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._ReloadButton.Name = "_ReloadButton";
this._ReloadButton.Size = new System.Drawing.Size(66, 22);
this._ReloadButton.Text = "Refresh";
this._ReloadButton.ToolTipText = "Refresh achievements and statistics for active game.";
this._ReloadButton.Click += new System.EventHandler(this.OnRefresh);
//
// _ToolStripSeparator1
//
_ToolStripSeparator1.Name = "_ToolStripSeparator1";
_ToolStripSeparator1.Size = new System.Drawing.Size(6, 25);
//
// _ResetButton
//
this._ResetButton.Image = global::SAM.Game.Properties.Resources.Reset;
this._ResetButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._ResetButton.Name = "_ResetButton";
this._ResetButton.Size = new System.Drawing.Size(55, 22);
this._ResetButton.Text = "Reset";
this._ResetButton.ToolTipText = "Reset achievements and/or statistics for active game.";
this._ResetButton.Click += new System.EventHandler(this.OnResetAllStats);
//
// _AchievementImageList
//
this._AchievementImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
this._AchievementImageList.ImageSize = new System.Drawing.Size(64, 64);
this._AchievementImageList.TransparentColor = System.Drawing.Color.Transparent;
//
// _MainStatusStrip
//
this._MainStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this._CountryStatusLabel,
this._GameStatusLabel,
this._DownloadStatusLabel});
this._MainStatusStrip.Location = new System.Drawing.Point(0, 370);
this._MainStatusStrip.Name = "_MainStatusStrip";
this._MainStatusStrip.Size = new System.Drawing.Size(632, 22);
this._MainStatusStrip.TabIndex = 4;
this._MainStatusStrip.Text = "statusStrip1";
//
// _CountryStatusLabel
//
this._CountryStatusLabel.Name = "_CountryStatusLabel";
this._CountryStatusLabel.Size = new System.Drawing.Size(0, 17);
//
// _GameStatusLabel
//
this._GameStatusLabel.Name = "_GameStatusLabel";
this._GameStatusLabel.Size = new System.Drawing.Size(617, 17);
this._GameStatusLabel.Spring = true;
this._GameStatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// _DownloadStatusLabel
//
this._DownloadStatusLabel.Image = global::SAM.Game.Properties.Resources.Download;
this._DownloadStatusLabel.Name = "_DownloadStatusLabel";
this._DownloadStatusLabel.Size = new System.Drawing.Size(111, 17);
this._DownloadStatusLabel.Text = "Download status";
this._DownloadStatusLabel.Visible = false;
//
// _CallbackTimer
//
this._CallbackTimer.Enabled = true;
this._CallbackTimer.Tick += new System.EventHandler(this.OnTimer);
//
// _MainTabControl
//
this._MainTabControl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._MainTabControl.Controls.Add(this._AchievementsTabPage);
this._MainTabControl.Controls.Add(this._StatisticsTabPage);
this._MainTabControl.Location = new System.Drawing.Point(8, 33);
this._MainTabControl.Name = "_MainTabControl";
this._MainTabControl.SelectedIndex = 0;
this._MainTabControl.Size = new System.Drawing.Size(616, 334);
this._MainTabControl.TabIndex = 5;
//
// _AchievementsTabPage
//
this._AchievementsTabPage.Controls.Add(this._AchievementListView);
this._AchievementsTabPage.Controls.Add(this._AchievementsToolStrip);
this._AchievementsTabPage.Location = new System.Drawing.Point(4, 22);
this._AchievementsTabPage.Name = "_AchievementsTabPage";
this._AchievementsTabPage.Padding = new System.Windows.Forms.Padding(3);
this._AchievementsTabPage.Size = new System.Drawing.Size(608, 308);
this._AchievementsTabPage.TabIndex = 0;
this._AchievementsTabPage.Text = "Achievements";
this._AchievementsTabPage.UseVisualStyleBackColor = true;
//
// _AchievementListView
//
this._AchievementListView.Activation = System.Windows.Forms.ItemActivation.OneClick;
this._AchievementListView.BackColor = System.Drawing.Color.Black;
this._AchievementListView.BackgroundImageTiled = true;
this._AchievementListView.CheckBoxes = true;
this._AchievementListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this._AchievementNameColumnHeader,
this._AchievementDescriptionColumnHeader});
this._AchievementListView.Dock = System.Windows.Forms.DockStyle.Fill;
this._AchievementListView.ForeColor = System.Drawing.Color.White;
this._AchievementListView.FullRowSelect = true;
this._AchievementListView.GridLines = true;
this._AchievementListView.HideSelection = false;
this._AchievementListView.LargeImageList = this._AchievementImageList;
this._AchievementListView.Location = new System.Drawing.Point(3, 28);
this._AchievementListView.Name = "_AchievementListView";
this._AchievementListView.Size = new System.Drawing.Size(602, 277);
this._AchievementListView.SmallImageList = this._AchievementImageList;
this._AchievementListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
this._AchievementListView.TabIndex = 4;
this._AchievementListView.UseCompatibleStateImageBehavior = false;
this._AchievementListView.View = System.Windows.Forms.View.Details;
this._AchievementListView.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.OnCheckAchievement);
//
// _AchievementNameColumnHeader
//
this._AchievementNameColumnHeader.Text = "Name";
this._AchievementNameColumnHeader.Width = 200;
//
// _AchievementDescriptionColumnHeader
//
this._AchievementDescriptionColumnHeader.Text = "Description";
this._AchievementDescriptionColumnHeader.Width = 380;
//
// _AchievementsToolStrip
//
this._AchievementsToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this._LockAllButton,
this._InvertAllButton,
this._UnlockAllButton});
this._AchievementsToolStrip.Location = new System.Drawing.Point(3, 3);
this._AchievementsToolStrip.Name = "_AchievementsToolStrip";
this._AchievementsToolStrip.Size = new System.Drawing.Size(602, 25);
this._AchievementsToolStrip.TabIndex = 5;
//
// _LockAllButton
//
this._LockAllButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this._LockAllButton.Image = global::SAM.Game.Properties.Resources.Lock;
this._LockAllButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._LockAllButton.Name = "_LockAllButton";
this._LockAllButton.Size = new System.Drawing.Size(23, 22);
this._LockAllButton.Text = "Lock All";
this._LockAllButton.ToolTipText = "Lock all achievements.";
this._LockAllButton.Click += new System.EventHandler(this.OnLockAll);
//
// _InvertAllButton
//
this._InvertAllButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this._InvertAllButton.Image = global::SAM.Game.Properties.Resources.Invert;
this._InvertAllButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._InvertAllButton.Name = "_InvertAllButton";
this._InvertAllButton.Size = new System.Drawing.Size(23, 22);
this._InvertAllButton.Text = "Invert All";
this._InvertAllButton.ToolTipText = "Invert all achievements.";
this._InvertAllButton.Click += new System.EventHandler(this.OnInvertAll);
//
// _UnlockAllButton
//
this._UnlockAllButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this._UnlockAllButton.Image = global::SAM.Game.Properties.Resources.Unlock;
this._UnlockAllButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._UnlockAllButton.Name = "_UnlockAllButton";
this._UnlockAllButton.Size = new System.Drawing.Size(23, 22);
this._UnlockAllButton.Text = "Unlock All";
this._UnlockAllButton.ToolTipText = "Unlock all achievements.";
this._UnlockAllButton.Click += new System.EventHandler(this.OnUnlockAll);
//
// _StatisticsTabPage
//
this._StatisticsTabPage.Controls.Add(this._EnableStatsEditingCheckBox);
this._StatisticsTabPage.Controls.Add(this._StatisticsDataGridView);
this._StatisticsTabPage.Location = new System.Drawing.Point(4, 22);
this._StatisticsTabPage.Name = "_StatisticsTabPage";
this._StatisticsTabPage.Padding = new System.Windows.Forms.Padding(3);
this._StatisticsTabPage.Size = new System.Drawing.Size(608, 308);
this._StatisticsTabPage.TabIndex = 1;
this._StatisticsTabPage.Text = "Statistics";
this._StatisticsTabPage.UseVisualStyleBackColor = true;
//
// _EnableStatsEditingCheckBox
//
this._EnableStatsEditingCheckBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._EnableStatsEditingCheckBox.AutoSize = true;
this._EnableStatsEditingCheckBox.Location = new System.Drawing.Point(6, 285);
this._EnableStatsEditingCheckBox.Name = "_EnableStatsEditingCheckBox";
this._EnableStatsEditingCheckBox.Size = new System.Drawing.Size(512, 17);
this._EnableStatsEditingCheckBox.TabIndex = 1;
this._EnableStatsEditingCheckBox.Text = "I understand by modifying the values of stats, I may screw things up and can\'t bl" +
"ame anyone but myself.";
this._EnableStatsEditingCheckBox.UseVisualStyleBackColor = true;
this._EnableStatsEditingCheckBox.CheckedChanged += new System.EventHandler(this.OnStatAgreementChecked);
//
// _StatisticsDataGridView
//
this._StatisticsDataGridView.AllowUserToAddRows = false;
this._StatisticsDataGridView.AllowUserToDeleteRows = false;
this._StatisticsDataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this._StatisticsDataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this._StatisticsDataGridView.Location = new System.Drawing.Point(6, 6);
this._StatisticsDataGridView.Name = "_StatisticsDataGridView";
this._StatisticsDataGridView.Size = new System.Drawing.Size(596, 273);
this._StatisticsDataGridView.TabIndex = 0;
this._StatisticsDataGridView.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.OnStatCellEndEdit);
this._StatisticsDataGridView.DataError += new System.Windows.Forms.DataGridViewDataErrorEventHandler(this.OnStatDataError);
//
// Manager
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(632, 392);
this.Controls.Add(this._MainToolStrip);
this.Controls.Add(this._MainTabControl);
this.Controls.Add(this._MainStatusStrip);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MinimumSize = new System.Drawing.Size(640, 50);
this.Name = "Manager";
this.Text = "Steam Achievement Manager 6.3";
this._MainToolStrip.ResumeLayout(false);
this._MainToolStrip.PerformLayout();
this._MainStatusStrip.ResumeLayout(false);
this._MainStatusStrip.PerformLayout();
this._MainTabControl.ResumeLayout(false);
this._AchievementsTabPage.ResumeLayout(false);
this._AchievementsTabPage.PerformLayout();
this._AchievementsToolStrip.ResumeLayout(false);
this._AchievementsToolStrip.PerformLayout();
this._StatisticsTabPage.ResumeLayout(false);
this._StatisticsTabPage.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this._StatisticsDataGridView)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.ToolStrip _MainToolStrip;
private System.Windows.Forms.ToolStripButton _StoreButton;
private System.Windows.Forms.ToolStripButton _ReloadButton;
private System.Windows.Forms.StatusStrip _MainStatusStrip;
private System.Windows.Forms.ToolStripStatusLabel _CountryStatusLabel;
private System.Windows.Forms.ToolStripStatusLabel _GameStatusLabel;
private System.Windows.Forms.ImageList _AchievementImageList;
private System.Windows.Forms.Timer _CallbackTimer;
private System.Windows.Forms.TabControl _MainTabControl;
private System.Windows.Forms.TabPage _AchievementsTabPage;
private System.Windows.Forms.TabPage _StatisticsTabPage;
private DoubleBufferedListView _AchievementListView;
private System.Windows.Forms.ColumnHeader _AchievementNameColumnHeader;
private System.Windows.Forms.ColumnHeader _AchievementDescriptionColumnHeader;
private System.Windows.Forms.ToolStrip _AchievementsToolStrip;
private System.Windows.Forms.ToolStripButton _LockAllButton;
private System.Windows.Forms.ToolStripButton _InvertAllButton;
private System.Windows.Forms.ToolStripButton _UnlockAllButton;
private System.Windows.Forms.DataGridView _StatisticsDataGridView;
public System.Windows.Forms.CheckBox _EnableStatsEditingCheckBox;
private System.Windows.Forms.ToolStripButton _ResetButton;
private System.Windows.Forms.ToolStripStatusLabel _DownloadStatusLabel;
}
}

843
SAM.Game/Manager.cs Normal file
View File

@@ -0,0 +1,843 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using APITypes = SAM.API.Types;
namespace SAM.Game
{
internal partial class Manager : Form
{
private readonly long _GameId;
private readonly API.Client _SteamClient;
private readonly WebClient _IconDownloader = new WebClient();
private readonly List<Stats.AchievementInfo> _IconQueue = new List<Stats.AchievementInfo>();
private readonly List<Stats.StatDefinition> _StatDefinitions = new List<Stats.StatDefinition>();
private readonly List<Stats.AchievementDefinition> _AchievementDefinitions =
new List<Stats.AchievementDefinition>();
private readonly BindingList<Stats.StatInfo> _Statistics = new BindingList<Stats.StatInfo>();
// ReSharper disable PrivateFieldCanBeConvertedToLocalVariable
private readonly API.Callbacks.UserStatsReceived _UserStatsReceivedCallback;
// ReSharper restore PrivateFieldCanBeConvertedToLocalVariable
//private API.Callback<APITypes.UserStatsStored> UserStatsStoredCallback;
public Manager(long gameId, API.Client client)
{
this.InitializeComponent();
this._MainTabControl.SelectedTab = this._AchievementsTabPage;
//this.statisticsList.Enabled = this.checkBox1.Checked;
this._AchievementImageList.Images.Add("Blank", new Bitmap(64, 64));
this._StatisticsDataGridView.AutoGenerateColumns = false;
this._StatisticsDataGridView.Columns.Add("name", "Name");
this._StatisticsDataGridView.Columns[0].ReadOnly = true;
this._StatisticsDataGridView.Columns[0].Width = 200;
this._StatisticsDataGridView.Columns[0].DataPropertyName = "DisplayName";
this._StatisticsDataGridView.Columns.Add("value", "Value");
this._StatisticsDataGridView.Columns[1].ReadOnly = this._EnableStatsEditingCheckBox.Checked == false;
this._StatisticsDataGridView.Columns[1].Width = 90;
this._StatisticsDataGridView.Columns[1].DataPropertyName = "Value";
this._StatisticsDataGridView.Columns.Add("extra", "Extra");
this._StatisticsDataGridView.Columns[2].ReadOnly = true;
this._StatisticsDataGridView.Columns[2].Width = 200;
this._StatisticsDataGridView.Columns[2].DataPropertyName = "Extra";
this._StatisticsDataGridView.DataSource = new BindingSource
{
DataSource = this._Statistics,
};
this._GameId = gameId;
this._SteamClient = client;
this._IconDownloader.DownloadDataCompleted += this.OnIconDownload;
string name = this._SteamClient.SteamApps001.GetAppData((uint)this._GameId, "name");
if (name != null)
{
base.Text += " | " + name;
}
else
{
base.Text += " | " + this._GameId.ToString(CultureInfo.InvariantCulture);
}
this._UserStatsReceivedCallback = client.CreateAndRegisterCallback<API.Callbacks.UserStatsReceived>();
this._UserStatsReceivedCallback.OnRun += this.OnUserStatsReceived;
//this.UserStatsStoredCallback = new API.Callback(1102, new API.Callback.CallbackFunction(this.OnUserStatsStored));
this.RefreshStats();
}
private void AddAchievementIcon(Stats.AchievementInfo info, Image icon)
{
if (icon == null)
{
info.ImageIndex = 0;
}
else
{
info.ImageIndex = this._AchievementImageList.Images.Count;
this._AchievementImageList.Images.Add(info.IsAchieved == true ? info.IconNormal : info.IconLocked, icon);
}
}
private void OnIconDownload(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null && e.Cancelled == false)
{
var info = e.UserState as Stats.AchievementInfo;
Bitmap bitmap;
try
{
using (var stream = new MemoryStream())
{
stream.Write(e.Result, 0, e.Result.Length);
bitmap = new Bitmap(stream);
}
}
catch (Exception)
{
bitmap = null;
}
this.AddAchievementIcon(info, bitmap);
this._AchievementListView.Update();
}
this.DownloadNextIcon();
}
private void DownloadNextIcon()
{
if (this._IconQueue.Count == 0)
{
this._DownloadStatusLabel.Visible = false;
return;
}
if (this._IconDownloader.IsBusy)
{
return;
}
this._DownloadStatusLabel.Text = string.Format("Downloading {0} icons...", this._IconQueue.Count);
this._DownloadStatusLabel.Visible = true;
var info = this._IconQueue[0];
this._IconQueue.RemoveAt(0);
this._IconDownloader.DownloadDataAsync(
new Uri(string.Format("http://media.steamcommunity.com/steamcommunity/public/images/apps/{0}/{1}",
this._GameId,
info.IsAchieved == true ? info.IconNormal : info.IconLocked)),
info);
}
private string TranslateError(int id)
{
switch (id)
{
case 2:
{
return "generic error -- this usually means you don't own the game";
}
}
return id.ToString(CultureInfo.InvariantCulture);
}
private string GetLocalizedString(KeyValue kv, string language, string defaultValue)
{
var name = kv[language].AsString("");
if (string.IsNullOrEmpty(name) == false)
{
return name;
}
if (language != "english")
{
name = kv["english"].AsString("");
if (string.IsNullOrEmpty(name) == false)
{
return name;
}
}
name = kv.AsString("");
if (string.IsNullOrEmpty(name) == false)
{
return name;
}
return defaultValue;
}
private bool LoadUserGameStatsSchema()
{
string path;
try
{
path = API.Steam.GetInstallPath();
path = Path.Combine(path, "appcache");
path = Path.Combine(path, "stats");
path = Path.Combine(path, string.Format("UserGameStatsSchema_{0}.bin", this._GameId));
if (File.Exists(path) == false)
{
return false;
}
}
catch
{
return false;
}
var kv = KeyValue.LoadAsBinary(path);
if (kv == null)
{
return false;
}
var currentLanguage = this._SteamClient.SteamApps003.GetCurrentGameLanguage();
//var currentLanguage = "german";
this._AchievementDefinitions.Clear();
this._StatDefinitions.Clear();
var stats = kv[this._GameId.ToString(CultureInfo.InvariantCulture)]["stats"];
if (stats.Valid == false ||
stats.Children == null)
{
return false;
}
foreach (var stat in stats.Children)
{
if (stat.Valid == false)
{
continue;
}
var rawType = stat["type_int"].Valid
? stat["type_int"].AsInteger(0)
: stat["type"].AsInteger(0);
var type = (APITypes.UserStatType)rawType;
switch (type)
{
case API.Types.UserStatType.Invalid:
{
break;
}
case APITypes.UserStatType.Integer:
{
var id = stat["name"].AsString("");
string name = GetLocalizedString(stat["display"]["name"], currentLanguage, id);
this._StatDefinitions.Add(new Stats.IntegerStatDefinition()
{
Id = stat["name"].AsString(""),
DisplayName = name,
MinValue = stat["min"].AsInteger(int.MinValue),
MaxValue = stat["max"].AsInteger(int.MaxValue),
MaxChange = stat["maxchange"].AsInteger(0),
IncrementOnly = stat["incrementonly"].AsBoolean(false),
DefaultValue = stat["default"].AsInteger(0),
Permission = stat["permission"].AsInteger(0),
});
break;
}
case APITypes.UserStatType.Float:
case APITypes.UserStatType.AverageRate:
{
var id = stat["name"].AsString("");
string name = GetLocalizedString(stat["display"]["name"], currentLanguage, id);
this._StatDefinitions.Add(new Stats.FloatStatDefinition()
{
Id = stat["name"].AsString(""),
DisplayName = name,
MinValue = stat["min"].AsFloat(float.MinValue),
MaxValue = stat["max"].AsFloat(float.MaxValue),
MaxChange = stat["maxchange"].AsFloat(0.0f),
IncrementOnly = stat["incrementonly"].AsBoolean(false),
DefaultValue = stat["default"].AsFloat(0.0f),
Permission = stat["permission"].AsInteger(0),
});
break;
}
case APITypes.UserStatType.Achievements:
case APITypes.UserStatType.GroupAchievements:
{
if (stat.Children != null)
{
foreach (var bits in stat.Children.Where(
b => b.Name.ToLowerInvariant() == "bits"))
{
if (bits.Valid == false ||
bits.Children == null)
{
continue;
}
foreach (var bit in bits.Children)
{
string id = bit["name"].AsString("");
string name = GetLocalizedString(bit["display"]["name"], currentLanguage, id);
string desc = GetLocalizedString(bit["display"]["desc"], currentLanguage, "");
this._AchievementDefinitions.Add(new Stats.AchievementDefinition()
{
Id = id,
Name = name,
Description = desc,
IconNormal = bit["display"]["icon"].AsString(""),
IconLocked = bit["display"]["icon_gray"].AsString(""),
IsHidden = bit["display"]["hidden"].AsBoolean(false),
Permission = bit["permission"].AsInteger(0),
});
}
}
}
break;
}
default:
{
throw new InvalidOperationException("invalid stat type");
}
}
}
return true;
}
private void OnUserStatsReceived(APITypes.UserStatsReceived param)
{
if (param.Result != 1)
{
this._GameStatusLabel.Text = string.Format(
"Error while retrieving stats: {0}",
TranslateError(param.Result));
this.EnableInput();
return;
}
if (this.LoadUserGameStatsSchema() == false)
{
this._GameStatusLabel.Text = "Failed to load schema.";
this.EnableInput();
return;
}
try
{
this.GetAchievements();
this.GetStatistics();
}
catch (Exception e)
{
this._GameStatusLabel.Text = "Error when handling stats retrieval.";
this.EnableInput();
MessageBox.Show(
"Error when handling stats retrieval:\n" + e,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
this._GameStatusLabel.Text = string.Format(
"Retrieved {0} achievements and {1} statistics.",
this._AchievementListView.Items.Count,
this._StatisticsDataGridView.Rows.Count);
this.EnableInput();
}
private void RefreshStats()
{
this._AchievementListView.Items.Clear();
this._StatisticsDataGridView.Rows.Clear();
if (this._SteamClient.SteamUserStats.RequestCurrentStats() == false)
{
MessageBox.Show(this, "Failed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
this._GameStatusLabel.Text = "Retrieving stat information...";
this.DisableInput();
}
private bool _IsUpdatingAchievementList;
private void GetAchievements()
{
this._IsUpdatingAchievementList = true;
this._AchievementListView.Items.Clear();
this._AchievementListView.BeginUpdate();
//this.Achievements.Clear();
foreach (var def in this._AchievementDefinitions)
{
if (def.Id == string.Empty)
{
continue;
}
bool isAchieved;
if (this._SteamClient.SteamUserStats.GetAchievementState(def.Id, out isAchieved) == false)
{
continue;
}
var info = new Stats.AchievementInfo()
{
Id = def.Id,
IsAchieved = isAchieved,
IconNormal = string.IsNullOrEmpty(def.IconNormal) ? null : def.IconNormal,
IconLocked = string.IsNullOrEmpty(def.IconLocked) ? def.IconNormal : def.IconLocked,
Permission = def.Permission,
Name = def.Name,
Description = def.Description,
};
var item = new ListViewItem()
{
Checked = isAchieved,
Tag = info,
Text = info.Name,
BackColor = (def.Permission & 2) == 0 ? Color.Black : Color.FromArgb(64, 0, 0),
};
info.Item = item;
if (item.Text.StartsWith("#") == true)
{
item.Text = info.Id;
}
else
{
item.SubItems.Add(info.Description);
}
info.ImageIndex = 0;
this.AddAchievementToIconQueue(info, false);
this._AchievementListView.Items.Add(item);
//this.Achievements.Add(info.Id, info);
}
this._AchievementListView.EndUpdate();
this._IsUpdatingAchievementList = false;
this.DownloadNextIcon();
}
private void GetStatistics()
{
this._Statistics.Clear();
foreach (var rdef in this._StatDefinitions)
{
if (string.IsNullOrEmpty(rdef.Id) == true)
{
continue;
}
if (rdef is Stats.IntegerStatDefinition)
{
var def = (Stats.IntegerStatDefinition)rdef;
int value;
if (this._SteamClient.SteamUserStats.GetStatValue(def.Id, out value))
{
this._Statistics.Add(new Stats.IntStatInfo()
{
Id = def.Id,
DisplayName = def.DisplayName,
IntValue = value,
OriginalValue = value,
IsIncrementOnly = def.IncrementOnly,
Permission = def.Permission,
});
}
}
else if (rdef is Stats.FloatStatDefinition)
{
var def = (Stats.FloatStatDefinition)rdef;
float value;
if (this._SteamClient.SteamUserStats.GetStatValue(def.Id, out value))
{
this._Statistics.Add(new Stats.FloatStatInfo()
{
Id = def.Id,
DisplayName = def.DisplayName,
FloatValue = value,
OriginalValue = value,
IsIncrementOnly = def.IncrementOnly,
Permission = def.Permission,
});
}
}
}
}
private void AddAchievementToIconQueue(Stats.AchievementInfo info, bool startDownload)
{
int imageIndex = this._AchievementImageList.Images.IndexOfKey(
info.IsAchieved == true ? info.IconNormal : info.IconLocked);
if (imageIndex >= 0)
{
info.ImageIndex = imageIndex;
}
else
{
this._IconQueue.Add(info);
if (startDownload == true)
{
this.DownloadNextIcon();
}
}
}
private int StoreAchievements()
{
if (this._AchievementListView.Items.Count == 0)
{
return 0;
}
var achievements = new List<Stats.AchievementInfo>();
foreach (ListViewItem item in this._AchievementListView.Items)
{
var achievementInfo = item.Tag as Stats.AchievementInfo;
if (achievementInfo != null &&
achievementInfo.IsAchieved != item.Checked)
{
achievementInfo.IsAchieved = item.Checked;
achievements.Add(item.Tag as Stats.AchievementInfo);
}
}
if (achievements.Count == 0)
{
return 0;
}
foreach (Stats.AchievementInfo info in achievements)
{
if (this._SteamClient.SteamUserStats.SetAchievement(info.Id, info.IsAchieved) == false)
{
MessageBox.Show(
this,
string.Format("An error occured while setting the state for {0}, aborting store.", info.Id),
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return -1;
}
}
return achievements.Count;
}
private int StoreStatistics()
{
if (this._Statistics.Count == 0)
{
return 0;
}
var statistics = this._Statistics.Where(stat => stat.IsModified == true).ToList();
if (statistics.Count == 0)
{
return 0;
}
foreach (Stats.StatInfo stat in statistics)
{
if (stat is Stats.IntStatInfo)
{
var intStat = (Stats.IntStatInfo)stat;
if (this._SteamClient.SteamUserStats.SetStatValue(
intStat.Id,
intStat.IntValue) == false)
{
MessageBox.Show(
this,
string.Format("An error occured while setting the value for {0}, aborting store.", stat.Id),
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return -1;
}
}
else if (stat is Stats.FloatStatInfo)
{
var floatStat = (Stats.FloatStatInfo)stat;
if (this._SteamClient.SteamUserStats.SetStatValue(
floatStat.Id,
floatStat.FloatValue) == false)
{
MessageBox.Show(
this,
string.Format("An error occured while setting the value for {0}, aborting store.", stat.Id),
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return -1;
}
}
else
{
throw new Exception();
}
}
return statistics.Count;
}
private void DisableInput()
{
this._ReloadButton.Enabled = false;
this._StoreButton.Enabled = false;
}
private void EnableInput()
{
this._ReloadButton.Enabled = true;
this._StoreButton.Enabled = true;
}
private void OnTimer(object sender, EventArgs e)
{
this._CallbackTimer.Enabled = false;
this._SteamClient.RunCallbacks(false);
this._CallbackTimer.Enabled = true;
}
private void OnRefresh(object sender, EventArgs e)
{
this.RefreshStats();
}
private void OnLockAll(object sender, EventArgs e)
{
foreach (ListViewItem item in this._AchievementListView.Items)
{
item.Checked = false;
}
}
private void OnInvertAll(object sender, EventArgs e)
{
foreach (ListViewItem item in this._AchievementListView.Items)
{
item.Checked = !item.Checked;
}
}
private void OnUnlockAll(object sender, EventArgs e)
{
foreach (ListViewItem item in this._AchievementListView.Items)
{
item.Checked = true;
}
}
private bool Store()
{
if (this._SteamClient.SteamUserStats.StoreStats() == false)
{
MessageBox.Show(
this,
"An error occured while storing, aborting.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return false;
}
return true;
}
private void OnStore(object sender, EventArgs e)
{
int achievements = this.StoreAchievements();
if (achievements < 0)
{
this.RefreshStats();
return;
}
int stats = this.StoreStatistics();
if (stats < 0)
{
this.RefreshStats();
return;
}
if (this.Store() == false)
{
this.RefreshStats();
return;
}
MessageBox.Show(
this,
string.Format("Stored {0} achievements and {1} statistics.", achievements, stats),
"Information",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
this.RefreshStats();
}
private void OnStatDataError(object sender, DataGridViewDataErrorEventArgs e)
{
if (e.Context == DataGridViewDataErrorContexts.Commit)
{
if (e.Exception is Stats.StatIsProtectedException)
{
e.ThrowException = false;
e.Cancel = true;
var view = (DataGridView)sender;
view.Rows[e.RowIndex].ErrorText = "Stat is protected! -- you can't modify it";
}
else
{
e.ThrowException = false;
e.Cancel = true;
var view = (DataGridView)sender;
view.Rows[e.RowIndex].ErrorText = "Invalid value";
}
}
}
private void OnStatAgreementChecked(object sender, EventArgs e)
{
this._StatisticsDataGridView.Columns[1].ReadOnly = this._EnableStatsEditingCheckBox.Checked == false;
}
private void OnStatCellEndEdit(object sender, DataGridViewCellEventArgs e)
{
var view = (DataGridView)sender;
view.Rows[e.RowIndex].ErrorText = "";
}
private void OnResetAllStats(object sender, EventArgs e)
{
if (MessageBox.Show(
"Are you absolutely sure you want to reset stats?",
"Warning",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning) == DialogResult.No)
{
return;
}
bool achievementsToo = DialogResult.Yes == MessageBox.Show(
"Do you want to reset achievements too?",
"Question",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (MessageBox.Show(
"Really really sure?",
"Warning",
MessageBoxButtons.YesNo,
MessageBoxIcon.Error) == DialogResult.No)
{
return;
}
if (this._SteamClient.SteamUserStats.ResetAllStats(achievementsToo) == false)
{
MessageBox.Show(this, "Failed.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
this.RefreshStats();
}
private void OnCheckAchievement(object sender, ItemCheckEventArgs e)
{
if (sender != this._AchievementListView)
{
return;
}
if (this._IsUpdatingAchievementList == true)
{
return;
}
var info = this._AchievementListView.Items[e.Index].Tag
as Stats.AchievementInfo;
if (info == null)
{
return;
}
if ((info.Permission & 2) != 0)
{
MessageBox.Show(
this,
"Sorry, but this is a protected achievement and cannot be managed with Steam Achievement Manager.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
e.NewValue = e.CurrentValue;
}
}
}
}

149
SAM.Game/Manager.resx Normal file
View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="_MainToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="_ToolStripSeparator1.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="_AchievementImageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>352, 20</value>
</metadata>
<metadata name="_MainStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>230, 17</value>
</metadata>
<metadata name="_CallbackTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>502, 20</value>
</metadata>
<metadata name="_AchievementsToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>628, 20</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAEBAQAAEABAAoAQAAFgAAACgAAAAQAAAAIAAAAAEABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AADAgP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA
</value>
</data>
</root>

92
SAM.Game/Program.cs Normal file
View File

@@ -0,0 +1,92 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System;
using System.Diagnostics;
using System.Windows.Forms;
namespace SAM.Game
{
internal static class Program
{
[STAThread]
public static void Main(string[] args)
{
long appId;
if (args.Length == 0)
{
Process.Start("SAM.Picker.exe");
return;
}
if (long.TryParse(args[0], out appId) == false)
{
MessageBox.Show(
"Could not parse application ID from commandline argument.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
if (API.Steam.GetInstallPath() == Application.StartupPath)
{
MessageBox.Show(
"This tool declines to being run from the Steam directory.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
API.Client client;
try
{
client = new API.Client();
if (client.Initialize(appId) == false)
{
MessageBox.Show(
"Steam is not running. Please start Steam then run this tool again.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
}
catch (DllNotFoundException)
{
MessageBox.Show(
"You've caused an exceptional error!",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Manager(appId, client));
}
}
}

View File

@@ -0,0 +1,61 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Steam Achievement Manager")]
[assembly: AssemblyDescription("A manager for game achievements in Steam.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Gibbed")]
[assembly: AssemblyProduct("SAM.Game")]
[assembly: AssemblyCopyright("Copyright © Gibbed 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("0e6ba693-1ffa-44a0-a3eb-556272789273")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("7.0.0.0")]
[assembly: AssemblyFileVersion("7.0.0.0")]

119
SAM.Game/Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,119 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SAM.Game.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SAM.Game.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
internal static System.Drawing.Bitmap Download {
get {
object obj = ResourceManager.GetObject("Download", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap Invert {
get {
object obj = ResourceManager.GetObject("Invert", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap Lock {
get {
object obj = ResourceManager.GetObject("Lock", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap Refresh {
get {
object obj = ResourceManager.GetObject("Refresh", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap Reset {
get {
object obj = ResourceManager.GetObject("Reset", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap Sad {
get {
object obj = ResourceManager.GetObject("Sad", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap Save {
get {
object obj = ResourceManager.GetObject("Save", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
internal static System.Drawing.Bitmap Unlock {
get {
object obj = ResourceManager.GetObject("Unlock", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="Lock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\lock.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Refresh" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\arrow-circle-double.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Unlock" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\lock-unlock.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Reset" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\bomb.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Invert" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\lock--pencil.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Save" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\transmitter.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Sad" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\poop-smiley-sad-enlarged.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Download" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\download-cloud.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

BIN
SAM.Game/Resources/bomb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 752 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

BIN
SAM.Game/Resources/lock.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 842 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 B

155
SAM.Game/SAM.Game.csproj Normal file
View File

@@ -0,0 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{7640DE31-E54E-45F9-9CF0-8DF3A3EA30FC}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SAM.Game</RootNamespace>
<AssemblyName>SAM.Game</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ApplicationIcon>Blank.ico</ApplicationIcon>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\upload\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
<PlatformTarget>x86</PlatformTarget>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Stats\AchievementInfo.cs" />
<Compile Include="DoubleBufferedListView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="KeyValue.cs" />
<Compile Include="KeyValueType.cs" />
<Compile Include="Manager.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Manager.Designer.cs">
<DependentUpon>Manager.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Manager.resx">
<DependentUpon>Manager.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="Stats\FloatStatInfo.cs" />
<Compile Include="Stats\IntStatInfo.cs" />
<Compile Include="Stats\StatFlags.cs" />
<Compile Include="Stats\StatInfo.cs" />
<Compile Include="Stats\AchievementDefinition.cs" />
<Compile Include="Stats\FloatStatDefinition.cs" />
<Compile Include="Stats\IntegerStatDefinition.cs" />
<Compile Include="Stats\StatDefinition.cs" />
<Compile Include="Stats\StatIsProtectedException.cs" />
<Compile Include="StreamHelpers.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Blank.ico" />
<Content Include="Resources\arrow-circle-double.png" />
<Content Include="Resources\bomb.png" />
<Content Include="Resources\download-cloud.png" />
<Content Include="Resources\lock--pencil.png" />
<Content Include="Resources\lock-unlock.png" />
<Content Include="Resources\lock.png" />
<Content Include="Resources\poop-smiley-sad-enlarged.png" />
<Content Include="Resources\poop-smiley-sad.png" />
<Content Include="Resources\transmitter.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SAM.API\SAM.API.csproj">
<Project>{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}</Project>
<Name>SAM.API</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeEditing/Localization/Localizable/@EntryValue">No</s:String></wpf:ResourceDictionary>

View File

@@ -0,0 +1,35 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game.Stats
{
internal class AchievementDefinition
{
public string Id;
public string Name;
public string Description;
public string IconNormal;
public string IconLocked;
public bool IsHidden;
public int Permission;
}
}

View File

@@ -0,0 +1,47 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System.Windows.Forms;
namespace SAM.Game.Stats
{
internal class AchievementInfo
{
public string Id;
public bool IsAchieved;
public int Permission;
public string IconNormal;
public string IconLocked;
public string Name;
public string Description;
public ListViewItem Item;
#region public int ImageIndex;
public int ImageIndex
{
get { return this.Item.ImageIndex; }
set { this.Item.ImageIndex = value; }
}
#endregion
}
}

View File

@@ -0,0 +1,33 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game.Stats
{
internal class FloatStatDefinition : StatDefinition
{
public float MinValue;
public float MaxValue;
public float MaxChange;
public bool IncrementOnly;
public float DefaultValue;
}
}

View File

@@ -0,0 +1,52 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game.Stats
{
internal class FloatStatInfo : StatInfo
{
public float OriginalValue;
public float FloatValue;
public override object Value
{
get { return this.FloatValue; }
set
{
var f = float.Parse((string)value);
if ((this.Permission & 2) != 0 &&
this.FloatValue.Equals(f) == false)
{
throw new StatIsProtectedException();
}
this.FloatValue = f;
}
}
public override bool IsModified
{
get { return this.FloatValue.Equals(this.OriginalValue) == false; }
}
}
}

View File

@@ -0,0 +1,52 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game.Stats
{
internal class IntStatInfo : StatInfo
{
public int OriginalValue;
public int IntValue;
public override object Value
{
get { return this.IntValue; }
set
{
var i = int.Parse((string)value);
if ((this.Permission & 2) != 0 &&
this.IntValue != i)
{
throw new StatIsProtectedException();
}
this.IntValue = i;
}
}
public override bool IsModified
{
get { return this.IntValue != this.OriginalValue; }
}
}
}

View File

@@ -0,0 +1,33 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game.Stats
{
internal class IntegerStatDefinition : StatDefinition
{
public int MinValue;
public int MaxValue;
public int MaxChange;
public bool IncrementOnly;
public int DefaultValue;
}
}

View File

@@ -0,0 +1,31 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game.Stats
{
internal abstract class StatDefinition
{
public string Id;
public string DisplayName;
public int Permission;
}
}

View File

@@ -0,0 +1,35 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System;
namespace SAM.Game.Stats
{
[Flags]
internal enum StatFlags
{
None = 0,
IncrementOnly = 1 << 0,
Protected = 1 << 1,
UnknownPermission = 1 << 2,
}
}

View File

@@ -0,0 +1,46 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
namespace SAM.Game.Stats
{
internal abstract class StatInfo
{
public abstract bool IsModified { get; }
public string Id { get; set; }
public string DisplayName { get; set; }
public abstract object Value { get; set; }
public bool IsIncrementOnly { get; set; }
public int Permission { get; set; }
public string Extra
{
get
{
var flags = StatFlags.None;
flags |= this.IsIncrementOnly == false ? 0 : StatFlags.IncrementOnly;
flags |= ((this.Permission & 2) != 0) == false ? 0 : StatFlags.Protected;
flags |= ((this.Permission & ~2) != 0) == false ? 0 : StatFlags.UnknownPermission;
return flags.ToString();
}
}
}
}

View File

@@ -0,0 +1,30 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System;
namespace SAM.Game.Stats
{
internal class StatIsProtectedException : Exception
{
}
}

115
SAM.Game/StreamHelpers.cs Normal file
View File

@@ -0,0 +1,115 @@
/* Copyright (c) 2017 Rick (rick 'at' gibbed 'dot' us)
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would
* be appreciated but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must not
* be misrepresented as being the original software.
*
* 3. This notice may not be removed or altered from any source
* distribution.
*/
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
namespace SAM.Game
{
internal static class StreamHelpers
{
public static byte ReadValueU8(this Stream stream)
{
return (byte)stream.ReadByte();
}
public static int ReadValueS32(this Stream stream)
{
var data = new byte[4];
int read = stream.Read(data, 0, 4);
Debug.Assert(read == 4);
return BitConverter.ToInt32(data, 0);
}
public static uint ReadValueU32(this Stream stream)
{
var data = new byte[4];
int read = stream.Read(data, 0, 4);
Debug.Assert(read == 4);
return BitConverter.ToUInt32(data, 0);
}
public static ulong ReadValueU64(this Stream stream)
{
var data = new byte[8];
int read = stream.Read(data, 0, 8);
Debug.Assert(read == 8);
return BitConverter.ToUInt64(data, 0);
}
public static float ReadValueF32(this Stream stream)
{
var data = new byte[4];
int read = stream.Read(data, 0, 4);
Debug.Assert(read == 4);
return BitConverter.ToSingle(data, 0);
}
internal static string ReadStringInternalDynamic(this Stream stream, Encoding encoding, char end)
{
int characterSize = encoding.GetByteCount("e");
Debug.Assert(characterSize == 1 || characterSize == 2 || characterSize == 4);
string characterEnd = end.ToString(CultureInfo.InvariantCulture);
int i = 0;
var data = new byte[128 * characterSize];
while (true)
{
if (i + characterSize > data.Length)
{
Array.Resize(ref data, data.Length + (128 * characterSize));
}
int read = stream.Read(data, i, characterSize);
Debug.Assert(read == characterSize);
if (encoding.GetString(data, i, characterSize) == characterEnd)
{
break;
}
i += characterSize;
}
if (i == 0)
{
return "";
}
return encoding.GetString(data, 0, i);
}
public static string ReadStringAscii(this Stream stream)
{
return stream.ReadStringInternalDynamic(Encoding.ASCII, '\0');
}
public static string ReadStringUnicode(this Stream stream)
{
return stream.ReadStringInternalDynamic(Encoding.UTF8, '\0');
}
}
}