From 1d92c138f7cb11487dfacf3c2ca6c4249864242d Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Fri, 26 Feb 2021 18:04:46 +0800 Subject: [PATCH] migrate Steam.Service --- SteamToolsV1.2+.sln | 24 +- .../App.axaml.cs | 2 + .../Program.cs | 59 ----- .../Startup.cs | 78 +++++++ ...amTools.Client.Desktop.Avalonia.App.csproj | 5 + .../SteamworksLocalApiServiceImpl.cs | 208 ++++++++++++++++++ .../ServiceCollectionExtensions.cs | 1 + ...n.SteamTools.Client.Desktop.Windows.csproj | 2 + .../ServiceCollectionExtensions.cs | 36 ++- .../Services/ILocalizationService.cs | 4 +- .../Services/ISteamDbWebApiService.cs | 26 +++ .../Services/ISteamService.cs | 18 ++ .../Services/ISteamworksLocalApiService.cs | 77 ++++++- .../Services/ISteamworksWebApiService.cs | 26 +++ .../Implementation/HttpServiceImpl.cs | 14 ++ .../SteamDbWebApiServiceImpl.cs | 40 ++++ .../Implementation/SteamServiceImpl.cs | 27 +++ .../SteamworksLocalApiServiceImpl.cs | 90 ++++++++ .../SteamworksWebApiServiceImpl.cs | 35 +++ .../UI/ViewModels/ViewModelBase.cs | 12 +- 20 files changed, 700 insertions(+), 84 deletions(-) create mode 100644 System.Application.SteamTools.Client.Desktop.Avalonia.App/Startup.cs create mode 100644 System.Application.SteamTools.Client.Desktop.Windows/Application/Services/Implementation/SteamworksLocalApiServiceImpl.cs create mode 100644 System.Application.SteamTools.Client.Desktop/Services/ISteamDbWebApiService.cs create mode 100644 System.Application.SteamTools.Client.Desktop/Services/ISteamworksWebApiService.cs create mode 100644 System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamDbWebApiServiceImpl.cs create mode 100644 System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksLocalApiServiceImpl.cs create mode 100644 System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksWebApiServiceImpl.cs diff --git a/SteamToolsV1.2+.sln b/SteamToolsV1.2+.sln index cd53d151c..7f72768c5 100644 --- a/SteamToolsV1.2+.sln +++ b/SteamToolsV1.2+.sln @@ -195,12 +195,12 @@ Global {D1F15D97-802E-4AA3-A4A5-B890ABE32897}.Release|Any CPU.Build.0 = Release|Any CPU {D1F15D97-802E-4AA3-A4A5-B890ABE32897}.Release|x86.ActiveCfg = Release|Any CPU {D1F15D97-802E-4AA3-A4A5-B890ABE32897}.Release|x86.Build.0 = Release|Any CPU - {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|x86.ActiveCfg = Debug|Any CPU - {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|x86.Build.0 = Debug|Any CPU - {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|Any CPU.Build.0 = Release|Any CPU + {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|Any CPU.ActiveCfg = Debug|x86 + {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|Any CPU.Build.0 = Debug|x86 + {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|x86.ActiveCfg = Debug|x86 + {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Debug|x86.Build.0 = Debug|x86 + {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|Any CPU.ActiveCfg = Release|x86 + {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|Any CPU.Build.0 = Release|x86 {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|x86.ActiveCfg = Release|Any CPU {2FFA5BCE-B3C3-46EA-8830-838C938BF814}.Release|x86.Build.0 = Release|Any CPU {4F09B6D1-3F83-45A0-AEC8-0F243E7CD263}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -227,12 +227,12 @@ Global {948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}.Release|Any CPU.Build.0 = Release|Any CPU {948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}.Release|x86.ActiveCfg = Release|Any CPU {948C1EA8-12DB-4F8A-A190-8615DFBD9FE4}.Release|x86.Build.0 = Release|Any CPU - {141532E1-540E-4E50-8723-96936C191281}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {141532E1-540E-4E50-8723-96936C191281}.Debug|Any CPU.Build.0 = Debug|Any CPU + {141532E1-540E-4E50-8723-96936C191281}.Debug|Any CPU.ActiveCfg = Debug|x86 + {141532E1-540E-4E50-8723-96936C191281}.Debug|Any CPU.Build.0 = Debug|x86 {141532E1-540E-4E50-8723-96936C191281}.Debug|x86.ActiveCfg = Debug|Any CPU {141532E1-540E-4E50-8723-96936C191281}.Debug|x86.Build.0 = Debug|Any CPU - {141532E1-540E-4E50-8723-96936C191281}.Release|Any CPU.ActiveCfg = Release|Any CPU - {141532E1-540E-4E50-8723-96936C191281}.Release|Any CPU.Build.0 = Release|Any CPU + {141532E1-540E-4E50-8723-96936C191281}.Release|Any CPU.ActiveCfg = Release|x86 + {141532E1-540E-4E50-8723-96936C191281}.Release|Any CPU.Build.0 = Release|x86 {141532E1-540E-4E50-8723-96936C191281}.Release|x86.ActiveCfg = Release|Any CPU {141532E1-540E-4E50-8723-96936C191281}.Release|x86.Build.0 = Release|Any CPU {60530AF8-4790-4A85-BCE2-C5673E9C601B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -260,15 +260,19 @@ Global {D018C980-17FD-49BB-A95D-EDE3C18BBE0A}.Release|x86.ActiveCfg = Release|Any CPU {D018C980-17FD-49BB-A95D-EDE3C18BBE0A}.Release|x86.Build.0 = Release|Any CPU {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Debug|Any CPU.ActiveCfg = Debug|x86 + {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Debug|Any CPU.Build.0 = Debug|x86 {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Debug|x86.ActiveCfg = Debug|x86 {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Debug|x86.Build.0 = Debug|x86 {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Release|Any CPU.ActiveCfg = Release|x86 + {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Release|Any CPU.Build.0 = Release|x86 {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Release|x86.ActiveCfg = Release|x86 {6DD9644F-F005-4C19-8ADF-70C303EC5BB8}.Release|x86.Build.0 = Release|x86 {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Debug|Any CPU.ActiveCfg = Debug|x86 + {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Debug|Any CPU.Build.0 = Debug|x86 {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Debug|x86.ActiveCfg = Debug|x86 {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Debug|x86.Build.0 = Debug|x86 {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Release|Any CPU.ActiveCfg = Release|x86 + {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Release|Any CPU.Build.0 = Release|x86 {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Release|x86.ActiveCfg = Release|x86 {3C05CED6-7712-40F0-AF17-8DD3F4C0A224}.Release|x86.Build.0 = Release|x86 {35D60129-6652-4B6E-A04A-9766C3CF1869}.Debug|Any CPU.ActiveCfg = Debug|Any CPU diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs b/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs index 19b8f9151..a4baf75bd 100644 --- a/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs +++ b/System.Application.SteamTools.Client.Desktop.Avalonia.App/App.axaml.cs @@ -29,6 +29,8 @@ namespace System.Application.UI // ÔÚUIԤÀÀÖУ¬ApplicationLifetime Ϊ null ViewModelBase.IsInDesignMode = ApplicationLifetime == null; + Startup.Init(); + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { if (!AppHelper.IsOfficialChannelPackage) diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia.App/Program.cs b/System.Application.SteamTools.Client.Desktop.Avalonia.App/Program.cs index ca4d17c06..df9f44082 100644 --- a/System.Application.SteamTools.Client.Desktop.Avalonia.App/Program.cs +++ b/System.Application.SteamTools.Client.Desktop.Avalonia.App/Program.cs @@ -1,10 +1,6 @@ using Avalonia; using Avalonia.ReactiveUI; -using Microsoft.Extensions.DependencyInjection; using NLog; -using System.Application.Models; -using System.Application.Services.Implementation; -using System.Application.UI.ViewModels; namespace System.Application.UI { @@ -22,9 +18,6 @@ namespace System.Application.UI var logger = LogManager.GetCurrentClassLogger(); try { - FileSystemDesktop.InitFileSystem(); - ModelValidatorProvider.Init(); - DI.Init(ConfigureServices); BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); } catch (Exception ex) @@ -49,57 +42,5 @@ namespace System.Application.UI .With(new Win32PlatformOptions { AllowEglInitialization = true }) .LogToTrace() .UseReactiveUI(); - - static void ConfigureServices(IServiceCollection services) - { - // 添加日志实现 - services.AddDesktopLogging(); - - // 模型验证框架 - services.TryAddModelValidator(); - - //var options = AppClientAttribute.Get(); - var options = new AppSettings - { - //AppSecretVisualStudioAppCenter = "", - }; - // app 配置项 - services.TryAddOptions(options); - - // 键值对存储 - services.TryAddStorage(); - - // 业务平台用户管理 - services.TryAddUserManager(); - - // 服务端API调用 - services.TryAddCloudServiceClient(); - - // 桌面平台服务 - services.AddDesktopPlatformService(); - - // 本地化服务 - services.AddLocalizationService(); - - // 主线程助手类(MainThreadDesktop) - services.AddMainThreadPlatformService(); - - // 模型视图组 - services.AddViewModelCollectionService(); - services.AddViewModel(); - services.AddViewModel(); - - // 业务用户配置文件服务 - services.AddConfigFileService(); - - // hosts 文件助手服务 - services.AddHostsFileService(); - - // 通用 Http 服务 - services.AddHttpService(); - - // Steam 相关助手、工具类服务 - services.AddSteamService(); - } } } \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia.App/Startup.cs b/System.Application.SteamTools.Client.Desktop.Avalonia.App/Startup.cs new file mode 100644 index 000000000..6f6f89cb8 --- /dev/null +++ b/System.Application.SteamTools.Client.Desktop.Avalonia.App/Startup.cs @@ -0,0 +1,78 @@ +using Microsoft.Extensions.DependencyInjection; +using System.Application.Models; +using System.Application.Services.Implementation; +using System.Application.UI.ViewModels; + +namespace System.Application.UI +{ + internal static class Startup + { + public static void Init() + { + FileSystemDesktop.InitFileSystem(); + ModelValidatorProvider.Init(); + DI.Init(ConfigureServices); + } + + static void ConfigureServices(IServiceCollection services) + { + // 添加日志实现 + services.AddDesktopLogging(); + + // 模型验证框架 + services.TryAddModelValidator(); + + //var options = AppClientAttribute.Get(); + var options = new AppSettings + { + //AppSecretVisualStudioAppCenter = "", + }; + // app 配置项 + services.TryAddOptions(options); + + // 键值对存储 + services.TryAddStorage(); + + // 业务平台用户管理 + services.TryAddUserManager(); + + // 服务端API调用 + services.TryAddCloudServiceClient(); + + // 桌面平台服务 此项放在其他通用业务实现服务之前 + services.AddDesktopPlatformService(); + + // 本地化服务 + services.AddLocalizationService(); + + // 主线程助手类(MainThreadDesktop) + services.AddMainThreadPlatformService(); + + // 模型视图组 + services.AddViewModelCollectionService(); + services.AddViewModel(); + services.AddViewModel(); + + // 业务用户配置文件服务 + services.AddConfigFileService(); + + // hosts 文件助手服务 + services.AddHostsFileService(); + + // 通用 Http 服务 + services.AddHttpService(); + + // Steam 相关助手、工具类服务 + services.AddSteamService(); + + // Steamworks LocalApi Service + services.TryAddSteamworksLocalApiService(); + + // SteamDb WebApi Service + services.AddSteamDbWebApiService(); + + // Steamworks WebApi Service + services.AddSteamworksWebApiService(); + } + } +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop.Avalonia.App/System.Application.SteamTools.Client.Desktop.Avalonia.App.csproj b/System.Application.SteamTools.Client.Desktop.Avalonia.App/System.Application.SteamTools.Client.Desktop.Avalonia.App.csproj index c2c716b41..edfc72dc4 100644 --- a/System.Application.SteamTools.Client.Desktop.Avalonia.App/System.Application.SteamTools.Client.Desktop.Avalonia.App.csproj +++ b/System.Application.SteamTools.Client.Desktop.Avalonia.App/System.Application.SteamTools.Client.Desktop.Avalonia.App.csproj @@ -11,6 +11,11 @@ Properties\app.manifest + + + x86 + + Properties\AssemblyInfo.cs diff --git a/System.Application.SteamTools.Client.Desktop.Windows/Application/Services/Implementation/SteamworksLocalApiServiceImpl.cs b/System.Application.SteamTools.Client.Desktop.Windows/Application/Services/Implementation/SteamworksLocalApiServiceImpl.cs new file mode 100644 index 000000000..426d573d1 --- /dev/null +++ b/System.Application.SteamTools.Client.Desktop.Windows/Application/Services/Implementation/SteamworksLocalApiServiceImpl.cs @@ -0,0 +1,208 @@ +using SAM.API; +using SAM.API.Types; +using System.Application.Models; +using System.Collections.Generic; +using System.Linq; +using static System.Application.Services.ISteamworksLocalApiService; +using UserStatsReceivedCallback = SAM.API.Callbacks.UserStatsReceived; + +namespace System.Application.Services.Implementation +{ + internal sealed class SteamworksLocalApiServiceImpl : ISteamworksLocalApiService + { + public Client SteamClient { get; } + + UserStatsReceivedCallback? UserStatsReceivedCallback; + + public SteamworksLocalApiServiceImpl() + { + SteamClient = new Client(); + } + + public bool IsSupported => true; + + public bool Initialize() + { + try + { + SteamClient.Initialize(0); + } + catch (Exception ex) + { + Log.Error(TAG, ex, "Initialize Fail."); + return false; + } + return true; + } + + public bool Initialize(int appid) + { + try + { + SteamClient.Initialize(appid); + } + catch (Exception ex) + { + Log.Error(TAG, ex, "Initialize Fail."); + return false; + } + return true; + } + + public long GetSteamId64() + { + if (SteamClient.SteamUser == null) + return 0L; + return (long)SteamClient.SteamUser.GetSteamId(); + } + + public bool OwnsApps(uint appid) + { + if (SteamClient.SteamApps008 == null) + return false; + return SteamClient.SteamApps008.IsSubscribedApp(appid); + } + + public List OwnsApps(List apps) + { + if (SteamClient.SteamApps008 == null || SteamClient.SteamApps001 == null) + return new List(); + return apps.FindAll(f => SteamClient.SteamApps008.IsSubscribedApp(f.AppId)) + .OrderBy(s => s.Name).Select((s, i) => new SteamApp + { + Index = i + 1, + AppId = s.AppId, + Name = s.Name, + Type = Enum.TryParse(GetAppData(s.AppId, "type"), true, out var result) ? result : SteamAppType.Unknown, + Icon = GetAppData(s.AppId, "icon"), + Logo = GetAppData(s.AppId, "logo"), + InstalledDir = GetAppInstallDir(s.AppId), + IsInstalled = IsAppInstalled(s.AppId) + }).ToList(); + } + + public string GetAppData(uint appid, string key) + { + return SteamClient.SteamApps001.GetAppData(appid, key); + } + + public bool IsSteamChinaLauncher() + { + return SteamClient.SteamUtils.IsSteamChinaLauncher(); + } + + public bool IsAppInstalled(uint appid) + { + return SteamClient.SteamApps008.IsAppInstalled(appid); + } + + public string GetAppInstallDir(uint appid) + { + return SteamClient.SteamApps008.GetAppInstallDir(appid); + } + + public string GetIPCountry() + { + return SteamClient.SteamUtils.GetIPCountry(); + } + + public string GetCurrentGameLanguage() + { + return SteamClient.SteamApps008.GetCurrentGameLanguage(); + } + + public string GetAvailableGameLanguages() + { + return SteamClient.SteamApps008.GetAvailableGameLanguages(); + } + + public bool GetStatValue(string name, out int value) + { + return SteamClient.SteamUserStats.GetStatValue(name, out value); + } + + public bool GetStatValue(string name, out float value) + { + return SteamClient.SteamUserStats.GetStatValue(name, out value); + } + + public bool GetAchievementState(string name, out bool isAchieved) + { + return SteamClient.SteamUserStats.GetAchievementState(name, out isAchieved); + } + + public bool GetAchievementAndUnlockTime(string name, out bool isAchieved, out long unlockTime) + { + return SteamClient.SteamUserStats.GetAchievementAndUnlockTime(name, out isAchieved, out unlockTime); + } + + public bool GetAchievementAchievedPercent(string name, out float percent) + { + return SteamClient.SteamUserStats.GetAchievementAchievedPercent(name, out percent); + } + + public void AddUserStatsReceivedCallback(Action action) + { + UserStatsReceivedCallback = SteamClient.CreateAndRegisterCallback(); + UserStatsReceivedCallback.OnRun += value => + { + var valueWrapper = new UserStatsReceivedWrapper(value); + action(valueWrapper); + }; + } + + sealed class UserStatsReceivedWrapper : IUserStatsReceived + { + readonly UserStatsReceived userStatsReceived; + + public UserStatsReceivedWrapper(UserStatsReceived userStatsReceived) + { + this.userStatsReceived = userStatsReceived; + } + + public ulong GameId => userStatsReceived.GameId; + + public int Result => userStatsReceived.Result; + } + + public bool RequestCurrentStats() + { + return SteamClient.SteamUserStats.RequestCurrentStats(); + } + + public bool ResetAllStats(bool achievementsToo) + { + return SteamClient.SteamUserStats.ResetAllStats(achievementsToo); + } + + public bool SetAchievement(string name, bool state) + { + return SteamClient.SteamUserStats.SetAchievement(name, state); + } + + public bool SetStatValue(string name, int value) + { + return SteamClient.SteamUserStats.SetStatValue(name, value); + } + + public bool SetStatValue(string name, float value) + { + return SteamClient.SteamUserStats.SetStatValue(name, value); + } + + public bool StoreStats() + { + return SteamClient.SteamUserStats.StoreStats(); + } + + public void RequestGlobalAchievementPercentages() + { + SteamClient.SteamUserStats.RequestGlobalAchievementPercentages(); + } + + public void RunCallbacks(bool server) + { + SteamClient.RunCallbacks(server); + } + } +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop.Windows/ServiceCollectionExtensions.cs b/System.Application.SteamTools.Client.Desktop.Windows/ServiceCollectionExtensions.cs index 5a257b434..d013c8d14 100644 --- a/System.Application.SteamTools.Client.Desktop.Windows/ServiceCollectionExtensions.cs +++ b/System.Application.SteamTools.Client.Desktop.Windows/ServiceCollectionExtensions.cs @@ -17,6 +17,7 @@ namespace Microsoft.Extensions.DependencyInjection if (DI.Platform == Platform.Windows) { services.AddSingleton(); + services.AddSingleton(); } else { diff --git a/System.Application.SteamTools.Client.Desktop.Windows/System.Application.SteamTools.Client.Desktop.Windows.csproj b/System.Application.SteamTools.Client.Desktop.Windows/System.Application.SteamTools.Client.Desktop.Windows.csproj index 0c94076ce..2e75a3e0b 100644 --- a/System.Application.SteamTools.Client.Desktop.Windows/System.Application.SteamTools.Client.Desktop.Windows.csproj +++ b/System.Application.SteamTools.Client.Desktop.Windows/System.Application.SteamTools.Client.Desktop.Windows.csproj @@ -3,6 +3,8 @@ net5.0 System + + x86 diff --git a/System.Application.SteamTools.Client.Desktop/ServiceCollectionExtensions.cs b/System.Application.SteamTools.Client.Desktop/ServiceCollectionExtensions.cs index eccfb9f9f..f37d00fce 100644 --- a/System.Application.SteamTools.Client.Desktop/ServiceCollectionExtensions.cs +++ b/System.Application.SteamTools.Client.Desktop/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using System.Application.Services; +using Microsoft.Extensions.DependencyInjection.Extensions; +using System.Application.Services; using System.Application.Services.Implementation; using System.Application.UI; using System.Application.UI.ViewModels; @@ -98,5 +99,38 @@ namespace Microsoft.Extensions.DependencyInjection services.AddSingleton(); return services; } + + /// + /// 尝试添加 Steamworks LocalApi Service + /// + /// + /// + public static IServiceCollection TryAddSteamworksLocalApiService(this IServiceCollection services) + { + services.TryAddSingleton(); + return services; + } + + /// + /// 添加 SteamDb WebApi Service + /// + /// + /// + public static IServiceCollection AddSteamDbWebApiService(this IServiceCollection services) + { + services.AddSingleton(); + return services; + } + + /// + /// 添加 Steamworks WebApi Service + /// + /// + /// + public static IServiceCollection AddSteamworksWebApiService(this IServiceCollection services) + { + services.AddSingleton(); + return services; + } } } \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop/Services/ILocalizationService.cs b/System.Application.SteamTools.Client.Desktop/Services/ILocalizationService.cs index 3f05481db..c0a2d4684 100644 --- a/System.Application.SteamTools.Client.Desktop/Services/ILocalizationService.cs +++ b/System.Application.SteamTools.Client.Desktop/Services/ILocalizationService.cs @@ -23,7 +23,7 @@ namespace System.Application.Services /// ILocalizationViewModel[] ViewModels { get; } - public static IList> Languages; + public static readonly IList> Languages; static ILocalizationService() { @@ -33,6 +33,8 @@ namespace System.Application.Services { "en", "English" }, { "zh-Hans", "Chinese(Simplified)" }, { "zh-Hant", "Chinese(Traditional)" }, + { "ja-JP", "Japanese" }, + { "ru", "Russian" }, }.ToList(); } } diff --git a/System.Application.SteamTools.Client.Desktop/Services/ISteamDbWebApiService.cs b/System.Application.SteamTools.Client.Desktop/Services/ISteamDbWebApiService.cs new file mode 100644 index 000000000..c5ee55278 --- /dev/null +++ b/System.Application.SteamTools.Client.Desktop/Services/ISteamDbWebApiService.cs @@ -0,0 +1,26 @@ +using System.Application.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace System.Application.Services +{ + public interface ISteamDbWebApiService + { + public static ISteamDbWebApiService Instance => DI.Get(); + + Task GetUserInfo(long steamId64); + + Task> GetUserInfo(IEnumerable steamId64s); + + Task GetAppInfo(int appId); + } + +#if DEBUG + + [Obsolete("use ISteamDbWebApiService", true)] + public class SteamDbApiService + { + } + +#endif +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop/Services/ISteamService.cs b/System.Application.SteamTools.Client.Desktop/Services/ISteamService.cs index a6567f32c..0440ac493 100644 --- a/System.Application.SteamTools.Client.Desktop/Services/ISteamService.cs +++ b/System.Application.SteamTools.Client.Desktop/Services/ISteamService.cs @@ -23,8 +23,21 @@ namespace System.Application.Services /// /// 结束 Steam 进程 /// + [Obsolete("可能引发,Win32异常,拒绝访问,改为 TryKillSteamProcess false 弹窗提示用户手动关闭 Steam,true 使用 IsRunningSteamProcess 再检测一遍,返回 int(pid) 提示用户去任务管理器中结束进程,null 再进行业务逻辑", true)] void KillSteamProcess(); + /// + /// 尝试结束 Steam 进程 + /// + /// + bool TryKillSteamProcess(); + + /// + /// Steam 进程是否正在运行,如果正在运行,返回进程PID提示用户去任务管理器中结束进程 + /// + /// + int? IsRunningSteamProcess(); + /// /// 启动 Steam /// @@ -86,6 +99,11 @@ namespace System.Application.Services [Obsolete("use ISteamService", true)] public class SteamService { + [Obsolete("use ISteamworksLocalApiService.Instance / ISteamDbWebApiService.Instance / ISteamworksWebApiService.Instance", true)] + public static SteamService Instance => throw new NotImplementedException(); + + [Obsolete("use ISteamworksLocalApiService.Instance / ISteamDbWebApiService.Instance / ISteamworksWebApiService.Instance", true)] + public TInterface Get() => throw new NotImplementedException(); } #endif diff --git a/System.Application.SteamTools.Client.Desktop/Services/ISteamworksLocalApiService.cs b/System.Application.SteamTools.Client.Desktop/Services/ISteamworksLocalApiService.cs index 523737cdc..ca86ac51f 100644 --- a/System.Application.SteamTools.Client.Desktop/Services/ISteamworksLocalApiService.cs +++ b/System.Application.SteamTools.Client.Desktop/Services/ISteamworksLocalApiService.cs @@ -1,24 +1,85 @@ -using System; +using System.Application.Models; using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace System.Application.Services { public interface ISteamworksLocalApiService { - //Client SteamClient { get; } - } + protected const string TAG = "SteamworksLocalApiS"; + public static ISteamworksLocalApiService Instance => DI.Get(); + + /// + /// 当前平台是否支持 + /// + bool IsSupported { get; } + + bool Initialize(); + + bool Initialize(int appid); + + long GetSteamId64(); + + bool OwnsApps(uint appid); + + List OwnsApps(List apps); + + string GetAppData(uint appid, string key); + + bool IsSteamChinaLauncher(); + + bool IsAppInstalled(uint appid); + + string GetAppInstallDir(uint appid); + + string GetIPCountry(); + + string GetCurrentGameLanguage(); + + string GetAvailableGameLanguages(); + + bool GetStatValue(string name, out int value); + + bool GetStatValue(string name, out float value); + + bool GetAchievementState(string name, out bool isAchieved); + + bool GetAchievementAndUnlockTime(string name, out bool isAchieved, out long unlockTime); + + bool GetAchievementAchievedPercent(string name, out float percent); + + void AddUserStatsReceivedCallback(Action action); + + bool RequestCurrentStats(); + + bool ResetAllStats(bool achievementsToo); + + bool SetAchievement(string name, bool state); + + bool SetStatValue(string name, int value); + + bool SetStatValue(string name, float value); + + bool StoreStats(); + + void RequestGlobalAchievementPercentages(); + + void RunCallbacks(bool server); + + public interface IUserStatsReceived + { + ulong GameId { get; } + + int Result { get; } + } + } #if DEBUG [Obsolete("use ISteamworksLocalApiService", true)] public class SteamworksApiService { - } #endif -} +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop/Services/ISteamworksWebApiService.cs b/System.Application.SteamTools.Client.Desktop/Services/ISteamworksWebApiService.cs new file mode 100644 index 000000000..46a4557d1 --- /dev/null +++ b/System.Application.SteamTools.Client.Desktop/Services/ISteamworksWebApiService.cs @@ -0,0 +1,26 @@ +using System.Application.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace System.Application.Services +{ + public interface ISteamworksWebApiService + { + public static ISteamworksWebApiService Instance => DI.Get(); + + Task GetAllSteamAppsString(); + + Task> GetAllSteamAppList(); + + Task GetUserInfo(long steamId64); + } + +#if DEBUG + + [Obsolete("use ISteamworksWebApiService", true)] + public class SteamworksWebApiService + { + } + +#endif +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop/Services/Implementation/HttpServiceImpl.cs b/System.Application.SteamTools.Client.Desktop/Services/Implementation/HttpServiceImpl.cs index e24c730b1..70126fb69 100644 --- a/System.Application.SteamTools.Client.Desktop/Services/Implementation/HttpServiceImpl.cs +++ b/System.Application.SteamTools.Client.Desktop/Services/Implementation/HttpServiceImpl.cs @@ -35,6 +35,20 @@ namespace System.Application.Services.Implementation { if (response.Content != null) { + var rspContentClrType = typeof(T); + if (rspContentClrType == typeof(string)) + { + return (T)(object)await response.Content.ReadAsStringAsync(cancellationToken); + } + else if (rspContentClrType == typeof(byte[])) + { + return (T)(object)await response.Content.ReadAsByteArrayAsync(cancellationToken); + } + else if (rspContentClrType == typeof(Stream)) + { + // 因为上面用了 using 释放,所以不支持流的形式 + throw new NotSupportedException(); + } var mime = response.Content.Headers.ContentType?.MediaType ?? Accept; switch (mime) { diff --git a/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamDbWebApiServiceImpl.cs b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamDbWebApiServiceImpl.cs new file mode 100644 index 000000000..18d18048f --- /dev/null +++ b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamDbWebApiServiceImpl.cs @@ -0,0 +1,40 @@ +using System.Application.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace System.Application.Services.Implementation +{ + internal sealed class SteamDbWebApiServiceImpl : ISteamDbWebApiService + { + readonly IHttpService s; + + public SteamDbWebApiServiceImpl(IHttpService s) + { + this.s = s; + } + + public async Task GetUserInfo(long steamId64) + { + var requestUri = string.Format(SteamApiUrls.STEAMDB_USERINFO_URL, steamId64); + var rsp = await s.GetAsync(requestUri); + return rsp ?? new SteamUser() { SteamId64 = steamId64 }; + } + + public async Task> GetUserInfo(IEnumerable steamId64s) + { + var users = new List(); + foreach (var i in steamId64s) + { + users.Add(await GetUserInfo(i)); + } + return users; + } + + public async Task GetAppInfo(int appId) + { + var requestUri = string.Format(SteamApiUrls.STEAMDB_APPINFO_URL, appId); + var rsp = await s.GetAsync(requestUri); + return rsp ?? new SteamApp() { AppId = (uint)appId }; + } + } +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamServiceImpl.cs b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamServiceImpl.cs index f1b88fe5f..ec780aeea 100644 --- a/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamServiceImpl.cs +++ b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamServiceImpl.cs @@ -53,6 +53,33 @@ namespace System.Application.Services.Implementation } } + public bool TryKillSteamProcess() + { + try + { + KillSteamProcess(); + return true; + } + catch (Exception e) + { + Log.Error(TAG, e, "KillSteamProcess Fail."); + return false; + } + } + + public int? IsRunningSteamProcess() + { + var processes = Process.GetProcesses(); + foreach (var p in processes) + { + if (steamProcess.Contains(p.ProcessName, StringComparer.OrdinalIgnoreCase)) + { + return p.Id; + } + } + return default; + } + public void StartSteam(string arguments) { if (!string.IsNullOrEmpty(SteamProgramPath)) diff --git a/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksLocalApiServiceImpl.cs b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksLocalApiServiceImpl.cs new file mode 100644 index 000000000..f783f64f0 --- /dev/null +++ b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksLocalApiServiceImpl.cs @@ -0,0 +1,90 @@ +using System.Application.Models; +using System.Collections.Generic; +using static System.Application.Services.ISteamworksLocalApiService; + +namespace System.Application.Services.Implementation +{ + internal sealed class SteamworksLocalApiServiceImpl : ISteamworksLocalApiService + { + public bool IsSupported => false; + + public bool Initialize() => default; + + public bool Initialize(int appid) => default; + + public long GetSteamId64() => default; + + public bool OwnsApps(uint appid) => default; + + public List OwnsApps(List apps) => new List(); + + public string GetAppData(uint appid, string key) => string.Empty; + + public bool IsSteamChinaLauncher() => default; + + public bool IsAppInstalled(uint appid) => default; + + public string GetAppInstallDir(uint appid) => string.Empty; + + public string GetIPCountry() => string.Empty; + + public string GetCurrentGameLanguage() => string.Empty; + + public string GetAvailableGameLanguages() => string.Empty; + + public bool GetStatValue(string name, out int value) + { + value = default; + return default; + } + + public bool GetStatValue(string name, out float value) + { + value = default; + return default; + } + + public bool GetAchievementState(string name, out bool isAchieved) + { + isAchieved = default; + return default; + } + + public bool GetAchievementAndUnlockTime(string name, out bool isAchieved, out long unlockTime) + { + isAchieved = default; + unlockTime = default; + return default; + } + + public bool GetAchievementAchievedPercent(string name, out float percent) + { + percent = default; + return default; + } + + public void AddUserStatsReceivedCallback(Action action) + { + } + + public bool RequestCurrentStats() => default; + + public bool ResetAllStats(bool achievementsToo) => default; + + public bool SetAchievement(string name, bool state) => default; + + public bool SetStatValue(string name, int value) => default; + + public bool SetStatValue(string name, float value) => default; + + public bool StoreStats() => default; + + public void RequestGlobalAchievementPercentages() + { + } + + public void RunCallbacks(bool server) + { + } + } +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksWebApiServiceImpl.cs b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksWebApiServiceImpl.cs new file mode 100644 index 000000000..eeee45a9a --- /dev/null +++ b/System.Application.SteamTools.Client.Desktop/Services/Implementation/SteamworksWebApiServiceImpl.cs @@ -0,0 +1,35 @@ +using System.Application.Models; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace System.Application.Services.Implementation +{ + internal sealed class SteamworksWebApiServiceImpl : ISteamworksWebApiService + { + readonly IHttpService s; + + public SteamworksWebApiServiceImpl(IHttpService s) + { + this.s = s; + } + + public async Task GetAllSteamAppsString() + { + var rsp = await s.GetAsync(SteamApiUrls.STEAMAPP_LIST_URL); + return rsp ?? string.Empty; + } + + public async Task> GetAllSteamAppList() + { + var rsp = await s.GetAsync(SteamApiUrls.STEAMAPP_LIST_URL); + return rsp?.AppList?.Apps ?? new List(); + } + + public async Task GetUserInfo(long steamId64) + { + var requestUri = string.Format(SteamApiUrls.STEAM_USERINFO_XML_URL, steamId64); + var rsp = await s.GetAsync(requestUri); + return rsp ?? new SteamUser() { SteamId64 = steamId64 }; + } + } +} \ No newline at end of file diff --git a/System.Application.SteamTools.Client.Desktop/UI/ViewModels/ViewModelBase.cs b/System.Application.SteamTools.Client.Desktop/UI/ViewModels/ViewModelBase.cs index e55c3d910..fd80782ca 100644 --- a/System.Application.SteamTools.Client.Desktop/UI/ViewModels/ViewModelBase.cs +++ b/System.Application.SteamTools.Client.Desktop/UI/ViewModels/ViewModelBase.cs @@ -15,10 +15,12 @@ namespace System.Application.UI.ViewModels /// public static bool IsInDesignMode { get; set; } - protected static TViewModel GetViewModel() where TViewModel : ViewModelBase, new() - { - if (IsInDesignMode) return new TViewModel(); - return DI.Get(); - } + //protected static TViewModel GetViewModel() where TViewModel : ViewModelBase, new() + //{ + // if (IsInDesignMode) return new TViewModel(); + // return DI.Get(); + //} + + protected static TViewModel GetViewModel() where TViewModel : ViewModelBase => DI.Get(); } } \ No newline at end of file