mirror of
https://github.com/HolographicHat/Yae.git
synced 2025-12-12 01:18:15 +08:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1429289ad | ||
|
|
1f311ed987 | ||
|
|
cc346915e3 | ||
|
|
cd0f49d83d | ||
|
|
d0b7d15894 | ||
|
|
504c8a2a9a | ||
|
|
b3162052da | ||
|
|
034d999d25 | ||
|
|
45d5620e83 | ||
|
|
fa13f9c8e5 | ||
|
|
2210a97d61 | ||
|
|
feb7ac44da | ||
|
|
3924129560 | ||
|
|
4f7f0cdfd2 | ||
|
|
cf0753c676 | ||
|
|
0b895d47ca | ||
|
|
78d2722e20 | ||
|
|
385c673323 | ||
|
|
50beb2cce7 | ||
|
|
324a4153e0 | ||
|
|
3de459aceb | ||
|
|
295bb89177 | ||
|
|
baaf4e8227 |
15
README.md
15
README.md
@@ -9,9 +9,22 @@
|
|||||||
|
|
||||||
- 支持导出所有类别的成就
|
- 支持导出所有类别的成就
|
||||||
- 支持官服,渠道服与国际服
|
- 支持官服,渠道服与国际服
|
||||||
- 支持导出至[椰羊](https://cocogoat.work/achievement)、[Snap·HuTao](https://github.com/DGP-Studio/Snap.HuTao)、[Paimon.moe](https://paimon.moe/achievement/)、[Seelie.me](https://seelie.me/achievements)、[寻空](https://github.com/xunkong/xunkong)和表格文件(csv)
|
|
||||||
- 没有窗口大小、游戏语言等要求
|
- 没有窗口大小、游戏语言等要求
|
||||||
|
|
||||||
|
## 导出支持
|
||||||
|
|
||||||
|
> 按照数字键选择导出方式,<kbd>0</kbd> 为默认导出方式
|
||||||
|
|
||||||
|
0. [椰羊](https://cocogoat.work/achievement)
|
||||||
|
1. [胡桃工具箱](https://github.com/DGP-Studio/Snap.HuTao)
|
||||||
|
2. [Paimon.moe](https://paimon.moe/achievement/)
|
||||||
|
3. [Seelie.me](https://seelie.me/achievements)
|
||||||
|
4. 表格文件 `.csv`
|
||||||
|
5. [寻空](https://github.com/xunkong/xunkong)
|
||||||
|
6. [原魔工具箱](https://apps.apple.com/app/id1663989619)
|
||||||
|
7. [TeyvatGuide](https://github.com/BTMuli/TeyvatGuide)
|
||||||
|
8. [UIAF](https://uigf.org/standards/UIAF.html) JSON 文件
|
||||||
|
|
||||||
## 使用说明
|
## 使用说明
|
||||||
→ [Tutorial.md](Tutorial.md)
|
→ [Tutorial.md](Tutorial.md)
|
||||||
|
|
||||||
|
|||||||
15
README_EN.md
15
README_EN.md
@@ -13,9 +13,22 @@
|
|||||||
|
|
||||||
- Support for exporting all categories of achievements
|
- Support for exporting all categories of achievements
|
||||||
- Supports all versions of Genshin Impact
|
- Supports all versions of Genshin Impact
|
||||||
- Support for exporting to [Cocogoat](https://cocogoat.work/achievement), [Snap·HuTao](https://github.com/DGP-Studio/Snap.HuTao), [Paimon.moe](https://paimon.moe/achievement/), [Seelie.me](https://seelie.me/achievements)、[XunKong](https://github.com/xunkong/xunkong) and form files (csv)
|
|
||||||
- There are no requirements for window size, game language, etc.
|
- There are no requirements for window size, game language, etc.
|
||||||
|
|
||||||
|
## Export support
|
||||||
|
|
||||||
|
> Select the export method according to the number keys, <kbd>0</kbd> is the default export method
|
||||||
|
|
||||||
|
0. [Cocogoat](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. Form File `.csv`
|
||||||
|
5. [XunKong](https://github.com/xunkong/xunkong)
|
||||||
|
6. [YuanmoTools](https://apps.apple.com/app/id1663989619)
|
||||||
|
7. [TeyvatGuide](https://github.com/BTMuli/TeyvatGuide)
|
||||||
|
8. [UIAF](https://uigf.org/standards/UIAF.html) JSON file
|
||||||
|
|
||||||
## Instructions for Use:
|
## Instructions for Use:
|
||||||
→ [Tutorial_EN.md](Tutorial_EN.md)
|
→ [Tutorial_EN.md](Tutorial_EN.md)
|
||||||
|
|
||||||
|
|||||||
12
Tutorial.md
12
Tutorial.md
@@ -71,11 +71,11 @@
|
|||||||
### 各种工具的介绍烦请移步至各工具的官方页面进行查看(下方序号对应导出序号)
|
### 各种工具的介绍烦请移步至各工具的官方页面进行查看(下方序号对应导出序号)
|
||||||
|
|
||||||
0. [椰羊](https://cocogoat.work/achievement)
|
0. [椰羊](https://cocogoat.work/achievement)
|
||||||
|
1. [胡桃工具箱](https://github.com/DGP-Studio/Snap.HuTao)
|
||||||
1. [Snap·HuTao](https://github.com/DGP-Studio/Snap.HuTao)
|
|
||||||
|
|
||||||
2. [Paimon.moe](https://paimon.moe/achievement/)
|
2. [Paimon.moe](https://paimon.moe/achievement/)
|
||||||
|
|
||||||
3. [Seelie.me](https://seelie.me/achievements)
|
3. [Seelie.me](https://seelie.me/achievements)
|
||||||
|
4. ~~表格文件 `.csv`~~
|
||||||
4. [寻空](https://github.com/xunkong/xunkong)
|
5. [寻空](https://github.com/xunkong/xunkong)
|
||||||
|
6. [原魔工具箱](https://apps.apple.com/app/id1663989619)
|
||||||
|
7. [TeyvatGuide](https://github.com/BTMuli/TeyvatGuide)
|
||||||
|
8. [UIAF](https://uigf.org/standards/UIAF.html) JSON 文件
|
||||||
|
|||||||
@@ -65,9 +65,12 @@ At this time, you can select the Achievements in the left column to view the imp
|
|||||||
|
|
||||||
### For the introduction of different tools, please visit the official page of each tool to see:
|
### For the introduction of different tools, please visit the official page of each tool to see:
|
||||||
|
|
||||||
1. [Snap·HuTao](https://github.com/DGP-Studio/Snap.HuTao)
|
0. [Cocogoat](https://cocogoat.work/achievement)
|
||||||
|
1. [Snap HuTao](https://github.com/DGP-Studio/Snap.HuTao)
|
||||||
2. [Paimon.moe](https://paimon.moe/achievement/)
|
2. [Paimon.moe](https://paimon.moe/achievement/)
|
||||||
|
|
||||||
3. [Seelie.me](https://seelie.me/achievements)
|
3. [Seelie.me](https://seelie.me/achievements)
|
||||||
|
4. ~~Form File `.csv`~~
|
||||||
|
5. [XunKong](https://github.com/xunkong/xunkong)
|
||||||
|
6. [YuanmoTools](https://apps.apple.com/app/id1663989619)
|
||||||
|
7. [Teyvat Guide](https://github.com/BTMuli/TeyvatGuide)
|
||||||
|
8. [UIAF](https://uigf.org/standards/UIAF.html) JSON 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>
|
||||||
|
|||||||
@@ -110,12 +110,11 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\HookManager.h" />
|
<ClInclude Include="src\HookManager.h" />
|
||||||
<ClInclude Include="src\il2cpp-api-functions.h" />
|
|
||||||
<ClInclude Include="src\il2cpp-appdata.h" />
|
<ClInclude Include="src\il2cpp-appdata.h" />
|
||||||
<ClInclude Include="src\il2cpp-functions.h" />
|
<ClInclude Include="src\il2cpp-functions.h" />
|
||||||
|
<ClInclude Include="src\il2cpp-types-ptr.h" />
|
||||||
<ClInclude Include="src\il2cpp-types.h" />
|
<ClInclude Include="src\il2cpp-types.h" />
|
||||||
<ClInclude Include="src\il2cpp-init.h" />
|
<ClInclude Include="src\il2cpp-init.h" />
|
||||||
<ClInclude Include="src\il2cpp-unity-functions.h" />
|
|
||||||
<ClInclude Include="src\pch.h" />
|
<ClInclude Include="src\pch.h" />
|
||||||
<ClInclude Include="src\util.h" />
|
<ClInclude Include="src\util.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,70 +1,47 @@
|
|||||||
#include "pch.h"
|
// ReSharper disable CppCStyleCast
|
||||||
|
// ReSharper disable CppInconsistentNaming
|
||||||
|
// ReSharper disable CppClangTidyModernizeUseStdPrint
|
||||||
|
// ReSharper disable CppClangTidyClangDiagnosticCastAlign
|
||||||
|
// ReSharper disable CppClangTidyHicppMultiwayPathsCovered
|
||||||
|
// ReSharper disable CppDefaultCaseNotHandledInSwitchStatement
|
||||||
|
// ReSharper disable CppClangTidyClangDiagnosticCastFunctionTypeStrict
|
||||||
|
|
||||||
|
#include "pch.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "il2cpp-init.h"
|
#include "il2cpp-init.h"
|
||||||
|
|
||||||
using Genshin::ByteArray, Genshin::ClientKcpEvent, Genshin::KcpPacket, Genshin::KcpEventType;
|
using Genshin::ByteArray;
|
||||||
using std::to_string;
|
|
||||||
|
|
||||||
HWND unityWnd = nullptr;
|
HWND unityWnd = nullptr;
|
||||||
HANDLE hPipe = nullptr;
|
HANDLE hPipe = nullptr;
|
||||||
|
|
||||||
// Allow Protocol: GetPlayerTokenRsp, PlayerLoginRsp, AchievementAllDataNotify, PingRsp
|
|
||||||
std::set<UINT16> PacketWhitelist = { 1347, 4424, 20342, 25731 };
|
|
||||||
|
|
||||||
bool OnPacket(KcpPacket* pkt) {
|
|
||||||
if (pkt->data == nullptr) return true;
|
|
||||||
auto len = pkt->length;
|
|
||||||
auto data = (ByteArray*)new BYTE[len + 32];
|
|
||||||
data->max_length = len;
|
|
||||||
memcpy(data->vector, pkt->data, len);
|
|
||||||
Genshin::XorEncrypt(&data, len, nullptr);
|
|
||||||
if (ReadMapped<UINT16>(data->vector, 0) != 0x4567) {
|
|
||||||
delete[] data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!PacketWhitelist.contains(ReadMapped<UINT16>(data->vector, 2))) {
|
|
||||||
//ifdef _DEBUG
|
|
||||||
printf("Blocked cmdid: %d\n", ReadMapped<UINT16>(data->vector, 2));
|
|
||||||
//endif
|
|
||||||
delete[] data;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
printf("Passed cmdid: %d\n", ReadMapped<UINT16>(data->vector, 2));
|
|
||||||
if (ReadMapped<UINT16>(data->vector, 2) == 20342) {
|
|
||||||
const auto headLength = ReadMapped<UINT16>(data->vector, 4);
|
|
||||||
const auto dataLength = ReadMapped<UINT32>(data->vector, 6);
|
|
||||||
const auto cStr = base64_encode(data->vector + 10 + headLength, dataLength) + "\n";
|
|
||||||
WriteFile(hPipe, cStr.c_str(), cStr.length(), nullptr, nullptr);
|
|
||||||
CloseHandle(hPipe);
|
|
||||||
auto manager = Genshin::GetSingletonInstance(Genshin::GetSingletonManager(), il2cpp_string_new("GameManager"));
|
|
||||||
Genshin::ForceQuit(manager);
|
|
||||||
}
|
|
||||||
delete[] data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string checksum;
|
std::string checksum;
|
||||||
|
|
||||||
namespace Hook {
|
namespace Hook {
|
||||||
|
|
||||||
void SetVersion(void* obj, Il2CppString* value, void* method) {
|
ByteArray* UnityEngine_RecordUserData(const INT type) {
|
||||||
const auto version = ToString(value);
|
if (type == 0) {
|
||||||
value = string_new(version + " YaeAchievement");
|
const auto arr = new ByteArray {};
|
||||||
CALL_ORIGIN(SetVersion, obj, value, method);
|
const auto len = checksum.length();
|
||||||
}
|
arr->max_length = len;
|
||||||
|
memcpy(&arr->vector[0], checksum.data(), len);
|
||||||
bool KcpRecv(void* client, ClientKcpEvent* evt, void* method) {
|
return arr;
|
||||||
const auto result = CALL_ORIGIN(KcpRecv, client, evt, method);
|
|
||||||
if (result == 0 || evt->fields.type != KcpEventType::EventRecvMsg) {
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
return OnPacket(evt->fields.packet) ? result : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteArray* UnityEngine_RecordUserData(INT type) {
|
|
||||||
return new ByteArray {};
|
return new ByteArray {};
|
||||||
}
|
}
|
||||||
// 不再使用checksum(?
|
|
||||||
|
uint16_t BitConverter_ToUInt16(ByteArray* val, const int startIndex) {
|
||||||
|
const auto ret = CALL_ORIGIN(BitConverter_ToUInt16, val, startIndex);
|
||||||
|
if (ret == 0xAB89 && ReadMapped<UINT16>(val->vector, 2) == 20248) {
|
||||||
|
const auto headLength = ReadMapped<UINT16>(val->vector, 4);
|
||||||
|
const auto dataLength = ReadMapped<UINT32>(val->vector, 6);
|
||||||
|
const auto cStr = base64_encode(val->vector + 10 + headLength, dataLength) + "\n";
|
||||||
|
WriteFile(hPipe, cStr.c_str(), (DWORD) cStr.length(), nullptr, nullptr);
|
||||||
|
CloseHandle(hPipe);
|
||||||
|
ExitProcess(0);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run(HMODULE* phModule) {
|
void Run(HMODULE* phModule) {
|
||||||
@@ -76,8 +53,11 @@ void Run(HMODULE* phModule) {
|
|||||||
Sleep(5000);
|
Sleep(5000);
|
||||||
DisableVMProtect();
|
DisableVMProtect();
|
||||||
InitIL2CPP();
|
InitIL2CPP();
|
||||||
HookManager::install(Genshin::KcpRecv, Hook::KcpRecv);
|
for (int i = 0; i < 3; i++) {
|
||||||
HookManager::install(Genshin::SetVersion, Hook::SetVersion);
|
const auto result = Genshin::RecordUserData(i);
|
||||||
|
checksum += string(reinterpret_cast<char*>(&result->vector[0]), result->max_length);
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
DO_API(0x9D1AC0, 0x9CADC0, Il2CppString*, il2cpp_string_new, (const char* str));
|
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
|
// ReSharper disable CppClangTidyBugproneMacroParentheses
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "il2cpp-types.h"
|
#include "il2cpp-types.h"
|
||||||
|
|
||||||
// IL2CPP APIs
|
|
||||||
#define DO_API(ca, oa, r, n, p) extern r (*n) p
|
|
||||||
#include "il2cpp-api-functions.h"
|
|
||||||
#undef DO_API
|
|
||||||
|
|
||||||
// Application-specific functions
|
// Application-specific functions
|
||||||
#define DO_APP_FUNC(ca, oa, r, n, p) extern r (*n) p
|
#define DO_APP_FUNC(ca, oa, r, n, p) extern r (*n) p
|
||||||
|
#define DO_UNI_FUNC(ca, oa, r, n, p) extern r (*n) p
|
||||||
namespace Genshin {
|
namespace Genshin {
|
||||||
#include "il2cpp-functions.h"
|
#include "il2cpp-functions.h"
|
||||||
}
|
}
|
||||||
|
#undef DO_UNI_FUNC
|
||||||
#undef DO_APP_FUNC
|
#undef DO_APP_FUNC
|
||||||
|
|
||||||
#define DO_UNI_FUNC(ca, oa, r, n, p) extern r (*n) p
|
#define DO_TYPEDEF(ca, oa, n) extern n##__Class **n##__TypeInfo
|
||||||
namespace Genshin {
|
namespace Genshin {
|
||||||
#include "il2cpp-unity-functions.h"
|
#include "il2cpp-types-ptr.h"
|
||||||
}
|
}
|
||||||
#undef DO_UNI_FUNC
|
#undef DO_TYPEDEF
|
||||||
@@ -2,14 +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(0x258fd40, 0x2548e50, void, SetVersion, (void* obj, Il2CppString* value, void* method));
|
DO_APP_FUNC(0x569170, 0x568470, LPVOID, il2cpp_object_new, (LPVOID t));
|
||||||
|
|
||||||
DO_APP_FUNC(0x3220f00, 0x31c1650, void, XorEncrypt, (ByteArray** data, int length, void* method));
|
DO_APP_FUNC(0x06C43A80, 0x06775280, ByteArray*, RecordUserData, (int32_t nType));
|
||||||
|
|
||||||
DO_APP_FUNC(0x12f5df0, 0x12ddd80, bool, KcpRecv, (void* client, ClientKcpEvent* evt, void* method));
|
DO_APP_FUNC(0x0C87B240, 0x0C89EFB0, uint16_t, BitConverter_ToUInt16, (ByteArray* val, int startIndex));
|
||||||
|
|
||||||
DO_APP_FUNC(0x264ee90, 0x2606720, VOID, ForceQuit, (LPVOID obj));
|
DO_UNI_FUNC(0x105560, 0x105560, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));
|
||||||
|
|
||||||
DO_APP_FUNC(0x624d630, 0x61bd630, LPVOID, GetSingletonManager, ());
|
|
||||||
|
|
||||||
DO_APP_FUNC(0x624d360, 0x61bd360, LPVOID, GetSingletonInstance, (LPVOID obj, Il2CppString* value));
|
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
|
// ReSharper disable CppClangTidyBugproneMacroParentheses
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
|
||||||
#include "il2cpp-init.h"
|
#include "il2cpp-init.h"
|
||||||
|
|
||||||
#define DO_API(ca, oa, r, n, p) r (*n) p
|
|
||||||
#include "il2cpp-api-functions.h"
|
|
||||||
#undef DO_API
|
|
||||||
|
|
||||||
#define DO_APP_FUNC(ca, oa, r, n, p) r (*n) p
|
#define DO_APP_FUNC(ca, oa, r, n, p) r (*n) p
|
||||||
|
#define DO_UNI_FUNC(ca, oa, r, n, p) r (*n) p
|
||||||
namespace Genshin {
|
namespace Genshin {
|
||||||
#include "il2cpp-functions.h"
|
#include "il2cpp-functions.h"
|
||||||
}
|
}
|
||||||
|
#undef DO_UNI_FUNC
|
||||||
#undef DO_APP_FUNC
|
#undef DO_APP_FUNC
|
||||||
|
|
||||||
#define DO_UNI_FUNC(ca, oa, r, n, p) r (*n) p
|
#define DO_TYPEDEF(ca, oa, n) n##__Class **n##__TypeInfo
|
||||||
namespace Genshin {
|
namespace Genshin {
|
||||||
#include "il2cpp-unity-functions.h"
|
#include "il2cpp-types-ptr.h"
|
||||||
}
|
}
|
||||||
#undef DO_UNI_FUNC
|
#undef DO_TYPEDEF
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
@@ -27,13 +27,12 @@ void InitIL2CPP() {
|
|||||||
auto hBase = GetModuleHandle("UserAssembly.dll");
|
auto hBase = GetModuleHandle("UserAssembly.dll");
|
||||||
auto bAddr = (UINT64)hBase;
|
auto bAddr = (UINT64)hBase;
|
||||||
auto cAddr = (UINT64)GetModuleHandle("UnityPlayer.dll");
|
auto cAddr = (UINT64)GetModuleHandle("UnityPlayer.dll");
|
||||||
#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))
|
#define DO_APP_FUNC(ca, oa, r, n, p) n = (r (*) p)(bAddr + (isCN ? ca : oa))
|
||||||
#include "il2cpp-functions.h"
|
|
||||||
#undef DO_APP_FUNC
|
|
||||||
#define DO_UNI_FUNC(ca, oa, r, n, p) n = (r (*) p)(cAddr + (isCN ? ca : oa))
|
#define DO_UNI_FUNC(ca, oa, r, n, p) n = (r (*) p)(cAddr + (isCN ? ca : oa))
|
||||||
#include "il2cpp-unity-functions.h"
|
#include "il2cpp-functions.h"
|
||||||
#undef DO_UNI_FUNC
|
#undef DO_UNI_FUNC
|
||||||
|
#undef DO_APP_FUNC
|
||||||
|
#define DO_TYPEDEF(ca, oa, n) n##__TypeInfo = (n##__Class **)(bAddr + (isCN ? ca : oa))
|
||||||
|
#include "il2cpp-types-ptr.h"
|
||||||
|
#undef DO_TYPEDEF
|
||||||
}
|
}
|
||||||
|
|||||||
0
lib/src/il2cpp-types-ptr.h
Normal file
0
lib/src/il2cpp-types-ptr.h
Normal file
@@ -1,3 +1,6 @@
|
|||||||
|
// ReSharper disable CppClangTidyClangDiagnosticReservedIdentifier
|
||||||
|
// ReSharper disable CppClangTidyBugproneReservedIdentifier
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#pragma region IL2CPPInternalTypes
|
#pragma region IL2CPPInternalTypes
|
||||||
@@ -36,30 +39,7 @@ namespace Genshin {
|
|||||||
il2cpp_array_size_t max_length;
|
il2cpp_array_size_t max_length;
|
||||||
uint8_t vector[32];
|
uint8_t vector[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KcpPacket {
|
struct CodedOutputStream__Class {
|
||||||
BYTE* data;
|
|
||||||
UINT32 length;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class KcpEventType : int {
|
|
||||||
EventNotSet = -1,
|
|
||||||
EventConnect = 0,
|
|
||||||
EventConnectFailed = 1,
|
|
||||||
EventDisconnect = 2,
|
|
||||||
EventRecvMsg = 3,
|
|
||||||
EventCount = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct KcpEvent_Fields {
|
|
||||||
KcpEventType type;
|
|
||||||
UINT32 token;
|
|
||||||
UINT32 data;
|
|
||||||
KcpPacket* packet;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ClientKcpEvent {
|
|
||||||
KcpEvent_Fields fields;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
using namespace Genshin;
|
|
||||||
|
|
||||||
DO_UNI_FUNC(0x103420, 0x103420, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));
|
|
||||||
@@ -8,9 +8,6 @@ HWND FindMainWindowByPID(DWORD pid);
|
|||||||
string ToString(Il2CppString* str, UINT codePage = CP_ACP);
|
string ToString(Il2CppString* str, UINT codePage = CP_ACP);
|
||||||
std::string base64_encode(BYTE const* buf, unsigned int bufLen);
|
std::string base64_encode(BYTE const* buf, unsigned int bufLen);
|
||||||
|
|
||||||
#define cstring_new(str) il2cpp_string_new(str)
|
|
||||||
#define string_new(str) cstring_new((str).c_str())
|
|
||||||
|
|
||||||
#define ErrorDialogT(title, msg) MessageBox(unityWnd, msg, title, MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
|
#define ErrorDialogT(title, msg) MessageBox(unityWnd, msg, title, MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
|
||||||
#define ErrorDialog(msg) ErrorDialogT("YaeAchievement", msg)
|
#define ErrorDialog(msg) ErrorDialogT("YaeAchievement", msg)
|
||||||
#define Win32ErrorDialog(code) ErrorDialogT("YaeAchievement", ("CRITICAL ERROR!\nError code: " + std::to_string(GetLastError()) + "-"#code"\n\nPlease take the screenshot and contact developer by GitHub Issue to solve this problem\nNOT MIHOYO/COGNOSPHERE CUSTOMER SERVICE!").c_str())
|
#define Win32ErrorDialog(code) ErrorDialogT("YaeAchievement", ("CRITICAL ERROR!\nError code: " + std::to_string(GetLastError()) + "-"#code"\n\nPlease take the screenshot and contact developer by GitHub Issue to solve this problem\nNOT MIHOYO/COGNOSPHERE CUSTOMER SERVICE!").c_str())
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ message Achievement {
|
|||||||
FINISHED = 2;
|
FINISHED = 2;
|
||||||
REWARD_TAKEN = 3;
|
REWARD_TAKEN = 3;
|
||||||
}
|
}
|
||||||
uint32 timestamp = 3;
|
uint32 timestamp = 14;
|
||||||
uint32 current = 14;
|
uint32 current = 13;
|
||||||
uint32 total = 8;
|
uint32 total = 9;
|
||||||
uint32 id = 1;
|
uint32 id = 7;
|
||||||
Status status = 13;
|
Status status = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message AchievementAllDataNotify {
|
message AchievementAllDataNotify {
|
||||||
repeated Achievement list = 2;
|
repeated Achievement list = 15;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/AppCenterSDK/Models/Serialization/Attributes.cs
Normal file
8
src/AppCenterSDK/Models/Serialization/Attributes.cs
Normal 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;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = 41;
|
public const uint AppVersionCode = 45;
|
||||||
public const string AppVersionName = "3.1";
|
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";
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public static class Injector {
|
|||||||
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
|
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var lpStartAddress = pLoadLibrary.CreateDelegate<LPTHREAD_START_ROUTINE>();
|
var lpStartAddress = (delegate* unmanaged[Stdcall]<void*, uint>)pLoadLibrary.Value; //THREAD_START_ROUTINE
|
||||||
var hThread = Native.CreateRemoteThread(hProc, default, 0, lpStartAddress, pBase, 0);
|
var hThread = Native.CreateRemoteThread(hProc, default, 0, lpStartAddress, pBase, 0);
|
||||||
if (hThread.IsNull) {
|
if (hThread.IsNull) {
|
||||||
var e = new Win32Exception();
|
var e = new Win32Exception();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://aka.ms/CsWin32.schema.json",
|
"$schema": "https://aka.ms/CsWin32.schema.json",
|
||||||
"className": "Native",
|
"className": "Native",
|
||||||
"allowMarshaling": true,
|
"allowMarshaling": false,
|
||||||
"public": true
|
"public": true
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
CreateProcess
|
CloseClipboard
|
||||||
|
CreateProcess
|
||||||
|
CreateRemoteThread
|
||||||
|
EmptyClipboard
|
||||||
|
GetConsoleMode
|
||||||
|
GetDC
|
||||||
|
GetDeviceCaps
|
||||||
GetModuleHandle
|
GetModuleHandle
|
||||||
GetProcAddress
|
GetProcAddress
|
||||||
VirtualAllocEx
|
|
||||||
WriteProcessMemory
|
|
||||||
CreateRemoteThread
|
|
||||||
VirtualFreeEx
|
|
||||||
WaitForSingleObject
|
|
||||||
OpenClipboard
|
|
||||||
EmptyClipboard
|
|
||||||
GlobalLock
|
|
||||||
SetClipboardData
|
|
||||||
GlobalUnlock
|
|
||||||
CloseClipboard
|
|
||||||
GetStdHandle
|
GetStdHandle
|
||||||
GetConsoleMode
|
GlobalLock
|
||||||
|
GlobalUnlock
|
||||||
|
OpenClipboard
|
||||||
|
ResumeThread
|
||||||
|
SetClipboardData
|
||||||
SetConsoleMode
|
SetConsoleMode
|
||||||
TerminateProcess
|
TerminateProcess
|
||||||
ResumeThread
|
VirtualAllocEx
|
||||||
GetDeviceCaps
|
VirtualFreeEx
|
||||||
GetDC
|
WaitForSingleObject
|
||||||
|
WriteProcessMemory
|
||||||
@@ -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;
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user