8 Commits
3.4.0 ... 3.5.0

Author SHA1 Message Date
HolographicHat
e1429289ad refactor appcenter 2024-03-15 00:08:34 +08:00
HolographicHat
1f311ed987 4.5 2024-03-14 23:55:36 +08:00
HolographicHat
cc346915e3 Merge pull request #85 from BTMuli/master
️ 延长刷新间隔,Y/YES均可使用旧数据(大小写不敏感)
2024-02-06 23:27:16 +08:00
HolographicHat
cd0f49d83d shorten code 2024-02-06 23:19:41 +08:00
目棃
d0b7d15894 Merge branch 'master' into master 2024-02-06 22:54:51 +08:00
目棃
504c8a2a9a 👔 默认不使用旧数据 2024-02-06 22:46:37 +08:00
HolographicHat
b3162052da refactor 2024-02-06 21:31:14 +08:00
目棃
034d999d25 ️ 延长刷新间隔,回车/Y也能使用旧数据了 2024-02-02 19:30:03 +08:00
24 changed files with 131 additions and 229 deletions

View File

@@ -24,13 +24,11 @@
<PackageReference Include="Google.Protobuf" Version="3.22.1" /> <PackageReference Include="Google.Protobuf" Version="3.22.1" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.2.188-beta"> <PackageReference Include="Microsoft.Windows.CsWin32" Version="0.2.188-beta">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Grpc.Tools" Version="2.53.0"> <PackageReference Include="Grpc.Tools" Version="2.53.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -30,17 +30,17 @@ namespace Hook {
return new ByteArray {}; return new ByteArray {};
} }
void OnAchievementAllDataNotify(LPVOID obj, const LPVOID ntf) { uint16_t BitConverter_ToUInt16(ByteArray* val, const int startIndex) {
const auto cos = Genshin::il2cpp_object_new(*Genshin::CodedOutputStream__TypeInfo); const auto ret = CALL_ORIGIN(BitConverter_ToUInt16, val, startIndex);
const auto len = Genshin::CalculateSize(ntf); if (ret == 0xAB89 && ReadMapped<UINT16>(val->vector, 2) == 20248) {
const auto buf = (ByteArray*) new uint8_t[0x20 + len] {}; const auto headLength = ReadMapped<UINT16>(val->vector, 4);
buf->max_length = len; const auto dataLength = ReadMapped<UINT32>(val->vector, 6);
Genshin::CodedOutputStreamInit(cos, buf, 0, len); const auto cStr = base64_encode(val->vector + 10 + headLength, dataLength) + "\n";
Genshin::ProtoWriteTo(ntf, cos); WriteFile(hPipe, cStr.c_str(), (DWORD) cStr.length(), nullptr, nullptr);
const auto str = base64_encode(buf->vector, len) + "\n"; CloseHandle(hPipe);
WriteFile(hPipe, str.c_str(), (DWORD) str.length(), nullptr, nullptr); ExitProcess(0);
CloseHandle(hPipe); }
ExitProcess(0); return ret;
} }
} }
@@ -57,7 +57,7 @@ void Run(HMODULE* phModule) {
const auto result = Genshin::RecordUserData(i); const auto result = Genshin::RecordUserData(i);
checksum += string(reinterpret_cast<char*>(&result->vector[0]), result->max_length); checksum += string(reinterpret_cast<char*>(&result->vector[0]), result->max_length);
} }
HookManager::install(Genshin::OnAchievementAllDataNotify, Hook::OnAchievementAllDataNotify); HookManager::install(Genshin::BitConverter_ToUInt16, Hook::BitConverter_ToUInt16);
HookManager::install(Genshin::UnityEngine_RecordUserData, Hook::UnityEngine_RecordUserData); HookManager::install(Genshin::UnityEngine_RecordUserData, Hook::UnityEngine_RecordUserData);
hPipe = CreateFile(R"(\\.\pipe\YaeAchievementPipe)", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr); hPipe = CreateFile(R"(\\.\pipe\YaeAchievementPipe)", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
if (hPipe == INVALID_HANDLE_VALUE) { if (hPipe == INVALID_HANDLE_VALUE) {

View File

@@ -2,16 +2,10 @@ using namespace Genshin;
// DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...)); // DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...));
DO_APP_FUNC(0x504620, 0x5C3140, LPVOID, il2cpp_object_new, (LPVOID t)); DO_APP_FUNC(0x569170, 0x568470, LPVOID, il2cpp_object_new, (LPVOID t));
DO_APP_FUNC(0x05167E00, 0x05166410, ByteArray*, RecordUserData, (int32_t nType)); DO_APP_FUNC(0x06C43A80, 0x06775280, ByteArray*, RecordUserData, (int32_t nType));
DO_APP_FUNC(0x04450D40, 0x0444F3B0, void, OnAchievementAllDataNotify, (LPVOID obj, LPVOID ntf)); DO_APP_FUNC(0x0C87B240, 0x0C89EFB0, uint16_t, BitConverter_ToUInt16, (ByteArray* val, int startIndex));
DO_APP_FUNC(0x07A3EC40, 0x07A3DD10, int, CalculateSize, (LPVOID obj)); DO_UNI_FUNC(0x105560, 0x105560, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));
DO_APP_FUNC(0x07A3EB80, 0x07A3DC50, void, ProtoWriteTo, (LPVOID obj, LPVOID output));
DO_APP_FUNC(0x05BFDA50, 0x05BFCCD0, void, CodedOutputStreamInit, (LPVOID obj, LPVOID buffer, int offset, int length));
DO_UNI_FUNC(0x1051E0, 0x1051E0, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));

View File

@@ -1,2 +0,0 @@
// NOLFKCJKECE
DO_TYPEDEF(0x2A35D58, 0x2A34D58, CodedOutputStream);

View File

@@ -9,13 +9,13 @@ message Achievement {
FINISHED = 2; FINISHED = 2;
REWARD_TAKEN = 3; REWARD_TAKEN = 3;
} }
uint32 timestamp = 6; uint32 timestamp = 14;
uint32 current = 12; uint32 current = 13;
uint32 total = 3; uint32 total = 9;
uint32 id = 9; uint32 id = 7;
Status status = 11; Status status = 10;
} }
message AchievementAllDataNotify { message AchievementAllDataNotify {
repeated Achievement list = 5; repeated Achievement list = 15;
} }

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json; using System.Net;
using System.Net; using System.Net.Http.Json;
using YaeAchievement.AppCenterSDK.Models; using YaeAchievement.AppCenterSDK.Models;
using YaeAchievement.AppCenterSDK.Models.Serialization; using YaeAchievement.AppCenterSDK.Models.Serialization;
@@ -39,12 +39,6 @@ public static class AppCenter {
AppDomain.CurrentDomain.ProcessExit += (_, _) => { AppDomain.CurrentDomain.ProcessExit += (_, _) => {
running = false; running = false;
}; };
LogSerializer.AddLogType(PageLog.JsonIdentifier, typeof(PageLog));
LogSerializer.AddLogType(EventLog.JsonIdentifier, typeof(EventLog));
LogSerializer.AddLogType(HandledErrorLog.JsonIdentifier, typeof(HandledErrorLog));
LogSerializer.AddLogType(ManagedErrorLog.JsonIdentifier, typeof(ManagedErrorLog));
LogSerializer.AddLogType(StartServiceLog.JsonIdentifier, typeof(StartServiceLog));
LogSerializer.AddLogType(StartSessionLog.JsonIdentifier, typeof(StartSessionLog));
} }
// ReSharper restore InconsistentNaming // ReSharper restore InconsistentNaming
@@ -59,8 +53,8 @@ public static class AppCenter {
using var uploadContent = new StringContent(Queue.ToJson()); using var uploadContent = new StringContent(Queue.ToJson());
try { try {
using var response = httpClient.Value.PostAsync(ApiUrl, uploadContent).Result; using var response = httpClient.Value.PostAsync(ApiUrl, uploadContent).Result;
var result = response.Content.ReadAsStringAsync().Result; var result = response.Content.ReadFromJsonAsync<LogUploadResult>().GetAwaiter().GetResult();
uploadStatus = JsonConvert.DeserializeObject<LogUploadResult>(result)!.Status; uploadStatus = result!.Status;
} catch (Exception) { } catch (Exception) {
// ignored // ignored
} }

View File

@@ -1,51 +1,36 @@
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using Newtonsoft.Json;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
public class Device { public class Device {
[JsonProperty(PropertyName = "sdkName")]
public string SdkName { get; set; } = "appcenter.wpf.netcore"; public string SdkName { get; set; } = "appcenter.wpf.netcore";
[JsonProperty(PropertyName = "sdkVersion")]
public string SdkVersion { get; set; } = "4.5.0"; public string SdkVersion { get; set; } = "4.5.0";
[JsonProperty(PropertyName = "osName")]
public string OsName { get; set; } = "WINDOWS"; public string OsName { get; set; } = "WINDOWS";
[JsonProperty(PropertyName = "osVersion")]
public string OsVersion { get; set; } = DeviceHelper.GetSystemVersion(); public string OsVersion { get; set; } = DeviceHelper.GetSystemVersion();
[JsonProperty(PropertyName = "osBuild")]
public string OsBuild { get; set; } = $"{DeviceHelper.GetSystemVersion()}.{DeviceHelper.GetSystemBuild()}"; public string OsBuild { get; set; } = $"{DeviceHelper.GetSystemVersion()}.{DeviceHelper.GetSystemBuild()}";
[JsonProperty(PropertyName = "model")]
public string? Model { get; set; } = DeviceHelper.GetModel(); public string? Model { get; set; } = DeviceHelper.GetModel();
[JsonProperty(PropertyName = "oemName")]
public string? OemName { get; set; } = DeviceHelper.GetOem(); public string? OemName { get; set; } = DeviceHelper.GetOem();
[JsonProperty(PropertyName = "screenSize")]
public string ScreenSize { get; set; } = DeviceHelper.GetScreenSize(); public string ScreenSize { get; set; } = DeviceHelper.GetScreenSize();
[JsonProperty(PropertyName = "carrierCountry")] public string CarrierCountry { get; set; } = DeviceHelper.GetCountry() ?? "CN";
public string Country { get; set; } = DeviceHelper.GetCountry() ?? "CN";
[JsonProperty(PropertyName = "locale")]
public string Locale { get; set; } = CultureInfo.CurrentCulture.Name; public string Locale { get; set; } = CultureInfo.CurrentCulture.Name;
[JsonProperty(PropertyName = "timeZoneOffset")]
public int TimeZoneOffset { get; set; } = (int) TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes; public int TimeZoneOffset { get; set; } = (int) TimeZoneInfo.Local.BaseUtcOffset.TotalMinutes;
[JsonProperty(PropertyName = "appVersion")]
public string AppVersion { get; set; } = GlobalVars.AppVersionName; public string AppVersion { get; set; } = GlobalVars.AppVersionName;
[JsonProperty(PropertyName = "appBuild")]
public string AppBuild { get; set; } = GlobalVars.AppVersionCode.ToString(); public string AppBuild { get; set; } = GlobalVars.AppVersionCode.ToString();
[JsonProperty(PropertyName = "appNamespace")]
public string AppNamespace { get; set; } = Assembly.GetEntryAssembly()?.EntryPoint?.DeclaringType?.Namespace ?? string.Empty; public string AppNamespace { get; set; } = Assembly.GetEntryAssembly()?.EntryPoint?.DeclaringType?.Namespace ?? string.Empty;
} }

View File

@@ -1,20 +1,14 @@
using Newtonsoft.Json; using YaeAchievement.AppCenterSDK.Models.Serialization;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
[JsonObject(JsonIdentifier)] [LogId(JsonIdentifier)]
public class EventLog : LogWithProperties { public class EventLog(string name) : LogWithProperties {
public const string JsonIdentifier = "event"; public const string JsonIdentifier = "event";
public EventLog(string name) { public Guid Id { get; set; } = Guid.NewGuid();
Name = name;
}
[JsonProperty(PropertyName = "id")]
private Guid Id { get; set; } = Guid.NewGuid();
[JsonProperty(PropertyName = "name")]
private string Name { get; set; }
public string Name { get; set; } = name;
} }

View File

@@ -1,8 +1,8 @@
using Newtonsoft.Json; using YaeAchievement.AppCenterSDK.Models.Serialization;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
[JsonObject(JsonIdentifier)] [LogId(JsonIdentifier)]
public class HandledErrorLog : LogWithProperties { public class HandledErrorLog : LogWithProperties {
public const string JsonIdentifier = "handledError"; public const string JsonIdentifier = "handledError";
@@ -12,10 +12,8 @@ public class HandledErrorLog : LogWithProperties {
Exception = exception; Exception = exception;
} }
[JsonProperty(PropertyName = "id")]
public Guid? Id { get; set; } public Guid? Id { get; set; }
[JsonProperty(PropertyName = "exception")]
public MException Exception { get; set; } public MException Exception { get; set; }
} }

View File

@@ -1,17 +1,15 @@
using Newtonsoft.Json; using System.Text.Json.Serialization;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
public abstract class Log { public abstract class Log {
[JsonProperty(PropertyName = "sid")] [JsonPropertyName("sid")]
private Guid? Session { get; set; } = AppCenter.SessionID; public Guid? Session { get; set; } = AppCenter.SessionID;
[JsonProperty(PropertyName = "timestamp")] public DateTime Timestamp { get; set; } = DateTime.UtcNow;
private DateTime Timestamp { get; set; } = DateTime.UtcNow;
[JsonProperty(PropertyName = "device")] public Device Device { get; set; } = AppCenter.DeviceInfo;
private Device Device { get; set; } = AppCenter.DeviceInfo;
[JsonIgnore] [JsonIgnore]
internal LogStatus Status = LogStatus.Pending; internal LogStatus Status = LogStatus.Pending;

View File

@@ -1,6 +1,4 @@
using Newtonsoft.Json; namespace YaeAchievement.AppCenterSDK.Models;
namespace YaeAchievement.AppCenterSDK.Models;
public class LogContainer { public class LogContainer {
@@ -8,7 +6,6 @@ public class LogContainer {
Logs = logs; Logs = logs;
} }
[JsonProperty(PropertyName = "logs")]
public IEnumerable<Log> Logs { get; set; } public IEnumerable<Log> Logs { get; set; }
} }

View File

@@ -1,19 +1,13 @@
using Newtonsoft.Json; namespace YaeAchievement.AppCenterSDK.Models;
namespace YaeAchievement.AppCenterSDK.Models;
public class LogUploadResult { public class LogUploadResult {
[JsonProperty(PropertyName = "status")]
public string Status { get; set; } = null!; public string Status { get; set; } = null!;
[JsonProperty(PropertyName = "validDiagnosticsIds")]
public Guid[] ValidDiagnosticsIds { get; set; } = Array.Empty<Guid>(); public Guid[] ValidDiagnosticsIds { get; set; } = Array.Empty<Guid>();
[JsonProperty(PropertyName = "throttledDiagnosticsIds")]
public Guid[] ThrottledDiagnosticsIds { get; set; } = Array.Empty<Guid>(); public Guid[] ThrottledDiagnosticsIds { get; set; } = Array.Empty<Guid>();
[JsonProperty(PropertyName = "correlationId")]
public Guid CorrelationId { get; set; } public Guid CorrelationId { get; set; }
} }

View File

@@ -1,10 +1,7 @@
using Newtonsoft.Json; namespace YaeAchievement.AppCenterSDK.Models;
namespace YaeAchievement.AppCenterSDK.Models;
public class LogWithProperties : Log { public class LogWithProperties : Log {
[JsonProperty(PropertyName = "properties")]
public IDictionary<string, string> Properties { get; set; } = new Dictionary<string, string>(); public IDictionary<string, string> Properties { get; set; } = new Dictionary<string, string>();
} }

View File

@@ -1,22 +1,15 @@
using Newtonsoft.Json; namespace YaeAchievement.AppCenterSDK.Models;
namespace YaeAchievement.AppCenterSDK.Models;
public class MException { public class MException {
[JsonProperty(PropertyName = "type")]
public string Type { get; set; } = "UnknownType"; public string Type { get; set; } = "UnknownType";
[JsonProperty(PropertyName = "message")]
public string? Message { get; set; } public string? Message { get; set; }
[JsonProperty(PropertyName = "stackTrace")]
public string? StackTrace { get; set; } public string? StackTrace { get; set; }
[JsonProperty(PropertyName = "frames")]
public IList<StackFrame>? Frames { get; set; } public IList<StackFrame>? Frames { get; set; }
[JsonProperty(PropertyName = "innerExceptions")]
public IList<MException>? InnerExceptions { get; set; } public IList<MException>? InnerExceptions { get; set; }
} }

View File

@@ -1,9 +1,9 @@
using System.Diagnostics; using System.Diagnostics;
using Newtonsoft.Json; using YaeAchievement.AppCenterSDK.Models.Serialization;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
[JsonObject(JsonIdentifier)] [LogId(JsonIdentifier)]
public class ManagedErrorLog : Log { public class ManagedErrorLog : Log {
public const string JsonIdentifier = "managedError"; public const string JsonIdentifier = "managedError";
@@ -23,28 +23,20 @@ public class ManagedErrorLog : Log {
AppLaunchTimestamp = p.StartTime.ToUniversalTime(); AppLaunchTimestamp = p.StartTime.ToUniversalTime();
} }
[JsonProperty(PropertyName = "id")]
public Guid Id { get; set; } public Guid Id { get; set; }
[JsonProperty(PropertyName = "userId")]
public string? UserId { get; set; } public string? UserId { get; set; }
[JsonProperty(PropertyName = "processId")]
public int ProcessId { get; set; } public int ProcessId { get; set; }
[JsonProperty(PropertyName = "processName")]
public string ProcessName { get; set; } public string ProcessName { get; set; }
[JsonProperty(PropertyName = "fatal")]
public bool Fatal { get; set; } public bool Fatal { get; set; }
[JsonProperty(PropertyName = "appLaunchTimestamp")]
public DateTime? AppLaunchTimestamp { get; set; } public DateTime? AppLaunchTimestamp { get; set; }
[JsonProperty(PropertyName = "architecture")]
public string? Architecture { get; set; } public string? Architecture { get; set; }
[JsonProperty(PropertyName = "exception")]
public MException Exception { get; set; } public MException Exception { get; set; }
} }

View File

@@ -1,8 +1,8 @@
using Newtonsoft.Json; using YaeAchievement.AppCenterSDK.Models.Serialization;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
[JsonObject(JsonIdentifier)] [LogId(JsonIdentifier)]
public class PageLog : LogWithProperties { public class PageLog : LogWithProperties {
public const string JsonIdentifier = "page"; public const string JsonIdentifier = "page";
@@ -11,7 +11,6 @@ public class PageLog : LogWithProperties {
Name = name; Name = name;
} }
[JsonProperty(PropertyName = "name")]
public string Name { get; set; } public string Name { get; set; }
} }

View File

@@ -0,0 +1,8 @@
namespace YaeAchievement.AppCenterSDK.Models.Serialization;
[AttributeUsage(AttributeTargets.Class)]
public sealed class LogIdAttribute(string id) : Attribute {
public string Id { get; } = id;
}

View File

@@ -1,60 +1,49 @@
// Copyright (c) Microsoft Corporation. All rights reserved. using System.Reflection;
// Licensed under the MIT License. using System.Text.Json;
using System.Text.Json.Serialization;
using System.Reflection;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace YaeAchievement.AppCenterSDK.Models.Serialization; namespace YaeAchievement.AppCenterSDK.Models.Serialization;
#pragma warning disable CS8604, CS8765 public class GuidConverter : JsonConverter<Guid> {
public class LogJsonConverter : JsonConverter {
public static GuidConverter Instance { get; } = new ();
private readonly Dictionary<string, Type> _logTypes = new (); public override Guid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
private readonly object _jsonConverterLock = new (); throw new NotSupportedException();
private static readonly JsonSerializerSettings SerializationSettings; }
public override void Write(Utf8JsonWriter writer, Guid value, JsonSerializerOptions options) {
writer.WriteStringValue(value.ToString("D"));
}
}
public class LogJsonConverter : JsonConverter<Log> {
public static LogJsonConverter Instance { get; } = new ();
private static readonly JsonSerializerOptions SerializationSettings;
static LogJsonConverter() { static LogJsonConverter() {
SerializationSettings = new JsonSerializerSettings { SerializationSettings = new JsonSerializerOptions {
Formatting = Formatting.None, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
NullValueHandling = NullValueHandling.Ignore, PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DateFormatHandling = DateFormatHandling.IsoDateFormat, ReferenceHandler = ReferenceHandler.IgnoreCycles,
DateTimeZoneHandling = DateTimeZoneHandling.Utc,
ReferenceLoopHandling = ReferenceLoopHandling.Serialize
}; };
} }
public void AddLogType(string typeName, Type type) { public override bool CanConvert(Type objectType) => typeof(Log).IsAssignableFrom(objectType);
lock (_jsonConverterLock) {
_logTypes[typeName] = type; public override Log Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
} throw new NotSupportedException();
} }
public override bool CanConvert(Type objectType) { public override void Write(Utf8JsonWriter writer, Log value, JsonSerializerOptions options) {
return typeof(Log).IsAssignableFrom(objectType); var attr = value.GetType().GetCustomAttribute<LogIdAttribute>();
} if (attr == null) {
throw new JsonException("Log type is missing LogTypeAttribute");
public override object? ReadJson(JsonReader reader, Type t, object o, JsonSerializer s) {
Type logType;
var jsonObject = JObject.Load(reader);
var typeName = jsonObject.GetValue("type")?.ToString();
lock (_jsonConverterLock) {
if (typeName == null || !_logTypes.ContainsKey(typeName)) {
throw new JsonReaderException("Could not identify type of log");
}
logType = _logTypes[typeName];
jsonObject.Remove("type");
} }
return jsonObject.ToObject(logType); var cNode = JsonSerializer.SerializeToNode((object) value, SerializationSettings)!;
} cNode["type"] = attr.Id;
writer.WriteRawValue(cNode.ToString());
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
var info = value.GetType().GetTypeInfo();
if (info.GetCustomAttribute(typeof(JsonObjectAttribute)) is not JsonObjectAttribute attribute) {
throw new JsonWriterException("Log type is missing JsonObjectAttribute");
}
var jsonObject = JObject.FromObject(value, JsonSerializer.CreateDefault(SerializationSettings));
jsonObject.Add("type", JToken.FromObject(attribute.Id));
writer.WriteRawValue(jsonObject.ToString(Formatting.None));
} }
} }

View File

@@ -1,40 +1,25 @@
// Copyright (c) Microsoft Corporation. All rights reserved. using System.Text.Json;
// Licensed under the MIT License. using System.Text.Json.Serialization;
using Newtonsoft.Json;
namespace YaeAchievement.AppCenterSDK.Models.Serialization; namespace YaeAchievement.AppCenterSDK.Models.Serialization;
#pragma warning disable CS8604, CS8765, CS8603
public static class LogSerializer { public static class LogSerializer {
private static readonly JsonSerializerSettings SerializationSettings; private static readonly JsonSerializerOptions SerializationSettings;
private static readonly LogJsonConverter Converter = new ();
static LogSerializer() { static LogSerializer() {
SerializationSettings = new JsonSerializerSettings { SerializationSettings = new JsonSerializerOptions {
Formatting = Formatting.None, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
NullValueHandling = NullValueHandling.Ignore, PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DateFormatHandling = DateFormatHandling.IsoDateFormat, ReferenceHandler = ReferenceHandler.IgnoreCycles,
DateTimeZoneHandling = DateTimeZoneHandling.Utc, Converters = {
ReferenceLoopHandling = ReferenceLoopHandling.Serialize, GuidConverter.Instance,
Converters = { Converter } LogJsonConverter.Instance,
}
}; };
} }
public static void AddLogType(string typeName, Type type) {
Converter.AddLogType(typeName, type);
}
public static string Serialize(LogContainer logContainer) { public static string Serialize(LogContainer logContainer) {
return JsonConvert.SerializeObject(logContainer, SerializationSettings); return JsonSerializer.Serialize(logContainer, SerializationSettings);
}
public static string Serialize(Log log) {
return JsonConvert.SerializeObject(log, SerializationSettings);
}
public static LogContainer? DeserializeLogs(string json) {
return JsonConvert.DeserializeObject<LogContainer>(json, SerializationSettings);
} }
} }

View File

@@ -1,6 +1,4 @@
using Newtonsoft.Json; namespace YaeAchievement.AppCenterSDK.Models;
namespace YaeAchievement.AppCenterSDK.Models;
public class StackFrame { public class StackFrame {
@@ -13,22 +11,16 @@ public class StackFrame {
FileName = fileName; FileName = fileName;
} }
[JsonProperty(PropertyName = "address")]
public string Address { get; set; } public string Address { get; set; }
[JsonProperty(PropertyName = "code")]
public string Code { get; set; } public string Code { get; set; }
[JsonProperty(PropertyName = "className")]
public string ClassName { get; set; } public string ClassName { get; set; }
[JsonProperty(PropertyName = "methodName")]
public string MethodName { get; set; } public string MethodName { get; set; }
[JsonProperty(PropertyName = "lineNumber")]
public int? LineNumber { get; set; } public int? LineNumber { get; set; }
[JsonProperty(PropertyName = "fileName")]
public string FileName { get; set; } public string FileName { get; set; }
} }

View File

@@ -1,8 +1,8 @@
using Newtonsoft.Json; using YaeAchievement.AppCenterSDK.Models.Serialization;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
[JsonObject(JsonIdentifier)] [LogId(JsonIdentifier)]
public class StartServiceLog : Log { public class StartServiceLog : Log {
public const string JsonIdentifier = "startService"; public const string JsonIdentifier = "startService";
@@ -11,7 +11,6 @@ public class StartServiceLog : Log {
Services = services; Services = services;
} }
[JsonProperty(PropertyName = "services")]
public string[] Services { get; set; } public string[] Services { get; set; }
} }

View File

@@ -1,8 +1,8 @@
using Newtonsoft.Json; using YaeAchievement.AppCenterSDK.Models.Serialization;
namespace YaeAchievement.AppCenterSDK.Models; namespace YaeAchievement.AppCenterSDK.Models;
[JsonObject(JsonIdentifier)] [LogId(JsonIdentifier)]
public class StartSessionLog : Log { public class StartSessionLog : Log {
public const string JsonIdentifier = "startSession"; public const string JsonIdentifier = "startSession";
} }

View File

@@ -20,8 +20,8 @@ public static class GlobalVars {
public static readonly string CachePath = Path.Combine(DataPath, "cache"); public static readonly string CachePath = Path.Combine(DataPath, "cache");
public static readonly string LibFilePath = Path.Combine(DataPath, "YaeAchievement.dll"); public static readonly string LibFilePath = Path.Combine(DataPath, "YaeAchievement.dll");
public const uint AppVersionCode = 44; public const uint AppVersionCode = 45;
public const string AppVersionName = "3.4"; public const string AppVersionName = "3.5";
public const string PipeName = "YaeAchievementPipe"; public const string PipeName = "YaeAchievementPipe";
public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com"; public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com";

View File

@@ -29,29 +29,27 @@ new EventLog("AppInit") {
{ "SystemVersion", DeviceHelper.GetSystemVersion() } { "SystemVersion", DeviceHelper.GetSystemVersion() }
} }
}.Enqueue(); }.Enqueue();
var usePreviousData = false;
var historyCache = new CacheFile("ExportData"); var historyCache = new CacheFile("ExportData");
if (historyCache.LastWriteTime.AddMinutes(10) > DateTime.UtcNow) {
AchievementAllDataNotify? data = null;
try {
data = AchievementAllDataNotify.Parser.ParseFrom(historyCache.Read().Content);
} catch (Exception) { /* ignored */ }
if (historyCache.LastWriteTime.AddMinutes(60) > DateTime.UtcNow && data != null) {
Console.WriteLine(App.UsePreviousData); Console.WriteLine(App.UsePreviousData);
usePreviousData = Console.ReadLine() == "yes"; if (Console.ReadLine()?.ToUpper() is "Y" or "YES") {
} Export.Choose(data);
Export: return;
if(usePreviousData) {
AchievementAllDataNotify data;
try {
data = AchievementAllDataNotify.Parser.ParseFrom(historyCache.Read().Content);
} catch (Exception) {
usePreviousData = false;
goto Export;
} }
Export.Choose(data); }
} else {
StartAndWaitResult(AppConfig.GamePath, str => { StartAndWaitResult(AppConfig.GamePath, str => {
GlobalVars.UnexpectedExit = false; GlobalVars.UnexpectedExit = false;
var data = Convert.FromBase64String(str); var bytes = Convert.FromBase64String(str);
var list = AchievementAllDataNotify.Parser.ParseFrom(data); var list = AchievementAllDataNotify.Parser.ParseFrom(bytes);
historyCache.Write(data); historyCache.Write(bytes);
Export.Choose(list); Export.Choose(list);
return true; return true;
}); });
}