chore: track Cocos Creator project for future migration

This commit is contained in:
cabinw
2026-09-08 21:54:30 +08:00
parent feb2ec5de1
commit 9f8990b579
23 changed files with 37475 additions and 5 deletions
+1 -4
View File
@@ -1,7 +1,4 @@
dist/
/dist/
node_modules/
.DS_Store
*.log
# Separate Cocos Creator repository; manage its history inside that project.
/wechat/HexTrail/
+2 -1
View File
@@ -72,6 +72,7 @@ npm run dev
| `assets/` | PNG 图集、历史素材与生成提示词 |
| `tests/`、`scripts/` | 自动测试、开发服务和生成脚本 |
| `cocos/` | Cocos Creator 棋盘及 UI 适配示例 |
| `wechat/HexTrail/` | Cocos Creator 3.8.8 工程,后续游戏移植的目标工程 |
| `docs/` | 玩法分析、关卡设计和移植说明 |
规则与数学模块不依赖 DOM、存储 API 或浏览器物理引擎。新增玩法应留在模型层,浏览器输入与存储逻辑留在适配层。
@@ -82,7 +83,7 @@ npm run dev
[Design.md](Design.md) 记录设计规范;[Design.html](Design.html) 内嵌图片与样式,可单文件离线分享。生成过程与提示词见 [素材说明](assets/GENERATION.md)。
Cocos 示例复用规则、碰撞、渲染命令和图集;HTML 控件、文件导入导出与存储需替换成宿主接口。接入步骤见 [Cocos 移植指南](docs/cocos-port.md)。`wechat/HexTrail/` 属于独立 Cocos 工程仓库,已从本仓库忽略。
Cocos 示例复用规则、碰撞、渲染命令和图集;HTML 控件、文件导入导出与存储需替换成宿主接口。接入步骤见 [Cocos 移植指南](docs/cocos-port.md)。`wechat/HexTrail/` 是本仓库管理的 Cocos Creator 3.8.8 工程,后续将把当前游戏移植到该工程中。使用 Creator 打开该目录;工程自身的 `.gitignore` 排除缓存、本地配置和构建产物,源码与项目配置随主仓库提交。
## 验证与已知限制
@@ -0,0 +1,5 @@
{
"image": {
"type": "sprite-frame"
}
}
+24
View File
@@ -0,0 +1,24 @@
#///////////////////////////
# Cocos Creator 3D Project
#///////////////////////////
library/
temp/
local/
build/
profiles/
native
#//////////////////////////
# NPM
#//////////////////////////
node_modules/
#//////////////////////////
# VSCode
#//////////////////////////
.vscode/
#//////////////////////////
# WebStorm
#//////////////////////////
.idea/
View File
@@ -0,0 +1,63 @@
# Cocos MCP Pro Quick Start
Version: 0.2.0
## 中文:第一次连接
### 1. 安装并打开面板
1. 保留Cocos Store下载的ZIP,不要重新打包或增加外层目录。
2. 在Creator中打开`扩展 -> 扩展管理器`,切到“项目”或“全局”扩展页并点击“导入”。
3. 直接选择正式ZIP;ZIP根目录已经包含`package.json`,无需先解压。
4. 确认扩展版本为`0.2.0`且已启用,等待Creator完成首次资源导入。
5. 从`扩展 -> Cocos MCP -> Open MCP Panel`打开控制台。
正式包已经包含`dist`和运行依赖。购买用户不需要执行`npm install`。
### 2. 一键检测并配置客户端
1. 确认面板显示MCP服务“运行中”。
2. 点击“一键检测”。Node、Bridge、WebSocket和Creator Scene均通过后再继续。
3. 只配置你实际使用的客户端。v0.2.0支持Cursor、Windsurf、Trae CN、Trae国际版、Zoo Code、Cline、Roo Code和Codex。
4. 完全退出并重新打开AI客户端,使它重新加载MCP配置。
5. 调用`cocos_ping`和`cocos_get_capabilities`。两项返回真实结果才算连接成功。
v0.2.0不再让客户端执行临时`.cmd`或`.sh`启动器。配置会直接记录Node和`bridge-cli.js`的绝对路径,并通过`--project`传入当前工程。写配置前会备份原文件,写完后再次校验;重新点“一键配置”也会迁移旧版启动器配置。
### 3. 完成第一个闭环任务
打开测试场景后,可以直接让AI执行:
```text
先读取场景,在Canvas下创建一个红色圆形和一个蓝色方形,横向排列。
完成后验证运行态结果并保存场景;如果失败,回滚全部改动,不要让我手动挂脚本。
```
这个任务应由`cocos_apply_ui_spec`或对应任务级工具一次完成。成功回执包含`status`、`changed`、`verified`、`undoAvailable`、`diagnostics`和`nextAction`。调用一次`cocos_mcp_undo_last`应撤销整个任务。
仍建议保持这个节奏:
```text
Inspect -> Mutate -> Verify -> Undo or Continue
```
### 4. 调试网页预览或构建错误
- 网页预览:使用`cocos_preview_debug_start`启动插件托管的Chrome/Edge会话,再用`read`读取JavaScript异常、Promise异常和失败网络请求,必要时用`capture`截图,最后`stop`。
- Creator构建:使用`cocos_get_build_diagnostics`整理现有构建日志。它只提供证据,不代表Android或iOS构建一定不受影响。
### 需要帮助
先查看同目录的[TROUBLESHOOTING.md](./TROUBLESHOOTING.md)。反馈问题时请附:Creator版本、插件版本、系统、AI客户端、一键检测结果和完整错误信息。请勿发送API Key或未脱敏项目资产。
联系邮箱:jimmymjing@gmail.com
## English: First connection
1. In Extension Manager, choose Project or Global, import the Store ZIP directly, enable v0.2.0, and open `Extensions -> Cocos MCP -> Open MCP Panel`. The ZIP already has `package.json` at its root and does not need to be extracted first.
2. Run the panel self-test. Node, Bridge, WebSocket, and Creator Scene must pass.
3. Auto-configure only the client you use, fully restart it, then call `cocos_ping` and `cocos_get_capabilities`.
4. v0.2.0 launches the absolute Node executable with `bridge-cli.js --project <project>`. It backs up, validates, and atomically replaces client config files; rerunning Auto Config migrates old launcher entries.
5. Try a transactional task such as a red circle and blue square. It must create, verify, save, and undo without requiring a generated script or manual component attachment.
The Store package bundles its runtime dependencies. Store customers do not need to run `npm install`.
@@ -0,0 +1,64 @@
# Cocos MCP Pro Troubleshooting
Version: 0.2.0
## 先运行“一键检测”
面板会分别检查Node、Bridge、WebSocket、Creator Scene和客户端配置。先处理第一个失败项,不要连续重装或盲目重试写操作。
## 面板打不开或提示`methods`不存在
确认正式ZIP的根目录直接包含`package.json`、`dist/main.js`、`dist/scene.js`和`dist/panels/default/index.js`,没有多嵌一层扩展目录。移除不完整或旧版扩展后重新导入正式ZIP,并重启Creator。不要把未构建源码目录当作商店扩展安装。
Creator 3.8.8在Windows上若提示`unzip: No zipfiles found`后又报`ENOENT scandir`,先把ZIP复制到只含英文和数字的本地路径(例如`C:\CocosMCP\cocos-mcp.zip`)再导入。这个报错可能来自Creator内置解压器无法读取ZIP来源路径中的中文;项目目录本身仍可保留中文、空格和`&`。
## 客户端提示`Connection closed`
1. 保持Creator和当前工程打开,确认面板服务正在运行。
2. 在面板里重新配置对应客户端。v0.2.0会迁移旧的`.cocos-mcp-launcher.cmd`或`.sh`配置。
3. 完全退出并重启AI客户端,然后调用`cocos_ping`。
4. 若仍失败,运行“一键检测”并查看客户端MCP日志。
正确配置应直接执行Node,参数依次包含`bridge-cli.js`、`--project`和工程目录。不要手抄他人的绝对路径。
## 提示`bridge cli missing`或路径乱码
这通常是旧版启动器或扩展目录不完整。卸载旧扩展,重新导入完整v0.2.0目录,再执行一键配置。路径中包含中文、空格或`&`时,不需要额外加转义字符;让面板生成配置即可。
## 提示`node not found`
安装Node.js 18至24,再回到面板重新运行一键配置。v0.2.0会把实际Node可执行文件的绝对路径写入客户端配置,不依赖GUI应用的`PATH`。
## 配置文件原有内容丢失了吗
不会直接覆盖。插件会解析现有JSON/TOML,更新`cocos-creator`条目,写入临时文件并校验后原子替换。原文件存在时会保留同目录`.cocos-mcp.bak`备份;格式损坏时会停止并明确报错。
## MCP连上了,但简单UI任务仍要求手动挂脚本
先调用`cocos_get_capabilities`,确认版本为0.2.0。圆形、矩形、文本、图片和按钮应使用`cocos_create_ui_*`或`cocos_apply_ui_spec`,不应临时生成组件脚本让用户手动挂载。若客户端仍这样规划,把这句话补给它:
```text
使用Cocos MCP Pro任务级UI工具直接完成;失败时返回诊断并回滚,不生成临时脚本,不要求我手动操作Creator。
```
## UI任务失败后留下半成品
停止继续写入,立即保存`diagnostics`并提交问题。`cocos_apply_ui_spec`设计为事务操作,任一步失败都应自动移除本次创建的节点。不要在残留状态上继续让AI“补救”。
## 图片或字体资源写入失败
`set_component_property`可接受资源UUID,也可直接接受`assets/...`路径。路径必须存在且资源类型与目标属性匹配;插件会在写入前解析并校验,不匹配时拒绝修改。
## 网页报错怎么读
使用`cocos_preview_debug_start`打开托管Chrome/Edge预览,不要把普通浏览器页面来回复制给AI。复现后调用`cocos_preview_debug_read`;可读取JavaScript异常、未处理Promise、控制台错误和失败网络请求。结束时调用`cocos_preview_debug_stop`。
## Android或iOS构建是否一定不受影响
不能只凭编辑器或网页错误下结论。`cocos_get_build_diagnostics`只整理Creator已有构建日志;仍需实际完成目标平台构建和设备测试。
## 反馈问题
邮箱:jimmymjing@gmail.com
请附Creator版本、插件版本、系统、AI客户端、一键检测结果、复现步骤和脱敏诊断。不要发送项目密钥、API Key或完整商业项目。
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,390 @@
"use strict";
// packages/cocos-ext/src/panels/default/index.ts
var LOCALE_STORAGE_KEY = "cocos-mcp-panel-locale";
var STR = {
zh: {
panelTitle: "Cocos MCP \u63A7\u5236\u53F0",
langLabel: "\u754C\u9762\u8BED\u8A00",
server: "\u670D\u52A1",
running: "\u8FD0\u884C\u4E2D",
stopped: "\u5DF2\u505C\u6B62",
port: "\u7AEF\u53E3",
connections: "\u8FDE\u63A5\u6570",
url: "\u9762\u677F URL\uFF08\u4EC5\u4F9B\u53C2\u8003\uFF09",
startServer: "\u542F\u52A8\u670D\u52A1",
stopServer: "\u505C\u6B62\u670D\u52A1",
refresh: "\u5237\u65B0",
runSelfTest: "\u4E00\u952E\u68C0\u6D4B",
selfTestTitle: "\u8FDE\u63A5\u8BCA\u65AD",
selfTestNever: "\u5C1A\u672A\u8FD0\u884C\u68C0\u6D4B",
quickStartTitle: "\u9996\u6B21\u4F7F\u7528",
quickStartStepServer: "\u542F\u52A8MCP\u670D\u52A1",
quickStartStepConfig: "\u914D\u7F6E\u81F3\u5C11\u4E00\u4E2AMCP\u5BA2\u6237\u7AEF",
quickStartStepConnect: "\u91CD\u542F\u5BA2\u6237\u7AEF\u5E76\u5EFA\u7ACB\u8FDE\u63A5",
quickStartDone: "\u5B8C\u6210",
quickStartPending: "\u5F85\u5B8C\u6210",
openGuide: "\u6253\u5F00Quick Start",
firstPromptLabel: "\u8FDE\u63A5\u6210\u529F\u540E\uFF0C\u5148\u8BA9AI\u8BFB\u53D6\u573A\u666F\uFF0C\u518D\u505A\u4E00\u4E2A\u5C0F\u6539\u52A8\u3002",
autoConfigTitle: "\u4E00\u952E\u914D\u7F6E MCP \u5BA2\u6237\u7AEF",
serverNamePh: "MCP \u670D\u52A1\u540D\uFF08\u5199\u5165\u5404\u5BA2\u6237\u7AEF\u914D\u7F6E\uFF09",
autoConfigAll: "\u4E00\u952E\u914D\u7F6E\u5168\u90E8\u5BA2\u6237\u7AEF",
configured: "\u5DF2\u914D\u7F6E",
notConfigured: "\u672A\u914D\u7F6E",
autoConfig: "\u4E00\u952E\u914D\u7F6E",
openConfig: "\u6253\u5F00\u914D\u7F6E",
cliTitle: "\u547D\u4EE4\u884C\u53C2\u8003\uFF08Codex / Gemini CLI\uFF09",
operationLogs: "\u64CD\u4F5C\u65E5\u5FD7",
clear: "\u6E05\u7A7A",
logLevelInfo: "\u4FE1\u606F",
logLevelWarn: "\u8B66\u544A",
logLevelError: "\u9519\u8BEF"
},
en: {
panelTitle: "Cocos MCP Console",
langLabel: "Language",
server: "Server",
running: "Running",
stopped: "Stopped",
port: "port",
connections: "Connections",
url: "Panel URL (reference)",
startServer: "Start Server",
stopServer: "Stop Server",
refresh: "Refresh",
runSelfTest: "Run Self-Test",
selfTestTitle: "Connection Diagnostics",
selfTestNever: "Self-test has not run yet",
quickStartTitle: "First Run",
quickStartStepServer: "Start the MCP service",
quickStartStepConfig: "Configure at least one MCP client",
quickStartStepConnect: "Restart the client and connect",
quickStartDone: "done",
quickStartPending: "pending",
openGuide: "Open Quick Start",
firstPromptLabel: "After connecting, inspect the scene before one small mutation.",
autoConfigTitle: "Auto Config MCP Clients",
serverNamePh: "server name (written to each client config)",
autoConfigAll: "Auto Config All",
configured: "configured",
notConfigured: "not configured",
autoConfig: "Auto Config",
openConfig: "Open Config",
cliTitle: "CLI reference (Codex / Gemini CLI)",
operationLogs: "Operation Logs",
clear: "Clear",
logLevelInfo: "info",
logLevelWarn: "warn",
logLevelError: "error"
}
};
function readLocale() {
try {
const v = localStorage.getItem(LOCALE_STORAGE_KEY);
if (v === "en" || v === "zh") {
return v;
}
} catch {
}
return "zh";
}
function writeLocale(l) {
try {
localStorage.setItem(LOCALE_STORAGE_KEY, l);
} catch {
}
}
var locale = readLocale();
function t(key) {
return STR[locale][key] ?? STR.en[key] ?? key;
}
var TEMPLATE = `
<div class="wrap">
<div class="row lang-bar">
<span id="langLabel" class="lang-label"></span>
<select id="langSelect" class="lang-select">
<option value="zh">\u4E2D\u6587</option>
<option value="en">English</option>
</select>
</div>
<h2 id="panelTitle"></h2>
<div class="card guide-card">
<div class="row guide-heading">
<h3 id="quickStartTitle"></h3>
<ui-button id="openGuideBtn"></ui-button>
</div>
<div id="quickStartSteps" class="guide-steps"></div>
<div id="firstPromptLabel" class="guide-note"></div>
</div>
<div class="card">
<div id="serverLine">-</div>
<div id="connLine">-</div>
<div id="urlLine">-</div>
<div class="row">
<ui-button id="startBtn"></ui-button>
<ui-button id="stopBtn"></ui-button>
<ui-button id="refreshBtn"></ui-button>
<ui-button id="selfTestBtn"></ui-button>
</div>
<h3 id="selfTestTitle" class="self-test-title"></h3>
<div id="selfTestResults" class="self-test-results"></div>
</div>
<div class="card">
<h3 id="autoConfigTitle"></h3>
<div class="row">
<ui-input id="serverNameInput"></ui-input>
<ui-button id="addAllBtn"></ui-button>
</div>
<div id="clientList"></div>
</div>
<div class="card">
<h3 id="cliTitle"></h3>
<div class="mono" id="claudeCmd"></div>
<div class="mono" id="geminiCmd"></div>
</div>
<div class="card">
<div class="row">
<h3 id="logsTitle"></h3>
<ui-button id="clearLogsBtn"></ui-button>
</div>
<div id="logs" class="logs"></div>
</div>
</div>
`;
var STYLE = `
.wrap { padding: 12px; color: #d4d4d4; font-size: 13px; }
.lang-bar { margin-bottom: 10px; }
.lang-label { margin-right: 8px; color: #aaa; }
.lang-select { background: #2d2d2d; color: #d4d4d4; border: 1px solid #444; border-radius: 4px; padding: 4px 8px; font-size: 13px; }
h2 { margin: 0 0 10px 0; font-size: 18px; }
h3 { margin: 0 0 8px 0; font-size: 14px; }
.card { border: 1px solid #333; border-radius: 6px; padding: 10px; margin-bottom: 10px; background: #1e1e1e; }
.row { display: flex; gap: 8px; align-items: center; margin-top: 8px; margin-bottom: 6px; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; background: #111; padding: 8px; border-radius: 4px; margin-bottom: 6px; word-break: break-all; }
.logs { max-height: 220px; overflow: auto; background: #111; border-radius: 4px; padding: 8px; }
.log { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; margin-bottom: 4px; white-space: pre-wrap; word-break: break-word; }
.log.error { color: #ff8a8a; }
.log.warn { color: #f7d774; }
.log.info { color: #9bd4ff; }
.client-row { display: grid; grid-template-columns: 110px 1fr auto auto; gap: 8px; align-items: center; margin: 6px 0; }
.tag { padding: 2px 6px; border-radius: 4px; font-size: 12px; background: #333; }
.ok { background: #1f5f2f; }
.bad { background: #6a2a2a; }
.guide-card { border-color: #315b4f; }
.guide-heading { justify-content: space-between; margin-top: 0; }
.guide-heading h3 { margin: 0; }
.guide-steps { display: grid; gap: 6px; }
.guide-step { display: grid; grid-template-columns: 68px 1fr; gap: 8px; align-items: center; }
.guide-status { padding: 2px 6px; border-radius: 4px; font-size: 12px; text-align: center; background: #5c4622; }
.guide-status.done { background: #1f5f2f; }
.guide-note { margin-top: 8px; color: #a8c9bd; }
.self-test-title { margin-top: 12px; }
.self-test-results { display: grid; gap: 5px; }
.self-test-row { display: grid; grid-template-columns: 22px 92px 1fr; gap: 6px; align-items: start; }
.self-test-icon.ok-text { color: #63d28b; }
.self-test-icon.bad-text { color: #ff8a8a; }
.self-test-message { color: #aaa; word-break: break-word; }
`;
module.exports = Editor.Panel.define({
template: TEMPLATE,
style: STYLE,
$: {
langLabel: "#langLabel",
langSelect: "#langSelect",
panelTitle: "#panelTitle",
quickStartTitle: "#quickStartTitle",
quickStartSteps: "#quickStartSteps",
openGuideBtn: "#openGuideBtn",
firstPromptLabel: "#firstPromptLabel",
serverLine: "#serverLine",
connLine: "#connLine",
urlLine: "#urlLine",
startBtn: "#startBtn",
stopBtn: "#stopBtn",
refreshBtn: "#refreshBtn",
selfTestBtn: "#selfTestBtn",
selfTestTitle: "#selfTestTitle",
selfTestResults: "#selfTestResults",
autoConfigTitle: "#autoConfigTitle",
serverNameInput: "#serverNameInput",
addAllBtn: "#addAllBtn",
clientList: "#clientList",
cliTitle: "#cliTitle",
claudeCmd: "#claudeCmd",
geminiCmd: "#geminiCmd",
logs: "#logs",
logsTitle: "#logsTitle",
clearLogsBtn: "#clearLogsBtn"
},
ready() {
const pluginName = "cocos-mcp";
locale = readLocale();
const readServerName = () => {
const input = this.$.serverNameInput;
const v = (input?.value ?? "").trim();
return v || "cocos-creator";
};
const applyStaticLabels = () => {
this.$.langLabel.textContent = t("langLabel");
this.$.panelTitle.textContent = t("panelTitle");
this.$.quickStartTitle.textContent = t("quickStartTitle");
this.$.openGuideBtn.textContent = t("openGuide");
this.$.firstPromptLabel.textContent = t("firstPromptLabel");
this.$.autoConfigTitle.textContent = t("autoConfigTitle");
this.$.cliTitle.textContent = t("cliTitle");
this.$.logsTitle.textContent = t("operationLogs");
this.$.startBtn.textContent = t("startServer");
this.$.stopBtn.textContent = t("stopServer");
this.$.refreshBtn.textContent = t("refresh");
this.$.selfTestBtn.textContent = t("runSelfTest");
this.$.selfTestTitle.textContent = t("selfTestTitle");
this.$.addAllBtn.textContent = t("autoConfigAll");
this.$.clearLogsBtn.textContent = t("clear");
const input = this.$.serverNameInput;
if (input) {
input.placeholder = t("serverNamePh");
}
const sel = this.$.langSelect;
if (sel) {
sel.value = locale;
}
};
const logLevelLabel = (level) => {
if (level === "error") {
return t("logLevelError");
}
if (level === "warn") {
return t("logLevelWarn");
}
return t("logLevelInfo");
};
const render = (state) => {
const run = state.server.running ? t("running") : t("stopped");
this.$.serverLine.textContent = `${t("server")}: ${run} (${t("port")}: ${state.server.port ?? "-"})`;
this.$.connLine.textContent = `${t("connections")}: ${state.server.connections}`;
this.$.urlLine.textContent = `${t("url")}: ${state.server.url ?? "-"}`;
this.$.claudeCmd.textContent = state.cliCommands.claude;
this.$.geminiCmd.textContent = state.cliCommands.gemini;
const selfTestResults = this.$.selfTestResults;
selfTestResults.innerHTML = "";
if (!state.selfTest) {
selfTestResults.textContent = t("selfTestNever");
} else {
for (const check of state.selfTest.checks) {
const row = document.createElement("div");
row.className = "self-test-row";
const icon = document.createElement("span");
icon.className = `self-test-icon ${check.ok ? "ok-text" : "bad-text"}`;
icon.textContent = check.ok ? "OK" : "X";
const id = document.createElement("strong");
id.textContent = check.id;
const message = document.createElement("span");
message.className = "self-test-message";
message.textContent = check.message;
row.append(icon, id, message);
selfTestResults.appendChild(row);
}
}
const guideSteps = this.$.quickStartSteps;
guideSteps.innerHTML = "";
const onboardingSteps = [
{ label: t("quickStartStepServer"), done: state.server.running },
{ label: t("quickStartStepConfig"), done: state.clients.some((client) => client.configured) },
{ label: t("quickStartStepConnect"), done: state.server.connections > 0 }
];
for (const step of onboardingSteps) {
const row = document.createElement("div");
row.className = "guide-step";
const status = document.createElement("span");
status.className = `guide-status${step.done ? " done" : ""}`;
status.textContent = step.done ? t("quickStartDone") : t("quickStartPending");
const label = document.createElement("span");
label.textContent = step.label;
row.append(status, label);
guideSteps.appendChild(row);
}
const list = this.$.clientList;
list.innerHTML = "";
for (const c of state.clients) {
const row = document.createElement("div");
row.className = "client-row";
const tagText = c.configured ? t("configured") : t("notConfigured");
const tagClass = c.configured ? "ok" : "bad";
row.innerHTML = `
<strong>${c.name}</strong>
<span title="${c.configPath}">${c.configPath}</span>
<span class="tag ${tagClass}">${tagText}</span>
<div>
<ui-button class="cfg-btn" data-client="${c.clientType}">${t("autoConfig")}</ui-button>
<ui-button class="open-btn" data-client="${c.clientType}">${t("openConfig")}</ui-button>
</div>
`;
list.appendChild(row);
}
list.querySelectorAll(".cfg-btn").forEach((el) => {
el.addEventListener("confirm", async () => {
const clientType = el.getAttribute("data-client");
await Editor.Message.request(pluginName, "add-mcp-to-client", clientType, readServerName());
await refresh();
});
});
list.querySelectorAll(".open-btn").forEach((el) => {
el.addEventListener("confirm", async () => {
const clientType = el.getAttribute("data-client");
await Editor.Message.request(pluginName, "open-client-config", clientType);
});
});
const logs = this.$.logs;
logs.innerHTML = "";
for (const l of state.logs.slice().reverse()) {
const line = document.createElement("div");
line.className = `log ${l.level}`;
line.textContent = `${l.ts} [${logLevelLabel(l.level)}] ${l.message}`;
logs.appendChild(line);
}
};
const refresh = async () => {
applyStaticLabels();
const state = await Editor.Message.request(pluginName, "get-mcp-panel-state", readServerName());
render(state);
};
this.$.langSelect?.addEventListener("change", () => {
const sel = this.$.langSelect;
const v = sel?.value === "en" ? "en" : "zh";
locale = v;
writeLocale(v);
refresh().catch((e) => console.error("[cocos-mcp panel] refresh after locale", e));
});
this.$.startBtn?.addEventListener("confirm", async () => {
await Editor.Message.request(pluginName, "start-mcp-server");
await refresh();
});
this.$.stopBtn?.addEventListener("confirm", async () => {
await Editor.Message.request(pluginName, "stop-mcp-server");
await refresh();
});
this.$.refreshBtn?.addEventListener("confirm", refresh);
this.$.selfTestBtn?.addEventListener("confirm", async () => {
await Editor.Message.request(pluginName, "run-mcp-self-test", readServerName());
await refresh();
});
this.$.openGuideBtn?.addEventListener("confirm", async () => {
await Editor.Message.request(pluginName, "open-user-guide");
});
this.$.addAllBtn?.addEventListener("confirm", async () => {
await Editor.Message.request(pluginName, "add-mcp-to-all-clients", readServerName());
await refresh();
});
this.$.clearLogsBtn?.addEventListener("confirm", async () => {
await Editor.Message.request(pluginName, "clear-panel-logs");
await refresh();
});
this.$.serverNameInput?.addEventListener("change", refresh);
refresh().catch((e) => {
console.error("[cocos-mcp panel] initial refresh failed", e);
});
}
});
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,8 @@
'use strict';
module.exports = {
description: 'stdio MCP bridge: WebSocket on Main, scene script for scene read/write (local-first)',
panel_title: 'Cocos MCP Server',
menu_path: 'Extension/Cocos MCP',
open_panel: 'Open MCP Panel',
};
@@ -0,0 +1,8 @@
'use strict';
module.exports = {
description: 'stdio MCP 桥接:Main 进程 WebSocket,Scene 脚本执行场景读写(本机优先)',
panel_title: 'Cocos MCP 服务器',
menu_path: '扩展/Cocos MCP',
open_panel: '打开 MCP 面板',
};
@@ -0,0 +1,37 @@
{
"name": "cocos-mcp",
"version": "0.2.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "cocos-mcp",
"version": "0.2.0",
"license": "UNLICENSED",
"dependencies": {
"ws": "^8.21.1"
}
},
"node_modules/ws": {
"version": "8.21.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.3.tgz",
"integrity": "sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
}
}
}
@@ -0,0 +1,142 @@
{
"$schema": "./@types/schema/package/index.json",
"package_version": 2,
"name": "cocos-mcp",
"version": "0.2.0",
"private": true,
"license": "UNLICENSED",
"author": "",
"editor": ">=3.8.0",
"description": "i18n:cocos-mcp.description",
"main": "./dist/main.js",
"panels": {
"default": {
"title": "i18n:cocos-mcp.panel_title",
"type": "dockable",
"main": "dist/panels/default/index",
"size": {
"min-width": 560,
"min-height": 420,
"width": 920,
"height": 760
}
}
},
"dependencies": {
"ws": "^8.21.1"
},
"contributions": {
"menu": [
{
"path": "i18n:cocos-mcp.menu_path",
"label": "i18n:cocos-mcp.open_panel",
"message": "open-panel"
}
],
"messages": {
"open-panel": {
"methods": [
"openPanel"
]
},
"open-user-guide": {
"methods": [
"openUserGuide"
]
},
"start-mcp-server": {
"methods": [
"startMcpServer"
]
},
"stop-mcp-server": {
"methods": [
"stopMcpServer"
]
},
"get-mcp-server-status": {
"methods": [
"getMcpServerStatus"
]
},
"get-mcp-panel-state": {
"methods": [
"getMcpPanelState"
]
},
"run-mcp-self-test": {
"methods": [
"runMcpSelfTest"
]
},
"add-mcp-to-client": {
"methods": [
"addMcpToClient"
]
},
"add-mcp-to-all-clients": {
"methods": [
"addMcpToAllClients"
]
},
"open-client-config": {
"methods": [
"openClientConfig"
]
},
"clear-panel-logs": {
"methods": [
"clearPanelLogs"
]
}
},
"scene": {
"script": "./dist/scene.js",
"methods": [
"ping",
"getCurrentSceneMeta",
"getHierarchy",
"searchNodes",
"inspectNode",
"settleUiNodes",
"verifyUiNode",
"prepareSetNodeActive",
"prepareSetNodeTransform",
"prepareSetNodeName",
"prepareCreateNode",
"prepareDeleteNode",
"prepareReparentNode",
"prepareSetNodeSiblingIndex",
"prepareInstantiatePrefab",
"prepareAddComponent",
"prepareRemoveComponent",
"prepareDuplicateNode",
"listChildUuidsUnderParent",
"duplicateNodeFallback",
"removeLastComponentByType",
"addLastComponentByType",
"getComponentStatsByType",
"getComponentUuidState",
"setSiblingIndexFallback",
"setComponentScalarPropertyDirect",
"getComponentAssetRefUuid",
"setComponentAssetRefDirect",
"setComponentAssetRefFromScene",
"clearComponentAssetRef",
"getNodeActiveState",
"registerNidForNewNode",
"forgetNodeNid",
"forgetNidsInSubtree",
"snapshotNidMappingsInSubtree",
"detachNodeForMcpUndo",
"restoreDetachedNodeForMcpUndo",
"discardDetachedNodesForMcpUndo",
"removeCreatedNodesForMcpUndo",
"forgetNidMappingsByUuids",
"restoreNidMapping",
"prepareSetComponentProperty"
]
}
},
"_storeId": "9854cb1796e2aa8cffeeacfc506ab17d"
}
+7
View File
@@ -0,0 +1,7 @@
{
"name": "HexTrail",
"uuid": "667d71b4-1b60-42a0-92a1-cd72e5416842",
"creator": {
"version": "3.8.8"
}
}
@@ -0,0 +1,3 @@
{
"__version__": "1.3.9"
}
@@ -0,0 +1,3 @@
{
"__version__": "1.0.1"
}
@@ -0,0 +1,226 @@
{
"__version__": "1.0.12",
"modules": {
"configs": {
"defaultConfig": {
"name": "Default Config",
"cache": {
"base": {
"_value": true
},
"gfx-webgl": {
"_value": true
},
"gfx-webgl2": {
"_value": true
},
"gfx-webgpu": {
"_value": false
},
"animation": {
"_value": true
},
"skeletal-animation": {
"_value": false
},
"3d": {
"_value": false
},
"meshopt": {
"_value": false
},
"2d": {
"_value": true
},
"sorting-2d": {
"_value": false
},
"rich-text": {
"_value": true
},
"mask": {
"_value": true
},
"graphics": {
"_value": true
},
"ui-skew": {
"_value": false
},
"affine-transform": {
"_value": true
},
"ui": {
"_value": true
},
"particle": {
"_value": false
},
"physics": {
"_value": false,
"_option": "physics-ammo"
},
"physics-ammo": {
"_value": false,
"_flags": {
"LOAD_BULLET_MANUALLY": false
}
},
"physics-cannon": {
"_value": false
},
"physics-physx": {
"_value": false,
"_flags": {
"LOAD_PHYSX_MANUALLY": false
}
},
"physics-builtin": {
"_value": false
},
"physics-2d": {
"_value": true,
"_option": "physics-2d-box2d"
},
"physics-2d-box2d": {
"_value": false
},
"physics-2d-box2d-wasm": {
"_value": false,
"_flags": {
"LOAD_BOX2D_MANUALLY": false
}
},
"physics-2d-builtin": {
"_value": false
},
"physics-2d-box2d-jsb": {
"_value": false
},
"intersection-2d": {
"_value": true
},
"primitive": {
"_value": false
},
"profiler": {
"_value": true
},
"occlusion-query": {
"_value": false
},
"geometry-renderer": {
"_value": false
},
"debug-renderer": {
"_value": false
},
"particle-2d": {
"_value": true
},
"audio": {
"_value": true
},
"video": {
"_value": true
},
"webview": {
"_value": true
},
"tween": {
"_value": true
},
"websocket": {
"_value": false
},
"websocket-server": {
"_value": false
},
"terrain": {
"_value": false
},
"light-probe": {
"_value": false
},
"tiled-map": {
"_value": true
},
"vendor-google": {
"_value": false
},
"spine": {
"_value": true,
"_option": "spine-3.8"
},
"spine-3.8": {
"_value": true,
"_flags": {
"LOAD_SPINE_MANUALLY": false
}
},
"spine-4.2": {
"_value": false,
"_flags": {
"LOAD_SPINE_MANUALLY": false
}
},
"dragon-bones": {
"_value": true
},
"marionette": {
"_value": false
},
"procedural-animation": {
"_value": false
},
"custom-pipeline-post-process": {
"_value": false
},
"render-pipeline": {
"_value": true,
"_option": "custom-pipeline"
},
"custom-pipeline": {
"_value": true
},
"legacy-pipeline": {
"_value": false
},
"xr": {
"_value": false
}
},
"includeModules": [
"2d",
"affine-transform",
"animation",
"audio",
"base",
"custom-pipeline",
"dragon-bones",
"gfx-webgl",
"gfx-webgl2",
"graphics",
"intersection-2d",
"mask",
"particle-2d",
"physics-2d-box2d",
"profiler",
"rich-text",
"spine-3.8",
"tiled-map",
"tween",
"ui",
"video",
"webview"
],
"noDeprecatedFeatures": {
"value": false,
"version": ""
},
"flags": {}
}
},
"globalConfigKey": "defaultConfig"
}
}
@@ -0,0 +1,23 @@
{
"__version__": "1.0.1",
"information": {
"customSplash": {
"id": "customSplash",
"label": "customSplash",
"enable": true,
"customSplash": {
"complete": false,
"form": "https://creator-api.cocos.com/api/form/show?sid=83e44122938e10687491dd8686ffd845"
}
},
"removeSplash": {
"id": "removeSplash",
"label": "removeSplash",
"enable": true,
"removeSplash": {
"complete": false,
"form": "https://creator-api.cocos.com/api/form/show?sid=83e44122938e10687491dd8686ffd845"
}
}
}
}
@@ -0,0 +1,3 @@
{
"__version__": "1.0.4"
}
@@ -0,0 +1,3 @@
{
"__version__": "1.0.6"
}
+9
View File
@@ -0,0 +1,9 @@
{
/* Base configuration. Do not edit this field. */
"extends": "./temp/tsconfig.cocos.json",
/* Add your custom configuration here. */
"compilerOptions": {
"strict": false
}
}