This commit is contained in:
HolographicHat
2025-06-08 00:44:32 +08:00
parent 645fe38c65
commit 62c08f54ab
13 changed files with 107 additions and 42 deletions

View File

@@ -446,6 +446,15 @@ namespace YaeAchievement.res {
}
}
/// <summary>
/// Looks up a localized string similar to An error occurred while reading the data. Please try again..
/// </summary>
internal static string StreamReadDataFail {
get {
return ResourceManager.GetString("StreamReadDataFail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Checking update....
/// </summary>
@@ -474,6 +483,15 @@ namespace YaeAchievement.res {
}
}
/// <summary>
/// Looks up a localized string similar to The process cannot access the file &apos;{0}&apos; because it is being used by another process. Please restart your computer and try again..
/// </summary>
internal static string UpdateFileShareViolation {
get {
return ResourceManager.GetString("UpdateFileShareViolation", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Has update: {0} =&gt; {1}.
/// </summary>

View File

@@ -175,4 +175,10 @@
<data name="SelectionPromptCompatInvalidChoice" xml:space="preserve">
<value>Please enter a number between 0 and {0}</value>
</data>
<data name="StreamReadDataFail" xml:space="preserve">
<value>An error occurred while reading the data. Please try again.</value>
</data>
<data name="UpdateFileShareViolation" xml:space="preserve">
<value>The process cannot access the file '{0}' because it is being used by another process. Please restart your computer and try again.</value>
</data>
</root>

View File

@@ -168,4 +168,10 @@
<data name="SelectionPromptCompatInvalidChoice" xml:space="preserve">
<value>请输入 0 到 {0} 之间的数字</value>
</data>
<data name="StreamReadDataFail" xml:space="preserve">
<value>读取数据时发生错误,请重试</value>
</data>
<data name="UpdateFileShareViolation" xml:space="preserve">
<value>文件 {0} 被其它程序占用,请 重启电脑 或 解除文件占用 后重试。</value>
</data>
</root>

View File

@@ -1,5 +1,5 @@
using System.Text.RegularExpressions;
using YaeAchievement.res;
using Spectre.Console;
using YaeAchievement.Utilities;
namespace YaeAchievement;
@@ -28,11 +28,15 @@ public static partial class AppConfig {
.Where(File.Exists)
.MaxBy(File.GetLastWriteTime);
if (logPath == null) {
throw new ApplicationException(App.ConfigNeedStartGenshin);
AnsiConsole.WriteLine(App.ConfigNeedStartGenshin);
Environment.Exit(-1);
}
GamePath = GetGamePathFromLogFile(logPath)
?? GetGamePathFromLogFile($"{logPath}.last")
?? throw new ApplicationException(App.ConfigNeedStartGenshin);
var gamePath = GetGamePathFromLogFile(logPath) ?? GetGamePathFromLogFile($"{logPath}.last");
if (gamePath == null) {
AnsiConsole.WriteLine(App.ConfigNeedStartGenshin);
Environment.Exit(-1);
}
GamePath = gamePath;
SentrySdk.AddBreadcrumb(GamePath.EndsWith("YuanShen.exe") ? "CN" : "OS", "GamePath");
}

View File

@@ -1,5 +1,4 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Net;
using System.Text;
using System.Text.Json;
@@ -8,7 +7,6 @@ using Microsoft.Win32;
using Spectre.Console;
using YaeAchievement.Outputs;
using YaeAchievement.Parsers;
using YaeAchievement.res;
using YaeAchievement.Utilities;
// ReSharper disable UnusedMember.Local

View File

@@ -1,4 +1,7 @@
using System.Diagnostics.CodeAnalysis;
global using System.Diagnostics;
global using YaeAchievement.res;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Proto;

View File

@@ -2,7 +2,6 @@
using System.Text.Json.Serialization;
using Google.Protobuf;
using Spectre.Console;
using YaeAchievement.res;
using YaeAchievement.Utilities;
namespace YaeAchievement.Parsers;
@@ -31,7 +30,7 @@ public sealed class AchievementAllDataNotify {
private static AchievementAllDataNotify? Instance { get; set; }
public static bool OnReceive(BinaryReader reader) {
var bytes = reader.ReadBytes(reader.ReadInt32());
var bytes = reader.ReadBytes();
CacheFile.Write("achievement_data", bytes);
Instance = ParseFrom(bytes);
return true;

View File

@@ -20,7 +20,7 @@ public sealed class PlayerStoreNotify {
public static PlayerStoreNotify Instance { get; } = new ();
public static bool OnReceive(BinaryReader reader) {
var bytes = reader.ReadBytes(reader.ReadInt32());
var bytes = reader.ReadBytes();
Instance.ParseFrom(bytes);
return true;
}

View File

@@ -2,7 +2,6 @@
using System.Text;
using Spectre.Console;
using YaeAchievement.Parsers;
using YaeAchievement.res;
using YaeAchievement.Utilities;
using static YaeAchievement.Utils;

View File

@@ -1,10 +1,29 @@
using System.Runtime.CompilerServices;
using Spectre.Console;
// ReSharper disable CheckNamespace
namespace Google.Protobuf;
public static class CodedInputStreamExtensions {
internal static class BinaryReaderExtensions {
public static byte[] ReadBytes(this BinaryReader reader) {
try {
var length = reader.ReadInt32();
if (length is < 0 or > 114514 * 2) {
throw new ArgumentException(nameof(length));
}
return reader.ReadBytes(length);
} catch (Exception e) when (e is IOException or ArgumentException) {
AnsiConsole.WriteLine(App.StreamReadDataFail);
Environment.Exit(-1);
throw new UnreachableException();
}
}
}
internal static class CodedInputStreamExtensions {
[UnsafeAccessor(UnsafeAccessorKind.Method)]
private static extern byte[] ReadRawBytes(CodedInputStream stream, int size);

View File

@@ -29,7 +29,16 @@ public sealed unsafe class GameProcess {
};
var wd = Path.GetDirectoryName(path)!;
if (!Native.CreateProcess(path, ref cmdLines, null, null, false, flags, null, wd, si, out var pi)) {
throw new ApplicationException($"CreateProcess fail: {Marshal.GetLastPInvokeErrorMessage()}");
var argumentData = new Dictionary<string, object> {
{ "path", path },
{ "workdir", wd },
{ "file_exists", File.Exists(path) },
};
throw new ApplicationException($"CreateProcess fail: {Marshal.GetLastPInvokeErrorMessage()}") {
Data = {
{ "sentry:context:Arguments", argumentData }
}
};
}
Id = pi.dwProcessId;
Handle = pi.hProcess;

View File

@@ -1,5 +1,4 @@
using Spectre.Console;
using YaeAchievement.res;
namespace YaeAchievement.Utilities;

View File

@@ -1,5 +1,4 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.IO.Pipes;
using System.Net;
@@ -11,7 +10,6 @@ using Windows.Win32.Foundation;
using Windows.Win32.System.Console;
using Proto;
using Spectre.Console;
using YaeAchievement.res;
using YaeAchievement.Utilities;
namespace YaeAchievement;
@@ -109,35 +107,42 @@ public static class Utils {
}
public static async Task CheckUpdate(bool useLocalLib) {
var versionData = await StartSpinnerAsync(App.UpdateChecking, _ => GetBucketFile("schicksal/version"));
var versionInfo = UpdateInfo.Parser.ParseFrom(versionData)!;
if (GlobalVars.AppVersionCode < versionInfo.VersionCode) {
AnsiConsole.WriteLine(App.UpdateNewVersion, GlobalVars.AppVersionName, versionInfo.VersionName);
AnsiConsole.WriteLine(App.UpdateDescription, versionInfo.Description);
if (versionInfo.EnableAutoUpdate) {
var newBin = await StartSpinnerAsync(App.UpdateDownloading, _ => GetBucketFile(versionInfo.PackageLink));
var tmpPath = Path.GetTempFileName();
var updaterPath = Path.Combine(GlobalVars.DataPath, "update.exe");
await using (var dstStream = File.Open($"{GlobalVars.DataPath}/update.exe", FileMode.Create)) {
await using var srcStream = typeof(Program).Assembly.GetManifestResourceStream("updater")!;
await srcStream.CopyToAsync(dstStream);
try {
var versionData = await StartSpinnerAsync(App.UpdateChecking, _ => GetBucketFile("schicksal/version"));
var versionInfo = UpdateInfo.Parser.ParseFrom(versionData)!;
if (GlobalVars.AppVersionCode < versionInfo.VersionCode) {
AnsiConsole.WriteLine(App.UpdateNewVersion, GlobalVars.AppVersionName, versionInfo.VersionName);
AnsiConsole.WriteLine(App.UpdateDescription, versionInfo.Description);
if (versionInfo.EnableAutoUpdate) {
var newBin = await StartSpinnerAsync(App.UpdateDownloading, _ => GetBucketFile(versionInfo.PackageLink));
var tmpPath = Path.GetTempFileName();
var updaterPath = Path.Combine(GlobalVars.DataPath, "update.exe");
await using (var dstStream = File.Open($"{GlobalVars.DataPath}/update.exe", FileMode.Create)) {
await using var srcStream = typeof(Program).Assembly.GetManifestResourceStream("updater")!;
await srcStream.CopyToAsync(dstStream);
}
await File.WriteAllBytesAsync(tmpPath, newBin);
ShellOpen(updaterPath, $"{Environment.ProcessId} \"{tmpPath}\"");
await StartSpinnerAsync(App.UpdateChecking, _ => Task.Delay(1919810));
GlobalVars.PauseOnExit = false;
Environment.Exit(0);
}
AnsiConsole.MarkupLine($"[link]{App.DownloadLink}[/]", versionInfo.PackageLink);
if (versionInfo.ForceUpdate) {
Environment.Exit(0);
}
await File.WriteAllBytesAsync(tmpPath, newBin);
ShellOpen(updaterPath, $"{Environment.ProcessId} \"{tmpPath}\"");
await StartSpinnerAsync(App.UpdateChecking, _ => Task.Delay(1919810));
GlobalVars.PauseOnExit = false;
Environment.Exit(0);
}
AnsiConsole.MarkupLine($"[link]{App.DownloadLink}[/]", versionInfo.PackageLink);
if (versionInfo.ForceUpdate) {
Environment.Exit(0);
if (versionInfo.EnableLibDownload && !useLocalLib) {
var data = await GetBucketFile("schicksal/lic.dll");
await File.WriteAllBytesAsync(GlobalVars.LibFilePath, data); // 要求重启电脑
}
_updateInfo = versionInfo;
} catch (IOException e) when ((uint) e.HResult == 0x80070020) { // ERROR_SHARING_VIOLATION
// IO_SharingViolation_File
// The process cannot access the file '{0}' because it is being used by another process.
AnsiConsole.WriteLine("文件 {0} 被其它程序占用,请 重启电脑 或 解除文件占用 后重试。", e.Message[36..^46]);
Environment.Exit(-1);
}
if (versionInfo.EnableLibDownload && !useLocalLib) {
var data = await GetBucketFile("schicksal/lic.dll");
await File.WriteAllBytesAsync(GlobalVars.LibFilePath, data);
}
_updateInfo = versionInfo;
}
// ReSharper disable once UnusedMethodReturnValue.Global