25 Commits
2.9.0 ... 3.3.0

Author SHA1 Message Date
HolographicHat
2210a97d61 4.3 2023-12-24 23:59:24 +08:00
HolographicHat
feb7ac44da 4.2 2023-11-09 21:39:05 +08:00
HolographicHat
3924129560 Merge pull request #74 from Lightczx/master
Disable marshalling
2023-10-30 14:04:24 +08:00
Lightczx
4f7f0cdfd2 disable marshalling 2023-10-30 13:51:01 +08:00
HolographicHat
cf0753c676 Merge pull request #73 from BTMuli/master
🐛 修复 TeyvatGuide 链接错误
2023-10-16 13:42:22 +08:00
BTMuli
0b895d47ca 🐛 修复 TeyvatGuide 链接错误 2023-10-16 12:39:32 +08:00
HolographicHat
78d2722e20 Merge pull request #72 from BTMuli/master
更新文档
2023-10-15 01:16:19 +08:00
BTMuli
385c673323 🚨 revert,删除多余空格 2023-10-15 00:31:18 +08:00
BTMuli
50beb2cce7 🚨 修复 CI 报错 2023-10-15 00:18:39 +08:00
BTMuli
324a4153e0 📝 删除混入其中的表格文件 2023-10-14 23:56:24 +08:00
BTMuli
3de459aceb 📝 更新部分信息 2023-10-14 23:54:49 +08:00
BTMuli
295bb89177 📝 更新导出说明 2023-10-14 23:50:31 +08:00
HolographicHat
baaf4e8227 rollback 2023-10-13 21:22:54 +08:00
HolographicHat
f41fe6fb12 4.1
* #71
2023-09-28 18:48:00 +08:00
HolographicHat
78bda3f49c Merge pull request #70 from BTMuli/master
#67
2023-09-23 00:00:30 +08:00
BTMuli
a10dc22461 🎨 修正检测方式 2023-09-22 23:39:37 +08:00
HolographicHat
74dda750ef Merge pull request #69 from Masterain98/master
Update GitLab CI configuration
2023-09-22 21:15:21 +08:00
Masterain
099270ad29 Update .gitlab-ci.yml 2023-09-21 23:42:47 -07:00
Masterain
fe5b2c0c12 Update .gitlab-ci.yml 2023-09-21 23:35:17 -07:00
HolographicHat
ed5d99745c Merge pull request #68 from Masterain98/master
Create GitLab CI Config File
2023-09-21 23:46:58 +08:00
Masterain
7175cd7427 Create .gitlab-ci.yml 2023-09-21 00:01:13 -07:00
HolographicHat
73747bcce5 #67 2023-09-19 22:28:58 +08:00
HolographicHat
b12c3209d7 fix ci 2023-08-27 11:39:40 +08:00
HolographicHat
5805070627 4.0.1 (fix #64) 2023-08-24 00:16:44 +08:00
HolographicHat
811daba164 4.0 2023-08-16 20:00:06 +08:00
27 changed files with 318 additions and 2551 deletions

View File

@@ -20,7 +20,7 @@ jobs:
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --no-restore
run: dotnet build -c Release --no-restore
- name: Publish
run: dotnet publish --property:OutputPath=.\publish\
- name: Upload artifact

64
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,64 @@
stages:
- test
- build
- release
Test:
stage: test
image: mcr.microsoft.com/windows/server
tags:
- windows
script:
- dotnet restore
- dotnet build -c Release --no-restore
- dotnet publish --property:OutputPath=.\publish\
- Move-Item -Path .\publish\publish\*.exe -Destination ..\ -Force
Build:
stage: build
only:
- tags
tags:
- windows
needs:
- job: Test
script:
- echo "This is build stage."
- Move-Item -Path ..\YaeAchievement.exe .\ -Force
after_script:
- echo "Current Job ID is $CI_JOB_ID"
- echo "THIS_JOB_ID=$CI_JOB_ID" >> build.env
artifacts:
paths:
- .\*.exe
expire_in: 90 days
reports:
dotenv: build.env
release:
stage: release
image: registry.gitlab.com/gitlab-org/release-cli:latest
only:
- tags
needs:
- job: Build
artifacts: true
variables:
TAG: '$CI_COMMIT_TAG'
script:
- echo "Create Release $TAG"
- echo "$THIS_JOB_ID"
release:
name: '$TAG'
tag_name: '$TAG'
ref: '$TAG'
description: 'Release $TAG by CI'
assets:
links:
- name: "YaeAchievement.exe"
url: "https://$CI_SERVER_SHELL_SSH_HOST/$CI_PROJECT_PATH/-/jobs/$THIS_JOB_ID/artifacts/raw/YaeAchievement.exe?inline=false"
link_type: package
- name: ".NET 7.0 Desktop Runtime"
url: "https://dotnet.microsoft.com/zh-cn/download/dotnet/thank-you/runtime-desktop-7.0.11-windows-x64-installer"
link_type: other

View File

@@ -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)

View File

@@ -13,9 +13,22 @@
- Support for exporting all categories of achievements
- 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.
## 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:
→ [Tutorial_EN.md](Tutorial_EN.md)

View File

@@ -71,11 +71,11 @@
### 各种工具的介绍烦请移步至各工具的官方页面进行查看(下方序号对应导出序号)
0. [椰羊](https://cocogoat.work/achievement)
1. [Snap·HuTao](https://github.com/DGP-Studio/Snap.HuTao)
1. [胡桃工具箱](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)
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 文件

View File

@@ -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:
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/)
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

View File

@@ -110,12 +110,11 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="src\HookManager.h" />
<ClInclude Include="src\il2cpp-api-functions.h" />
<ClInclude Include="src\il2cpp-appdata.h" />
<ClInclude Include="src\il2cpp-functions.h" />
<ClInclude Include="src\il2cpp-types-ptr.h" />
<ClInclude Include="src\il2cpp-types.h" />
<ClInclude Include="src\il2cpp-init.h" />
<ClInclude Include="src\il2cpp-unity-functions.h" />
<ClInclude Include="src\pch.h" />
<ClInclude Include="src\util.h" />
</ItemGroup>

View File

@@ -1,106 +1,63 @@
#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 "il2cpp-init.h"
using Genshin::ByteArray, Genshin::ClientKcpEvent, Genshin::KcpPacket, Genshin::KcpEventType;
using std::to_string;
using Genshin::ByteArray;
HWND unityWnd = nullptr;
HANDLE hPipe = nullptr;
// Allow Protocol: GetPlayerToken, PlayerLogin, AchievementAllDataNotify, Ping, PlayerForceExit
std::set<UINT16> PacketWhitelist = { 6929, 7187, 4356, 6011, 1268, 24845, 24404, 29313 };
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) == 1268) {
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 = ToString(iStr) + "\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;
namespace Hook {
int KcpSend(void* client, KcpPacket* pkt, void* method) {
return OnPacket(pkt) ? CALL_ORIGIN(KcpSend, client, pkt, method) : 0;
}
void SetVersion(void* obj, Il2CppString* value, void* method) {
auto version = ToString(value);
value = string_new(version + " YaeAchievement");
CALL_ORIGIN(SetVersion, obj, value, method);
}
bool KcpRecv(void* client, ClientKcpEvent* evt, void* method) {
auto result = CALL_ORIGIN(KcpRecv, client, evt, method);
if (result == 0 || evt->fields.type != KcpEventType::EventRecvMsg) {
return result;
ByteArray* UnityEngine_RecordUserData(const INT type) {
if (type == 0) {
const auto arr = new ByteArray {};
const auto len = checksum.length();
arr->max_length = len;
memcpy(&arr->vector[0], checksum.data(), len);
return arr;
}
return OnPacket(evt->fields.packet) ? result : false;
return new ByteArray {};
}
ByteArray* UnityEngine_RecordUserData(INT type) {
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);
void OnAchievementAllDataNotify(LPVOID obj, const LPVOID ntf) {
const auto cos = Genshin::il2cpp_object_new(*Genshin::CodedOutputStream__TypeInfo);
const auto len = Genshin::CalculateSize(ntf);
const auto buf = (ByteArray*) new uint8_t[0x20 + len] {};
buf->max_length = len;
Genshin::CodedOutputStreamInit(cos, buf, 0, len);
Genshin::ProtoWriteTo(ntf, cos);
const auto str = base64_encode(buf->vector, len) + "\n";
WriteFile(hPipe, str.c_str(), (DWORD) str.length(), nullptr, nullptr);
CloseHandle(hPipe);
ExitProcess(0);
}
}
void Run(HMODULE* phModule) {
//AllocConsole();
//freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
while (
GetModuleHandle("UserAssembly.dll") == nullptr ||
(unityWnd = FindMainWindowByPID(GetCurrentProcessId())) == nullptr
) {
while ((unityWnd = FindMainWindowByPID(GetCurrentProcessId())) == nullptr) {
Sleep(1000);
}
Sleep(5000);
DisableVMProtect();
InitIL2CPP();
auto enc = Genshin::GetDefaultEncoding();
for (int i = 0; i < 3; i++) {
checksum += ToString(Genshin::GetString(enc, Genshin::RecordUserData(i)));
const auto result = Genshin::RecordUserData(i);
checksum += string(reinterpret_cast<char*>(&result->vector[0]), result->max_length);
}
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::OnAchievementAllDataNotify, Hook::OnAchievementAllDataNotify);
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) {

View File

@@ -1 +0,0 @@
DO_API(0x941c20, 0x93e230, Il2CppString*, il2cpp_string_new, (const char* str));

View File

@@ -1,20 +1,19 @@
// ReSharper disable CppClangTidyBugproneMacroParentheses
#pragma once
#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
#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 {
#include "il2cpp-functions.h"
}
#undef DO_UNI_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 {
#include "il2cpp-unity-functions.h"
#include "il2cpp-types-ptr.h"
}
#undef DO_UNI_FUNC
#undef DO_TYPEDEF

View File

@@ -2,30 +2,16 @@ using namespace Genshin;
// DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...));
DO_APP_FUNC(0x728b850, 0x7247520, Il2CppString*, ToBase64String, (ByteArray* value, int offset, int length, void* method));
DO_APP_FUNC(0x4F1EF0, 0x545600, LPVOID, il2cpp_object_new, (LPVOID t));
DO_APP_FUNC(0x215d110, 0x214d7a0, void, SetVersion, (void* obj, Il2CppString* value, void* method));
DO_APP_FUNC(0x052818B0, 0x0529E520, ByteArray*, RecordUserData, (int32_t nType));
DO_APP_FUNC(0x7b4dc00, 0x7afe4e0, ByteArray*, RecordUserData, (int32_t nType));
DO_APP_FUNC(0x05DCBE60, 0x05DF2F40, void, OnAchievementAllDataNotify, (LPVOID obj, LPVOID ntf));
DO_APP_FUNC(0x166e5d0, 0x1662f60, void, XorEncrypt, (ByteArray** data, int length, void* method));
DO_APP_FUNC(0x043EC0B0, 0x043FA380, int, CalculateSize, (LPVOID obj));
DO_APP_FUNC(0xf71860, 0xf69870, int, KcpSend, (void* client, KcpPacket* pkt, void* method));
DO_APP_FUNC(0x043EBFF0, 0x043FA2C0, void, ProtoWriteTo, (LPVOID obj, LPVOID output));
DO_APP_FUNC(0x433e670, 0x4315590, bool, KcpRecv, (void* client, ClientKcpEvent* evt, void* method));
DO_APP_FUNC(0x06F08220, 0x06F3F280, void, CodedOutputStreamInit, (LPVOID obj, LPVOID buffer, int offset, int length));
DO_APP_FUNC(0x75627b0, 0x751a960, LPVOID, GetDefaultEncoding, ());
DO_APP_FUNC(0x7561ff0, 0x751a1c0, Il2CppString*, GetString, (LPVOID encoding, LPVOID bytes));
DO_APP_FUNC(0x7560d90, 0x7518f90, ByteArray*, GetBytes, (LPVOID encoding, LPVOID str));
DO_APP_FUNC(0x1349850, 0x13415f0, VOID, RequestLogin, (LPVOID obj, LPVOID token, UINT uid));
DO_APP_FUNC(0x11ab1d0, 0x3e9f710, VOID, SetChecksum, (LPVOID obj, Il2CppString* value));
DO_APP_FUNC(0xd4e730, 0xd49dd0, VOID, ForceQuit, (LPVOID obj));
DO_APP_FUNC(0x607fbf0, 0x6044870, LPVOID, GetSingletonManager, ());
DO_APP_FUNC(0x607f920, 0x60445a0, LPVOID, GetSingletonInstance, (LPVOID obj, Il2CppString* value));
DO_UNI_FUNC(0x105970, 0x105970, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));

View File

@@ -1,22 +1,22 @@
// ReSharper disable CppClangTidyBugproneMacroParentheses
#include "pch.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_UNI_FUNC(ca, oa, r, n, p) r (*n) p
namespace Genshin {
#include "il2cpp-functions.h"
}
#undef DO_UNI_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 {
#include "il2cpp-unity-functions.h"
#include "il2cpp-types-ptr.h"
}
#undef DO_UNI_FUNC
#undef DO_TYPEDEF
using std::string;
@@ -27,13 +27,12 @@ void InitIL2CPP() {
auto hBase = GetModuleHandle("UserAssembly.dll");
auto bAddr = (UINT64)hBase;
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))
#include "il2cpp-functions.h"
#undef DO_APP_FUNC
#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_APP_FUNC
#define DO_TYPEDEF(ca, oa, n) n##__TypeInfo = (n##__Class **)(bAddr + (isCN ? ca : oa))
#include "il2cpp-types-ptr.h"
#undef DO_TYPEDEF
}

View File

@@ -0,0 +1,2 @@
// LFGDACFKABF
DO_TYPEDEF(0x2965BA0, 0, CodedOutputStream);

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +0,0 @@
using namespace Genshin;
DO_UNI_FUNC(0x100560, 0x100560, ByteArray*, UnityEngine_RecordUserData, (int32_t nType));

View File

@@ -68,3 +68,38 @@ HWND FindMainWindowByPID(DWORD pid) {
}
#pragma endregion
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::string base64_encode(BYTE const* buf, unsigned int bufLen) {
std::string ret;
int i = 0;
BYTE char_array_3[3];
BYTE char_array_4[4];
while (bufLen--) {
char_array_3[i++] = *buf++;
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (i = 0; (i < 4); i++)
ret += base64_chars[char_array_4[i]];
i = 0;
}
}
if (i) {
int j;
for (j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for (j = 0; j < i + 1; j++)
ret += base64_chars[char_array_4[j]];
while (i++ < 3)
ret += '=';
}
return ret;
}

View File

@@ -6,9 +6,7 @@ VOID DisableVMProtect();
bool IsLittleEndian();
HWND FindMainWindowByPID(DWORD pid);
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())
std::string base64_encode(BYTE const* buf, unsigned int bufLen);
#define ErrorDialogT(title, msg) MessageBox(unityWnd, msg, title, MB_OK | MB_ICONERROR | MB_SYSTEMMODAL);
#define ErrorDialog(msg) ErrorDialogT("YaeAchievement", msg)

22
res/App.Designer.cs generated
View File

@@ -121,7 +121,9 @@ namespace YaeAchievement.res {
///[3] Seelie.me
///[4] Csv file
///[5] Xunkong
///Input a number (0-5): .
///[7] Teyvat Guide
///[8] UIAF JSON File
///Input a number (0-8): .
/// </summary>
internal static string ExportChoose {
get {
@@ -174,6 +176,24 @@ namespace YaeAchievement.res {
}
}
/// <summary>
/// Looks up a localized string similar to Please launch/update Teyvat Guide and retry..
/// </summary>
internal static string ExportToTauriFail {
get {
return ResourceManager.GetString("ExportToTauriFail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to Teyvat Guide..
/// </summary>
internal static string ExportToTauriSuccess {
get {
return ResourceManager.GetString("ExportToTauriSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to {0}.
/// </summary>

View File

@@ -32,7 +32,9 @@
[3] Seelie.me
[4] Csv file
[5] Xunkong
Input a number (0-5): </value>
[7] Teyvat Guide
[8] UIAF JSON File
Input a number (0-8): </value>
</data>
<data name="ExportToCocogoatSuccess" xml:space="preserve">
<value>Successfully exported to cocogoat.</value>
@@ -129,4 +131,10 @@ Input a number (0-5): </value>
<data name="NoWritePermission" xml:space="preserve">
<value>No write permission on {0}.</value>
</data>
<data name="ExportToTauriSuccess" xml:space="preserve">
<value>Successfully exported to Teyvat Guide.</value>
</data>
<data name="ExportToTauriFail" xml:space="preserve">
<value>Please launch/update Teyvat Guide and retry.</value>
</data>
</root>

View File

@@ -26,8 +26,9 @@
[4] 表格文件
[5] 寻空
[6] 原魔工具箱
[7] UIAF JSON 文件
输入一个数字 (0-7): </value>
[7] Teyvat Guide
[8] UIAF JSON 文件
输入一个数字 (0-8): </value>
</data>
<data name="ExportToCocogoatSuccess" xml:space="preserve">
<value>在浏览器内进行下一步操作</value>
@@ -115,9 +116,15 @@
<value>网络错误,请检查网络后重试 ({0}: {1})</value>
</data>
<data name="GenshinHashError" xml:space="preserve">
<value>请将原神更新至最新版本后重试</value>
<value>当前适配版本不匹配,请更新原神至最新版本后重试或等待工具更新。</value>
</data>
<data name="NoWritePermission" xml:space="preserve">
<value>无法写入文件,请更换软件所在目录后重试</value>
</data>
<data name="ExportToTauriFail" xml:space="preserve">
<value>启动 Teyvat Guide 或更新 Teyvat Guide 至最新版本后重试</value>
</data>
<data name="ExportToTauriSuccess" xml:space="preserve">
<value>在 Teyvat Guide 进行下一步操作</value>
</data>
</root>

View File

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

View File

@@ -32,8 +32,9 @@ public static class Export {
4 => ToCSV,
5 => ToXunkong,
6 => ToWxApp1,
7 => ToUIAFJson,
8 => ToRawJson,
7 => ToTeyvatGuide,
8 => ToUIAFJson,
9 => ToRawJson,
_ => ToCocogoat
})).Invoke(data);
}
@@ -77,19 +78,38 @@ public static class Export {
}
private static void ToHuTao(AchievementAllDataNotify data) {
if (CheckWinUIAppScheme("hutao"))
{
if (CheckWinUIAppScheme("hutao")) {
Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data)));
Utils.ShellOpen("hutao://achievement/import");
Console.WriteLine(App.ExportToSnapGenshinSuccess);
}
else
{
} else {
Console.WriteLine(App.ExportToSnapGenshinNeedUpdate);
Utils.ShellOpen("ms-windows-store://pdp/?productid=9PH4NXJ2JN52");
}
}
private static void ToXunkong(AchievementAllDataNotify data) {
if (CheckWinUIAppScheme("xunkong")) {
Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data)));
Utils.ShellOpen("xunkong://import-achievement?caller=YaeAchievement&from=clipboard");
Console.WriteLine(App.ExportToXunkongSuccess);
} else {
Console.WriteLine(App.ExportToXunkongNeedUpdate);
Utils.ShellOpen("ms-windows-store://pdp/?productid=9N2SVG0JMT12");
}
}
private static void ToTeyvatGuide(AchievementAllDataNotify data) {
if (Process.GetProcessesByName("TeyvatGuide").Any()) {
Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data)));
Utils.ShellOpen("teyvatguide://import_uigf?app=YaeAchievement");
Console.WriteLine(App.ExportToTauriSuccess);
} else {
Console.WriteLine(App.ExportToTauriFail);
Utils.ShellOpen("ms-windows-store://pdp/?productid=9NLBNNNBNSJN");
}
}
// ReSharper disable once InconsistentNaming
private static void ToUIAFJson(AchievementAllDataNotify data) {
var path = Path.GetFullPath($"uiaf-{DateTime.Now:yyyyMMddHHmmss}.json");
@@ -168,17 +188,6 @@ public static class Export {
}
}
private static void ToXunkong(AchievementAllDataNotify data) {
if (CheckWinUIAppScheme("xunkong")) {
Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data)));
Utils.ShellOpen("xunkong://import-achievement?caller=YaeAchievement&from=clipboard");
Console.WriteLine(App.ExportToXunkongSuccess);
} else {
Console.WriteLine(App.ExportToXunkongNeedUpdate);
Utils.ShellOpen("ms-windows-store://pdp/?productid=9N2SVG0JMT12");
}
}
private static void ToRawJson(AchievementAllDataNotify data) {
var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-raw.json");
var text = JsonSerializer.Serialize(data, new JsonSerializerOptions {

View File

@@ -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 = 39;
public const string AppVersionName = "2.9";
public const uint AppVersionCode = 43;
public const string AppVersionName = "3.3";
public const string PipeName = "YaeAchievementPipe";
public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com";

View File

@@ -45,7 +45,7 @@ public static class Injector {
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);
if (hThread.IsNull) {
var e = new Win32Exception();

View File

@@ -1,6 +1,6 @@
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"className": "Native",
"allowMarshaling": true,
"allowMarshaling": false,
"public": true
}

View File

@@ -1,21 +1,21 @@
CreateProcess
CloseClipboard
CreateProcess
CreateRemoteThread
EmptyClipboard
GetConsoleMode
GetDC
GetDeviceCaps
GetModuleHandle
GetProcAddress
VirtualAllocEx
WriteProcessMemory
CreateRemoteThread
VirtualFreeEx
WaitForSingleObject
OpenClipboard
EmptyClipboard
GlobalLock
SetClipboardData
GlobalUnlock
CloseClipboard
GetStdHandle
GetConsoleMode
GlobalLock
GlobalUnlock
OpenClipboard
ResumeThread
SetClipboardData
SetConsoleMode
TerminateProcess
ResumeThread
GetDeviceCaps
GetDC
VirtualAllocEx
VirtualFreeEx
WaitForSingleObject
WriteProcessMemory

View File

@@ -92,7 +92,7 @@ public static class Utils {
public static void CheckUpdate(bool useLocalLib) {
var info = UpdateInfo.Parser.ParseFrom(GetBucketFileAsByteArray("schicksal/version"))!;
if (GlobalVars.AppVersionCode != info.VersionCode) {
if (GlobalVars.AppVersionCode < info.VersionCode) {
Console.WriteLine(App.UpdateNewVersion, GlobalVars.AppVersionName, info.VersionName);
Console.WriteLine(App.UpdateDescription, info.Description);
if (info.EnableAutoDownload) {