diff --git a/src/Starward.Core/HoYoPlay/GameInfo.cs b/src/Starward.Core/HoYoPlay/GameInfo.cs
index df42fc4a1..230c39edb 100644
--- a/src/Starward.Core/HoYoPlay/GameInfo.cs
+++ b/src/Starward.Core/HoYoPlay/GameInfo.cs
@@ -71,21 +71,21 @@ public class GameInfoDisplay
/// 大背景图
///
[JsonPropertyName("background")]
- public GameImage Background { get; set; }
+ public GameImage? Background { get; set; }
///
/// 游戏Logo
///
[JsonPropertyName("logo")]
- public GameImage Logo { get; set; }
+ public GameImage? Logo { get; set; }
///
/// 小缩略背景图
///
[JsonPropertyName("thumbnail")]
- public GameImage Thumbnail { get; set; }
+ public GameImage? Thumbnail { get; set; }
}
diff --git a/src/Starward.Language/Lang.Designer.cs b/src/Starward.Language/Lang.Designer.cs
index 7a0d8e522..007238d2c 100644
--- a/src/Starward.Language/Lang.Designer.cs
+++ b/src/Starward.Language/Lang.Designer.cs
@@ -1655,6 +1655,24 @@ public static string GameResourcePage_LatestVersion {
}
}
+ ///
+ /// 查找类似 Actual Size of Installed Games 的本地化字符串。
+ ///
+ public static string GameSelector_ActualSizeOfInstalledGames {
+ get {
+ return ResourceManager.GetString("GameSelector_ActualSizeOfInstalledGames", resourceCulture);
+ }
+ }
+
+ ///
+ /// 查找类似 Storage Space Saved by Hard Links 的本地化字符串。
+ ///
+ public static string GameSelector_StorageSpaceSavedByHardLinks {
+ get {
+ return ResourceManager.GetString("GameSelector_StorageSpaceSavedByHardLinks", resourceCulture);
+ }
+ }
+
///
/// 查找类似 Anti-Aliasing 的本地化字符串。
///
diff --git a/src/Starward.Language/Lang.resx b/src/Starward.Language/Lang.resx
index 1b011af94..688d2c149 100644
--- a/src/Starward.Language/Lang.resx
+++ b/src/Starward.Language/Lang.resx
@@ -1645,4 +1645,10 @@ Do you accept the risk and continue to use it?
Use Version Poster
+
+ Actual Size of Installed Games
+
+
+ Storage Space Saved by Hard Links
+
\ No newline at end of file
diff --git a/src/Starward.Language/Lang.zh-CN.resx b/src/Starward.Language/Lang.zh-CN.resx
index e1e18d040..5542304be 100644
--- a/src/Starward.Language/Lang.zh-CN.resx
+++ b/src/Starward.Language/Lang.zh-CN.resx
@@ -1645,4 +1645,10 @@
使用版本海报
+
+ 已安装游戏实际占用空间
+
+
+ 通过硬链接节省存储空间
+
\ No newline at end of file
diff --git a/src/Starward/Features/GameSelector/GameBizDisplay.cs b/src/Starward/Features/GameSelector/GameBizDisplay.cs
index 5e07455b3..91abb6c19 100644
--- a/src/Starward/Features/GameSelector/GameBizDisplay.cs
+++ b/src/Starward/Features/GameSelector/GameBizDisplay.cs
@@ -1,5 +1,4 @@
-using CommunityToolkit.Mvvm.ComponentModel;
-using Starward.Core.HoYoPlay;
+using Starward.Core.HoYoPlay;
using System.Collections.Generic;
@@ -11,18 +10,6 @@ public class GameBizDisplay
public GameInfo GameInfo { get; set; }
- public List Servers { get; set; } = new();
-
-}
-
-
-public class GameBizDisplayServer : ObservableObject
-{
-
- public GameBizIcon GameBizIcon { get; set; }
-
-
- public bool IsPinned { get; set => SetProperty(ref field, value); }
-
+ public List Servers { get; set; } = new();
}
diff --git a/src/Starward/Features/GameSelector/GameBizIcon.cs b/src/Starward/Features/GameSelector/GameBizIcon.cs
index f962469a0..4318f21a1 100644
--- a/src/Starward/Features/GameSelector/GameBizIcon.cs
+++ b/src/Starward/Features/GameSelector/GameBizIcon.cs
@@ -10,6 +10,9 @@ public partial class GameBizIcon : ObservableObject, IEquatable
{
+ private const double GB = 1 << 30;
+
+
public GameId GameId { get; set; }
public GameBiz GameBiz { get; set; }
@@ -25,6 +28,15 @@ public partial class GameBizIcon : ObservableObject, IEquatable
public double MaskOpacity { get; set => SetProperty(ref field, value); } = 1.0;
+ public bool IsPinned { get; set => SetProperty(ref field, value); }
+
+ public string? InstallPath { get; set => SetProperty(ref field, value); }
+
+ public long TotalSize { get; set { field = value; OnPropertyChanged(nameof(TotalSizeText)); } }
+
+ public string? TotalSizeText => TotalSize == 0 ? null : $"{TotalSize / GB:F2}GB";
+
+
public bool IsSelected
{
get;
@@ -61,6 +73,25 @@ public GameBizIcon(GameInfo gameInfo)
+ public void UpdateInfo()
+ {
+ GameIcon = GameBizToIcon(GameBiz);
+ ServerIcon = GameBizToServerIcon(GameBiz);
+ GameName = GameBiz.ToGameName();
+ ServerName = GameBiz.ToGameServerName();
+ }
+
+
+ public void UpdateInfo(GameInfo gameInfo)
+ {
+ GameIcon = gameInfo.Display.Icon.Url;
+ ServerIcon = GameBizToServerIcon(gameInfo.GameBiz);
+ GameName = gameInfo.Display.Name;
+ ServerName = gameInfo.GameBiz.ToGameServerName();
+ }
+
+
+
private static string GameBizToIcon(GameBiz gameBiz)
{
return gameBiz.Game switch
diff --git a/src/Starward/Features/GameSelector/GameSelector.xaml b/src/Starward/Features/GameSelector/GameSelector.xaml
index aca916c6e..fb1c3c185 100644
--- a/src/Starward/Features/GameSelector/GameSelector.xaml
+++ b/src/Starward/Features/GameSelector/GameSelector.xaml
@@ -65,7 +65,7 @@
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0,0,0,1
+ 0
+
+
+
-
-
+
-
-
+
+
+
+
+ Foreground="{ThemeResource TextFillColorSecondaryBrush}"
+ Visibility="{x:Bind InstalledGamesSavedSize, Converter={StaticResource ObjectToVisibilityConverter}}">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
diff --git a/src/Starward/Features/GameSelector/GameSelector.xaml.cs b/src/Starward/Features/GameSelector/GameSelector.xaml.cs
index 112c30d83..5f13905a2 100644
--- a/src/Starward/Features/GameSelector/GameSelector.xaml.cs
+++ b/src/Starward/Features/GameSelector/GameSelector.xaml.cs
@@ -5,18 +5,24 @@
using Microsoft.UI.Xaml.Controls.Primitives;
using Starward.Core;
using Starward.Core.HoYoPlay;
+using Starward.Features.GameLauncher;
using Starward.Features.HoYoPlay;
using Starward.Frameworks;
using Starward.Helpers;
using Starward.Messages;
-using Starward.Services.Launcher;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Diagnostics;
using System.Globalization;
+using System.IO;
using System.Linq;
using System.Numerics;
+using System.Runtime.InteropServices;
using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Vanara.PInvoke;
using Windows.Foundation;
@@ -30,7 +36,10 @@ public sealed partial class GameSelector : UserControl
public event EventHandler<(GameId, bool DoubleTapped)>? CurrentGameChanged;
- private HoYoPlayService _hoyoplayService = AppService.GetService();
+ private readonly HoYoPlayService _hoyoplayService = AppService.GetService();
+
+
+ private readonly GameLauncherService _gameLauncherService = AppService.GetService();
@@ -38,11 +47,11 @@ public GameSelector()
{
this.InitializeComponent();
InitializeGameSelector();
+ this.Loaded += GameSelector_Loaded;
}
-
public GameBiz CurrentGameBiz { get; set; }
@@ -64,38 +73,35 @@ public void InitializeGameSelector()
{
InitializeGameIconsArea();
InitializeGameServerArea();
+ InitializeInstalledGamesCommand.Execute(null);
}
- [RelayCommand]
- public void AutoSearchInstalledGames()
+ private async void GameSelector_Loaded(object sender, RoutedEventArgs e)
{
- try
- {
- // todo 从注册表自动搜索已安装的游戏
- var service = AppService.GetService();
- var sb = new StringBuilder();
- foreach (GameBiz biz in GameBiz.AllGameBizs)
- {
- if (service.IsGameExeExists(biz))
- {
- sb.Append(biz.ToString());
- sb.Append(',');
- }
- }
- AppSetting.SelectedGameBizs = sb.ToString().TrimEnd(',');
- InitializeGameSelector();
- }
- catch (Exception ex)
- {
+ await Task.Delay(2000);
+ await UpdateGameInfoAsync();
+ }
+
+
+
+
+ public async void OnLanguageChanged(object? sender, LanguageChangedMessage message)
+ {
+ // todo 语言切换
+ if (message.Completed)
+ {
+ this.Bindings.Update();
+ await UpdateGameInfoAsync();
}
}
+
#region Game Icon
@@ -415,7 +421,6 @@ private void GameBizIcons_CollectionChanged(object? sender, System.Collections.S
-
#region Full Background 黑色半透明背景
@@ -485,7 +490,7 @@ private void InitializeGameServerArea()
try
{
var list = new List();
- var infos = _hoyoplayService.GetCachedGameInfos();
+ var infos = _hoyoplayService.GetCachedGameInfoList();
if (LanguageUtil.FilterLanguage(CultureInfo.CurrentUICulture.Name) is "zh-cn")
{
@@ -510,6 +515,7 @@ private void InitializeGameServerArea()
}
}
+ // 分类每个游戏的服务器信息
foreach (var item in list)
{
string game = item.GameInfo.GameBiz.Game;
@@ -518,18 +524,16 @@ private void InitializeGameServerArea()
GameBiz biz = game + suffix;
if (biz.IsKnown())
{
- var server = new GameBizDisplayServer
+ var server = new GameBizIcon(biz)
{
- GameBizIcon = new GameBizIcon(biz),
IsPinned = GameBizIcons.Any(x => x.GameBiz == biz),
};
item.Servers.Add(server);
}
else if (_hoyoplayService.GetCachedGameInfo(biz) is GameInfo info)
{
- var server = new GameBizDisplayServer
+ var server = new GameBizIcon(info)
{
- GameBizIcon = new GameBizIcon(info),
IsPinned = GameBizIcons.Any(x => x.GameBiz == biz),
};
item.Servers.Add(server);
@@ -543,6 +547,37 @@ private void InitializeGameServerArea()
+ ///
+ /// 更新所有游戏服务器信息,更新游戏图标
+ ///
+ ///
+ private async Task UpdateGameInfoAsync()
+ {
+ try
+ {
+ _hoyoplayService.ClearCache();
+ await _hoyoplayService.UpdateGameInfoListAsync();
+ InitializeGameServerArea();
+ foreach (GameBizIcon icon in GameBizIcons)
+ {
+ if (icon.GameBiz.IsKnown())
+ {
+ icon.UpdateInfo();
+ }
+ else
+ {
+ GameInfo info = await _hoyoplayService.GetGameInfoAsync(icon.GameId);
+ icon.UpdateInfo(info);
+ }
+ }
+ await InitializeInstalledGamesCommand.ExecuteAsync(null);
+ }
+ catch { }
+ }
+
+
+
+
///
/// 游戏服务器选择区域是否可见
///
@@ -559,7 +594,7 @@ private void Grid_GameBizDisplay_Tapped(object sender, Microsoft.UI.Xaml.Input.T
if (sender is FrameworkElement ele)
{
e.Handled = true;
- _isGameBizDisplayPressed = true;
+ _isGameBizDisplayPressed = !_isGameBizDisplayPressed;
FlyoutBase.GetAttachedFlyout(ele)?.ShowAt(ele, new FlyoutShowOptions
{
Placement = FlyoutPlacementMode.Bottom,
@@ -587,6 +622,42 @@ private void Grid_GameBizDisplay_PointerEntered(object sender, Microsoft.UI.Xaml
}
+ ///
+ /// 点击服务器图标
+ ///
+ ///
+ ///
+ private void Button_GameServer_Click(object sender, RoutedEventArgs e)
+ {
+ try
+ {
+ if (sender is FrameworkElement fe && fe.DataContext is GameBizIcon server)
+ {
+ if (CurrentGameBizIcon is not null)
+ {
+ CurrentGameBizIcon.IsSelected = false;
+ }
+
+ if (GameBizIcons.FirstOrDefault(x => x.GameId == server.GameId) is GameBizIcon icon)
+ {
+ CurrentGameBizIcon = icon;
+ CurrentGameBiz = icon.GameBiz;
+ CurrentGameId = icon.GameId;
+ icon.IsSelected = true;
+ }
+ else
+ {
+ CurrentGameBizIcon = server;
+ server.IsSelected = true;
+ }
+
+ CurrentGameChanged?.Invoke(this, (server.GameId, false));
+ AppSetting.CurrentGameBiz = server.GameBiz;
+ }
+ }
+ catch { }
+ }
+
///
/// 固定游戏服务器图标到待选区
@@ -595,9 +666,9 @@ private void Grid_GameBizDisplay_PointerEntered(object sender, Microsoft.UI.Xaml
///
private void Button_PinGameBiz_Click(object sender, RoutedEventArgs e)
{
- if (sender is FrameworkElement fe && fe.DataContext is GameBizDisplayServer server)
+ if (sender is FrameworkElement fe && fe.DataContext is GameBizIcon server)
{
- var biz = server.GameBizIcon.GameBiz;
+ var biz = server.GameBiz;
if (GameBizIcons.FirstOrDefault(x => x.GameBiz == biz) is GameBizIcon icon)
{
GameBizIcons.Remove(icon);
@@ -605,7 +676,7 @@ private void Button_PinGameBiz_Click(object sender, RoutedEventArgs e)
}
else
{
- GameBizIcons.Add(server.GameBizIcon);
+ GameBizIcons.Add(server);
server.IsPinned = true;
}
}
@@ -620,17 +691,166 @@ private void Button_PinGameBiz_Click(object sender, RoutedEventArgs e)
+ #region Installed Games
+
+
+ ///
+ /// 已安装游戏的实际占用空间
+ ///
+ public string? InstalledGamesActualSize { get; set => SetProperty(ref field, value); }
+
+
+ ///
+ /// 已安装游戏的总空间
+ ///
+ public string? InstalledGamesSavedSize { get; set => SetProperty(ref field, value); }
+
+
+
+
+ public ObservableCollection InstalledGames { get; set; } = new();
+
+
- public void OnLanguageChanged(object? sender, LanguageChangedMessage message)
+ private CancellationTokenSource? _initializeInstalledGamesCancellationTokenSource;
+
+
+ ///
+ /// 初始化已安装游戏列表,计算已安装游戏的实际占用空间
+ ///
+ ///
+ [RelayCommand]
+ private async Task InitializeInstalledGamesAsync()
{
- // todo 语言切换
- if (message.Completed)
+ const double GB = 1 << 30;
+ try
{
- this.Bindings.Update();
+ _initializeInstalledGamesCancellationTokenSource?.Cancel();
+ _initializeInstalledGamesCancellationTokenSource = new();
+ CancellationToken token = _initializeInstalledGamesCancellationTokenSource.Token;
+
+ InstalledGames.Clear();
+ InstalledGamesActualSize = null;
+ InstalledGamesSavedSize = null;
+ List files = new();
+
+ foreach (GameBizDisplay display in GameBizDisplays)
+ {
+ List _duplicateFiles = new();
+ int serverCount = 0;
+ foreach (GameBizIcon server in display.Servers)
+ {
+ string? installPath = _gameLauncherService.GetGameInstallPath(server.GameId);
+ if (Directory.Exists(installPath))
+ {
+ server.InstallPath = installPath;
+ var _files = new DirectoryInfo(installPath).EnumerateFiles("*", SearchOption.AllDirectories).ToList();
+ server.TotalSize = _files.Sum(x => x.Length);
+ InstalledGames.Add(server);
+ if (_files.Count() > 0)
+ {
+ serverCount++;
+ _duplicateFiles.AddRange(_files);
+ }
+ }
+ }
+ if (serverCount > 1)
+ {
+ files.AddRange(_duplicateFiles);
+ }
+ }
+ long totalSize = InstalledGames.Sum(x => x.TotalSize);
+ InstalledGamesActualSize = $"{totalSize / GB:F2}GB";
+
+ if (token.IsCancellationRequested)
+ {
+ return;
+ }
+
+ if (files.Count > 0)
+ {
+ (long fileSize, long actualSize) = await Task.Run(() =>
+ {
+ long size = 0;
+ Dictionary dic = new();
+ foreach (var file in files)
+ {
+ size += file.Length;
+ using var handle = File.OpenHandle(file.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ var idInfo = Kernel32.GetFileInformationByHandleEx(handle, Kernel32.FILE_INFO_BY_HANDLE_CLASS.FileIdInfo);
+ var idInfoBytes = MemoryMarshal.AsBytes(MemoryMarshal.CreateReadOnlySpan(ref idInfo, 1));
+ dic[Convert.ToHexString(idInfoBytes)] = file.Length;
+ }
+ return (size, dic.Values.Sum());
+ }, token);
+
+ if (token.IsCancellationRequested)
+ {
+ return;
+ }
+
+ InstalledGamesActualSize = $"{(totalSize - fileSize + actualSize) / GB:F2}GB";
+ InstalledGamesSavedSize = $"{(fileSize - actualSize) / GB:F2}GB";
+ }
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
+ }
+ }
+
+
+
+
+
+ [RelayCommand]
+ public void AutoSearchInstalledGames()
+ {
+ try
+ {
+ // todo 从注册表自动搜索已安装的游戏
+ //var service = AppService.GetService();
+ //var sb = new StringBuilder();
+ //foreach (GameBiz biz in GameBiz.AllGameBizs)
+ //{
+ // if (service.IsGameExeExistsAsync(biz))
+ // {
+ // sb.Append(biz.ToString());
+ // sb.Append(',');
+ // }
+ //}
+ //AppSetting.SelectedGameBizs = sb.ToString().TrimEnd(',');
+ //InitializeGameSelector();
+ }
+ catch (Exception ex)
+ {
+ Debug.WriteLine(ex);
}
}
+
+
+ ///
+ /// 防止点击已安装游戏列表时,触发
+ ///
+ ///
+ ///
+ private void Expander_InstalledGamesActualSize_Tapped(object sender, Microsoft.UI.Xaml.Input.TappedRoutedEventArgs e)
+ {
+ e.Handled = true;
+ }
+
+
+
+ #endregion
+
+
+
+
+
+
+
}
diff --git a/src/Starward/Features/HoYoPlay/HoYoPlayService.cs b/src/Starward/Features/HoYoPlay/HoYoPlayService.cs
index c419948ac..6f5717ba7 100644
--- a/src/Starward/Features/HoYoPlay/HoYoPlayService.cs
+++ b/src/Starward/Features/HoYoPlay/HoYoPlayService.cs
@@ -10,6 +10,7 @@
using System.Linq;
using System.Net.Http;
using System.Text.Json;
+using System.Threading;
using System.Threading.Tasks;
namespace Starward.Features.HoYoPlay;
@@ -38,11 +39,12 @@ public HoYoPlayService(ILogger logger, HoYoPlayClient client, H
Enabled = true,
Interval = TimeSpan.FromMinutes(10).TotalMilliseconds,
};
- _timer.Elapsed += async (_, _) => await PrepareDataAsync();
+ _timer.Elapsed += (_, _) => ClearCache();
LoadCachedGameInfo();
}
+ private List _gameInfoList = new();
private ConcurrentDictionary _gameInfo = new();
@@ -60,6 +62,8 @@ public HoYoPlayService(ILogger logger, HoYoPlayClient client, H
private ConcurrentDictionary _gameConfig = new();
+ private ConcurrentDictionary _gameChannelSDK = new();
+
private void LoadCachedGameInfo()
{
@@ -71,6 +75,7 @@ private void LoadCachedGameInfo()
var infos = JsonSerializer.Deserialize>(json);
if (infos is not null)
{
+ _gameInfoList = infos;
foreach (var item in infos)
{
_gameInfo[item] = item;
@@ -82,229 +87,120 @@ private void LoadCachedGameInfo()
}
- private void CacheGameInfo()
- {
- try
- {
- var infos = _gameInfo.Values.ToList();
- string json = JsonSerializer.Serialize(infos);
- AppSetting.CachedGameInfo = json;
- }
- catch { }
- }
-
-
public void ClearCache()
{
+ _gameInfoList.Clear();
_gameInfo.Clear();
_gameBackground.Clear();
_gameContent.Clear();
_gamePackage.Clear();
+ _gameChannelSDK.Clear();
}
-
- public async Task PrepareDataAsync()
+ public async Task GetGameInfoAsync(GameId gameId)
{
- try
+ if (!_gameInfo.TryGetValue(gameId, out GameInfo? info))
{
- ClearCache();
string lang = CultureInfo.CurrentUICulture.Name;
- List tasks = [];
- tasks.Add(PrepareDataForServerAsync(LauncherId.ChinaOfficial, lang));
- tasks.Add(PrepareDataForServerAsync(LauncherId.GlobalOfficial, lang));
- tasks.Add(PrepareDataForBilibiliServerAsync(lang));
- await Task.WhenAll(tasks);
- CacheGameInfo();
- await PrepareImagesAsync();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, nameof(PrepareDataAsync));
+ var list = await _client.GetGameInfoAsync(LauncherId.FromGameId(gameId)!, lang);
+ foreach (var item in list)
+ {
+ _gameInfo[item] = item;
+ }
+ info = list.First(x => x == gameId);
}
+ return info;
}
- private async Task PrepareDataForServerAsync(string launcherId, string? language = null)
+ public GameInfo? GetCachedGameInfo(GameBiz biz)
{
- try
- {
- language ??= CultureInfo.CurrentUICulture.Name;
- List infos = await _client.GetGameInfoAsync(launcherId, language);
- foreach (GameInfo item in infos)
- {
- _gameInfo[item] = item;
- }
- List backgrounds = await _client.GetGameBackgroundAsync(launcherId, language);
- foreach (GameBackgroundInfo item in backgrounds)
- {
- _gameBackground[item.GameId] = item;
- }
- foreach (var item in infos)
- {
- GameContent content = await _client.GetGameContentAsync(launcherId, language, item);
- _gameContent[content.GameId] = content;
- }
- List packages = await _client.GetGamePackageAsync(launcherId, language);
- foreach (GamePackage item in packages)
- {
- _gamePackage[item.GameId] = item;
- }
- List configs = await _client.GetGameConfigAsync(launcherId, language);
- foreach (GameConfig item in configs)
- {
- _gameConfig[item.GameId] = item;
- }
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, nameof(PrepareDataForServerAsync));
- }
+ return _gameInfo.Values.FirstOrDefault(x => x.GameBiz == biz);
}
- private async Task PrepareDataForBilibiliServerAsync(string? language = null)
+ public List GetCachedGameInfoList()
{
- try
+ return _gameInfoList;
+ }
+
+
+
+ public async Task> UpdateGameInfoListAsync(CancellationToken cancellationToken = default)
+ {
+ List infos = new List();
+ string lang = CultureInfo.CurrentUICulture.Name;
+ if (LanguageUtil.FilterLanguage(lang) is "zh-cn")
{
- language ??= CultureInfo.CurrentUICulture.Name;
- foreach ((GameBiz biz, string launcherId) in LauncherId.GetBilibiliLaunchers())
- {
- List infos = await _client.GetGameInfoAsync(launcherId, language);
- foreach (GameInfo item in infos)
- {
- _gameInfo[item] = item;
- }
- List backgrounds = await _client.GetGameBackgroundAsync(launcherId, language);
- foreach (GameBackgroundInfo item in backgrounds)
- {
- _gameBackground[item.GameId] = item;
- }
- foreach (GameInfo item in infos)
- {
- GameContent content = await _client.GetGameContentAsync(launcherId, language, item);
- _gameContent[item] = content;
- }
- List packages = await _client.GetGamePackageAsync(launcherId, language);
- foreach (GamePackage item in packages)
- {
- _gamePackage[item.GameId] = item;
- }
- List configs = await _client.GetGameConfigAsync(launcherId, language);
- foreach (GameConfig item in configs)
- {
- _gameConfig[item.GameId] = item;
- }
- }
+ infos.AddRange(await _client.GetGameInfoAsync(LauncherId.ChinaOfficial, lang, cancellationToken));
+ infos.AddRange(await _client.GetGameInfoAsync(LauncherId.GlobalOfficial, lang, cancellationToken));
}
- catch (Exception ex)
+ else
+ {
+ infos.AddRange(await _client.GetGameInfoAsync(LauncherId.GlobalOfficial, lang, cancellationToken));
+ infos.AddRange(await _client.GetGameInfoAsync(LauncherId.ChinaOfficial, lang, cancellationToken));
+ }
+ foreach ((GameBiz _, string launcherId) in LauncherId.GetBilibiliLaunchers())
+ {
+ infos.AddRange(await _client.GetGameInfoAsync(launcherId, lang, cancellationToken));
+ }
+ _gameInfoList = infos;
+ foreach (var item in infos)
{
- _logger.LogError(ex, nameof(PrepareDataForBilibiliServerAsync));
+ _gameInfo[item] = item;
}
+ string json = JsonSerializer.Serialize(infos);
+ AppSetting.CachedGameInfo = json;
+ _ = DownloadGameVersionPosterAsync(infos);
+ return infos;
}
- private async Task PrepareImagesAsync()
+ private async Task DownloadGameVersionPosterAsync(List infos)
{
try
{
- List bizs = GetSelectedGameBizs();
- List<(string Url, bool InBg)> urls = [];
- foreach (GameBiz biz in bizs)
+ List urls = new();
+ foreach (var info in infos)
{
- if (GameId.FromGameBiz(biz) is GameId gameId)
+ if (!string.IsNullOrWhiteSpace(info.Display.Background?.Url))
{
- if (_gameInfo.TryGetValue(gameId, out GameInfo? info))
- {
- urls.Add((info.Display.Background.Url, true));
- }
- if (_gameBackground.TryGetValue(gameId, out GameBackgroundInfo? background))
- {
- urls.AddRange(background.Backgrounds.Select(x => (x.Background.Url, false)));
- }
+ urls.Add(info.Display.Background.Url);
}
}
- string bg = Path.Combine(AppConfig.UserDataFolder, "bg");
- string cache = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Starward\cache");
- Directory.CreateDirectory(bg);
- Directory.CreateDirectory(cache);
- await Parallel.ForEachAsync(urls, async (item, _) =>
+ if (AppSetting.UserDataFolder is not null)
{
- try
+ string bg = Path.Combine(AppSetting.UserDataFolder, "bg");
+ Directory.CreateDirectory(bg);
+ await Parallel.ForEachAsync(urls, async (url, _) =>
{
- if (string.IsNullOrWhiteSpace(item.Url))
+ try
{
- return;
+ string name = Path.GetFileName(url);
+ string path = Path.Combine(bg, name);
+ if (!File.Exists(path))
+ {
+ byte[] bytes = await _httpClient.GetByteArrayAsync(url);
+ await File.WriteAllBytesAsync(path, bytes);
+ }
}
- string name = Path.GetFileName(item.Url);
- string path = item.InBg ? Path.Combine(bg, name) : Path.Combine(cache, name);
- if (!File.Exists(path))
+ catch (Exception ex)
{
- byte[] bytes = await _httpClient.GetByteArrayAsync(item.Url);
- await File.WriteAllBytesAsync(path, bytes);
+ _logger.LogError(ex, "Download image: {url}", url);
}
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Download image: {url}", item);
- }
- });
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, nameof(PrepareImagesAsync));
- }
- }
-
-
-
- private static List GetSelectedGameBizs()
- {
- List bizs = new();
- foreach (string str in AppConfig.SelectedGameBizs?.Split(',') ?? [])
- {
- if (GameBiz.TryParse(str, out GameBiz biz))
- {
- bizs.Add(biz);
+ });
}
}
- return bizs;
- }
-
-
-
-
- public async Task GetGameInfoAsync(GameId gameId)
- {
- if (!_gameInfo.TryGetValue(gameId, out GameInfo? info))
+ catch (Exception ex)
{
- string lang = CultureInfo.CurrentUICulture.Name;
- var list = await _client.GetGameInfoAsync(LauncherId.FromGameId(gameId)!, lang);
- foreach (var item in list)
- {
- _gameInfo[item] = item;
- }
- info = list.First(x => x == gameId);
+ _logger.LogError(ex, nameof(DownloadGameVersionPosterAsync));
}
- return info;
- }
-
-
-
- public GameInfo? GetCachedGameInfo(GameBiz gameBiz)
- {
- return _gameInfo.Values.FirstOrDefault(x => x.GameBiz == gameBiz);
- }
-
-
- public List GetCachedGameInfos()
- {
- return _gameInfo.Values.ToList();
}
@@ -391,12 +287,17 @@ public async Task> GetGameDeprecatedFilesAsync(GameId g
public async Task GetGameChannelSDKAsync(GameId gameId)
{
- var launcherId = LauncherId.FromGameId(gameId);
- if (launcherId is not null)
+ if (!_gameChannelSDK.TryGetValue(gameId, out GameChannelSDK? sdk))
{
- return await _client.GetGameChannelSDKAsync(launcherId, "en-us", gameId);
+ string lang = CultureInfo.CurrentUICulture.Name;
+ var list = await _client.GetGameChannelSDKAsync(LauncherId.FromGameId(gameId)!, lang);
+ foreach (var item in list)
+ {
+ _gameChannelSDK[item.GameId] = item;
+ }
+ sdk = list.FirstOrDefault(x => x.GameId == gameId);
}
- return null;
+ return sdk;
}