From 97c7671595d7ad471623ae3dba9667b2c2dcf631 Mon Sep 17 00:00:00 2001 From: Lightczx <1686188646@qq.com> Date: Mon, 17 Apr 2023 12:00:48 +0800 Subject: [PATCH] use hoyoverse instead of hoyolab to login --- .../Snap.Hutao.SourceGeneration/JsonParser.cs | 11 +- .../CSharpLanguageFeatureTest.cs | 41 +- .../Snap.Hutao/Model/Intrinsic/ChannelType.cs | 105 ++++ .../Model/Intrinsic/SubChannelType.cs | 50 ++ .../Resource/Localization/SH.Designer.cs | 227 ++++++++- .../Snap.Hutao/Resource/Localization/SH.resx | 2 +- .../Snap.Hutao/Service/Game/GameService.cs | 11 +- .../Snap.Hutao/Service/Game/LaunchScheme.cs | 94 +++- .../Snap.Hutao/Service/Game/MultiChannel.cs | 15 +- .../View/Card/GachaStatisticsCard.xaml | 477 +++++++++--------- .../View/Card/GachaStatisticsCard.xaml.cs | 6 +- .../View/Page/AnnouncementPage.xaml | 2 +- .../View/Page/LoginHoyoverseUserPage.xaml.cs | 6 +- .../ViewModel/Game/LaunchGameViewModel.cs | 12 +- 14 files changed, 772 insertions(+), 287 deletions(-) create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ChannelType.cs create mode 100644 src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/SubChannelType.cs diff --git a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/JsonParser.cs b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/JsonParser.cs index 3b281150..1a4bb285 100644 --- a/src/Snap.Hutao/Snap.Hutao.SourceGeneration/JsonParser.cs +++ b/src/Snap.Hutao/Snap.Hutao.SourceGeneration/JsonParser.cs @@ -2,6 +2,7 @@ using System.Collections; using System.Collections.Generic; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Text; @@ -46,7 +47,7 @@ public static class JsonParser stringBuilder ??= new StringBuilder(); splitArrayPool ??= new Stack>(); - //Remove all whitespace not within strings to make parsing simpler + // Remove all whitespace not within strings to make parsing simpler stringBuilder.Length = 0; for (int i = 0; i < json.Length; i++) { @@ -64,7 +65,7 @@ public static class JsonParser stringBuilder.Append(c); } - //Parse the thing! + // Parse the thing! return (T?)ParseValue(typeof(T), stringBuilder.ToString()); } @@ -96,7 +97,7 @@ public static class JsonParser return json.Length - 1; } - //Splits { :, : } and [ , ] into a list of strings + // Splits { :, : } and [ , ] into a list of strings private static List Split(string json) { List splitArray = splitArrayPool!.Count > 0 ? splitArrayPool.Pop() : new List(); @@ -315,7 +316,7 @@ public static class JsonParser return null; } - Dictionary dict = new Dictionary(elems.Count / 2); + Dictionary dict = new(elems.Count / 2); for (int i = 0; i < elems.Count; i += 2) { dict[elems[i].Substring(1, elems[i].Length - 2)] = ParseAnonymousValue(elems[i + 1]); @@ -396,7 +397,7 @@ public static class JsonParser { object instance = FormatterServices.GetUninitializedObject(type); - //The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON + // The list is split into key/value pairs only, this means the split must be divisible by 2 to be valid JSON List elems = Split(json); if (elems.Count % 2 != 0) { diff --git a/src/Snap.Hutao/Snap.Hutao.Test/CSharpLanguageFeatureTest.cs b/src/Snap.Hutao/Snap.Hutao.Test/CSharpLanguageFeatureTest.cs index d267cb5d..43874f8a 100644 --- a/src/Snap.Hutao/Snap.Hutao.Test/CSharpLanguageFeatureTest.cs +++ b/src/Snap.Hutao/Snap.Hutao.Test/CSharpLanguageFeatureTest.cs @@ -1,4 +1,6 @@ -namespace Snap.Hutao.Test; +using System; + +namespace Snap.Hutao.Test; [TestClass] public class CSharpLanguageFeatureTest @@ -22,4 +24,41 @@ public class CSharpLanguageFeatureTest Assert.IsTrue(*pStr == '\0'); } } + + [TestMethod] + public void EnumParseCanNotHandleEmptyString() + { + bool caught = false; + try + { + Enum.Parse(string.Empty); + } + catch (ArgumentException) + { + caught = true; + } + + Assert.IsTrue(caught); + } + + [TestMethod] + public void EnumParseCanHandleNumberString() + { + EnumA a = Enum.Parse("2"); + Assert.AreEqual(a, EnumA.ValueB); + } + + [TestMethod] + public void EnumToStringDecimal() + { + Assert.AreEqual("2", EnumA.ValueB.ToString("D")); + } + + private enum EnumA + { + None = 0, + ValueA = 1, + ValueB = 2, + ValueC = 3, + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ChannelType.cs b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ChannelType.cs new file mode 100644 index 00000000..5a2f8fcc --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/ChannelType.cs @@ -0,0 +1,105 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Model.Intrinsic; + +/// +/// 渠道类型 +/// +internal enum ChannelType +{ + /// + /// 错误值 + /// + Default = 0, + + /// + /// 官方渠道 + /// + Official = 1, + + /// + /// 索尼 + /// + MiHoYoSONY = 2, + + /// + /// 小米 + /// + XiaoMi = 11, + + /// + /// 酷派 + /// + KuPai = 12, + + /// + /// 应用宝 + /// + YYB = 13, + + /// + /// 哔哩哔哩 + /// + Bili = 14, + + /// + /// 华为 + /// + HW = 15, + + /// + /// 魅族 + /// + MZ = 16, + + /// + /// 奇虎 + /// + QiHu = 17, + + /// + /// 欧泊 + /// + OPPO = 18, + + /// + /// 维沃 + /// + VIVO = 19, + + /// + /// 阿里 + /// + Ali = 20, + + /// + /// 豌豆荚 + /// + WDJ = 21, + + /// + /// 联想 + /// + Lenove = 22, + + /// + /// 金立 + /// + JinLi = 23, + + /// + /// 百度 + /// + BaiDu = 25, + + /// + /// 当乐 + /// + DL = 26, + + /// + /// WeGame + /// + WeGame = 27, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/SubChannelType.cs b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/SubChannelType.cs new file mode 100644 index 00000000..23cab0b0 --- /dev/null +++ b/src/Snap.Hutao/Snap.Hutao/Model/Intrinsic/SubChannelType.cs @@ -0,0 +1,50 @@ +// Copyright (c) DGP Studio. All rights reserved. +// Licensed under the MIT license. + +namespace Snap.Hutao.Model.Intrinsic; + +/// +/// 子渠道类型 +/// +internal enum SubChannelType +{ + /// + /// 默认 + /// + Default = 0, + + /// + /// 官方 + /// + Official = 1, + + /// + /// 非 TapTap + /// + NoTapTap = 2, + + /// + /// Epic + /// + Epic = 3, + + /// + /// 三星 + /// + Samsung = 4, + + /// + /// Steam + /// + Steam = 5, + + /// + /// 谷歌 + /// + Google = 6, + + /// + /// 最大值 + /// + MAX = 7, +} \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs index 2d444890..3b242c7e 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.Designer.cs @@ -2545,7 +2545,7 @@ namespace Snap.Hutao.Resource.Localization { } /// - /// 查找类似 无法读取游戏配置文件 的本地化字符串。 + /// 查找类似 无法读取游戏配置文件: {0} 的本地化字符串。 /// internal static string ViewModelLaunchGameMultiChannelReadFail { get { @@ -4722,6 +4722,204 @@ namespace Snap.Hutao.Resource.Localization { } } + /// + /// 查找类似 搭配圣遗物 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarArtifactSetCombinationHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarArtifactSetCombinationHeader", resourceCulture); + } + } + + /// + /// 查找类似 养成材料 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarAscensionMaterialsHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarAscensionMaterialsHeader", resourceCulture); + } + } + + /// + /// 查找类似 筛选角色 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarAutoSuggestBoxPlaceHolder { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarAutoSuggestBoxPlaceHolder", resourceCulture); + } + } + + /// + /// 查找类似 汉语 CV 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarChineseCVNameTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarChineseCVNameTitle", resourceCulture); + } + } + + /// + /// 查找类似 命之座 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarConstellationNameTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarConstellationNameTitle", resourceCulture); + } + } + + /// + /// 查找类似 衣装 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarCostumeHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarCostumeHeader", resourceCulture); + } + } + + /// + /// 查找类似 生日 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarDateofBirthTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarDateofBirthTitle", resourceCulture); + } + } + + /// + /// 查找类似 英语 CV 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarEnglishCVNameTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarEnglishCVNameTitle", resourceCulture); + } + } + + /// + /// 查找类似 料理 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarFoodHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarFoodHeader", resourceCulture); + } + } + + /// + /// 查找类似 日语 CV 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarJapaneseCVNameTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarJapaneseCVNameTitle", resourceCulture); + } + } + + /// + /// 查找类似 韩语 CV 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarKoreanCVNameTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarKoreanCVNameTitle", resourceCulture); + } + } + + /// + /// 查找类似 其它 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarMiscHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarMiscHeader", resourceCulture); + } + } + + /// + /// 查找类似 所属 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarOccupationNameTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarOccupationNameTitle", resourceCulture); + } + } + + /// + /// 查找类似 原料理 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarOriginalFoodTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarOriginalFoodTitle", resourceCulture); + } + } + + /// + /// 查找类似 资料 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarQuotesHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarQuotesHeader", resourceCulture); + } + } + + /// + /// 查找类似 特殊料理 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarSpecialFoodTitle { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarSpecialFoodTitle", resourceCulture); + } + } + + /// + /// 查找类似 故事 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarStoriesHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarStoriesHeader", resourceCulture); + } + } + + /// + /// 查找类似 天赋 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarTanlentHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarTanlentHeader", resourceCulture); + } + } + + /// + /// 查找类似 搭配角色 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarTeamCombinationHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarTeamCombinationHeader", resourceCulture); + } + } + + /// + /// 查找类似 搭配武器 的本地化字符串。 + /// + internal static string ViewPageWiKiAvatarWeaponCombinationHeader { + get { + return ResourceManager.GetString("ViewPageWiKiAvatarWeaponCombinationHeader", resourceCulture); + } + } + + /// + /// 查找类似 添加到养成计划 的本地化字符串。 + /// + internal static string ViewPageWiKiGeneralAddToDevPlanButtonLabel { + get { + return ResourceManager.GetString("ViewPageWiKiGeneralAddToDevPlanButtonLabel", resourceCulture); + } + } + + /// + /// 查找类似 筛选怪物 的本地化字符串。 + /// + internal static string ViewPageWiKiMonsterAutoSuggestBoxPlaceHolder { + get { + return ResourceManager.GetString("ViewPageWiKiMonsterAutoSuggestBoxPlaceHolder", resourceCulture); + } + } + /// /// 查找类似 掉落物品 的本地化字符串。 /// @@ -4731,6 +4929,33 @@ namespace Snap.Hutao.Resource.Localization { } } + /// + /// 查找类似 突破后 的本地化字符串。 + /// + internal static string ViewPageWiKiWeaponAfterAscensionTitle { + get { + return ResourceManager.GetString("ViewPageWiKiWeaponAfterAscensionTitle", resourceCulture); + } + } + + /// + /// 查找类似 筛选武器 的本地化字符串。 + /// + internal static string ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder { + get { + return ResourceManager.GetString("ViewPageWiKiWeaponAutoSuggestBoxPlaceHolder", resourceCulture); + } + } + + /// + /// 查找类似 突破前 的本地化字符串。 + /// + internal static string ViewPageWiKiWeaponBeforeAscensionTitle { + get { + return ResourceManager.GetString("ViewPageWiKiWeaponBeforeAscensionTitle", resourceCulture); + } + } + /// /// 查找类似 登录失败,请重新登录 的本地化字符串。 /// diff --git a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx index e5f887dd..c6bc9487 100644 --- a/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx +++ b/src/Snap.Hutao/Snap.Hutao/Resource/Localization/SH.resx @@ -916,7 +916,7 @@ 切换服务器失败 - 无法读取游戏配置文件 + 无法读取游戏配置文件: {0} 游戏路径不正确,前往设置更改游戏路径 diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs index 3a17830d..5aeba103 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/GameService.cs @@ -26,7 +26,6 @@ namespace Snap.Hutao.Service.Game; /// [HighQuality] [Injection(InjectAs.Singleton, typeof(IGameService))] -[SuppressMessage("", "CA1001")] internal sealed class GameService : IGameService { private const string GamePathKey = $"{nameof(GameService)}.Cache.{SettingEntry.GamePath}"; @@ -161,18 +160,20 @@ internal sealed class GameService : IGameService { if (parameter.Key == "channel") { - if (parameter.Value != scheme.Channel) + string channel = scheme.Channel.ToString("D"); + if (parameter.Value != channel) { - parameter.Value = scheme.Channel; + parameter.Value = channel; changed = true; } } if (parameter.Key == "sub_channel") { - if (parameter.Value != scheme.SubChannel) + string subChannel = scheme.SubChannel.ToString("D"); + if (parameter.Value != subChannel) { - parameter.Value = scheme.SubChannel; + parameter.Value = subChannel; changed = true; } } diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs index 83ca97e4..534df145 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/LaunchScheme.cs @@ -1,6 +1,7 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Intrinsic; using System.Collections.Immutable; namespace Snap.Hutao.Service.Game; @@ -16,54 +17,95 @@ internal sealed class LaunchScheme /// public static readonly ImmutableList KnownSchemes = new List() { - new LaunchScheme(SH.ModelBindingLaunchGameLaunchSchemeChinese, "eYd89JmJ", "18", "1", "1"), - new LaunchScheme(SH.ModelBindingLaunchGameLaunchSchemeBilibili, "KAtdSsoQ", "17", "14", "0"), - new LaunchScheme(SH.ModelBindingLaunchGameLaunchSchemeOversea, "gcStgarh", "10", "1", "0"), - }.ToImmutableList(); + // 官服 + new() + { + DisplayName = SH.ModelBindingLaunchGameLaunchSchemeChinese, + LauncherId = "18", + Key = "eYd89JmJ", + Channel = ChannelType.Official, + SubChannel = SubChannelType.Default, + IsOversea = false, + }, - /// - /// 构造一个新的启动方案 - /// - /// 名称 - /// 通道 - /// 子通道 - /// 启动器Id - private LaunchScheme(string displayName, string key, string launcherId, string channel, string subChannel) - { - DisplayName = displayName; - Channel = channel; - SubChannel = subChannel; - LauncherId = launcherId; - Key = key; - } + // 渠道服 + new() + { + DisplayName = SH.ModelBindingLaunchGameLaunchSchemeBilibili, + LauncherId = "17", + Key = "KAtdSsoQ", + Channel = ChannelType.Bili, + SubChannel = SubChannelType.Default, + IsOversea = false, + }, + + // 国际服 + new() + { + DisplayName = SH.ModelBindingLaunchGameLaunchSchemeOversea, + LauncherId = "10", + Key = "gcStgarh", + Channel = ChannelType.Official, + SubChannel = SubChannelType.Default, + IsOversea = true, + }, + new() + { + DisplayName = SH.ModelBindingLaunchGameLaunchSchemeOversea, + LauncherId = "10", + Key = "gcStgarh", + Channel = ChannelType.Official, + SubChannel = SubChannelType.Epic, + IsOversea = true, + }, + new() + { + DisplayName = SH.ModelBindingLaunchGameLaunchSchemeOversea, + LauncherId = "10", + Key = "gcStgarh", + Channel = ChannelType.Official, + SubChannel = SubChannelType.Google, + IsOversea = true, + }, + }.ToImmutableList(); /// /// 名称 /// - public string DisplayName { get; } + public string DisplayName { get; private set; } = default!; /// /// 通道 /// - public string Channel { get; } + public ChannelType Channel { get; private set; } /// /// 子通道 /// - public string SubChannel { get; } + public SubChannelType SubChannel { get; private set; } /// - /// 启动器Id + /// 启动器 Id /// - public string LauncherId { get; } + public string LauncherId { get; private set; } = default!; /// /// API Key /// - public string Key { get; } + public string Key { get; private set; } = default!; /// /// 是否为海外 /// - public bool IsOversea { get => LauncherId == "10" && Channel == "1" && SubChannel == "0"; } + public bool IsOversea { get; private set; } + + /// + /// 多通道相等 + /// + /// 多通道 + /// 是否相等 + public bool MultiChannelEqual(MultiChannel multiChannel) + { + return Channel == multiChannel.Channel && SubChannel == multiChannel.SubChannel; + } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/Service/Game/MultiChannel.cs b/src/Snap.Hutao/Snap.Hutao/Service/Game/MultiChannel.cs index 4a97ddf0..b3888a98 100644 --- a/src/Snap.Hutao/Snap.Hutao/Service/Game/MultiChannel.cs +++ b/src/Snap.Hutao/Snap.Hutao/Service/Game/MultiChannel.cs @@ -1,28 +1,30 @@ // Copyright (c) DGP Studio. All rights reserved. // Licensed under the MIT license. +using Snap.Hutao.Model.Intrinsic; + namespace Snap.Hutao.Service.Game; /// /// 多通道 /// [HighQuality] -internal struct MultiChannel +internal readonly struct MultiChannel { /// /// 通道 /// - public string Channel; + public readonly ChannelType Channel; /// /// 子通道 /// - public string SubChannel; + public readonly SubChannelType SubChannel; /// /// 配置文件路径 当不为 null 时则存在文件读写问题 /// - public string? ConfigFilePath; + public readonly string? ConfigFilePath; /// /// 构造一个新的多通道 @@ -32,8 +34,9 @@ internal struct MultiChannel /// 配置文件路径 public MultiChannel(string? channel, string? subChannel, string? configFilePath = null) { - Channel = channel ?? string.Empty; - SubChannel = subChannel ?? string.Empty; + Channel = string.IsNullOrEmpty(channel) ? ChannelType.Default : Enum.Parse(channel); + SubChannel = string.IsNullOrEmpty(subChannel) ? SubChannelType.Default : Enum.Parse(subChannel); + ConfigFilePath = configFilePath; } } \ No newline at end of file diff --git a/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml index a8f85e48..83456902 100644 --- a/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml +++ b/src/Snap.Hutao/Snap.Hutao/View/Card/GachaStatisticsCard.xaml @@ -1,4 +1,4 @@ -