135 Commits
2.0.0 ... 3.2.0

Author SHA1 Message Date
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
HolographicHat
849f379ca5 3.8 2023-07-06 14:31:55 +08:00
HolographicHat
29c57cbc1e Merge pull request #62 from Lightczx/master
Improve export experience for Snap Hutao
2023-06-29 21:30:58 +08:00
DismissedLight
8fdb10898a Improve export experience for Snap Hutao 2023-06-29 14:38:19 +08:00
HolographicHat
f4f1f14651 Merge pull request #61 from prpjzz/master
Add Readme_EN.md
2023-06-22 15:03:23 +08:00
prpjzz
390af6cd85 Update Tutorial_EN.md 2023-06-19 22:00:38 +07:00
prpjzz
a78f36dfa8 Update README_EN.md 2023-06-19 21:56:51 +07:00
prpjzz
e3d7152da2 Update Tutorial_EN.md 2023-06-19 21:14:20 +07:00
prpjzz
60a4dd04c4 Merge branch 'HolographicHat:master' into master 2023-06-19 18:49:45 +07:00
HolographicHat
69c402417b 3.7 2023-05-24 17:32:27 +08:00
prpjzz
d9034ec635 Update Tutorial_EN.md 2023-05-03 14:06:04 +07:00
prpjzz
f742cf37d5 Create Tutorial_EN.md 2023-05-03 13:27:26 +07:00
prpjzz
4136a1b0c4 Update README_EN.md 2023-05-03 13:26:38 +07:00
prpjzz
e039d2f944 Update README_EN.md 2023-05-03 13:26:21 +07:00
prpjzz
0e23a05a78 Update README_EN.md 2023-05-03 13:25:26 +07:00
prpjzz
5f5a0614a6 Update README_EN.md 2023-05-03 13:20:02 +07:00
HolographicHat
c60d3a3b82 v2.7 2023-04-12 12:28:03 +08:00
HolographicHat
58dcd5b228 Fix 2023-04-02 18:23:58 +08:00
HolographicHat
a72007ffa6 Merge remote-tracking branch 'origin/master' 2023-04-02 16:20:23 +08:00
HolographicHat
d3b9d10d01 #55 2023-04-02 16:17:11 +08:00
HolographicHat
69184fa59d Auto compile protos 2023-03-30 08:54:50 +08:00
HolographicHat
8473336b37 Update Tutorial.md 2023-03-01 20:57:42 +08:00
HolographicHat
ffc0854291 bump version to 2.6.0 2023-03-01 20:48:45 +08:00
HolographicHat
3b2b1fba49 fix ci 2023-02-28 19:59:46 +08:00
HolographicHat
c325b5f754 3.5 2023-02-28 19:16:51 +08:00
HolographicHat
8e2e438c96 fix ci 2023-02-27 20:01:23 +08:00
HolographicHat
9bc2cdb443 Update actions .net version 2023-02-27 19:47:06 +08:00
HolographicHat
826ed661cd Merge pull request #51 from Lightczx/master
Use Microsoft.Windows.CsWin32 to replace manual PInvoke
2023-02-27 19:45:11 +08:00
DismissedLight
5f8ff734f2 fixup native call 2023-02-26 14:41:24 +08:00
DismissedLight
50007c2c53 Use CsWin32 2023-02-26 13:46:03 +08:00
HolographicHat
7512c6fca2 Merge pull request #50 from peaceshi/master
open export dir.
2023-02-21 18:09:06 +08:00
peaceshi
2feae6ddb9 open export dir. 2023-02-20 18:13:05 +08:00
HolographicHat
52ae44f467 fix #49 2023-02-09 21:18:51 +08:00
HolographicHat
d93f6f92c0 Merge pull request #48 from xzm2000/patch-1
Update Tutorial.md
2023-01-25 22:52:54 +08:00
xzm2000
20b59eab7e Update Tutorial.md
update url
2023-01-25 11:23:51 +08:00
HolographicHat
0094b9b959 Update README.md 2023-01-19 15:08:33 +08:00
HolographicHat
24b68fbed1 Merge pull request #46 from Finchaos/patch-1
Create Tutorial.md
2023-01-19 15:04:04 +08:00
HolographicHat
397923d4ad Update and rename tutorial.md to Tutorial.md 2023-01-19 14:54:08 +08:00
Finchaos
0a3482e7b2 Create tutorial.md 2023-01-19 14:21:34 +08:00
HolographicHat
7ae18cfbf0 v2.5 2023-01-18 11:52:00 +08:00
HolographicHat
24cd49fa03 3.4 AchievementAllDataNotify 2023-01-18 02:54:42 +08:00
HolographicHat
f0dbb9162b Use 77.cocogoat.cn 2023-01-18 02:47:20 +08:00
HolographicHat
68ff9c5a25 3.4 native lib 2023-01-18 02:46:54 +08:00
HolographicHat
31b77a9fb3 fix empty result and bump version to 2.4.1 2022-12-07 23:36:18 +08:00
HolographicHat
d2d5bafcd6 v2.4 2022-12-07 13:02:22 +08:00
HolographicHat
e2f1f1e343 lib for 3.3 2022-12-07 12:13:27 +08:00
HolographicHat
349e15fe25 v2.3 2022-11-02 09:31:18 +08:00
HolographicHat
9e0d18910b improve user experience 2022-11-01 11:11:11 +08:00
HolographicHat
afee99fd3f native lib 3.2 2022-11-01 10:26:18 +08:00
HolographicHat
4dae8c52b6 Update actions/upload-artifact 2022-10-17 08:39:35 +08:00
HolographicHat
3294ac4b89 add try catch 2022-10-17 08:19:21 +08:00
HolographicHat
ccb19c832c ignore tmp file delete exception 2022-10-08 19:41:39 +08:00
HolographicHat
1207dd70b3 Add game executable hash check 2022-10-03 16:33:58 +08:00
HolographicHat
204f211249 bump version to 2.2.1 2022-10-02 13:20:18 +08:00
HolographicHat
043a861030 improve update 2022-10-02 13:19:54 +08:00
HolographicHat
09a9d4c22b fix crash 2022-10-02 00:39:45 +08:00
HolographicHat
9094b9c718 update 2022-10-01 20:03:03 +08:00
HolographicHat
d7ac18587a snapgenshin -> snaphutao 2022-09-29 21:03:44 +08:00
HolographicHat
82c5054002 bump version to 2.2 2022-09-28 11:13:43 +08:00
HolographicHat
553d67bff7 fix 2022-09-28 11:09:32 +08:00
HolographicHat
07a08f56d4 3.1 native lib 2022-09-27 19:02:13 +08:00
HolographicHat
656589bc80 add cmdline args 2022-09-27 18:16:52 +08:00
HolographicHat
9aaefe4cd7 snap.hutao 2022-09-27 16:58:46 +08:00
HolographicHat
d84571ba1c Fix and optimize game path detect 2022-09-25 22:36:29 +08:00
HolographicHat
9bc8d2473a improve Export.cs 2022-09-25 22:33:29 +08:00
HolographicHat
7b3e22c84f Fix path error 2022-09-25 21:04:18 +08:00
HolographicHat
faa583587a update dependencies 2022-09-25 13:34:30 +08:00
HolographicHat
37bfb93fa9 better exception message 2022-09-25 13:31:30 +08:00
HolographicHat
b88858d2dc Improve game path getter 2022-09-25 13:02:11 +08:00
HolographicHat
c2e3a3b13d auto install vcruntime 2022-09-25 12:29:10 +08:00
HolographicHat
78a29e9390 clear input buffer before select export way 2022-09-19 18:44:17 +08:00
HolographicHat
a76f03b035 Fix 2022-09-06 13:32:36 +08:00
HolographicHat
d814ece2de fix i18n 2022-09-04 19:02:06 +08:00
HolographicHat
9414ffbe12 Merge remote-tracking branch 'origin/master' 2022-09-02 20:24:21 +08:00
HolographicHat
251246fd74 Fix 2022-09-02 20:24:05 +08:00
HolographicHat
76785c5179 Update README_EN.md 2022-09-02 20:00:41 +08:00
HolographicHat
e086e14e8d Create build workflow 2022-09-02 19:50:41 +08:00
HolographicHat
29aa4fea2d Update csproj 2022-09-02 19:50:08 +08:00
HolographicHat
ffd75da2bf fix #31 2022-09-01 11:16:08 +08:00
HolographicHat
92e8cd8997 Merge remote-tracking branch 'origin/master' 2022-08-30 14:54:10 +08:00
HolographicHat
4b62901dbe UIAF update 2022-08-30 14:53:53 +08:00
HolographicHat
2216610413 Update Readme 2022-08-27 13:17:27 +00:00
HolographicHat
99b8db2a69 Merge pull request #26 from prpjzz/master
Update readme_en.md and make some changes to the original readme file
2022-08-27 20:41:27 +08:00
prpjzz
5b6e86459d Delete icon.png 2022-08-27 19:25:30 +07:00
prpjzz
bf46494b6b Update README.md 2022-08-27 19:24:58 +07:00
prpjzz
458a56a855 Create README_EN.md 2022-08-27 19:23:34 +07:00
prpjzz
ef21274cd2 Add files via upload 2022-08-27 19:22:52 +07:00
prpjzz
7528f4247b Add files via upload 2022-08-27 19:22:29 +07:00
HolographicHat
652b5afa80 Update README.md 2022-08-27 15:21:52 +08:00
HolographicHat
59a042019a Add en lang 2022-08-27 15:08:01 +08:00
HolographicHat
4e94d67d0b Bump version to 2.1 2022-08-24 17:03:06 +08:00
HolographicHat
7dafd95099 Merge remote-tracking branch 'origin/master' 2022-08-24 17:02:53 +08:00
HolographicHat
76c20407ea Update README.md 2022-08-23 00:00:33 +08:00
HolographicHat
b79b82ec10 Merge pull request #24 from xunkong/hat
Add Xunkong and adapt to UIAF 1.1
2022-08-22 23:59:59 +08:00
Scighost
07fe60a092 Add Xunkong and adapt to UIAF 1.1 2022-08-22 23:37:27 +08:00
HolographicHat
7fa2fbac25 3.0 offsets 2022-08-22 14:25:35 +08:00
HolographicHat
28ffa6fb1a UIAF 1.1 2022-08-21 12:10:47 +08:00
HolographicHat
4c2cb28313 add export 2022-08-21 12:06:50 +08:00
HolographicHat
2f1a5ad99e #23 2022-08-19 18:09:49 +08:00
HolographicHat
9b0c384d4b Add AppConfig 2022-08-19 18:09:30 +08:00
HolographicHat
b2111db4eb Implement #22 2022-08-15 23:36:23 +08:00
HolographicHat
2442264224 Add CacheFile 2022-08-15 23:35:29 +08:00
HolographicHat
b596cad02e Remove unused code 2022-08-15 23:34:47 +08:00
HolographicHat
30a0189f5e Merge remote-tracking branch 'origin/master' 2022-08-14 21:42:38 +08:00
HolographicHat
f47fd234b4 add vcruntime check 2022-08-14 21:42:21 +08:00
HolographicHat
7d306a60c9 Update README.md 2022-08-14 21:28:30 +08:00
HolographicHat
10dd03335f lib update 2022-08-12 23:34:04 +08:00
HolographicHat
41863c32f7 optimize 2022-07-16 01:41:11 +08:00
HolographicHat
4c3e9d8e50 Fix os2.8 crash 2022-07-15 23:02:00 +08:00
HolographicHat
9d60cda4c7 Merge pull request #19 from huiyadanli/master
Add feat: get game path from registry (YuanShen.exe)
2022-07-15 22:03:55 +08:00
huiyadanli
e0c836e55d Add feat: get game path from registry (YuanShen.exe) 2022-07-15 21:51:36 +08:00
HolographicHat
02b4d9df0b Update README.md 2022-07-15 16:34:36 +08:00
53 changed files with 1900 additions and 5396 deletions

30
.github/workflows/dotnet.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
name: .NET Build
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Setup .NET
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build -c Release --no-restore
- name: Publish
run: dotnet publish --property:OutputPath=.\publish\
- name: Upload artifact
uses: actions/upload-artifact@v3.1.0
with:
name: Artifacts
path: publish

9
.gitignore vendored
View File

@@ -4,3 +4,12 @@ obj/
riderModule.iml
/_ReSharper.Caches/
.idea
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
.vs/
src/Proto/*

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

@@ -1,7 +1,42 @@
<div align="center">
<div align="center"><img width="100" src="https://github.com/HolographicHat/YaeAchievement/blob/master/icon.ico">
# YaeAchievement
![GitHub](https://img.shields.io/badge/License-GPL--3.0-brightgreen?style=flat-square) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/HolographicHat/genshin-achievement-export?color=brightgreen&label=Release&style=flat-square) ![GitHub issues](https://img.shields.io/github/issues/HolographicHat/genshin-achievement-export?label=Issues&style=flat-square) ![Downloads](https://img.shields.io/github/downloads/HolographicHat/genshin-achievement-export/total?color=brightgreen&label=Downloads&style=flat-square) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)
![GitHub](https://img.shields.io/badge/License-GPL--3.0-brightgreen?style=flat-square) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/HolographicHat/YaeAchievement?color=brightgreen&label=Release&style=flat-square) ![GitHub issues](https://img.shields.io/github/issues/HolographicHat/YaeAchievement?label=Issues&style=flat-square) ![Downloads](https://img.shields.io/github/downloads/HolographicHat/YaeAchievement/total?color=brightgreen&label=Downloads&style=flat-square) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)
简体中文 | [English](README_EN.md)
</div>
- 支持导出所有类别的成就
- 支持官服,渠道服与国际服
- 没有窗口大小、游戏语言等要求
## 导出支持
> 按照数字键选择导出方式,<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)
## 下载地址
[releases/latest](https://github.com/HolographicHat/YaeAchievement/releases/latest)
## 问题反馈
[issues](https://github.com/HolographicHat/YaeAchievement/issues)或[QQ群: 913777414](https://qm.qq.com/cgi-bin/qm/qr?k=9UGz-chQVTjZa4b82RA_A41vIcBVNpms&jump_from=webapi)
## 常见问题
0. Q: 打不开
A: 安装 [.NET Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-7.0.3-windows-x64-installer)
1. Q: 原神启动时报错: 数据异常(31-4302)
A: 不要把软件和原神主程序放一起

47
README_EN.md Normal file
View File

@@ -0,0 +1,47 @@
<div align="center"><img width="100" src="https://github.com/HolographicHat/YaeAchievement/blob/master/icon.ico">
# YaeAchievement
![GitHub](https://img.shields.io/badge/License-GPL--3.0-brightgreen?style=flat-square) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/HolographicHat/YaeAchievement?color=brightgreen&label=Release&style=flat-square) ![GitHub issues](https://img.shields.io/github/issues/HolographicHat/YaeAchievement?label=Issues&style=flat-square) ![Downloads](https://img.shields.io/github/downloads/HolographicHat/YaeAchievement/total?color=brightgreen&label=Downloads&style=flat-square) ![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)
[简体中文](README.md) | English
**I18n support currently in [snapshot version](https://github.com/HolographicHat/YaeAchievement/actions/)**
**Next release: 2022/09/28 (Genshin 3.1)**
</div>
- Support for exporting all categories of achievements
- Supports all versions of Genshin Impact
- 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)
## Download: [Here](https://github.com/HolographicHat/YaeAchievement/releases/latest)
## Feedback or Problem?
[issues](https://github.com/HolographicHat/YaeAchievement/issues) or [QQ群: 913777414](https://qm.qq.com/cgi-bin/qm/qr?k=9UGz-chQVTjZa4b82RA_A41vIcBVNpms&jump_from=webapi)
## Frequently asked questions
0. Q: Unable to start
A: Download and install [.NET Runtime 7](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-7.0.7-windows-x64-installer) or ` winget install Microsoft.DotNet.Runtime.7`
1. Q: Error while Genshin started: Data Exception (31-4302)
A: Don't place software in the directory containing Genshin Impact.

81
Tutorial.md Normal file
View File

@@ -0,0 +1,81 @@
## 使用说明
1.选择正确的下载文件以2.4.1版本为例):
点击该网址https://github.com/HolographicHat/YaeAchievement/releases
点击图中红框圈中的名称为“YaeAchievement.exe”的文件浏览器会自动弹出下载。建议将该文件保存在桌面或者其它易于寻找的文件夹内。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/1.png)
2.安装启动软件所需文件(若已安装该运行时可忽略此步骤)
点击该网址https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-7.0.3-windows-x64-installer 。
进入网页后浏览器会自动弹出下载,同样地,将文件保存在桌面或者其它易于寻找的文件夹内。
下载完成后打开名称形如dotnet-runtime-x.x.x-win-x64.exe的文件会弹出安装窗口如下图所示。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/2.png)
直接点击安装即可。
3.打开主程序所需的操作以及成就导出的选择
双击在第一步下载的名称为“YaeAchievement.exe”的文件成功打开后会提示原神正在启动如下图所示。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/3.png)
原神启动完成后,点击进入游戏即可。
点击进入游戏后原神闪退,工具会提示您选择导出至何种工具,如下图所示。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/4.png)
此时可根据自己的需要进行选择,一般推荐导出至[0]椰羊以及[4]表格文件(.csv
选择完毕后各工具导出页面如下:
#### 椰羊:
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/5.png)
#### Snap.Hutao
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main//images/6.png)
#### Seelie.me
此时YaeAchievement会提示成就数据已导出。请在保存YaeAchievement的文件夹内找到名称形如export-20xxxxxxxxxxxx-seelie.json的文件。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/7.png)
然后点击该网址https://seelie.me/settings, 进入网页后选择导入,如下图所示。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/8.png)
点击导入后选中名称形如export-20xxxxxxxxxxxx-seelie.json的文件如下图所示。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/9.png)
当弹出如下图所示的提示时表示导入成功。
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/10.png)
此时可选择左栏成就,查看导入的成就数据。
#### 寻空:
![image](https://github.com/Finchaos/yae-markdown-230119/blob/main/images/11.png)
### 各种工具的介绍烦请移步至各工具的官方页面进行查看(下方序号对应导出序号)
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 文件

76
Tutorial_EN.md Normal file
View File

@@ -0,0 +1,76 @@
## Instructions for Use
1.Download YaeAchievementLatest Version
Click Herehttps://github.com/HolographicHat/YaeAchievement/releases
Click on the file named "YaeAchievement.exe" in the red box to automatically pop up and download.It is recommended that you save this file in a desktop or other easy-to-see folder.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide1.png)
2.Install .NET Runtime 7 (this step can be ignored if the runtime is already installed)
Click Herehttps://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-7.0.7-windows-x64-installer .
Or `winget install Microsoft.DotNet.Runtime.7` if you use Windows 11 or have Winget installed.
The browser automatically pops up and downloads when you enter the web page, as well as saving files in a desktop or other easy-to-see folder.
When you open a file with the name dotnet-runtime-x.x.x-win-x64.exe after the download is complete, an installation window pops up, as shown below.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide2.png)
Just click Install.
3.The actions required to open the main program and the options for the achievement export
Double-click the file named "YaeAchievement.exe" downloaded in the first step to open it successfully, indicating that the original god is starting, as shown below.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide3.png)
Once the primordial startup is complete, click to enter the game.
When you click into the game, the tool prompts you to choose which tool to export, as shown below.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide4.png)
For global user, you should select [3] Seelie.me or [4] Export to csv file。
After selecting, each page exports the tool as follows:
#### Snap.Hutao
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide5.png)
#### Seelie.me
At this point, Yae Achievement will remind that performance data has been exported. Please find the file named export-20xxxxxxxxxxxx-seelie.json in the Yae Achievement save directory.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide6.png)
Then click on the URL: https://seelie.me/settings, enter the website and select Import Account, as illustrated in the figure below.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide7.png)
After clicking Import, select a file named export-20xxxxxxxxxxxx-seelie.json, as shown in the figure below.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide8.png)
When the prompt as shown in the image below pops up, the import process succeeds.
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide9.png)
At this time, you can select the Achievements in the left column to view the imported performance data.
### For the introduction of different tools, please visit the official page of each tool to see:
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

@@ -1,20 +1,63 @@
<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>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<ApplicationManifest>res\app.manifest</ApplicationManifest>
<AssemblyVersion>2.0.0</AssemblyVersion>
<FileVersion>2.0.0</FileVersion>
<ApplicationIcon>icon.ico</ApplicationIcon>
<DebugType>embedded</DebugType>
<SelfContained>false</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
<PublishReadyToRun>true</PublishReadyToRun>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Protobuf" Version="3.21.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2-beta1" />
<PackageReference Include="Google.Protobuf" Version="3.22.1" />
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.2.188-beta">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Grpc.Tools" Version="2.53.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="res\App.resx">
<Generator>ResXFileCodeGenerator</Generator>
<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>
</ItemGroup>
<ItemGroup>
<Compile Update="res\App.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>App.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<Protobuf Include="res/proto/*.proto" ProtoRoot="res/proto" GrpcServices="None" />
</ItemGroup>
</Project>

View File

@@ -105,7 +105,7 @@
<AdditionalDependencies>detours-x64.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PostBuildEvent>
<Command>copy $(TargetPath) $(ProjectDir)..\bin\Debug\net6.0</Command>
<Command>copy $(TargetPath) $(ProjectDir)..\bin\Debug\net7.0-windows\win-x64\YaeAchievementLib.dll /y</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
@@ -115,6 +115,7 @@
<ClInclude Include="src\il2cpp-functions.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

@@ -5,10 +5,11 @@
using Genshin::ByteArray, Genshin::ClientKcpEvent, Genshin::KcpPacket, Genshin::KcpEventType;
using std::to_string;
HWND unityWnd = 0;
HANDLE hPipe = 0;
HWND unityWnd = nullptr;
HANDLE hPipe = nullptr;
std::set<UINT16> PacketWhitelist = { 172, 198, 112, 2676, 7, 21 }; // ping, token, loginreq
// Allow Protocol: GetPlayerTokenRsp, PlayerLoginRsp, AchievementAllDataNotify, PingRsp
std::set<UINT16> PacketWhitelist = { 1574, 1548, 29462, 2794 };
bool OnPacket(KcpPacket* pkt) {
if (pkt->data == nullptr) return true;
@@ -16,63 +17,86 @@ bool OnPacket(KcpPacket* pkt) {
auto data = (ByteArray*)new BYTE[len + 32];
data->max_length = len;
memcpy(data->vector, pkt->data, len);
Genshin::Packet_Xor(&data, len, nullptr);
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
//ifdef _DEBUG
printf("Blocked cmdid: %d\n", ReadMapped<UINT16>(data->vector, 2));
#endif
//endif
delete[] data;
return false;
}
if (ReadMapped<UINT16>(data->vector, 2) == 2676) {
auto headLength = ReadMapped<UINT16>(data->vector, 4);
auto dataLength = ReadMapped<UINT32>(data->vector, 6);
auto iStr = Genshin::Convert_ToBase64String(data, 10 + headLength, dataLength, nullptr);
auto cStr = IlStringToString(iStr) + "\n";
printf("Passed cmdid: %d\n", ReadMapped<UINT16>(data->vector, 2));
if (ReadMapped<UINT16>(data->vector, 2) == 29462) {
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);
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 Kcp_Send(void* client, KcpPacket* pkt, void* method) {
return OnPacket(pkt) ? CALL_ORIGIN(Kcp_Send, client, pkt, method) : 0;
void SetVersion(void* obj, Il2CppString* value, void* method) {
const auto version = ToString(value);
value = string_new(version + " YaeAchievement");
CALL_ORIGIN(SetVersion, obj, value, method);
}
bool Kcp_Recv(void* client, ClientKcpEvent* evt, void* method) {
auto result = CALL_ORIGIN(Kcp_Recv, client, evt, method);
bool KcpRecv(void* client, ClientKcpEvent* evt, void* method) {
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 {};
}
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 Run(HMODULE* phModule) {
//AllocConsole();
//freopen_s((FILE**)stdout, "CONOUT$", "w", stdout);
while (
GetModuleHandle("UserAssembly.dll") == nullptr ||
(unityWnd = FindMainWindowByPID(GetCurrentProcessId())) == 0
) {
while ((unityWnd = FindMainWindowByPID(GetCurrentProcessId())) == nullptr) {
Sleep(1000);
}
Sleep(5000);
DisableVMProtect();
InitIL2CPP();
HookManager::install(Genshin::Kcp_Send, Hook::Kcp_Send);
HookManager::install(Genshin::Kcp_Recv, Hook::Kcp_Recv);
for (int i = 0; i < 3; i++) {
const auto result = Genshin::RecordUserData(i);
checksum += string(reinterpret_cast<char*>(&result->vector[0]), result->max_length);
}
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);
ExitProcess(0);
return;
}
}

View File

@@ -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(0x4243d0, 0x420bf0, Il2CppString*, il2cpp_string_new, (const char* str));

View File

@@ -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
@@ -12,3 +12,9 @@ namespace Genshin {
#include "il2cpp-functions.h"
}
#undef DO_APP_FUNC
#define DO_UNI_FUNC(ca, oa, r, n, p) extern r (*n) p
namespace Genshin {
#include "il2cpp-unity-functions.h"
}
#undef DO_UNI_FUNC

View File

@@ -1,7 +1,21 @@
using namespace Genshin;
DO_APP_FUNC(0x05E24240, 0x04EA1150, Il2CppString*, Convert_ToBase64String, (ByteArray* value, int offset, int length, void* method));
DO_APP_FUNC(0x018280A0, 0x018293F0, void, Packet_Xor, (ByteArray** data, int length, void* method));
// DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...));
DO_APP_FUNC(0x0193BA70, 0x0193C7D0, int, Kcp_Send, (void* client, KcpPacket* pkt, void* method));
DO_APP_FUNC(0x029EF820, 0x029F05C0, bool, Kcp_Recv, (void* client, ClientKcpEvent* evt, void* method));
DO_APP_FUNC(0x1929870, 0x1922c30, void, SetVersion, (void* obj, Il2CppString* value, void* method));
DO_APP_FUNC(0x6e7d020, 0x6e38a10, ByteArray*, RecordUserData, (int32_t nType));
DO_APP_FUNC(0x2b13f40, 0x2b09ce0, void, XorEncrypt, (ByteArray** data, int length, void* method));
DO_APP_FUNC(0x2d79560, 0x2d6e6f0, bool, KcpRecv, (void* client, ClientKcpEvent* evt, void* method));
DO_APP_FUNC(0x20004f0, 0x1ff8530, VOID, RequestLogin, (LPVOID obj, LPVOID token, UINT uid));
DO_APP_FUNC(0x130ead0, 0x1b90950, VOID, SetChecksum, (LPVOID obj, Il2CppString* value));
DO_APP_FUNC(0x2266e40, 0x225eb50, VOID, ForceQuit, (LPVOID obj));
DO_APP_FUNC(0x60af410, 0x60735f0, LPVOID, GetSingletonManager, ());
DO_APP_FUNC(0x60af140, 0x6073320, LPVOID, GetSingletonInstance, (LPVOID obj, Il2CppString* value));

View File

@@ -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
@@ -12,23 +12,28 @@ namespace Genshin {
}
#undef DO_APP_FUNC
using std::string;
UINT64 GetAddressByExports(HMODULE base, const char* name) {
UINT64 funcAddr = reinterpret_cast<UINT64>(GetProcAddress(base, name));
return funcAddr == 0 ? 0 : funcAddr;
#define DO_UNI_FUNC(ca, oa, r, n, p) r (*n) p
namespace Genshin {
#include "il2cpp-unity-functions.h"
}
#undef DO_UNI_FUNC
using std::string;
void InitIL2CPP() {
TCHAR szFileName[MAX_PATH];
GetModuleFileName(NULL, szFileName, MAX_PATH);
auto isCN = string(szFileName).contains("YuanShen.exe");
auto isCN = strstr(szFileName, "YuanShen.exe");//string(szFileName).contains();
auto hBase = GetModuleHandle("UserAssembly.dll");
auto bAddr = (UINT64)hBase;
#define DO_API(r, n, p) n = (r (*) p) GetAddressByExports(hBase, #n);
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"
#undef DO_UNI_FUNC
}

File diff suppressed because it is too large Load Diff

View File

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

View File

@@ -1,9 +1,20 @@
#include "pch.h"
#include "util.h"
VOID DisableVMProtect() {
DWORD oldProtect = 0;
auto ntdll = GetModuleHandleA("ntdll.dll");
auto pNtProtectVirtualMemory = GetProcAddress(ntdll, "NtProtectVirtualMemory");
auto pNtQuerySection = GetProcAddress(ntdll, "NtQuerySection");
DWORD old;
VirtualProtect(pNtProtectVirtualMemory, 1, PAGE_EXECUTE_READWRITE, &old);
*(uintptr_t*)pNtProtectVirtualMemory = *(uintptr_t*)pNtQuerySection & ~(0xFFui64 << 32) | (uintptr_t)(*(uint32_t*)((uintptr_t)pNtQuerySection + 4) - 1) << 32;
VirtualProtect(pNtProtectVirtualMemory, 1, old, &old);
}
#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];
@@ -14,11 +25,13 @@ string IlStringToString(Il2CppString* str, UINT codePage) {
#pragma endregion
#pragma region ByteUtils
bool IsLittleEndian() {
UINT i = 1;
char* c = (char*)&i;
return (*c);
}
#pragma endregion
#pragma region FindMainWindowByPID
@@ -55,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

@@ -2,13 +2,18 @@
using std::string;
VOID DisableVMProtect();
bool IsLittleEndian();
HWND FindMainWindowByPID(DWORD pid);
string IlStringToString(Il2CppString* str, UINT codePage = CP_ACP);
string ToString(Il2CppString* str, UINT codePage = CP_ACP);
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 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())
template<class T>
static T ReadMapped(void* data, int offset, bool littleEndian = false) {

397
res/App.Designer.cs generated Normal file
View File

@@ -0,0 +1,397 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace YaeAchievement.res {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class App {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal App() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("YaeAchievement.res.App", typeof(App).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to all achievement.
/// </summary>
internal static string AllAchievement {
get {
return ResourceManager.GetString("AllAchievement", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please close another instance..
/// </summary>
internal static string AnotherInstance {
get {
return ResourceManager.GetString("AnotherInstance", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to YaeAchievement ({0}).
/// </summary>
internal static string AppBanner {
get {
return ResourceManager.GetString("AppBanner", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to You need to login genshin impact before exporting..
/// </summary>
internal static string ConfigNeedStartGenshin {
get {
return ResourceManager.GetString("ConfigNeedStartGenshin", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Download: {0}.
/// </summary>
internal static string DownloadLink {
get {
return ResourceManager.GetString("DownloadLink", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Network error ({0}: {1}).
/// </summary>
internal static string ExceptionNetwork {
get {
return ResourceManager.GetString("ExceptionNetwork", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Export to:
///[0] Cocogoat (https://cocogoat.work/achievement, Default)
///[1] Snap.HuTao
///[2] Paimon.moe
///[3] Seelie.me
///[4] Csv file
///[5] Xunkong
///[7] Teyvat Guide
///[8] UIAF JSON File
///Input a number (0-8): .
/// </summary>
internal static string ExportChoose {
get {
return ResourceManager.GetString("ExportChoose", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Fail, please contact developer to get help information.
/// </summary>
internal static string ExportToCocogoatFail {
get {
return ResourceManager.GetString("ExportToCocogoatFail", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to cocogoat..
/// </summary>
internal static string ExportToCocogoatSuccess {
get {
return ResourceManager.GetString("ExportToCocogoatSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to {0}.
/// </summary>
internal static string ExportToFileSuccess {
get {
return ResourceManager.GetString("ExportToFileSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please update Snap Hutao and retry..
/// </summary>
internal static string ExportToSnapGenshinNeedUpdate {
get {
return ResourceManager.GetString("ExportToSnapGenshinNeedUpdate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to Snap Hutao..
/// </summary>
internal static string ExportToSnapGenshinSuccess {
get {
return ResourceManager.GetString("ExportToSnapGenshinSuccess", resourceCulture);
}
}
/// <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>
internal static string ExportToWxApp1Success {
get {
return ResourceManager.GetString("ExportToWxApp1Success", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please update xunkong and retry..
/// </summary>
internal static string ExportToXunkongNeedUpdate {
get {
return ResourceManager.GetString("ExportToXunkongNeedUpdate", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Successfully exported to xunkong..
/// </summary>
internal static string ExportToXunkongSuccess {
get {
return ResourceManager.GetString("ExportToXunkongSuccess", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Game process start ({0}).
/// </summary>
internal static string GameLoading {
get {
return ResourceManager.GetString("GameLoading", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Game exited..
/// </summary>
internal static string GameProcessExit {
get {
return ResourceManager.GetString("GameProcessExit", resourceCulture);
}
}
/// <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>
internal static string GenshinIsRunning {
get {
return ResourceManager.GetString("GenshinIsRunning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Network error:.
/// </summary>
internal static string NetworkError {
get {
return ResourceManager.GetString("NetworkError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No write permission on {0}..
/// </summary>
internal static string NoWritePermission {
get {
return ResourceManager.GetString("NoWritePermission", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Press any key to exit..
/// </summary>
internal static string PressKeyToExit {
get {
return ResourceManager.GetString("PressKeyToExit", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Reward not taken.
/// </summary>
internal static string StatusFinished {
get {
return ResourceManager.GetString("StatusFinished", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Invalid.
/// </summary>
internal static string StatusInvalid {
get {
return ResourceManager.GetString("StatusInvalid", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Finished.
/// </summary>
internal static string StatusRewardTaken {
get {
return ResourceManager.GetString("StatusRewardTaken", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Unfinished.
/// </summary>
internal static string StatusUnfinished {
get {
return ResourceManager.GetString("StatusUnfinished", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Description:
///{0}.
/// </summary>
internal static string UpdateDescription {
get {
return ResourceManager.GetString("UpdateDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Downloading update package....
/// </summary>
internal static string UpdateDownloading {
get {
return ResourceManager.GetString("UpdateDownloading", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Has update: {0} =&gt; {1}.
/// </summary>
internal static string UpdateNewVersion {
get {
return ResourceManager.GetString("UpdateNewVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] Updater {
get {
object obj = ResourceManager.GetObject("Updater", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Looks up a localized string similar to Upload error to appcenter....
/// </summary>
internal static string UploadError {
get {
return ResourceManager.GetString("UploadError", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use previous fetched data? (yes|no).
/// </summary>
internal static string UsePreviousData {
get {
return ResourceManager.GetString("UsePreviousData", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Downloading Visual C++ Redistributable....
/// </summary>
internal static string VcRuntimeDownload {
get {
return ResourceManager.GetString("VcRuntimeDownload", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Installing Visual C++ Redistributable....
/// </summary>
internal static string VcRuntimeInstalling {
get {
return ResourceManager.GetString("VcRuntimeInstalling", resourceCulture);
}
}
}
}

140
res/App.resx Normal file
View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ExportToCocogoatFail" xml:space="preserve">
<value>Fail, please contact developer to get help information</value>
</data>
<data name="AllAchievement" xml:space="preserve">
<value>all achievement</value>
</data>
<data name="ExportChoose" xml:space="preserve">
<value>Export to:
[0] Cocogoat (https://cocogoat.work/achievement, Default)
[1] Snap.HuTao
[2] Paimon.moe
[3] Seelie.me
[4] Csv file
[5] Xunkong
[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>
</data>
<data name="ExportToWxApp1Success" xml:space="preserve">
<value>{0}</value>
</data>
<data name="ExportToSnapGenshinSuccess" xml:space="preserve">
<value>Successfully exported to Snap Hutao.</value>
</data>
<data name="ExportToSnapGenshinNeedUpdate" xml:space="preserve">
<value>Please update Snap Hutao and retry.</value>
</data>
<data name="ExportToFileSuccess" xml:space="preserve">
<value>Successfully exported to {0}</value>
</data>
<data name="ExportToXunkongSuccess" xml:space="preserve">
<value>Successfully exported to xunkong.</value>
</data>
<data name="ExportToXunkongNeedUpdate" xml:space="preserve">
<value>Please update xunkong and retry.</value>
</data>
<data name="StatusInvalid" xml:space="preserve">
<value>Invalid</value>
</data>
<data name="StatusRewardTaken" xml:space="preserve">
<value>Finished</value>
</data>
<data name="StatusUnfinished" xml:space="preserve">
<value>Unfinished</value>
</data>
<data name="StatusFinished" xml:space="preserve">
<value>Reward not taken</value>
</data>
<data name="ConfigNeedStartGenshin" xml:space="preserve">
<value>You need to login genshin impact before exporting.</value>
</data>
<data name="DownloadLink" xml:space="preserve">
<value>Download: {0}</value>
</data>
<data name="GameProcessExit" xml:space="preserve">
<value>Game exited.</value>
</data>
<data name="GameLoading" xml:space="preserve">
<value>Game process start ({0})</value>
</data>
<data name="UploadError" xml:space="preserve">
<value>Upload error to appcenter...</value>
</data>
<data name="PressKeyToExit" xml:space="preserve">
<value>Press any key to exit.</value>
</data>
<data name="GenshinIsRunning" xml:space="preserve">
<value>Please close game before run this application. ({0})</value>
</data>
<data name="AnotherInstance" xml:space="preserve">
<value>Please close another instance.</value>
</data>
<data name="UpdateNewVersion" xml:space="preserve">
<value>Has update: {0} =&gt; {1}</value>
</data>
<data name="UpdateDescription" xml:space="preserve">
<value>Description:
{0}</value>
</data>
<data name="UpdateDownloading" xml:space="preserve">
<value>Downloading update package...</value>
</data>
<data name="AppBanner" xml:space="preserve">
<value>YaeAchievement ({0})</value>
</data>
<data name="UsePreviousData" xml:space="preserve">
<value>Use previous fetched data? (yes|no)</value>
</data>
<data name="NetworkError" xml:space="preserve">
<value>Network error:</value>
</data>
<data name="VcRuntimeDownload" xml:space="preserve">
<value>Downloading Visual C++ Redistributable...</value>
</data>
<data name="VcRuntimeInstalling" xml:space="preserve">
<value>Installing Visual C++ Redistributable...</value>
</data>
<data name="ExceptionNetwork" xml:space="preserve">
<value>Network error ({0}: {1})</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<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>
<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>

130
res/App.zh.resx Normal file
View File

@@ -0,0 +1,130 @@
<root>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>1.3</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="ExportToCocogoatFail" xml:space="preserve">
<value>导出失败, 请联系开发者以获取帮助</value>
</data>
<data name="AllAchievement" xml:space="preserve">
<value>全部成就</value>
</data>
<data name="ExportChoose" xml:space="preserve">
<value>导出至:
[0] 椰羊 (https://cocogoat.work/achievement, 默认)
[1] Snap Hutao
[2] Paimon.moe
[3] Seelie.me
[4] 表格文件
[5] 寻空
[6] 原魔工具箱
[7] Teyvat Guide
[8] UIAF JSON 文件
输入一个数字 (0-8): </value>
</data>
<data name="ExportToCocogoatSuccess" xml:space="preserve">
<value>在浏览器内进行下一步操作</value>
</data>
<data name="ExportToWxApp1Success" xml:space="preserve">
<value>在小程序导入页面输入以下代码: {0}</value>
</data>
<data name="ExportToSnapGenshinSuccess" xml:space="preserve">
<value>在 Snap Hutao 中进行下一步操作</value>
</data>
<data name="ExportToSnapGenshinNeedUpdate" xml:space="preserve">
<value>更新/安装 Snap Hutao 最新版本后重试</value>
</data>
<data name="ExportToFileSuccess" xml:space="preserve">
<value>成就数据已导出至 {0}</value>
</data>
<data name="ExportToXunkongSuccess" xml:space="preserve">
<value>在寻空中进行下一步操作</value>
</data>
<data name="ExportToXunkongNeedUpdate" xml:space="preserve">
<value>更新寻空至最新版本后重试</value>
</data>
<data name="StatusInvalid" xml:space="preserve">
<value>未知</value>
</data>
<data name="StatusFinished" xml:space="preserve">
<value>已完成但未领取奖励</value>
</data>
<data name="StatusUnfinished" xml:space="preserve">
<value>未完成</value>
</data>
<data name="StatusRewardTaken" xml:space="preserve">
<value>已完成</value>
</data>
<data name="ConfigNeedStartGenshin" xml:space="preserve">
<value>在导出前你需要先完成一次登入流程.</value>
</data>
<data name="DownloadLink" xml:space="preserve">
<value>下载地址: {0}</value>
</data>
<data name="GameProcessExit" xml:space="preserve">
<value>游戏进程异常退出</value>
</data>
<data name="GameLoading" xml:space="preserve">
<value>原神正在启动 ({0})</value>
</data>
<data name="UploadError" xml:space="preserve">
<value>正在上报错误信息...</value>
</data>
<data name="PressKeyToExit" xml:space="preserve">
<value>按任意键退出</value>
</data>
<data name="GenshinIsRunning" xml:space="preserve">
<value>原神正在运行,请关闭后重试 ({0})</value>
</data>
<data name="AnotherInstance" xml:space="preserve">
<value>另一个实例正在运行,请关闭后重试</value>
</data>
<data name="UpdateNewVersion" xml:space="preserve">
<value>有可用更新: {0} =&gt; {1}</value>
</data>
<data name="UpdateDescription" xml:space="preserve">
<value>更新内容:
{0}</value>
</data>
<data name="UpdateDownloading" xml:space="preserve">
<value>正在下载更新包...</value>
</data>
<data name="AppBanner" xml:space="preserve">
<value>YaeAchievement - 原神成就导出工具 ({0})</value>
</data>
<data name="UsePreviousData" xml:space="preserve">
<value>要使用上一次获取到的成就数据吗? (yes|no)</value>
</data>
<data name="NetworkError" xml:space="preserve">
<value>网络错误: {0}</value>
</data>
<data name="VcRuntimeDownload" xml:space="preserve">
<value>正在下载 Visual C++ Redistributable...</value>
</data>
<data name="VcRuntimeInstalling" xml:space="preserve">
<value>正在安装 Visual C++ Redistributable...</value>
</data>
<data name="ExceptionNetwork" xml:space="preserve">
<value>网络错误,请检查网络后重试 ({0}: {1})</value>
</data>
<data name="GenshinHashError" xml:space="preserve">
<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>

BIN
res/Updater.exe Normal file

Binary file not shown.

View File

@@ -0,0 +1,21 @@
syntax = "proto3";
option csharp_namespace = "Proto";
message Achievement {
enum Status {
INVALID = 0;
UNFINISHED = 1;
FINISHED = 2;
REWARD_TAKEN = 3;
}
uint32 timestamp = 11;
uint32 current = 12;
uint32 total = 3;
uint32 id = 15;
Status status = 7;
}
message AchievementAllDataNotify {
repeated Achievement list = 8;
}

View File

@@ -0,0 +1,16 @@
syntax = "proto3";
option csharp_namespace = "Proto";
message AchievementItem {
uint32 pre = 1;
uint32 group = 2;
string name = 3;
string description = 4;
}
message AchievementInfo {
string version = 1;
map<uint32, string> group = 2;
map<uint32, AchievementItem> items = 3;
}

10
res/proto/CacheItem.proto Normal file
View File

@@ -0,0 +1,10 @@
syntax = "proto3";
option csharp_namespace = "Proto";
message CacheItem {
uint32 version = 1;
string checksum = 2;
string etag = 3;
bytes content = 4;
}

View File

@@ -0,0 +1,15 @@
syntax = "proto3";
option csharp_namespace = "Proto";
message UpdateInfo {
uint32 versionCode = 1;
string versionName = 2;
string description = 3;
string packageLink = 4;
bool forceUpdate = 5;
bool enableLibDownload = 6;
bool enableAutoDownload = 7;
string currentCNGameHash = 8;
string currentOSGameHash = 9;
}

View File

@@ -5,15 +5,13 @@ using YaeAchievement.AppCenterSDK.Models.Serialization;
namespace YaeAchievement.AppCenterSDK;
#pragma warning disable CA1416, CA2211
public static class AppCenter {
private const string LogCache = "./cache/bf18159fb833715i.miko";
private const string AppSecret = "648b83bf-d439-49bd-97f4-e1e506bdfe39";
private const string ApiUrl = "https://in.appcenter.ms/logs?api-version=1.0.0";
// ReSharper disable InconsistentNaming
public static Guid? SessionID;
public static Guid? SessionID { get; private set; }
public static readonly string DeviceID;
public static readonly Device DeviceInfo;
private static List<Log> Queue;
@@ -40,10 +38,6 @@ public static class AppCenter {
});
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
running = false;
if (Queue.Count > 0) {
Directory.CreateDirectory("cache");
File.WriteAllText(LogCache, Queue.ToJson());
}
};
LogSerializer.AddLogType(PageLog.JsonIdentifier, typeof(PageLog));
LogSerializer.AddLogType(EventLog.JsonIdentifier, typeof(EventLog));
@@ -51,13 +45,6 @@ public static class AppCenter {
LogSerializer.AddLogType(ManagedErrorLog.JsonIdentifier, typeof(ManagedErrorLog));
LogSerializer.AddLogType(StartServiceLog.JsonIdentifier, typeof(StartServiceLog));
LogSerializer.AddLogType(StartSessionLog.JsonIdentifier, typeof(StartSessionLog));
if (Directory.Exists("./cache") && File.Exists(LogCache)) {
var list = File.ReadAllText(LogCache).FromJson()?.Logs;
if (list != null) {
Queue.AddRange(list);
}
File.Delete(LogCache);
}
}
// ReSharper restore InconsistentNaming
@@ -98,9 +85,4 @@ public static class AppCenter {
private static string ToJson(this IEnumerable<Log> queue) {
return LogSerializer.Serialize(new LogContainer(queue));
}
private static LogContainer? FromJson(this string text) {
return LogSerializer.DeserializeLogs(text);
}
}
#pragma warning restore CA1416, CA2211

View File

@@ -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;
}

62
src/AppConfig.cs Normal file
View File

@@ -0,0 +1,62 @@
using System.Text.RegularExpressions;
using YaeAchievement.res;
namespace YaeAchievement;
public static class AppConfig {
public static string GamePath { get; private set; } = null!;
internal static void Load(string argumentPath) {
if (argumentPath != "auto" && File.Exists(argumentPath)) {
GamePath = argumentPath;
return;
}
var pathCacheFile = new CacheFile("genshin_impact_game_path");
if (pathCacheFile.Exists()) {
var path = pathCacheFile.Read().Content.ToStringUtf8();
if (path != null && File.Exists(path)) {
GamePath = path;
return;
}
}
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var cnLogPath = Path.Combine(appDataPath, @"..\LocalLow\miHoYo\原神\output_log.txt");
var osLogPath = Path.Combine(appDataPath, @"..\LocalLow\miHoYo\Genshin Impact\output_log.txt");
if (!File.Exists(cnLogPath) && !File.Exists(osLogPath)) {
throw new ApplicationException(App.ConfigNeedStartGenshin);
}
string finalLogPath;
if (!File.Exists(osLogPath)) {
finalLogPath = cnLogPath;
} else if (!File.Exists(cnLogPath)) {
finalLogPath = osLogPath;
} else {
var cnLastWriteTime = File.GetLastWriteTime(cnLogPath);
var osLastWriteTime = File.GetLastWriteTime(osLogPath);
finalLogPath = cnLastWriteTime > osLastWriteTime ? cnLogPath : osLogPath;
}
GamePath = GetGamePathFromLogFile(finalLogPath)
?? GetGamePathFromLogFile($"{finalLogPath}.last")
?? throw new ApplicationException(App.ConfigNeedStartGenshin);
pathCacheFile.Write(GamePath);
}
private static string? GetGamePathFromLogFile(string path) {
if (!File.Exists(path)) {
return null;
}
var copiedLogFilePath = Path.GetTempFileName();
File.Copy(path, copiedLogFilePath, true);
var content = File.ReadAllText(copiedLogFilePath);
try {
File.Delete(copiedLogFilePath);
} catch (Exception) { /* ignore */}
var matchResult = Regex.Match(content, @"(?m).:/.+(GenshinImpact_Data|YuanShen_Data)");
if (!matchResult.Success) {
return null;
}
var entryName = matchResult.Groups["1"].Value.Replace("_Data", ".exe");
return Path.GetFullPath(Path.Combine(matchResult.Value, "..", entryName));
}
}

43
src/CacheFile.cs Normal file
View File

@@ -0,0 +1,43 @@
using System.IO.Compression;
using Google.Protobuf;
using Proto;
namespace YaeAchievement;
public class CacheFile {
private readonly string _cacheName;
private CacheItem? _content;
public DateTime LastWriteTime => Exists() ? File.GetLastWriteTimeUtc(_cacheName) : DateTime.UnixEpoch;
public CacheFile(string identifier) {
_cacheName = Path.Combine(GlobalVars.CachePath, $"{identifier.MD5Hash()[..16]}.miko");
}
public bool Exists() => File.Exists(_cacheName);
public CacheItem Read() {
if (_content == null) {
using var fInput = File.OpenRead(_cacheName);
using var dInput = new GZipStream(fInput, CompressionMode.Decompress);
_content = CacheItem.Parser.ParseFrom(dInput);
}
return _content;
}
public void Write(string data, string? etag = null) => Write(ByteString.CopyFromUtf8(data), data.MD5Hash(), etag);
public void Write(byte[] data, string? etag = null) => Write(ByteString.CopyFrom(data), data.MD5Hash(), etag);
private void Write(ByteString data, string hash, string? etag) {
using var fOut = File.OpenWrite(_cacheName);
using var cOut = new GZipStream(fOut, CompressionLevel.SmallestSize);
new CacheItem {
Etag = etag ?? string.Empty,
Version = 3,
Checksum = hash,
Content = data
}.WriteTo(cOut);
}
}

View File

@@ -1,67 +1,129 @@
using System.Diagnostics.CodeAnalysis;
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 Newtonsoft.Json;
using static AchievementAllDataNotify.Types.Achievement.Types;
using Proto;
using YaeAchievement.AppCenterSDK;
using YaeAchievement.res;
using static Proto.Achievement.Types;
namespace YaeAchievement;
public static class Export {
public static uint ExportTo { get; set; } = uint.MaxValue;
public static void Choose(AchievementAllDataNotify data) {
Console.Write(@"导出至:
[0] (https://cocogoat.work/achievement, 默认)
[1] SnapGenshin
[2] Paimon.moe
[3] Seelie.me
[4]
(0-4): ".Split("\n").Select(s => s.Trim()).JoinToString("\n") + " ");
if (!int.TryParse(Console.ReadLine(), out var num)) num = 0;
((Action<AchievementAllDataNotify>) (num switch {
1 => ToSnapGenshin,
if (ExportTo == uint.MaxValue) {
Console.Write(App.ExportChoose);
while (Console.KeyAvailable) {
Console.ReadKey(false);
}
if (!uint.TryParse(Console.ReadLine(), out var num)) num = 0;
ExportTo = num;
}
((Action<AchievementAllDataNotify>) (ExportTo switch {
1 => ToHuTao,
2 => ToPaimon,
3 => ToSeelie,
4 => ToCSV,
7 => ToRawJson,
5 => ToXunkong,
6 => ToWxApp1,
7 => ToTeyvatGuide,
8 => ToUIAFJson,
9 => ToRawJson,
_ => ToCocogoat
})).Invoke(data);
}
private class CocogoatResponse {
[JsonPropertyName("key")] public string Code { get; set; } = null!;
}
private static void ToCocogoat(AchievementAllDataNotify data) {
var result = JsonConvert.SerializeObject(ExportToUIAFApp(data));
var result = JsonSerializer.Serialize(ExportToUIAFApp(data));
using var request = new HttpRequestMessage {
Method = HttpMethod.Post,
RequestUri = new Uri("https://77.cocogoat.work/v1/memo?source=全部成就"),
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.Value.Send(request);
using var response = Utils.CHttpClient.Send(request);
if (response.StatusCode != HttpStatusCode.Created) {
Console.WriteLine("导出失败, 请联系开发者以获取帮助");
Console.WriteLine(App.ExportToCocogoatFail);
return;
}
dynamic memo = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result)!;
Console.WriteLine(Utils.ShellOpen($"https://cocogoat.work/achievement?memo={memo.key}")
? "在浏览器内进行下一步操作"
: $"https://cocogoat.work/achievement?memo={memo.key}");
var responseText = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var responseJson = JsonSerializer.Deserialize<CocogoatResponse>(responseText)!;
Console.WriteLine(Utils.ShellOpen($"https://cocogoat.work/achievement?memo={responseJson.Code}")
? App.ExportToCocogoatSuccess
: $"https://cocogoat.work/achievement?memo={responseJson.Code}");
}
private static void ToSnapGenshin(AchievementAllDataNotify data) {
if (CheckSnapScheme()) {
Utils.CopyToClipboard(JsonConvert.SerializeObject(ExportToUIAFApp(data)));
Utils.ShellOpen("snapgenshin://achievement/import/uiaf");
Console.WriteLine("在 SnapGenshin 进行下一步操作");
private static void ToWxApp1(AchievementAllDataNotify data) {
var id = Guid.NewGuid().ToString("N").Substring(20, 8);
var result = JsonSerializer.Serialize(new Dictionary<string, object> {
{ "key", id },
{ "data", ExportToUIAFApp(data) }
});
using var request = new HttpRequestMessage {
Method = HttpMethod.Post,
RequestUri = new Uri("https://api.qyinter.com/achievementRedis"),
Content = new StringContent(result, Encoding.UTF8, "application/json")
};
using var response = Utils.CHttpClient.Send(request);
Console.WriteLine(App.ExportToWxApp1Success, id);
}
private static void ToHuTao(AchievementAllDataNotify data) {
if (CheckWinUIAppScheme("hutao")) {
Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data)));
Utils.ShellOpen("hutao://achievement/import");
Console.WriteLine(App.ExportToSnapGenshinSuccess);
} else {
Console.WriteLine("更新 SnapGenshin 至最新版本后重试");
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");
if (TryWriteToFile(path, JsonSerializer.Serialize(ExportToUIAFApp(data)))) {
Console.WriteLine(App.ExportToFileSuccess, path);
}
}
private static void ToPaimon(AchievementAllDataNotify data) {
var info = LoadAchievementInfo();
var output = new Dictionary<uint, Dictionary<uint, bool>>();
foreach (var ach in data.List.Where(a => a.Status is Status.Finished or Status.RewardTaken)) {
if (!info.Items.TryGetValue(ach.Id, out var achInfo) || achInfo == null) {
Console.WriteLine($"Unable to find {ach.Id} in metadata.");
Console.WriteLine($@"Unable to find {ach.Id} in metadata.");
continue;
}
var map = output.GetValueOrDefault(achInfo.Group, new Dictionary<uint, bool>());
@@ -72,8 +134,9 @@ public static class Export {
["achievement"] = output.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value)
};
var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-paimon.json");
File.WriteAllText(path, JsonConvert.SerializeObject(final));
Console.WriteLine($"成就数据已导出至 {path}");
if (TryWriteToFile(path, JsonSerializer.Serialize(final))) {
Console.WriteLine(App.ExportToFileSuccess, path);
}
}
private static void ToSeelie(AchievementAllDataNotify data) {
@@ -87,8 +150,9 @@ public static class Export {
["achievements"] = output.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value)
};
var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-seelie.json");
File.WriteAllText(path, JsonConvert.SerializeObject(final));
Console.WriteLine($"成就数据已导出至 {path}");
if (TryWriteToFile(path, JsonSerializer.Serialize(final))) {
Console.WriteLine(App.ExportToFileSuccess, path);
}
}
// ReSharper disable once InconsistentNaming
@@ -98,13 +162,13 @@ public static class Export {
foreach (var ach in data.List.OrderBy(a => a.Id)) {
if (UnusedAchievement.Contains(ach.Id)) continue;
if (!info.Items.TryGetValue(ach.Id, out var achInfo) || achInfo == null) {
Console.WriteLine($"Unable to find {ach.Id} in metadata.");
Console.WriteLine($@"Unable to find {ach.Id} in metadata.");
continue;
}
var finishAt = "";
if (ach.Timestamp != 0) {
var ts = Convert.ToInt64(ach.Timestamp);
finishAt = DateTimeOffset.FromUnixTimeSeconds(ts).ToString("yyyy/MM/dd HH:mm:ss");
finishAt = DateTimeOffset.FromUnixTimeSeconds(ts).ToLocalTime().ToString("yyyy/MM/dd HH:mm:ss");
}
var current = ach.Status != Status.Unfinished ? ach.Current == 0 ? ach.Total : ach.Current : ach.Current;
outList.Add(new List<object> {
@@ -118,38 +182,48 @@ public static class Export {
return item.JoinToString(",");
}));
var path = Path.GetFullPath($"achievement-{DateTime.Now:yyyyMMddHHmmss}.csv");
File.WriteAllText(path, $"\uFEFF{string.Join("\n", output)}");
Console.WriteLine($"成就数据已导出至 {path}");
if (TryWriteToFile(path, $"\uFEFF{string.Join("\n", output)}")) {
Console.WriteLine(App.ExportToFileSuccess, path);
Process.Start("explorer.exe", $"{Path.GetDirectoryName(path)}");
}
}
private static void ToRawJson(AchievementAllDataNotify data) {
var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-raw.json");
File.WriteAllText(path, JsonConvert.SerializeObject(data, Formatting.Indented));
Console.WriteLine($"成就数据已导出至 {path}");
var text = JsonSerializer.Serialize(data, new JsonSerializerOptions {
WriteIndented = true
});
if (TryWriteToFile(path, text)) {
Console.WriteLine(App.ExportToFileSuccess, path);
}
}
// ReSharper disable once InconsistentNaming
private static Dictionary<string, object> ExportToUIAFApp(AchievementAllDataNotify data) {
var output = data.List
.Where(a => a.Status is Status.Finished or Status.RewardTaken)
.Select(ach => new Dictionary<string, uint> { ["id"] = ach.Id, ["current"] = ach.Current, ["timestamp"] = ach.Timestamp })
.Where(a => (uint)a.Status > 1 || a.Current > 0)
.Select(ach => new Dictionary<string, uint> {
["id"] = ach.Id,
["status"] = (uint) ach.Status,
["current"] = ach.Current,
["timestamp"] = ach.Timestamp
})
.ToList();
return new Dictionary<string, object> {
["info"] = new Dictionary<string, object> {
["export_app"] = "YaeAchievement",
["export_timestamp"] = DateTimeOffset.Now.ToUnixTimeMilliseconds(),
["export_timestamp"] = DateTimeOffset.Now.ToUnixTimeSeconds(),
["export_app_version"] = GlobalVars.AppVersionName,
["uiaf_version"] = "v1.0"
["uiaf_version"] = "v1.1"
},
["list"] = output
};
}
[SuppressMessage("Interoperability", "CA1416:验证平台兼容性")]
private static bool CheckSnapScheme() {
return (string?)Registry.ClassesRoot.OpenSubKey("snapgenshin")?.GetValue("") == "URL:snapgenshin";
private static bool CheckWinUIAppScheme(string protocol) {
return (string?)Registry.ClassesRoot.OpenSubKey(protocol)?.GetValue("") == $"URL:{protocol}";
}
private static string JoinToString(this IEnumerable<object> list, string separator) {
return string.Join(separator, list);
}
@@ -158,10 +232,10 @@ public static class Export {
private static string ToDesc(this Status status) {
return status switch {
Status.Invalid => "未知",
Status.Finished => "已完成但未领取奖励",
Status.Unfinished => "未完成",
Status.RewardTaken => "已完成",
Status.Invalid => App.StatusInvalid,
Status.Finished => App.StatusFinished,
Status.Unfinished => App.StatusUnfinished,
Status.RewardTaken => App.StatusRewardTaken,
_ => throw new ArgumentOutOfRangeException(nameof(status), status, null)
};
}
@@ -170,4 +244,21 @@ 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;
}
private static bool TryWriteToFile(string path, string contents) {
try {
File.WriteAllText(path, contents);
return true;
} catch (UnauthorizedAccessException) {
Console.WriteLine(App.NoWritePermission, path);
return false;
}
}
}

View File

@@ -1,40 +1,28 @@
using System.Collections.Specialized;
using System.Diagnostics.CodeAnalysis;
using System.Net;
using System.Security.Cryptography;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using Newtonsoft.Json;
namespace YaeAchievement;
[SuppressMessage("ReSharper", "MemberCanBePrivate.Global")]
// ReSharper disable MemberCanBePrivate.Global
public static class Extensions {
// ReSharper disable once InconsistentNaming
private static readonly Lazy<Aes> aes = new (Aes.Create);
// ReSharper disable once InconsistentNaming
private static readonly Lazy<MD5> md5 = new (MD5.Create);
// ReSharper disable once InconsistentNaming
private static readonly Lazy<SHA1> sha1 = new (SHA1.Create);
// ReSharper disable once InconsistentNaming
private static readonly Lazy<HttpClient> defaultClient = new (() => new HttpClient(new HttpClientHandler {
Proxy = GlobalVars.DebugProxy ? new WebProxy("http://127.0.0.1:8888") : null
}) {
DefaultRequestHeaders = {{ "User-Agent", "UnityPlayer/2017.4.30f1 (UnityWebRequest/1.0, libcurl/7.51.0-DEV)" }}
});
public static byte[] ToBytes(this string text) {
return Encoding.UTF8.GetBytes(text);
}
public static string DecodeToString(this byte[] bytes) {
return Encoding.UTF8.GetString(bytes);
// ReSharper disable once InconsistentNaming
public static string MD5Hash(this string text) {
return text.ToBytes().MD5Hash();
}
// ReSharper disable once InconsistentNaming
public static string MD5Hash(this string text) {
return md5.Value.ComputeHash(text.ToBytes()).ToHex();
public static string MD5Hash(this byte[] data) {
return md5.Value.ComputeHash(data).ToHex().ToLower();
}
// ReSharper disable once InconsistentNaming
@@ -43,55 +31,6 @@ public static class Extensions {
return base64 ? bytes.ToBase64() : bytes.ToHex();
}
public static HttpResponseMessage Send(this HttpRequestMessage message, HttpClient? client = null) {
Logger.Trace($"{message.Method} {message.RequestUri?.GetFullPath()}");
return (client ?? defaultClient.Value).Send(message); // dispose message?
}
public static T? Send<T>(this HttpRequestMessage message, HttpClient? client = null, Func<string, string>? onPreDeserialize = null) {
Logger.Trace($"{message.Method} {message.RequestUri?.GetFullPath()}");
using var response = (client ?? defaultClient.Value).Send(message);
var text = response.Content.ReadAsStringAsync().Result;
if (onPreDeserialize != null) {
text = onPreDeserialize.Invoke(text);
}
return JsonConvert.DeserializeObject<T>(text);
}
public static string ToQueryString(this NameValueCollection collection, bool escape = true) {
var items = collection.AllKeys
.Select(key => escape ?
$"{HttpUtility.UrlEncode(key)}={HttpUtility.UrlEncode(collection[key])}" :
$"{key}={collection[key]}");
return string.Join("&", items);
}
public static string ToQueryString(this IEnumerable<KeyValuePair<string, object>> dict, bool escape = true) {
var items = dict
.Select(pair => escape ?
$"{HttpUtility.UrlEncode(pair.Key)}={HttpUtility.UrlEncode(pair.Value.ToString())}" :
$"{pair.Key}={pair.Value}");
return string.Join("&", items);
}
public static string ToJsonString<TKey, TValue>(this Dictionary<TKey, TValue> data) where TKey : notnull {
return JsonConvert.SerializeObject(data);
}
public static string GetFullPath(this Uri uri) {
return $"{uri.Scheme}://{uri.Host}{uri.AbsolutePath}";
}
public static IEnumerable<KeyValuePair<string, string>> ToKeyValuePairs(this NameValueCollection collection) {
return collection.AllKeys
.Select(key => new KeyValuePair<string, string>(key!, collection[key] ?? string.Empty))
.ToArray();
}
public static string UrlEncode(this string text) {
return HttpUtility.UrlEncode(text);
}
public static string ToHex(this byte[] bytes) {
return Convert.ToHexString(bytes);
}
@@ -99,8 +38,4 @@ public static class Extensions {
public static string ToBase64(this byte[] bytes) {
return Convert.ToBase64String(bytes);
}
public static byte[] FromBase64(this string text) {
return Convert.FromBase64String(text);
}
}
}

View File

@@ -1,27 +1,33 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Reflection;
namespace YaeAchievement;
[SuppressMessage("ReSharper", "ConvertToConstant.Global")]
[SuppressMessage("ReSharper", "FieldCanBeMadeReadOnly.Global")]
// ReSharper disable InconsistentNaming
// ReSharper disable ConvertToConstant.Global
// ReSharper disable FieldCanBeMadeReadOnly.Global
// ReSharper disable once MemberCanBePrivate.Global
#pragma warning disable CA2211
public static class GlobalVars {
public static bool DebugProxy = false;
public static bool CheckGamePath = true;
public static bool UnexpectedExit = true;
public static string GamePath = null!;
public static Logger.Level LogLevel = Logger.Level.Info;
public static Version AppVersion = Assembly.GetEntryAssembly()!.GetName().Version!;
public static bool DebugProxy => false;
public static bool UnexpectedExit { get; set; } = true;
public static bool PauseOnExit { get; set; } = true;
public static Version AppVersion { get; } = Assembly.GetEntryAssembly()!.GetName().Version!;
public static readonly string AppPath = AppDomain.CurrentDomain.BaseDirectory;
private static readonly string CommonData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
public static readonly string DataPath = Path.Combine(CommonData, "Yae");
public static readonly string CachePath = Path.Combine(DataPath, "cache");
public static readonly string LibFilePath = Path.Combine(DataPath, "YaeAchievement.dll");
public const uint AppVersionCode = 42;
public const string AppVersionName = "3.2";
public const uint AppVersionCode = 28;
public const string AppVersionName = "2.0";
public const string LibName = "YaeLib.dll";
public const string PipeName = "YaeAchievementPipe";
public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com";
public const string ConfigFileName = "YaeAchievement.runtimeconfig.json";
static GlobalVars() {
Directory.CreateDirectory(DataPath);
Directory.CreateDirectory(CachePath);
}
}
#pragma warning restore CA2211

View File

@@ -1,49 +1,62 @@
using System.ComponentModel;
using YaeAchievement.Win32;
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;
}
public static int LoadLibraryAndInject(IntPtr handle, string libPath) {
var hKernel = Native.GetModuleHandle("kernel32.dll");
if (hKernel == IntPtr.Zero) {
return new Win32Exception().PrintMsgAndReturnErrCode("GetModuleHandle fail");
}
var pLoadLibrary = Native.GetProcAddress(hKernel, "LoadLibraryA");
if (pLoadLibrary == IntPtr.Zero) {
return new Win32Exception().PrintMsgAndReturnErrCode("GetProcAddress fail");
}
var pBase = Native.VirtualAllocEx(handle, IntPtr.Zero, libPath.Length + 1, AllocationType.Reserve | AllocationType.Commit, MemoryProtection.ReadWrite);
if (pBase == IntPtr.Zero) {
return new Win32Exception().PrintMsgAndReturnErrCode("VirtualAllocEx fail");
}
if (!Native.WriteProcessMemory(handle, pBase, libPath.ToCharArray(), libPath.Length, out _)) {
return new Win32Exception().PrintMsgAndReturnErrCode("WriteProcessMemory fail");
}
var hThread = Native.CreateRemoteThread(handle, IntPtr.Zero, 0, pLoadLibrary, pBase, 0, out _);
if (hThread == IntPtr.Zero) {
var e = new Win32Exception();
if (!Native.VirtualFreeEx(handle, pBase, 0, AllocationType.Release)) {
new Win32Exception().PrintMsgAndReturnErrCode("VirtualFreeEx fail");
// todo: refactor
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 = (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();
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;
}
return e.PrintMsgAndReturnErrCode("CreateRemoteThread fail");
}
return !Native.CloseHandle(hThread) ? new Win32Exception().PrintMsgAndReturnErrCode("CloseHandle fail") : 0;
}
}
}

View File

@@ -1,40 +0,0 @@
namespace YaeAchievement;
public static class Logger {
public enum Level {
Trace, Debug, Info, Warn, Error
}
public static void Error(string msg) {
Log(msg, Level.Error);
}
public static void Warn(string msg) {
Log(msg, Level.Warn);
}
public static void Info(string msg) {
Log(msg, Level.Info);
}
public static void Debug(string msg) {
Log(msg, Level.Debug);
}
public static void Trace(string msg) {
Log(msg, Level.Trace);
}
private static void Log(string msg, Level level) {
if (level >= GlobalVars.LogLevel) {
Console.WriteLine(msg);
}
}
public static void WriteLog(string msg, Level level = Level.Info) {
if (level >= GlobalVars.LogLevel) {
Console.Write($"{DateTime.Now:MM/dd HH:mm:ss} {level.ToString().ToUpper().PadLeft(5)} : {msg}");
}
}
}

6
src/NativeMethods.json Normal file
View File

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

21
src/NativeMethods.txt Normal file
View File

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

View File

@@ -1,21 +1,27 @@
using YaeAchievement;
using Proto;
using YaeAchievement;
using YaeAchievement.AppCenterSDK;
using YaeAchievement.AppCenterSDK.Models;
using YaeAchievement.res;
using static YaeAchievement.Utils;
InstallExitHook();
CheckSelfIsRunning();
TryDisableQuickEdit();
InstallExitHook();
InstallExceptionHook();
CheckSelfIsRunning();
await CheckVcRuntime();
CheckGenshinIsRunning();
Console.WriteLine("----------------------------------------------------");
Console.WriteLine($"YaeAchievement - 原神成就导出工具 ({GlobalVars.AppVersionName})");
Console.WriteLine("https://github.com/HolographicHat/YaeAchievement");
Console.WriteLine("----------------------------------------------------");
Console.WriteLine(@"----------------------------------------------------");
Console.WriteLine(App.AppBanner, GlobalVars.AppVersionName);
Console.WriteLine(@"https://github.com/HolographicHat/YaeAchievement");
Console.WriteLine(@"----------------------------------------------------");
LoadConfig();
CheckUpdate();
AppConfig.Load(args.GetOrNull(0) ?? "auto");
Export.ExportTo = ToUIntOrNull(args.GetOrNull(1)) ?? uint.MaxValue;
CheckUpdate(ToBooleanOrFalse(args.GetOrNull(2)));
AppCenter.Init();
new EventLog("AppInit") {
Properties = {
@@ -23,9 +29,29 @@ new EventLog("AppInit") {
{ "SystemVersion", DeviceHelper.GetSystemVersion() }
}
}.Enqueue();
StartAndWaitResult(GlobalVars.GamePath, str => {
GlobalVars.UnexpectedExit = false;
var list = AchievementAllDataNotify.Parser.ParseFrom(Convert.FromBase64String(str));
Export.Choose(list);
return true;
});
var usePreviousData = false;
var historyCache = new CacheFile("ExportData");
if (historyCache.LastWriteTime.AddMinutes(10) > DateTime.UtcNow) {
Console.WriteLine(App.UsePreviousData);
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;
var data = Convert.FromBase64String(str);
var list = AchievementAllDataNotify.Parser.ParseFrom(data);
historyCache.Write(data);
Export.Choose(list);
return true;
});
}

View File

@@ -1,584 +0,0 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: AchievementAllDataNotify.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
/// <summary>Holder for reflection information generated from AchievementAllDataNotify.proto</summary>
public static partial class AchievementAllDataNotifyReflection {
#region Descriptor
/// <summary>File descriptor for AchievementAllDataNotify.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static AchievementAllDataNotifyReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"Ch5BY2hpZXZlbWVudEFsbERhdGFOb3RpZnkucHJvdG8iowIKGEFjaGlldmVt",
"ZW50QWxsRGF0YU5vdGlmeRIzCgRsaXN0GAQgAygLMiUuQWNoaWV2ZW1lbnRB",
"bGxEYXRhTm90aWZ5LkFjaGlldmVtZW50GtEBCgtBY2hpZXZlbWVudBIKCgJp",
"ZBgOIAEoDRI8CgZzdGF0dXMYDSABKA4yLC5BY2hpZXZlbWVudEFsbERhdGFO",
"b3RpZnkuQWNoaWV2ZW1lbnQuU3RhdHVzEg8KB2N1cnJlbnQYDCABKA0SDQoF",
"dG90YWwYCCABKA0SEQoJdGltZXN0YW1wGAsgASgNIkUKBlN0YXR1cxILCgdJ",
"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)})
}));
}
#endregion
}
#region Messages
public sealed partial class AchievementAllDataNotify : pb::IMessage<AchievementAllDataNotify>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<AchievementAllDataNotify> _parser = new pb::MessageParser<AchievementAllDataNotify>(() => new AchievementAllDataNotify());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<AchievementAllDataNotify> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::AchievementAllDataNotifyReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementAllDataNotify() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementAllDataNotify(AchievementAllDataNotify other) : this() {
list_ = other.list_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementAllDataNotify Clone() {
return new AchievementAllDataNotify(this);
}
/// <summary>Field number for the "list" field.</summary>
public const int ListFieldNumber = 4;
private static readonly pb::FieldCodec<global::AchievementAllDataNotify.Types.Achievement> _repeated_list_codec
= pb::FieldCodec.ForMessage(34, 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)]
public pbc::RepeatedField<global::AchievementAllDataNotify.Types.Achievement> List {
get { return list_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as AchievementAllDataNotify);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(AchievementAllDataNotify other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if(!list_.Equals(other.list_)) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
hash ^= list_.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
list_.WriteTo(output, _repeated_list_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
list_.WriteTo(ref output, _repeated_list_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
size += list_.CalculateSize(_repeated_list_codec);
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(AchievementAllDataNotify other) {
if (other == null) {
return;
}
list_.Add(other.list_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 34: {
list_.AddEntriesFrom(input, _repeated_list_codec);
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 34: {
list_.AddEntriesFrom(ref input, _repeated_list_codec);
break;
}
}
}
}
#endif
#region Nested types
/// <summary>Container for nested types declared in the AchievementAllDataNotify message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static partial class Types {
public sealed partial class Achievement : pb::IMessage<Achievement>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<Achievement> _parser = new pb::MessageParser<Achievement>(() => new Achievement());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<Achievement> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::AchievementAllDataNotify.Descriptor.NestedTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Achievement() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Achievement(Achievement other) : this() {
id_ = other.id_;
status_ = other.status_;
current_ = other.current_;
total_ = other.total_;
timestamp_ = other.timestamp_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public Achievement Clone() {
return new Achievement(this);
}
/// <summary>Field number for the "id" field.</summary>
public const int IdFieldNumber = 14;
private uint id_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint Id {
get { return id_; }
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;
}
}
/// <summary>Field number for the "current" field.</summary>
public const int CurrentFieldNumber = 12;
private uint current_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint Current {
get { return current_; }
set {
current_ = value;
}
}
/// <summary>Field number for the "total" field.</summary>
public const int TotalFieldNumber = 8;
private uint total_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint Total {
get { return total_; }
set {
total_ = value;
}
}
/// <summary>Field number for the "timestamp" field.</summary>
public const int TimestampFieldNumber = 11;
private uint timestamp_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint Timestamp {
get { return timestamp_; }
set {
timestamp_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as Achievement);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(Achievement other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Id != other.Id) return false;
if (Status != other.Status) return false;
if (Current != other.Current) return false;
if (Total != other.Total) return false;
if (Timestamp != other.Timestamp) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (Id != 0) hash ^= Id.GetHashCode();
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) hash ^= Status.GetHashCode();
if (Current != 0) hash ^= Current.GetHashCode();
if (Total != 0) hash ^= Total.GetHashCode();
if (Timestamp != 0) hash ^= Timestamp.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Total != 0) {
output.WriteRawTag(64);
output.WriteUInt32(Total);
}
if (Timestamp != 0) {
output.WriteRawTag(88);
output.WriteUInt32(Timestamp);
}
if (Current != 0) {
output.WriteRawTag(96);
output.WriteUInt32(Current);
}
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
output.WriteRawTag(104);
output.WriteEnum((int) Status);
}
if (Id != 0) {
output.WriteRawTag(112);
output.WriteUInt32(Id);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Total != 0) {
output.WriteRawTag(64);
output.WriteUInt32(Total);
}
if (Timestamp != 0) {
output.WriteRawTag(88);
output.WriteUInt32(Timestamp);
}
if (Current != 0) {
output.WriteRawTag(96);
output.WriteUInt32(Current);
}
if (Status != global::AchievementAllDataNotify.Types.Achievement.Types.Status.Invalid) {
output.WriteRawTag(104);
output.WriteEnum((int) Status);
}
if (Id != 0) {
output.WriteRawTag(112);
output.WriteUInt32(Id);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (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 (Current != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Current);
}
if (Total != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Total);
}
if (Timestamp != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Timestamp);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(Achievement other) {
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.Current != 0) {
Current = other.Current;
}
if (other.Total != 0) {
Total = other.Total;
}
if (other.Timestamp != 0) {
Timestamp = other.Timestamp;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 64: {
Total = input.ReadUInt32();
break;
}
case 88: {
Timestamp = input.ReadUInt32();
break;
}
case 96: {
Current = input.ReadUInt32();
break;
}
case 104: {
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
break;
}
case 112: {
Id = input.ReadUInt32();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 64: {
Total = input.ReadUInt32();
break;
}
case 88: {
Timestamp = input.ReadUInt32();
break;
}
case 96: {
Current = input.ReadUInt32();
break;
}
case 104: {
Status = (global::AchievementAllDataNotify.Types.Achievement.Types.Status) input.ReadEnum();
break;
}
case 112: {
Id = input.ReadUInt32();
break;
}
}
}
}
#endif
#region Nested types
/// <summary>Container for nested types declared in the Achievement message type.</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static partial class Types {
public enum Status {
[pbr::OriginalName("INVALID")] Invalid = 0,
[pbr::OriginalName("UNFINISHED")] Unfinished = 1,
[pbr::OriginalName("FINISHED")] Finished = 2,
[pbr::OriginalName("REWARD_TAKEN")] RewardTaken = 3,
}
}
#endregion
}
}
#endregion
}
#endregion
#endregion Designer generated code

View File

@@ -1,588 +0,0 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: AchievementInfo.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
/// <summary>Holder for reflection information generated from AchievementInfo.proto</summary>
public static partial class AchievementInfoReflection {
#region Descriptor
/// <summary>File descriptor for AchievementInfo.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static AchievementInfoReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"ChVBY2hpZXZlbWVudEluZm8ucHJvdG8iUAoPQWNoaWV2ZW1lbnRJdGVtEgsK",
"A3ByZRgBIAEoDRINCgVncm91cBgCIAEoDRIMCgRuYW1lGAMgASgJEhMKC2Rl",
"c2NyaXB0aW9uGAQgASgJIugBCg9BY2hpZXZlbWVudEluZm8SDwoHdmVyc2lv",
"bhgBIAEoCRIqCgVncm91cBgCIAMoCzIbLkFjaGlldmVtZW50SW5mby5Hcm91",
"cEVudHJ5EioKBWl0ZW1zGAMgAygLMhsuQWNoaWV2ZW1lbnRJbmZvLkl0ZW1z",
"RW50cnkaLAoKR3JvdXBFbnRyeRILCgNrZXkYASABKA0SDQoFdmFsdWUYAiAB",
"KAk6AjgBGj4KCkl0ZW1zRW50cnkSCwoDa2V5GAEgASgNEh8KBXZhbHVlGAIg",
"ASgLMhAuQWNoaWV2ZW1lbnRJdGVtOgI4AWIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::AchievementItem), global::AchievementItem.Parser, new[]{ "Pre", "Group", "Name", "Description" }, null, null, null, null),
new pbr::GeneratedClrTypeInfo(typeof(global::AchievementInfo), global::AchievementInfo.Parser, new[]{ "Version", "Group", "Items" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { null, null, })
}));
}
#endregion
}
#region Messages
public sealed partial class AchievementItem : pb::IMessage<AchievementItem>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<AchievementItem> _parser = new pb::MessageParser<AchievementItem>(() => new AchievementItem());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<AchievementItem> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::AchievementInfoReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementItem() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementItem(AchievementItem other) : this() {
pre_ = other.pre_;
group_ = other.group_;
name_ = other.name_;
description_ = other.description_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementItem Clone() {
return new AchievementItem(this);
}
/// <summary>Field number for the "pre" field.</summary>
public const int PreFieldNumber = 1;
private uint pre_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint Pre {
get { return pre_; }
set {
pre_ = value;
}
}
/// <summary>Field number for the "group" field.</summary>
public const int GroupFieldNumber = 2;
private uint group_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint Group {
get { return group_; }
set {
group_ = value;
}
}
/// <summary>Field number for the "name" field.</summary>
public const int NameFieldNumber = 3;
private string name_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Name {
get { return name_; }
set {
name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "description" field.</summary>
public const int DescriptionFieldNumber = 4;
private string description_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Description {
get { return description_; }
set {
description_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as AchievementItem);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(AchievementItem other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Pre != other.Pre) return false;
if (Group != other.Group) return false;
if (Name != other.Name) return false;
if (Description != other.Description) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (Pre != 0) hash ^= Pre.GetHashCode();
if (Group != 0) hash ^= Group.GetHashCode();
if (Name.Length != 0) hash ^= Name.GetHashCode();
if (Description.Length != 0) hash ^= Description.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Pre != 0) {
output.WriteRawTag(8);
output.WriteUInt32(Pre);
}
if (Group != 0) {
output.WriteRawTag(16);
output.WriteUInt32(Group);
}
if (Name.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Name);
}
if (Description.Length != 0) {
output.WriteRawTag(34);
output.WriteString(Description);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Pre != 0) {
output.WriteRawTag(8);
output.WriteUInt32(Pre);
}
if (Group != 0) {
output.WriteRawTag(16);
output.WriteUInt32(Group);
}
if (Name.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Name);
}
if (Description.Length != 0) {
output.WriteRawTag(34);
output.WriteString(Description);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (Pre != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Pre);
}
if (Group != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(Group);
}
if (Name.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (Description.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Description);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(AchievementItem other) {
if (other == null) {
return;
}
if (other.Pre != 0) {
Pre = other.Pre;
}
if (other.Group != 0) {
Group = other.Group;
}
if (other.Name.Length != 0) {
Name = other.Name;
}
if (other.Description.Length != 0) {
Description = other.Description;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Pre = input.ReadUInt32();
break;
}
case 16: {
Group = input.ReadUInt32();
break;
}
case 26: {
Name = input.ReadString();
break;
}
case 34: {
Description = input.ReadString();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 8: {
Pre = input.ReadUInt32();
break;
}
case 16: {
Group = input.ReadUInt32();
break;
}
case 26: {
Name = input.ReadString();
break;
}
case 34: {
Description = input.ReadString();
break;
}
}
}
}
#endif
}
public sealed partial class AchievementInfo : pb::IMessage<AchievementInfo>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<AchievementInfo> _parser = new pb::MessageParser<AchievementInfo>(() => new AchievementInfo());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<AchievementInfo> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::AchievementInfoReflection.Descriptor.MessageTypes[1]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementInfo() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementInfo(AchievementInfo other) : this() {
version_ = other.version_;
group_ = other.group_.Clone();
items_ = other.items_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public AchievementInfo Clone() {
return new AchievementInfo(this);
}
/// <summary>Field number for the "version" field.</summary>
public const int VersionFieldNumber = 1;
private string version_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Version {
get { return version_; }
set {
version_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "group" field.</summary>
public const int GroupFieldNumber = 2;
private static readonly pbc::MapField<uint, string>.Codec _map_group_codec
= new pbc::MapField<uint, string>.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForString(18, ""), 18);
private readonly pbc::MapField<uint, string> group_ = new pbc::MapField<uint, string>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public pbc::MapField<uint, string> Group {
get { return group_; }
}
/// <summary>Field number for the "items" field.</summary>
public const int ItemsFieldNumber = 3;
private static readonly pbc::MapField<uint, global::AchievementItem>.Codec _map_items_codec
= new pbc::MapField<uint, global::AchievementItem>.Codec(pb::FieldCodec.ForUInt32(8, 0), pb::FieldCodec.ForMessage(18, global::AchievementItem.Parser), 26);
private readonly pbc::MapField<uint, global::AchievementItem> items_ = new pbc::MapField<uint, global::AchievementItem>();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public pbc::MapField<uint, global::AchievementItem> Items {
get { return items_; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as AchievementInfo);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(AchievementInfo other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Version != other.Version) return false;
if (!Group.Equals(other.Group)) return false;
if (!Items.Equals(other.Items)) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (Version.Length != 0) hash ^= Version.GetHashCode();
hash ^= Group.GetHashCode();
hash ^= Items.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Version.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Version);
}
group_.WriteTo(output, _map_group_codec);
items_.WriteTo(output, _map_items_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Version.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Version);
}
group_.WriteTo(ref output, _map_group_codec);
items_.WriteTo(ref output, _map_items_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (Version.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Version);
}
size += group_.CalculateSize(_map_group_codec);
size += items_.CalculateSize(_map_items_codec);
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(AchievementInfo other) {
if (other == null) {
return;
}
if (other.Version.Length != 0) {
Version = other.Version;
}
group_.Add(other.group_);
items_.Add(other.items_);
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 10: {
Version = input.ReadString();
break;
}
case 18: {
group_.AddEntriesFrom(input, _map_group_codec);
break;
}
case 26: {
items_.AddEntriesFrom(input, _map_items_codec);
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 10: {
Version = input.ReadString();
break;
}
case 18: {
group_.AddEntriesFrom(ref input, _map_group_codec);
break;
}
case 26: {
items_.AddEntriesFrom(ref input, _map_items_codec);
break;
}
}
}
}
#endif
}
#endregion
#endregion Designer generated code

View File

@@ -1,341 +0,0 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: CacheItem.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
/// <summary>Holder for reflection information generated from CacheItem.proto</summary>
public static partial class CacheItemReflection {
#region Descriptor
/// <summary>File descriptor for CacheItem.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static CacheItemReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"Cg9DYWNoZUl0ZW0ucHJvdG8iTQoJQ2FjaGVJdGVtEg8KB3ZlcnNpb24YASAB",
"KAUSEAoIY2hlY2tzdW0YAiABKAkSDAoEZXRhZxgDIAEoCRIPCgdjb250ZW50",
"GAQgASgMYgZwcm90bzM="));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::CacheItem), global::CacheItem.Parser, new[]{ "Version", "Checksum", "Etag", "Content" }, null, null, null, null)
}));
}
#endregion
}
#region Messages
public sealed partial class CacheItem : pb::IMessage<CacheItem>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<CacheItem> _parser = new pb::MessageParser<CacheItem>(() => new CacheItem());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<CacheItem> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::CacheItemReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public CacheItem() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public CacheItem(CacheItem other) : this() {
version_ = other.version_;
checksum_ = other.checksum_;
etag_ = other.etag_;
content_ = other.content_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public CacheItem Clone() {
return new CacheItem(this);
}
/// <summary>Field number for the "version" field.</summary>
public const int VersionFieldNumber = 1;
private int version_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int Version {
get { return version_; }
set {
version_ = value;
}
}
/// <summary>Field number for the "checksum" field.</summary>
public const int ChecksumFieldNumber = 2;
private string checksum_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Checksum {
get { return checksum_; }
set {
checksum_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "etag" field.</summary>
public const int EtagFieldNumber = 3;
private string etag_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Etag {
get { return etag_; }
set {
etag_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "content" field.</summary>
public const int ContentFieldNumber = 4;
private pb::ByteString content_ = pb::ByteString.Empty;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public pb::ByteString Content {
get { return content_; }
set {
content_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as CacheItem);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(CacheItem other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (Version != other.Version) return false;
if (Checksum != other.Checksum) return false;
if (Etag != other.Etag) return false;
if (Content != other.Content) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (Version != 0) hash ^= Version.GetHashCode();
if (Checksum.Length != 0) hash ^= Checksum.GetHashCode();
if (Etag.Length != 0) hash ^= Etag.GetHashCode();
if (Content.Length != 0) hash ^= Content.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Version != 0) {
output.WriteRawTag(8);
output.WriteInt32(Version);
}
if (Checksum.Length != 0) {
output.WriteRawTag(18);
output.WriteString(Checksum);
}
if (Etag.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Etag);
}
if (Content.Length != 0) {
output.WriteRawTag(34);
output.WriteBytes(Content);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Version != 0) {
output.WriteRawTag(8);
output.WriteInt32(Version);
}
if (Checksum.Length != 0) {
output.WriteRawTag(18);
output.WriteString(Checksum);
}
if (Etag.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Etag);
}
if (Content.Length != 0) {
output.WriteRawTag(34);
output.WriteBytes(Content);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (Version != 0) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Version);
}
if (Checksum.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Checksum);
}
if (Etag.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Etag);
}
if (Content.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeBytesSize(Content);
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(CacheItem other) {
if (other == null) {
return;
}
if (other.Version != 0) {
Version = other.Version;
}
if (other.Checksum.Length != 0) {
Checksum = other.Checksum;
}
if (other.Etag.Length != 0) {
Etag = other.Etag;
}
if (other.Content.Length != 0) {
Content = other.Content;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
Version = input.ReadInt32();
break;
}
case 18: {
Checksum = input.ReadString();
break;
}
case 26: {
Etag = input.ReadString();
break;
}
case 34: {
Content = input.ReadBytes();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 8: {
Version = input.ReadInt32();
break;
}
case 18: {
Checksum = input.ReadString();
break;
}
case 26: {
Etag = input.ReadString();
break;
}
case 34: {
Content = input.ReadBytes();
break;
}
}
}
}
#endif
}
#endregion
#endregion Designer generated code

View File

@@ -1,454 +0,0 @@
// <auto-generated>
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: UpdateInfo.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021, 8981
#region Designer generated code
using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
/// <summary>Holder for reflection information generated from UpdateInfo.proto</summary>
public static partial class UpdateInfoReflection {
#region Descriptor
/// <summary>File descriptor for UpdateInfo.proto</summary>
public static pbr::FileDescriptor Descriptor {
get { return descriptor; }
}
private static pbr::FileDescriptor descriptor;
static UpdateInfoReflection() {
byte[] descriptorData = global::System.Convert.FromBase64String(
string.Concat(
"ChBVcGRhdGVJbmZvLnByb3RvIqwBCgpVcGRhdGVJbmZvEhMKC3ZlcnNpb25D",
"b2RlGAEgASgNEhMKC3ZlcnNpb25OYW1lGAIgASgJEhMKC2Rlc2NyaXB0aW9u",
"GAMgASgJEhMKC3BhY2thZ2VMaW5rGAQgASgJEhMKC2ZvcmNlVXBkYXRlGAUg",
"ASgIEhkKEWVuYWJsZUxpYkRvd25sb2FkGAYgASgIEhoKEmVuYWJsZUF1dG9E",
"b3dubG9hZBgHIAEoCGIGcHJvdG8z"));
descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
new pbr::FileDescriptor[] { },
new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
new pbr::GeneratedClrTypeInfo(typeof(global::UpdateInfo), global::UpdateInfo.Parser, new[]{ "VersionCode", "VersionName", "Description", "PackageLink", "ForceUpdate", "EnableLibDownload", "EnableAutoDownload" }, null, null, null, null)
}));
}
#endregion
}
#region Messages
public sealed partial class UpdateInfo : pb::IMessage<UpdateInfo>
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
, pb::IBufferMessage
#endif
{
private static readonly pb::MessageParser<UpdateInfo> _parser = new pb::MessageParser<UpdateInfo>(() => new UpdateInfo());
private pb::UnknownFieldSet _unknownFields;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pb::MessageParser<UpdateInfo> Parser { get { return _parser; } }
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public static pbr::MessageDescriptor Descriptor {
get { return global::UpdateInfoReflection.Descriptor.MessageTypes[0]; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
pbr::MessageDescriptor pb::IMessage.Descriptor {
get { return Descriptor; }
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public UpdateInfo() {
OnConstruction();
}
partial void OnConstruction();
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public UpdateInfo(UpdateInfo other) : this() {
versionCode_ = other.versionCode_;
versionName_ = other.versionName_;
description_ = other.description_;
packageLink_ = other.packageLink_;
forceUpdate_ = other.forceUpdate_;
enableLibDownload_ = other.enableLibDownload_;
enableAutoDownload_ = other.enableAutoDownload_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public UpdateInfo Clone() {
return new UpdateInfo(this);
}
/// <summary>Field number for the "versionCode" field.</summary>
public const int VersionCodeFieldNumber = 1;
private uint versionCode_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public uint VersionCode {
get { return versionCode_; }
set {
versionCode_ = value;
}
}
/// <summary>Field number for the "versionName" field.</summary>
public const int VersionNameFieldNumber = 2;
private string versionName_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string VersionName {
get { return versionName_; }
set {
versionName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "description" field.</summary>
public const int DescriptionFieldNumber = 3;
private string description_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string Description {
get { return description_; }
set {
description_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "packageLink" field.</summary>
public const int PackageLinkFieldNumber = 4;
private string packageLink_ = "";
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public string PackageLink {
get { return packageLink_; }
set {
packageLink_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
}
}
/// <summary>Field number for the "forceUpdate" field.</summary>
public const int ForceUpdateFieldNumber = 5;
private bool forceUpdate_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool ForceUpdate {
get { return forceUpdate_; }
set {
forceUpdate_ = value;
}
}
/// <summary>Field number for the "enableLibDownload" field.</summary>
public const int EnableLibDownloadFieldNumber = 6;
private bool enableLibDownload_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool EnableLibDownload {
get { return enableLibDownload_; }
set {
enableLibDownload_ = value;
}
}
/// <summary>Field number for the "enableAutoDownload" field.</summary>
public const int EnableAutoDownloadFieldNumber = 7;
private bool enableAutoDownload_;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool EnableAutoDownload {
get { return enableAutoDownload_; }
set {
enableAutoDownload_ = value;
}
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override bool Equals(object other) {
return Equals(other as UpdateInfo);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public bool Equals(UpdateInfo other) {
if (ReferenceEquals(other, null)) {
return false;
}
if (ReferenceEquals(other, this)) {
return true;
}
if (VersionCode != other.VersionCode) return false;
if (VersionName != other.VersionName) return false;
if (Description != other.Description) return false;
if (PackageLink != other.PackageLink) return false;
if (ForceUpdate != other.ForceUpdate) return false;
if (EnableLibDownload != other.EnableLibDownload) return false;
if (EnableAutoDownload != other.EnableAutoDownload) return false;
return Equals(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override int GetHashCode() {
int hash = 1;
if (VersionCode != 0) hash ^= VersionCode.GetHashCode();
if (VersionName.Length != 0) hash ^= VersionName.GetHashCode();
if (Description.Length != 0) hash ^= Description.GetHashCode();
if (PackageLink.Length != 0) hash ^= PackageLink.GetHashCode();
if (ForceUpdate != false) hash ^= ForceUpdate.GetHashCode();
if (EnableLibDownload != false) hash ^= EnableLibDownload.GetHashCode();
if (EnableAutoDownload != false) hash ^= EnableAutoDownload.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
return hash;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public override string ToString() {
return pb::JsonFormatter.ToDiagnosticString(this);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (VersionCode != 0) {
output.WriteRawTag(8);
output.WriteUInt32(VersionCode);
}
if (VersionName.Length != 0) {
output.WriteRawTag(18);
output.WriteString(VersionName);
}
if (Description.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Description);
}
if (PackageLink.Length != 0) {
output.WriteRawTag(34);
output.WriteString(PackageLink);
}
if (ForceUpdate != false) {
output.WriteRawTag(40);
output.WriteBool(ForceUpdate);
}
if (EnableLibDownload != false) {
output.WriteRawTag(48);
output.WriteBool(EnableLibDownload);
}
if (EnableAutoDownload != false) {
output.WriteRawTag(56);
output.WriteBool(EnableAutoDownload);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (VersionCode != 0) {
output.WriteRawTag(8);
output.WriteUInt32(VersionCode);
}
if (VersionName.Length != 0) {
output.WriteRawTag(18);
output.WriteString(VersionName);
}
if (Description.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Description);
}
if (PackageLink.Length != 0) {
output.WriteRawTag(34);
output.WriteString(PackageLink);
}
if (ForceUpdate != false) {
output.WriteRawTag(40);
output.WriteBool(ForceUpdate);
}
if (EnableLibDownload != false) {
output.WriteRawTag(48);
output.WriteBool(EnableLibDownload);
}
if (EnableAutoDownload != false) {
output.WriteRawTag(56);
output.WriteBool(EnableAutoDownload);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public int CalculateSize() {
int size = 0;
if (VersionCode != 0) {
size += 1 + pb::CodedOutputStream.ComputeUInt32Size(VersionCode);
}
if (VersionName.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(VersionName);
}
if (Description.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Description);
}
if (PackageLink.Length != 0) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(PackageLink);
}
if (ForceUpdate != false) {
size += 1 + 1;
}
if (EnableLibDownload != false) {
size += 1 + 1;
}
if (EnableAutoDownload != false) {
size += 1 + 1;
}
if (_unknownFields != null) {
size += _unknownFields.CalculateSize();
}
return size;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(UpdateInfo other) {
if (other == null) {
return;
}
if (other.VersionCode != 0) {
VersionCode = other.VersionCode;
}
if (other.VersionName.Length != 0) {
VersionName = other.VersionName;
}
if (other.Description.Length != 0) {
Description = other.Description;
}
if (other.PackageLink.Length != 0) {
PackageLink = other.PackageLink;
}
if (other.ForceUpdate != false) {
ForceUpdate = other.ForceUpdate;
}
if (other.EnableLibDownload != false) {
EnableLibDownload = other.EnableLibDownload;
}
if (other.EnableAutoDownload != false) {
EnableAutoDownload = other.EnableAutoDownload;
}
_unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
public void MergeFrom(pb::CodedInputStream input) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
input.ReadRawMessage(this);
#else
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
break;
case 8: {
VersionCode = input.ReadUInt32();
break;
}
case 18: {
VersionName = input.ReadString();
break;
}
case 26: {
Description = input.ReadString();
break;
}
case 34: {
PackageLink = input.ReadString();
break;
}
case 40: {
ForceUpdate = input.ReadBool();
break;
}
case 48: {
EnableLibDownload = input.ReadBool();
break;
}
case 56: {
EnableAutoDownload = input.ReadBool();
break;
}
}
}
#endif
}
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
[global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
uint tag;
while ((tag = input.ReadTag()) != 0) {
switch(tag) {
default:
_unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
break;
case 8: {
VersionCode = input.ReadUInt32();
break;
}
case 18: {
VersionName = input.ReadString();
break;
}
case 26: {
Description = input.ReadString();
break;
}
case 34: {
PackageLink = input.ReadString();
break;
}
case 40: {
ForceUpdate = input.ReadBool();
break;
}
case 48: {
EnableLibDownload = input.ReadBool();
break;
}
case 56: {
EnableAutoDownload = input.ReadBool();
break;
}
}
}
}
#endif
}
#endregion
#endregion Designer generated code

View File

@@ -1,215 +1,172 @@
using System.ComponentModel;
using Microsoft.Win32;
using System.ComponentModel;
using System.Diagnostics;
using System.IO.Compression;
using System.IO.Pipes;
using System.Net;
using System.Net.Http.Headers;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json.Nodes;
using Google.Protobuf;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Console;
using Proto;
using YaeAchievement.AppCenterSDK;
using YaeAchievement.Win32;
using static YaeAchievement.Win32.OpenFileFlags;
using YaeAchievement.res;
namespace YaeAchievement;
public static class Utils {
public static readonly Lazy<HttpClient> CHttpClient = new (() => {
var c = new HttpClient(new HttpClientHandler {
Proxy = GlobalVars.DebugProxy ? new WebProxy("http://127.0.0.1:8888") : null,
AutomaticDecompression = DecompressionMethods.Brotli | DecompressionMethods.GZip
}) {
DefaultRequestHeaders = {
UserAgent = {
new ProductInfoHeaderValue("YaeAchievement", GlobalVars.AppVersion.ToString(2))
}
public static readonly HttpClient CHttpClient = new (new HttpClientHandler {
Proxy = GlobalVars.DebugProxy ? new WebProxy("http://127.0.0.1:8888") : null,
AutomaticDecompression = DecompressionMethods.Brotli | DecompressionMethods.GZip
}) {
DefaultRequestHeaders = {
UserAgent = {
new ProductInfoHeaderValue("YaeAchievement", GlobalVars.AppVersion.ToString(2))
}
};
return c;
});
}
};
public static string GetBucketFileAsString(string path, bool cache = true) {
return Encoding.UTF8.GetString(GetBucketFileAsByteArray(path, cache));
}
public static byte[] GetBucketFileAsByteArray(string path, bool cache = true) {
using var msg = new HttpRequestMessage {
Method = HttpMethod.Get,
RequestUri = new Uri($"{GlobalVars.BucketHost}/{path}")
};
CacheItem? ci = null;
var cacheName = cache ? $"./cache/{CalculateMD5(path)[..16]}.miko" : "";
if (cache) {
Directory.CreateDirectory("cache");
if (File.Exists(cacheName)) {
using var input = File.OpenRead(cacheName);
using var dInput = new GZipStream(input, CompressionMode.Decompress);
ci = CacheItem.Parser.ParseFrom(dInput);
msg.Headers.TryAddWithoutValidation("If-None-Match", $"{ci.Etag}");
try {
using var msg = new HttpRequestMessage {
Method = HttpMethod.Get,
RequestUri = new Uri($"{GlobalVars.BucketHost}/{path}")
};
var cacheFile = new CacheFile(path);
if (cache && cacheFile.Exists()) {
msg.Headers.TryAddWithoutValidation("If-None-Match", $"{cacheFile.Read().Etag}");
}
using var response = CHttpClient.Send(msg);
if (cache && response.StatusCode == HttpStatusCode.NotModified) {
return cacheFile.Read().Content.ToByteArray();
}
response.EnsureSuccessStatusCode();
var responseBytes = response.Content.ReadAsByteArrayAsync().Result;
if (cache) {
var etag = response.Headers.ETag!.Tag;
cacheFile.Write(responseBytes, etag);
}
return responseBytes;
} catch (Exception e) when(e is SocketException or TaskCanceledException) {
Console.WriteLine(App.NetworkError, e.Message);
Environment.Exit(-1);
return null!;
}
using var response = CHttpClient.Value.Send(msg);
if (cache && response.StatusCode == HttpStatusCode.NotModified) {
return ci!.Content.ToByteArray();
}
response.EnsureSuccessStatusCode();
var responseBytes = response.Content.ReadAsByteArrayAsync().Result;
if (cache) {
var etag = response.Headers.ETag!.Tag;
using var os = File.OpenWrite(cacheName);
using var cos = new GZipStream(os, CompressionLevel.SmallestSize);
new CacheItem {
Etag = etag,
Version = 3,
Checksum = CalculateMD5(responseBytes),
Content = ByteString.CopyFrom(responseBytes)
}.WriteTo(cos);
}
return responseBytes;
}
// ReSharper disable once InconsistentNaming
private static string CalculateMD5(string text) {
return CalculateMD5(Encoding.UTF8.GetBytes(text));
public static T? GetOrNull<T>(this T[] array, uint index) where T : class {
return array.Length > index ? array[index] : null;
}
public static uint? ToUIntOrNull(string? value) {
return value != null ? uint.TryParse(value, out var result) ? result : null : null;
}
// ReSharper disable once InconsistentNaming
private static string CalculateMD5(byte[] bytes) {
using var md5 = MD5.Create();
var b = md5.ComputeHash(bytes);
return Convert.ToHexString(b).ToLower();
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);
var hGlobal = (HANDLE) Marshal.AllocHGlobal((text.Length + 1) * 2);
var hPtr = (nint) 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();
}
}
public static void LoadConfig() {
var conf = JsonNode.Parse(File.ReadAllText(GlobalVars.ConfigFileName))!;
var path = conf["location"];
if (path == null || !CheckGamePathValid(path.GetValue<string>())) {
GlobalVars.GamePath = SelectGameExecutable();
conf["location"] = GlobalVars.GamePath;
File.WriteAllText(GlobalVars.ConfigFileName, conf.ToJsonString());
} else {
GlobalVars.GamePath = path.GetValue<string>();
}
}
public static void CheckUpdate() {
// ReSharper disable once NotAccessedField.Local
private static UpdateInfo _updateInfo = null!;
public static void CheckUpdate(bool useLocalLib) {
var info = UpdateInfo.Parser.ParseFrom(GetBucketFileAsByteArray("schicksal/version"))!;
if (GlobalVars.AppVersionCode != info.VersionCode) {
Console.WriteLine($"有可用更新: {GlobalVars.AppVersionName} => {info.VersionName}");
Console.WriteLine($"更新内容: \n{info.Description}");
if (GlobalVars.AppVersionCode < info.VersionCode) {
Console.WriteLine(App.UpdateNewVersion, GlobalVars.AppVersionName, info.VersionName);
Console.WriteLine(App.UpdateDescription, info.Description);
if (info.EnableAutoDownload) {
Console.WriteLine("正在下载更新包...");
var fullPath = Path.GetFullPath($"update.{Path.GetExtension(info.PackageLink)}");
File.WriteAllBytes(fullPath, GetBucketFileAsByteArray(info.PackageLink));
Console.WriteLine("关闭程序后, 将压缩包解压至当前目录即可完成更新.");
ShellOpen(fullPath);
Console.WriteLine(App.UpdateDownloading);
var tmpPath = Path.GetTempFileName();
File.WriteAllBytes(tmpPath, GetBucketFileAsByteArray(info.PackageLink));
var updaterArgs = $"{Environment.ProcessId}|{Environment.ProcessPath}|{tmpPath}";
var updaterPath = Path.Combine(GlobalVars.DataPath, "update.exe");
File.WriteAllBytes(updaterPath, App.Updater);
ShellOpen(updaterPath, updaterArgs.ToBytes().ToBase64());
GlobalVars.PauseOnExit = false;
Environment.Exit(0);
}
Console.WriteLine($"下载地址: {info.PackageLink}");
Console.WriteLine(App.DownloadLink, info.PackageLink);
if (info.ForceUpdate) {
//Console.WriteLine("在完成此次更新前, 程序可能无法正常使用.");
Environment.Exit(0);
}
}
if (info.EnableLibDownload) {
File.WriteAllBytes(GlobalVars.LibName, GetBucketFileAsByteArray("schicksal/lib.dll"));
if (useLocalLib) {
Console.WriteLine(@"[DEBUG] Use local native lib.");
File.Copy(Path.Combine(GlobalVars.AppPath, "YaeAchievementLib.dll"), GlobalVars.LibFilePath, true);
} else if (info.EnableLibDownload) {
File.WriteAllBytes(GlobalVars.LibFilePath, GetBucketFileAsByteArray("schicksal/lib.dll"));
}
}
public static void CheckSelfIsRunning() {
Process.EnterDebugMode();
var cur = Process.GetCurrentProcess();
foreach (var process in Process.GetProcesses().Where(process => process.Id != cur.Id)) {
if (process.ProcessName == cur.ProcessName) {
Logger.Error("另一个实例正在运行,请关闭后重试");
Environment.Exit(302);
}
}
Process.LeaveDebugMode();
}
public static bool ShellOpen(string path) {
return new Process {
StartInfo = {
FileName = path,
UseShellExecute = true
}
}.Start();
_updateInfo = info;
}
private static bool CheckGamePathValid(string path) {
var dir = Path.GetDirectoryName(path)!;
return !GlobalVars.CheckGamePath ||
File.Exists($"{dir}/UnityPlayer.dll") && File.Exists($"{dir}/mhypbase.dll");
}
private static string SelectGameExecutable() {
var fnPtr = Marshal.AllocHGlobal(32768);
Native.RtlZeroMemory(fnPtr, 32768);
var ofn = new OpenFileName {
file = fnPtr,
size = Marshal.SizeOf<OpenFileName>(),
owner = Native.GetConsoleWindow(),
flags = Explorer | NoNetworkButton | FileMustExist | NoChangeDir,
title = "选择主程序",
filter = "国服/国际服主程序 (YuanShen/GenshinImpact.exe)\0YuanShen.exe;GenshinImpact.exe\0",
maxFile = 32768
};
new Thread(() => {
var handle = Native.FindWindow("#32770", "选择主程序");
while (handle == IntPtr.Zero) {
handle = Native.FindWindow("#32770", "选择主程序");
Thread.Sleep(1);
public static void CheckSelfIsRunning() {
try {
Process.EnterDebugMode();
var cur = Process.GetCurrentProcess();
foreach (var process in Process.GetProcesses().Where(process => process.Id != cur.Id)) {
if (process.ProcessName == cur.ProcessName) {
Console.WriteLine(App.AnotherInstance);
Environment.Exit(302);
}
}
var currentThreadId = Native.GetCurrentThreadId();
var foregroundThreadId = Native.GetWindowThreadProcessId(Native.GetForegroundWindow(), out _);
Native.AttachThreadInput(currentThreadId, foregroundThreadId, true);
Native.SetWindowPos(handle, new IntPtr(-1), 0, 0, 0, 0, 1 | 2);
Native.SetForegroundWindow(handle);
Native.AttachThreadInput(currentThreadId, foregroundThreadId, false);
}).Start();
if(!Native.GetOpenFileName(ofn)) {
var err = Native.CommDlgExtendedError();
if (err != 0) {
throw new SystemException($"Dialog error: {err}");
}
Console.WriteLine("操作被取消");
Environment.Exit(0);
}
var path = Marshal.PtrToStringAuto(fnPtr)!;
Marshal.FreeHGlobal(fnPtr);
return path;
Process.LeaveDebugMode();
} catch (Win32Exception) {}
}
// 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 bool ShellOpen(string path, string? args = null) {
try {
var startInfo = new ProcessStartInfo {
FileName = path,
UseShellExecute = true
};
if (args != null) {
startInfo.Arguments = args;
}
return new Process {
StartInfo = startInfo
}.Start();
} catch (Exception) {
return false;
}
}
// ReSharper disable once UnusedMethodReturnValue.Global
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() {
Process.EnterDebugMode();
foreach (var process in Process.GetProcesses()) {
if (process.ProcessName is "GenshinImpact" or "YuanShen") {
Console.WriteLine("原神正在运行,请关闭后重试");
if (process.ProcessName is "GenshinImpact" or "YuanShen"
&& !process.HasExited
&& process.MainWindowHandle != nint.Zero
) {
Console.WriteLine(App.GenshinIsRunning, process.Id);
Environment.Exit(301);
}
}
@@ -222,56 +179,93 @@ public static class Utils {
public static void InstallExitHook() {
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
proc?.Kill();
Logger.Info("按任意键退出");
Console.ReadKey();
if (GlobalVars.PauseOnExit) {
Console.WriteLine(App.PressKeyToExit);
Console.ReadKey();
}
};
}
public static void InstallExceptionHook() {
AppDomain.CurrentDomain.UnhandledException += (_, e) => {
Console.WriteLine(e.ExceptionObject.ToString());
Logger.Error("正在上报错误信息...");
AppCenter.TrackCrash((Exception) e.ExceptionObject);
AppCenter.Upload();
var ex = e.ExceptionObject;
switch (ex) {
case ApplicationException ex1:
Console.WriteLine(ex1.Message);
break;
case SocketException ex2:
Console.WriteLine(App.ExceptionNetwork, nameof(SocketException), ex2.Message);
break;
case HttpRequestException ex3:
Console.WriteLine(App.ExceptionNetwork, nameof(HttpRequestException), ex3.Message);
break;
default:
Console.WriteLine(ex.ToString());
Console.WriteLine(App.UploadError);
AppCenter.TrackCrash((Exception) e.ExceptionObject);
AppCenter.Upload();
break;
}
Environment.Exit(-1);
};
}
private static bool CheckGenshinIsLatestVersion(string path) {
#if DEBUG
return true;
#else
if (!File.Exists(path)) return false;
var hash = File.ReadAllBytes(path).MD5Hash();
return hash == _updateInfo.CurrentCNGameHash || hash == _updateInfo.CurrentOSGameHash;
#endif
}
// ReSharper disable once UnusedMethodReturnValue.Global
public static Thread StartAndWaitResult(string exePath, Func<string, bool> onReceive) {
const string lib = "C:/ProgramData/yae.dll";
File.Copy(Path.GetFullPath(GlobalVars.LibName), lib, true);
if (!CheckGenshinIsLatestVersion(exePath)) {
Console.WriteLine(App.GenshinHashError);
Environment.Exit(0);
}
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
try {
File.Delete(GlobalVars.LibFilePath);
} catch (Exception) { /* ignored */ }
};
if (!Injector.CreateProcess(exePath, out var hProcess, out var hThread, out var pid)) {
Environment.Exit(new Win32Exception().PrintMsgAndReturnErrCode("ICreateProcess fail"));
}
if (Injector.LoadLibraryAndInject(hProcess, lib) != 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"));
}
}
Logger.Info($"原神正在启动 ({pid})");
Console.WriteLine(App.GameLoading, pid);
proc = Process.GetProcessById(Convert.ToInt32(pid));
proc.EnableRaisingEvents = true;
proc.Exited += (_, _) => {
if (GlobalVars.UnexpectedExit) {
if (GlobalVars.UnexpectedExit)
{
proc = null;
Console.WriteLine("游戏进程异常退出");
Console.WriteLine(App.GameProcessExit);
Environment.Exit(114514);
}
};
AppDomain.CurrentDomain.ProcessExit += (_, _) => {
File.Delete(lib);
};
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();
@@ -291,4 +285,42 @@ public static class Utils {
th.Start();
return th;
}
}
public static async Task CheckVcRuntime() {
using var root = Registry.LocalMachine;
using var sub = root.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall")!;
var installed = sub.GetSubKeyNames()
.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) {
Console.WriteLine(App.VcRuntimeDownload);
var pkgPath = Path.Combine(GlobalVars.DataPath, "vc_redist.x64.exe");
byte[] bytes;
try {
bytes = await CHttpClient.GetByteArrayAsync("https://aka.ms/vs/17/release/vc_redist.x64.exe");
} catch (Exception e) when(e is SocketException or TaskCanceledException) {
Console.WriteLine(App.NetworkError, e.Message);
Environment.Exit(-1);
return;
}
await File.WriteAllBytesAsync(pkgPath, bytes);
Console.WriteLine(App.VcRuntimeInstalling);
using var process = new Process {
StartInfo = {
FileName = pkgPath,
Arguments = "/install /passive /norestart"
}
};
process.Start();
await process.WaitForExitAsync();
File.Delete(pkgPath);
}
}
}

View File

@@ -1,14 +0,0 @@
namespace YaeAchievement.Win32;
[Flags]
public enum AllocationType : uint {
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}

View File

@@ -1,9 +0,0 @@
namespace YaeAchievement.Win32;
[Flags]
public enum CreationFlags : uint {
CreateSuspended = 0x00000004,
DetachedProcess = 0x00000008,
CreateNoWindow = 0x08000000,
ExtendedStartupInfoPresent = 0x00080000
}

View File

@@ -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) {
Logger.Error($"{msg}: {ex.Message}");
AppCenter.TrackCrash(ex, false);
return ex.NativeErrorCode;
}
}

View File

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

View File

@@ -1,150 +0,0 @@
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Security;
namespace YaeAchievement.Win32;
[SuppressMessage("Interoperability", "CA1401:P/Invokes 应该是不可见的")]
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)]
[SuppressMessage("Globalization", "CA2101:指定对 P/Invoke 字符串参数进行封送处理")]
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")]
public static extern IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttributes,
int dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
out IntPtr lpThreadId
);
[DllImport("kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
// 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("comdlg32.dll", SetLastError = true)]
public static extern int CommDlgExtendedError();
[DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
[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")]
public static extern bool EmptyClipboard();
[DllImport("kernel32.dll")]
public static extern void RtlZeroMemory(IntPtr dst, ulong length);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
[DllImport("user32.dll", SetLastError = true)]
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint pid);
[DllImport("kernel32.dll")]
public static extern uint GetCurrentThreadId();
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", SetLastError = true)]
public static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);
[DllImport("gdi32.dll")]
public static extern int GetDeviceCaps(IntPtr hdc, int nIndex);
[DllImport("user32.dll")]
public static extern IntPtr GetDC(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ReleaseDC(IntPtr hWnd, IntPtr hdc);
}

View File

@@ -1,9 +0,0 @@
namespace YaeAchievement.Win32;
[Flags]
public enum OpenFileFlags : uint {
Explorer = 0x00080000,
NoChangeDir = 0x00000008,
FileMustExist = 0x00001000,
NoNetworkButton = 0x00020000,
}

View File

@@ -1,32 +0,0 @@
using System.Runtime.InteropServices;
// ReSharper disable MemberCanBePrivate.Global
// ReSharper disable FieldCanBeMadeReadOnly.Global
namespace YaeAchievement.Win32;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct OpenFileName {
public int size;
public IntPtr owner;
public IntPtr instance;
public string filter;
public IntPtr customFilter;
public int maxCustFilter;
public int filterIndex;
public IntPtr file;
public int maxFile;
public IntPtr fileTitle;
public int maxFileTitle;
public string initialDir;
public string title;
public OpenFileFlags flags;
public short fileOffset;
public short fileExtension;
public string defExt;
public IntPtr custData;
public IntPtr hook;
public string templateName;
public IntPtr reservedPtr;
public int reservedInt;
public int flagsEx;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}