mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-12 01:18:15 +08:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b2b1fba49 | ||
|
|
c325b5f754 | ||
|
|
8e2e438c96 | ||
|
|
9bc2cdb443 | ||
|
|
826ed661cd | ||
|
|
5f8ff734f2 | ||
|
|
50007c2c53 | ||
|
|
7512c6fca2 | ||
|
|
2feae6ddb9 | ||
|
|
52ae44f467 | ||
|
|
d93f6f92c0 | ||
|
|
20b59eab7e | ||
|
|
0094b9b959 | ||
|
|
24b68fbed1 | ||
|
|
397923d4ad | ||
|
|
0a3482e7b2 | ||
|
|
7ae18cfbf0 | ||
|
|
24cd49fa03 | ||
|
|
f0dbb9162b | ||
|
|
68ff9c5a25 | ||
|
|
31b77a9fb3 | ||
|
|
d2d5bafcd6 | ||
|
|
e2f1f1e343 | ||
|
|
349e15fe25 | ||
|
|
9e0d18910b | ||
|
|
afee99fd3f | ||
|
|
4dae8c52b6 | ||
|
|
3294ac4b89 | ||
|
|
ccb19c832c | ||
|
|
1207dd70b3 |
8
.github/workflows/dotnet.yml
vendored
8
.github/workflows/dotnet.yml
vendored
@@ -14,17 +14,17 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v2
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
dotnet-version: 7.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build --no-restore
|
||||
- name: Publish
|
||||
run: dotnet publish -o .\publish\
|
||||
run: dotnet publish --property:OutputPath=.\publish\
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3.1.0
|
||||
with:
|
||||
name: Artifacts
|
||||
path: publish
|
||||
|
||||
@@ -13,11 +13,7 @@
|
||||
- 没有窗口大小、游戏语言等要求
|
||||
|
||||
## 使用说明
|
||||
第一次打开需要先设置原神主程序(YuanShen.exe/GenshinImpact.exe)所在路径
|
||||

|
||||
设置完毕后,等待原神启动
|
||||
当你看到门时,点击进入游戏,游戏将自动退出
|
||||
游戏退出后,在程序内输入数字以选择导出到哪个网站/应用
|
||||
→ [Tutorial.md](Tutorial.md)
|
||||
|
||||
## 下载地址
|
||||
[releases/latest](https://github.com/HolographicHat/YaeAchievement/releases/latest)
|
||||
|
||||
81
Tutorial.md
Normal file
81
Tutorial.md
Normal file
@@ -0,0 +1,81 @@
|
||||
## 使用说明
|
||||
|
||||
1.选择正确的下载文件(以2.4.1版本为例):
|
||||
|
||||
点击该网址:https://github.com/HolographicHat/YaeAchievement/releases
|
||||
|
||||
点击图中红框圈中的名称为“YaeAchievement.exe”的文件,浏览器会自动弹出下载。建议将该文件保存在桌面或者其它易于寻找的文件夹内。
|
||||
|
||||

|
||||
|
||||
2.安装启动软件所需文件(若已安装该运行时可忽略此步骤)
|
||||
|
||||
点击该网址:https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-6.0.9-windows-x64-installer 。
|
||||
|
||||
进入网页后浏览器会自动弹出下载,同样地,将文件保存在桌面或者其它易于寻找的文件夹内。
|
||||
|
||||
下载完成后打开名称形如dotnet-runtime-x.x.x-win-x64.exe的文件,会弹出安装窗口,如下图所示。
|
||||
|
||||

|
||||
|
||||
直接点击安装即可。
|
||||
|
||||
3.打开主程序所需的操作以及成就导出的选择
|
||||
|
||||
双击在第一步下载的名称为“YaeAchievement.exe”的文件,成功打开后会提示原神正在启动,如下图所示。
|
||||
|
||||

|
||||
|
||||
原神启动完成后,点击进入游戏即可。
|
||||
|
||||
点击进入游戏后原神闪退,工具会提示您选择导出至何种工具,如下图所示。
|
||||
|
||||

|
||||
|
||||
此时可根据自己的需要进行选择,一般推荐导出至[0]椰羊以及[4]表格文件(.csv)。
|
||||
|
||||
选择完毕后各工具导出页面如下:
|
||||
|
||||
#### 椰羊:
|
||||
|
||||

|
||||
|
||||
#### Snap.Hutao:
|
||||
|
||||

|
||||
|
||||
#### Seelie.me:
|
||||
|
||||
此时YaeAchievement会提示成就数据已导出。请在保存YaeAchievement的文件夹内找到名称形如export-20xxxxxxxxxxxx-seelie.json的文件。
|
||||
|
||||

|
||||
|
||||
然后点击该网址https://seelie.me/settings, 进入网页后选择导入,如下图所示。
|
||||
|
||||

|
||||
|
||||
点击导入后选中名称形如export-20xxxxxxxxxxxx-seelie.json的文件,如下图所示。
|
||||
|
||||

|
||||
|
||||
当弹出如下图所示的提示时表示导入成功。
|
||||
|
||||

|
||||
|
||||
此时可选择左栏成就,查看导入的成就数据。
|
||||
|
||||
#### 寻空:
|
||||
|
||||

|
||||
|
||||
### 各种工具的介绍烦请移步至各工具的官方页面进行查看(下方序号对应导出序号)
|
||||
|
||||
0. [椰羊](https://cocogoat.work/achievement)
|
||||
|
||||
1. [Snap·HuTao](https://github.com/DGP-Studio/Snap.HuTao)
|
||||
|
||||
2. [Paimon.moe](https://paimon.moe/achievement/)
|
||||
|
||||
3. [Seelie.me](https://seelie.me/achievements)
|
||||
|
||||
4. [寻空](https://github.com/xunkong/xunkong)
|
||||
@@ -1,8 +1,8 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>preview</LangVersion>
|
||||
@@ -21,8 +21,12 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.21.6" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Google.Protobuf" Version="3.22.0" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.2.188-beta">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -31,6 +35,10 @@
|
||||
<LastGenOutput>App.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Remove="res\Updater.exe" />
|
||||
<None Remove="src\NativeMethods.json" />
|
||||
<None Remove="src\NativeMethods.txt" />
|
||||
<AdditionalFiles Include="src\NativeMethods.json" />
|
||||
<AdditionalFiles Include="src\NativeMethods.txt" />
|
||||
<EmbeddedResource Include="res\Updater.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</EmbeddedResource>
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
<AdditionalDependencies>detours-x64.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PostBuildEvent>
|
||||
<Command>copy $(TargetPath) $(ProjectDir)..\bin\Debug\net6.0\win-x64\YaeAchievementLib.dll /y</Command>
|
||||
<Command>copy $(TargetPath) $(ProjectDir)..\bin\Debug\net7.0-windows\win-x64\YaeAchievementLib.dll /y</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -8,7 +8,8 @@ using std::to_string;
|
||||
HWND unityWnd = 0;
|
||||
HANDLE hPipe = 0;
|
||||
|
||||
std::set<UINT16> PacketWhitelist = { 172, 198, 112, 2676, 7, 21, 135 }; // ping, token, loginreq
|
||||
// Allow Protocol: GetPlayerToken, PlayerLogin, AchievementAllDataNotify, Ping
|
||||
std::set<UINT16> PacketWhitelist = { 167, 175, 154, 164, 2698, 14, 34, 106 };
|
||||
|
||||
bool OnPacket(KcpPacket* pkt) {
|
||||
if (pkt->data == nullptr) return true;
|
||||
@@ -29,19 +30,22 @@ bool OnPacket(KcpPacket* pkt) {
|
||||
return false;
|
||||
}
|
||||
printf("Passed cmdid: %d\n", ReadMapped<UINT16>(data->vector, 2));
|
||||
if (ReadMapped<UINT16>(data->vector, 2) == 2676) {
|
||||
if (ReadMapped<UINT16>(data->vector, 2) == 2698) {
|
||||
auto headLength = ReadMapped<UINT16>(data->vector, 4);
|
||||
auto dataLength = ReadMapped<UINT32>(data->vector, 6);
|
||||
auto iStr = Genshin::ToBase64String(data, 10 + headLength, dataLength, nullptr);
|
||||
auto cStr = IlStringToString(iStr) + "\n";
|
||||
auto cStr = ToString(iStr) + "\n";
|
||||
WriteFile(hPipe, cStr.c_str(), cStr.length(), nullptr, nullptr);
|
||||
CloseHandle(hPipe);
|
||||
ExitProcess(0);
|
||||
auto manager = Genshin::GetSingletonInstance(Genshin::GetSingletonManager(), il2cpp_string_new("GameManager"));
|
||||
Genshin::ForceQuit(manager);
|
||||
}
|
||||
delete[] data;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string checksum;
|
||||
|
||||
namespace Hook {
|
||||
|
||||
int KcpSend(void* client, KcpPacket* pkt, void* method) {
|
||||
@@ -49,7 +53,7 @@ namespace Hook {
|
||||
}
|
||||
|
||||
void SetVersion(void* obj, Il2CppString* value, void* method) {
|
||||
auto version = IlStringToString(value);
|
||||
auto version = ToString(value);
|
||||
value = string_new(version + " YaeAchievement");
|
||||
CALL_ORIGIN(SetVersion, obj, value, method);
|
||||
}
|
||||
@@ -62,15 +66,18 @@ namespace Hook {
|
||||
return OnPacket(evt->fields.packet) ? result : false;
|
||||
}
|
||||
|
||||
std::map<INT, UINT> signatures;
|
||||
|
||||
ByteArray* UnityEngine_RecordUserData(INT type) {
|
||||
if (signatures.count(type)) {
|
||||
return GCHandle_GetObject<ByteArray>(signatures[type]);
|
||||
}
|
||||
auto result = CALL_ORIGIN(UnityEngine_RecordUserData, type);
|
||||
signatures[type] = GCHandle_New(result, true);
|
||||
return result;
|
||||
return Genshin::GetBytes(Genshin::GetDefaultEncoding(), il2cpp_string_new(""));
|
||||
}
|
||||
|
||||
VOID SetChecksum(LPVOID obj, Il2CppString* value) {
|
||||
CALL_ORIGIN(SetChecksum, obj, il2cpp_string_new(checksum.c_str()));
|
||||
}
|
||||
|
||||
VOID RequestLogin(LPVOID obj, LPVOID token, UINT32 uid) {
|
||||
HookManager::install(Genshin::SetChecksum, SetChecksum);
|
||||
CALL_ORIGIN(RequestLogin, obj, token, uid);
|
||||
HookManager::detach(SetChecksum);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,14 +91,17 @@ void Run(HMODULE* phModule) {
|
||||
Sleep(1000);
|
||||
}
|
||||
Sleep(5000);
|
||||
DisableVMProtect();
|
||||
InitIL2CPP();
|
||||
HookManager::install(Genshin::UnityEngine_RecordUserData, Hook::UnityEngine_RecordUserData);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
Genshin::RecordUserData(i, nullptr);
|
||||
auto enc = Genshin::GetDefaultEncoding();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
checksum += ToString(Genshin::GetString(enc, Genshin::RecordUserData(i)));
|
||||
}
|
||||
HookManager::install(Genshin::KcpSend, Hook::KcpSend);
|
||||
HookManager::install(Genshin::KcpRecv, Hook::KcpRecv);
|
||||
HookManager::install(Genshin::SetVersion, Hook::SetVersion);
|
||||
HookManager::install(Genshin::RequestLogin, Hook::RequestLogin);
|
||||
HookManager::install(Genshin::UnityEngine_RecordUserData, Hook::UnityEngine_RecordUserData);
|
||||
hPipe = CreateFile(R"(\\.\pipe\YaeAchievementPipe)", GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
|
||||
if (hPipe == INVALID_HANDLE_VALUE) {
|
||||
Win32ErrorDialog(1001);
|
||||
|
||||
@@ -1,310 +1 @@
|
||||
#ifndef DO_API_NO_RETURN
|
||||
#define DO_API_NO_RETURN(r, n, p) DO_API(r,n,p)
|
||||
#endif
|
||||
|
||||
#pragma region General
|
||||
DO_API(int, il2cpp_init, (const char* domain_name));
|
||||
DO_API(int, il2cpp_init_utf16, (const Il2CppChar* domain_name));
|
||||
DO_API(void, il2cpp_shutdown, ());
|
||||
DO_API(void, il2cpp_set_config_dir, (const char* config_path));
|
||||
DO_API(void, il2cpp_set_data_dir, (const char* data_path));
|
||||
DO_API(void, il2cpp_set_temp_dir, (const char* temp_path));
|
||||
DO_API(void, il2cpp_set_commandline_arguments, (int argc, const char* const argv[], const char* basedir));
|
||||
DO_API(void, il2cpp_set_commandline_arguments_utf16, (int argc, const Il2CppChar* const argv[], const char* basedir));
|
||||
DO_API(void, il2cpp_set_config_utf16, (const Il2CppChar* executablePath));
|
||||
DO_API(void, il2cpp_set_config, (const char* executablePath));
|
||||
DO_API(void, il2cpp_set_memory_callbacks, (Il2CppMemoryCallbacks* callbacks));
|
||||
DO_API(const Il2CppImage*, il2cpp_get_corlib, ());
|
||||
DO_API(void, il2cpp_add_internal_call, (const char* name, Il2CppMethodPointer method));
|
||||
DO_API(Il2CppMethodPointer, il2cpp_resolve_icall, (const char* name));
|
||||
DO_API(void*, il2cpp_alloc, (size_t size));
|
||||
DO_API(void, il2cpp_free, (void* ptr));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Array
|
||||
DO_API(Il2CppClass*, il2cpp_array_class_get, (Il2CppClass* element_class, uint32_t rank));
|
||||
DO_API(uint32_t, il2cpp_array_length, (Il2CppArray* array));
|
||||
DO_API(uint32_t, il2cpp_array_get_byte_length, (Il2CppArray* array));
|
||||
DO_API(Il2CppArray*, il2cpp_array_new, (Il2CppClass* elementTypeInfo, il2cpp_array_size_t length));
|
||||
DO_API(Il2CppArray*, il2cpp_array_new_specific, (Il2CppClass* arrayTypeInfo, il2cpp_array_size_t length));
|
||||
DO_API(Il2CppArray*, il2cpp_array_new_full, (Il2CppClass* array_class, il2cpp_array_size_t* lengths, il2cpp_array_size_t* lower_bounds));
|
||||
DO_API(Il2CppClass*, il2cpp_bounded_array_class_get, (Il2CppClass* element_class, uint32_t rank, bool bounded));
|
||||
DO_API(int, il2cpp_array_element_size, (const Il2CppClass* array_class));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Assembly
|
||||
DO_API(const Il2CppImage*, il2cpp_assembly_get_image, (const Il2CppAssembly* assembly));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Class
|
||||
DO_API(void, il2cpp_class_for_each, (void(*klassReportFunc)(Il2CppClass* klass, void* userData), void* userData));
|
||||
DO_API(const Il2CppType*, il2cpp_class_enum_basetype, (Il2CppClass* klass));
|
||||
DO_API(bool, il2cpp_class_is_generic, (const Il2CppClass* klass));
|
||||
DO_API(bool, il2cpp_class_is_inflated, (const Il2CppClass* klass));
|
||||
DO_API(bool, il2cpp_class_is_assignable_from, (Il2CppClass* klass, Il2CppClass* oklass));
|
||||
DO_API(bool, il2cpp_class_is_subclass_of, (Il2CppClass* klass, Il2CppClass* klassc, bool check_interfaces));
|
||||
DO_API(bool, il2cpp_class_has_parent, (Il2CppClass* klass, Il2CppClass* klassc));
|
||||
DO_API(Il2CppClass*, il2cpp_class_from_il2cpp_type, (const Il2CppType* type));
|
||||
DO_API(Il2CppClass*, il2cpp_class_from_name, (const Il2CppImage* image, const char* namespaze, const char* name));
|
||||
DO_API(Il2CppClass*, il2cpp_class_from_system_type, (Il2CppReflectionType* type));
|
||||
DO_API(Il2CppClass*, il2cpp_class_get_element_class, (Il2CppClass* klass));
|
||||
DO_API(const EventInfo*, il2cpp_class_get_events, (Il2CppClass* klass, void** iter));
|
||||
DO_API(FieldInfo*, il2cpp_class_get_fields, (Il2CppClass* klass, void** iter));
|
||||
DO_API(Il2CppClass*, il2cpp_class_get_nested_types, (Il2CppClass* klass, void** iter));
|
||||
DO_API(Il2CppClass*, il2cpp_class_get_interfaces, (Il2CppClass* klass, void** iter));
|
||||
DO_API(const PropertyInfo*, il2cpp_class_get_properties, (Il2CppClass* klass, void** iter));
|
||||
DO_API(const PropertyInfo*, il2cpp_class_get_property_from_name, (Il2CppClass* klass, const char* name));
|
||||
DO_API(FieldInfo*, il2cpp_class_get_field_from_name, (Il2CppClass* klass, const char* name));
|
||||
DO_API(const MethodInfo*, il2cpp_class_get_methods, (Il2CppClass* klass, void** iter));
|
||||
DO_API(const MethodInfo*, il2cpp_class_get_method_from_name, (Il2CppClass* klass, const char* name, int argsCount));
|
||||
DO_API(const char*, il2cpp_class_get_name, (Il2CppClass* klass));
|
||||
DO_API(void, il2cpp_type_get_name_chunked, (const Il2CppType* type, void(*chunkReportFunc)(void* data, void* userData), void* userData));
|
||||
DO_API(const char*, il2cpp_class_get_namespace, (Il2CppClass* klass));
|
||||
DO_API(Il2CppClass*, il2cpp_class_get_parent, (Il2CppClass* klass));
|
||||
DO_API(Il2CppClass*, il2cpp_class_get_declaring_type, (Il2CppClass* klass));
|
||||
DO_API(int32_t, il2cpp_class_instance_size, (Il2CppClass* klass));
|
||||
DO_API(size_t, il2cpp_class_num_fields, (const Il2CppClass* enumKlass));
|
||||
DO_API(bool, il2cpp_class_is_valuetype, (const Il2CppClass* klass));
|
||||
DO_API(int32_t, il2cpp_class_value_size, (Il2CppClass* klass, uint32_t* align));
|
||||
DO_API(bool, il2cpp_class_is_blittable, (const Il2CppClass* klass));
|
||||
DO_API(int, il2cpp_class_get_flags, (const Il2CppClass* klass));
|
||||
DO_API(bool, il2cpp_class_is_abstract, (const Il2CppClass* klass));
|
||||
DO_API(bool, il2cpp_class_is_interface, (const Il2CppClass* klass));
|
||||
DO_API(int, il2cpp_class_array_element_size, (const Il2CppClass* klass));
|
||||
DO_API(Il2CppClass*, il2cpp_class_from_type, (const Il2CppType* type));
|
||||
DO_API(const Il2CppType*, il2cpp_class_get_type, (Il2CppClass* klass));
|
||||
DO_API(uint32_t, il2cpp_class_get_type_token, (Il2CppClass* klass));
|
||||
DO_API(bool, il2cpp_class_has_attribute, (Il2CppClass* klass, Il2CppClass* attr_class));
|
||||
DO_API(bool, il2cpp_class_has_references, (Il2CppClass* klass));
|
||||
DO_API(bool, il2cpp_class_is_enum, (const Il2CppClass* klass));
|
||||
DO_API(const Il2CppImage*, il2cpp_class_get_image, (Il2CppClass* klass));
|
||||
DO_API(const char*, il2cpp_class_get_assemblyname, (const Il2CppClass* klass));
|
||||
DO_API(int, il2cpp_class_get_rank, (const Il2CppClass* klass));
|
||||
DO_API(uint32_t, il2cpp_class_get_data_size, (const Il2CppClass* klass));
|
||||
DO_API(void*, il2cpp_class_get_static_field_data, (const Il2CppClass* klass));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Stats
|
||||
DO_API(bool, il2cpp_stats_dump_to_file, (const char* path));
|
||||
DO_API(uint64_t, il2cpp_stats_get_value, (Il2CppStat stat));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Domain
|
||||
DO_API(Il2CppDomain*, il2cpp_domain_get, ());
|
||||
DO_API(const Il2CppAssembly*, il2cpp_domain_assembly_open, (Il2CppDomain* domain, const char* name));
|
||||
DO_API(const Il2CppAssembly**, il2cpp_domain_get_assemblies, (const Il2CppDomain* domain, size_t* size));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Exception
|
||||
DO_API_NO_RETURN(void, il2cpp_raise_exception, (Il2CppException*));
|
||||
DO_API(Il2CppException*, il2cpp_exception_from_name_msg, (const Il2CppImage* image, const char* name_space, const char* name, const char* msg));
|
||||
DO_API(Il2CppException*, il2cpp_get_exception_argument_null, (const char* arg));
|
||||
DO_API(void, il2cpp_format_exception, (const Il2CppException* ex, char* message, int message_size));
|
||||
DO_API(void, il2cpp_format_stack_trace, (const Il2CppException* ex, char* output, int output_size));
|
||||
DO_API(void, il2cpp_unhandled_exception, (Il2CppException*));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Field
|
||||
DO_API(int, il2cpp_field_get_flags, (FieldInfo* field));
|
||||
DO_API(const char*, il2cpp_field_get_name, (FieldInfo* field));
|
||||
DO_API(Il2CppClass*, il2cpp_field_get_parent, (FieldInfo* field));
|
||||
DO_API(size_t, il2cpp_field_get_offset, (FieldInfo* field));
|
||||
DO_API(const Il2CppType*, il2cpp_field_get_type, (FieldInfo* field));
|
||||
DO_API(void, il2cpp_field_get_value, (Il2CppObject* obj, FieldInfo* field, void* value));
|
||||
DO_API(Il2CppObject*, il2cpp_field_get_value_object, (FieldInfo* field, Il2CppObject* obj));
|
||||
DO_API(bool, il2cpp_field_has_attribute, (FieldInfo* field, Il2CppClass* attr_class));
|
||||
DO_API(void, il2cpp_field_set_value, (Il2CppObject* obj, FieldInfo* field, void* value));
|
||||
DO_API(void, il2cpp_field_static_get_value, (FieldInfo* field, void* value));
|
||||
DO_API(void, il2cpp_field_static_set_value, (FieldInfo* field, void* value));
|
||||
DO_API(void, il2cpp_field_set_value_object, (Il2CppObject* instance, FieldInfo* field, Il2CppObject* value));
|
||||
DO_API(bool, il2cpp_field_is_literal, (FieldInfo* field));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region GC
|
||||
DO_API(void, il2cpp_gc_collect, (int maxGenerations));
|
||||
DO_API(int32_t, il2cpp_gc_collect_a_little, ());
|
||||
DO_API(void, il2cpp_gc_disable, ());
|
||||
DO_API(void, il2cpp_gc_enable, ());
|
||||
DO_API(bool, il2cpp_gc_is_disabled, ());
|
||||
DO_API(int64_t, il2cpp_gc_get_max_time_slice_ns, ());
|
||||
DO_API(void, il2cpp_gc_set_max_time_slice_ns, (int64_t maxTimeSlice));
|
||||
DO_API(bool, il2cpp_gc_is_incremental, ());
|
||||
DO_API(int64_t, il2cpp_gc_get_used_size, ());
|
||||
DO_API(int64_t, il2cpp_gc_get_heap_size, ());
|
||||
DO_API(void, il2cpp_gc_wbarrier_set_field, (Il2CppObject* obj, void** targetAddress, void* object));
|
||||
DO_API(bool, il2cpp_gc_has_strict_wbarriers, ());
|
||||
DO_API(void, il2cpp_gc_set_external_allocation_tracker, (void(*func)(void*, size_t, int)));
|
||||
DO_API(void, il2cpp_gc_set_external_wbarrier_tracker, (void(*func)(void**)));
|
||||
DO_API(void, il2cpp_gc_foreach_heap, (void(*func)(void* data, void* userData), void* userData));
|
||||
DO_API(void, il2cpp_stop_gc_world, ());
|
||||
DO_API(void, il2cpp_start_gc_world, ());
|
||||
#pragma endregion
|
||||
|
||||
#pragma region GCHandle
|
||||
DO_API(uint32_t, il2cpp_gchandle_new, (Il2CppObject* obj, bool pinned));
|
||||
DO_API(uint32_t, il2cpp_gchandle_new_weakref, (Il2CppObject* obj, bool track_resurrection));
|
||||
DO_API(Il2CppObject*, il2cpp_gchandle_get_target, (uint32_t gchandle));
|
||||
DO_API(void, il2cpp_gchandle_free, (uint32_t gchandle));
|
||||
DO_API(void, il2cpp_gchandle_foreach_get_target, (void(*func)(void* data, void* userData), void* userData));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region VMRuntimeInfo
|
||||
DO_API(uint32_t, il2cpp_object_header_size, ());
|
||||
DO_API(uint32_t, il2cpp_array_object_header_size, ());
|
||||
DO_API(uint32_t, il2cpp_offset_of_array_length_in_array_object_header, ());
|
||||
DO_API(uint32_t, il2cpp_offset_of_array_bounds_in_array_object_header, ());
|
||||
DO_API(uint32_t, il2cpp_allocation_granularity, ());
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Liveness
|
||||
DO_API(void*, il2cpp_unity_liveness_calculation_begin, (Il2CppClass* filter, int max_object_count, il2cpp_register_object_callback callback, void* userdata, il2cpp_WorldChangedCallback onWorldStarted, il2cpp_WorldChangedCallback onWorldStopped));
|
||||
DO_API(void, il2cpp_unity_liveness_calculation_end, (void* state));
|
||||
DO_API(void, il2cpp_unity_liveness_calculation_from_root, (Il2CppObject* root, void* state));
|
||||
DO_API(void, il2cpp_unity_liveness_calculation_from_statics, (void* state));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Method
|
||||
DO_API(const Il2CppType*, il2cpp_method_get_return_type, (const MethodInfo* method));
|
||||
DO_API(Il2CppClass*, il2cpp_method_get_declaring_type, (const MethodInfo* method));
|
||||
DO_API(const char*, il2cpp_method_get_name, (const MethodInfo* method));
|
||||
DO_API(const MethodInfo*, il2cpp_method_get_from_reflection, (const Il2CppReflectionMethod* method));
|
||||
DO_API(Il2CppReflectionMethod*, il2cpp_method_get_object, (const MethodInfo* method, Il2CppClass* refclass));
|
||||
DO_API(bool, il2cpp_method_is_generic, (const MethodInfo* method));
|
||||
DO_API(bool, il2cpp_method_is_inflated, (const MethodInfo* method));
|
||||
DO_API(bool, il2cpp_method_is_instance, (const MethodInfo* method));
|
||||
DO_API(uint32_t, il2cpp_method_get_param_count, (const MethodInfo* method));
|
||||
DO_API(const Il2CppType*, il2cpp_method_get_param, (const MethodInfo* method, uint32_t index));
|
||||
DO_API(Il2CppClass*, il2cpp_method_get_class, (const MethodInfo* method));
|
||||
DO_API(bool, il2cpp_method_has_attribute, (const MethodInfo* method, Il2CppClass* attr_class));
|
||||
DO_API(uint32_t, il2cpp_method_get_flags, (const MethodInfo* method, uint32_t* iflags));
|
||||
DO_API(uint32_t, il2cpp_method_get_token, (const MethodInfo* method));
|
||||
DO_API(const char*, il2cpp_method_get_param_name, (const MethodInfo* method, uint32_t index));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Property
|
||||
DO_API(uint32_t, il2cpp_property_get_flags, (PropertyInfo* prop));
|
||||
DO_API(const MethodInfo*, il2cpp_property_get_get_method, (PropertyInfo* prop));
|
||||
DO_API(const MethodInfo*, il2cpp_property_get_set_method, (PropertyInfo* prop));
|
||||
DO_API(const char*, il2cpp_property_get_name, (PropertyInfo* prop));
|
||||
DO_API(Il2CppClass*, il2cpp_property_get_parent, (PropertyInfo* prop));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Object
|
||||
DO_API(Il2CppClass*, il2cpp_object_get_class, (Il2CppObject* obj));
|
||||
DO_API(uint32_t, il2cpp_object_get_size, (Il2CppObject* obj));
|
||||
DO_API(const MethodInfo*, il2cpp_object_get_virtual_method, (Il2CppObject* obj, const MethodInfo* method));
|
||||
DO_API(Il2CppObject*, il2cpp_object_new, (const Il2CppClass* klass));
|
||||
DO_API(void*, il2cpp_object_unbox, (Il2CppObject* obj));
|
||||
DO_API(Il2CppObject*, il2cpp_value_box, (Il2CppClass* klass, void* data));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Monitor
|
||||
DO_API(void, il2cpp_monitor_enter, (Il2CppObject* obj));
|
||||
DO_API(bool, il2cpp_monitor_try_enter, (Il2CppObject* obj, uint32_t timeout));
|
||||
DO_API(void, il2cpp_monitor_exit, (Il2CppObject* obj));
|
||||
DO_API(void, il2cpp_monitor_pulse, (Il2CppObject* obj));
|
||||
DO_API(void, il2cpp_monitor_pulse_all, (Il2CppObject* obj));
|
||||
DO_API(void, il2cpp_monitor_wait, (Il2CppObject* obj));
|
||||
DO_API(bool, il2cpp_monitor_try_wait, (Il2CppObject* obj, uint32_t timeout));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Runtime
|
||||
DO_API(Il2CppObject*, il2cpp_runtime_invoke, (const MethodInfo* method, void* obj, void** params, Il2CppException** exc));
|
||||
DO_API(Il2CppObject*, il2cpp_runtime_invoke_convert_args, (const MethodInfo* method, void* obj, Il2CppObject** params, int paramCount, Il2CppException** exc));
|
||||
DO_API(void, il2cpp_runtime_class_init, (Il2CppClass* klass));
|
||||
DO_API(void, il2cpp_runtime_object_init, (Il2CppObject* obj));
|
||||
DO_API(void, il2cpp_runtime_object_init_exception, (Il2CppObject* obj, Il2CppException** exc));
|
||||
DO_API(void, il2cpp_runtime_unhandled_exception_policy_set, (Il2CppRuntimeUnhandledExceptionPolicy value));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region String
|
||||
DO_API(int32_t, il2cpp_string_length, (Il2CppString* str));
|
||||
DO_API(Il2CppChar*, il2cpp_string_chars, (Il2CppString* str));
|
||||
DO_API(Il2CppString*, il2cpp_string_new, (const char* str));
|
||||
DO_API(Il2CppString*, il2cpp_string_new_len, (const char* str, uint32_t length));
|
||||
DO_API(Il2CppString*, il2cpp_string_new_utf16, (const Il2CppChar* text, int32_t len));
|
||||
DO_API(Il2CppString*, il2cpp_string_new_wrapper, (const char* str));
|
||||
DO_API(Il2CppString*, il2cpp_string_intern, (Il2CppString* str));
|
||||
DO_API(Il2CppString*, il2cpp_string_is_interned, (Il2CppString* str));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Thread
|
||||
DO_API(Il2CppThread*, il2cpp_thread_current, ());
|
||||
DO_API(Il2CppThread*, il2cpp_thread_attach, (Il2CppDomain* domain));
|
||||
DO_API(void, il2cpp_thread_detach, (Il2CppThread* thread));
|
||||
DO_API(Il2CppThread**, il2cpp_thread_get_all_attached_threads, (size_t* size));
|
||||
DO_API(bool, il2cpp_is_vm_thread, (Il2CppThread* thread));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region StackTrace
|
||||
DO_API(void, il2cpp_current_thread_walk_frame_stack, (Il2CppFrameWalkFunc func, void* user_data));
|
||||
DO_API(void, il2cpp_thread_walk_frame_stack, (Il2CppThread* thread, Il2CppFrameWalkFunc func, void* user_data));
|
||||
DO_API(bool, il2cpp_current_thread_get_top_frame, (Il2CppStackFrameInfo* frame));
|
||||
DO_API(bool, il2cpp_thread_get_top_frame, (Il2CppThread* thread, Il2CppStackFrameInfo* frame));
|
||||
DO_API(bool, il2cpp_current_thread_get_frame_at, (int32_t offset, Il2CppStackFrameInfo* frame));
|
||||
DO_API(bool, il2cpp_thread_get_frame_at, (Il2CppThread* thread, int32_t offset, Il2CppStackFrameInfo* frame));
|
||||
DO_API(int32_t, il2cpp_current_thread_get_stack_depth, ());
|
||||
DO_API(int32_t, il2cpp_thread_get_stack_depth, (Il2CppThread* thread));
|
||||
DO_API(void, il2cpp_override_stack_backtrace, (Il2CppBacktraceFunc stackBacktraceFunc));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Type
|
||||
DO_API(Il2CppObject*, il2cpp_type_get_object, (const Il2CppType* type));
|
||||
DO_API(int, il2cpp_type_get_type, (const Il2CppType* type));
|
||||
DO_API(Il2CppClass*, il2cpp_type_get_class_or_element_class, (const Il2CppType* type));
|
||||
DO_API(char*, il2cpp_type_get_name, (const Il2CppType* type));
|
||||
DO_API(bool, il2cpp_type_is_byref, (const Il2CppType* type));
|
||||
DO_API(uint32_t, il2cpp_type_get_attrs, (const Il2CppType* type));
|
||||
DO_API(bool, il2cpp_type_equals, (const Il2CppType* type, const Il2CppType* otherType));
|
||||
DO_API(char*, il2cpp_type_get_assembly_qualified_name, (const Il2CppType* type));
|
||||
DO_API(bool, il2cpp_type_is_static, (const Il2CppType* type));
|
||||
DO_API(bool, il2cpp_type_is_pointer_type, (const Il2CppType* type));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Image
|
||||
DO_API(const Il2CppAssembly*, il2cpp_image_get_assembly, (const Il2CppImage* image));
|
||||
DO_API(const char*, il2cpp_image_get_name, (const Il2CppImage* image));
|
||||
DO_API(const char*, il2cpp_image_get_filename, (const Il2CppImage* image));
|
||||
DO_API(const MethodInfo*, il2cpp_image_get_entry_point, (const Il2CppImage* image));
|
||||
DO_API(size_t, il2cpp_image_get_class_count, (const Il2CppImage* image));
|
||||
DO_API(const Il2CppClass*, il2cpp_image_get_class, (const Il2CppImage* image, size_t index));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region MemoryInformation
|
||||
DO_API(Il2CppManagedMemorySnapshot*, il2cpp_capture_memory_snapshot, ());
|
||||
DO_API(void, il2cpp_free_captured_memory_snapshot, (Il2CppManagedMemorySnapshot* snapshot));
|
||||
DO_API(void, il2cpp_set_find_plugin_callback, (Il2CppSetFindPlugInCallback method));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Logging
|
||||
DO_API(void, il2cpp_register_log_callback, (Il2CppLogCallback method));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Debugger
|
||||
DO_API(void, il2cpp_debugger_set_agent_options, (const char* options));
|
||||
DO_API(bool, il2cpp_is_debugger_attached, ());
|
||||
DO_API(void, il2cpp_register_debugger_agent_transport, (Il2CppDebuggerTransport* debuggerTransport));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region DebugMetadata
|
||||
DO_API(bool, il2cpp_debug_get_method_info, (const MethodInfo*, Il2CppMethodDebugInfo* methodDebugInfo));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region TLSModule
|
||||
DO_API(void, il2cpp_unity_install_unitytls_interface, (const void* unitytlsInterfaceStruct));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region CustomAttributes
|
||||
DO_API(Il2CppCustomAttrInfo*, il2cpp_custom_attrs_from_class, (Il2CppClass* klass));
|
||||
DO_API(Il2CppCustomAttrInfo*, il2cpp_custom_attrs_from_method, (const MethodInfo* method));
|
||||
DO_API(Il2CppObject*, il2cpp_custom_attrs_get_attr, (Il2CppCustomAttrInfo* ainfo, Il2CppClass* attr_klass));
|
||||
DO_API(bool, il2cpp_custom_attrs_has_attr, (Il2CppCustomAttrInfo* ainfo, Il2CppClass* attr_klass));
|
||||
DO_API(Il2CppArray*, il2cpp_custom_attrs_construct, (Il2CppCustomAttrInfo* cinfo));
|
||||
DO_API(void, il2cpp_custom_attrs_free, (Il2CppCustomAttrInfo* ainfo));
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Il2CppClassUserDataForGetComponentOptimization
|
||||
DO_API(int, il2cpp_class_get_userdata_offset, ());
|
||||
DO_API(void, il2cpp_class_set_userdata, (Il2CppClass* klass, void* userdata));
|
||||
DO_API(void, il2cpp_set_default_thread_affinity, (int64_t affinity_mask));
|
||||
#pragma endregion
|
||||
DO_API(0x991b10, 0x99ad10, Il2CppString*, il2cpp_string_new, (const char* str));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "il2cpp-types.h"
|
||||
|
||||
// IL2CPP APIs
|
||||
#define DO_API(r, n, p) extern r (*n) p
|
||||
#define DO_API(ca, oa, r, n, p) extern r (*n) p
|
||||
#include "il2cpp-api-functions.h"
|
||||
#undef DO_API
|
||||
|
||||
|
||||
@@ -2,26 +2,30 @@ using namespace Genshin;
|
||||
|
||||
// DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...));
|
||||
|
||||
// N: System.Convert$ToBase64String
|
||||
// L: mscorlib
|
||||
DO_APP_FUNC(0x051CC420, 0x051CCB00, Il2CppString*, ToBase64String, (ByteArray* value, int offset, int length, void* method));
|
||||
DO_APP_FUNC(0x728c160, 0x71cc2e0, Il2CppString*, ToBase64String, (ByteArray* value, int offset, int length, void* method));
|
||||
|
||||
// N: MoleMole.MonoLoginMainPage.version$set
|
||||
// L: Assembly-CSharp
|
||||
DO_APP_FUNC(0X01E6CC80, 0x01E6CD90, void, SetVersion, (void* obj, Il2CppString* value, void* method));
|
||||
DO_APP_FUNC(0x2e2c930, 0x2dc4b90, void, SetVersion, (void* obj, Il2CppString* value, void* method));
|
||||
|
||||
// N: UnityEngine.Application$RecordUserData
|
||||
// L: UnityEngine.CoreModule
|
||||
DO_APP_FUNC(0x05AFD640, 0x05AFD630, ByteArray*, RecordUserData, (int32_t nType, void* method));
|
||||
DO_APP_FUNC(0x7c318d0, 0x7b69060, ByteArray*, RecordUserData, (int32_t nType));
|
||||
|
||||
// N: MoleMole.Packet$XorEncrypt [Obfuscated]
|
||||
// L: Assembly-CSharp
|
||||
DO_APP_FUNC(0x0133C8A0, 0x0133D110, void, XorEncrypt, (ByteArray** data, int length, void* method));
|
||||
DO_APP_FUNC(0x1ba7d30, 0x1b7b9f0, void, XorEncrypt, (ByteArray** data, int length, void* method));
|
||||
|
||||
// N: Kcp.KcpNative$kcp_client_send_packet [Obfuscated]
|
||||
// L: Assembly-CSharp
|
||||
DO_APP_FUNC(0x0094FBD0, 0x0094FCF0, int, KcpSend, (void* client, KcpPacket* pkt, void* method));
|
||||
DO_APP_FUNC(0xc3fe80, 0xc47280, int, KcpSend, (void* client, KcpPacket* pkt, void* method));
|
||||
|
||||
// N: MoleMole.KcpClient$TryDequeueEvent [Obfuscated]
|
||||
// L: Assembly-CSharp
|
||||
DO_APP_FUNC(0x026C8690, 0x026C9030, bool, KcpRecv, (void* client, ClientKcpEvent* evt, void* method));
|
||||
DO_APP_FUNC(0xf1ec70, 0xf1bca0, bool, KcpRecv, (void* client, ClientKcpEvent* evt, void* method));
|
||||
|
||||
DO_APP_FUNC(0x75a6880, 0x74e4b80, LPVOID, GetDefaultEncoding, ());
|
||||
|
||||
DO_APP_FUNC(0x75a6130, 0x74e4420, Il2CppString*, GetString, (LPVOID encoding, LPVOID bytes));
|
||||
|
||||
DO_APP_FUNC(0x75a4fc0, 0x74e32b0, ByteArray*, GetBytes, (LPVOID encoding, LPVOID str));
|
||||
|
||||
DO_APP_FUNC(0x1bf31f0, 0x1bc5f60, VOID, RequestLogin, (LPVOID obj, LPVOID token, UINT uid));
|
||||
|
||||
DO_APP_FUNC(0x4922d40, 0x4879590, VOID, SetChecksum, (LPVOID obj, Il2CppString* value));
|
||||
|
||||
DO_APP_FUNC(0x34780d0, 0x3401460, VOID, ForceQuit, (LPVOID obj));
|
||||
|
||||
DO_APP_FUNC(0x57df820, 0x5727410, LPVOID, GetSingletonManager, ());
|
||||
|
||||
DO_APP_FUNC(0x57df550, 0x5727140, LPVOID, GetSingletonInstance, (LPVOID obj, Il2CppString* value));
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include "il2cpp-init.h"
|
||||
|
||||
#define DO_API(r, n, p) r (*n) p
|
||||
#define DO_API(ca, oa, r, n, p) r (*n) p
|
||||
#include "il2cpp-api-functions.h"
|
||||
#undef DO_API
|
||||
|
||||
@@ -20,11 +20,6 @@ namespace Genshin {
|
||||
|
||||
using std::string;
|
||||
|
||||
UINT64 GetAddressByExports(HMODULE base, const char* name) {
|
||||
UINT64 funcAddr = reinterpret_cast<UINT64>(GetProcAddress(base, name));
|
||||
return funcAddr == 0 ? 0 : funcAddr;
|
||||
}
|
||||
|
||||
void InitIL2CPP() {
|
||||
TCHAR szFileName[MAX_PATH];
|
||||
GetModuleFileName(NULL, szFileName, MAX_PATH);
|
||||
@@ -32,7 +27,7 @@ void InitIL2CPP() {
|
||||
auto hBase = GetModuleHandle("UserAssembly.dll");
|
||||
auto bAddr = (UINT64)hBase;
|
||||
auto cAddr = (UINT64)GetModuleHandle("UnityPlayer.dll");
|
||||
#define DO_API(r, n, p) n = (r (*) p) GetAddressByExports(hBase, #n);
|
||||
#define DO_API(ca, oa, r, n, p) n = (r (*) p)(bAddr + (isCN ? ca : oa))
|
||||
#include "il2cpp-api-functions.h"
|
||||
#undef DO_API
|
||||
#define DO_APP_FUNC(ca, oa, r, n, p) n = (r (*) p)(bAddr + (isCN ? ca : oa))
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
using namespace Genshin;
|
||||
|
||||
DO_UNI_FUNC(0x00BAB2B0, 0x00BAB2B0, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));
|
||||
DO_UNI_FUNC(0x00100570, 0x00100570, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));
|
||||
|
||||
@@ -1,9 +1,20 @@
|
||||
#include "pch.h"
|
||||
#include "util.h"
|
||||
|
||||
VOID DisableVMProtect() {
|
||||
DWORD oldProtect = 0;
|
||||
auto ntdll = GetModuleHandleA("ntdll.dll");
|
||||
BYTE callcode = ((BYTE*)GetProcAddress(ntdll, "NtQuerySection"))[4] - 1;
|
||||
BYTE restore[] = { 0x4C, 0x8B, 0xD1, 0xB8, callcode };
|
||||
auto nt_vp = (BYTE*)GetProcAddress(ntdll, "NtProtectVirtualMemory");
|
||||
VirtualProtect(nt_vp, sizeof(restore), PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||
memcpy(nt_vp, restore, sizeof(restore));
|
||||
VirtualProtect(nt_vp, sizeof(restore), oldProtect, &oldProtect);
|
||||
}
|
||||
|
||||
#pragma region StringConvert
|
||||
|
||||
string IlStringToString(Il2CppString* str, UINT codePage) {
|
||||
string ToString(Il2CppString* str, UINT codePage) {
|
||||
auto chars = reinterpret_cast<const wchar_t*>(str->chars);
|
||||
auto len = WideCharToMultiByte(codePage, 0, chars, -1, nullptr, 0, nullptr, nullptr);
|
||||
auto buffer = new char[len];
|
||||
@@ -13,14 +24,6 @@ string IlStringToString(Il2CppString* str, UINT codePage) {
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region GC
|
||||
|
||||
UINT32 GCHandle_New(void* object, bool pinned) {
|
||||
return il2cpp_gchandle_new((Il2CppObject*)object, pinned);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region ByteUtils
|
||||
|
||||
bool IsLittleEndian() {
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
using std::string;
|
||||
|
||||
VOID DisableVMProtect();
|
||||
bool IsLittleEndian();
|
||||
HWND FindMainWindowByPID(DWORD pid);
|
||||
UINT32 GCHandle_New(LPVOID object, bool pinned);
|
||||
string IlStringToString(Il2CppString* str, UINT codePage = CP_ACP);
|
||||
string ToString(Il2CppString* str, UINT codePage = CP_ACP);
|
||||
|
||||
#define cstring_new(str) il2cpp_string_new(str)
|
||||
#define string_new(str) cstring_new((str).c_str())
|
||||
@@ -26,8 +26,3 @@ static T ReadMapped(void* data, int offset, bool littleEndian = false) {
|
||||
memcpy(&result, cData + offset, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static T* GCHandle_GetObject(UINT handle) {
|
||||
return (T*) il2cpp_gchandle_get_target(handle);
|
||||
}
|
||||
|
||||
20
res/App.Designer.cs
generated
20
res/App.Designer.cs
generated
@@ -219,6 +219,15 @@ namespace YaeAchievement.res {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please update genshin and retry..
|
||||
/// </summary>
|
||||
internal static string GenshinHashError {
|
||||
get {
|
||||
return ResourceManager.GetString("GenshinHashError", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Please close game before run this application. ({0}).
|
||||
/// </summary>
|
||||
@@ -246,15 +255,6 @@ namespace YaeAchievement.res {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to To fetch new data, Restart the application after delete cache\d1a8ef40a67a5929.miko..
|
||||
/// </summary>
|
||||
internal static string RefreshData {
|
||||
get {
|
||||
return ResourceManager.GetString("RefreshData", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Reward not taken.
|
||||
/// </summary>
|
||||
@@ -339,7 +339,7 @@ namespace YaeAchievement.res {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Use previous fetched data..
|
||||
/// Looks up a localized string similar to Use previous fetched data? (yes|no).
|
||||
/// </summary>
|
||||
internal static string UsePreviousData {
|
||||
get {
|
||||
|
||||
@@ -105,10 +105,7 @@ Input a number (0-5): </value>
|
||||
<value>YaeAchievement ({0})</value>
|
||||
</data>
|
||||
<data name="UsePreviousData" xml:space="preserve">
|
||||
<value>Use previous fetched data.</value>
|
||||
</data>
|
||||
<data name="RefreshData" xml:space="preserve">
|
||||
<value>To fetch new data, Restart the application after delete cache\d1a8ef40a67a5929.miko.</value>
|
||||
<value>Use previous fetched data? (yes|no)</value>
|
||||
</data>
|
||||
<data name="NetworkError" xml:space="preserve">
|
||||
<value>Network error:</value>
|
||||
@@ -126,4 +123,7 @@ Input a number (0-5): </value>
|
||||
<data name="Updater" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>Updater.exe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</data>
|
||||
<data name="GenshinHashError" xml:space="preserve">
|
||||
<value>Please update genshin and retry.</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -99,10 +99,7 @@
|
||||
<value>YaeAchievement - 原神成就导出工具 ({0})</value>
|
||||
</data>
|
||||
<data name="UsePreviousData" xml:space="preserve">
|
||||
<value>使用上一次获取到的成就数据</value>
|
||||
</data>
|
||||
<data name="RefreshData" xml:space="preserve">
|
||||
<value>要重新获取数据,手动删除 cache\d1a8ef40a67a5929.miko 后重新启动 YaeAchievement</value>
|
||||
<value>要使用上一次获取到的成就数据吗? (yes|no)</value>
|
||||
</data>
|
||||
<data name="NetworkError" xml:space="preserve">
|
||||
<value>网络错误: {0}</value>
|
||||
@@ -116,4 +113,7 @@
|
||||
<data name="ExceptionNetwork" xml:space="preserve">
|
||||
<value>网络错误,请检查网络后重试 ({0}: {1})</value>
|
||||
</data>
|
||||
<data name="GenshinHashError" xml:space="preserve">
|
||||
<value>请将原神更新至最新版本后重试</value>
|
||||
</data>
|
||||
</root>
|
||||
BIN
res/Updater.exe
BIN
res/Updater.exe
Binary file not shown.
@@ -1,5 +1,7 @@
|
||||
using Microsoft.Win32;
|
||||
using YaeAchievement.Win32;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.Graphics.Gdi;
|
||||
|
||||
namespace YaeAchievement.AppCenterSDK;
|
||||
|
||||
@@ -21,9 +23,9 @@ public static class DeviceHelper {
|
||||
}
|
||||
|
||||
public static string GetScreenSize() {
|
||||
var desktop = Native.GetDC(IntPtr.Zero);
|
||||
var size = $"{Native.GetDeviceCaps(desktop, 118)}x{Native.GetDeviceCaps(desktop, 117)}";
|
||||
Native.ReleaseDC(IntPtr.Zero, desktop);
|
||||
var desktop = Native.GetDC(HWND.Null);
|
||||
var size = $"{Native.GetDeviceCaps(desktop, GET_DEVICE_CAPS_INDEX.DESKTOPHORZRES)}x{Native.GetDeviceCaps(desktop, GET_DEVICE_CAPS_INDEX.DESKTOPVERTRES)}";
|
||||
_ = Native.ReleaseDC(HWND.Null, desktop);
|
||||
return size;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,9 @@ public static class AppConfig {
|
||||
var copiedLogFilePath = Path.GetTempFileName();
|
||||
File.Copy(path, copiedLogFilePath, true);
|
||||
var content = File.ReadAllText(copiedLogFilePath);
|
||||
File.Delete(copiedLogFilePath);
|
||||
try {
|
||||
File.Delete(copiedLogFilePath);
|
||||
} catch (Exception) { /* ignore */}
|
||||
var matchResult = Regex.Match(content, @"(?m).:/.+(GenshinImpact_Data|YuanShen_Data)");
|
||||
if (!matchResult.Success) {
|
||||
return null;
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
using System.Net;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Win32;
|
||||
using YaeAchievement.AppCenterSDK;
|
||||
using YaeAchievement.res;
|
||||
using static AchievementAllDataNotify.Types.Achievement.Types;
|
||||
|
||||
@@ -41,7 +44,7 @@ public static class Export {
|
||||
var result = JsonSerializer.Serialize(ExportToUIAFApp(data));
|
||||
using var request = new HttpRequestMessage {
|
||||
Method = HttpMethod.Post,
|
||||
RequestUri = new Uri($"https://77.cocogoat.work/v1/memo?source={App.AllAchievement}"),
|
||||
RequestUri = new Uri($"https://77.cocogoat.cn/v1/memo?source={App.AllAchievement}"),
|
||||
Content = new StringContent(result, Encoding.UTF8, "application/json")
|
||||
};
|
||||
using var response = Utils.CHttpClient.Send(request);
|
||||
@@ -141,6 +144,7 @@ public static class Export {
|
||||
var path = Path.GetFullPath($"achievement-{DateTime.Now:yyyyMMddHHmmss}.csv");
|
||||
File.WriteAllText(path, $"\uFEFF{string.Join("\n", output)}");
|
||||
Console.WriteLine(App.ExportToFileSuccess, path);
|
||||
Process.Start("explorer.exe", $"{Path.GetDirectoryName(path)}");
|
||||
}
|
||||
|
||||
private static void ToXunkong(AchievementAllDataNotify data) {
|
||||
@@ -210,4 +214,11 @@ public static class Export {
|
||||
var b = Utils.GetBucketFileAsByteArray("schicksal/metadata");
|
||||
return AchievementInfo.Parser.ParseFrom(b);
|
||||
}
|
||||
|
||||
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
|
||||
// ReSharper disable once LocalizableElement
|
||||
Console.WriteLine($"{msg}: {ex.Message}");
|
||||
AppCenter.TrackCrash(ex, false);
|
||||
return ex.NativeErrorCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ public static class GlobalVars {
|
||||
public static readonly string CachePath = Path.Combine(DataPath, "cache");
|
||||
public static readonly string LibFilePath = Path.Combine(DataPath, "YaeAchievement.dll");
|
||||
|
||||
public const uint AppVersionCode = 31;
|
||||
public const string AppVersionName = "2.2.1";
|
||||
public const uint AppVersionCode = 35;
|
||||
public const string AppVersionName = "2.5";
|
||||
|
||||
public const string PipeName = "YaeAchievementPipe";
|
||||
public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com";
|
||||
|
||||
@@ -1,52 +1,61 @@
|
||||
using System.ComponentModel;
|
||||
using YaeAchievement.Win32;
|
||||
using static YaeAchievement.Win32.Native;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.System.Memory;
|
||||
using Windows.Win32.System.Threading;
|
||||
|
||||
namespace YaeAchievement;
|
||||
namespace YaeAchievement;
|
||||
|
||||
public static class Injector {
|
||||
|
||||
public static unsafe bool CreateProcess(string path, out IntPtr hProc, out IntPtr hThread, out uint pid) {
|
||||
var si = new StartupInfo();
|
||||
SecurityAttributes* attr = null;
|
||||
public static unsafe bool CreateProcess(string path, out HANDLE hProc, out HANDLE hThread, out uint pid) {
|
||||
Span<char> cmdLines = stackalloc char[1]; // "\0"
|
||||
var si = new STARTUPINFOW {
|
||||
cb = unchecked((uint)sizeof(STARTUPINFOW))
|
||||
};
|
||||
var dir = Path.GetDirectoryName(path)!;
|
||||
var result = Native.CreateProcess(
|
||||
path, null, ref *attr, ref *attr, false,
|
||||
CreationFlags.CreateSuspended, IntPtr.Zero, dir, ref si, out var pi
|
||||
path, ref cmdLines, default, default, false,
|
||||
PROCESS_CREATION_FLAGS.CREATE_SUSPENDED, default, dir, in si, out var pi
|
||||
);
|
||||
pid = pi.dwProcessID;
|
||||
pid = pi.dwProcessId;
|
||||
hProc = pi.hProcess;
|
||||
hThread = pi.hThread;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// todo: refactor
|
||||
public static int LoadLibraryAndInject(IntPtr hProc, string libPath) {
|
||||
var hKernel = GetModuleHandle("kernel32.dll");
|
||||
if (hKernel == IntPtr.Zero) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail");
|
||||
public static unsafe int LoadLibraryAndInject(HANDLE hProc, ReadOnlySpan<byte> libPath) {
|
||||
fixed (char* lpModelName = "kernel32.dll") {
|
||||
var hKernel = Native.GetModuleHandle(lpModelName);
|
||||
if (hKernel.IsNull) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail");
|
||||
}
|
||||
fixed(byte* lpProcName = "LoadLibraryA"u8) {
|
||||
var pLoadLibrary = Native.GetProcAddress(hKernel, (PCSTR)lpProcName);
|
||||
if (pLoadLibrary.IsNull) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail");
|
||||
}
|
||||
var pBase = Native.VirtualAllocEx(hProc, default, unchecked((uint)libPath.Length + 1), VIRTUAL_ALLOCATION_TYPE.MEM_RESERVE | VIRTUAL_ALLOCATION_TYPE.MEM_COMMIT, PAGE_PROTECTION_FLAGS.PAGE_READWRITE);
|
||||
if ((nint)pBase == 0) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail");
|
||||
}
|
||||
fixed (void* lpBuffer = libPath) {
|
||||
if (!Native.WriteProcessMemory(hProc, pBase, lpBuffer, unchecked((uint)libPath.Length))) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
|
||||
}
|
||||
}
|
||||
var lpStartAddress = pLoadLibrary.CreateDelegate<LPTHREAD_START_ROUTINE>();
|
||||
var hThread = Native.CreateRemoteThread(hProc, default, 0, lpStartAddress, pBase, 0);
|
||||
if (hThread.IsNull) {
|
||||
var e = new Win32Exception();
|
||||
Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE);
|
||||
return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail");
|
||||
}
|
||||
if (Native.WaitForSingleObject(hThread, 2000) == 0) {
|
||||
Native.VirtualFreeEx(hProc, pBase, 0, VIRTUAL_FREE_TYPE.MEM_RELEASE);
|
||||
}
|
||||
return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0;
|
||||
}
|
||||
}
|
||||
var pLoadLibrary = GetProcAddress(hKernel, "LoadLibraryA");
|
||||
if (pLoadLibrary == IntPtr.Zero) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail");
|
||||
}
|
||||
var pBase = VirtualAllocEx(hProc, IntPtr.Zero, libPath.Length + 1, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
|
||||
if (pBase == IntPtr.Zero) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail");
|
||||
}
|
||||
if (!WriteProcessMemory(hProc, pBase, libPath.ToCharArray(), libPath.Length, out _)) {
|
||||
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
|
||||
}
|
||||
var hThread = CreateRemoteThread(hProc, IntPtr.Zero, 0, pLoadLibrary, pBase, 0, out _);
|
||||
if (hThread == IntPtr.Zero) {
|
||||
var e = new Win32Exception();
|
||||
VirtualFreeEx(hProc, pBase, 0, AllocationType.Release);
|
||||
return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail");
|
||||
}
|
||||
if (WaitForSingleObject(hThread, 2000) == 0) {
|
||||
VirtualFreeEx(hProc, pBase, 0, AllocationType.Release);
|
||||
}
|
||||
return !CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
6
src/NativeMethods.json
Normal file
6
src/NativeMethods.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://aka.ms/CsWin32.schema.json",
|
||||
"className": "Native",
|
||||
"allowMarshaling": true,
|
||||
"public": true
|
||||
}
|
||||
21
src/NativeMethods.txt
Normal file
21
src/NativeMethods.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
CreateProcess
|
||||
GetModuleHandle
|
||||
GetProcAddress
|
||||
VirtualAllocEx
|
||||
WriteProcessMemory
|
||||
CreateRemoteThread
|
||||
VirtualFreeEx
|
||||
WaitForSingleObject
|
||||
OpenClipboard
|
||||
EmptyClipboard
|
||||
GlobalLock
|
||||
SetClipboardData
|
||||
GlobalUnlock
|
||||
CloseClipboard
|
||||
GetStdHandle
|
||||
GetConsoleMode
|
||||
SetConsoleMode
|
||||
TerminateProcess
|
||||
ResumeThread
|
||||
GetDeviceCaps
|
||||
GetDC
|
||||
@@ -4,12 +4,12 @@ using YaeAchievement.AppCenterSDK.Models;
|
||||
using YaeAchievement.res;
|
||||
using static YaeAchievement.Utils;
|
||||
|
||||
TryDisableQuickEdit();
|
||||
InstallExitHook();
|
||||
InstallExceptionHook();
|
||||
|
||||
await CheckVcRuntime();
|
||||
CheckSelfIsRunning();
|
||||
TryDisableQuickEdit();
|
||||
CheckGenshinIsRunning();
|
||||
|
||||
Console.WriteLine(@"----------------------------------------------------");
|
||||
@@ -28,11 +28,22 @@ new EventLog("AppInit") {
|
||||
{ "SystemVersion", DeviceHelper.GetSystemVersion() }
|
||||
}
|
||||
}.Enqueue();
|
||||
var usePreviousData = false;
|
||||
var historyCache = new CacheFile("ExportData");
|
||||
if (historyCache.LastWriteTime.AddMinutes(10) > DateTime.UtcNow) {
|
||||
Console.WriteLine(App.UsePreviousData);
|
||||
Console.WriteLine(App.RefreshData);
|
||||
Export.Choose(AchievementAllDataNotify.Parser.ParseFrom(historyCache.Read().Content));
|
||||
usePreviousData = Console.ReadLine() == "yes";
|
||||
}
|
||||
Export:
|
||||
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 => {
|
||||
GlobalVars.UnexpectedExit = false;
|
||||
|
||||
@@ -23,17 +23,17 @@ public static partial class AchievementAllDataNotifyReflection {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"Ch5BY2hpZXZlbWVudEFsbERhdGFOb3RpZnkucHJvdG8iowIKGEFjaGlldmVt",
|
||||
"ZW50QWxsRGF0YU5vdGlmeRIzCgRsaXN0GAQgAygLMiUuQWNoaWV2ZW1lbnRB",
|
||||
"bGxEYXRhTm90aWZ5LkFjaGlldmVtZW50GtEBCgtBY2hpZXZlbWVudBIKCgJp",
|
||||
"ZBgOIAEoDRI8CgZzdGF0dXMYDSABKA4yLC5BY2hpZXZlbWVudEFsbERhdGFO",
|
||||
"b3RpZnkuQWNoaWV2ZW1lbnQuU3RhdHVzEg8KB2N1cnJlbnQYDCABKA0SDQoF",
|
||||
"dG90YWwYCCABKA0SEQoJdGltZXN0YW1wGAsgASgNIkUKBlN0YXR1cxILCgdJ",
|
||||
"ZW50QWxsRGF0YU5vdGlmeRIzCgRsaXN0GA8gAygLMiUuQWNoaWV2ZW1lbnRB",
|
||||
"bGxEYXRhTm90aWZ5LkFjaGlldmVtZW50GtEBCgtBY2hpZXZlbWVudBIRCgl0",
|
||||
"aW1lc3RhbXAYDSABKA0SDwoHY3VycmVudBgCIAEoDRINCgV0b3RhbBgFIAEo",
|
||||
"DRIKCgJpZBgJIAEoDRI8CgZzdGF0dXMYBiABKA4yLC5BY2hpZXZlbWVudEFs",
|
||||
"bERhdGFOb3RpZnkuQWNoaWV2ZW1lbnQuU3RhdHVzIkUKBlN0YXR1cxILCgdJ",
|
||||
"TlZBTElEEAASDgoKVU5GSU5JU0hFRBABEgwKCEZJTklTSEVEEAISEAoMUkVX",
|
||||
"QVJEX1RBS0VOEANiBnByb3RvMw=="));
|
||||
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
|
||||
new pbr::FileDescriptor[] { },
|
||||
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AchievementAllDataNotify), global::AchievementAllDataNotify.Parser, new[]{ "List" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::AchievementAllDataNotify.Types.Achievement), global::AchievementAllDataNotify.Types.Achievement.Parser, new[]{ "Id", "Status", "Current", "Total", "Timestamp" }, null, new[]{ typeof(global::AchievementAllDataNotify.Types.Achievement.Types.Status) }, null, null)})
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::AchievementAllDataNotify), global::AchievementAllDataNotify.Parser, new[]{ "List" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::AchievementAllDataNotify.Types.Achievement), global::AchievementAllDataNotify.Types.Achievement.Parser, new[]{ "Timestamp", "Current", "Total", "Id", "Status" }, null, new[]{ typeof(global::AchievementAllDataNotify.Types.Achievement.Types.Status) }, null, null)})
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
@@ -85,9 +85,9 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "list" field.</summary>
|
||||
public const int ListFieldNumber = 4;
|
||||
public const int ListFieldNumber = 15;
|
||||
private static readonly pb::FieldCodec<global::AchievementAllDataNotify.Types.Achievement> _repeated_list_codec
|
||||
= pb::FieldCodec.ForMessage(34, global::AchievementAllDataNotify.Types.Achievement.Parser);
|
||||
= pb::FieldCodec.ForMessage(122, global::AchievementAllDataNotify.Types.Achievement.Parser);
|
||||
private readonly pbc::RepeatedField<global::AchievementAllDataNotify.Types.Achievement> list_ = new pbc::RepeatedField<global::AchievementAllDataNotify.Types.Achievement>();
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
@@ -188,7 +188,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 34: {
|
||||
case 122: {
|
||||
list_.AddEntriesFrom(input, _repeated_list_codec);
|
||||
break;
|
||||
}
|
||||
@@ -207,7 +207,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 34: {
|
||||
case 122: {
|
||||
list_.AddEntriesFrom(ref input, _repeated_list_codec);
|
||||
break;
|
||||
}
|
||||
@@ -255,11 +255,11 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public Achievement(Achievement other) : this() {
|
||||
id_ = other.id_;
|
||||
status_ = other.status_;
|
||||
timestamp_ = other.timestamp_;
|
||||
current_ = other.current_;
|
||||
total_ = other.total_;
|
||||
timestamp_ = other.timestamp_;
|
||||
id_ = other.id_;
|
||||
status_ = other.status_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -269,32 +269,20 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
return new Achievement(this);
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "id" field.</summary>
|
||||
public const int IdFieldNumber = 14;
|
||||
private uint id_;
|
||||
/// <summary>Field number for the "timestamp" field.</summary>
|
||||
public const int TimestampFieldNumber = 13;
|
||||
private uint timestamp_;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public uint Id {
|
||||
get { return id_; }
|
||||
public uint Timestamp {
|
||||
get { return timestamp_; }
|
||||
set {
|
||||
id_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "status" field.</summary>
|
||||
public const int StatusFieldNumber = 13;
|
||||
private global::AchievementAllDataNotify.Types.Achievement.Types.Status status_ = global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public global::AchievementAllDataNotify.Types.Achievement.Types.Status Status {
|
||||
get { return status_; }
|
||||
set {
|
||||
status_ = value;
|
||||
timestamp_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "current" field.</summary>
|
||||
public const int CurrentFieldNumber = 12;
|
||||
public const int CurrentFieldNumber = 2;
|
||||
private uint current_;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
@@ -306,7 +294,7 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "total" field.</summary>
|
||||
public const int TotalFieldNumber = 8;
|
||||
public const int TotalFieldNumber = 5;
|
||||
private uint total_;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
@@ -317,15 +305,27 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "timestamp" field.</summary>
|
||||
public const int TimestampFieldNumber = 11;
|
||||
private uint timestamp_;
|
||||
/// <summary>Field number for the "id" field.</summary>
|
||||
public const int IdFieldNumber = 9;
|
||||
private uint id_;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public uint Timestamp {
|
||||
get { return timestamp_; }
|
||||
public uint Id {
|
||||
get { return id_; }
|
||||
set {
|
||||
timestamp_ = value;
|
||||
id_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "status" field.</summary>
|
||||
public const int StatusFieldNumber = 6;
|
||||
private global::AchievementAllDataNotify.Types.Achievement.Types.Status status_ = global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid;
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public global::AchievementAllDataNotify.Types.Achievement.Types.Status Status {
|
||||
get { return status_; }
|
||||
set {
|
||||
status_ = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,11 +344,11 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
if (ReferenceEquals(other, this)) {
|
||||
return true;
|
||||
}
|
||||
if (Id != other.Id) return false;
|
||||
if (Status != other.Status) return false;
|
||||
if (Timestamp != other.Timestamp) return false;
|
||||
if (Current != other.Current) return false;
|
||||
if (Total != other.Total) return false;
|
||||
if (Timestamp != other.Timestamp) return false;
|
||||
if (Id != other.Id) return false;
|
||||
if (Status != other.Status) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -356,11 +356,11 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override int GetHashCode() {
|
||||
int hash = 1;
|
||||
if (Id != 0) hash ^= Id.GetHashCode();
|
||||
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) hash ^= Status.GetHashCode();
|
||||
if (Timestamp != 0) hash ^= Timestamp.GetHashCode();
|
||||
if (Current != 0) hash ^= Current.GetHashCode();
|
||||
if (Total != 0) hash ^= Total.GetHashCode();
|
||||
if (Timestamp != 0) hash ^= Timestamp.GetHashCode();
|
||||
if (Id != 0) hash ^= Id.GetHashCode();
|
||||
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) hash ^= Status.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
@@ -379,26 +379,26 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
|
||||
output.WriteRawMessage(this);
|
||||
#else
|
||||
if (Total != 0) {
|
||||
output.WriteRawTag(64);
|
||||
output.WriteUInt32(Total);
|
||||
}
|
||||
if (Timestamp != 0) {
|
||||
output.WriteRawTag(88);
|
||||
output.WriteUInt32(Timestamp);
|
||||
}
|
||||
if (Current != 0) {
|
||||
output.WriteRawTag(96);
|
||||
output.WriteRawTag(16);
|
||||
output.WriteUInt32(Current);
|
||||
}
|
||||
if (Total != 0) {
|
||||
output.WriteRawTag(40);
|
||||
output.WriteUInt32(Total);
|
||||
}
|
||||
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
|
||||
output.WriteRawTag(104);
|
||||
output.WriteRawTag(48);
|
||||
output.WriteEnum((int) Status);
|
||||
}
|
||||
if (Id != 0) {
|
||||
output.WriteRawTag(112);
|
||||
output.WriteRawTag(72);
|
||||
output.WriteUInt32(Id);
|
||||
}
|
||||
if (Timestamp != 0) {
|
||||
output.WriteRawTag(104);
|
||||
output.WriteUInt32(Timestamp);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
@@ -409,26 +409,26 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
|
||||
if (Total != 0) {
|
||||
output.WriteRawTag(64);
|
||||
output.WriteUInt32(Total);
|
||||
}
|
||||
if (Timestamp != 0) {
|
||||
output.WriteRawTag(88);
|
||||
output.WriteUInt32(Timestamp);
|
||||
}
|
||||
if (Current != 0) {
|
||||
output.WriteRawTag(96);
|
||||
output.WriteRawTag(16);
|
||||
output.WriteUInt32(Current);
|
||||
}
|
||||
if (Total != 0) {
|
||||
output.WriteRawTag(40);
|
||||
output.WriteUInt32(Total);
|
||||
}
|
||||
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
|
||||
output.WriteRawTag(104);
|
||||
output.WriteRawTag(48);
|
||||
output.WriteEnum((int) Status);
|
||||
}
|
||||
if (Id != 0) {
|
||||
output.WriteRawTag(112);
|
||||
output.WriteRawTag(72);
|
||||
output.WriteUInt32(Id);
|
||||
}
|
||||
if (Timestamp != 0) {
|
||||
output.WriteRawTag(104);
|
||||
output.WriteUInt32(Timestamp);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
@@ -439,11 +439,8 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public int CalculateSize() {
|
||||
int size = 0;
|
||||
if (Id != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Id);
|
||||
}
|
||||
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status);
|
||||
if (Timestamp != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Timestamp);
|
||||
}
|
||||
if (Current != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Current);
|
||||
@@ -451,8 +448,11 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
if (Total != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Total);
|
||||
}
|
||||
if (Timestamp != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Timestamp);
|
||||
if (Id != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Id);
|
||||
}
|
||||
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Status);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
@@ -466,11 +466,8 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
if (other == null) {
|
||||
return;
|
||||
}
|
||||
if (other.Id != 0) {
|
||||
Id = other.Id;
|
||||
}
|
||||
if (other.Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
|
||||
Status = other.Status;
|
||||
if (other.Timestamp != 0) {
|
||||
Timestamp = other.Timestamp;
|
||||
}
|
||||
if (other.Current != 0) {
|
||||
Current = other.Current;
|
||||
@@ -478,8 +475,11 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
if (other.Total != 0) {
|
||||
Total = other.Total;
|
||||
}
|
||||
if (other.Timestamp != 0) {
|
||||
Timestamp = other.Timestamp;
|
||||
if (other.Id != 0) {
|
||||
Id = other.Id;
|
||||
}
|
||||
if (other.Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
|
||||
Status = other.Status;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
@@ -496,26 +496,26 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
|
||||
break;
|
||||
case 64: {
|
||||
Total = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 88: {
|
||||
Timestamp = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 96: {
|
||||
case 16: {
|
||||
Current = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 104: {
|
||||
case 40: {
|
||||
Total = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 48: {
|
||||
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
|
||||
break;
|
||||
}
|
||||
case 112: {
|
||||
case 72: {
|
||||
Id = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 104: {
|
||||
Timestamp = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -531,26 +531,26 @@ public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementA
|
||||
default:
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
|
||||
break;
|
||||
case 64: {
|
||||
Total = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 88: {
|
||||
Timestamp = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 96: {
|
||||
case 16: {
|
||||
Current = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 104: {
|
||||
case 40: {
|
||||
Total = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 48: {
|
||||
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
|
||||
break;
|
||||
}
|
||||
case 112: {
|
||||
case 72: {
|
||||
Id = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
case 104: {
|
||||
Timestamp = input.ReadUInt32();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,15 +22,16 @@ public static partial class UpdateInfoReflection {
|
||||
static UpdateInfoReflection() {
|
||||
byte[] descriptorData = global::System.Convert.FromBase64String(
|
||||
string.Concat(
|
||||
"ChBVcGRhdGVJbmZvLnByb3RvIqwBCgpVcGRhdGVJbmZvEhMKC3ZlcnNpb25D",
|
||||
"ChBVcGRhdGVJbmZvLnByb3RvIuIBCgpVcGRhdGVJbmZvEhMKC3ZlcnNpb25D",
|
||||
"b2RlGAEgASgNEhMKC3ZlcnNpb25OYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9u",
|
||||
"GAMgASgJEhMKC3BhY2thZ2VMaW5rGAQgASgJEhMKC2ZvcmNlVXBkYXRlGAUg",
|
||||
"ASgIEhkKEWVuYWJsZUxpYkRvd25sb2FkGAYgASgIEhoKEmVuYWJsZUF1dG9E",
|
||||
"b3dubG9hZBgHIAEoCGIGcHJvdG8z"));
|
||||
"b3dubG9hZBgHIAEoCBIZChFjdXJyZW50Q05HYW1lSGFzaBgIIAEoCRIZChFj",
|
||||
"dXJyZW50T1NHYW1lSGFzaBgJIAEoCWIGcHJvdG8z"));
|
||||
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)
|
||||
new pbr::GeneratedClrTypeInfo(typeof(global::UpdateInfo), global::UpdateInfo.Parser, new[]{ "VersionCode", "VersionName", "Description", "PackageLink", "ForceUpdate", "EnableLibDownload", "EnableAutoDownload", "CurrentCNGameHash", "CurrentOSGameHash" }, null, null, null, null)
|
||||
}));
|
||||
}
|
||||
#endregion
|
||||
@@ -78,6 +79,8 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
forceUpdate_ = other.forceUpdate_;
|
||||
enableLibDownload_ = other.enableLibDownload_;
|
||||
enableAutoDownload_ = other.enableAutoDownload_;
|
||||
currentCNGameHash_ = other.currentCNGameHash_;
|
||||
currentOSGameHash_ = other.currentOSGameHash_;
|
||||
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -171,6 +174,30 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "currentCNGameHash" field.</summary>
|
||||
public const int CurrentCNGameHashFieldNumber = 8;
|
||||
private string currentCNGameHash_ = "";
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string CurrentCNGameHash {
|
||||
get { return currentCNGameHash_; }
|
||||
set {
|
||||
currentCNGameHash_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Field number for the "currentOSGameHash" field.</summary>
|
||||
public const int CurrentOSGameHashFieldNumber = 9;
|
||||
private string currentOSGameHash_ = "";
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public string CurrentOSGameHash {
|
||||
get { return currentOSGameHash_; }
|
||||
set {
|
||||
currentOSGameHash_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
|
||||
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
|
||||
public override bool Equals(object other) {
|
||||
@@ -193,6 +220,8 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
if (ForceUpdate != other.ForceUpdate) return false;
|
||||
if (EnableLibDownload != other.EnableLibDownload) return false;
|
||||
if (EnableAutoDownload != other.EnableAutoDownload) return false;
|
||||
if (CurrentCNGameHash != other.CurrentCNGameHash) return false;
|
||||
if (CurrentOSGameHash != other.CurrentOSGameHash) return false;
|
||||
return Equals(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -207,6 +236,8 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
if (ForceUpdate != false) hash ^= ForceUpdate.GetHashCode();
|
||||
if (EnableLibDownload != false) hash ^= EnableLibDownload.GetHashCode();
|
||||
if (EnableAutoDownload != false) hash ^= EnableAutoDownload.GetHashCode();
|
||||
if (CurrentCNGameHash.Length != 0) hash ^= CurrentCNGameHash.GetHashCode();
|
||||
if (CurrentOSGameHash.Length != 0) hash ^= CurrentOSGameHash.GetHashCode();
|
||||
if (_unknownFields != null) {
|
||||
hash ^= _unknownFields.GetHashCode();
|
||||
}
|
||||
@@ -253,6 +284,14 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
output.WriteRawTag(56);
|
||||
output.WriteBool(EnableAutoDownload);
|
||||
}
|
||||
if (CurrentCNGameHash.Length != 0) {
|
||||
output.WriteRawTag(66);
|
||||
output.WriteString(CurrentCNGameHash);
|
||||
}
|
||||
if (CurrentOSGameHash.Length != 0) {
|
||||
output.WriteRawTag(74);
|
||||
output.WriteString(CurrentOSGameHash);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(output);
|
||||
}
|
||||
@@ -291,6 +330,14 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
output.WriteRawTag(56);
|
||||
output.WriteBool(EnableAutoDownload);
|
||||
}
|
||||
if (CurrentCNGameHash.Length != 0) {
|
||||
output.WriteRawTag(66);
|
||||
output.WriteString(CurrentCNGameHash);
|
||||
}
|
||||
if (CurrentOSGameHash.Length != 0) {
|
||||
output.WriteRawTag(74);
|
||||
output.WriteString(CurrentOSGameHash);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
_unknownFields.WriteTo(ref output);
|
||||
}
|
||||
@@ -322,6 +369,12 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
if (EnableAutoDownload != false) {
|
||||
size += 1 + 1;
|
||||
}
|
||||
if (CurrentCNGameHash.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(CurrentCNGameHash);
|
||||
}
|
||||
if (CurrentOSGameHash.Length != 0) {
|
||||
size += 1 + pb::CodedOutputStream.ComputeStringSize(CurrentOSGameHash);
|
||||
}
|
||||
if (_unknownFields != null) {
|
||||
size += _unknownFields.CalculateSize();
|
||||
}
|
||||
@@ -355,6 +408,12 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
if (other.EnableAutoDownload != false) {
|
||||
EnableAutoDownload = other.EnableAutoDownload;
|
||||
}
|
||||
if (other.CurrentCNGameHash.Length != 0) {
|
||||
CurrentCNGameHash = other.CurrentCNGameHash;
|
||||
}
|
||||
if (other.CurrentOSGameHash.Length != 0) {
|
||||
CurrentOSGameHash = other.CurrentOSGameHash;
|
||||
}
|
||||
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
|
||||
}
|
||||
|
||||
@@ -398,6 +457,14 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
EnableAutoDownload = input.ReadBool();
|
||||
break;
|
||||
}
|
||||
case 66: {
|
||||
CurrentCNGameHash = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 74: {
|
||||
CurrentOSGameHash = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -441,6 +508,14 @@ public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
|
||||
EnableAutoDownload = input.ReadBool();
|
||||
break;
|
||||
}
|
||||
case 66: {
|
||||
CurrentCNGameHash = input.ReadString();
|
||||
break;
|
||||
}
|
||||
case 74: {
|
||||
CurrentOSGameHash = input.ReadString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
82
src/Utils.cs
82
src/Utils.cs
@@ -1,14 +1,17 @@
|
||||
using System.ComponentModel;
|
||||
using Microsoft.Win32;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.IO.Pipes;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Win32;
|
||||
using System.Text;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.System.Console;
|
||||
using YaeAchievement.AppCenterSDK;
|
||||
using YaeAchievement.res;
|
||||
using YaeAchievement.Win32;
|
||||
|
||||
namespace YaeAchievement;
|
||||
|
||||
@@ -64,21 +67,27 @@ public static class Utils {
|
||||
public static bool ToBooleanOrFalse(string? value) {
|
||||
return value != null && bool.TryParse(value, out var result) && result;
|
||||
}
|
||||
|
||||
public static void CopyToClipboard(string text) {
|
||||
if (Native.OpenClipboard(IntPtr.Zero)) {
|
||||
|
||||
public static unsafe void CopyToClipboard(string text) {
|
||||
if (Native.OpenClipboard(HWND.Null))
|
||||
{
|
||||
Native.EmptyClipboard();
|
||||
var hGlobal = Marshal.AllocHGlobal((text.Length + 1) * 2);
|
||||
var hPtr = Native.GlobalLock(hGlobal);
|
||||
HANDLE hGlobal = (HANDLE)Marshal.AllocHGlobal((text.Length + 1) * 2);
|
||||
IntPtr hPtr = (IntPtr)Native.GlobalLock(hGlobal);
|
||||
Marshal.Copy(text.ToCharArray(), 0, hPtr, text.Length);
|
||||
Native.GlobalUnlock(hPtr);
|
||||
Native.SetClipboardData(13, hGlobal);
|
||||
Marshal.FreeHGlobal(hGlobal);
|
||||
Native.CloseClipboard();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
// ReSharper disable once NotAccessedField.Local
|
||||
private static UpdateInfo _updateInfo = null!;
|
||||
|
||||
public static void CheckUpdate(bool useLocalLib) {
|
||||
var info = UpdateInfo.Parser.ParseFrom(GetBucketFileAsByteArray("schicksal/version"))!;
|
||||
@@ -91,10 +100,7 @@ public static class Utils {
|
||||
File.WriteAllBytes(tmpPath, GetBucketFileAsByteArray(info.PackageLink));
|
||||
var updaterArgs = $"{Environment.ProcessId}|{Environment.ProcessPath}|{tmpPath}";
|
||||
var updaterPath = Path.Combine(GlobalVars.DataPath, "update.exe");
|
||||
var updaterHash = App.Updater.MD5Hash();
|
||||
if (!File.Exists(updaterPath) || File.ReadAllBytes(updaterPath).MD5Hash() != updaterHash) {
|
||||
File.WriteAllBytes(updaterPath, App.Updater);
|
||||
}
|
||||
File.WriteAllBytes(updaterPath, App.Updater);
|
||||
ShellOpen(updaterPath, updaterArgs.ToBytes().ToBase64());
|
||||
GlobalVars.PauseOnExit = false;
|
||||
Environment.Exit(0);
|
||||
@@ -110,6 +116,7 @@ public static class Utils {
|
||||
} else if (info.EnableLibDownload) {
|
||||
File.WriteAllBytes(GlobalVars.LibFilePath, GetBucketFileAsByteArray("schicksal/lib.dll"));
|
||||
}
|
||||
_updateInfo = info;
|
||||
}
|
||||
|
||||
public static void CheckSelfIsRunning() {
|
||||
@@ -143,9 +150,10 @@ public static class Utils {
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMethodReturnValue.Global
|
||||
public static bool TryDisableQuickEdit() {
|
||||
var handle = Native.GetStdHandle();
|
||||
return Native.GetConsoleMode(handle, out var mode) && Native.SetConsoleMode(handle, mode&~64);
|
||||
public static unsafe bool TryDisableQuickEdit() {
|
||||
var handle = Native.GetStdHandle(STD_HANDLE.STD_INPUT_HANDLE);
|
||||
CONSOLE_MODE mode = default;
|
||||
return Native.GetConsoleMode(handle, &mode) && Native.SetConsoleMode(handle, mode & ~CONSOLE_MODE.ENABLE_QUICK_EDIT_MODE);
|
||||
}
|
||||
|
||||
public static void CheckGenshinIsRunning() {
|
||||
@@ -198,9 +206,22 @@ public static class Utils {
|
||||
Environment.Exit(-1);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
private static bool CheckGenshinIsLatestVersion(string path) {
|
||||
#if DEBUG
|
||||
return true;
|
||||
#else
|
||||
var hash = File.ReadAllBytes(path).MD5Hash();
|
||||
return File.Exists(path) && (hash == _updateInfo.CurrentCNGameHash || hash == _updateInfo.CurrentOSGameHash);
|
||||
#endif
|
||||
}
|
||||
|
||||
// ReSharper disable once UnusedMethodReturnValue.Global
|
||||
public static Thread StartAndWaitResult(string exePath, Func<string, bool> onReceive) {
|
||||
if (!CheckGenshinIsLatestVersion(exePath)) {
|
||||
Console.WriteLine(App.GenshinHashError);
|
||||
Environment.Exit(0);
|
||||
}
|
||||
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
|
||||
try {
|
||||
File.Delete(GlobalVars.LibFilePath);
|
||||
@@ -209,8 +230,10 @@ public static class Utils {
|
||||
if (!Injector.CreateProcess(exePath, out var hProcess, out var hThread, out var pid)) {
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail"));
|
||||
}
|
||||
if (Injector.LoadLibraryAndInject(hProcess, GlobalVars.LibFilePath) != 0) {
|
||||
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||
if (Injector.LoadLibraryAndInject(hProcess,Encoding.UTF8.GetBytes(GlobalVars.LibFilePath)) != 0)
|
||||
{
|
||||
if (!Native.TerminateProcess(hProcess, 0))
|
||||
{
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail"));
|
||||
}
|
||||
}
|
||||
@@ -218,22 +241,27 @@ public static class Utils {
|
||||
proc = Process.GetProcessById(Convert.ToInt32(pid));
|
||||
proc.EnableRaisingEvents = true;
|
||||
proc.Exited += (_, _) => {
|
||||
if (GlobalVars.UnexpectedExit) {
|
||||
if (GlobalVars.UnexpectedExit)
|
||||
{
|
||||
proc = null;
|
||||
Console.WriteLine(App.GameProcessExit);
|
||||
Environment.Exit(114514);
|
||||
}
|
||||
};
|
||||
if (Native.ResumeThread(hThread) == 0xFFFFFFFF) {
|
||||
if (Native.ResumeThread(hThread) == 0xFFFFFFFF)
|
||||
{
|
||||
var e = new Win32Exception();
|
||||
if (!Native.TerminateProcess(hProcess, 0)) {
|
||||
if (!Native.TerminateProcess(hProcess, 0))
|
||||
{
|
||||
new Win32Exception().PrintMsgAndReturnErrCode("TerminateProcess fail");
|
||||
}
|
||||
Environment.Exit(e.PrintMsgAndReturnErrCode("ResumeThread fail"));
|
||||
}
|
||||
if (!Native.CloseHandle(hProcess)) {
|
||||
if (!Native.CloseHandle(hProcess))
|
||||
{
|
||||
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail"));
|
||||
}
|
||||
|
||||
var ts = new ThreadStart(() => {
|
||||
var server = new NamedPipeServerStream(GlobalVars.PipeName);
|
||||
server.WaitForConnection();
|
||||
@@ -260,7 +288,13 @@ public static class Utils {
|
||||
using var root = Registry.LocalMachine;
|
||||
using var sub = root.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall")!;
|
||||
var installed = sub.GetSubKeyNames()
|
||||
.Select(subKeyName => sub.OpenSubKey(subKeyName))
|
||||
.Select(subKeyName => {
|
||||
try {
|
||||
return sub.OpenSubKey(subKeyName);
|
||||
} catch (Exception) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.Select(item => item?.GetValue("DisplayName") as string ?? string.Empty)
|
||||
.Any(name => name.Contains("Microsoft Visual C++ 2022 X64 "));
|
||||
if (!installed) {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[Flags]
|
||||
public enum AllocationType : uint {
|
||||
Commit = 0x00001000,
|
||||
Reserve = 0x00002000,
|
||||
Reset = 0x00080000,
|
||||
TopDown = 0x00100000,
|
||||
WriteWatch = 0x00200000,
|
||||
Physical = 0x00400000,
|
||||
Rotate = 0x00800000,
|
||||
ResetUndo = 0x01000000,
|
||||
LargePages = 0x20000000,
|
||||
Decommit = 0x00004000,
|
||||
Release = 0x00008000
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[Flags]
|
||||
public enum CreationFlags : uint {
|
||||
CreateSuspended = 0x00000004,
|
||||
DetachedProcess = 0x00000008,
|
||||
CreateNoWindow = 0x08000000,
|
||||
ExtendedStartupInfoPresent = 0x00080000
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using YaeAchievement.AppCenterSDK;
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
public static class Extensions {
|
||||
|
||||
public static int PrintMsgAndReturnErrCode(this Win32Exception ex, string msg) {
|
||||
Console.WriteLine($"{msg}: {ex.Message}");
|
||||
AppCenter.TrackCrash(ex, false);
|
||||
return ex.NativeErrorCode;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[Flags]
|
||||
public enum MemoryProtection : uint {
|
||||
Execute = 0x10,
|
||||
ExecuteRead = 0x20,
|
||||
ExecuteReadWrite = 0x40,
|
||||
ExecuteWriteCopy = 0x80,
|
||||
NoAccess = 0x01,
|
||||
ReadOnly = 0x02,
|
||||
ReadWrite = 0x04,
|
||||
WriteCopy = 0x08,
|
||||
GuardModifierFlag = 0x100,
|
||||
NoCacheModifierFlag = 0x200,
|
||||
WriteCombineModifierFlag = 0x400
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
#pragma warning disable CA1401, CA2101
|
||||
public static class Native {
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
|
||||
public static extern bool CreateProcess(
|
||||
string lpApplicationName,
|
||||
string? lpCommandLine,
|
||||
ref SecurityAttributes lpProcessAttributes,
|
||||
ref SecurityAttributes lpThreadAttributes,
|
||||
bool bInheritHandles,
|
||||
CreationFlags dwCreationFlags,
|
||||
IntPtr lpEnvironment,
|
||||
string? lpCurrentDirectory,
|
||||
[In] ref StartupInfo lpStartupInfo,
|
||||
out ProcessInformation lpProcessInformation
|
||||
);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool TerminateProcess(IntPtr hProcess, uint uExitCode);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
public static extern bool WriteProcessMemory(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpBaseAddress,
|
||||
char[] lpBuffer,
|
||||
int nSize,
|
||||
out IntPtr lpNumberOfBytesWritten
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||
public static extern IntPtr GetModuleHandle(string lpModuleName);
|
||||
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
|
||||
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
public static extern IntPtr VirtualAllocEx(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpAddress,
|
||||
int dwSize,
|
||||
AllocationType flAllocationType,
|
||||
MemoryProtection flProtect
|
||||
);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
|
||||
public static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress, int dwSize, AllocationType dwFreeType);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern uint ResumeThread(IntPtr hThread);
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr CreateRemoteThread(
|
||||
IntPtr hProcess,
|
||||
IntPtr lpThreadAttributes,
|
||||
int dwStackSize,
|
||||
IntPtr lpStartAddress,
|
||||
IntPtr lpParameter,
|
||||
uint dwCreationFlags,
|
||||
out IntPtr lpThreadId
|
||||
);
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
private const int STD_INPUT_HANDLE = -10;
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GetStdHandle(int nStdHandle = STD_INPUT_HANDLE);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GetConsoleMode(IntPtr handle, out int lpMode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool SetConsoleMode(IntPtr handle, int ioMode);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GlobalLock(IntPtr mem);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool GlobalUnlock(IntPtr mem);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool OpenClipboard(IntPtr owner);
|
||||
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool CloseClipboard();
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr SetClipboardData(uint uFormat, IntPtr data);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool EmptyClipboard();
|
||||
|
||||
[DllImport("gdi32.dll", SetLastError = true)]
|
||||
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern IntPtr GetDC(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hdc);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern uint WaitForSingleObject(IntPtr handle, ulong dwMilliseconds);
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct ProcessInformation {
|
||||
public IntPtr hProcess;
|
||||
public IntPtr hThread;
|
||||
public uint dwProcessID;
|
||||
public uint dwThreadID;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct SecurityAttributes {
|
||||
public int nLength;
|
||||
public IntPtr lpSecurityDescriptor;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
// ReSharper disable FieldCanBeMadeReadOnly.Global
|
||||
|
||||
namespace YaeAchievement.Win32;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct StartupInfo {
|
||||
public uint cb;
|
||||
public string lpReserved;
|
||||
public string lpDesktop;
|
||||
public string lpTitle;
|
||||
public uint dwX;
|
||||
public uint dwY;
|
||||
public uint dwXSize;
|
||||
public uint dwYSize;
|
||||
public uint dwXCountChars;
|
||||
public uint dwYCountChars;
|
||||
public uint dwFillAttribute;
|
||||
public uint dwFlags;
|
||||
public ushort wShowWindow;
|
||||
public ushort cbReserved2;
|
||||
public IntPtr lpReserved2;
|
||||
public IntPtr hStdInput;
|
||||
public IntPtr hStdOutput;
|
||||
public IntPtr hStdError;
|
||||
}
|
||||
Reference in New Issue
Block a user