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

22
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.

59
SAM.API/Callback.cs Normal file
View File

@@ -0,0 +1,59 @@
/* 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.Runtime.InteropServices;
namespace SAM.API
{
public abstract class Callback : ICallback
{
public delegate void CallbackFunction(IntPtr param);
public event CallbackFunction OnRun;
public abstract int Id { get; }
public abstract bool IsServer { get; }
public void Run(IntPtr param)
{
this.OnRun(param);
}
}
public abstract class Callback<TParameter> : ICallback
where TParameter : struct
{
public delegate void CallbackFunction(TParameter arg);
public event CallbackFunction OnRun;
public abstract int Id { get; }
public abstract bool IsServer { get; }
public void Run(IntPtr pvParam)
{
var data = (TParameter)Marshal.PtrToStructure(pvParam, typeof(TParameter));
this.OnRun(data);
}
}
}

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.API.Callbacks
{
public class AppDataChanged : Callback<Types.AppDataChanged>
{
public override int Id
{
get { return 1001; }
}
public override bool IsServer
{
get { return false; }
}
}
}

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.API.Callbacks
{
public class UserStatsReceived : Callback<Types.UserStatsReceived>
{
public override int Id
{
get { return 1101; }
}
public override bool IsServer
{
get { return false; }
}
}
}

140
SAM.API/Client.cs Normal file
View File

@@ -0,0 +1,140 @@
/* 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.Globalization;
using System.Linq;
namespace SAM.API
{
public class Client
{
public Wrappers.SteamClient009 SteamClient;
public Wrappers.SteamUser012 SteamUser;
public Wrappers.SteamUserStats007 SteamUserStats;
public Wrappers.SteamUtils005 SteamUtils;
public Wrappers.SteamApps001 SteamApps001;
public Wrappers.SteamApps003 SteamApps003;
private int _Pipe;
private int _User;
private readonly List<ICallback> _Callbacks = new List<ICallback>();
public bool Initialize(long appId)
{
if (appId != 0)
{
Environment.SetEnvironmentVariable("SteamAppId", appId.ToString(CultureInfo.InvariantCulture));
}
if (Steam.GetInstallPath() == null)
{
return false;
}
if (Steam.Load() == false)
{
return false;
}
this.SteamClient = Steam.CreateInterface<Wrappers.SteamClient009>("SteamClient009");
if (this.SteamClient == null)
{
return false;
}
this._Pipe = this.SteamClient.CreateSteamPipe();
if (this._Pipe == 0)
{
return false;
}
this._User = this.SteamClient.ConnectToGlobalUser(this._Pipe);
if (this._User == 0)
{
return false;
}
this.SteamUtils = this.SteamClient.GetSteamUtils004(this._Pipe);
if (appId > 0 && this.SteamUtils.GetAppId() != (uint)appId)
{
return false;
}
this.SteamUser = this.SteamClient.GetSteamUser012(this._User, this._Pipe);
this.SteamUserStats = this.SteamClient.GetSteamUserStats006(this._User, this._Pipe);
this.SteamApps001 = this.SteamClient.GetSteamApps001(this._User, this._Pipe);
this.SteamApps003 = this.SteamClient.GetSteamApps003(this._User, this._Pipe);
return true;
}
~Client()
{
if (this.SteamClient != null)
{
this.SteamClient.ReleaseUser(this._Pipe, this._User);
this._User = 0;
this.SteamClient.ReleaseSteamPipe(this._Pipe);
this._Pipe = 0;
}
}
public TCallback CreateAndRegisterCallback<TCallback>()
where TCallback : ICallback, new()
{
var callback = new TCallback();
this._Callbacks.Add(callback);
return callback;
}
private bool _RunningCallbacks;
public void RunCallbacks(bool server)
{
if (this._RunningCallbacks == true)
{
return;
}
this._RunningCallbacks = true;
Types.CallbackMessage message;
int call;
while (Steam.GetCallback(this._Pipe, out message, out call) == true)
{
var callbackId = message.Id;
foreach (ICallback callback in this._Callbacks.Where(
candidate => candidate.Id == callbackId &&
candidate.IsServer == server))
{
callback.Run(message.ParamPointer);
}
Steam.FreeLastCallback(this._Pipe);
}
this._RunningCallbacks = false;
}
}
}

33
SAM.API/ICallback.cs Normal file
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.
*/
using System;
namespace SAM.API
{
public interface ICallback
{
int Id { get; }
bool IsServer { get; }
void Run(IntPtr param);
}
}

31
SAM.API/INativeWrapper.cs Normal file
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.
*/
using System;
namespace SAM.API
{
public interface INativeWrapper
{
void SetupFunctions(IntPtr objectAddress);
}
}

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.
*/
using System;
using System.Runtime.InteropServices;
namespace SAM.API.Interfaces
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ISteamApps001
{
public IntPtr GetAppData;
}
}

View File

@@ -0,0 +1,40 @@
/* 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.Runtime.InteropServices;
namespace SAM.API.Interfaces
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ISteamApps003
{
public IntPtr IsSubscribed;
public IntPtr IsLowViolence;
public IntPtr IsCybercafe;
public IntPtr IsVACBanned;
public IntPtr GetCurrentGameLanguage;
public IntPtr GetAvailableGameLanguages;
public IntPtr IsSubscribedApp;
public IntPtr IsDlcInstalled;
}
}

View File

@@ -0,0 +1,54 @@
/* 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.Runtime.InteropServices;
namespace SAM.API.Interfaces
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ISteamClient009
{
public IntPtr CreateSteamPipe;
public IntPtr ReleaseSteamPipe;
public IntPtr ConnectToGlobalUser;
public IntPtr CreateLocalUser;
public IntPtr ReleaseUser;
public IntPtr GetISteamUser;
public IntPtr GetISteamGameServer;
public IntPtr SetLocalIPBinding;
public IntPtr GetISteamFriends;
public IntPtr GetISteamUtils;
public IntPtr GetISteamMatchmaking;
public IntPtr GetISteamMasterServerUpdater;
public IntPtr GetISteamMatchmakingServers;
public IntPtr GetISteamGenericInterface;
public IntPtr GetISteamUserStats;
public IntPtr GetISteamGameServerStats;
public IntPtr GetISteamApps;
public IntPtr GetISteamNetworking;
public IntPtr GetISteamRemoteStorage;
public IntPtr RunFrame;
public IntPtr GetIPCCallCount;
public IntPtr SetWarningMessageHook;
}
}

View File

@@ -0,0 +1,48 @@
/* 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.Runtime.InteropServices;
namespace SAM.API.Interfaces
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ISteamUser012
{
public IntPtr GetHSteamUser;
public IntPtr LoggedOn;
public IntPtr GetSteamID;
public IntPtr InitiateGameConnection;
public IntPtr TerminateGameConnection;
public IntPtr TrackAppUsageEvent;
public IntPtr GetUserDataFolder;
public IntPtr StartVoiceRecording;
public IntPtr StopVoiceRecording;
public IntPtr GetCompressedVoice;
public IntPtr DecompressVoice;
public IntPtr GetAuthSessionTicket;
public IntPtr BeginAuthSession;
public IntPtr EndAuthSession;
public IntPtr CancelAuthTicket;
public IntPtr UserHasLicenseForApp;
}
}

View File

@@ -0,0 +1,62 @@
/* 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.Runtime.InteropServices;
namespace SAM.API.Interfaces
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public class ISteamUserStats007
{
public IntPtr RequestCurrentStats;
public IntPtr GetStatFloat;
public IntPtr GetStatInteger;
public IntPtr SetStatFloat;
public IntPtr SetStatInteger;
public IntPtr UpdateAvgRateStat;
public IntPtr GetAchievement;
public IntPtr SetAchievement;
public IntPtr ClearAchievement;
public IntPtr GetAchievementAndUnlockTime;
public IntPtr StoreStats;
public IntPtr GetAchievementIcon;
public IntPtr GetAchievementDisplayAttribute;
public IntPtr IndicateAchievementProgress;
public IntPtr RequestUserStats;
public IntPtr GetUserStatFloat;
public IntPtr GetUserStatInt;
public IntPtr GetUserAchievement;
public IntPtr GetUserAchievementAndUnlockTime;
public IntPtr ResetAllStats;
public IntPtr FindOrCreateLeaderboard;
public IntPtr FindLeaderboard;
public IntPtr GetLeaderboardName;
public IntPtr GetLeaderboardEntryCount;
public IntPtr GetLeaderboardSortMethod;
public IntPtr GetLeaderboardDisplayType;
public IntPtr DownloadLeaderboardEntries;
public IntPtr GetDownloadedLeaderboardEntry;
public IntPtr UploadLeaderboardScore;
public IntPtr GetNumberOfCurrentPlayers;
}
}

View File

@@ -0,0 +1,51 @@
/* 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.Runtime.InteropServices;
namespace SAM.API.Interfaces
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct ISteamUtils005
{
public IntPtr GetSecondsSinceAppActive;
public IntPtr GetSecondsSinceComputerActive;
public IntPtr GetConnectedUniverse;
public IntPtr GetServerRealTime;
public IntPtr GetIPCountry;
public IntPtr GetImageSize;
public IntPtr GetImageRGBA;
public IntPtr GetCSERIPPort;
public IntPtr GetCurrentBatteryPower;
public IntPtr GetAppID;
public IntPtr SetOverlayNotificationPosition;
public IntPtr IsAPICallCompleted;
public IntPtr GetAPICallFailureReason;
public IntPtr GetAPICallResult;
public IntPtr RunFrame;
public IntPtr GetIPCCallCount;
public IntPtr SetWarningMessageHook;
public IntPtr IsOverlayEnabled;
public IntPtr OverlayNeedsPresent;
}
}

22
SAM.API/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.

33
SAM.API/NativeClass.cs Normal file
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.
*/
using System;
using System.Runtime.InteropServices;
namespace SAM.API
{
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
internal struct NativeClass
{
public IntPtr VirtualTable;
}
}

90
SAM.API/NativeWrapper.cs Normal file
View File

@@ -0,0 +1,90 @@
/* 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.Runtime.InteropServices;
namespace SAM.API
{
public abstract class NativeWrapper<TNativeFunctions> : INativeWrapper
{
protected IntPtr ObjectAddress;
protected TNativeFunctions Functions;
public override string ToString()
{
return string.Format(
"Steam Interface<{0}> #{1:X8}",
typeof(TNativeFunctions),
this.ObjectAddress.ToInt32());
}
public void SetupFunctions(IntPtr objectAddress)
{
this.ObjectAddress = objectAddress;
var iface = (NativeClass)Marshal.PtrToStructure(
this.ObjectAddress,
typeof(NativeClass));
this.Functions = (TNativeFunctions)Marshal.PtrToStructure(
iface.VirtualTable,
typeof(TNativeFunctions));
}
private readonly Dictionary<IntPtr, Delegate> _FunctionCache = new Dictionary<IntPtr, Delegate>();
protected Delegate GetDelegate<TDelegate>(IntPtr pointer)
{
Delegate function;
if (this._FunctionCache.ContainsKey(pointer) == false)
{
function = Marshal.GetDelegateForFunctionPointer(pointer, typeof(TDelegate));
this._FunctionCache[pointer] = function;
}
else
{
function = this._FunctionCache[pointer];
}
return function;
}
protected TDelegate GetFunction<TDelegate>(IntPtr pointer)
where TDelegate : class
{
return (TDelegate)((object)this.GetDelegate<TDelegate>(pointer));
}
protected void Call<TDelegate>(IntPtr pointer, params object[] args)
{
this.GetDelegate<TDelegate>(pointer).DynamicInvoke(args);
}
protected TReturn Call<TReturn, TDelegate>(IntPtr pointer, params object[] args)
{
return (TReturn)this.GetDelegate<TDelegate>(pointer).DynamicInvoke(args);
}
}
}

BIN
SAM.API/Pink.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

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 API")]
[assembly: AssemblyDescription("Easy to use classes for accessing the Steam API.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Gibbed")]
[assembly: AssemblyProduct("SAM.API")]
[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("5a9771a4-ca63-42aa-bbf6-0b2a0147a8ea")]
// 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")]

128
SAM.API/SAM.API.csproj Normal file
View File

@@ -0,0 +1,128 @@
<?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>{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SAM.API</RootNamespace>
<AssemblyName>SAM.API</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ApplicationIcon>Pink.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\Debug\</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>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<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.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Callbacks\AppDataChanged.cs" />
<Compile Include="Callbacks\UserStatsReceived.cs" />
<Compile Include="ICallback.cs" />
<Compile Include="Types\CallbackMessage.cs" />
<Compile Include="Wrappers\SteamUserStats007.cs" />
<Compile Include="Types\AccountType.cs" />
<Compile Include="Wrappers\SteamUser012.cs" />
<Compile Include="INativeWrapper.cs" />
<Compile Include="Interfaces\ISteamApps001.cs" />
<Compile Include="Interfaces\ISteamApps003.cs" />
<Compile Include="Interfaces\ISteamClient009.cs" />
<Compile Include="Interfaces\ISteamUser012.cs" />
<Compile Include="Interfaces\ISteamUserStats007.cs" />
<Compile Include="Interfaces\ISteamUtils005.cs" />
<Compile Include="NativeClass.cs" />
<Compile Include="Types\ItemRequestResult.cs" />
<Compile Include="Types\AppDataChanged.cs" />
<Compile Include="Wrappers\SteamApps003.cs" />
<Compile Include="Wrappers\SteamApps001.cs" />
<Compile Include="Callback.cs" />
<Compile Include="Wrappers\SteamClient009.cs" />
<Compile Include="Client.cs" />
<Compile Include="NativeWrapper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Steam.cs" />
<Compile Include="Types\UserItemsReceived.cs" />
<Compile Include="Types\UserStatsStored.cs" />
<Compile Include="Types\UserStatsReceived.cs" />
<Compile Include="Types\UserStatType.cs" />
<Compile Include="Wrappers\SteamUtils005.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Pink.ico" />
</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>
<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>

151
SAM.API/Steam.cs Normal file
View File

@@ -0,0 +1,151 @@
/* 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.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace SAM.API
{
public static class Steam
{
private struct Native
{
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr GetProcAddress(IntPtr module, string name);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr LoadLibraryEx(string path, IntPtr file, uint flags);
[DllImport("kernel32.dll", SetLastError = true)]
internal static extern IntPtr SetDllDirectory(string path);
internal const uint LoadWithAlteredSearchPath = 8;
}
private static Delegate GetExportDelegate<TDelegate>(IntPtr module, string name)
{
IntPtr address = Native.GetProcAddress(module, name);
return address == IntPtr.Zero ? null : Marshal.GetDelegateForFunctionPointer(address, typeof(TDelegate));
}
private static TDelegate GetExportFunction<TDelegate>(IntPtr module, string name)
where TDelegate : class
{
return (TDelegate)((object)GetExportDelegate<TDelegate>(module, name));
}
private static IntPtr _Handle = IntPtr.Zero;
public static string GetInstallPath()
{
return (string)Registry.GetValue(@"HKEY_LOCAL_MACHINE\Software\Valve\Steam", "InstallPath", null);
}
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi)]
private delegate IntPtr NativeCreateInterface(string version, IntPtr returnCode);
private static NativeCreateInterface _CallCreateInterface;
public static TClass CreateInterface<TClass>(string version)
where TClass : INativeWrapper, new()
{
IntPtr address = _CallCreateInterface(version, IntPtr.Zero);
if (address == IntPtr.Zero)
{
return default(TClass);
}
var rez = new TClass();
rez.SetupFunctions(address);
return rez;
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeSteamGetCallback(int pipe, out Types.CallbackMessage message, out int call);
private static NativeSteamGetCallback _CallSteamBGetCallback;
public static bool GetCallback(int pipe, out Types.CallbackMessage message, out int call)
{
return _CallSteamBGetCallback(pipe, out message, out call);
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeSteamFreeLastCallback(int pipe);
private static NativeSteamFreeLastCallback _CallSteamFreeLastCallback;
public static bool FreeLastCallback(int pipe)
{
return _CallSteamFreeLastCallback(pipe);
}
public static bool Load()
{
if (_Handle != IntPtr.Zero)
{
return true;
}
string path = GetInstallPath();
if (path == null)
{
return false;
}
Native.SetDllDirectory(path + ";" + Path.Combine(path, "bin"));
path = Path.Combine(path, "steamclient.dll");
IntPtr module = Native.LoadLibraryEx(path, IntPtr.Zero, Native.LoadWithAlteredSearchPath);
if (module == IntPtr.Zero)
{
return false;
}
_CallCreateInterface = GetExportFunction<NativeCreateInterface>(module, "CreateInterface");
if (_CallCreateInterface == null)
{
return false;
}
_CallSteamBGetCallback = GetExportFunction<NativeSteamGetCallback>(module, "Steam_BGetCallback");
if (_CallSteamBGetCallback == null)
{
return false;
}
_CallSteamFreeLastCallback = GetExportFunction<NativeSteamFreeLastCallback>(module, "Steam_FreeLastCallback");
if (_CallSteamFreeLastCallback == null)
{
return false;
}
_Handle = module;
return true;
}
}
}

View File

@@ -0,0 +1,35 @@
K 25
svn:wc:ra_dav:version-url
V 63
/private/steam/!svn/ver/3/branches/SAM/SAM.API/Interfaces/Types
END
UserStatType.cs
K 25
svn:wc:ra_dav:version-url
V 79
/private/steam/!svn/ver/3/branches/SAM/SAM.API/Interfaces/Types/UserStatType.cs
END
UserStatsStored.cs
K 25
svn:wc:ra_dav:version-url
V 82
/private/steam/!svn/ver/3/branches/SAM/SAM.API/Interfaces/Types/UserStatsStored.cs
END
AppDataChanged.cs
K 25
svn:wc:ra_dav:version-url
V 81
/private/steam/!svn/ver/3/branches/SAM/SAM.API/Interfaces/Types/AppDataChanged.cs
END
UserStatsReceived.cs
K 25
svn:wc:ra_dav:version-url
V 84
/private/steam/!svn/ver/3/branches/SAM/SAM.API/Interfaces/Types/UserStatsReceived.cs
END
UserItemsReceived.cs
K 25
svn:wc:ra_dav:version-url
V 84
/private/steam/!svn/ver/3/branches/SAM/SAM.API/Interfaces/Types/UserItemsReceived.cs
END

198
SAM.API/Types/.svn/entries Normal file
View File

@@ -0,0 +1,198 @@
10
dir
3
http://svn.gib.me/private/steam/branches/SAM/SAM.API/Interfaces/Types
http://svn.gib.me/private/steam
2009-10-27T01:01:54.542973Z
3
rick
c0897d6c-93c2-de11-ba30-0030489379b8
UserStatType.cs
file
2009-05-24T01:37:54.427000Z
64f89c9f38f7d18e3df59f61f593711e
2009-10-27T01:01:54.542973Z
3
rick
331
UserStatsStored.cs
file
2009-05-24T01:37:50.433000Z
11f1e7e1d5e4b4740ab9b9e42b16a00a
2009-10-27T01:01:54.542973Z
3
rick
377
AppDataChanged.cs
file
2009-05-24T01:37:09.724000Z
d6c03af98adc354940dcdbaeb4a0ddc1
2009-10-27T01:01:54.542973Z
3
rick
374
UserStatsReceived.cs
file
2009-05-24T01:37:46.994000Z
20130d9b19a6a0532b6b4329e2d8cab3
2009-10-27T01:01:54.542973Z
3
rick
379
UserItemsReceived.cs
file
2009-05-24T01:37:34.076000Z
e6f8773c6330b3ec861b4d4f8a4c1fbf
2009-10-27T01:01:54.542973Z
3
rick
343

View File

@@ -0,0 +1,14 @@
using System;
using System.Runtime.InteropServices;
namespace SAM.API.Interfaces.Client
{
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct AppDataChanged
{
//[MarshalAs(UnmanagedType.U8)]
public UInt32 m_nAppID;
//[MarshalAs(UnmanagedType.I4)]
public bool m_eResult;
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Runtime.InteropServices;
namespace SAM.API.Interfaces.Client
{
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct UserItemsReceived
{
public UInt64 m_nGameID;
public Int32 Unknown; // 08
public Int32 m_nItemCount; // 0C
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SAM.API.Interfaces.Client
{
public enum UserStatType
{
Invalid = 0,
Integer = 1,
Float = 2,
AverageRate = 3,
Achievements = 4,
GroupAchievements = 5,
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Runtime.InteropServices;
namespace SAM.API.Interfaces.Client
{
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct UserStatsReceived
{
//[MarshalAs(UnmanagedType.U8)]
public UInt64 m_nGameID;
//[MarshalAs(UnmanagedType.I4)]
public Int32 m_eResult;
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Runtime.InteropServices;
namespace SAM.API.Interfaces.Client
{
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
public struct UserStatsStored
{
//[MarshalAs(UnmanagedType.U8)]
public UInt64 m_nGameID;
//[MarshalAs(UnmanagedType.I4)]
public Int32 m_eResult;
}
}

View File

@@ -0,0 +1,38 @@
/* 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.API.Types
{
public enum AccountType : int
{
Invalid = 0,
Individual = 1,
Multiset = 2,
GameServer = 3,
AnonGameServer = 4,
Pending = 5,
ContentServer = 6,
Clan = 7,
Chat = 8,
P2PSuperSeeder = 9,
}
}

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.
*/
using System.Runtime.InteropServices;
namespace SAM.API.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AppDataChanged
{
public uint Id;
public bool Result;
}
}

View File

@@ -0,0 +1,36 @@
/* 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.Runtime.InteropServices;
namespace SAM.API.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct CallbackMessage
{
public int User;
public int Id;
public IntPtr ParamPointer;
public int ParamSize;
}
}

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.API.Types
{
public enum ItemRequestResult : int
{
InvalidValue = -1,
OK = 0,
Denied = 1,
ServerError = 2,
Timeout = 3,
Invalid = 4,
NoMatch = 5,
UnknownError = 6,
NotLoggedOn = 7,
}
}

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.Runtime.InteropServices;
namespace SAM.API.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct UserItemsReceived
{
public ulong GameId;
public int Unknown;
public int ItemCount;
}
}

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.
*/
namespace SAM.API.Types
{
public enum UserStatType
{
Invalid = 0,
Integer = 1,
Float = 2,
AverageRate = 3,
Achievements = 4,
GroupAchievements = 5,
}
}

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.
*/
using System.Runtime.InteropServices;
namespace SAM.API.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct UserStatsReceived
{
public ulong GameId;
public int Result;
}
}

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.
*/
using System.Runtime.InteropServices;
namespace SAM.API.Types
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct UserStatsStored
{
public ulong GameId;
public int Result;
}
}

View File

@@ -0,0 +1,56 @@
/* 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.Runtime.InteropServices;
using System.Text;
using SAM.API.Interfaces;
namespace SAM.API.Wrappers
{
public class SteamApps001 : NativeWrapper<ISteamApps001>
{
#region GetAppData
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate int NativeGetAppData(
IntPtr self,
uint appId,
string key,
StringBuilder valueBuffer,
int valueLength);
public string GetAppData(uint appId, string key)
{
var sb = new StringBuilder();
sb.EnsureCapacity(1024);
int result = this.Call<int, NativeGetAppData>(
this.Functions.GetAppData,
this.ObjectAddress,
appId,
key,
sb,
sb.Capacity);
return result == 0 ? null : sb.ToString();
}
#endregion
}
}

View File

@@ -0,0 +1,55 @@
/* 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.Runtime.InteropServices;
using SAM.API.Interfaces;
namespace SAM.API.Wrappers
{
public class SteamApps003 : NativeWrapper<ISteamApps003>
{
#region IsSubscribed
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeIsSubscribedApp(IntPtr self, Int64 gameId);
public bool IsSubscribedApp(Int64 gameId)
{
return this.Call<bool, NativeIsSubscribedApp>(this.Functions.IsSubscribedApp, this.ObjectAddress, gameId);
}
#endregion
#region GetCurrentGameLanguage
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr NativeGetCurrentGameLanguage(IntPtr self);
public string GetCurrentGameLanguage()
{
var languagePointer = this.Call<IntPtr, NativeGetCurrentGameLanguage>(
this.Functions.GetCurrentGameLanguage,
this.ObjectAddress);
return Marshal.PtrToStringAnsi(languagePointer);
}
#endregion
}
}

View File

@@ -0,0 +1,200 @@
/* 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.Runtime.InteropServices;
using SAM.API.Interfaces;
namespace SAM.API.Wrappers
{
public class SteamClient009 : NativeWrapper<ISteamClient009>
{
#region CreateSteamPipe
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate int NativeCreateSteamPipe(IntPtr self);
public int CreateSteamPipe()
{
return this.Call<int, NativeCreateSteamPipe>(this.Functions.CreateSteamPipe, this.ObjectAddress);
}
#endregion
#region ReleaseSteamPipe
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeReleaseSteamPipe(IntPtr self);
public bool ReleaseSteamPipe(int pipe)
{
return this.Call<bool, NativeReleaseSteamPipe>(this.Functions.ReleaseSteamPipe, this.ObjectAddress);
}
#endregion
#region CreateLocalUser
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate int NativeCreateLocalUser(IntPtr self, ref int pipe, Types.AccountType type);
public int CreateLocalUser(ref int pipe, Types.AccountType type)
{
var call = this.GetFunction<NativeCreateLocalUser>(this.Functions.CreateLocalUser);
return call(this.ObjectAddress, ref pipe, type);
}
#endregion
#region ConnectToGlobalUser
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate int NativeConnectToGlobalUser(IntPtr self, int pipe);
public int ConnectToGlobalUser(int pipe)
{
return this.Call<int, NativeConnectToGlobalUser>(
this.Functions.ConnectToGlobalUser,
this.ObjectAddress,
pipe);
}
#endregion
#region ReleaseUser
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate void NativeReleaseUser(IntPtr self, int pipe, int user);
public void ReleaseUser(int pipe, int user)
{
this.Call<NativeReleaseUser>(this.Functions.ReleaseUser, this.ObjectAddress, pipe, user);
}
#endregion
#region SetLocalIPBinding
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate void NativeSetLocalIPBinding(IntPtr self, uint host, ushort port);
public void SetLocalIPBinding(uint host, ushort port)
{
this.Call<NativeSetLocalIPBinding>(this.Functions.SetLocalIPBinding, this.ObjectAddress, host, port);
}
#endregion
#region GetISteamUser
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr NativeGetISteamUser(IntPtr self, int user, int pipe, string version);
private TClass GetISteamUser<TClass>(int user, int pipe, string version)
where TClass : INativeWrapper, new()
{
IntPtr address = this.Call<IntPtr, NativeGetISteamUser>(
this.Functions.GetISteamUser,
this.ObjectAddress,
user,
pipe,
version);
var result = new TClass();
result.SetupFunctions(address);
return result;
}
#endregion
#region GetSteamUser012
public SteamUser012 GetSteamUser012(int user, int pipe)
{
return this.GetISteamUser<SteamUser012>(user, pipe, "SteamUser012");
}
#endregion
#region GetISteamUserStats
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr NativeGetISteamUserStats(IntPtr self, int user, int pipe, string version);
private TClass GetISteamUserStats<TClass>(int user, int pipe, string version)
where TClass : INativeWrapper, new()
{
IntPtr address = this.Call<IntPtr, NativeGetISteamUserStats>(
this.Functions.GetISteamUserStats,
this.ObjectAddress,
user,
pipe,
version);
var result = new TClass();
result.SetupFunctions(address);
return result;
}
#endregion
#region GetSteamUserStats007
public SteamUserStats007 GetSteamUserStats006(int user, int pipe)
{
return this.GetISteamUserStats<SteamUserStats007>(user, pipe, "STEAMUSERSTATS_INTERFACE_VERSION007");
}
#endregion
#region GetISteamUtils
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate IntPtr NativeGetISteamUtils(IntPtr self, int pipe, string version);
public TClass GetISteamUtils<TClass>(int pipe, string version)
where TClass : INativeWrapper, new()
{
IntPtr address = this.Call<IntPtr, NativeGetISteamUtils>(
this.Functions.GetISteamUtils,
this.ObjectAddress,
pipe,
version);
var result = new TClass();
result.SetupFunctions(address);
return result;
}
#endregion
#region GetSteamUtils004
public SteamUtils005 GetSteamUtils004(int pipe)
{
return this.GetISteamUtils<SteamUtils005>(pipe, "SteamUtils005");
}
#endregion
#region GetISteamApps
private delegate IntPtr NativeGetISteamApps(int user, int pipe, string version);
private TClass GetISteamApps<TClass>(int user, int pipe, string version)
where TClass : INativeWrapper, new()
{
IntPtr address = this.Call<IntPtr, NativeGetISteamApps>(this.Functions.GetISteamApps, user, pipe, version);
var result = new TClass();
result.SetupFunctions(address);
return result;
}
#endregion
#region GetSteamApps001
public SteamApps001 GetSteamApps001(int user, int pipe)
{
return this.GetISteamApps<SteamApps001>(user, pipe, "STEAMAPPS_INTERFACE_VERSION001");
}
#endregion
#region GetSteamApps003
public SteamApps003 GetSteamApps003(int user, int pipe)
{
return this.GetISteamApps<SteamApps003>(user, pipe, "STEAMAPPS_INTERFACE_VERSION003");
}
#endregion
}
}

View File

@@ -0,0 +1,55 @@
/* 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.Runtime.InteropServices;
using SAM.API.Interfaces;
namespace SAM.API.Wrappers
{
public class SteamUser012 : NativeWrapper<ISteamUser012>
{
#region IsLoggedIn
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeLoggedOn(IntPtr self);
public bool IsLoggedIn()
{
return this.Call<bool, NativeLoggedOn>(this.Functions.LoggedOn, this.ObjectAddress);
}
#endregion
#region GetSteamID
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate void NativeGetSteamId(IntPtr self, out ulong steamId);
public ulong GetSteamId()
{
var call = this.GetFunction<NativeGetSteamId>(this.Functions.GetSteamID);
ulong steamId;
call(this.ObjectAddress, out steamId);
return steamId;
}
#endregion
}
}

View File

@@ -0,0 +1,180 @@
/* 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.Runtime.InteropServices;
using SAM.API.Interfaces;
namespace SAM.API.Wrappers
{
public class SteamUserStats007 : NativeWrapper<ISteamUserStats007>
{
#region RequestCurrentStats
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeRequestCurrentStats(IntPtr self);
public bool RequestCurrentStats()
{
return this.Call<bool, NativeRequestCurrentStats>(this.Functions.RequestCurrentStats, this.ObjectAddress);
}
#endregion
#region GetStatValue (int)
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeGetStatInt(IntPtr self, string name, out int data);
public bool GetStatValue(string name, out int value)
{
var call = this.GetFunction<NativeGetStatInt>(this.Functions.GetStatInteger);
return call(this.ObjectAddress, name, out value);
}
#endregion
#region GetStatValue (float)
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeGetStatFloat(IntPtr self, string name, out float data);
public bool GetStatValue(string name, out float value)
{
var call = this.GetFunction<NativeGetStatFloat>(this.Functions.GetStatFloat);
return call(this.ObjectAddress, name, out value);
}
#endregion
#region SetStatValue (int)
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeSetStatInt(IntPtr self, string name, int data);
public bool SetStatValue(string name, int value)
{
return this.Call<bool, NativeSetStatInt>(
this.Functions.SetStatInteger,
this.ObjectAddress,
name,
value);
}
#endregion
#region SetStatValue (float)
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeSetStatFloat(IntPtr self, string name, float data);
public bool SetStatValue(string name, float value)
{
return this.Call<bool, NativeSetStatFloat>(
this.Functions.SetStatFloat,
this.ObjectAddress,
name,
value);
}
#endregion
#region GetAchievement
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeGetAchievement(IntPtr self, string name, out bool isAchieved);
public bool GetAchievementState(string name, out bool isAchieved)
{
var call = this.GetFunction<NativeGetAchievement>(this.Functions.GetAchievement);
return call(this.ObjectAddress, name, out isAchieved);
}
#endregion
#region SetAchievementState
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeSetAchievement(IntPtr self, string name);
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeClearAchievement(IntPtr self, string name);
public bool SetAchievement(string name, bool state)
{
if (state == false)
{
return this.Call<bool, NativeClearAchievement>(this.Functions.ClearAchievement, this.ObjectAddress, name);
}
return this.Call<bool, NativeSetAchievement>(this.Functions.SetAchievement, this.ObjectAddress, name);
}
#endregion
#region StoreStats
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeStoreStats(IntPtr self);
public bool StoreStats()
{
return this.Call<bool, NativeStoreStats>(this.Functions.StoreStats, this.ObjectAddress);
}
#endregion
#region GetAchievementIcon
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate int NativeGetAchievementIcon(IntPtr self, string name);
public int GetAchievementIcon(string name)
{
return this.Call<int, NativeGetAchievementIcon>(
this.Functions.GetAchievementIcon,
this.ObjectAddress,
name);
}
#endregion
#region GetAchievementDisplayAttribute
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate string NativeGetAchievementDisplayAttribute(IntPtr self, string name, string key);
public string GetAchievementDisplayAttribute(string name, string key)
{
return this.Call<string, NativeGetAchievementDisplayAttribute>(
this.Functions.GetAchievementDisplayAttribute,
this.ObjectAddress,
name,
key);
}
#endregion
#region ResetAllStats
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeResetAllStats(IntPtr self, bool achievementsToo);
public bool ResetAllStats(bool achievementsToo)
{
return this.Call<bool, NativeResetAllStats>(
this.Functions.ResetAllStats,
this.ObjectAddress,
achievementsToo);
}
#endregion
}
}

View File

@@ -0,0 +1,85 @@
/* 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.Runtime.InteropServices;
using SAM.API.Interfaces;
namespace SAM.API.Wrappers
{
public class SteamUtils005 : NativeWrapper<ISteamUtils005>
{
#region GetConnectedUniverse
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate int NativeGetConnectedUniverse(IntPtr self);
public int GetConnectedUniverse()
{
return this.Call<int, NativeGetConnectedUniverse>(this.Functions.GetConnectedUniverse, this.ObjectAddress);
}
#endregion
#region GetIPCountry
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate string NativeGetIPCountry(IntPtr self);
public string GetIPCountry()
{
return this.Call<string, NativeGetIPCountry>(this.Functions.GetIPCountry, this.ObjectAddress);
}
#endregion
#region GetImageSize
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeGetImageSize(IntPtr self, int index, out int width, out int height);
public bool GetImageSize(int index, out int width, out int height)
{
var call = this.GetFunction<NativeGetImageSize>(this.Functions.GetImageSize);
return call(this.ObjectAddress, index, out width, out height);
}
#endregion
#region GetImageRGBA
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool NativeGetImageRGBA(IntPtr self, int index, byte[] buffer, int length);
public bool GetImageRGBA(int index, byte[] data)
{
var call = this.GetFunction<NativeGetImageRGBA>(this.Functions.GetImageRGBA);
return call(this.ObjectAddress, index, data, data.Length);
}
#endregion
#region GetAppID
[UnmanagedFunctionPointer(CallingConvention.ThisCall)]
private delegate uint NativeGetAppId(IntPtr self);
public uint GetAppId()
{
return this.Call<uint, NativeGetAppId>(this.Functions.GetAppID, this.ObjectAddress);
}
#endregion
}
}

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');
}
}
}

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.Picker
{
internal class DoubleBufferedListView : ListView
{
public DoubleBufferedListView()
{
base.DoubleBuffered = true;
}
}
}

68
SAM.Picker/GameInfo.cs Normal file
View File

@@ -0,0 +1,68 @@
/* 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.Globalization;
using System.Windows.Forms;
namespace SAM.Picker
{
internal class GameInfo
{
public long Id;
public string Type;
public ListViewItem Item;
#region public string Name;
public string Name
{
get { return this.Item.Text; }
set { this.Item.Text = value ?? "App " + this.Id.ToString(CultureInfo.InvariantCulture); }
}
#endregion
#region public int ImageIndex;
public int ImageIndex
{
get { return this.Item.ImageIndex; }
set { this.Item.ImageIndex = value; }
}
#endregion
public string Logo;
public GameInfo(Int64 id, string type)
{
this.Id = id;
this.Type = type;
this.Item = new ListViewItem()
{
Tag = this,
};
this.Name = null;
this.ImageIndex = 0;
this.Logo = null;
}
}
}

245
SAM.Picker/GamePicker.Designer.cs generated Normal file
View File

@@ -0,0 +1,245 @@
namespace SAM.Picker
{
partial class GamePicker
{
/// <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.Windows.Forms.ToolStripSeparator _ToolStripSeparator2;
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GamePicker));
this._GameLogoImageList = new System.Windows.Forms.ImageList(this.components);
this._CallbackTimer = new System.Windows.Forms.Timer(this.components);
this._PickerToolStrip = new System.Windows.Forms.ToolStrip();
this._RefreshGamesButton = new System.Windows.Forms.ToolStripButton();
this._AddGameTextBox = new System.Windows.Forms.ToolStripTextBox();
this._AddGameButton = new System.Windows.Forms.ToolStripButton();
this._FilterDropDownButton = new System.Windows.Forms.ToolStripDropDownButton();
this._FilterGamesMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._FilterDemosMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._FilterModsMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._FilterJunkMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._GameListView = new SAM.Picker.DoubleBufferedListView();
this._PickerStatusStrip = new System.Windows.Forms.StatusStrip();
this._PickerStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
this._DownloadStatusLabel = new System.Windows.Forms.ToolStripStatusLabel();
_ToolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
_ToolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this._PickerToolStrip.SuspendLayout();
this._PickerStatusStrip.SuspendLayout();
this.SuspendLayout();
//
// _GameLogoImageList
//
this._GameLogoImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
this._GameLogoImageList.ImageSize = new System.Drawing.Size(184, 69);
this._GameLogoImageList.TransparentColor = System.Drawing.Color.Transparent;
//
// _CallbackTimer
//
this._CallbackTimer.Enabled = true;
this._CallbackTimer.Tick += new System.EventHandler(this.OnTimer);
//
// _PickerToolStrip
//
this._PickerToolStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this._RefreshGamesButton,
_ToolStripSeparator1,
this._AddGameTextBox,
this._AddGameButton,
_ToolStripSeparator2,
this._FilterDropDownButton});
this._PickerToolStrip.Location = new System.Drawing.Point(0, 0);
this._PickerToolStrip.Name = "_PickerToolStrip";
this._PickerToolStrip.Size = new System.Drawing.Size(742, 25);
this._PickerToolStrip.TabIndex = 1;
this._PickerToolStrip.Text = "toolStrip1";
//
// _RefreshGamesButton
//
this._RefreshGamesButton.Image = global::SAM.Picker.Properties.Resources.Refresh;
this._RefreshGamesButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._RefreshGamesButton.Name = "_RefreshGamesButton";
this._RefreshGamesButton.Size = new System.Drawing.Size(105, 22);
this._RefreshGamesButton.Text = "Refresh Games";
this._RefreshGamesButton.Click += new System.EventHandler(this.OnRefresh);
//
// _ToolStripSeparator1
//
_ToolStripSeparator1.Name = "_ToolStripSeparator1";
_ToolStripSeparator1.Size = new System.Drawing.Size(6, 25);
//
// _AddGameTextBox
//
this._AddGameTextBox.Name = "_AddGameTextBox";
this._AddGameTextBox.Size = new System.Drawing.Size(100, 25);
//
// _AddGameButton
//
this._AddGameButton.Image = global::SAM.Picker.Properties.Resources.Search;
this._AddGameButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._AddGameButton.Name = "_AddGameButton";
this._AddGameButton.Size = new System.Drawing.Size(83, 22);
this._AddGameButton.Text = "Add Game";
this._AddGameButton.Click += new System.EventHandler(this.OnAddGame);
//
// _ToolStripSeparator2
//
_ToolStripSeparator2.Name = "_ToolStripSeparator2";
_ToolStripSeparator2.Size = new System.Drawing.Size(6, 25);
//
// _FilterDropDownButton
//
this._FilterDropDownButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this._FilterDropDownButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this._FilterGamesMenuItem,
this._FilterDemosMenuItem,
this._FilterModsMenuItem,
this._FilterJunkMenuItem});
this._FilterDropDownButton.Image = global::SAM.Picker.Properties.Resources.Filter;
this._FilterDropDownButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this._FilterDropDownButton.Name = "_FilterDropDownButton";
this._FilterDropDownButton.Size = new System.Drawing.Size(29, 22);
this._FilterDropDownButton.Text = "Game filtering";
//
// _FilterGamesMenuItem
//
this._FilterGamesMenuItem.Checked = true;
this._FilterGamesMenuItem.CheckOnClick = true;
this._FilterGamesMenuItem.CheckState = System.Windows.Forms.CheckState.Checked;
this._FilterGamesMenuItem.Name = "_FilterGamesMenuItem";
this._FilterGamesMenuItem.Size = new System.Drawing.Size(152, 22);
this._FilterGamesMenuItem.Text = "Show &games";
this._FilterGamesMenuItem.CheckedChanged += new System.EventHandler(this.OnFilterUpdate);
//
// _FilterDemosMenuItem
//
this._FilterDemosMenuItem.CheckOnClick = true;
this._FilterDemosMenuItem.Name = "_FilterDemosMenuItem";
this._FilterDemosMenuItem.Size = new System.Drawing.Size(152, 22);
this._FilterDemosMenuItem.Text = "Show &demos";
this._FilterDemosMenuItem.CheckedChanged += new System.EventHandler(this.OnFilterUpdate);
//
// _FilterModsMenuItem
//
this._FilterModsMenuItem.CheckOnClick = true;
this._FilterModsMenuItem.Name = "_FilterModsMenuItem";
this._FilterModsMenuItem.Size = new System.Drawing.Size(152, 22);
this._FilterModsMenuItem.Text = "Show &mods";
this._FilterModsMenuItem.CheckedChanged += new System.EventHandler(this.OnFilterUpdate);
//
// _FilterJunkMenuItem
//
this._FilterJunkMenuItem.CheckOnClick = true;
this._FilterJunkMenuItem.Name = "_FilterJunkMenuItem";
this._FilterJunkMenuItem.Size = new System.Drawing.Size(152, 22);
this._FilterJunkMenuItem.Text = "Show &junk";
this._FilterJunkMenuItem.CheckedChanged += new System.EventHandler(this.OnFilterUpdate);
//
// _GameListView
//
this._GameListView.BackColor = System.Drawing.Color.Black;
this._GameListView.Dock = System.Windows.Forms.DockStyle.Fill;
this._GameListView.ForeColor = System.Drawing.Color.White;
this._GameListView.LargeImageList = this._GameLogoImageList;
this._GameListView.Location = new System.Drawing.Point(0, 25);
this._GameListView.MultiSelect = false;
this._GameListView.Name = "_GameListView";
this._GameListView.Size = new System.Drawing.Size(742, 245);
this._GameListView.SmallImageList = this._GameLogoImageList;
this._GameListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
this._GameListView.TabIndex = 0;
this._GameListView.TileSize = new System.Drawing.Size(184, 69);
this._GameListView.UseCompatibleStateImageBehavior = false;
this._GameListView.ItemActivate += new System.EventHandler(this.OnSelectGame);
//
// _PickerStatusStrip
//
this._PickerStatusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this._PickerStatusLabel,
this._DownloadStatusLabel});
this._PickerStatusStrip.Location = new System.Drawing.Point(0, 270);
this._PickerStatusStrip.Name = "_PickerStatusStrip";
this._PickerStatusStrip.Size = new System.Drawing.Size(742, 22);
this._PickerStatusStrip.TabIndex = 2;
this._PickerStatusStrip.Text = "statusStrip";
//
// _PickerStatusLabel
//
this._PickerStatusLabel.Name = "_PickerStatusLabel";
this._PickerStatusLabel.Size = new System.Drawing.Size(727, 17);
this._PickerStatusLabel.Spring = true;
this._PickerStatusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// _DownloadStatusLabel
//
this._DownloadStatusLabel.Image = global::SAM.Picker.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;
//
// GamePicker
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(742, 292);
this.Controls.Add(this._GameListView);
this.Controls.Add(this._PickerStatusStrip);
this.Controls.Add(this._PickerToolStrip);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "GamePicker";
this.Text = "Steam Achievement Manager 6.3 | Pick a game... Any game...";
this._PickerToolStrip.ResumeLayout(false);
this._PickerToolStrip.PerformLayout();
this._PickerStatusStrip.ResumeLayout(false);
this._PickerStatusStrip.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private DoubleBufferedListView _GameListView;
private System.Windows.Forms.ImageList _GameLogoImageList;
private System.Windows.Forms.Timer _CallbackTimer;
private System.Windows.Forms.ToolStrip _PickerToolStrip;
private System.Windows.Forms.ToolStripButton _RefreshGamesButton;
private System.Windows.Forms.ToolStripTextBox _AddGameTextBox;
private System.Windows.Forms.ToolStripButton _AddGameButton;
private System.Windows.Forms.ToolStripDropDownButton _FilterDropDownButton;
private System.Windows.Forms.ToolStripMenuItem _FilterGamesMenuItem;
private System.Windows.Forms.ToolStripMenuItem _FilterJunkMenuItem;
private System.Windows.Forms.ToolStripMenuItem _FilterDemosMenuItem;
private System.Windows.Forms.ToolStripMenuItem _FilterModsMenuItem;
private System.Windows.Forms.StatusStrip _PickerStatusStrip;
private System.Windows.Forms.ToolStripStatusLabel _DownloadStatusLabel;
private System.Windows.Forms.ToolStripStatusLabel _PickerStatusLabel;
}
}

368
SAM.Picker/GamePicker.cs Normal file
View File

@@ -0,0 +1,368 @@
/* 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.Diagnostics;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows.Forms;
using System.Xml.XPath;
using APITypes = SAM.API.Types;
namespace SAM.Picker
{
internal partial class GamePicker : Form
{
private readonly API.Client _SteamClient;
private readonly WebClient _GameListDownloader = new WebClient();
private readonly WebClient _LogoDownloader = new WebClient();
private List<GameInfo> _Games = new List<GameInfo>();
public List<GameInfo> Games
{
get { return _Games; }
}
private readonly List<GameInfo> _LogoQueue = new List<GameInfo>();
// ReSharper disable PrivateFieldCanBeConvertedToLocalVariable
private readonly API.Callbacks.AppDataChanged _AppDataChangedCallback;
// ReSharper restore PrivateFieldCanBeConvertedToLocalVariable
public GamePicker(API.Client client)
{
this.InitializeComponent();
this._GameLogoImageList.Images.Add(
"Blank",
new Bitmap(this._GameLogoImageList.ImageSize.Width, this._GameLogoImageList.ImageSize.Height));
this._GameListDownloader.DownloadDataCompleted += this.OnGameListDownload;
this._LogoDownloader.DownloadDataCompleted += this.OnLogoDownload;
this._SteamClient = client;
this._AppDataChangedCallback = client.CreateAndRegisterCallback<API.Callbacks.AppDataChanged>();
this._AppDataChangedCallback.OnRun += this.OnAppDataChanged;
this.AddGames();
}
private void OnAppDataChanged(APITypes.AppDataChanged param)
{
if (param.Result == true)
{
foreach (GameInfo info in this._Games)
{
if (info.Id == param.Id)
{
info.Name = this._SteamClient.SteamApps001.GetAppData((uint)info.Id, "name");
this.AddGameToLogoQueue(info);
this._GameListView.Sort();
this._GameListView.Update();
break;
}
}
}
}
private void OnGameListDownload(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null && e.Cancelled == false)
{
using (var stream = new MemoryStream())
{
stream.Write(e.Result, 0, e.Result.Length);
stream.Seek(0, SeekOrigin.Begin);
var document = new XPathDocument(stream);
var navigator = document.CreateNavigator();
var nodes = navigator.Select("/games/game");
while (nodes.MoveNext())
{
string type = nodes.Current.GetAttribute("type", "");
if (type == string.Empty)
{
type = "normal";
}
this.AddGame(nodes.Current.ValueAsLong, type);
}
}
}
else
{
this.AddDefaultGames();
//MessageBox.Show(e.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.RefreshGames();
this._RefreshGamesButton.Enabled = true;
this.DownloadNextLogo();
}
private void RefreshGames()
{
this._GameListView.BeginUpdate();
this._GameListView.Items.Clear();
foreach (GameInfo info in this._Games)
{
if (info.Type == "normal" &&
_FilterGamesMenuItem.Checked == false)
{
continue;
}
if (info.Type == "demo" &&
this._FilterDemosMenuItem.Checked == false)
{
continue;
}
if (info.Type == "mod" &&
this._FilterModsMenuItem.Checked == false)
{
continue;
}
if (info.Type == "junk" &&
this._FilterJunkMenuItem.Checked == false)
{
continue;
}
this._GameListView.Items.Add(info.Item);
}
this._GameListView.EndUpdate();
this._PickerStatusLabel.Text = string.Format(
"Displaying {0} games. Total {1} games.",
this._GameListView.Items.Count,
this._Games.Count);
}
private void OnLogoDownload(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null && e.Cancelled == false)
{
var info = e.UserState as GameInfo;
if (info != null)
{
Image logo;
try
{
using (var stream = new MemoryStream())
{
stream.Write(e.Result, 0, e.Result.Length);
logo = new Bitmap(stream);
}
}
catch
{
logo = null;
}
if (logo != null)
{
info.ImageIndex = this._GameLogoImageList.Images.Count;
this._GameLogoImageList.Images.Add(info.Logo, logo);
this._GameListView.Update();
}
}
}
this.DownloadNextLogo();
}
private void DownloadNextLogo()
{
if (this._LogoQueue.Count == 0)
{
this._DownloadStatusLabel.Visible = false;
return;
}
if (this._LogoDownloader.IsBusy)
{
return;
}
this._DownloadStatusLabel.Text = string.Format(
"Downloading {0} game icons...",
this._LogoQueue.Count);
this._DownloadStatusLabel.Visible = true;
GameInfo info = this._LogoQueue[0];
this._LogoQueue.RemoveAt(0);
var logoPath = string.Format(
"http://media.steamcommunity.com/steamcommunity/public/images/apps/{0}/{1}.jpg",
info.Id,
info.Logo);
this._LogoDownloader.DownloadDataAsync(new Uri(logoPath), info);
}
private void AddGameToLogoQueue(GameInfo info)
{
string logo = this._SteamClient.SteamApps001.GetAppData((uint)info.Id, "logo");
if (logo == null)
{
return;
}
info.Logo = logo;
int imageIndex = this._GameLogoImageList.Images.IndexOfKey(logo);
if (imageIndex >= 0)
{
info.ImageIndex = imageIndex;
}
else
{
this._LogoQueue.Add(info);
this.DownloadNextLogo();
}
}
private bool OwnsGame(long id)
{
return this._SteamClient.SteamApps003.IsSubscribedApp(id);
}
private void AddGame(long id, string type)
{
if (this._Games.Any(i => i.Id == id) == true)
{
return;
}
if (this.OwnsGame(id) == false)
{
return;
}
var info = new GameInfo(id, type);
info.Name = this._SteamClient.SteamApps001.GetAppData((uint)info.Id, "name");
this._Games.Add(info);
this.AddGameToLogoQueue(info);
}
private void AddGames()
{
this._GameListView.Items.Clear();
this._Games = new List<GameInfo>();
this._GameListDownloader.DownloadDataAsync(new Uri(string.Format("http://gib.me/sam/games.xml")));
this._RefreshGamesButton.Enabled = false;
}
private void AddDefaultGames()
{
this.AddGame(480, "normal"); // Spacewar
}
private void OnTimer(object sender, EventArgs e)
{
this._CallbackTimer.Enabled = false;
this._SteamClient.RunCallbacks(false);
this._CallbackTimer.Enabled = true;
}
private void OnSelectGame(object sender, EventArgs e)
{
if (this._GameListView.SelectedItems.Count == 0)
{
return;
}
var info = this._GameListView.SelectedItems[0].Tag as GameInfo;
if (info == null)
{
return;
}
try
{
Process.Start("SAM.Game.exe", info.Id.ToString(CultureInfo.InvariantCulture));
}
catch (Win32Exception)
{
MessageBox.Show(
this,
"Failed to start SAM.Game.exe.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
private void OnRefresh(object sender, EventArgs e)
{
this._AddGameTextBox.Text = "";
this.AddGames();
}
private void OnAddGame(object sender, EventArgs e)
{
long id;
if (long.TryParse(this._AddGameTextBox.Text, out id) == false)
{
MessageBox.Show(
this,
"Please enter a valid game ID.",
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
if (this.OwnsGame(id) == false)
{
MessageBox.Show(this, "You don't own that game.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
this._AddGameTextBox.Text = "";
this._GameListView.Items.Clear();
this._Games = new List<GameInfo>();
this.AddGame(id, "normal");
this._FilterGamesMenuItem.Checked = true;
this.RefreshGames();
this.DownloadNextLogo();
}
private void OnFilterUpdate(object sender, EventArgs e)
{
this.RefreshGames();
}
}
}

327
SAM.Picker/GamePicker.resx Normal file
View File

@@ -0,0 +1,327 @@
<?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="_GameLogoImageList.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="_CallbackTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>233, 17</value>
</metadata>
<metadata name="_PickerToolStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>359, 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="_ToolStripSeparator2.GenerateMember" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>False</value>
</metadata>
<metadata name="_PickerStatusStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>464, 17</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>
AAABAAMAEBAAAAEACABoBQAANgAAACAgAAABAAgAqAgAAJ4FAAAwMAAAAQAYAKgcAABGDgAAKAAAABAA
AAAgAAAAAQAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAgP8A////AMXKxwD///8ADQkMAJus
oQBeW10AwNXIAIyMjAC2trYAa29tAHVzdAC5v7wAj5aRAHx8fACRjI8AstnBAGGCbgAlNisAPFFGAHCX
gACbq6EAgX+AAHp4egDA1cgAR2FSADApLgChsKcAj5aRAGtvbQBih3EAX15fAIODgwCTj5IApcKyABwb
GwC0vbcAYIJtAGmJdgBjZ2UAoLKmADJEOQCGhIUAd3Z2ALa2tgB2nYYAXltdAIafjwBnhXQAcY9+ADFE
OACzyrwALD0zAHZ0dQCFgYMArsW4AGeHcwBHSEgAhpqNAG6PfABtjnoAJiUlALDGuQAWIBsAhIODAHh3
eADFyscAbY96AGmGdQBshncAio+MAEVFRABDP0IAqbauAGOEcAAdGhwAioqKALm/vACLh4kAdXJ0AIWC
hAC5xr8Ah6yWAGSAcABrh3cAaod2AGyMeQCbr6MAjaqZAEVdTwAJBgcAi4uLAF5/awCfuKkArcO1AJus
oQBGYFEAX3tqAGuIeABphnQACw8NAC4sLgBMSksAjo6OAGWDcgBif20AYX9tAJWyoQBrdW8Abo56AHiY
hgBMYlUADQkMAIOCgwCMjIwAhYWFAGyLeQBqh3cAaYd1AEZTSwCmxbQAGCMcAC8qLACQkJAAgYGBAFhb
WQBvjHsAX3hpAHGRfwB9oIoAHCYfAKS/sAAvKi4AkpKSAK6wrwBlgXAAUVZTACIkIgCChIMAL0U3AHRy
cwB9fH0AdXR1AGmCcwBwinsAMUc5AEVARACEg4QAdnN1AGJgYQB8enwAh4eHAAAAAAD///8AAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBAQEBAQEBAQEBAQEAAQEBAQIC
AQEBAQEBAQEBAQEBAQIBAQIBAQEBAQEBAQEBAQIBAgIBAgEBAQEBAQEBAgICAgICAQIBAQEBAQEBAQIC
AgICAgECAgEBAQEBAQECAgICAgECAgICAQEBAQEBAgIBAQICAgICAgICAgEBAQEBAQEBAQICAgICAgIC
AQEBAQEBAQECAgICAQEBAQIBAQEBAQEBAQICAQICAgECAQEBAQEBAQEBAgECAgIBAgEBAQEBAQEBAQIB
AgICAQIBAQEBAQEBAQECAgEBAQICAQEBAQEBAQEBAQICAgICAQEAAQEBAQEBAQEBAQEBAQEAgAEAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAACgA
AAAgAAAAQAAAAAEACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwID/AP///wCAgAAAAIAAAACA
gAAAAIAAwMDAAMDcwADwyqYAgICAAP8A/wD/AAAA//8AAAD/AAAA//8AAAD/AP///wDw+/8ApKCgANTw
/wCx4v8AjtT/AGvG/wBIuP8AJar/AACq/wAAktwAAHq5AABilgAASnMAADJQANTj/wCxx/8Ajqv/AGuP
/wBIc/8AJVf/AABV/wAASdwAAD25AAAxlgAAJXMAABlQANTU/wCxsf8Ajo7/AGtr/wBISP8AJSX/AAAA
/wAAANwAAAC5AAAAlgAAAHMAAABQAOPU/wDHsf8Aq47/AI9r/wBzSP8AVyX/AFUA/wBJANwAPQC5ADEA
lgAlAHMAGQBQAPDU/wDisf8A1I7/AMZr/wC4SP8AqiX/AKoA/wCSANwAegC5AGIAlgBKAHMAMgBQAP/U
/wD/sf8A/47/AP9r/wD/SP8A/yX/AP8A/wDcANwAuQC5AJYAlgBzAHMAUABQAP/U8AD/seIA/47UAP9r
xgD/SLgA/yWqAP8AqgDcAJIAuQB6AJYAYgBzAEoAUAAyAP/U4wD/sccA/46rAP9rjwD/SHMA/yVXAP8A
VQDcAEkAuQA9AJYAMQBzACUAUAAZAP/U1AD/sbEA/46OAP9rawD/SEgA/yUlAP8AAADcAAAAuQAAAJYA
AABzAAAAUAAAAP/j1AD/x7EA/6uOAP+PawD/c0gA/1clAP9VAADcSQAAuT0AAJYxAABzJQAAUBkAAP/w
1AD/4rEA/9SOAP/GawD/uEgA/6olAP+qAADckgAAuXoAAJZiAABzSgAAUDIAAP//1AD//7EA//+OAP//
awD//0gA//8lAP//AADc3AAAubkAAJaWAABzcwAAUFAAAPD/1ADi/7EA1P+OAMb/awC4/0gAqv8lAKr/
AACS3AAAerkAAGKWAABKcwAAMlAAAOP/1ADH/7EAq/+OAI//awBz/0gAV/8lAFX/AABJ3AAAPbkAADGW
AAAlcwAAGVAAANT/1ACx/7EAjv+OAGv/awBI/0gAJf8lAAD/AAAA3AAAALkAAACWAAAAcwAAAFAAANT/
4wCx/8cAjv+rAGv/jwBI/3MAJf9XAAD/VQAA3EkAALk9AACWMQAAcyUAAFAZANT/8ACx/+IAjv/UAGv/
xgBI/7gAJf+qAAD/qgAA3JIAALl6AACWYgAAc0oAAFAyANT//wCx//8Ajv//AGv//wBI//8AJf//AAD/
/wAA3NwAALm5AACWlgAAc3MAAFBQAPLy8gDm5uYA2traAM7OzgDCwsIAtra2AKqqqgCenp4AkpKSAIaG
hgB6enoAbm5uAGJiYgBWVlYASkpKAD4+PgAyMjIAJiYmABoaGgAODg4AAAABAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAAAAAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAgICAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQIBAQECAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAQICAgECAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAgICAgICAQIBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgIB
AgIBAQEBAQEBAQEBAQEBAQEBAQEBAQICAgICAgICAQICAgIBAQEBAQEBAQEBAQEBAQEBAQICAgICAgIB
AQICAgICAgICAgEBAQEBAQECAgIBAgICAgICAgIBAQEBAQECAgICAgICAgEBAQEBAgIBAQICAgICAgIC
AQEBAQEBAQICAgIBAQEBAgEBAQECAQICAgICAgIBAQEBAQEBAQEBAQICAQICAgECAQEBAQIBAgICAgIB
AQEBAQEBAQEBAQEBAQIBAgICAQIBAQEBAgIBAQICAQEBAQEBAQEBAQEBAQEBAgECAgIBAgEBAQEBAgIC
AgEBAQEBAQEBAQEBAQEBAQECAgEBAQICAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQECAgICAgEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQAAAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAMAAAAOAAAABAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAHAAAADKAAAADAA
AABgAAAAAQAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMCA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/wAAAAAAAAAA
AMCA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/wAAAMCA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/////////////////////8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/////8CA
/8CA/8CA/8CA/8CA/////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/////////////////////////8CA/8CA/////8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA////////////////////////////////
/8CA/////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA////////////
/////////////////////////////////8CA/////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/////////////////////////////////////////////////8CA/8CA////////////
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA////////////////////////////////////////////////
/////8CA/8CA/8CA/////////////////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA////////////////////////
/////////////////////////////////////////////////////////////////////////////8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA////
/////////////////////////////////////////////////////8CA/8CA/8CA/8CA/8CA////////
/////////////////////////////////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/////////////8CA/8CA/////////////////////////////////////////////////////8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA////////////////////////////////////////////////////
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/////8CA/8CA////////////////////////////////////////
/////////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA////////////////////
/////8CA/8CA/8CA/8CA/8CA/////////8CA/8CA/8CA/8CA/8CA/8CA/////8CA/8CA////////////
/////////////////////////////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/////////////////8CA/8CA/////////////8CA/8CA/////////8CA/8CA/8CA
/8CA/////8CA/8CA/////////////////////////////////////////////8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/////////////8CA////////////
/////////8CA/////////8CA/8CA/8CA/8CA/////8CA/8CA////////////////////////////////
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/////////8CA/8CA/////////////////////8CA/8CA/////8CA/8CA/8CA/8CA/////8CA/8CA
/////////////////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/////////8CA/8CA/////////////////////8CA////
/////8CA/8CA/8CA/8CA/8CA/////8CA/8CA/////////8CA/////////8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA////////
/8CA/////////////////8CA/8CA/////////8CA/8CA/8CA/8CA/8CA/8CA/////8CA/8CA/8CA////
/////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/////////////8CA/8CA/8CA/8CA/8CA/////////////8CA/8CA/8CA
/8CA/8CA/8CA/8CA/////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/////////////8CA/8CA
/8CA/////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/////////////////////////////8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/////8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/wAA
AMCA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/wAAAAAAAAAAAMCA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA
/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/8CA/wAAAAAAAMAAAAAAAwAAgAAAAAAB
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAB
AADAAAAAAAMAAA==
</value>
</data>
</root>

22
SAM.Picker/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.

72
SAM.Picker/Program.cs Normal file
View File

@@ -0,0 +1,72 @@
/* 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.Windows.Forms;
namespace SAM.Picker
{
internal static class Program
{
[STAThread]
private static void Main()
{
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(0) == 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 GamePicker(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 Picker")]
[assembly: AssemblyDescription("A game picker for the Steam Achievement Manager.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Gibbed")]
[assembly: AssemblyProduct("SAM.Picker")]
[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("e133af48-a6c2-4890-8237-9552e0d325ac")]
// 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")]

View File

@@ -0,0 +1,91 @@
//------------------------------------------------------------------------------
// <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.Picker.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.Picker.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 Filter {
get {
object obj = ResourceManager.GetObject("Filter", 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 Search {
get {
object obj = ResourceManager.GetObject("Search", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}

View File

@@ -0,0 +1,133 @@
<?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="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="Filter" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\television-test.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="Search" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\magnifier.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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 700 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,141 @@
<?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>{E89E57BB-0F09-47F3-98A0-2026E2E65FBA}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>SAM.Picker</RootNamespace>
<AssemblyName>SAM.Picker</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ApplicationIcon>SAM.ico</ApplicationIcon>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>
<UpgradeBackupLocation />
<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="DoubleBufferedListView.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="GameInfo.cs" />
<Compile Include="GamePicker.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="GamePicker.Designer.cs">
<DependentUpon>GamePicker.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="GamePicker.resx">
<DependentUpon>GamePicker.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>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SAM.API\SAM.API.csproj">
<Project>{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}</Project>
<Name>SAM.API</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="Resources\arrow-circle-double.png" />
<None Include="Resources\magnifier.png" />
<None Include="Resources\television-test.png" />
<None Include="Resources\download-cloud.png" />
<Content Include="SAM.ico" />
</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>
<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>

BIN
SAM.Picker/SAM.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

32
SAM.sln Normal file
View File

@@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SAM.Picker", "SAM.Picker\SAM.Picker.csproj", "{E89E57BB-0F09-47F3-98A0-2026E2E65FBA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SAM.API", "SAM.API\SAM.API.csproj", "{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SAM.Game", "SAM.Game\SAM.Game.csproj", "{7640DE31-E54E-45F9-9CF0-8DF3A3EA30FC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E89E57BB-0F09-47F3-98A0-2026E2E65FBA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E89E57BB-0F09-47F3-98A0-2026E2E65FBA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E89E57BB-0F09-47F3-98A0-2026E2E65FBA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E89E57BB-0F09-47F3-98A0-2026E2E65FBA}.Release|Any CPU.Build.0 = Release|Any CPU
{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DF9102D5-048A-4D21-8CE3-3544CBDF0ED1}.Release|Any CPU.Build.0 = Release|Any CPU
{7640DE31-E54E-45F9-9CF0-8DF3A3EA30FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7640DE31-E54E-45F9-9CF0-8DF3A3EA30FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7640DE31-E54E-45F9-9CF0-8DF3A3EA30FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7640DE31-E54E-45F9-9CF0-8DF3A3EA30FC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal