diff --git a/src/Starward.Core/HoYoPlay/GameBranch.cs b/src/Starward.Core/HoYoPlay/GameBranch.cs
index ed13bbd7f..62dacbd6e 100644
--- a/src/Starward.Core/HoYoPlay/GameBranch.cs
+++ b/src/Starward.Core/HoYoPlay/GameBranch.cs
@@ -36,7 +36,7 @@ public class GameBranchPackage
[JsonPropertyName("package_id")]
public string PackageId { get; set; }
-
+ // main or pre_download
[JsonPropertyName("branch")]
public string Branch { get; set; }
diff --git a/src/Starward.Core/HoYoPlay/GameChunkBuild.cs b/src/Starward.Core/HoYoPlay/GameChunkBuild.cs
index 1ad7156ae..1fbbdded3 100644
--- a/src/Starward.Core/HoYoPlay/GameChunkBuild.cs
+++ b/src/Starward.Core/HoYoPlay/GameChunkBuild.cs
@@ -2,19 +2,24 @@
namespace Starward.Core.HoYoPlay;
+
public class GameChunkBuild
{
- // json string build_id
[JsonPropertyName("build_id")]
public string BuildId { get; set; }
- // string tag
+ ///
+ /// 游戏版本
+ ///
[JsonPropertyName("tag")]
public string Tag { get; set; }
+ ///
+ /// 文件清单
+ ///
[JsonPropertyName("manifests")]
public List Manifests { get; set; }
@@ -22,43 +27,60 @@ public class GameChunkBuild
}
-
+///
+/// Chunk 下载模式文件清单
+///
public class GameChunkManifest
{
-
- // string category_id
+ ///
+ /// 资源ID
+ ///
[JsonPropertyName("category_id")]
public string CategoryId { get; set; }
- // string category_name
+ ///
+ /// 资源名称
+ ///
[JsonPropertyName("category_name")]
public string CategoryName { get; set; }
- // string matching_field
+ ///
+ /// 资源类型,game or 语音类型(zh-cn, en-us, ja-jp, ko-kr)
+ ///
[JsonPropertyName("matching_field")]
public string MatchingField { get; set; }
- // gamechunkmanifestfile manifest
+ ///
+ /// 清单文件信息
+ ///
[JsonPropertyName("manifest")]
public GameChunkManifestFile Manifest { get; set; }
- // gamechunkmanifesturl chunk_download
+ ///
+ /// 分块文件下载链接前缀
+ ///
[JsonPropertyName("chunk_download")]
public GameChunkManifestUrl ChunkDownload { get; set; }
- // gamechunkmanifesturl manifest_download
+ ///
+ /// 清单文件下载链接前缀
+ ///
[JsonPropertyName("manifest_download")]
public GameChunkManifestUrl ManifestDownload { get; set; }
- // gamechunkmanifeststats stats
+ ///
+ /// 文件统计信息
+ ///
[JsonPropertyName("stats")]
public GameChunkManifestStats Stats { get; set; }
- // gamechunkmanifeststats deduplicated_stats
+ ///
+ /// 去重后的文件统计信息
+ ///
[JsonPropertyName("deduplicated_stats")]
public GameChunkManifestStats DeduplicatedStats { get; set; }
@@ -68,11 +90,15 @@ public class GameChunkManifest
public class GameChunkManifestFile
{
-
+ ///
+ /// 文件名,与下载链接前缀拼接为下载链接
+ ///
[JsonPropertyName("id")]
public string Id { get; set; }
-
+ ///
+ /// 解压后的MD5
+ ///
[JsonPropertyName("checksum")]
public string Checksum { get; set; }
@@ -90,26 +116,38 @@ public class GameChunkManifestFile
-
+///
+/// 文件下载链接前缀
+///
public class GameChunkManifestUrl
{
-
+ ///
+ /// 加密
+ ///
[JsonPropertyName("encryption")]
public int Encryption { get; set; }
-
+ ///
+ /// 密码
+ ///
[JsonPropertyName("password")]
public string Password { get; set; }
-
+ ///
+ /// 压缩
+ ///
[JsonPropertyName("compression")]
public int Compression { get; set; }
-
+ ///
+ /// 前缀
+ ///
[JsonPropertyName("url_prefix")]
public string UrlPrefix { get; set; }
-
+ ///
+ /// 后缀
+ ///
[JsonPropertyName("url_suffix")]
public string UrlSuffix { get; set; }
@@ -117,6 +155,7 @@ public class GameChunkManifestUrl
+
public class GameChunkManifestStats
{
@@ -139,4 +178,6 @@ public class GameChunkManifestStats
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString)]
public int ChunkCount { get; set; }
+
}
+
diff --git a/src/Starward.Core/HoYoPlay/GamePatchBuild.cs b/src/Starward.Core/HoYoPlay/GamePatchBuild.cs
new file mode 100644
index 000000000..15db31c58
--- /dev/null
+++ b/src/Starward.Core/HoYoPlay/GamePatchBuild.cs
@@ -0,0 +1,85 @@
+using System.Text.Json.Serialization;
+
+namespace Starward.Core.HoYoPlay;
+
+
+public class GamePatchBuild
+{
+
+ [JsonPropertyName("build_id")]
+ public string BuildId { get; set; }
+
+
+ [JsonPropertyName("patch_id")]
+ public string PatchId { get; set; }
+
+
+ ///
+ /// 游戏版本
+ ///
+ [JsonPropertyName("tag")]
+ public string Tag { get; set; }
+
+
+ ///
+ /// 文件清单
+ ///
+ [JsonPropertyName("manifests")]
+ public List Manifests { get; set; }
+
+
+}
+
+
+///
+/// Chunk 下载模式补丁文件清单
+///
+public class GamePatchManifest
+{
+ ///
+ /// 资源ID
+ ///
+ [JsonPropertyName("category_id")]
+ public string CategoryId { get; set; }
+
+ ///
+ /// 资源名称
+ ///
+ [JsonPropertyName("category_name")]
+ public string CategoryName { get; set; }
+
+ ///
+ /// 资源类型,game or 语音类型(zh-cn, en-us, ja-jp, ko-kr)
+ ///
+ [JsonPropertyName("matching_field")]
+ public string MatchingField { get; set; }
+
+ ///
+ /// 清单文件信息
+ ///
+ [JsonPropertyName("manifest")]
+ public GameChunkManifestFile Manifest { get; set; }
+
+
+ ///
+ /// 分块文件下载链接前缀
+ ///
+ [JsonPropertyName("diff_download")]
+ public GameChunkManifestUrl DiffDownload { get; set; }
+
+
+ ///
+ /// 清单文件下载链接前缀
+ ///
+ [JsonPropertyName("manifest_download")]
+ public GameChunkManifestUrl ManifestDownload { get; set; }
+
+
+ ///
+ /// 文件统计信息
+ ///
+ [JsonPropertyName("stats")]
+ public Dictionary Stats { get; set; }
+
+
+}
diff --git a/src/Starward.Core/HoYoPlay/HoYoPlayClient.cs b/src/Starward.Core/HoYoPlay/HoYoPlayClient.cs
index 336958799..0bae6145e 100644
--- a/src/Starward.Core/HoYoPlay/HoYoPlayClient.cs
+++ b/src/Starward.Core/HoYoPlay/HoYoPlayClient.cs
@@ -64,6 +64,25 @@ private async Task CommonGetAsync(string url, string node, CancellationTok
+ private async Task CommonSendAsync(HttpRequestMessage request, CancellationToken cancellationToken = default)
+ {
+ var response = await _httpClient.SendAsync(request, cancellationToken);
+ response.EnsureSuccessStatusCode();
+ var responseData = await response.Content.ReadFromJsonAsync(typeof(miHoYoApiWrapper), HoYoPlayJsonContext.Default, cancellationToken) as miHoYoApiWrapper;
+ if (responseData is null)
+ {
+ throw new miHoYoApiException(-1, "Can not parse the response body.");
+ }
+ if (responseData.Retcode != 0)
+ {
+ throw new miHoYoApiException(responseData.Retcode, responseData.Message);
+ }
+ return responseData.Data;
+ }
+
+
+
+
private static string BuildUrl(string api, string launcherId, string language)
{
@@ -455,7 +474,7 @@ public async Task> GetGameBranchAsync(string launcherId, string
///
- /// Chunk 下载模式清单
+ /// Chunk 下载模式文件清单
///
///
///
@@ -467,17 +486,17 @@ public async Task GetGameChunkBuildAsync(GameBranch gameBranch,
string? url = null;
if (gameBranch.GameId.GameBiz.IsChinaServer())
{
- url = "https://api-takumi.mihoyo.com/downloader/sophon_chunk/api/getBuild?plat_app=ddxf5qt290cg";
+ url = "https://downloader-api.mihoyo.com/downloader/sophon_chunk/api/getBuild?";
}
if (gameBranch.GameId.GameBiz.IsGlobalServer())
{
- url = "https://sg-public-api.hoyoverse.com/downloader/sophon_chunk/api/getBuild?plat_app=ddxf6vlr1reo";
+ url = "https://sg-downloader-api.hoyoverse.com/downloader/sophon_chunk/api/getBuild?";
}
if (url is null)
{
throw new ArgumentOutOfRangeException(nameof(gameBranch), $"Unknown game biz ({gameBranch.GameId.GameBiz}).");
}
- url += $"&branch={gameBranchPackage.Branch}&package_id={gameBranchPackage.PackageId}&password={gameBranchPackage.Password}";
+ url += $"branch={gameBranchPackage.Branch}&package_id={gameBranchPackage.PackageId}&password={gameBranchPackage.Password}";
return await CommonGetAsync(url, cancellationToken);
}
@@ -485,7 +504,7 @@ public async Task GetGameChunkBuildAsync(GameBranch gameBranch,
///
- /// Chunk 下载模式清单
+ /// Chunk 下载模式文件清单
///
///
///
@@ -498,22 +517,52 @@ public async Task GetGameChunkBuildAsync(GameBranch gameBranch,
string? url = null;
if (gameBranch.GameId.GameBiz.IsChinaServer())
{
- url = "https://api-takumi.mihoyo.com/downloader/sophon_chunk/api/getBuild?plat_app=ddxf5qt290cg";
+ url = "https://downloader-api.mihoyo.com/downloader/sophon_chunk/api/getBuild?";
}
if (gameBranch.GameId.GameBiz.IsGlobalServer())
{
- url = "https://sg-public-api.hoyoverse.com/downloader/sophon_chunk/api/getBuild?plat_app=ddxf6vlr1reo";
+ url = "https://sg-downloader-api.hoyoverse.com/downloader/sophon_chunk/api/getBuild?";
}
if (url is null)
{
throw new ArgumentOutOfRangeException(nameof(gameBranch), $"Unknown game biz ({gameBranch.GameId.GameBiz}).");
}
- url += $"&branch={gameBranchPackage.Branch}&package_id={gameBranchPackage.PackageId}&password={gameBranchPackage.Password}&tag={version}";
+ url += $"branch={gameBranchPackage.Branch}&package_id={gameBranchPackage.PackageId}&password={gameBranchPackage.Password}&tag={version}";
return await CommonGetAsync(url, cancellationToken);
}
+ ///
+ /// Chunk 下载模式的增量更新补丁文件清单
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task GetGameChunkPatchBuildAsync(GameBranch gameBranch, GameBranchPackage gameBranchPackage, CancellationToken cancellationToken = default)
+ {
+ string? url = null;
+ if (gameBranch.GameId.GameBiz.IsChinaServer())
+ {
+ url = "https://downloader-api.mihoyo.com/downloader/sophon_chunk/api/getPatchBuild?";
+ }
+ if (gameBranch.GameId.GameBiz.IsGlobalServer())
+ {
+ url = "https://sg-downloader-api.hoyoverse.com/downloader/sophon_chunk/api/getPatchBuild?";
+ }
+ if (url is null)
+ {
+ throw new ArgumentOutOfRangeException(nameof(gameBranch), $"Unknown game biz ({gameBranch.GameId.GameBiz}).");
+ }
+ url += $"branch={gameBranchPackage.Branch}&package_id={gameBranchPackage.PackageId}&password={gameBranchPackage.Password}";
+ var request = new HttpRequestMessage(HttpMethod.Post, url);
+ return await CommonSendAsync(request, cancellationToken);
+ }
+
+
+
}
diff --git a/src/Starward.Core/HoYoPlay/HoYoPlayJsonContext.cs b/src/Starward.Core/HoYoPlay/HoYoPlayJsonContext.cs
index babefba66..970bb7c4f 100644
--- a/src/Starward.Core/HoYoPlay/HoYoPlayJsonContext.cs
+++ b/src/Starward.Core/HoYoPlay/HoYoPlayJsonContext.cs
@@ -14,6 +14,7 @@ namespace Starward.Core.HoYoPlay;
[JsonSerializable(typeof(List))]
[JsonSerializable(typeof(List))]
[JsonSerializable(typeof(miHoYoApiWrapper))]
+[JsonSerializable(typeof(miHoYoApiWrapper))]
internal partial class HoYoPlayJsonContext : JsonSerializerContext
{