8 Commits
3.8.0 ... 4.1.0

Author SHA1 Message Date
HolographicHat
bf5525d2ea 5.1 2024-10-09 16:03:25 +08:00
HolographicHat
cf3749f887 fix #114 2024-09-12 23:47:01 +08:00
HolographicHat
21af4de1a6 5.0 2024-08-29 18:24:21 +08:00
HolographicHat
8e0fd2d27c fix #111 2024-08-05 18:11:51 +08:00
HolographicHat
0348cfa365 Merge pull request #107 from eltociear/add-japanese-readme-tutorial 2024-07-31 07:58:19 +08:00
Ikko Eltociear Ashimine
494eda32c2 docs: add Japanese README and tutorial 2024-07-23 00:47:25 +09:00
HolographicHat
975638c1ee Merge pull request #104 from canmengxian/master 2024-07-17 18:33:19 +08:00
残梦
c82a10353f Update Utils.cs 2024-06-23 23:16:13 +08:00
18 changed files with 264 additions and 149 deletions

View File

@@ -1,42 +1,42 @@
<div align="center"><img width="100" src="https://github.com/HolographicHat/YaeAchievement/blob/master/icon.ico"> <div align="center"><img width="100" src="https://github.com/HolographicHat/YaeAchievement/blob/master/icon.ico">
# YaeAchievement # 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) ![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) 简体中文 | [English](README_EN.md) | [日本語](README_JP.md)
</div> </div>
- 支持导出所有类别的成就 - 支持导出所有类别的成就
- 支持官服,渠道服与国际服 - 支持官服,渠道服与国际服
- 没有窗口大小、游戏语言等要求 - 没有窗口大小、游戏语言等要求
## 导出支持 ## 导出支持
> 按照数字键选择导出方式,<kbd>0</kbd> 为默认导出方式 > 按照数字键选择导出方式,<kbd>0</kbd> 为默认导出方式
0. [椰羊](https://cocogoat.work/achievement) 0. [椰羊](https://cocogoat.work/achievement)
1. [胡桃工具箱](https://github.com/DGP-Studio/Snap.HuTao) 1. [胡桃工具箱](https://github.com/DGP-Studio/Snap.HuTao)
2. [Paimon.moe](https://paimon.moe/achievement/) 2. [Paimon.moe](https://paimon.moe/achievement/)
3. [Seelie.me](https://seelie.me/achievements) 3. [Seelie.me](https://seelie.me/achievements)
4. 表格文件 `.csv` 4. 表格文件 `.csv`
5. [寻空](https://github.com/xunkong/xunkong) 5. [寻空](https://github.com/xunkong/xunkong)
6. [原魔工具箱](https://apps.apple.com/app/id1663989619) 6. [原魔工具箱](https://apps.apple.com/app/id1663989619)
7. [TeyvatGuide](https://github.com/BTMuli/TeyvatGuide) 7. [TeyvatGuide](https://github.com/BTMuli/TeyvatGuide)
8. [UIAF](https://uigf.org/standards/UIAF.html) JSON 文件 8. [UIAF](https://uigf.org/standards/UIAF.html) JSON 文件
## 使用说明 ## 使用说明
→ [Tutorial.md](Tutorial.md) → [Tutorial.md](Tutorial.md)
## 下载地址 ## 下载地址
[releases/latest](https://github.com/HolographicHat/YaeAchievement/releases/latest) [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) [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: 打不开 0. Q: 打不开
A: 安装 [.NET Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.4-windows-x64-installer) A: 安装 [.NET Runtime](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.4-windows-x64-installer)
1. Q: 原神启动时报错: 数据异常(31-4302) 1. Q: 原神启动时报错: 数据异常(31-4302)
A: 不要把软件和原神主程序放一起 A: 不要把软件和原神主程序放一起

View File

@@ -4,7 +4,7 @@
![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) ![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 [简体中文](README.md) | English | [日本語](README_JP.md)
</div> </div>

44
README_JP.md Normal file
View File

@@ -0,0 +1,44 @@
<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](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_JP.md](Tutorial_JP.md)
## ダウンロード: [こちら](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 7](https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.4-windows-x64-installer) をダウンロードしてインストールするか、`winget install Microsoft.DotNet.Runtime.8` を実行してください。
1. Q: 原神を起動中にエラーが発生しました: データ例外 (31-4302)
A: ソフトウェアを原神のディレクトリに配置しないでください。

75
Tutorial_JP.md Normal file
View File

@@ -0,0 +1,75 @@
## 使用説明書
1. YaeAchievement最新バージョンをダウンロード
こちらをクリックhttps://github.com/HolographicHat/YaeAchievement/releases
赤枠で囲まれた「YaeAchievement.exe」という名前のファイルをクリックすると、自動的にポップアップしてダウンロードされます。このファイルをデスクトップや他の見やすいフォルダに保存することをお勧めします。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide1.png)
2. .NET Runtime 7をインストールランタイムが既にインストールされている場合はこのステップを無視できます
こちらをクリックhttps://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.4-windows-x64-installer .
または、Windows 11を使用しているか、Wingetがインストールされている場合は、`winget install Microsoft.DotNet.Runtime.7`を実行します。
ウェブページにアクセスすると、ブラウザが自動的にポップアップしてダウンロードされます。ファイルをデスクトップや他の見やすいフォルダに保存します。
ダウンロードが完了したら、dotnet-runtime-x.x.x-win-x64.exeという名前のファイルを開くと、インストールウィンドウがポップアップします。以下の図のように表示されます。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide2.png)
インストールをクリックするだけです。
3. メインプログラムを開くための操作と実績エクスポートのオプション
最初のステップでダウンロードした「YaeAchievement.exe」という名前のファイルをダブルクリックして開くと、原神が起動していることを示します。以下の図のように表示されます。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide3.png)
原神の起動が完了したら、ゲームに入ります。
ゲームに入ると、ツールがどのツールにエクスポートするかを選択するように促します。以下の図のように表示されます。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide4.png)
グローバルユーザーの場合、[3] Seelie.meまたは[4] csvファイルにエクスポートを選択する必要があります。
選択後、各ページは次のようにツールをエクスポートします:
#### Snap.Hutao
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide5.png)
#### Seelie.me
この時点で、Yae Achievementは実績データがエクスポートされたことを通知します。Yae Achievement保存ディレクトリにexport-20xxxxxxxxxxxx-seelie.jsonという名前のファイルを見つけてください。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide6.png)
次に、URLhttps://seelie.me/settings をクリックし、ウェブサイトにアクセスしてインポートアカウントを選択します。以下の図のように表示されます。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide7.png)
インポートをクリックした後、export-20xxxxxxxxxxxx-seelie.jsonという名前のファイルを選択します。以下の図のように表示されます。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide8.png)
以下の図のようなプロンプトが表示されたら、インポートプロセスは成功です。
![image](https://github.com/prpjzz/yae-markdown-en/blob/main/image/Guide9.png)
この時点で、左側の列のAchievementsを選択して、インポートされた実績データを表示できます。
### 各ツールの紹介については、各ツールの公式ページをご覧ください:
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ファイル

View File

@@ -32,7 +32,7 @@ namespace Hook {
uint16_t BitConverter_ToUInt16(ByteArray* val, const int startIndex) { uint16_t BitConverter_ToUInt16(ByteArray* val, const int startIndex) {
const auto ret = CALL_ORIGIN(BitConverter_ToUInt16, val, startIndex); const auto ret = CALL_ORIGIN(BitConverter_ToUInt16, val, startIndex);
if (ret == 0xAB89 && ReadMapped<UINT16>(val->vector, 2) == 3199) { if (ret == 0xAB89 && ReadMapped<UINT16>(val->vector, 2) == 24082) {
const auto headLength = ReadMapped<UINT16>(val->vector, 4); const auto headLength = ReadMapped<UINT16>(val->vector, 4);
const auto dataLength = ReadMapped<UINT32>(val->vector, 6); const auto dataLength = ReadMapped<UINT32>(val->vector, 6);
const auto cStr = base64_encode(val->vector + 10 + headLength, dataLength) + "\n"; const auto cStr = base64_encode(val->vector + 10 + headLength, dataLength) + "\n";

View File

@@ -2,8 +2,8 @@ using namespace Genshin;
// DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...)); // DO_APP_FUNC(CN_OFFSET, OS_OFFSET, RETURN, FUNC_NAME, (ARGS...));
DO_APP_FUNC(0x0052A510, 0x0052ED10, ByteArray*, il2cpp_array_new_specific, (void* arrayTypeInfo, uint64_t length)); DO_APP_FUNC(0x002ED400, 0x002ED390, ByteArray*, il2cpp_array_new_specific, (void* arrayTypeInfo, uint64_t length));
DO_APP_FUNC(0x01688250, 0x0168CB50, ByteArray*, RecordUserData, (int32_t nType)); DO_APP_FUNC(0x0113ADC0, 0x0113AFC0, ByteArray*, RecordUserData, (int32_t nType));
DO_APP_FUNC(0x0FC7D610, 0x0FCA7240, uint16_t, BitConverter_ToUInt16, (ByteArray* val, int startIndex)); DO_APP_FUNC(0x0F826CF0, 0x0F825F10, uint16_t, BitConverter_ToUInt16, (ByteArray* val, int startIndex));

View File

@@ -18,7 +18,8 @@ using std::string;
void InitIL2CPP() { void InitIL2CPP() {
TCHAR szFileName[MAX_PATH]; TCHAR szFileName[MAX_PATH];
GetModuleFileName(nullptr, szFileName, MAX_PATH); GetModuleFileName(nullptr, szFileName, MAX_PATH);
const auto isCN = strstr(szFileName, "YuanShen.exe"); _strupr_s(szFileName);
const auto isCN = strstr(szFileName, "YUANSHEN.EXE");
const auto uBase = reinterpret_cast<uint64_t>(GetModuleHandle(isCN ? "YuanShen.exe" : "GenshinImpact.exe")); const auto uBase = reinterpret_cast<uint64_t>(GetModuleHandle(isCN ? "YuanShen.exe" : "GenshinImpact.exe"));
#define DO_APP_FUNC(ca, oa, r, n, p) n = (r (*) p)(uBase + (isCN ? ca : oa)) #define DO_APP_FUNC(ca, oa, r, n, p) n = (r (*) p)(uBase + (isCN ? ca : oa))
#include "il2cpp-functions.h" #include "il2cpp-functions.h"

90
res/App.Designer.cs generated
View File

@@ -9,8 +9,8 @@
namespace YaeAchievement.res { namespace YaeAchievement.res {
using System; using System;
/// <summary> /// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc. /// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary> /// </summary>
@@ -22,15 +22,15 @@ namespace YaeAchievement.res {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class App { internal class App {
private static global::System.Resources.ResourceManager resourceMan; private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture; private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal App() { internal App() {
} }
/// <summary> /// <summary>
/// Returns the cached ResourceManager instance used by this class. /// Returns the cached ResourceManager instance used by this class.
/// </summary> /// </summary>
@@ -44,7 +44,7 @@ namespace YaeAchievement.res {
return resourceMan; return resourceMan;
} }
} }
/// <summary> /// <summary>
/// Overrides the current thread's CurrentUICulture property for all /// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class. /// resource lookups using this strongly typed resource class.
@@ -58,7 +58,7 @@ namespace YaeAchievement.res {
resourceCulture = value; resourceCulture = value;
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to all achievement. /// Looks up a localized string similar to all achievement.
/// </summary> /// </summary>
@@ -67,7 +67,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("AllAchievement", resourceCulture); return ResourceManager.GetString("AllAchievement", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please close another instance.. /// Looks up a localized string similar to Please close another instance..
/// </summary> /// </summary>
@@ -76,7 +76,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("AnotherInstance", resourceCulture); return ResourceManager.GetString("AnotherInstance", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to YaeAchievement ({0}). /// Looks up a localized string similar to YaeAchievement ({0}).
/// </summary> /// </summary>
@@ -85,7 +85,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("AppBanner", resourceCulture); return ResourceManager.GetString("AppBanner", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to You need to login genshin impact before exporting.. /// Looks up a localized string similar to You need to login genshin impact before exporting..
/// </summary> /// </summary>
@@ -94,7 +94,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ConfigNeedStartGenshin", resourceCulture); return ResourceManager.GetString("ConfigNeedStartGenshin", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Download: {0}. /// Looks up a localized string similar to Download: {0}.
/// </summary> /// </summary>
@@ -103,7 +103,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("DownloadLink", resourceCulture); return ResourceManager.GetString("DownloadLink", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Network error ({0}: {1}). /// Looks up a localized string similar to Network error ({0}: {1}).
/// </summary> /// </summary>
@@ -112,9 +112,9 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExceptionNetwork", resourceCulture); return ResourceManager.GetString("ExceptionNetwork", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Export to: /// Looks up a localized string similar to Export to:
///[0] Cocogoat (https://cocogoat.work/achievement, Default) ///[0] Cocogoat (https://cocogoat.work/achievement, Default)
///[1] Snap.HuTao ///[1] Snap.HuTao
///[2] Paimon.moe ///[2] Paimon.moe
@@ -130,7 +130,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportChoose", resourceCulture); return ResourceManager.GetString("ExportChoose", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Fail, please contact developer to get help information. /// Looks up a localized string similar to Fail, please contact developer to get help information.
/// </summary> /// </summary>
@@ -139,7 +139,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToCocogoatFail", resourceCulture); return ResourceManager.GetString("ExportToCocogoatFail", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Successfully exported to cocogoat.. /// Looks up a localized string similar to Successfully exported to cocogoat..
/// </summary> /// </summary>
@@ -148,7 +148,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToCocogoatSuccess", resourceCulture); return ResourceManager.GetString("ExportToCocogoatSuccess", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Successfully exported to {0}. /// Looks up a localized string similar to Successfully exported to {0}.
/// </summary> /// </summary>
@@ -157,7 +157,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToFileSuccess", resourceCulture); return ResourceManager.GetString("ExportToFileSuccess", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please update Snap Hutao and retry.. /// Looks up a localized string similar to Please update Snap Hutao and retry..
/// </summary> /// </summary>
@@ -166,7 +166,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToSnapGenshinNeedUpdate", resourceCulture); return ResourceManager.GetString("ExportToSnapGenshinNeedUpdate", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Successfully exported to Snap Hutao.. /// Looks up a localized string similar to Successfully exported to Snap Hutao..
/// </summary> /// </summary>
@@ -175,7 +175,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToSnapGenshinSuccess", resourceCulture); return ResourceManager.GetString("ExportToSnapGenshinSuccess", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please launch/update Teyvat Guide and retry.. /// Looks up a localized string similar to Please launch/update Teyvat Guide and retry..
/// </summary> /// </summary>
@@ -184,7 +184,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToTauriFail", resourceCulture); return ResourceManager.GetString("ExportToTauriFail", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Successfully exported to Teyvat Guide.. /// Looks up a localized string similar to Successfully exported to Teyvat Guide..
/// </summary> /// </summary>
@@ -193,7 +193,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToTauriSuccess", resourceCulture); return ResourceManager.GetString("ExportToTauriSuccess", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to {0}. /// Looks up a localized string similar to {0}.
/// </summary> /// </summary>
@@ -202,7 +202,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToWxApp1Success", resourceCulture); return ResourceManager.GetString("ExportToWxApp1Success", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please update xunkong and retry.. /// Looks up a localized string similar to Please update xunkong and retry..
/// </summary> /// </summary>
@@ -211,7 +211,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToXunkongNeedUpdate", resourceCulture); return ResourceManager.GetString("ExportToXunkongNeedUpdate", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Successfully exported to xunkong.. /// Looks up a localized string similar to Successfully exported to xunkong..
/// </summary> /// </summary>
@@ -220,7 +220,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("ExportToXunkongSuccess", resourceCulture); return ResourceManager.GetString("ExportToXunkongSuccess", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Game process start ({0}). /// Looks up a localized string similar to Game process start ({0}).
/// </summary> /// </summary>
@@ -229,7 +229,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GameLoading", resourceCulture); return ResourceManager.GetString("GameLoading", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Game exited.. /// Looks up a localized string similar to Game exited..
/// </summary> /// </summary>
@@ -238,7 +238,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GameProcessExit", resourceCulture); return ResourceManager.GetString("GameProcessExit", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please update genshin and retry.. /// Looks up a localized string similar to Please update genshin and retry..
/// </summary> /// </summary>
@@ -247,7 +247,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GenshinHashError", resourceCulture); return ResourceManager.GetString("GenshinHashError", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please close game before run this application. ({0}). /// Looks up a localized string similar to Please close game before run this application. ({0}).
/// </summary> /// </summary>
@@ -256,7 +256,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("GenshinIsRunning", resourceCulture); return ResourceManager.GetString("GenshinIsRunning", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Network error:. /// Looks up a localized string similar to Network error:.
/// </summary> /// </summary>
@@ -265,7 +265,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("NetworkError", resourceCulture); return ResourceManager.GetString("NetworkError", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to No write permission on {0}.. /// Looks up a localized string similar to No write permission on {0}..
/// </summary> /// </summary>
@@ -274,7 +274,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("NoWritePermission", resourceCulture); return ResourceManager.GetString("NoWritePermission", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Press any key to exit.. /// Looks up a localized string similar to Press any key to exit..
/// </summary> /// </summary>
@@ -283,7 +283,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("PressKeyToExit", resourceCulture); return ResourceManager.GetString("PressKeyToExit", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Reward not taken. /// Looks up a localized string similar to Reward not taken.
/// </summary> /// </summary>
@@ -292,7 +292,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusFinished", resourceCulture); return ResourceManager.GetString("StatusFinished", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Invalid. /// Looks up a localized string similar to Invalid.
/// </summary> /// </summary>
@@ -301,7 +301,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusInvalid", resourceCulture); return ResourceManager.GetString("StatusInvalid", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Finished. /// Looks up a localized string similar to Finished.
/// </summary> /// </summary>
@@ -310,7 +310,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusRewardTaken", resourceCulture); return ResourceManager.GetString("StatusRewardTaken", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Unfinished. /// Looks up a localized string similar to Unfinished.
/// </summary> /// </summary>
@@ -319,9 +319,9 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("StatusUnfinished", resourceCulture); return ResourceManager.GetString("StatusUnfinished", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Description: /// Looks up a localized string similar to Description:
///{0}. ///{0}.
/// </summary> /// </summary>
internal static string UpdateDescription { internal static string UpdateDescription {
@@ -329,7 +329,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UpdateDescription", resourceCulture); return ResourceManager.GetString("UpdateDescription", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Downloading update package.... /// Looks up a localized string similar to Downloading update package....
/// </summary> /// </summary>
@@ -338,7 +338,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UpdateDownloading", resourceCulture); return ResourceManager.GetString("UpdateDownloading", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Has update: {0} =&gt; {1}. /// Looks up a localized string similar to Has update: {0} =&gt; {1}.
/// </summary> /// </summary>
@@ -347,7 +347,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UpdateNewVersion", resourceCulture); return ResourceManager.GetString("UpdateNewVersion", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized resource of type System.Byte[]. /// Looks up a localized resource of type System.Byte[].
/// </summary> /// </summary>
@@ -357,7 +357,7 @@ namespace YaeAchievement.res {
return ((byte[])(obj)); return ((byte[])(obj));
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Upload error to appcenter.... /// Looks up a localized string similar to Upload error to appcenter....
/// </summary> /// </summary>
@@ -366,7 +366,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UploadError", resourceCulture); return ResourceManager.GetString("UploadError", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Use previous fetched data? (yes|no). /// Looks up a localized string similar to Use previous fetched data? (yes|no).
/// </summary> /// </summary>
@@ -375,7 +375,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("UsePreviousData", resourceCulture); return ResourceManager.GetString("UsePreviousData", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Downloading Visual C++ Redistributable.... /// Looks up a localized string similar to Downloading Visual C++ Redistributable....
/// </summary> /// </summary>
@@ -384,7 +384,7 @@ namespace YaeAchievement.res {
return ResourceManager.GetString("VcRuntimeDownload", resourceCulture); return ResourceManager.GetString("VcRuntimeDownload", resourceCulture);
} }
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Installing Visual C++ Redistributable.... /// Looks up a localized string similar to Installing Visual C++ Redistributable....
/// </summary> /// </summary>

View File

@@ -3,7 +3,7 @@
<root> <root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <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 name="root" msdata:IsDataSet="true">
</xsd:element> </xsd:element>
</xsd:schema> </xsd:schema>
<resheader name="resmimetype"> <resheader name="resmimetype">

View File

@@ -49,7 +49,7 @@
自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI无需 自动缩放。Windows Presentation Foundation (WPF)应用程序自动感知 DPI无需
选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应 选择加入。选择加入此设置的 Windows 窗体应用程序(面向 .NET Framework 4.6)还应
在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。 在其 app.config 中将 "EnableWindowsFormsHighDpiAutoResizing" 设置设置为 "true"。
将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation --> 将应用程序设为感知长路径。请参阅 https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation -->
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <application xmlns="urn:schemas-microsoft-com:asm.v3">

View File

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

View File

@@ -1,10 +1,10 @@
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using YaeAchievement.res; using YaeAchievement.res;
namespace YaeAchievement; namespace YaeAchievement;
public static partial class AppConfig { public static partial class AppConfig {
public static string GamePath { get; private set; } = null!; public static string GamePath { get; private set; } = null!;
internal static void Load(string argumentPath) { internal static void Load(string argumentPath) {
@@ -36,8 +36,8 @@ public static partial class AppConfig {
var osLastWriteTime = File.GetLastWriteTime(osLogPath); var osLastWriteTime = File.GetLastWriteTime(osLogPath);
finalLogPath = cnLastWriteTime > osLastWriteTime ? cnLogPath : osLogPath; finalLogPath = cnLastWriteTime > osLastWriteTime ? cnLogPath : osLogPath;
} }
GamePath = GetGamePathFromLogFile(finalLogPath) GamePath = GetGamePathFromLogFile(finalLogPath)
?? GetGamePathFromLogFile($"{finalLogPath}.last") ?? GetGamePathFromLogFile($"{finalLogPath}.last")
?? throw new ApplicationException(App.ConfigNeedStartGenshin); ?? throw new ApplicationException(App.ConfigNeedStartGenshin);
pathCacheFile.Write(GamePath); pathCacheFile.Write(GamePath);
} }
@@ -62,5 +62,5 @@ public static partial class AppConfig {
[GeneratedRegex(@"(?m).:/.+(GenshinImpact_Data|YuanShen_Data)", RegexOptions.IgnoreCase)] [GeneratedRegex(@"(?m).:/.+(GenshinImpact_Data|YuanShen_Data)", RegexOptions.IgnoreCase)]
private static partial Regex GamePathRegex(); private static partial Regex GamePathRegex();
} }

View File

@@ -2,13 +2,13 @@
using Google.Protobuf; using Google.Protobuf;
using Proto; using Proto;
namespace YaeAchievement; namespace YaeAchievement;
public class CacheFile(string identifier) { public class CacheFile(string identifier) {
private readonly string _cacheName = Path.Combine(GlobalVars.CachePath, $"{identifier.MD5Hash()[..16]}.miko"); private readonly string _cacheName = Path.Combine(GlobalVars.CachePath, $"{identifier.MD5Hash()[..16]}.miko");
private CacheItem? _content; private CacheItem? _content;
public DateTime LastWriteTime => Exists() ? File.GetLastWriteTimeUtc(_cacheName) : DateTime.UnixEpoch; public DateTime LastWriteTime => Exists() ? File.GetLastWriteTimeUtc(_cacheName) : DateTime.UnixEpoch;
public bool Exists() => File.Exists(_cacheName); public bool Exists() => File.Exists(_cacheName);
@@ -25,7 +25,7 @@ public class CacheFile(string identifier) {
public void Write(string data, string? etag = null) => Write(ByteString.CopyFromUtf8(data), data.MD5Hash(), etag); 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); public void Write(byte[] data, string? etag = null) => Write(ByteString.CopyFrom(data), data.MD5Hash(), etag);
private void Write(ByteString data, string hash, string? etag) { private void Write(ByteString data, string hash, string? etag) {
using var fOut = File.OpenWrite(_cacheName); using var fOut = File.OpenWrite(_cacheName);
using var cOut = new GZipStream(fOut, CompressionLevel.SmallestSize); using var cOut = new GZipStream(fOut, CompressionLevel.SmallestSize);

View File

@@ -9,7 +9,7 @@ using Proto;
using YaeAchievement.res; using YaeAchievement.res;
using static Proto.Achievement.Types; using static Proto.Achievement.Types;
namespace YaeAchievement; namespace YaeAchievement;
public static class Export { public static class Export {
@@ -45,7 +45,7 @@ public static class Export {
private class CocogoatResponse { private class CocogoatResponse {
[JsonPropertyName("key")] public string Code { get; init; } = null!; [JsonPropertyName("key")] public string Code { get; init; } = null!;
} }
private static void ToCocogoat(AchievementAllDataNotify data) { private static void ToCocogoat(AchievementAllDataNotify data) {
var result = JsonSerializer.Serialize(ExportToUIAFApp(data)); var result = JsonSerializer.Serialize(ExportToUIAFApp(data));
using var request = new HttpRequestMessage(); using var request = new HttpRequestMessage();
@@ -63,7 +63,7 @@ public static class Export {
? App.ExportToCocogoatSuccess ? App.ExportToCocogoatSuccess
: $"https://cocogoat.work/achievement?memo={responseJson.Code}"); : $"https://cocogoat.work/achievement?memo={responseJson.Code}");
} }
private static void ToWxApp1(AchievementAllDataNotify data) { private static void ToWxApp1(AchievementAllDataNotify data) {
var id = Guid.NewGuid().ToString("N").Substring(20, 8); var id = Guid.NewGuid().ToString("N").Substring(20, 8);
var result = JsonSerializer.Serialize(new Dictionary<string, object> { var result = JsonSerializer.Serialize(new Dictionary<string, object> {
@@ -88,7 +88,7 @@ public static class Export {
Utils.ShellOpen("ms-windows-store://pdp/?productid=9PH4NXJ2JN52"); Utils.ShellOpen("ms-windows-store://pdp/?productid=9PH4NXJ2JN52");
} }
} }
private static void ToXunkong(AchievementAllDataNotify data) { private static void ToXunkong(AchievementAllDataNotify data) {
if (CheckWinUIAppScheme("xunkong")) { if (CheckWinUIAppScheme("xunkong")) {
Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data))); Utils.CopyToClipboard(JsonSerializer.Serialize(ExportToUIAFApp(data)));
@@ -120,30 +120,25 @@ public static class Export {
} }
private static void ToPaimon(AchievementAllDataNotify data) { private static void ToPaimon(AchievementAllDataNotify data) {
var info = LoadAchievementInfo(); var info = LoadAchievementInfo().Items.ToDictionary(pair => pair.Key, pair => pair.Value.Group);
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.");
continue;
}
var map = output.GetValueOrDefault(achInfo.Group, new Dictionary<uint, bool>());
map[ach.Id == 81222 ? 81219 : ach.Id] = true;
output[achInfo.Group] = map;
}
var final = new Dictionary<string, Dictionary<uint, Dictionary<uint, bool>>> { var final = new Dictionary<string, Dictionary<uint, Dictionary<uint, bool>>> {
["achievement"] = output.OrderBy(pair => pair.Key).ToDictionary(pair => pair.Key, pair => pair.Value) ["achievement"] = data.List
.Where(achievement => achievement.Status is Status.Finished or Status.RewardTaken)
.Where(achievement => info.ContainsKey(achievement.Id))
.GroupBy(achievement => info[achievement.Id], achievement => achievement.Id)
.OrderBy(group => group.Key)
.ToDictionary(group => group.Key, group => group.ToDictionary(id => id, _ => true))
}; };
var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-paimon.json"); var path = Path.GetFullPath($"export-{DateTime.Now:yyyyMMddHHmmss}-paimon.json");
if (TryWriteToFile(path, JsonSerializer.Serialize(final))) { if (TryWriteToFile(path, JsonSerializer.Serialize(final))) {
Console.WriteLine(App.ExportToFileSuccess, path); Console.WriteLine(App.ExportToFileSuccess, path);
} }
} }
private static void ToSeelie(AchievementAllDataNotify data) { private static void ToSeelie(AchievementAllDataNotify data) {
var output = new Dictionary<uint, Dictionary<string, bool>>(); var output = new Dictionary<uint, Dictionary<string, bool>>();
foreach (var ach in data.List.Where(a => a.Status is Status.Finished or Status.RewardTaken)) { foreach (var ach in data.List.Where(a => a.Status is Status.Finished or Status.RewardTaken)) {
output[ach.Id == 81222 ? 81219 : ach.Id] = new Dictionary<string, bool> { output[ach.Id] = new Dictionary<string, bool> {
["done"] = true ["done"] = true
}; };
} }
@@ -227,7 +222,7 @@ public static class Export {
private static string JoinToString(this IEnumerable<object> list, string separator) { private static string JoinToString(this IEnumerable<object> list, string separator) {
return string.Join(separator, list); return string.Join(separator, list);
} }
private static readonly List<uint> UnusedAchievement = [ 84517 ]; private static readonly List<uint> UnusedAchievement = [ 84517 ];
private static string ToDesc(this Status status) { private static string ToDesc(this Status status) {

View File

@@ -10,21 +10,21 @@ public static class Extensions {
private static readonly Lazy<MD5> md5 = new (MD5.Create); private static readonly Lazy<MD5> md5 = new (MD5.Create);
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
private static readonly Lazy<SHA1> sha1 = new (SHA1.Create); private static readonly Lazy<SHA1> sha1 = new (SHA1.Create);
public static byte[] ToBytes(this string text) { public static byte[] ToBytes(this string text) {
return Encoding.UTF8.GetBytes(text); return Encoding.UTF8.GetBytes(text);
} }
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public static string MD5Hash(this string text) { public static string MD5Hash(this string text) {
return text.ToBytes().MD5Hash(); return text.ToBytes().MD5Hash();
} }
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public static string MD5Hash(this byte[] data) { public static string MD5Hash(this byte[] data) {
return md5.Value.ComputeHash(data).ToHex().ToLower(); return md5.Value.ComputeHash(data).ToHex().ToLower();
} }
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
public static string SHA1Hash(this string text, bool base64 = true) { public static string SHA1Hash(this string text, bool base64 = true) {
var bytes = sha1.Value.ComputeHash(text.ToBytes()); var bytes = sha1.Value.ComputeHash(text.ToBytes());
@@ -34,7 +34,7 @@ public static class Extensions {
public static string ToHex(this byte[] bytes) { public static string ToHex(this byte[] bytes) {
return Convert.ToHexString(bytes); return Convert.ToHexString(bytes);
} }
public static string ToBase64(this byte[] bytes) { public static string ToBase64(this byte[] bytes) {
return Convert.ToBase64String(bytes); return Convert.ToBase64String(bytes);
} }

View File

@@ -1,6 +1,6 @@
using System.Reflection; using System.Reflection;
namespace YaeAchievement; namespace YaeAchievement;
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming
// ReSharper disable ConvertToConstant.Global // ReSharper disable ConvertToConstant.Global
@@ -8,21 +8,21 @@ namespace YaeAchievement;
// ReSharper disable once MemberCanBePrivate.Global // ReSharper disable once MemberCanBePrivate.Global
public static class GlobalVars { public static class GlobalVars {
public static bool DebugProxy => false; public static bool DebugProxy => false;
public static bool UnexpectedExit { get; set; } = true; public static bool UnexpectedExit { get; set; } = true;
public static bool PauseOnExit { get; set; } = true; public static bool PauseOnExit { get; set; } = true;
public static Version AppVersion { get; } = Assembly.GetEntryAssembly()!.GetName().Version!; public static Version AppVersion { get; } = Assembly.GetEntryAssembly()!.GetName().Version!;
public static readonly string AppPath = AppDomain.CurrentDomain.BaseDirectory; public static readonly string AppPath = AppDomain.CurrentDomain.BaseDirectory;
private static readonly string CommonData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); private static readonly string CommonData = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
public static readonly string DataPath = Path.Combine(CommonData, "Yae"); public static readonly string DataPath = Path.Combine(CommonData, "Yae");
public static readonly string CachePath = Path.Combine(DataPath, "cache"); public static readonly string CachePath = Path.Combine(DataPath, "cache");
public static readonly string LibFilePath = Path.Combine(DataPath, "YaeAchievement.dll"); public static readonly string LibFilePath = Path.Combine(DataPath, "YaeAchievement.dll");
public const uint AppVersionCode = 48; public const uint AppVersionCode = 51;
public const string AppVersionName = "3.8"; public const string AppVersionName = "4.1";
public const string PipeName = "YaeAchievementPipe"; public const string PipeName = "YaeAchievementPipe";
public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com"; public const string BucketHost = "https://cn-cd-1259389942.file.myqcloud.com";

View File

@@ -7,7 +7,7 @@ using Windows.Win32.System.Threading;
namespace YaeAchievement; namespace YaeAchievement;
public static class Injector { public static class Injector {
public static unsafe bool CreateProcess(string path, out HANDLE hProc, out HANDLE hThread, out uint pid) { public static unsafe bool CreateProcess(string path, out HANDLE hProc, out HANDLE hThread, out uint pid) {
Span<char> cmdLines = stackalloc char[1]; // "\0" Span<char> cmdLines = stackalloc char[1]; // "\0"
var si = new STARTUPINFOW { var si = new STARTUPINFOW {

View File

@@ -62,7 +62,7 @@ public static class Utils {
public static uint? ToUIntOrNull(string? value) { public static uint? ToUIntOrNull(string? value) {
return value != null ? uint.TryParse(value, out var result) ? result : null : null; return value != null ? uint.TryParse(value, out var result) ? result : null : null;
} }
public static bool ToBooleanOrFalse(string? value) { public static bool ToBooleanOrFalse(string? value) {
return value != null && bool.TryParse(value, out var result) && result; return value != null && bool.TryParse(value, out var result) && result;
} }
@@ -87,7 +87,7 @@ public static class Utils {
// ReSharper disable once NotAccessedField.Local // ReSharper disable once NotAccessedField.Local
private static UpdateInfo _updateInfo = null!; private static UpdateInfo _updateInfo = null!;
public static void CheckUpdate(bool useLocalLib) { public static void CheckUpdate(bool useLocalLib) {
var info = UpdateInfo.Parser.ParseFrom(GetBucketFileAsByteArray("schicksal/version"))!; var info = UpdateInfo.Parser.ParseFrom(GetBucketFileAsByteArray("schicksal/version"))!;
if (GlobalVars.AppVersionCode < info.VersionCode) { if (GlobalVars.AppVersionCode < info.VersionCode) {
@@ -160,8 +160,8 @@ public static class Utils {
public static void CheckGenshinIsRunning() { public static void CheckGenshinIsRunning() {
Process.EnterDebugMode(); Process.EnterDebugMode();
foreach (var process in Process.GetProcesses()) { foreach (var process in Process.GetProcesses()) {
if (process.ProcessName is "GenshinImpact" or "YuanShen" if (process.ProcessName is "GenshinImpact" or "YuanShen"
&& !process.HasExited && !process.HasExited
&& process.MainWindowHandle != nint.Zero && process.MainWindowHandle != nint.Zero
) { ) {
Console.WriteLine(App.GenshinIsRunning, process.Id); Console.WriteLine(App.GenshinIsRunning, process.Id);
@@ -170,10 +170,10 @@ public static class Utils {
} }
Process.LeaveDebugMode(); Process.LeaveDebugMode();
} }
// ReSharper disable once InconsistentNaming // ReSharper disable once InconsistentNaming
private static Process? proc; private static Process? proc;
public static void InstallExitHook() { public static void InstallExitHook() {
AppDomain.CurrentDomain.ProcessExit += (_, _) => { AppDomain.CurrentDomain.ProcessExit += (_, _) => {
proc?.Kill(); proc?.Kill();
@@ -222,7 +222,7 @@ public static class Utils {
Environment.Exit(0); Environment.Exit(0);
} }
AppDomain.CurrentDomain.ProcessExit += (_, _) => { AppDomain.CurrentDomain.ProcessExit += (_, _) => {
try { try {
File.Delete(GlobalVars.LibFilePath); File.Delete(GlobalVars.LibFilePath);
} catch (Exception) { /* ignored */ } } catch (Exception) { /* ignored */ }
}; };
@@ -293,7 +293,7 @@ public static class Utils {
} }
}) })
.Select(item => item?.GetValue("DisplayName") as string ?? string.Empty) .Select(item => item?.GetValue("DisplayName") as string ?? string.Empty)
.Any(name => name.Contains("Microsoft Visual C++ 2022 X64 ")); .Any(name => name.Contains("Microsoft Visual C++ 2022 X64 ") || name.Contains("Microsoft Visual C++ 2015-2022 Redistributable (x64)"));
if (!installed) { if (!installed) {
Console.WriteLine(App.VcRuntimeDownload); Console.WriteLine(App.VcRuntimeDownload);
var pkgPath = Path.Combine(GlobalVars.DataPath, "vc_redist.x64.exe"); var pkgPath = Path.Combine(GlobalVars.DataPath, "vc_redist.x64.exe");