@yangrunchi/a_6 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,7 +40,7 @@
40
40
  └── {模块文件夹}/
41
41
  ├── Panel/ -- 存放多个 UI.lua 文件(可选)
42
42
  ├── Items/ -- 存放 Item 文件,命名以 Item.lua 结尾(可选)
43
- └── {XXX}UI.lua -- UI 文件必须以 UI.lua 结尾
43
+ └── UI{XXX}.lua -- UI 文件必须以 UI{XXX}.lua 开头
44
44
  命名示例
45
45
  类型 命名格式 示例
46
46
  普通面板 UI{XXX}.lua UIBagPanel.lua
@@ -54,7 +54,7 @@
54
54
  dev/GUIExport/bag/UIMainBag.lua dev/GUILayout/bag/UIMainBagPanel.lua
55
55
  dev/GUIExport/bag/UISubBag.lua dev/GUILayout/bag/UISubBagPanel.lua
56
56
 
57
- 若以UI{XXX}.lua后缀结尾 --> 则首次自动生成GUILayout 目录下的 lua 文件。
57
+ 若以UI{XXX}.lua 前缀开头 --> 则首次自动生成GUILayout 目录下的 lua 文件。
58
58
 
59
59
  模版类型 —— 区分单独面板和子面板,减少重复代码
60
60
 
@@ -66,20 +66,20 @@
66
66
  ID = 41600,
67
67
 
68
68
  OBJ_PATH = "GUILayout/R/UIWingPanel",
69
- UI_PATH = "R/WingUI",
69
+ UI_PATH = "R/UIWing",
70
70
  UI_Name = "翅膀"
71
71
  }
72
72
 
73
73
  -- 打开方式
74
74
  ssrUIManager:OPEN(ssrObjCfg.Wing)
75
75
  ```
76
- #### 类型二:子面板(依赖通用一级背景框 ComOneBgOBJ
76
+ #### 类型二:子面板(依赖通用一级背景框 UIComOneBgPanel
77
77
  - **适用**:UISub{XXX}.lua
78
78
  - **模版**:A4_template_2.txt
79
79
  - **目的**:
80
- 依赖通用一级背景框的模版 ,就是把子界面拼接组装到 ComOneBgOBJ 里面,更灵活些。
80
+ 依赖通用一级背景框的模版 ,就是把子界面拼接组装到 UIComOneBgPanel 里面,更灵活些。
81
81
  - **注意事项**:
82
- 1、通用一级框 ComOneBgOBJ , 包含 遮罩 背景 关闭 问号 页签(有无都支持) 红点 等,能用一级背景框,尽量使用。
82
+ 1、通用一级框 UIComOneBgPanel , 包含 遮罩 背景 关闭 问号 页签(有无都支持) 红点 等,能用一级背景框,尽量使用。
83
83
 
84
84
  2、子界面 【垂直水平居中】 推荐使用节点
85
85
  第一种:基础容器 + 节点 —— 【N多元素 放2级节点里面】
@@ -107,8 +107,8 @@
107
107
  OBJ_ORDER = { ssrObjCfg.Mail },
108
108
  --OBJ_DESCRIBE = { "41400" }, 没有页签注释
109
109
  OBJ_TITLE = { "96000" },
110
- OBJ_PATH = "GUILayout/R/Com/ComOneBgOBJ",
111
- UI_PATH = "R/Com/ComOneBgUI",
110
+ OBJ_PATH = "GUILayout/R/Com/UIComOneBgPanel",
111
+ UI_PATH = "R/Com/UIComOneBg",
112
112
  }
113
113
  -- 打开方式
114
114
  ssrUIManager:OPEN(ssrObjCfg.Mail)
@@ -163,8 +163,8 @@
163
163
  OBJ_DESCRIBE = { "强化", "升星", "镶嵌", "洗炼" }, -- OBJ_DESCRIBE 数字 按钮名字是图片 ,否则按钮名字是中文
164
164
  OBJ_TITLE = { "1049", "1049", "1049", "1049" },
165
165
 
166
- OBJ_PATH = "GUILayout/R/Com/ComOneBgOBJ",
167
- UI_PATH = "R/Com/ComOneBgUI",
166
+ OBJ_PATH = "GUILayout/R/Com/UIComOneBgPanel",
167
+ UI_PATH = "R/Com/UIComOneBg",
168
168
  }
169
169
 
170
170
  -- 打开方式(自动选中对应页签)
@@ -253,7 +253,7 @@
253
253
  ssrRedMgr:SetRed(ssrObjCfg.NiepanZB.ID, isRed, 参数1)
254
254
  ssrRedMgr:SetRed(ssrObjCfg.NiepanZB.ID, isRed, 参数2)
255
255
 
256
- -- 注意:参数格式为 NiepanData、XiLianData、ChenghaoData 等 Vo 对象
256
+ -- 注意:参考格式为 NiepanData、XiLianData、ChenghaoData 等 Vo 对象
257
257
 
258
258
  ```
259
259
 
@@ -265,11 +265,24 @@
265
265
 
266
266
  ### 方式一:VSCode 任务集成 + 快捷键安装脚本
267
267
 
268
- **配置文件:** `dev/.vscode/project-keys.json`
268
+ **配置文件:** `a_tools/a_node/Tools/project-keys.json`
269
269
  **启用快捷键:终端执行** `node a_tools/a_node/Tools/install-keys.js`
270
270
  **禁用快捷键:终端执行** `node a_tools/a_node/Tools/uninstall-keys.js`
271
271
  `修改 project-keys.json 后,必须重新执行【启用快捷键】`
272
272
 
273
273
  ### 方式二:远程执行脚本(适合非 VSCode 用户)无需安装 VSCode,打开浏览器即可使用
274
274
 
275
- ### 远程地址:http://10.13.0.26:8080/
275
+ ### 远程地址:http://10.13.0.26:9964/
276
+
277
+
278
+ cd a_tools/a_node
279
+ npm login # 先登录 npm 账号
280
+ npm publish # 发布
281
+
282
+ npm config set //registry.npmjs.org/:_authToken=ck_fovt6rin8irk.KCuiWzbxfGUfPwFAmFWRVrILcfO9p2bq5yzjHP73ucw
283
+
284
+ #检查 token 是否生效:
285
+ npm whoami
286
+ npm view @yangrunchi/a_6
287
+ npm publish --access public
288
+
@@ -6,13 +6,15 @@
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
  const { execSync } = require('child_process');
9
+ const { getSVNAuthor } = require('../Tools/svn-utils');
9
10
 
10
11
  // ==================== 配置 ====================
12
+ const projectRoot = require('../Tools/project-root')();
11
13
 
12
14
  // 目录路径配置
13
- const csvcfgDir = path.join(__dirname, '../../../dev/GUILayout/ssrgame/csvcfg'); // CSV配置目录
14
- const mgrDir = path.join(__dirname, '../../../dev/GUILayout/ssrgame/mgr'); // 管理器目录
15
- const gameConfigDir = path.join(__dirname, '../../../dev/scripts/game_config'); // 游戏配置目录
15
+ const csvcfgDir = path.join(projectRoot, 'dev/GUILayout/ssrgame/csvcfg'); // CSV配置目录
16
+ const mgrDir = path.join(projectRoot, 'dev/GUILayout/ssrgame/mgr'); // 管理器目录
17
+ const gameConfigDir = path.join(projectRoot, 'dev/scripts/game_config'); // 游戏配置目录
16
18
  const tableMgrPath = path.join(mgrDir, 'TableMgr.lua'); // 输出文件路径
17
19
 
18
20
  // 标记定义 - 用于识别文件中需要自动更新的区域
@@ -55,10 +57,14 @@ try {
55
57
  const configPath = path.join(__dirname, '../AutoCode/A1_996_config.json');
56
58
  if (fs.existsSync(configPath)) {
57
59
  config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
58
- console.log('✅ 已加载配置, 作者:', config.author);
59
60
  }
60
61
  } catch (err) { }
61
62
 
63
+ // 自动获取 SVN 账户名(覆盖 config.author)
64
+ const projectRootForAuthor = path.resolve(__dirname, '../../..');
65
+ config.author = getSVNAuthor(projectRootForAuthor, config.author);
66
+ console.log('✅ 已加载配置, 作者:', config.author);
67
+
62
68
  // 需要排除的文件(不生成 require 语句)
63
69
  const excludeFiles = new Set(['template', 'example', 'test']);
64
70
  console.log('\n🚀 开始生成 TableMgr.lua...');
@@ -74,20 +80,6 @@ function getDateTime() {
74
80
 
75
81
  // ==================== SVN 辅助函数 ====================
76
82
 
77
- /**
78
- * 获取 SVN 用户名(当前登录的 SVN 用户)
79
- */
80
- function getSvnUsername() {
81
- try {
82
- const output = execSync(`svn info --show-item last-changed-author`, {
83
- encoding: 'utf8',
84
- stdio: ['pipe', 'pipe', 'ignore']
85
- }).trim();
86
- if (output) return output;
87
- } catch (err) { }
88
- return process.env.USERNAME || process.env.USER || config.author || 'unknown';
89
- }
90
-
91
83
  /**
92
84
  * 执行 SVN 更新(版本2风格)
93
85
  * @param {string} dirPath 目录路径
@@ -172,7 +164,7 @@ function commitTableMgrToSvn() {
172
164
  statusOutput.trim().startsWith('A'));
173
165
 
174
166
  if (needCommit) {
175
- const svnUser = getSvnUsername();
167
+ const svnUser = config.author;
176
168
  const isNewFile = !fs.existsSync(tableMgrPath) || statusOutput.trim().startsWith('A');
177
169
  const commitMessage = isNewFile ?
178
170
  `[Auto] ${svnUser} -首次创建 TableMgr.lua - ${getDateTime()}` :
package/AutoCfg/csvcfg.js CHANGED
@@ -10,8 +10,8 @@ const iconv = require('iconv-lite');
10
10
  const { execSync } = require('child_process');
11
11
 
12
12
  // ==================== 路径配置 ====================
13
- const projectRoot = path.join(__dirname, '../../../../'); // 996M2_Client 目录
14
- const moduleTableRoot = path.join(__dirname, '../../../../ModuleTable'); // ModuleTable 目录
13
+ const projectRoot = require('../Tools/project-root')();
14
+ const moduleTableRoot = path.join(projectRoot, '..', 'ModuleTable');
15
15
 
16
16
  // 源文件目录(xlsx 文件)
17
17
  const tPath = path.join(moduleTableRoot, 'table');
@@ -20,10 +20,10 @@ const tPath = path.join(moduleTableRoot, 'table');
20
20
  const toolPath = path.join(moduleTableRoot, 'tool');
21
21
 
22
22
  // 服务端输出目录
23
- const sPath = path.join(__dirname, '../../../../MirServer/Mir200/Envir/QuestDiary/cfgcsv');
23
+ const sPath = path.join(projectRoot, '..', 'MirServer/Mir200/Envir/QuestDiary/cfgcsv');
24
24
 
25
25
  // 客户端输出目录
26
- const cPath = path.join(__dirname, '../../../dev/GUILayout/ssrgame/csvcfg');
26
+ const cPath = path.join(projectRoot, 'dev/GUILayout/ssrgame/csvcfg');
27
27
 
28
28
  // 打印路径信息
29
29
  console.log('========================================');
@@ -1,7 +1,7 @@
1
1
  // -- 作者: 杨润池
2
- // -- 日期: 2026年0421
3
- // -- 版本: 1.2
4
- // -- 描述: 自动生成代码 (支持 UI/UISub/UIMain 前缀)
2
+ // -- 日期: 2026年0624
3
+ // -- 版本: 1.3
4
+ // -- 描述: 自动生成代码 (支持 UI/UISub/UIMain 前缀,作者自动获取 SVN 账户名)
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
@@ -18,6 +18,9 @@ try {
18
18
  process.exit(1);
19
19
  }
20
20
 
21
+ // 导入 SVN 工具函数
22
+ const { getSVNAuthor } = require('../Tools/svn-utils');
23
+
21
24
  // 读取 MainUI 模板(默认模板)
22
25
  const templatePath = path.join(__dirname, 'A4_template_1.txt');
23
26
  let templateMain = '';
@@ -40,12 +43,14 @@ try {
40
43
  process.exit(1);
41
44
  }
42
45
 
43
- const guiExportDir = path.join(__dirname, '../../../dev/GUIExport');
44
- const guiLayoutDir = path.join(__dirname, '../../../dev/GUILayout');
45
- const author = config.author;
46
+ const projectRoot = require('../Tools/project-root')();
47
+ const guiExportDir = path.join(projectRoot, 'dev/GUIExport');
48
+ const guiLayoutDir = path.join(projectRoot, 'dev/GUILayout');
49
+ const author = getSVNAuthor(projectRoot, config.author);
46
50
 
47
51
  console.log(`[DEBUG] guiExportDir: ${guiExportDir}`);
48
52
  console.log(`[DEBUG] guiLayoutDir: ${guiLayoutDir}`);
53
+ console.log(`[DEBUG] author: ${author}`);
49
54
 
50
55
  function getDateTime() {
51
56
  const d = new Date();
@@ -63,16 +68,16 @@ function generate(uiFilePath) {
63
68
 
64
69
  console.log(`[DEBUG] uiFileName: ${uiFileName}`);
65
70
 
66
- // 修正: 检查文件名是否包含 UIUISubUIMain 前缀
67
- const hasUIPrefix = uiFileName.startsWith('UI');
71
+ // 检查文件名是否符合 UI/UISub/UIMain 前缀规则(互斥判断,避免 UI 误匹配 UIMain/UISub)
68
72
  const hasUISubPrefix = uiFileName.startsWith('UISub');
69
73
  const hasUIMainPrefix = uiFileName.startsWith('UIMain');
74
+ const hasUIPrefix = uiFileName.startsWith('UI') && !hasUISubPrefix && !hasUIMainPrefix;
70
75
 
71
76
  const isValidUI = hasUIPrefix || hasUISubPrefix || hasUIMainPrefix;
72
77
 
73
78
  if (!isValidUI) {
74
79
  console.log(`[SKIP] Not a valid UI file: ${uiFileName}`);
75
- console.log(`[INFO] Expected file starting with: UI, UISub, or UIMain`);
80
+ console.log(`[INFO] Expected file starting with: UI{XXX}, UIMain{XXX}, or UISub{XXX}`);
76
81
  return false;
77
82
  }
78
83
 
@@ -105,16 +110,20 @@ function generate(uiFilePath) {
105
110
  console.log(`[MKDIR] ${path.relative(guiLayoutDir, dir)}`);
106
111
  }
107
112
 
108
- // 判断模板类型
113
+ // 判断模板类型:UISub → SubUI 模板,UI/UIMain → MainUI 模板
109
114
  let selectedTemplate = templateMain;
110
115
  let templateType = "MainUI";
116
+ let prefixType = "UI";
111
117
 
112
118
  if (hasUISubPrefix) {
113
119
  selectedTemplate = templateSub;
114
120
  templateType = "SubUI";
121
+ prefixType = "UISub";
122
+ } else if (hasUIMainPrefix) {
123
+ prefixType = "UIMain";
115
124
  }
116
125
 
117
- console.log(`[INFO] Using ${templateType} template (prefix: ${hasUISubPrefix ? 'UISub' : (hasUIMainPrefix ? 'UIMain' : 'UI')})`);
126
+ console.log(`[INFO] Using ${templateType} template (prefix: ${prefixType})`);
118
127
 
119
128
  // 替换模板变量
120
129
  const content = selectedTemplate
@@ -20,7 +20,8 @@ if (config.watchEnabled === false) {
20
20
  process.exit(0);
21
21
  }
22
22
 
23
- const watchDir = path.join(__dirname, '../../../dev/GUIExport');
23
+ const projectRoot = require('../Tools/project-root')();
24
+ const watchDir = path.join(projectRoot, 'dev/GUIExport');
24
25
  const generateScript = path.join(__dirname, 'A2_generate-panel.js');
25
26
 
26
27
  console.log(`[WATCH] Directory: ${watchDir}`);
@@ -83,10 +84,10 @@ fs.watch(watchDir, { recursive: true }, (eventType, filename) => {
83
84
  return;
84
85
  }
85
86
 
86
- // 检查文件名是否以 UIUISubUIMain 开头
87
- const hasUIPrefix = baseName.startsWith('UI');
87
+ // 检查文件名是否符合 UI/UISub/UIMain 前缀规则(互斥判断,避免 UI 误匹配 UIMain/UISub)
88
88
  const hasUISubPrefix = baseName.startsWith('UISub');
89
89
  const hasUIMainPrefix = baseName.startsWith('UIMain');
90
+ const hasUIPrefix = baseName.startsWith('UI') && !hasUISubPrefix && !hasUIMainPrefix;
90
91
 
91
92
  const isValidUI = hasUIPrefix || hasUISubPrefix || hasUIMainPrefix;
92
93
 
@@ -7,11 +7,13 @@ const fs = require('fs');
7
7
  const path = require('path');
8
8
  const { execSync } = require('child_process');
9
9
  const os = require('os');
10
+ const { getSVNAuthor } = require('../Tools/svn-utils');
10
11
 
11
12
  // ==================== 配置 ====================
13
+ const projectRoot = require('../Tools/project-root')();
12
14
 
13
- const bPath = path.join(__dirname, '../../../dev/GUILayout/ssrgame/net', 'NetMsgCfg.lua');
14
- const ssrgameRoot = path.join(__dirname, '../../../dev/GUILayout/ssrgame');
15
+ const bPath = path.join(projectRoot, 'dev/GUILayout/ssrgame/net/NetMsgCfg.lua');
16
+ const ssrgameRoot = path.join(projectRoot, 'dev/GUILayout/ssrgame');
15
17
  const funcDataDir = path.join(ssrgameRoot, 'funcData');
16
18
  const mgrDir = path.join(ssrgameRoot, 'mgr');
17
19
 
@@ -70,12 +72,16 @@ try {
70
72
  if (fs.existsSync(configPath)) {
71
73
  const configContent = fs.readFileSync(configPath, 'utf-8');
72
74
  config = JSON.parse(configContent);
73
- console.log('✅ 已加载配置, 作者:', config.author);
74
75
  }
75
76
  } catch (err) {
76
77
  console.log('⚠️ 未找到配置文件,使用默认配置');
77
78
  }
78
79
 
80
+ // 自动获取 SVN 账户名(覆盖 config.author)
81
+ const projectRootForAuthor = path.resolve(__dirname, '../../..');
82
+ config.author = getSVNAuthor(projectRootForAuthor, config.author);
83
+ console.log('✅ 已加载配置, 作者:', config.author);
84
+
79
85
  console.log('🚀 开始生成 funcData 类...');
80
86
  console.log('📁 协议文件:', bPath);
81
87
  console.log('📁 数据类输出目录:', funcDataDir);
@@ -9,10 +9,11 @@ const iconv = require('iconv-lite');
9
9
  const svnUtils = require('../Tools/svn-utils');
10
10
 
11
11
  // ==================== 配置 ====================
12
+ const projectRoot = require('../Tools/project-root')();
12
13
 
13
- const NetMsgrPath = path.join(__dirname, '../../../../NetMsg');
14
- const aPath = path.join(__dirname, '../../../../MirServer/Mir200/Envir/QuestDiary/net/', 'NetMsgCfg.lua');
15
- const bPath = path.join(__dirname, '../../../dev/GUILayout/ssrgame/net', 'NetMsgCfg.lua');
14
+ const NetMsgrPath = path.join(projectRoot, '..', 'NetMsg');
15
+ const aPath = path.join(projectRoot, '..', 'MirServer/Mir200/Envir/QuestDiary/net/NetMsgCfg.lua');
16
+ const bPath = path.join(projectRoot, 'dev/GUILayout/ssrgame/net/NetMsgCfg.lua');
16
17
 
17
18
  // 标记定义(统一管理,避免硬编码)
18
19
  const MARKERS = {
@@ -8,8 +8,9 @@ const iconv = require('iconv-lite');
8
8
  const svnUtils = require('../Tools/svn-utils');
9
9
 
10
10
  // ==================== 配置 ====================
11
+ const projectRoot = require('../Tools/project-root')();
11
12
 
12
- const ProjecPath = path.join(__dirname, '../../../../../Project');
13
+ const ProjecPath = path.join(projectRoot, '..');
13
14
 
14
15
  console.log('🚀 开始执行协议同步流程...');
15
16
  console.log('📁 当前工作目录:', __dirname);
@@ -1,117 +1,207 @@
1
1
  // -- 作者: 杨润池
2
2
  // -- 日期: 2025年10月25日
3
- // -- 版本: 2.0
4
- // -- 描述: 添加快捷键
3
+ // -- 版本: 2.2
4
+ // -- 描述: 多编辑器快捷键同步工具(VS Code / CodeBuddy CN / Cursor)
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
 
9
- function installProjectKeys() {
10
- try {
11
- // 1. 检查项目配置文件是否存在
12
- const projectKeysPath = path.join(__dirname, 'project-keys.json');
13
- if (!fs.existsSync(projectKeysPath)) {
14
- console.log('❌ 项目快捷键配置文件不存在:', projectKeysPath);
15
- console.log('💡 请创建 .vscode/project-keys.json 文件');
16
- return false;
9
+ // ============================================================
10
+ // 获取所有已安装编辑器的 keybindings.json 路径
11
+ // ============================================================
12
+ function getEditorPaths() {
13
+ const editors = [];
14
+ const platform = process.platform;
15
+ const home = process.env.HOME || process.env.USERPROFILE || '';
16
+ const appData = process.env.APPDATA || (platform === 'darwin'
17
+ ? path.join(home, 'Library', 'Application Support')
18
+ : path.join(home, '.config'));
19
+
20
+ function addEditor(name, dirName) {
21
+ const editorPath = path.join(appData, dirName, 'User', 'keybindings.json');
22
+ const editorDir = path.dirname(editorPath);
23
+ if (fs.existsSync(editorDir)) {
24
+ editors.push({ name, path: editorPath });
17
25
  }
26
+ }
18
27
 
19
- // 2. 读取项目配置
20
- let projectKeys;
21
- try {
22
- const projectKeysContent = fs.readFileSync(projectKeysPath, 'utf8');
23
- projectKeys = JSON.parse(projectKeysContent);
24
- } catch (error) {
25
- console.log('❌ 读取项目快捷键配置失败:', error.message);
26
- return false;
27
- }
28
+ // 按优先级检测编辑器
29
+ addEditor('VS Code', 'Code');
30
+ addEditor('CodeBuddy CN', 'CodeBuddy CN');
31
+ addEditor('CodeBuddy', 'CodeBuddy');
32
+ addEditor('Cursor', 'Cursor');
33
+
34
+ // 如果 CodeBuddy CN 和 CodeBuddy 同时存在,只保留 CN 版本
35
+ const hasCN = editors.some(e => e.name === 'CodeBuddy CN');
36
+ if (hasCN) {
37
+ const idx = editors.findIndex(e => e.name === 'CodeBuddy');
38
+ if (idx !== -1) editors.splice(idx, 1);
39
+ }
28
40
 
29
- // 3. 确定全局快捷键文件路径
30
- const globalKeysPath = path.join(
31
- process.env.APPDATA ||
32
- (process.platform === 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + '/.config'),
33
- 'Code/User/keybindings.json'
34
- );
35
-
36
- // 4. 确保目录存在
37
- const globalKeysDir = path.dirname(globalKeysPath);
38
- if (!fs.existsSync(globalKeysDir)) {
39
- fs.mkdirSync(globalKeysDir, { recursive: true });
40
- }
41
+ return editors;
42
+ }
41
43
 
42
- // 5. 读取或创建全局配置
44
+ // ============================================================
45
+ // 安装快捷键到单个编辑器
46
+ // ============================================================
47
+ function installToEditor(editor, projectKeys, projectName) {
48
+ try {
49
+ console.log(`\n📝 正在配置 ${editor.name}...`);
50
+ console.log(` 路径: ${editor.path}`);
51
+
52
+ // 读取或创建配置
43
53
  let globalKeys = [];
44
- if (fs.existsSync(globalKeysPath)) {
54
+ if (fs.existsSync(editor.path)) {
45
55
  try {
46
- const globalKeysContent = fs.readFileSync(globalKeysPath, 'utf8');
47
- globalKeys = JSON.parse(globalKeysContent);
56
+ const content = fs.readFileSync(editor.path, 'utf8');
57
+ globalKeys = JSON.parse(content);
48
58
  if (!Array.isArray(globalKeys)) {
49
- console.log('⚠️ 全局快捷键配置不是数组格式,重置为数组');
59
+ console.log(` ⚠️ 配置不是数组格式,重置`);
50
60
  globalKeys = [];
51
61
  }
52
- } catch (error) {
53
- console.log('⚠️ 读取全局快捷键配置失败,创建新配置:', error.message);
62
+ } catch (e) {
63
+ console.log(` ⚠️ 读取失败,创建新配置: ${e.message}`);
54
64
  globalKeys = [];
55
65
  }
56
66
  }
57
67
 
58
- // 6. 获取项目名称用于条件
59
- const projectName = path.basename(process.cwd());
60
- console.log(`📁 项目名称: ${projectName}`);
61
-
62
- // 7. 移除已存在的本项目快捷键(避免重复)
63
- const existingKeysCount = globalKeys.length;
64
- globalKeys = globalKeys.filter(item =>
65
- !(item.when && item.when.includes(projectName))
66
- );
67
- const removedCount = existingKeysCount - globalKeys.length;
68
- if (removedCount > 0) {
69
- console.log(`🗑️ 移除了 ${removedCount} 个已存在的项目快捷键`);
68
+ // 移除本项目已有快捷键(避免重复)
69
+ const before = globalKeys.length;
70
+ globalKeys = globalKeys.filter(item => {
71
+ if (item.when && typeof item.when === 'string') {
72
+ return !item.when.includes(projectName);
73
+ }
74
+ return true;
75
+ });
76
+ const removed = before - globalKeys.length;
77
+ if (removed > 0) {
78
+ console.log(` 🗑️ 移除 ${removed} 个已有快捷键`);
70
79
  }
71
80
 
72
- // 8. 添加新的项目快捷键
73
- if (projectKeys.shortcuts && Array.isArray(projectKeys.shortcuts)) {
74
- projectKeys.shortcuts.forEach((shortcut, index) => {
75
- // 深拷贝避免修改原对象
76
- const newShortcut = JSON.parse(JSON.stringify(shortcut));
81
+ // 添加新快捷键
82
+ if (!projectKeys.shortcuts || !Array.isArray(projectKeys.shortcuts)) {
83
+ console.log(` ❌ 缺少 shortcuts 数组`);
84
+ return false;
85
+ }
77
86
 
78
- // 添加条件限制
79
- if (!newShortcut.when) {
80
- newShortcut.when = `resourcePath =~ /${projectName}/`;
81
- }
87
+ let added = 0;
88
+ projectKeys.shortcuts.forEach((sc, i) => {
89
+ const ns = JSON.parse(JSON.stringify(sc)); // 深拷贝
82
90
 
83
- globalKeys.push(newShortcut);
84
- console.log(`✅ 添加快捷键 ${index + 1}: ${newShortcut.key} -> ${newShortcut.command}`);
85
- });
86
- } else {
87
- console.log('❌ 项目配置中缺少 shortcuts 数组');
91
+ // 智能合并 when 条件
92
+ if (!ns.when) {
93
+ ns.when = `resourcePath =~ /${projectName}/`;
94
+ } else if (!ns.when.includes(projectName)) {
95
+ ns.when = `(${ns.when}) && resourcePath =~ /${projectName}/`;
96
+ }
97
+
98
+ globalKeys.push(ns);
99
+ added++;
100
+ console.log(` ✅ [${i + 1}] ${ns.key} → ${ns.command}`);
101
+ });
102
+
103
+ // 确保目录存在
104
+ const dir = path.dirname(editor.path);
105
+ if (!fs.existsSync(dir)) {
106
+ fs.mkdirSync(dir, { recursive: true });
107
+ }
108
+
109
+ // 写回
110
+ fs.writeFileSync(editor.path, JSON.stringify(globalKeys, null, 4));
111
+ console.log(` ✅ ${editor.name} 完成! 添加 ${added} 个快捷键`);
112
+ return true;
113
+
114
+ } catch (error) {
115
+ console.log(` ❌ ${editor.name} 失败: ${error.message}`);
116
+ return false;
117
+ }
118
+ }
119
+
120
+ // ============================================================
121
+ // 主入口
122
+ // ============================================================
123
+ function installProjectKeys() {
124
+ try {
125
+ console.log('='.repeat(56));
126
+ console.log(' 🚀 项目快捷键同步工具 v2.2');
127
+ console.log('='.repeat(56));
128
+
129
+ // 1. 读取项目配置
130
+ const projectKeysPath = path.join(__dirname, 'project-keys.json');
131
+ if (!fs.existsSync(projectKeysPath)) {
132
+ console.log(`❌ 配置文件不存在: ${projectKeysPath}`);
133
+ console.log('💡 请在同目录下创建 project-keys.json');
88
134
  return false;
89
135
  }
90
136
 
91
- // 9. 写回全局配置
137
+ let projectKeys;
92
138
  try {
93
- fs.writeFileSync(globalKeysPath, JSON.stringify(globalKeys, null, 4));
94
- console.log(`🎉 项目快捷键安装成功! 共添加 ${projectKeys.shortcuts.length} 个快捷键`);
95
- console.log(`📝 全局配置文件: ${globalKeysPath}`);
96
- return true;
97
- } catch (error) {
98
- console.log('❌ 写入全局快捷键配置失败:', error.message);
139
+ projectKeys = JSON.parse(fs.readFileSync(projectKeysPath, 'utf8'));
140
+ console.log('✅ 项目配置读取成功');
141
+ } catch (e) {
142
+ console.log(`❌ JSON 解析失败: ${e.message}`);
99
143
  return false;
100
144
  }
101
145
 
146
+ // 2. 项目名称
147
+ const projectName = path.basename(process.cwd());
148
+ console.log(`📁 项目: ${projectName}`);
149
+ console.log(`📋 快捷键数量: ${projectKeys.shortcuts ? projectKeys.shortcuts.length : 0}`);
150
+
151
+ // 3. 显示快捷键列表
152
+ if (projectKeys.shortcuts && projectKeys.shortcuts.length > 0) {
153
+ console.log('\n📌 将要安装:');
154
+ projectKeys.shortcuts.forEach((sc, i) => {
155
+ console.log(` ${i + 1}. ${sc.key} → ${sc.command}${sc.args ? ` (${sc.args})` : ''}`);
156
+ });
157
+ }
158
+
159
+ // 4. 检测编辑器
160
+ const editors = getEditorPaths();
161
+ if (editors.length === 0) {
162
+ console.log('\n⚠️ 未检测到已安装的编辑器');
163
+ console.log('💡 支持: VS Code, CodeBuddy CN, CodeBuddy, Cursor');
164
+ return false;
165
+ }
166
+
167
+ console.log(`\n🔍 检测到 ${editors.length} 个编辑器:`);
168
+ editors.forEach(e => console.log(` ✅ ${e.name}`));
169
+
170
+ // 5. 同步
171
+ console.log('\n🚀 开始同步...');
172
+ console.log('-'.repeat(56));
173
+
174
+ let success = 0;
175
+ editors.forEach(e => {
176
+ if (installToEditor(e, projectKeys, projectName)) success++;
177
+ });
178
+
179
+ // 6. 总结
180
+ console.log('\n' + '='.repeat(56));
181
+ console.log(`🎉 同步完成! 成功: ${success}/${editors.length}`);
182
+ console.log('='.repeat(56));
183
+ console.log('💡 可能需要重启编辑器或执行 "Reload Window" 才能生效');
184
+
185
+ return success === editors.length;
186
+
102
187
  } catch (error) {
103
- console.log('💥 安装过程中发生未知错误:', error.message);
188
+ console.log(`💥 未知错误: ${error.message}`);
189
+ console.error(error);
104
190
  return false;
105
191
  }
106
192
  }
107
193
 
108
- // 执行安装
194
+ // ============================================================
195
+ // 执行
196
+ // ============================================================
109
197
  if (require.main === module) {
110
198
  installProjectKeys();
111
199
  }
112
200
 
113
201
  module.exports = installProjectKeys;
114
202
 
115
- //Preferences: Open Keyboard Shortcuts
116
-
117
- //node a_tools/a_node/Tools/install-keys.js
203
+ // 使用方法:
204
+ // node a_tools/a_node/Tools/install-keys.js
205
+ // 支持的编辑器:
206
+ // VS Code / CodeBuddy CN / CodeBuddy / Cursor
207
+ // 自动检测已安装的编辑器并同步快捷键
@@ -0,0 +1,41 @@
1
+ /**
2
+ * 项目根路径查找模块
3
+ * 通过查找 996M2_Client.exe 或 env.json 定位项目根目录
4
+ */
5
+ const path = require('path');
6
+ const fs = require('fs');
7
+
8
+ let _cachedRoot = null;
9
+
10
+ function findProjectRoot() {
11
+ if (_cachedRoot) return _cachedRoot;
12
+
13
+ // 优先从环境变量获取(cli.js 会设置)
14
+ if (process.env.M2_PROJECT_ROOT) {
15
+ _cachedRoot = process.env.M2_PROJECT_ROOT;
16
+ return _cachedRoot;
17
+ }
18
+
19
+ // 从当前工作目录向上查找
20
+ let cwd = process.cwd();
21
+ const markers = ['996M2_Client.exe', 'env.json', 'game.dat'];
22
+
23
+ for (let i = 0; i < 6; i++) {
24
+ for (const marker of markers) {
25
+ if (fs.existsSync(path.join(cwd, marker))) {
26
+ _cachedRoot = cwd;
27
+ return _cachedRoot;
28
+ }
29
+ }
30
+ const parent = path.dirname(cwd);
31
+ if (parent === cwd) break;
32
+ cwd = parent;
33
+ }
34
+
35
+ // 找不到则报错
36
+ console.error('错误: 找不到 996M2_Client 项目根目录');
37
+ console.error('请在 996M2_Client 项目目录下运行此命令');
38
+ process.exit(1);
39
+ }
40
+
41
+ module.exports = findProjectRoot;
@@ -1,10 +1,11 @@
1
1
  // -- 作者: 杨润池
2
2
  // -- 日期: 2025年10月25日
3
- // -- 版本: 2.0
4
- // -- 描述: SVN 工具
3
+ // -- 版本: 2.1
4
+ // -- 描述: SVN 工具函数集
5
5
 
6
6
  const fs = require('fs');
7
7
  const { execSync, spawnSync } = require('child_process');
8
+
8
9
  // 详细检测 SVN 是否可用
9
10
  function checkSvnEnvironment() {
10
11
  const pathEnv = process.env.PATH || '';
@@ -98,8 +99,6 @@ function cleanDirectory(targetPath) {
98
99
  return true;
99
100
  }
100
101
 
101
- // console.log(`🗑️ 清理目录: ${targetPath}`);
102
-
103
102
  // 使用 rd /s /q 命令强制删除目录(Windows)
104
103
  if (process.platform === 'win32') {
105
104
  execSync(`rd /s /q "${targetPath}"`, { stdio: 'inherit' });
@@ -116,11 +115,62 @@ function cleanDirectory(targetPath) {
116
115
  }
117
116
  }
118
117
 
118
+ /**
119
+ * 获取当前 SVN 仓库的账户名
120
+ * @param {string} projectRoot - 项目根目录路径
121
+ * @param {string} [fallbackAuthor] - SVN 不可用时回退的作者名
122
+ * @returns {string} SVN 账户名或回退作者名
123
+ */
124
+ function getSVNAuthor(projectRoot, fallbackAuthor) {
125
+ try {
126
+ // 获取当前仓库的地址(用于匹配 svn auth 中的 realm)
127
+ const reposUrl = execSync(`svn info --show-item=repos-root-url "${projectRoot}"`, {
128
+ encoding: 'utf-8'
129
+ }).trim();
130
+
131
+ // 提取仓库主机地址(如 "192.168.13.64"),兼容有无端口号、不同协议
132
+ const reposHost = reposUrl.replace(/^[a-z]+:\/\//, '').split(':')[0];
133
+
134
+ // 解析 svn auth 输出,匹配当前仓库的用户名
135
+ const authOutput = execSync('svn auth --non-interactive', {
136
+ encoding: 'utf-8'
137
+ });
138
+
139
+ // 按分隔线分割每个认证条目
140
+ const entries = authOutput.split(/^-{3,}$/m);
141
+ for (const entry of entries) {
142
+ const realmMatch = entry.match(/Authentication realm:\s*<([^>]+)>/);
143
+ if (realmMatch) {
144
+ // 提取 realm 中的主机地址进行匹配
145
+ const realmHost = realmMatch[1].replace(/^[a-z]+:\/\//, '').split(':')[0];
146
+ if (realmHost === reposHost) {
147
+ const userMatch = entry.match(/Username:\s*(.+)/);
148
+ if (userMatch) {
149
+ return userMatch[1].trim();
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ // fallback: 取 svn auth 中最后一个用户名(最近使用的)
156
+ const userLines = authOutput.match(/Username:\s*(.+)/g);
157
+ if (userLines && userLines.length > 0) {
158
+ return userLines[userLines.length - 1].replace(/Username:\s*/, '').trim();
159
+ }
160
+ } catch (e) {
161
+ // SVN 命令失败时忽略,回退到传入的 fallbackAuthor
162
+ }
163
+
164
+ // 最终回退:使用传入的回退作者名
165
+ return fallbackAuthor || '';
166
+ }
167
+
119
168
  // 导出所有函数
120
169
  module.exports = {
121
170
  checkSvnEnvironment,
122
171
  isSvnAvailable,
123
172
  runCommand,
124
173
  runCommit,
125
- cleanDirectory
126
- };
174
+ cleanDirectory,
175
+ getSVNAuthor
176
+ };
@@ -1,65 +1,195 @@
1
1
  // -- 作者: 杨润池
2
2
  // -- 日期: 2025年10月25日
3
- // -- 版本: 2.0
4
- // -- 描述: 删除快捷键
3
+ // -- 版本: 2.2
4
+ // -- 描述: 多编辑器快捷键卸载工具(VS Code / CodeBuddy CN / Cursor)
5
5
 
6
6
  const fs = require('fs');
7
7
  const path = require('path');
8
8
 
9
- function uninstallProjectKeys() {
9
+ // ============================================================
10
+ // 获取所有已安装编辑器的 keybindings.json 路径
11
+ // ============================================================
12
+ function getEditorPaths() {
13
+ const editors = [];
14
+ const platform = process.platform;
15
+ const home = process.env.HOME || process.env.USERPROFILE || '';
16
+ const appData = process.env.APPDATA || (platform === 'darwin'
17
+ ? path.join(home, 'Library', 'Application Support')
18
+ : path.join(home, '.config'));
19
+
20
+ function addEditor(name, dirName) {
21
+ const editorPath = path.join(appData, dirName, 'User', 'keybindings.json');
22
+ const editorDir = path.dirname(editorPath);
23
+ if (fs.existsSync(editorDir)) {
24
+ editors.push({ name, path: editorPath });
25
+ }
26
+ }
27
+
28
+ addEditor('VS Code', 'Code');
29
+ addEditor('CodeBuddy CN', 'CodeBuddy CN');
30
+ addEditor('CodeBuddy', 'CodeBuddy');
31
+ addEditor('Cursor', 'Cursor');
32
+
33
+ // 如果 CodeBuddy CN 和 CodeBuddy 同时存在,只保留 CN
34
+ const hasCN = editors.some(e => e.name === 'CodeBuddy CN');
35
+ if (hasCN) {
36
+ const idx = editors.findIndex(e => e.name === 'CodeBuddy');
37
+ if (idx !== -1) editors.splice(idx, 1);
38
+ }
39
+
40
+ return editors;
41
+ }
42
+
43
+ // ============================================================
44
+ // 从单个编辑器卸载项目快捷键
45
+ // ============================================================
46
+ function uninstallFromEditor(editor, projectName) {
10
47
  try {
11
- // 确定全局快捷键文件路径
12
- const globalKeysPath = path.join(
13
- process.env.APPDATA ||
14
- (process.platform === 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + '/.config'),
15
- 'Code/User/keybindings.json'
16
- );
17
-
18
- if (!fs.existsSync(globalKeysPath)) {
19
- console.log('ℹ️ 全局快捷键配置文件不存在,无需卸载');
48
+ console.log(`\n📝 正在处理 ${editor.name}...`);
49
+ console.log(` 路径: ${editor.path}`);
50
+
51
+ if (!fs.existsSync(editor.path)) {
52
+ console.log(` ℹ️ 配置文件不存在,跳过`);
20
53
  return true;
21
54
  }
22
55
 
23
- // 读取全局配置
56
+ // 读取配置
24
57
  let globalKeys = [];
25
58
  try {
26
- const globalKeysContent = fs.readFileSync(globalKeysPath, 'utf8');
27
- globalKeys = JSON.parse(globalKeysContent);
59
+ const content = fs.readFileSync(editor.path, 'utf8');
60
+ globalKeys = JSON.parse(content);
28
61
  if (!Array.isArray(globalKeys)) {
29
- console.log('⚠️ 全局快捷键配置不是数组格式,重置为数组');
30
- globalKeys = [];
62
+ console.log(` ⚠️ 配置不是数组格式,跳过`);
63
+ return true;
31
64
  }
32
- } catch (error) {
33
- console.log('读取全局快捷键配置失败:', error.message);
65
+ } catch (e) {
66
+ console.log(` 读取失败: ${e.message}`);
34
67
  return false;
35
68
  }
36
69
 
37
- // 获取项目名称
38
- const projectName = path.basename(process.cwd());
39
-
40
- // 移除本项目相关的快捷键
41
- const initialCount = globalKeys.length;
42
- globalKeys = globalKeys.filter(item =>
43
- !(item.when && item.when.includes(projectName))
44
- );
45
- const removedCount = initialCount - globalKeys.length;
46
-
47
- // 写回全局配置
48
- fs.writeFileSync(globalKeysPath, JSON.stringify(globalKeys, null, 4));
49
- console.log(`🗑️ 卸载完成! 移除了 ${removedCount} 个项目快捷键`);
70
+ // 移除本项目快捷键
71
+ const before = globalKeys.length;
72
+ globalKeys = globalKeys.filter(item => {
73
+ if (item.when && typeof item.when === 'string') {
74
+ return !item.when.includes(projectName);
75
+ }
76
+ return true;
77
+ });
78
+ const removed = before - globalKeys.length;
79
+
80
+ // 写回 或 删除空文件
81
+ if (globalKeys.length === 0) {
82
+ fs.unlinkSync(editor.path);
83
+ console.log(` 🗑️ 配置已清空,已删除文件`);
84
+ } else {
85
+ fs.writeFileSync(editor.path, JSON.stringify(globalKeys, null, 4));
86
+ }
87
+ console.log(` ✅ ${editor.name} 卸载完成! 移除 ${removed} 个快捷键`);
88
+
89
+ if (removed === 0) {
90
+ console.log(` ℹ️ 没有找到本项目的快捷键`);
91
+ }
92
+
50
93
  return true;
51
94
 
52
95
  } catch (error) {
53
- console.log('💥 卸载过程中发生错误:', error.message);
96
+ console.log(` ❌ ${editor.name} 失败: ${error.message}`);
97
+ return false;
98
+ }
99
+ }
100
+
101
+ // ============================================================
102
+ // 主入口
103
+ // ============================================================
104
+ function uninstallProjectKeys() {
105
+ try {
106
+ console.log('='.repeat(56));
107
+ console.log(' 🗑️ 项目快捷键卸载工具 v2.2');
108
+ console.log('='.repeat(56));
109
+
110
+ // 项目名称
111
+ const projectName = path.basename(process.cwd());
112
+ console.log(`📁 项目: ${projectName}`);
113
+
114
+ // 检测编辑器
115
+ const editors = getEditorPaths();
116
+ if (editors.length === 0) {
117
+ console.log('\n⚠️ 未检测到已安装的编辑器');
118
+ console.log('💡 支持: VS Code, CodeBuddy CN, CodeBuddy, Cursor');
119
+ return false;
120
+ }
121
+
122
+ console.log(`\n🔍 检测到 ${editors.length} 个编辑器:`);
123
+ editors.forEach(e => console.log(` ✅ ${e.name}`));
124
+
125
+ // 仅处理存在配置文件的编辑器
126
+ const withConfig = editors.filter(e => fs.existsSync(e.path));
127
+ const noConfig = editors.filter(e => !fs.existsSync(e.path));
128
+
129
+ if (noConfig.length > 0) {
130
+ console.log(`\nℹ️ ${noConfig.length} 个编辑器无配置文件,将跳过:`);
131
+ noConfig.forEach(e => console.log(` - ${e.name}`));
132
+ }
133
+
134
+ if (withConfig.length === 0) {
135
+ console.log('\nℹ️ 所有编辑器都无配置文件,无需卸载');
136
+ return true;
137
+ }
138
+
139
+ // 卸载
140
+ console.log('\n🚀 开始卸载...');
141
+ console.log('-'.repeat(56));
142
+
143
+ let success = 0;
144
+ let totalRemoved = 0;
145
+
146
+ // 先统计每个编辑器中要移除的快捷键数量
147
+ withConfig.forEach(e => {
148
+ try {
149
+ const content = fs.readFileSync(e.path, 'utf8');
150
+ const keys = JSON.parse(content);
151
+ if (Array.isArray(keys)) {
152
+ const count = keys.filter(item =>
153
+ item.when && typeof item.when === 'string' && item.when.includes(projectName)
154
+ ).length;
155
+ if (count > 0) {
156
+ console.log(` 📋 ${e.name}: 将移除 ${count} 个快捷键`);
157
+ }
158
+ }
159
+ } catch (_) { /* ignore */ }
160
+ });
161
+
162
+ // 执行卸载
163
+ withConfig.forEach(e => {
164
+ if (uninstallFromEditor(e, projectName)) success++;
165
+ });
166
+
167
+ // 总结
168
+ console.log('\n' + '='.repeat(56));
169
+ console.log(`🎉 卸载完成! 处理: ${success}/${withConfig.length} 个编辑器`);
170
+ console.log('='.repeat(56));
171
+ console.log('💡 可能需要重启编辑器或执行 "Reload Window" 才能生效');
172
+
173
+ return success === withConfig.length;
174
+
175
+ } catch (error) {
176
+ console.log(`💥 未知错误: ${error.message}`);
177
+ console.error(error);
54
178
  return false;
55
179
  }
56
180
  }
57
181
 
58
- // 执行卸载
182
+ // ============================================================
183
+ // 执行
184
+ // ============================================================
59
185
  if (require.main === module) {
60
186
  uninstallProjectKeys();
61
187
  }
62
188
 
63
189
  module.exports = uninstallProjectKeys;
64
190
 
65
- //node a_tools/a_node/Tools/uninstall-keys.js
191
+ // 使用方法:
192
+ // node a_tools/a_node/Tools/uninstall-keys.js
193
+ // 支持的编辑器:
194
+ // VS Code / CodeBuddy CN / CodeBuddy / Cursor
195
+ // 自动检测并移除所有编辑器中的本项目快捷键
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
6
- <title>BAT脚本管理器 - 远程执行控制台</title>
6
+ <title>盟约传奇 一键工具</title>
7
7
  <style>
8
8
  * {
9
9
  box-sizing: border-box;
@@ -594,7 +594,7 @@
594
594
  let localTaskRunning = false; // 本地发起任务是否在执行
595
595
  let pendingEndTimer = null;
596
596
 
597
- const WS_URL = `ws://${window.location.hostname}:8080`;
597
+ const WS_URL = `ws://${window.location.hostname}:9964`;
598
598
 
599
599
  // DOM 元素
600
600
  const authOverlay = document.getElementById('authOverlay');
@@ -1,42 +1,26 @@
1
1
  [
2
2
  {
3
- "id": "1776933313049",
4
- "name": "打配置",
5
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-csvcfg.bat",
3
+ "id": "1782186651373",
4
+ "name": "一键配置",
5
+ "path": "G:\\MengYueChuanQi996\\Project\\996M2_Client\\a_tools\\a_node\\run-csvcfg.bat",
6
6
  "args": "",
7
- "addedBy": "qwe1234",
8
- "addedAt": "2026-04-23T08:35:13.049Z"
9
- },
10
- {
11
- "id": "1776937917012",
12
- "name": "同步协议",
13
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-sync.bat",
14
- "args": "",
15
- "addedBy": "qqww123",
16
- "addedAt": "2026-04-23T09:51:57.012Z"
17
- },
18
- {
19
- "id": "1777254823830",
20
- "name": "启动客服端",
21
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-client.bat",
22
- "args": "",
23
- "addedBy": "yrc001",
24
- "addedAt": "2026-04-27T01:53:43.830Z"
7
+ "addedBy": "admin",
8
+ "addedAt": "2026-06-23T03:50:51.373Z"
25
9
  },
26
10
  {
27
- "id": "1777254878031",
28
- "name": "自动生成代码",
29
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-autoCode.bat",
11
+ "id": "1782186676214",
12
+ "name": "一键协议",
13
+ "path": "G:/MengYueChuanQi996/Project/996M2_Client/a_tools/a_node/run-sync.bat",
30
14
  "args": "",
31
- "addedBy": "yrc001",
32
- "addedAt": "2026-04-27T01:54:38.031Z"
15
+ "addedBy": "admin",
16
+ "addedAt": "2026-06-23T03:51:16.214Z"
33
17
  },
34
18
  {
35
- "id": "1781243927262",
36
- "name": "9963工程(📁 G:/NiePanChuanQi/Project)SVN更新",
37
- "path": "H:/NiePanChuanQi/Project/996M2_Client/a_tools/a_node/run-svn.bat",
19
+ "id": "1782186725524",
20
+ "name": "9964工程(📁 G:/MengYueChuanQi996/Project)SVN更新",
21
+ "path": "G:/MengYueChuanQi996/Project/996M2_Client/a_tools/a_node/run-svn.bat",
38
22
  "args": "",
39
23
  "addedBy": "admin",
40
- "addedAt": "2026-06-12T05:58:47.262Z"
24
+ "addedAt": "2026-06-23T03:52:05.524Z"
41
25
  }
42
26
  ]
@@ -7,7 +7,7 @@ const crypto = require('crypto');
7
7
  const http = require('http');
8
8
  const os = require('os');
9
9
 
10
- const PORT = 8080;
10
+ const PORT = 9964;
11
11
  const USER_FILE = path.join(__dirname, 'users.json');
12
12
 
13
13
  const onlineUsers = new Map();
package/cli.js CHANGED
@@ -24,30 +24,35 @@ if (!commands[action]) {
24
24
  process.exit(0);
25
25
  }
26
26
 
27
- const cmd = commands[action];
28
-
29
- // 特殊处理:启动客户端需要找到项目根目录的 exe
30
- if (action === '1') {
31
- console.log(`🚀 执行: ${cmd.desc}`);
32
- // 从当前工作目录向上查找 996M2_Client.exe
27
+ // 从当前工作目录向上查找项目根目录
28
+ function findProjectRoot() {
33
29
  let cwd = process.cwd();
34
- let exePath = null;
35
- for (let i = 0; i < 5; i++) {
36
- const testPath = path.join(cwd, '996M2_Client.exe');
37
- if (fs.existsSync(testPath)) {
38
- exePath = testPath;
39
- break;
30
+ const markers = ['996M2_Client.exe', 'env.json', 'game.dat'];
31
+ for (let i = 0; i < 6; i++) {
32
+ for (const marker of markers) {
33
+ if (fs.existsSync(path.join(cwd, marker))) {
34
+ return cwd;
35
+ }
40
36
  }
41
37
  const parent = path.dirname(cwd);
42
- if (parent === cwd) break; // 到达根目录
38
+ if (parent === cwd) break;
43
39
  cwd = parent;
44
40
  }
45
- if (!exePath) {
46
- console.error('错误: 找不到 996M2_Client.exe');
47
- console.error('请在 996M2_Client 项目目录下运行 a_6 1');
48
- console.error('或者 cd 到包含 996M2_Client.exe 的目录');
41
+ return null;
42
+ }
43
+
44
+ const projectRoot = findProjectRoot();
45
+ const cmd = commands[action];
46
+
47
+ if (action === '1') {
48
+ // 特殊处理:启动客户端
49
+ if (!projectRoot) {
50
+ console.error('错误: 找不到 996M2_Client 项目目录');
51
+ console.error('请在项目目录下运行 a_6 1');
49
52
  process.exit(1);
50
53
  }
54
+ const exePath = path.join(projectRoot, '996M2_Client.exe');
55
+ console.log(`🚀 执行: ${cmd.desc}`);
51
56
  console.log(`启动 996M2 客户端...`);
52
57
  console.log(`路径: ${exePath}`);
53
58
  exec(`start "" "${exePath}"`, (err) => {
@@ -57,10 +62,14 @@ if (action === '1') {
57
62
  }
58
63
  console.log('客户端已启动');
59
64
  });
60
- // 给异步回调一点时间
61
65
  setTimeout(() => process.exit(0), 2000);
62
66
  } else {
67
+ // 设置环境变量,让子脚本也能找到项目根目录
68
+ const env = { ...process.env };
69
+ if (projectRoot) {
70
+ env.M2_PROJECT_ROOT = projectRoot;
71
+ }
63
72
  const batFile = path.join(__dirname, cmd.file);
64
73
  console.log(`🚀 执行: ${cmd.desc}`);
65
- execSync(`"${batFile}"`, { stdio: 'inherit', shell: true });
74
+ execSync(`"${batFile}"`, { stdio: 'inherit', shell: true, env });
66
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yangrunchi/a_6",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "996M2 客户端 Node.js 工具集 — 协议同步、自动生成代码、CSV配置、SVN管理、BAT脚本管理器",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -1,4 +0,0 @@
1
- @echo off
2
- cd /d "%~dp0"
3
- node server.js
4
- pause