ResourceDownloader

This commit is contained in:
Kei-Luna
2026-04-27 16:13:27 +09:00
parent 8415969ffe
commit 7b6d1a3054
4 changed files with 104 additions and 1 deletions

View File

@@ -11,6 +11,8 @@ if (!argsMap.TryGetValue("--package", out var packagePath)
}
argsMap.TryGetValue("--pid", out var pidValue);
argsMap.TryGetValue("--resource-package", out var resourcePackagePath);
argsMap.TryGetValue("--resource-target", out var resourceTargetDirectory);
try
{
@@ -23,6 +25,9 @@ try
ZipFile.ExtractToDirectory(packagePath, stagingDirectory, overwriteFiles: true);
CopyDirectory(stagingDirectory, targetDirectory);
if (!string.IsNullOrWhiteSpace(resourcePackagePath) && !string.IsNullOrWhiteSpace(resourceTargetDirectory))
UpdateResources(resourcePackagePath, resourceTargetDirectory);
Process.Start(new ProcessStartInfo
{
FileName = restartExecutable,
@@ -88,3 +93,20 @@ static bool ShouldSkip(string relativePath)
{
return relativePath.StartsWith("Config", StringComparison.OrdinalIgnoreCase);
}
static void UpdateResources(string resourcePackagePath, string resourceTargetDirectory)
{
var resourceStagingDirectory = Path.Combine(Path.GetTempPath(), "MikuSB", "resource-staging", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(resourceStagingDirectory);
ZipFile.ExtractToDirectory(resourcePackagePath, resourceStagingDirectory, overwriteFiles: true);
var extractedRoot = Directory.GetDirectories(resourceStagingDirectory).FirstOrDefault() ?? resourceStagingDirectory;
var excelOutputSource = Path.Combine(extractedRoot, "ExcelOutput");
if (!Directory.Exists(excelOutputSource))
throw new DirectoryNotFoundException($"ExcelOutput directory was not found in resource package: {excelOutputSource}");
var excelOutputTarget = Path.Combine(resourceTargetDirectory, "ExcelOutput");
Directory.CreateDirectory(excelOutputTarget);
CopyDirectory(excelOutputSource, excelOutputTarget);
}

View File

@@ -7,6 +7,7 @@ using MikuSB.GameServer.Server.CallGS;
using MikuSB.GameServer.Server.Packet;
using MikuSB.Internationalization;
using MikuSB.MikuSB.Tool;
using MikuSB.MikuSB.Update;
using MikuSB.Proto;
using MikuSB.SdkServer;
using MikuSB.TcpSharp;
@@ -146,6 +147,7 @@ public class LoaderManager : MikuSB
// Load the game data
try
{
await UpdateService.EnsureResourcesPresentAsync();
Logger.Info(I18NManager.Translate("Server.ServerInfo.LoadingItem", I18NManager.Translate("Word.GameData")));
ResourceManager.LoadGameData();
}

View File

@@ -1,6 +1,7 @@
using System.Diagnostics;
using System.Net;
using System.Net.Http.Headers;
using System.IO.Compression;
using System.Text.Json;
using System.Text.Json.Serialization;
using MikuSB.Util;
@@ -16,6 +17,13 @@ public static class UpdateService
private static readonly string RepositoryName = "MikuSB";
private static readonly string AssetName = "MikuSB-win-x64.zip";
private static readonly int TimeoutSeconds = 5;
private static readonly string ResourceArchiveUrl =
"https://github.com/Kei-Luna/MikuSB-Resource/archive/refs/heads/main.zip";
private static readonly string[] RequiredResourceFiles =
[
"card.json",
"weapon.json"
];
public static async Task<bool> TryStartSelfUpdateAsync()
{
@@ -72,6 +80,10 @@ public static class UpdateService
Logger.Info($"Downloading update {release.TagName}.");
await DownloadFileAsync(client, asset.DownloadUrl, packagePath, cts.Token);
var resourcePackagePath = Path.Combine(tempRoot, "MikuSB-Resource-main.zip");
Logger.Info("Downloading resource package.");
await DownloadFileAsync(client, ResourceArchiveUrl, resourcePackagePath, cts.Token);
var checksumAsset = release.Assets.FirstOrDefault(x =>
string.Equals(x.Name, AssetName + ".sha256", StringComparison.OrdinalIgnoreCase));
if (checksumAsset != null)
@@ -90,7 +102,9 @@ public static class UpdateService
ArgumentList =
{
"--package", packagePath,
"--resource-package", resourcePackagePath,
"--target", AppContext.BaseDirectory,
"--resource-target", Path.Combine(AppContext.BaseDirectory, ConfigManager.Config.Path.ResourcePath),
"--restart", Path.Combine(AppContext.BaseDirectory, "MikuSB.exe"),
"--pid", Environment.ProcessId.ToString()
}
@@ -112,6 +126,15 @@ public static class UpdateService
}
}
public static async Task EnsureResourcesPresentAsync()
{
if (!AreRequiredResourcesPresent())
{
Logger.Warn("Required resources are missing. Downloading resource package.");
await DownloadAndInstallResourcesAsync();
}
}
private static string StageUpdaterExecutable()
{
var sourceDirectory = AppContext.BaseDirectory;
@@ -131,6 +154,45 @@ public static class UpdateService
return stagedUpdaterPath;
}
private static bool AreRequiredResourcesPresent()
{
var excelOutputPath = Path.Combine(AppContext.BaseDirectory, ConfigManager.Config.Path.ResourcePath, "ExcelOutput");
if (!Directory.Exists(excelOutputPath))
return false;
return RequiredResourceFiles.All(fileName => File.Exists(Path.Combine(excelOutputPath, fileName)));
}
private static async Task DownloadAndInstallResourcesAsync()
{
using var client = CreateHttpClient();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(Math.Max(1, TimeoutSeconds)));
var tempRoot = Path.Combine(Path.GetTempPath(), "MikuSB", "resources", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(tempRoot);
var resourcePackagePath = Path.Combine(tempRoot, "MikuSB-Resource-main.zip");
await DownloadFileAsync(client, ResourceArchiveUrl, resourcePackagePath, cts.Token);
InstallResourcesFromArchive(resourcePackagePath,
Path.Combine(AppContext.BaseDirectory, ConfigManager.Config.Path.ResourcePath));
}
private static void InstallResourcesFromArchive(string resourcePackagePath, string resourceTargetDirectory)
{
var resourceStagingDirectory = Path.Combine(Path.GetTempPath(), "MikuSB", "resource-staging", Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(resourceStagingDirectory);
ZipFile.ExtractToDirectory(resourcePackagePath, resourceStagingDirectory, overwriteFiles: true);
var extractedRoot = Directory.GetDirectories(resourceStagingDirectory).FirstOrDefault() ?? resourceStagingDirectory;
var excelOutputSource = Path.Combine(extractedRoot, "ExcelOutput");
if (!Directory.Exists(excelOutputSource))
throw new DirectoryNotFoundException($"ExcelOutput directory was not found in resource package: {excelOutputSource}");
var excelOutputTarget = Path.Combine(resourceTargetDirectory, "ExcelOutput");
Directory.CreateDirectory(excelOutputTarget);
CopyDirectory(excelOutputSource, excelOutputTarget);
}
private static bool ConfirmUpdate(string latestVersion)
{
Console.Write($"New version found: {BuildVersion.Current} -> {latestVersion}. Update now? [Y/n]: ");
@@ -199,6 +261,23 @@ public static class UpdateService
await source.CopyToAsync(destination, cancellationToken);
}
private static void CopyDirectory(string sourceDirectory, string targetDirectory)
{
foreach (var directory in Directory.GetDirectories(sourceDirectory, "*", SearchOption.AllDirectories))
{
var relativePath = Path.GetRelativePath(sourceDirectory, directory);
Directory.CreateDirectory(Path.Combine(targetDirectory, relativePath));
}
foreach (var file in Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories))
{
var relativePath = Path.GetRelativePath(sourceDirectory, file);
var destinationPath = Path.Combine(targetDirectory, relativePath);
Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)!);
File.Copy(file, destinationPath, overwrite: true);
}
}
private static void VerifySha256(string packagePath, string checksumPath)
{
var expected = File.ReadAllText(checksumPath).Split(' ', StringSplitOptions.RemoveEmptyEntries)[0].Trim();

View File

@@ -1 +1 @@
v=0.3
v=0.4