diff --git a/src/GlobalVars.cs b/src/GlobalVars.cs
index 1ded994..b5917aa 100644
--- a/src/GlobalVars.cs
+++ b/src/GlobalVars.cs
@@ -13,6 +13,8 @@ public static class GlobalVars {
public static string GamePath = "";
public static Version AppVersion = Assembly.GetEntryAssembly()!.GetName().Version!;
+ public const uint AppVersionCode = 77;
+ public const string AppVersionName = "2.?";
public const string LibName = "YaeLib.dll";
public const string PipeName = "YaeAchievementPipe";
public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com";
diff --git a/src/Logger.cs b/src/Logger.cs
deleted file mode 100644
index 73c87be..0000000
--- a/src/Logger.cs
+++ /dev/null
@@ -1,5 +0,0 @@
-namespace YaeAchievement;
-
-public static class Logger {
-
-}
\ No newline at end of file
diff --git a/src/Proto/UpdateInfo.cs b/src/Proto/UpdateInfo.cs
new file mode 100644
index 0000000..0166ccc
--- /dev/null
+++ b/src/Proto/UpdateInfo.cs
@@ -0,0 +1,454 @@
+//
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: UpdateInfo.proto
+//
+#pragma warning disable 1591, 0612, 3021, 8981
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+/// Holder for reflection information generated from UpdateInfo.proto
+public static partial class UpdateInfoReflection {
+
+ #region Descriptor
+ /// File descriptor for UpdateInfo.proto
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static UpdateInfoReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChBVcGRhdGVJbmZvLnByb3RvIqwBCgpVcGRhdGVJbmZvEhMKC3ZlcnNpb25D",
+ "b2RlGAEgASgNEhMKC3ZlcnNpb25OYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9u",
+ "GAMgASgJEhMKC3BhY2thZ2VMaW5rGAQgASgJEhMKC2ZvcmNlVXBkYXRlGAUg",
+ "ASgIEhkKEWVuYWJsZUxpYkRvd25sb2FkGAYgASgIEhoKEmVuYWJsZUF1dG9E",
+ "b3dubG9hZBgHIAEoCGIGcHJvdG8z"));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { },
+ new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::UpdateInfo), global::UpdateInfo.Parser, new[]{ "VersionCode", "VersionName", "Description", "PackageLink", "ForceUpdate", "EnableLibDownload", "EnableAutoDownload" }, null, null, null, null)
+ }));
+ }
+ #endregion
+
+}
+#region Messages
+public sealed partial class UpdateInfo : pb::IMessage
+#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ , pb::IBufferMessage
+#endif
+{
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new UpdateInfo());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::UpdateInfoReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public UpdateInfo() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public UpdateInfo(UpdateInfo other) : this() {
+ versionCode_ = other.versionCode_;
+ versionName_ = other.versionName_;
+ description_ = other.description_;
+ packageLink_ = other.packageLink_;
+ forceUpdate_ = other.forceUpdate_;
+ enableLibDownload_ = other.enableLibDownload_;
+ enableAutoDownload_ = other.enableAutoDownload_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public UpdateInfo Clone() {
+ return new UpdateInfo(this);
+ }
+
+ /// Field number for the "versionCode" field.
+ public const int VersionCodeFieldNumber = 1;
+ private uint versionCode_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public uint VersionCode {
+ get { return versionCode_; }
+ set {
+ versionCode_ = value;
+ }
+ }
+
+ /// Field number for the "versionName" field.
+ public const int VersionNameFieldNumber = 2;
+ private string versionName_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string VersionName {
+ get { return versionName_; }
+ set {
+ versionName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "description" field.
+ public const int DescriptionFieldNumber = 3;
+ private string description_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Description {
+ get { return description_; }
+ set {
+ description_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "packageLink" field.
+ public const int PackageLinkFieldNumber = 4;
+ private string packageLink_ = "";
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string PackageLink {
+ get { return packageLink_; }
+ set {
+ packageLink_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "forceUpdate" field.
+ public const int ForceUpdateFieldNumber = 5;
+ private bool forceUpdate_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool ForceUpdate {
+ get { return forceUpdate_; }
+ set {
+ forceUpdate_ = value;
+ }
+ }
+
+ /// Field number for the "enableLibDownload" field.
+ public const int EnableLibDownloadFieldNumber = 6;
+ private bool enableLibDownload_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool EnableLibDownload {
+ get { return enableLibDownload_; }
+ set {
+ enableLibDownload_ = value;
+ }
+ }
+
+ /// Field number for the "enableAutoDownload" field.
+ public const int EnableAutoDownloadFieldNumber = 7;
+ private bool enableAutoDownload_;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool EnableAutoDownload {
+ get { return enableAutoDownload_; }
+ set {
+ enableAutoDownload_ = value;
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override bool Equals(object other) {
+ return Equals(other as UpdateInfo);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool Equals(UpdateInfo other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (VersionCode != other.VersionCode) return false;
+ if (VersionName != other.VersionName) return false;
+ if (Description != other.Description) return false;
+ if (PackageLink != other.PackageLink) return false;
+ if (ForceUpdate != other.ForceUpdate) return false;
+ if (EnableLibDownload != other.EnableLibDownload) return false;
+ if (EnableAutoDownload != other.EnableAutoDownload) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (VersionCode != 0) hash ^= VersionCode.GetHashCode();
+ if (VersionName.Length != 0) hash ^= VersionName.GetHashCode();
+ if (Description.Length != 0) hash ^= Description.GetHashCode();
+ if (PackageLink.Length != 0) hash ^= PackageLink.GetHashCode();
+ if (ForceUpdate != false) hash ^= ForceUpdate.GetHashCode();
+ if (EnableLibDownload != false) hash ^= EnableLibDownload.GetHashCode();
+ if (EnableAutoDownload != false) hash ^= EnableAutoDownload.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void WriteTo(pb::CodedOutputStream output) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ output.WriteRawMessage(this);
+ #else
+ if (VersionCode != 0) {
+ output.WriteRawTag(8);
+ output.WriteUInt32(VersionCode);
+ }
+ if (VersionName.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(VersionName);
+ }
+ if (Description.Length != 0) {
+ output.WriteRawTag(26);
+ output.WriteString(Description);
+ }
+ if (PackageLink.Length != 0) {
+ output.WriteRawTag(34);
+ output.WriteString(PackageLink);
+ }
+ if (ForceUpdate != false) {
+ output.WriteRawTag(40);
+ output.WriteBool(ForceUpdate);
+ }
+ if (EnableLibDownload != false) {
+ output.WriteRawTag(48);
+ output.WriteBool(EnableLibDownload);
+ }
+ if (EnableAutoDownload != false) {
+ output.WriteRawTag(56);
+ output.WriteBool(EnableAutoDownload);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+ if (VersionCode != 0) {
+ output.WriteRawTag(8);
+ output.WriteUInt32(VersionCode);
+ }
+ if (VersionName.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(VersionName);
+ }
+ if (Description.Length != 0) {
+ output.WriteRawTag(26);
+ output.WriteString(Description);
+ }
+ if (PackageLink.Length != 0) {
+ output.WriteRawTag(34);
+ output.WriteString(PackageLink);
+ }
+ if (ForceUpdate != false) {
+ output.WriteRawTag(40);
+ output.WriteBool(ForceUpdate);
+ }
+ if (EnableLibDownload != false) {
+ output.WriteRawTag(48);
+ output.WriteBool(EnableLibDownload);
+ }
+ if (EnableAutoDownload != false) {
+ output.WriteRawTag(56);
+ output.WriteBool(EnableAutoDownload);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(ref output);
+ }
+ }
+ #endif
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public int CalculateSize() {
+ int size = 0;
+ if (VersionCode != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeUInt32Size(VersionCode);
+ }
+ if (VersionName.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(VersionName);
+ }
+ if (Description.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Description);
+ }
+ if (PackageLink.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(PackageLink);
+ }
+ if (ForceUpdate != false) {
+ size += 1 + 1;
+ }
+ if (EnableLibDownload != false) {
+ size += 1 + 1;
+ }
+ if (EnableAutoDownload != false) {
+ size += 1 + 1;
+ }
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(UpdateInfo other) {
+ if (other == null) {
+ return;
+ }
+ if (other.VersionCode != 0) {
+ VersionCode = other.VersionCode;
+ }
+ if (other.VersionName.Length != 0) {
+ VersionName = other.VersionName;
+ }
+ if (other.Description.Length != 0) {
+ Description = other.Description;
+ }
+ if (other.PackageLink.Length != 0) {
+ PackageLink = other.PackageLink;
+ }
+ if (other.ForceUpdate != false) {
+ ForceUpdate = other.ForceUpdate;
+ }
+ if (other.EnableLibDownload != false) {
+ EnableLibDownload = other.EnableLibDownload;
+ }
+ if (other.EnableAutoDownload != false) {
+ EnableAutoDownload = other.EnableAutoDownload;
+ }
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(pb::CodedInputStream input) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ input.ReadRawMessage(this);
+ #else
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 8: {
+ VersionCode = input.ReadUInt32();
+ break;
+ }
+ case 18: {
+ VersionName = input.ReadString();
+ break;
+ }
+ case 26: {
+ Description = input.ReadString();
+ break;
+ }
+ case 34: {
+ PackageLink = input.ReadString();
+ break;
+ }
+ case 40: {
+ ForceUpdate = input.ReadBool();
+ break;
+ }
+ case 48: {
+ EnableLibDownload = input.ReadBool();
+ break;
+ }
+ case 56: {
+ EnableAutoDownload = input.ReadBool();
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+ break;
+ case 8: {
+ VersionCode = input.ReadUInt32();
+ break;
+ }
+ case 18: {
+ VersionName = input.ReadString();
+ break;
+ }
+ case 26: {
+ Description = input.ReadString();
+ break;
+ }
+ case 34: {
+ PackageLink = input.ReadString();
+ break;
+ }
+ case 40: {
+ ForceUpdate = input.ReadBool();
+ break;
+ }
+ case 48: {
+ EnableLibDownload = input.ReadBool();
+ break;
+ }
+ case 56: {
+ EnableAutoDownload = input.ReadBool();
+ break;
+ }
+ }
+ }
+ }
+ #endif
+
+}
+
+#endregion
+
+
+#endregion Designer generated code
diff --git a/src/Utils.cs b/src/Utils.cs
index 9149091..9b189d6 100644
--- a/src/Utils.cs
+++ b/src/Utils.cs
@@ -29,42 +29,44 @@ public static class Utils {
return c;
});
- public static string GetBucketFileAsString(string path) {
- return Encoding.UTF8.GetString(GetBucketFileAsByteArray(path));
+ public static string GetBucketFileAsString(string path, bool cache = true) {
+ return Encoding.UTF8.GetString(GetBucketFileAsByteArray(path, cache));
}
- public static byte[] GetBucketFileAsByteArray(string path) {
+ public static byte[] GetBucketFileAsByteArray(string path, bool cache = true) {
using var msg = new HttpRequestMessage {
Method = HttpMethod.Get,
RequestUri = new Uri($"{GlobalVars.BucketHost}/{path}")
};
CacheItem? ci = null;
- string? etag = null;
- var cacheName = $"./cache/{CalculateMD5(path)[..16]}.miko";
- if (File.Exists(cacheName)) {
- using var input = File.OpenRead(cacheName);
- using var dInput = new GZipStream(input, CompressionMode.Decompress);
- ci = CacheItem.Parser.ParseFrom(dInput);
- etag = ci.Etag;
- }
- if (etag != null) {
- msg.Headers.TryAddWithoutValidation("If-None-Match", $"{etag}");
+ var cacheName = cache ? $"./cache/{CalculateMD5(path)[..16]}.miko" : "";
+ if (cache) {
+ Directory.CreateDirectory("cache");
+ if (File.Exists(cacheName)) {
+ using var input = File.OpenRead(cacheName);
+ using var dInput = new GZipStream(input, CompressionMode.Decompress);
+ ci = CacheItem.Parser.ParseFrom(dInput);
+ msg.Headers.TryAddWithoutValidation("If-None-Match", $"{ci.Etag}");
+
+ }
}
using var response = CHttpClient.Value.Send(msg);
- if (response.StatusCode == HttpStatusCode.NotModified) {
+ if (cache && response.StatusCode == HttpStatusCode.NotModified) {
return ci!.Content.ToByteArray();
}
response.EnsureSuccessStatusCode();
- etag = response.Headers.ETag!.Tag;
var responseBytes = response.Content.ReadAsByteArrayAsync().Result;
- using var os = File.OpenWrite(cacheName);
- using var cos = new GZipStream(os, CompressionLevel.SmallestSize);
- new CacheItem {
- Etag = etag,
- Version = 3,
- Checksum = CalculateMD5(responseBytes),
- Content = ByteString.CopyFrom(responseBytes)
- }.WriteTo(cos);
+ if (cache) {
+ var etag = response.Headers.ETag!.Tag;
+ using var os = File.OpenWrite(cacheName);
+ using var cos = new GZipStream(os, CompressionLevel.SmallestSize);
+ new CacheItem {
+ Etag = etag,
+ Version = 3,
+ Checksum = CalculateMD5(responseBytes),
+ Content = ByteString.CopyFrom(responseBytes)
+ }.WriteTo(cos);
+ }
return responseBytes;
}
@@ -81,7 +83,6 @@ public static class Utils {
}
public static void LoadConfig() {
- Directory.CreateDirectory("cache");
var conf = JsonNode.Parse(File.ReadAllText(GlobalVars.ConfigFileName))!;
var path = conf["genshinPath"];
if (path == null || CheckGamePathValid(path.GetValue())) {
@@ -93,6 +94,35 @@ public static class Utils {
}
}
+ public static void CheckUpdate() {
+ var info = UpdateInfo.Parser.ParseFrom(GetBucketFileAsByteArray("schicksal/version"))!;
+ if (GlobalVars.AppVersionCode != info.VersionCode) {
+ Console.WriteLine($"有可用更新: {GlobalVars.AppVersionName} => {info.VersionName}");
+ Console.WriteLine($"更新内容: \n{info.Description}");
+ if (info.EnableAutoDownload) {
+ Console.WriteLine("正在下载更新包...");
+ var fullPath = Path.GetFullPath("update.7z");
+ File.WriteAllBytes(fullPath, GetBucketFileAsByteArray(info.PackageLink));
+ Console.WriteLine("下载完毕! 关闭程序后, 将压缩包解压至当前目录即可完成更新.");
+ new Process {
+ StartInfo = {
+ FileName = fullPath,
+ UseShellExecute = true
+ }
+ }.Start();
+ Environment.Exit(0);
+ }
+ Console.WriteLine($"下载地址: {info.PackageLink}");
+ if (info.ForceUpdate) {
+ Console.WriteLine("在完成此次更新前, 程序可能无法正常使用.");
+ Environment.Exit(0);
+ }
+ }
+ if (info.EnableLibDownload) {
+ File.WriteAllBytes("YaeLib.dll", GetBucketFileAsByteArray("schicksal/lib.dll"));
+ }
+ }
+
private static bool CheckGamePathValid(string path) {
var dir = Path.GetDirectoryName(path)!;
return File.Exists($"{dir}/UnityPlayer.dll") && File.Exists($"{dir}/mhypbase.dll");