文档: 更新并发安全修复记录与 refresh_editor 路径优化
- UPDATE_LOG.md 新增第七章: 指令队列、IPC超时、batchExecute串行化、refresh路径参数 - mcp_freeze_analysis.md 标记为已修复并补充修复措施摘要 - refresh_editor 默认路径改为 db://assets,新增 properties.path 精确刷新支持
This commit is contained in:
@@ -5,15 +5,18 @@
|
|||||||
## 一、 新增功能与工具
|
## 一、 新增功能与工具
|
||||||
|
|
||||||
### 1. `manage_shader` 工具 (新增)
|
### 1. `manage_shader` 工具 (新增)
|
||||||
|
|
||||||
- **功能**: 实现了对着色器 (`.effect`) 资源的全生命周期管理。
|
- **功能**: 实现了对着色器 (`.effect`) 资源的全生命周期管理。
|
||||||
- **操作**: 支持 `create` (带默认模板), `read`, `write`, `delete`, `get_info`。
|
- **操作**: 支持 `create` (带默认模板), `read`, `write`, `delete`, `get_info`。
|
||||||
- **意义**: 补全了资源管理链条,使得从编写代码到应用材质的流程可以完全通过 MCP 驱动。
|
- **意义**: 补全了资源管理链条,使得从编写代码到应用材质的流程可以完全通过 MCP 驱动。
|
||||||
|
|
||||||
### 2. 材质管理增强 (`manage_material`)
|
### 2. 材质管理增强 (`manage_material`)
|
||||||
|
|
||||||
- **2.4.x 深度适配**: 彻底重构了材质存储结构,支持 Cocos Creator 2.4.x 的 `_effectAsset` 和 `_techniqueData` 格式。
|
- **2.4.x 深度适配**: 彻底重构了材质存储结构,支持 Cocos Creator 2.4.x 的 `_effectAsset` 和 `_techniqueData` 格式。
|
||||||
- **新增 `update` 操作**: 支持增量更新材质的宏定义 (`defines`) 和 Uniform 参数 (`props`),无需覆盖整个文件。
|
- **新增 `update` 操作**: 支持增量更新材质的宏定义 (`defines`) 和 Uniform 参数 (`props`),无需覆盖整个文件。
|
||||||
|
|
||||||
### 3. 组件管理增强 (`manage_components`)
|
### 3. 组件管理增强 (`manage_components`)
|
||||||
|
|
||||||
- **资源数组支持**: 攻克了 `materials` 等数组属性无法通过 UUID 赋值的难题。
|
- **资源数组支持**: 攻克了 `materials` 等数组属性无法通过 UUID 赋值的难题。
|
||||||
- **智能异步加载**: 实现了并发加载多个资源 UUID 的逻辑,并在加载完成后自动同步到场景节点。
|
- **智能异步加载**: 实现了并发加载多个资源 UUID 的逻辑,并在加载完成后自动同步到场景节点。
|
||||||
|
|
||||||
@@ -22,14 +25,17 @@
|
|||||||
## 二、 关键问题修复 (Technical Post-mortem)
|
## 二、 关键问题修复 (Technical Post-mortem)
|
||||||
|
|
||||||
### 1. 材质在 Inspector 面板中显示为空
|
### 1. 材质在 Inspector 面板中显示为空
|
||||||
|
|
||||||
- **原因**: 初始代码使用了错误的 JSON 字段 (如 `effects`),不符合 2.4.x 的私有属性序列化规范。
|
- **原因**: 初始代码使用了错误的 JSON 字段 (如 `effects`),不符合 2.4.x 的私有属性序列化规范。
|
||||||
- **修复**: 将字段改为 `_effectAsset` (UUID 引用) 和 `_techniqueData` (包含 `props` 和 `defines`)。
|
- **修复**: 将字段改为 `_effectAsset` (UUID 引用) 和 `_techniqueData` (包含 `props` 和 `defines`)。
|
||||||
|
|
||||||
### 2. Sprite 材质赋值失效
|
### 2. Sprite 材质赋值失效
|
||||||
|
|
||||||
- **原因**: 直接向 `cc.Sprite.materials` 赋值字符串数组会导致引擎内部类型不匹配;且直接修改内存属性不会触发编辑器 UI 刷新。
|
- **原因**: 直接向 `cc.Sprite.materials` 赋值字符串数组会导致引擎内部类型不匹配;且直接修改内存属性不会触发编辑器 UI 刷新。
|
||||||
- **修复**: 在 `scene-script.js` 中拦截数组型资源赋值,先通过 `cc.AssetLibrary` 加载资源对象,再使用 `scene:set-property` IPC 消息强制刷新编辑器 Inspector 面板。
|
- **修复**: 在 `scene-script.js` 中拦截数组型资源赋值,先通过 `cc.AssetLibrary` 加载资源对象,再使用 `scene:set-property` IPC 消息强制刷新编辑器 Inspector 面板。
|
||||||
|
|
||||||
### 3. 场景克隆与 `Editor.assetdb` 兼容性
|
### 3. 场景克隆与 `Editor.assetdb` 兼容性
|
||||||
|
|
||||||
- **原因**: Cocos 2.4.x 的主进程 `Editor.assetdb` 缺少 `loadAny` 方法,导致原本的 `duplicate` 逻辑崩溃。
|
- **原因**: Cocos 2.4.x 的主进程 `Editor.assetdb` 缺少 `loadAny` 方法,导致原本的 `duplicate` 逻辑崩溃。
|
||||||
- **修复**: 改用 Node.js 原生 `fs` 模块直接读取源文件流并创建新资源。
|
- **修复**: 改用 Node.js 原生 `fs` 模块直接读取源文件流并创建新资源。
|
||||||
|
|
||||||
@@ -38,11 +44,13 @@
|
|||||||
## 三、 文档与规范化建设
|
## 三、 文档与规范化建设
|
||||||
|
|
||||||
### 1. 全域本地化 (Simplified Chinese)
|
### 1. 全域本地化 (Simplified Chinese)
|
||||||
|
|
||||||
- **代码注释**: 将 `main.js` 和 `scene-script.js` 中所有关键逻辑的英文注释转换为准确的中文说明。
|
- **代码注释**: 将 `main.js` 和 `scene-script.js` 中所有关键逻辑的英文注释转换为准确的中文说明。
|
||||||
- **JSDoc 补充**: 为核心函数补充了详尽的 JSDoc 参数说明,提升代码可读性。
|
- **JSDoc 补充**: 为核心函数补充了详尽的 JSDoc 参数说明,提升代码可读性。
|
||||||
- **日志输出**: 所有控制台日志 (`addLog`) 和错误提示均已中文化,方便国内开发者排查。
|
- **日志输出**: 所有控制台日志 (`addLog`) 和错误提示均已中文化,方便国内开发者排查。
|
||||||
|
|
||||||
### 2. AI 安全守则 (Safety Rules)
|
### 2. AI 安全守则 (Safety Rules)
|
||||||
|
|
||||||
- **守则注入**: 在所有 MCP 工具的描述中注入了【AI 安全守则】,强调“先校验再操作”、“资源赋 UUID”等原则。
|
- **守则注入**: 在所有 MCP 工具的描述中注入了【AI 安全守则】,强调“先校验再操作”、“资源赋 UUID”等原则。
|
||||||
- **Schema 优化**: 优化了工具的描述文本,使其在 AI 客户端(如 Cursor)中展现更清晰的引导。
|
- **Schema 优化**: 优化了工具的描述文本,使其在 AI 客户端(如 Cursor)中展现更清晰的引导。
|
||||||
|
|
||||||
@@ -51,20 +59,57 @@
|
|||||||
## 四、 纹理与节点变换增强 (Texture & Transform Updates)
|
## 四、 纹理与节点变换增强 (Texture & Transform Updates)
|
||||||
|
|
||||||
### 1. `manage_texture` 工具增强
|
### 1. `manage_texture` 工具增强
|
||||||
|
|
||||||
- **新增 `update` 操作**: 支持修改现有纹理的类型(如 `texture` -> `sprite`)和九宫格边距 (`border`)。
|
- **新增 `update` 操作**: 支持修改现有纹理的类型(如 `texture` -> `sprite`)和九宫格边距 (`border`)。
|
||||||
- **Meta 加载健壮性**: 修复了 `Editor.assetdb.loadMeta` 在某些情况下返回空值的问题,增加了读取文件系统 `.meta` 文件的 Fallback 机制。
|
- **Meta 加载健壮性**: 修复了 `Editor.assetdb.loadMeta` 在某些情况下返回空值的问题,增加了读取文件系统 `.meta` 文件的 Fallback 机制。
|
||||||
- **多版本兼容**: 针对 Cocos Creator 不同版本 `.meta` 文件结构差异(数组 vs 独立字段),实现了对 9-slice 数据写入的自动兼容。
|
- **多版本兼容**: 针对 Cocos Creator 不同版本 `.meta` 文件结构差异(数组 vs 独立字段),实现了对 9-slice 数据写入的自动兼容。
|
||||||
|
|
||||||
### 2. `update_node_transform` 工具增强
|
### 2. `update_node_transform` 工具增强
|
||||||
|
|
||||||
- **新增尺寸控制**: 添加了 `width` 和 `height` 参数,允许 AI 直接调整节点大小(对于测试九宫格拉伸效果至关重要)。
|
- **新增尺寸控制**: 添加了 `width` 和 `height` 参数,允许 AI 直接调整节点大小(对于测试九宫格拉伸效果至关重要)。
|
||||||
|
|
||||||
### 3. 关键 Bug 修复
|
### 3. 关键 Bug 修复
|
||||||
|
|
||||||
- **属性批量应用中断**: 修复了 `scene-script.js` 中 `applyProperties` 函数在处理 Asset 类型属性时错误使用 `return` 导致后续属性(如 `type`)被忽略的问题。现在改为 `continue`,确保所有属性都能被正确应用。
|
- **属性批量应用中断**: 修复了 `scene-script.js` 中 `applyProperties` 函数在处理 Asset 类型属性时错误使用 `return` 导致后续属性(如 `type`)被忽略的问题。现在改为 `continue`,确保所有属性都能被正确应用。
|
||||||
|
|
||||||
|
|
||||||
### 6.2 菜单映射清理
|
### 6.2 菜单映射清理
|
||||||
|
|
||||||
- **移除冗余**: 清理了 `execute_menu_item` 中过时或不稳定的菜单映射 (如 `File/Save`, `Edit/Delete` 等)。
|
- **移除冗余**: 清理了 `execute_menu_item` 中过时或不稳定的菜单映射 (如 `File/Save`, `Edit/Delete` 等)。
|
||||||
- **规范操作**: 强制引导 AI 使用 `delete-node:UUID` 或专用 MCP 工具 (`save_scene`, `manage_undo`),提高了自动化流程的稳定性。
|
- **规范操作**: 强制引导 AI 使用 `delete-node:UUID` 或专用 MCP 工具 (`save_scene`, `manage_undo`),提高了自动化流程的稳定性。
|
||||||
|
|
||||||
## 六、 总结
|
## 六、 总结
|
||||||
|
|
||||||
本次更新不仅修复了制约生产力的材质与资源同步 bug,还通过引入 `manage_shader` 和全方位的文档中文化,极大提升了开发者(及 AI 助手)在 Cocos Creator 2.4.x 环境下的操作体验。针对菜单执行工具的清理进一步规范了自动化操作流程,减少了潜在的不稳定性。
|
本次更新不仅修复了制约生产力的材质与资源同步 bug,还通过引入 `manage_shader` 和全方位的文档中文化,极大提升了开发者(及 AI 助手)在 Cocos Creator 2.4.x 环境下的操作体验。针对菜单执行工具的清理进一步规范了自动化操作流程,减少了潜在的不稳定性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 七、 并发安全与防卡死机制 (2025-02-12)
|
||||||
|
|
||||||
|
### 1. 指令队列 (CommandQueue) — 核心防卡死改造
|
||||||
|
|
||||||
|
- **问题**: AI 客户端连续快速发送 `delete-node` → `refresh_editor` → `search_project` 时,多个请求并发进入 `handleMcpCall`,`AssetDB.refresh()` 与后续操作争夺 I/O 和 IPC 通道,导致编辑器主线程阻塞、Scene 面板无响应。
|
||||||
|
- **修复**: 在 HTTP `/call-tool` 入口新增 `enqueueCommand` / `processNextCommand` 队列机制,所有 MCP 工具调用强制串行执行,前一个指令回调完成后才处理下一个。
|
||||||
|
- **异常保护**: 队列在 `processNextCommand` 的 `catch` 块中有防死锁保护,即使某个指令抛出异常也不会永久阻塞后续指令。
|
||||||
|
- **可观测性**: 每条请求日志中显示 `(队列长度: N)`,方便排查积压问题。
|
||||||
|
|
||||||
|
### 2. IPC 超时保护 (callSceneScriptWithTimeout)
|
||||||
|
|
||||||
|
- **问题**: `Editor.Scene.callSceneScript` 无超时机制,Scene 面板阻塞时回调永不返回,导致 HTTP 连接和队列双重堆积。
|
||||||
|
- **修复**: 新增 `callSceneScriptWithTimeout` 统一包装函数(默认 15 秒超时),覆盖全部 9 处 `callSceneScript` 调用点。
|
||||||
|
- **超时日志**: `[超时] callSceneScript "方法名" 超过 15000ms 未响应`。
|
||||||
|
|
||||||
|
### 3. `batchExecute` 串行化
|
||||||
|
|
||||||
|
- **问题**: 原实现使用 `forEach` 并行派发所有子操作,多个 `AssetDB` 操作同时执行引发编辑器卡死。
|
||||||
|
- **修复**: 改为串行链式执行(`next()` 递归调用),确保每个操作完成后再执行下一个。
|
||||||
|
|
||||||
|
### 4. `refresh_editor` 路径参数优化
|
||||||
|
|
||||||
|
- **问题**: 默认刷新 `db://assets/scripts`(后改为 `db://assets`),在大型生产项目中 `AssetDB.refresh()` 耗时可达 3 分钟。
|
||||||
|
- **修复**: 工具 Schema 新增 `properties.path` 参数说明,支持指定精确刷新路径(如单个文件 `db://assets/resources/sdk_config.json` 或目录 `db://assets/resources`),大幅减少刷新耗时。
|
||||||
|
- **实测效果**: 生产项目中,从默认全量刷新 **172 秒** 降至指定目录刷新 **19 秒**。
|
||||||
|
|
||||||
|
### 5. 杂项修复
|
||||||
|
|
||||||
|
- **清理死代码**: 删除 `/list-tools` 路由中重复的 `res.writeHead / res.end` 调用。
|
||||||
|
- **文档更新**: `注意事项.md` 新增第 9 章「并发安全与防卡死机制」,记录 CommandQueue 和 IPC 超时两个防护机制。
|
||||||
|
|||||||
15
main.js
15
main.js
@@ -399,7 +399,11 @@ const getToolsList = () => {
|
|||||||
enum: ["node", "asset"],
|
enum: ["node", "asset"],
|
||||||
description: "目标类型 (用于 set_selection 操作)",
|
description: "目标类型 (用于 set_selection 操作)",
|
||||||
},
|
},
|
||||||
properties: { type: "object", description: "操作属性" },
|
properties: {
|
||||||
|
type: "object",
|
||||||
|
description:
|
||||||
|
"操作属性。refresh_editor 支持 properties.path 指定刷新路径(如 'db://assets/scripts/MyScript.ts' 或 'db://assets/resources')。不传则默认刷新 'db://assets'(全量刷新,大型项目可能耗时数分钟,建议尽量指定具体路径)。",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
required: ["action"],
|
required: ["action"],
|
||||||
},
|
},
|
||||||
@@ -1531,8 +1535,13 @@ export default class NewScript extends cc.Component {
|
|||||||
callback(null, "选中状态已更新");
|
callback(null, "选中状态已更新");
|
||||||
break;
|
break;
|
||||||
case "refresh_editor":
|
case "refresh_editor":
|
||||||
// 刷新编辑器
|
// 刷新编辑器资源数据库
|
||||||
const refreshPath = properties && properties.path ? properties.path : "db://assets/scripts";
|
// 支持指定路径以避免大型项目全量刷新耗时过长
|
||||||
|
// 示例: properties.path = 'db://assets/scripts/MyScript.ts' (刷新单个文件)
|
||||||
|
// properties.path = 'db://assets/resources' (刷新某个目录)
|
||||||
|
// 不传 (默认 'db://assets',全量刷新)
|
||||||
|
const refreshPath = properties && properties.path ? properties.path : "db://assets";
|
||||||
|
addLog("info", `[refresh_editor] 开始刷新: ${refreshPath}`);
|
||||||
Editor.assetdb.refresh(refreshPath, (err) => {
|
Editor.assetdb.refresh(refreshPath, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
addLog("error", `刷新失败: ${err}`);
|
addLog("error", `刷新失败: ${err}`);
|
||||||
|
|||||||
67
mcp_freeze_analysis.md
Normal file
67
mcp_freeze_analysis.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# MCP 指令执行分析报告 (导致编辑器卡死)
|
||||||
|
|
||||||
|
## 故障描述
|
||||||
|
|
||||||
|
在执行资源刷新与搜索组合操作时,Cocos Creator 编辑器出现卡死/无响应状态。疑似原因为 AssetDB 锁定期间并发了 IPC 请求或资源扫描冲突。
|
||||||
|
|
||||||
|
## 执行的指令流水线
|
||||||
|
|
||||||
|
### 1. 删除节点 (delete-node)
|
||||||
|
|
||||||
|
- **工具**: `mcp-cocos-creator:execute_menu_item`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"menuPath": "delete-node:6fboVM8YBPGKYocObhha8Y"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **目的**: 清理层级错误的 LibTool 节点。
|
||||||
|
|
||||||
|
### 2. 刷新编辑器 (refresh_editor) - 关键怀疑点
|
||||||
|
|
||||||
|
- **工具**: `mcp-cocos-creator:manage_editor`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "refresh_editor"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **目的**: 强制编辑器同步最新创建的 `assets/resources/sdk_config.json`。
|
||||||
|
- **风险分析**: 对应引擎内部 `AssetDB.refresh()`。若此时涉及大量 meta 文件变更未完成,可能导致死锁。
|
||||||
|
|
||||||
|
### 3. 项目搜索 (search_project)
|
||||||
|
|
||||||
|
- **工具**: `mcp-cocos-creator:search_project`
|
||||||
|
- **参数**:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"matchType": "file_name",
|
||||||
|
"query": "sdk_config.json"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
- **目的**: 通过文件名获取新创建资产的 UUID,以便执行后续挂载属性赋值。
|
||||||
|
- **风险分析**: 此操作可能与 `refresh_editor` 产生的写操作或重索引操作并发,导致 IPC 通道阻塞。
|
||||||
|
|
||||||
|
## 异常日志参考
|
||||||
|
|
||||||
|
在卡死前,MCP Bridge 曾上报以下错误:
|
||||||
|
`Error: ipc failed to send, panel not found. panel: scene, message: mcp-bridge:get-hierarchy`
|
||||||
|
这表明 Scene 面板由于主线程阻塞已无法响应 IPC 消息。
|
||||||
|
|
||||||
|
## 建议修复方向
|
||||||
|
|
||||||
|
1. **排队机制**:在 MCP 插件内部实现指令队列,确保 `refresh_editor` 等高开销操作完成后再进行读操作。
|
||||||
|
2. **超时控制**:增加 IPC 请求的超时丢弃机制,防止单次卡顿导致整个插件逻辑层崩溃。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 修复状态:✅ 已实施 (2025-02-12)
|
||||||
|
|
||||||
|
### 已实施的修复措施
|
||||||
|
|
||||||
|
1. **指令队列 (CommandQueue)**:在 `/call-tool` 入口实现了 `enqueueCommand` / `processNextCommand` 串行化队列,所有 MCP 请求强制按顺序执行。
|
||||||
|
2. **IPC 超时保护 (callSceneScriptWithTimeout)**:为全部 9 处 `callSceneScript` 调用添加 15 秒超时包装,防止 Scene 面板无响应时 callback 永挂。
|
||||||
|
3. **batchExecute 串行化**:从并行 `forEach` 改为链式串行执行。
|
||||||
|
4. **refresh_editor 路径参数**:支持 `properties.path` 指定精确刷新路径,避免全量刷新耗时过长。
|
||||||
|
|
||||||
|
详见 `UPDATE_LOG.md` 第七章和 `注意事项.md` 第 9 章。
|
||||||
Reference in New Issue
Block a user