From 4179af4f4ddda54da917d2099f5b11182a409c17 Mon Sep 17 00:00:00 2001 From: liantian-cn Date: Sat, 15 Aug 2026 13:09:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A8=A1=E5=9D=97=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=E8=87=B3=E6=88=91=E7=9A=84=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 模块存储位置从 {UserProfile}/.config/{AppName}/module 迁移至 Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)/{AppName}/module (Windows 下跟随用户已知文件夹重定向,本机为 E:\Documents\Shigure\module)。 - ModuleStore.ResolveModuleDirectory() 返回表达式改为 MyDocuments 版本,三个无参调用点自动跟随 - Program.cs 迁移提示文案「用户配置目录」改为「我的文档目录」,检测逻辑不变(仅检测 exe 旁 module/) - 7 个文档同步更新(README/CLAUDE/打包说明/Obsidian 00/01/10/11),路径统一写 {MyDocuments}/Shigure/module - 旧目录(含 .config 版本)不自动迁移、不删除,由提示引导手动移动 --- App/Program.cs | 4 ++-- CLAUDE.md | 6 +++--- Modules/ModuleStore.cs | 3 +-- Obsidian/30-Shigure/00-Shigure-MOC.md | 2 +- Obsidian/30-Shigure/01-Shigure-启动随机副本与会话协调.md | 2 +- Obsidian/30-Shigure/10-Shigure-UI功能地图与数据所有权.md | 2 +- Obsidian/30-Shigure/11-Shigure-本地数据路径构建与验证.md | 8 ++++---- README.md | 8 ++++---- 打包说明.md | 2 +- 9 files changed, 18 insertions(+), 19 deletions(-) diff --git a/App/Program.cs b/App/Program.cs index 1c4ecaeb..890eff00 100644 --- a/App/Program.cs +++ b/App/Program.cs @@ -35,7 +35,7 @@ internal static class Program runtimeSession)); } - // 模块目录迁移提示:旧目录(baseDirectory/module)存在且有内容、且新目录(用户配置目录)尚无模块文件时, + // 模块目录迁移提示:旧目录(baseDirectory/module)存在且有内容、且新目录(我的文档目录)尚无模块文件时, // 弹一次纯文案提示,引导用户手动移动模块;条件不满足或检测异常时静默,不影响启动。 private static void ShowModuleMigrationHint(string baseDirectory, ModuleStore moduleStore) { @@ -55,7 +55,7 @@ internal static class Program } MessageBox.Show( - $"模块目录已迁移到用户配置目录。\n\n" + + $"模块目录已迁移到我的文档目录。\n\n" + $"新的模块目录:\n{moduleStore.ModuleDirectory}\n\n" + $"请将旧目录 {oldDirectory} 中的模块文件手动移动到新目录。", "Shigure", diff --git a/CLAUDE.md b/CLAUDE.md index ae8f5dc3..8285936e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -20,7 +20,7 @@ dotnet run --project .\Shigure.csproj -- --toggle XBUTTON2 --mode switch --logic - **没有测试项目**:验证 = 能编译 + 实际运行点开「设置」走查。`dotnet build` 干净通过(0 警告 0 错误)是基线要求。 - 启动参数见 [README.md](README.md#运行)(`--toggle/--mode/--logic-ms/--render-ms`),解析在 [App/AppOptions.cs](App/AppOptions.cs)。目标进程名来自 `wow_process.txt`。 -程序直接从当前 EXE 所在目录运行;`AppPaths.BaseDirectory` 即 `AppContext.BaseDirectory`,配置、按键映射和插件源码均从该目录读取;模块从用户配置目录读取(`ModuleStore.ResolveModuleDirectory()`,见下)。 +程序直接从当前 EXE 所在目录运行;`AppPaths.BaseDirectory` 即 `AppContext.BaseDirectory`,配置、按键映射和插件源码均从该目录读取;模块从我的文档目录读取(`ModuleStore.ResolveModuleDirectory()`,见下)。 ## 架构与数据流 @@ -54,13 +54,13 @@ Infrastructure/ 配置读取(ConfigService)、JSON 辅助、UI 缓存、路径 UI/ WinForms 界面、编辑器、主题 Fuyutsui/ 内置插件权威源;构建/发布时完整复制,运行时部署到游戏 AddOns config/ keymap/ 运行时 JSON 数据(构建时复制到输出, 见 .csproj 的 None+CopyToOutputDirectory) -module 运行时模块数据位于用户配置目录 ~/.config/Shigure/module(启动时自动创建, 不随构建复制) +module 运行时模块数据位于我的文档目录 {MyDocuments}/Shigure/module(启动时自动创建, 不随构建复制) wow_process.txt 目标游戏进程名列表;构建时复制,运行期间每次定位都会重新读取 ``` ## 模块解析(改逻辑前必读) -- 模块以 `~/.config/Shigure/module/模块名.json` 平铺保存(`ModuleStore.ResolveModuleDirectory()` 返回用户配置目录,`{UserProfile}/.config/{程序集名}/module`),**文件名取自模块名,故模块名不可重复**;加载递归扫描子目录。模型在 [Modules/ModuleStore.cs](Modules/ModuleStore.cs)(`ModuleDefinition`/`ModuleMatch`/`ModuleRule`/`ModuleUnit`/`ModuleCountField`/`ModuleValueAdjustment`)。`RecommendedTalent` 是 `ModuleDefinition` 上的纯展示字段,不参与匹配(`ModuleMatch.Specificity` 不计入)。 +- 模块以 `{MyDocuments}/Shigure/module/模块名.json` 平铺保存(`ModuleStore.ResolveModuleDirectory()` 返回我的文档目录,`{MyDocuments}/{程序集名}/module`),**文件名取自模块名,故模块名不可重复**;加载递归扫描子目录。模型在 [Modules/ModuleStore.cs](Modules/ModuleStore.cs)(`ModuleDefinition`/`ModuleMatch`/`ModuleRule`/`ModuleUnit`/`ModuleCountField`/`ModuleValueAdjustment`)。`RecommendedTalent` 是 `ModuleDefinition` 上的纯展示字段,不参与匹配(`ModuleMatch.Specificity` 不计入)。 - `ModuleStore` 的 `Reload`/`Save`/`Delete` 会在同一个门锁内串行完整文件事务与内存快照更新;`Save` 通过同目录临时文件提交,重命名失败会回滚新文件。编辑器写入不要绕过它,避免运行时读到半次操作。运行时工厂不再自行 `Reload`:启动和模块刷新先由 `ModuleDependencyService` 导入依赖、拒绝宏容量超限模块,再把已验证的内存快照交给运行时。 - 职业/专精明确的模块保存时会写入 `Dependencies` 快照。`ModuleDependencyService` 以本地为优先追加缺失的 ClassBlocks/spellsList/ClassMacros,按动态宏 30 槽、其它宏 1 槽检查所有受影响专精;任一专精超过 keymap 容量就拒绝整个模块且不写 Lua。依赖提交失败会恢复配置和宏原文。 - 选择优先级:`ModuleStore.FindSelectedOrBestMatch` —— 先用 UI/参数选定的 `ModuleId`;否则取 `Match` 命中字段最多者(`ModuleMatch.Specificity` 越大越优先),并列按名称。`Match` 字段留空 = 任意。`PartyType` 数字会归一化为 `"1-40"`。 diff --git a/Modules/ModuleStore.cs b/Modules/ModuleStore.cs index aa8a4be2..c2e01cbe 100644 --- a/Modules/ModuleStore.cs +++ b/Modules/ModuleStore.cs @@ -292,8 +292,7 @@ public sealed class ModuleStore public static string ResolveModuleDirectory() { return Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), - ".config", + Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), AppInfo.AppName, "module"); } diff --git a/Obsidian/30-Shigure/00-Shigure-MOC.md b/Obsidian/30-Shigure/00-Shigure-MOC.md index 60a4732f..93dd306c 100644 --- a/Obsidian/30-Shigure/00-Shigure-MOC.md +++ b/Obsidian/30-Shigure/00-Shigure-MOC.md @@ -89,7 +89,7 @@ Program.Main | 状态步骤映射 | ClassBlocks Lua,经转换器生成 | `ConfigService` / `StateBuilder` | `config/*.json` | | 法术宏到键位 | ClassMacros Lua,经转换器生成 | `KeymapService` | `keymap/*.json` | | 游戏插件副本 | 项目内置 `Fuyutsui/` | WoW AddOn 加载器 | `Interface/AddOns/Fuyutsui` | -| 行为规则 | 模块编辑器或手工 JSON | `ModuleStore` / `ModuleLogic` | `~/.config/Shigure/module` | +| 行为规则 | 模块编辑器或手工 JSON | `ModuleStore` / `ModuleLogic` | `{MyDocuments}/Shigure/module` | | UI 缓存与偏好 | WinForms 界面 | WinForms 界面 | `cache/` | | 运行状态 | `ShigureRuntime` 单循环 | `StatusForm` | `RenderSnapshot`,不持久化 | diff --git a/Obsidian/30-Shigure/01-Shigure-启动随机副本与会话协调.md b/Obsidian/30-Shigure/01-Shigure-启动随机副本与会话协调.md index 7caf5562..5ad573d9 100644 --- a/Obsidian/30-Shigure/01-Shigure-启动随机副本与会话协调.md +++ b/Obsidian/30-Shigure/01-Shigure-启动随机副本与会话协调.md @@ -73,7 +73,7 @@ verified_at: 2026-08-10 ## 核心数据与不变量 -- 随机子进程**不复制业务数据目录**;`config`、`keymap`、`cache` 仍由原始根目录提供,模块由用户配置目录 `~/.config/Shigure/module` 提供。 +- 随机子进程**不复制业务数据目录**;`config`、`keymap`、`cache` 仍由原始根目录提供,模块由我的文档目录 `{MyDocuments}/Shigure/module` 提供。 - `SHIGURE_RANDOMIZED_PROCESS=1` 是防递归开关。外部若伪造相关环境变量,也会改变启动和路径行为。 - 清理范围是按源 EXE 路径哈希隔离的专属临时根目录;清理会递归删除其所有子项并吞掉 IO/权限异常。 - 每次会话构造新的 `ConfigService`、`KeymapService`、`PixelScanner`、`StateBuilder`、`KeySender` 和 `LogicRegistry`;`ModuleStore` 与触发键读取器跨会话共享。 diff --git a/Obsidian/30-Shigure/10-Shigure-UI功能地图与数据所有权.md b/Obsidian/30-Shigure/10-Shigure-UI功能地图与数据所有权.md index 8f4d0b92..0891d75e 100644 --- a/Obsidian/30-Shigure/10-Shigure-UI功能地图与数据所有权.md +++ b/Obsidian/30-Shigure/10-Shigure-UI功能地图与数据所有权.md @@ -56,7 +56,7 @@ verified_at: 2026-08-10 | `MainForm` 浮条 | 启停、打开设置/状态、关闭、拖动 | 会话状态、UI 缓存 | `SetEnabled`、重启/停止、窗口偏好 | | 通用设置 | 触发键、模式、模块选择、配置生成与插件部署 | `AppOptions`、模块目录、项目 Fuyutsui | 缓存/设置、会话重启、同步队列 | | `StatusForm` | 九个状态/诊断页 | `RenderSnapshot`、日志 | 不拥有运行状态 | -| 模块编辑器 | 匹配、规则、动态单位、数量、调整/公式、排序 | 模块快照 | `~/.config/Shigure/module` | +| 模块编辑器 | 匹配、规则、动态单位、数量、调整/公式、排序 | 模块快照 | `{MyDocuments}/Shigure/module` | | ClassBlocks 编辑器 | 职业/专精状态块编辑 | `Fuyutsui/class/*.lua` 项目源 | ClassBlocks table、config、当前 Lua 游戏部署 | | ClassMacros 编辑器 | common/spec/static/special 宏编辑 | `Fuyutsui/core/classmacros.lua` 项目源 | ClassMacros table、keymap、当前 Lua 游戏部署 | | 条件/单位对话框 | 构造受限条件和动态定义 | 当前草稿 | 返回编辑器内存模型 | diff --git a/Obsidian/30-Shigure/11-Shigure-本地数据路径构建与验证.md b/Obsidian/30-Shigure/11-Shigure-本地数据路径构建与验证.md index 48458957..f7cf4680 100644 --- a/Obsidian/30-Shigure/11-Shigure-本地数据路径构建与验证.md +++ b/Obsidian/30-Shigure/11-Shigure-本地数据路径构建与验证.md @@ -41,7 +41,7 @@ verified_at: 2026-08-10 # Shigure 本地数据、路径、构建与验证 > [!abstract] AI 快速摘要 -> Shigure 的业务根目录通常是正式 EXE 所在目录;随机副本子进程通过环境变量仍指回该目录。程序从这里读取内置 `Fuyutsui/`、`config`、`keymap`、`cache` 和 `wow_process.txt`;模块从用户配置目录 `~/.config/Shigure/module` 读取。项目插件是权威源,目标游戏中的 Fuyutsui 只是由部署服务维护的运行副本。项目是无第三方 NuGet 引用的 `net10.0-windows` WinForms WinExe,仓库没有测试项目。 +> Shigure 的业务根目录通常是正式 EXE 所在目录;随机副本子进程通过环境变量仍指回该目录。程序从这里读取内置 `Fuyutsui/`、`config`、`keymap`、`cache` 和 `wow_process.txt`;模块从我的文档目录 `{MyDocuments}/Shigure/module` 读取。项目插件是权威源,目标游戏中的 Fuyutsui 只是由部署服务维护的运行副本。项目是无第三方 NuGet 引用的 `net10.0-windows` WinForms WinExe,仓库没有测试项目。 ## 图谱位置 @@ -65,7 +65,7 @@ verified_at: 2026-08-10 AppContext.BaseDirectory = 随机临时目录(仅运行依赖) ``` -这使随机 EXE 可以加载临时目录 DLL,同时配置、Keymap 和缓存等数据仍落在正式安装目录;模块则在用户配置目录(子进程与父进程同属一个 Windows 用户,解析结果一致)。环境变量属于信任边界:若外部预先设置/篡改,可能改变业务数据根目录。 +这使随机 EXE 可以加载临时目录 DLL,同时配置、Keymap 和缓存等数据仍落在正式安装目录;模块则在我的文档目录(子进程与父进程同属一个 Windows 用户,解析结果一致)。环境变量属于信任边界:若外部预先设置/篡改,可能改变业务数据根目录。 ## 本地数据地图 @@ -74,7 +74,7 @@ verified_at: 2026-08-10 | `config/common.json` | 协议固定字段 | `ConfigService` | 打包内容/人工维护 | | `config/.json` | 13 职业和专精步骤映射、法术元数据 | `ConfigService`, `StateBuilder` | `FuyutsuiConfigConverter` | | `keymap/*.json` | unit/spell/macroCondition→hotkey | `KeymapService`, `KeymapCatalog` | `FuyutsuiKeymapConverter` | -| `~/.config/Shigure/module/**/*.json` | 匹配、规则、动态值和公式 | `ModuleStore` | 模块编辑器/人工 | +| `{MyDocuments}/Shigure/module/**/*.json` | 匹配、规则、动态值和公式 | `ModuleStore` | 模块编辑器/人工 | | `cache/` | 窗口和 UI 偏好 | UI 基础设施 | MainForm/各 UI | | `Fuyutsui/class/*.lua` | 内置 ClassBlocks 权威源 | ClassBlocks Store/转换器 | ClassBlocks 编辑器/人工 | | `Fuyutsui/core/classmacros.lua` | 内置宏权威源 | ClassMacros Store/转换器 | 宏编辑器/人工 | @@ -99,7 +99,7 @@ verified_at: 2026-08-10 - 开启 nullable 与 implicit usings。 - 应用版本在项目文件中为 1.2.1,并被模块编辑器保存到模块元数据。 - 项目没有 `PackageReference`;核心只依赖 .NET/WinForms/System.Drawing 和 Win32 P/Invoke。 -- 项目文件声明嵌入 UI assets,并把 `Fuyutsui/**`、配置、Keymap 和 `wow_process.txt` 按规则复制到输出;Fuyutsui 同时明确复制到 publish。模块不随构建/发布复制,由用户配置目录 `~/.config/Shigure/module` 提供。 +- 项目文件声明嵌入 UI assets,并把 `Fuyutsui/**`、配置、Keymap 和 `wow_process.txt` 按规则复制到输出;Fuyutsui 同时明确复制到 publish。模块不随构建/发布复制,由我的文档目录 `{MyDocuments}/Shigure/module` 提供。 - 实际打包策略还应对照 `打包说明.md`;随机启动器只复制正式输出目录**顶层**运行依赖到临时目录。 ## 当前验证能力 diff --git a/README.md b/README.md index b3a92b3c..18ab65a8 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Shigure 是一个 Windows WinForms 桌面程序。它从目标窗口读取 Fuyut - `日志`:记录启动、停止、职业识别、模块匹配、逻辑状态、施放步骤、配置同步和异常。 - `关于`:显示产品、公司、版本、模块目录和配置目录。 -触发键、发送模式、模块选择、模块保存以及配置同步都会按需重启运行循环。窗口位置、大小、模块选择和表格列宽等 UI 状态保存在 `cache/window-state.json`;模块保存在用户配置目录 `~/.config/Shigure/module`。`cache/` 与模块数据都是本地数据,默认不提交到 Git。 +触发键、发送模式、模块选择、模块保存以及配置同步都会按需重启运行循环。窗口位置、大小、模块选择和表格列宽等 UI 状态保存在 `cache/window-state.json`;模块保存在我的文档目录 `{MyDocuments}/Shigure/module`。`cache/` 与模块数据都是本地数据,默认不提交到 Git。 ## 环境要求 @@ -87,7 +87,7 @@ dotnet run --project .\Shigure.csproj -- --toggle XBUTTON2 --mode switch --logic - `click`:每次按下只执行一轮逻辑。 - `hold`:按住时运行,松开后停止。 -程序会直接从当前 EXE 所在目录运行,并从该目录读取 `Fuyutsui/`、`config/`、`keymap/` 和 `wow_process.txt`;模块从用户配置目录 `~/.config/Shigure/module` 读取。 +程序会直接从当前 EXE 所在目录运行,并从该目录读取 `Fuyutsui/`、`config/`、`keymap/` 和 `wow_process.txt`;模块从我的文档目录 `{MyDocuments}/Shigure/module` 读取。 ## 构建 @@ -111,7 +111,7 @@ Assets\ 应用图标、品牌资源、职业图和专精图 Fuyutsui\ 权威插件源码、配置/宏编辑源及游戏部署源 config\ 由 Fuyutsui 职业配置生成的扫描映射 keymap\ 由 Fuyutsui 职业宏生成的按键映射 -module\ 模块示例模板(运行时模块保存在用户配置目录 `~/.config/Shigure/module`) +module\ 模块示例模板(运行时模块保存在我的文档目录 `{MyDocuments}/Shigure/module`) Tools\ 辅助脚本 ``` @@ -159,7 +159,7 @@ Tools\ 辅助脚本 ## 模块系统 -模块以 `模块名.json` 保存在用户配置目录 `~/.config/Shigure/module`。名称不能重复;加载时会递归扫描子目录,以兼容旧版布局。模块页保存时会写入当前 Shigure 版本。职业和专精均已指定时,模块还会携带该专精的 `ClassBlocks`、职业 `spellsList`,以及该职业的通用/专精动态宏、静态宏和特殊宏;旧模块没有这些依赖信息时仍可正常使用。 +模块以 `模块名.json` 保存在我的文档目录 `{MyDocuments}/Shigure/module`。名称不能重复;加载时会递归扫描子目录,以兼容旧版布局。模块页保存时会写入当前 Shigure 版本。职业和专精均已指定时,模块还会携带该专精的 `ClassBlocks`、职业 `spellsList`,以及该职业的通用/专精动态宏、静态宏和特殊宏;旧模块没有这些依赖信息时仍可正常使用。 启动和“刷新模块”会把模块携带而本地缺少的配置与宏追加到项目 `Fuyutsui/`,不会覆盖或删除本地已有条目。发生新增后会自动重建 `config/keymap`、同步游戏插件并按需重启运行。导入前会按每项动态宏 30 个槽位、静态/特殊宏各 1 个槽位检查该职业所有受影响专精;合并结果超过 273 个槽位时,整个模块不会进入模块列表或运行时,本地 Lua 也不会被修改。模块文件仍保留在模块目录,清理宏后可刷新重试。 diff --git a/打包说明.md b/打包说明.md index 352bbed7..44d4d6f3 100644 --- a/打包说明.md +++ b/打包说明.md @@ -143,7 +143,7 @@ wow_process.txt 其中插件目录是插件权威源,程序会在启动或“更新配置”时把它部署到已运行游戏的 `Interface\AddOns\插件名称`;`Assets` 中的图标和职业/专精图片已作为资源嵌入程序,不要求单独分发。上述运行数据会在发布时复制到输出目录,最稳妥的方式仍是把 `win-x64` 整个文件夹压缩成 zip 再发送。 -模块不随发布包分发:模块保存在用户配置目录 `~/.config/Shigure/module`(首次运行自动创建),全新用户首次启动模块列表为空。使用改名脚本打包时该目录随程序名变化,例如改名为 `MyShigure` 后为 `~/.config/MyShigure/module`。 +模块不随发布包分发:模块保存在我的文档目录 `{MyDocuments}/Shigure/module`(首次运行自动创建),全新用户首次启动模块列表为空。使用改名脚本打包时该目录随程序名变化,例如改名为 `MyShigure` 后为 `{MyDocuments}/MyShigure/module`。 不要只发送单个 exe,也不要删除发布目录中的插件目录。如果缺少内置插件目录,配置/宏编辑和游戏插件部署都会失败。