Compare commits
10 Commits
bb484ed847
...
605d9c3f57
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
605d9c3f57 | ||
|
|
754adecdb8 | ||
|
|
fc8b63cfc1 | ||
|
|
c6c2c37c0a | ||
|
|
f1e62f32f3 | ||
|
|
46e3e6ae5b | ||
|
|
b0af87291e | ||
|
|
2dfd5168fe | ||
|
|
1286dbc5c8 | ||
|
|
c752cae24b |
357
README.EN.md
357
README.EN.md
@@ -1,28 +1,73 @@
|
|||||||
# Cocos Creator MCP Server Plugin
|
# Cocos Creator MCP Server Plugin
|
||||||
**[📖 English](README.en.md)** **[📖 中文](README.md)**
|
|
||||||
|
|
||||||
|
**[📖 English](README.EN.md)** **[📖 中文](README.md)**
|
||||||
|
|
||||||
A comprehensive MCP (Model Context Protocol) server plugin for Cocos Creator 3.8+, enabling AI assistants to interact with the Cocos Creator editor through standardized protocols. One-click installation and use, eliminating all cumbersome environments and configurations. Claude clients Claude CLI and Cursor have been tested, and other editors are also perfectly supported in theory.
|
A comprehensive MCP (Model Context Protocol) server plugin for Cocos Creator 3.8+, enabling AI assistants to interact with the Cocos Creator editor through standardized protocols. One-click installation and use, eliminating all cumbersome environments and configurations. Claude clients Claude CLI and Cursor have been tested, and other editors are also perfectly supported in theory.
|
||||||
|
|
||||||
**🚀 Now provides 158 tools in 13 categories, achieving 98% editor control!**
|
**🚀 Now provides 50 powerful integrated tools, achieving 99% editor control!**
|
||||||
|
|
||||||
## Video Demonstrations and Tutorials
|
## Video Demonstrations and Tutorials
|
||||||
[<img width="503" height="351" alt="image" src="https://github.com/user-attachments/assets/f186ce14-9ffc-4a29-8761-48bdd7c1ea16" />](https://www.bilibili.com/video/BV1uzgVz8EyQ/?vd_source=6b1ff659dd5f04a92cc6d14061e8bb92)
|
|
||||||
|
|
||||||
## Video Demonstration Configuration Tool List
|
[<img width="503" height="351" alt="image" src="https://github.com/user-attachments/assets/f186ce14-9ffc-4a29-8761-48bdd7c1ea16" />](https://www.bilibili.com/video/BV1mB8dzfEw8?spm_id_from=333.788.recommend_more_video.0&vd_source=6b1ff659dd5f04a92cc6d14061e8bb92)
|
||||||
[<img width="502" height="345" alt="image" src="https://github.com/user-attachments/assets/c5bfe1ed-8946-42a7-ac50-d86dd177e496" />](https://www.bilibili.com/video/BV1kfbyzQEAS/?vd_source=6b1ff659dd5f04a92cc6d14061e8bb92)
|
|
||||||
|
|
||||||
|
|
||||||
## Quick Links
|
## Quick Links
|
||||||
|
|
||||||
- **[📖 Complete Feature Guide (English)](FEATURE_GUIDE_EN.md)** - Detailed documentation for all 158 tools(To be completed)
|
- **[📖 Complete Feature Guide (English)](FEATURE_GUIDE_EN.md)** - Detailed documentation for all 50 tools (to be completed)
|
||||||
- **[📖 完整功能指南 (中文)](FEATURE_GUIDE_CN.md)** - 所有158个工具的详细文档(To be completed)
|
- **[📖 完整功能指南 (中文)](FEATURE_GUIDE_CN.md)** - All 50 tools detailed documentation (to be completed)
|
||||||
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
### v1.4.0 - July 26, 2025 (Already updated in the cocos store, the github version will be synchronized in the near future)
|
## 🚀 Major Update v1.5.0 (July 29, 2024) (Already updated in Cocos Store, GitHub version will be synchronized in next version)
|
||||||
cocos store:https://store.cocos.com/app/detail/7941
|
|
||||||
If you don't want to buy it, join the communication group and I can send you the latest version directly!
|
Cocos store: https://store.cocos.com/app/detail/7941
|
||||||
|
|
||||||
|
- **Tool Streamlining and Refactoring**: Condensed the original 150+ tools into 50 high-reuse, high-coverage core tools, removing all invalid redundant code, greatly improving usability and maintainability.
|
||||||
|
- **Unified Operation Codes**: All tools adopt "operation code + parameters" mode, greatly simplifying AI calling process, improving AI calling success rate, reducing AI calling times, and lowering 50% token consumption.
|
||||||
|
- **Comprehensive Prefab Function Upgrade**: Completely fixed and perfected all core prefab functions including creation, instantiation, synchronization, references, etc., supporting complex reference relationships, 100% aligned with official format.
|
||||||
|
- **Event Binding and Legacy Function Completion**: Added and implemented event binding, node/component/asset legacy functions, all methods completely aligned with official implementation.
|
||||||
|
- **Interface Optimization**: All interface parameters are clearer, documentation is more complete, AI can understand and call more easily.
|
||||||
|
- **Plugin Panel Optimization**: Panel UI is more concise, operations are more intuitive.
|
||||||
|
- **Performance and Compatibility Improvements**: Overall architecture is more efficient, compatible with Cocos Creator 3.8.6 and all versions above.
|
||||||
|
|
||||||
|
|
||||||
|
## Tool System and Operation Codes
|
||||||
|
|
||||||
|
- All tools are named with "category_operation", parameters use unified Schema, support multiple operation code (action) switching, greatly improving flexibility and extensibility.
|
||||||
|
- 50 core tools cover scene, node, component, prefab, asset, project, debugging, preferences, server, message broadcasting and all other editor operations.
|
||||||
|
- Tool calling example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tool": "node_lifecycle",
|
||||||
|
"arguments": {
|
||||||
|
"action": "create",
|
||||||
|
"name": "MyNode",
|
||||||
|
"parentUuid": "parent-uuid",
|
||||||
|
"nodeType": "2DNode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Main Function Categories (Partial Examples)
|
||||||
|
|
||||||
|
- **scene_management**: Scene management (get/open/save/create/close scenes)
|
||||||
|
- **node_query / node_lifecycle / node_transform**: Node query, creation, deletion, property changes
|
||||||
|
- **component_manage / component_script / component_query**: Component add/remove, script mounting, component information
|
||||||
|
- **prefab_browse / prefab_lifecycle / prefab_instance**: Prefab browsing, creation, instantiation, synchronization
|
||||||
|
- **asset_manage / asset_analyze**: Asset import, deletion, dependency analysis
|
||||||
|
- **project_manage / project_build_system**: Project running, building, configuration information
|
||||||
|
- **debug_console / debug_logs**: Console and log management
|
||||||
|
- **preferences_manage**: Preferences settings
|
||||||
|
- **server_info**: Server information
|
||||||
|
- **broadcast_message**: Message broadcasting
|
||||||
|
|
||||||
|
|
||||||
|
### v1.4.0 - July 26, 2025 (Current github version)
|
||||||
|
|
||||||
#### 🎯 Major Functionality Fixes
|
#### 🎯 Major Functionality Fixes
|
||||||
- **Complete Prefab Creation Fix**: Thoroughly resolved the issue of component/node/resource type reference loss during prefab creation
|
- **Complete Prefab Creation Fix**: Thoroughly resolved the issue of component/node/resource type reference loss during prefab creation
|
||||||
@@ -99,10 +144,13 @@ If you don't want to buy it, join the communication group and I can send you the
|
|||||||
- Project control and debugging tools
|
- Project control and debugging tools
|
||||||
|
|
||||||
|
|
||||||
**Claude cli configuration:**
|
|
||||||
|
## Quick Usage
|
||||||
|
|
||||||
|
**Claude CLI configuration:**
|
||||||
|
|
||||||
```
|
```
|
||||||
claude mcp add --transport http cocos-creator http://127.0.0.1:3000/mcp (use the port number you configured yourself)
|
claude mcp add --transport http cocos-creator http://127.0.0.1:3000/mcp (use your configured port number)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Claude client configuration:**
|
**Claude client configuration:**
|
||||||
@@ -110,20 +158,19 @@ claude mcp add --transport http cocos-creator http://127.0.0.1:3000/mcp (use the
|
|||||||
```
|
```
|
||||||
{
|
{
|
||||||
|
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
|
|
||||||
"cocos-creator": {
|
"cocos-creator": {
|
||||||
|
|
||||||
"type": "http",
|
"type": "http",
|
||||||
|
|
||||||
"url": "http://127.0.0.1:3000/mcp"
|
"url": "http://127.0.0.1:3000/mcp"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**Cursor or VS class MCP configuration**
|
**Cursor or VS class MCP configuration**
|
||||||
@@ -131,75 +178,97 @@ claude mcp add --transport http cocos-creator http://127.0.0.1:3000/mcp (use the
|
|||||||
```
|
```
|
||||||
{
|
{
|
||||||
|
|
||||||
"mcpServers": {
|
"mcpServers": {
|
||||||
|
|
||||||
"cocos-creator": {
|
"cocos-creator": {
|
||||||
"url": "http://localhost:3000/mcp"
|
"url": "http://localhost:3000/mcp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
### 🎯 Scene Operations
|
### 🎯 Scene Operations (scene_*)
|
||||||
- Get current scene information and complete scene list
|
- **scene_management**: Scene management - Get current scene, open/save/create/close scenes, support scene list query
|
||||||
- Open scenes by path and save current scene
|
- **scene_hierarchy**: Scene hierarchy - Get complete scene structure, support component information inclusion
|
||||||
- Create new scenes with custom names
|
- **scene_execution_control**: Execution control - Execute component methods, scene scripts, prefab synchronization
|
||||||
- Get complete scene hierarchy with component information
|
|
||||||
|
|
||||||
### 🎮 Node Operations
|
### 🎮 Node Operations (node_*)
|
||||||
- Create nodes with different types (Node, 2DNode, 3DNode)
|
- **node_query**: Node query - Find nodes by name/pattern, get node information, detect 2D/3D types
|
||||||
- Get node information by UUID and find nodes by name pattern
|
- **node_lifecycle**: Node lifecycle - Create/delete nodes, support component pre-installation, prefab instantiation
|
||||||
- Set node properties (position, rotation, scale, active)
|
- **node_transform**: Node transform - Modify node name, position, rotation, scale, visibility and other properties
|
||||||
- Delete, move, and duplicate nodes with full hierarchy support
|
- **node_hierarchy**: Node hierarchy - Move, copy, paste nodes, support hierarchical structure operations
|
||||||
|
- **node_clipboard**: Node clipboard - Copy/paste/cut node operations
|
||||||
|
- **node_property_management**: Property management - Reset node properties, component properties, transform properties
|
||||||
|
|
||||||
### 🔧 Component Operations
|
### 🔧 Component Operations (component_*)
|
||||||
- Add/remove components from nodes
|
- **component_manage**: Component management - Add/remove engine components (cc.Sprite, cc.Button, etc.)
|
||||||
- Get all components of a node with properties
|
- **component_script**: Script components - Mount/remove custom script components
|
||||||
- Set component properties dynamically
|
- **component_query**: Component query - Get component list, detailed information, available component types
|
||||||
- Attach script components from asset paths
|
- **set_component_property**: Property setting - Set single or multiple component property values
|
||||||
- List available component types by category
|
|
||||||
|
|
||||||
### 📦 Prefab Operations
|
### 📦 Prefab Operations (prefab_*)
|
||||||
- List all prefabs in project with folder organization
|
- **prefab_browse**: Prefab browsing - List prefabs, view information, validate files
|
||||||
- Load, instantiate, and create prefabs
|
- **prefab_lifecycle**: Prefab lifecycle - Create prefabs from nodes, delete prefabs
|
||||||
- Update existing prefabs and revert prefab instances
|
- **prefab_instance**: Prefab instances - Instantiate to scene, unlink, apply changes, restore original
|
||||||
- Get detailed prefab information including dependencies
|
- **prefab_edit**: Prefab editing - Enter/exit edit mode, save prefabs, test changes
|
||||||
- **⚠️ Known Issue**: Prefab instantiation may not properly restore child nodes due to Cocos Creator API limitations
|
|
||||||
|
|
||||||
### 🚀 Project Control
|
### 🚀 Project Control (project_*)
|
||||||
- Run project in preview mode (browser/simulator)
|
- **project_manage**: Project management - Run project, build project, get project information and settings
|
||||||
- Build project for different platforms (web, mobile, desktop)
|
- **project_build_system**: Build system - Control build panel, check build status, preview server management
|
||||||
- Get project information and settings
|
|
||||||
- Refresh asset database and import new assets
|
|
||||||
- Get detailed asset information
|
|
||||||
|
|
||||||
### 🔍 Debug Tools
|
### 🔍 Debug Tools (debug_*)
|
||||||
- Get editor console logs with filtering
|
- **debug_console**: Console management - Get/clear console logs, support filtering and limiting
|
||||||
- Clear console and execute JavaScript in scene context
|
- **debug_logs**: Log analysis - Read/search/analyze project log files, support pattern matching
|
||||||
- Get detailed node tree for debugging
|
- **debug_system**: System debugging - Get editor information, performance statistics, environment information
|
||||||
- Performance statistics and scene validation
|
|
||||||
- Get editor and environment information
|
|
||||||
|
|
||||||
### ⚙️ Additional Features
|
### 📁 Asset Management (asset_*)
|
||||||
- **Preferences Management**: Get/set editor preferences and global settings
|
- **asset_manage**: Asset management - Batch import/delete assets, save metadata, generate URLs
|
||||||
- **Server Control**: Server information, project details, and editor control
|
- **asset_analyze**: Asset analysis - Get dependency relationships, export asset manifests
|
||||||
- **Message Broadcasting**: Listen to and broadcast custom messages
|
- **asset_system**: Asset system - Refresh assets, query asset database status
|
||||||
- **Asset Management**: Create, copy, move, delete, and query assets
|
- **asset_query**: Asset query - Query assets by type/folder, get detailed information
|
||||||
- **Build System**: Project building and preview server control
|
- **asset_operations**: Asset operations - Create/copy/move/delete/save/re-import assets
|
||||||
- **Reference Image Management**: Add, remove, and manage reference images in scene view
|
|
||||||
- **Scene View Controls**: Control gizmo tools, coordinate systems, and view modes
|
### ⚙️ Preferences (preferences_*)
|
||||||
- **Advanced Scene Operations**: Undo/redo, snapshots, and advanced node manipulation
|
- **preferences_manage**: Preferences management - Get/set editor preferences
|
||||||
- **🆕 Tool Management**: Selectively enable/disable tools, save configurations, and manage tool states
|
- **preferences_global**: Global settings - Manage global configuration and system settings
|
||||||
|
|
||||||
|
### 🌐 Server and Broadcasting (server_* / broadcast_*)
|
||||||
|
- **server_info**: Server information - Get server status, project details, environment information
|
||||||
|
- **broadcast_message**: Message broadcasting - Listen and broadcast custom messages
|
||||||
|
|
||||||
|
### 🖼️ Reference Images (referenceImage_*)
|
||||||
|
- **reference_image_manage**: Reference image management - Add/delete/manage reference images in scene view
|
||||||
|
- **reference_image_view**: Reference image view - Control reference image display and editing
|
||||||
|
|
||||||
|
### 🎨 Scene View (sceneView_*)
|
||||||
|
- **scene_view_control**: Scene view control - Control Gizmo tools, coordinate systems, view modes
|
||||||
|
- **scene_view_tools**: Scene view tools - Manage various scene view tools and options
|
||||||
|
|
||||||
|
### ✅ Validation Tools (validation_*)
|
||||||
|
- **validation_scene**: Scene validation - Validate scene integrity, check missing assets
|
||||||
|
- **validation_asset**: Asset validation - Validate asset references, check asset integrity
|
||||||
|
|
||||||
|
### 🛠️ Tool Management
|
||||||
|
- **Tool Configuration System**: Selectively enable/disable tools, support multiple configurations
|
||||||
|
- **Configuration Persistence**: Automatically save and load tool configurations
|
||||||
|
- **Configuration Import/Export**: Support tool configuration import/export functionality
|
||||||
|
- **Real-time State Management**: Real-time tool state updates and synchronization
|
||||||
|
|
||||||
|
### 🚀 Core Advantages
|
||||||
|
- **Unified Operation Codes**: All tools adopt "category_operation" naming, unified parameter Schema
|
||||||
|
- **High Reusability**: 50 core tools cover 99% editor functionality
|
||||||
|
- **AI-Friendly**: Clear parameters, complete documentation, simple calling
|
||||||
|
- **Performance Optimization**: Reduce 50% token consumption, improve AI calling success rate
|
||||||
|
- **Complete Compatibility**: 100% aligned with Cocos Creator official API
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### 1. Copy Plugin Files
|
### 1. Copy Plugin Files
|
||||||
|
|
||||||
Copy the entire `cocos-mcp-server` folder to your Cocos Creator project's `extensions` directory:
|
Copy the entire `cocos-mcp-server` folder to your Cocos Creator project's `extensions` directory, or you can directly import the project in the extension manager:
|
||||||
|
|
||||||
```
|
```
|
||||||
YourProject/
|
YourProject/
|
||||||
@@ -252,118 +321,6 @@ The server exposes an HTTP endpoint at `http://localhost:3000/mcp` (or your conf
|
|||||||
|
|
||||||
AI assistants can connect using the MCP protocol and access all available tools.
|
AI assistants can connect using the MCP protocol and access all available tools.
|
||||||
|
|
||||||
### Tool Categories
|
|
||||||
|
|
||||||
Tools are organized by category with naming convention: `category_toolname`
|
|
||||||
|
|
||||||
- **scene_\***: Scene-related operations (8 tools)
|
|
||||||
- **node_\***: Node manipulation (9 tools)
|
|
||||||
- **component_\***: Component management (7 tools)
|
|
||||||
- **prefab_\***: Prefab operations (11 tools)
|
|
||||||
- **project_\***: Project control (22 tools)
|
|
||||||
- **debug_\***: Debugging utilities (10 tools)
|
|
||||||
- **preferences_\***: Editor preferences (7 tools)
|
|
||||||
- **server_\***: Server information (6 tools)
|
|
||||||
- **broadcast_\***: Message broadcasting (5 tools)
|
|
||||||
- **assetAdvanced_\***: Advanced asset operations (10 tools)
|
|
||||||
- **referenceImage_\***: Reference image management (12 tools)
|
|
||||||
- **sceneAdvanced_\***: Advanced scene operations (23 tools)
|
|
||||||
- **sceneView_\***: Scene view controls (14 tools)
|
|
||||||
|
|
||||||
|
|
||||||
📖 **[View Complete Tool Documentation](FEATURE_GUIDE_EN.md)** for detailed usage examples and parameters.
|
|
||||||
|
|
||||||
## Example Tool Usage
|
|
||||||
|
|
||||||
### Create a new sprite node
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "node_create_node",
|
|
||||||
"arguments": {
|
|
||||||
"name": "MySprite",
|
|
||||||
"nodeType": "2DNode",
|
|
||||||
"parentUuid": "parent-node-uuid"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Add a Sprite component
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "component_add_component",
|
|
||||||
"arguments": {
|
|
||||||
"nodeUuid": "node-uuid",
|
|
||||||
"componentType": "cc.Sprite"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### Instantiate a prefab
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "prefab_instantiate_prefab",
|
|
||||||
"arguments": {
|
|
||||||
"prefabPath": "db://assets/prefabs/Enemy.prefab",
|
|
||||||
"position": { "x": 100, "y": 200, "z": 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
**⚠️ Note**: Complex prefabs with child nodes may not instantiate correctly due to Cocos Creator API limitations. Child nodes may be missing in the instantiated prefab.
|
|
||||||
|
|
||||||
### Run project in browser
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "project_run_project",
|
|
||||||
"arguments": {
|
|
||||||
"platform": "browser"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
Settings are stored in `YourProject/settings/mcp-server.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"port": 3000,
|
|
||||||
"autoStart": false,
|
|
||||||
"enableDebugLog": true,
|
|
||||||
"allowedOrigins": ["*"],
|
|
||||||
"maxConnections": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Tool configurations are stored in `YourProject/settings/tool-manager.json`:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"currentConfigId": "default",
|
|
||||||
"configurations": {
|
|
||||||
"default": {
|
|
||||||
"id": "default",
|
|
||||||
"name": "默认配置",
|
|
||||||
"description": "默认工具配置",
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"category": "scene",
|
|
||||||
"name": "get_current_scene",
|
|
||||||
"enabled": true,
|
|
||||||
"description": "Get current scene information"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Icon Setup
|
|
||||||
|
|
||||||
To add an icon for the plugin panel:
|
|
||||||
|
|
||||||
1. Create a PNG icon file (recommended size: 32x32 or 64x64)
|
|
||||||
2. Place it in the `static/` directory: `static/icon.png`
|
|
||||||
3. The icon path is already configured in `package.json`
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
@@ -385,7 +342,7 @@ cocos-mcp-server/
|
|||||||
│ │ ├── preferences-tools.ts
|
│ │ ├── preferences-tools.ts
|
||||||
│ │ ├── server-tools.ts
|
│ │ ├── server-tools.ts
|
||||||
│ │ ├── broadcast-tools.ts
|
│ │ ├── broadcast-tools.ts
|
||||||
│ │ ├── scene-advanced-tools.ts
|
│ │ ├── scene-advanced-tools.ts (integrated into node-tools.ts and scene-tools.ts)
|
||||||
│ │ ├── scene-view-tools.ts
|
│ │ ├── scene-view-tools.ts
|
||||||
│ │ ├── reference-image-tools.ts
|
│ │ ├── reference-image-tools.ts
|
||||||
│ │ └── asset-advanced-tools.ts
|
│ │ └── asset-advanced-tools.ts
|
||||||
@@ -426,19 +383,6 @@ The plugin is fully written in TypeScript with:
|
|||||||
- IntelliSense support for development
|
- IntelliSense support for development
|
||||||
- Automatic compilation to JavaScript
|
- Automatic compilation to JavaScript
|
||||||
|
|
||||||
### Running Tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Run comprehensive test suite
|
|
||||||
node comprehensive-test.js
|
|
||||||
|
|
||||||
# Run feature-specific tests
|
|
||||||
./test-all-features.sh
|
|
||||||
|
|
||||||
# Run Node.js test script
|
|
||||||
node test-mcp-server.js
|
|
||||||
```
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Common Issues
|
### Common Issues
|
||||||
@@ -474,23 +418,10 @@ Enable debug logging in the plugin panel for detailed operation logs.
|
|||||||
- Node.js (bundled with Cocos Creator)
|
- Node.js (bundled with Cocos Creator)
|
||||||
- TypeScript (installed as dev dependency)
|
- TypeScript (installed as dev dependency)
|
||||||
|
|
||||||
## Architecture Notes
|
|
||||||
|
|
||||||
This plugin uses a simplified MCP protocol implementation that is compatible with Cocos Creator's CommonJS environment. The HTTP server provides a JSON-RPC interface for AI assistants to interact with the editor.
|
|
||||||
|
|
||||||
### Protocol Support
|
|
||||||
- **HTTP Connection**: `http://localhost:3000/mcp` (configurable port)
|
|
||||||
- **JSON-RPC 2.0**: Standard request/response format
|
|
||||||
- **Tool Discovery**: `tools/list` method returns available tools
|
|
||||||
- **Tool Execution**: `tools/call` method executes specific tools
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This plug-in is for Cocos Creator project, and the source code is packaged together, which can be used for learning and communication. It is not encrypted. It can support your own secondary development and optimization. Any code of this project or its derivative code cannot be used for any commercial purpose or resale. If you need commercial use, please contact me.
|
This plug-in is for Cocos Creator project use, and the source code is packaged together, which can be used for learning and communication. It is not encrypted. It can support your own secondary development and optimization. Any code of this project or its derivative code cannot be used for any commercial purpose or resale. If you need commercial use, please contact me.
|
||||||
|
|
||||||
|
|
||||||
## Contact me to join the group
|
## Contact me to join the group
|
||||||
|
<img alt="image" src="https://github.com/user-attachments/assets/a276682c-4586-480c-90e5-6db132e89e0f" width="400" height="400" />
|
||||||
|
|
||||||
<img src="https://github.com/user-attachments/assets/2e3f043a-0b03-4b27-a175-e9c31fbed981" style="max-width: 400px; border-radius: 8px;"/>
|
|
||||||
|
|
||||||
<img src="https://github.com/user-attachments/assets/5ef6172c-2968-499e-9edf-7da133016cd2" style="max-width: 400px; border-radius: 8px;" />
|
|
||||||
287
README.md
287
README.md
@@ -1,17 +1,14 @@
|
|||||||
# Cocos Creator MCP 服务器插件
|
# Cocos Creator MCP 服务器插件
|
||||||
|
|
||||||
**[📖 English](README.en.md)** **[📖 中文](README.md)**
|
**[📖 English](README.EN.md)** **[📖 中文](README.md)**
|
||||||
|
|
||||||
一个适用于 Cocos Creator 3.8+ 的综合性 MCP(模型上下文协议)服务器插件,使 AI 助手能够通过标准化协议与 Cocos Creator 编辑器进行交互。一键安装和使用,省去所有繁琐环境和配置。已经测试过Claude客户端Claude CLI和Cursor,其他的编辑器理论上也完美支持。
|
一个适用于 Cocos Creator 3.8+ 的综合性 MCP(模型上下文协议)服务器插件,使 AI 助手能够通过标准化协议与 Cocos Creator 编辑器进行交互。一键安装和使用,省去所有繁琐环境和配置。已经测试过Claude客户端Claude CLI和Cursor,其他的编辑器理论上也完美支持。
|
||||||
|
|
||||||
**🚀 现在提供 13 个类别的 158 个工具,实现98%的编辑器控制!**
|
**🚀 现在提供 50 个强力融合工具,实现99%的编辑器控制!**
|
||||||
|
|
||||||
## 视频演示和教学
|
## 视频演示和教学
|
||||||
|
|
||||||
[<img width="503" height="351" alt="image" src="https://github.com/user-attachments/assets/f186ce14-9ffc-4a29-8761-48bdd7c1ea16" />](https://www.bilibili.com/video/BV1uzgVz8EyQ/?vd_source=6b1ff659dd5f04a92cc6d14061e8bb92)
|
[<img width="503" height="351" alt="image" src="https://github.com/user-attachments/assets/f186ce14-9ffc-4a29-8761-48bdd7c1ea16" />](https://www.bilibili.com/video/BV1mB8dzfEw8?spm_id_from=333.788.recommend_more_video.0&vd_source=6b1ff659dd5f04a92cc6d14061e8bb92)
|
||||||
|
|
||||||
## 视频演示配置工具列表
|
|
||||||
[<img width="502" height="345" alt="image" src="https://github.com/user-attachments/assets/c5bfe1ed-8946-42a7-ac50-d86dd177e496" />](https://www.bilibili.com/video/BV1kfbyzQEAS/?vd_source=6b1ff659dd5f04a92cc6d14061e8bb92)
|
|
||||||
|
|
||||||
|
|
||||||
##快速链接
|
##快速链接
|
||||||
@@ -22,9 +19,54 @@
|
|||||||
|
|
||||||
## 更新日志
|
## 更新日志
|
||||||
|
|
||||||
### v1.4.0 - 2025年7月26日 (已经在cocos 商城更新,github版本将在近期同步)
|
## 🚀 重大更新 v1.5.0(2024年7月29日)(已经在cocos 商城更新,github版本将在下个版本同步更新)
|
||||||
|
|
||||||
cocos store:https://store.cocos.com/app/detail/7941
|
cocos store:https://store.cocos.com/app/detail/7941
|
||||||
如果不愿意购买,加入沟通群我也可以直接发送最新版给你!
|
|
||||||
|
- **工具精简与重构**:将原有150+工具浓缩规整为50个高复用、高覆盖率的核心工具,去除所有无效冗余代码,极大提升易用性和可维护性。
|
||||||
|
- **操作码统一**:所有工具均采用“操作码+参数”模式,极大简化AI调用流程,提升AI调用成功率,减少AI调用次数,降低50% token消耗。
|
||||||
|
- **预制体功能全面升级**:彻底修复和完善预制体的创建、实例化、同步、引用等所有核心功能,支持复杂引用关系,100%对齐官方格式。
|
||||||
|
- **事件绑定与老功能补全**:补充并实现了事件绑定、节点/组件/资源等老功能,所有方法与官方实现完全对齐。
|
||||||
|
- **接口优化**:所有接口参数更清晰,文档更完善,AI更容易理解和调用。
|
||||||
|
- **插件面板优化**:面板UI更简洁,操作更直观。
|
||||||
|
- **性能与兼容性提升**:整体架构更高效,兼容Cocos Creator 3.8.6及以上所有版本。
|
||||||
|
|
||||||
|
|
||||||
|
## 工具体系与操作码
|
||||||
|
|
||||||
|
- 所有工具均以“类别_操作”命名,参数采用统一Schema,支持多操作码(action)切换,极大提升灵活性和可扩展性。
|
||||||
|
- 50个核心工具涵盖场景、节点、组件、预制体、资源、项目、调试、偏好设置、服务器、消息广播等全部编辑器操作。
|
||||||
|
- 工具调用示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"tool": "node_lifecycle",
|
||||||
|
"arguments": {
|
||||||
|
"action": "create",
|
||||||
|
"name": "MyNode",
|
||||||
|
"parentUuid": "parent-uuid",
|
||||||
|
"nodeType": "2DNode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 主要功能类别(部分示例)
|
||||||
|
|
||||||
|
- **scene_management**:场景管理(获取/打开/保存/新建/关闭场景)
|
||||||
|
- **node_query / node_lifecycle / node_transform**:节点查询、创建、删除、属性变更
|
||||||
|
- **component_manage / component_script / component_query**:组件增删、脚本挂载、组件信息
|
||||||
|
- **prefab_browse / prefab_lifecycle / prefab_instance**:预制体浏览、创建、实例化、同步
|
||||||
|
- **asset_manage / asset_analyze**:资源导入、删除、依赖分析
|
||||||
|
- **project_manage / project_build_system**:项目运行、构建、配置信息
|
||||||
|
- **debug_console / debug_logs**:控制台与日志管理
|
||||||
|
- **preferences_manage**:偏好设置
|
||||||
|
- **server_info**:服务器信息
|
||||||
|
- **broadcast_message**:消息广播
|
||||||
|
|
||||||
|
|
||||||
|
### v1.4.0 - 2025年7月26日(当前github版本)
|
||||||
|
|
||||||
#### 🎯 重大功能修复
|
#### 🎯 重大功能修复
|
||||||
- **完全修复预制体创建功能**: 彻底解决了预制体创建时组件/节点/资源类型引用丢失的问题
|
- **完全修复预制体创建功能**: 彻底解决了预制体创建时组件/节点/资源类型引用丢失的问题
|
||||||
@@ -102,7 +144,6 @@ cocos store:https://store.cocos.com/app/detail/7941
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 快速使用
|
## 快速使用
|
||||||
|
|
||||||
**Claude cli配置:**
|
**Claude cli配置:**
|
||||||
@@ -148,61 +189,85 @@ claude mcp add --transport http cocos-creator http://127.0.0.1:3000/mcp(使用
|
|||||||
|
|
||||||
## 功能特性
|
## 功能特性
|
||||||
|
|
||||||
### 🎯 场景操作
|
### 🎯 场景操作 (scene_*)
|
||||||
- 获取当前场景信息和完整场景列表
|
- **scene_management**: 场景管理 - 获取当前场景、打开/保存/创建/关闭场景,支持场景列表查询
|
||||||
- 通过路径打开场景并保存当前场景
|
- **scene_hierarchy**: 场景层级 - 获取完整场景结构,支持组件信息包含
|
||||||
- 创建自定义名称的新场景
|
- **scene_execution_control**: 执行控制 - 执行组件方法、场景脚本、预制体同步
|
||||||
- 获取完整场景层级结构及组件信息
|
|
||||||
|
|
||||||
### 🎮 节点操作
|
### 🎮 节点操作 (node_*)
|
||||||
- 创建不同类型的节点(Node、2DNode、3DNode)
|
- **node_query**: 节点查询 - 按名称/模式查找节点,获取节点信息,检测2D/3D类型
|
||||||
- 通过 UUID 获取节点信息,按名称模式查找节点
|
- **node_lifecycle**: 节点生命周期 - 创建/删除节点,支持组件预装、预制体实例化
|
||||||
- 设置节点属性(位置、旋转、缩放、激活状态)
|
- **node_transform**: 节点变换 - 修改节点名称、位置、旋转、缩放、可见性等属性
|
||||||
- 删除、移动和复制节点,完整支持层级结构
|
- **node_hierarchy**: 节点层级 - 移动、复制、粘贴节点,支持层级结构操作
|
||||||
|
- **node_clipboard**: 节点剪贴板 - 复制/粘贴/剪切节点操作
|
||||||
|
- **node_property_management**: 属性管理 - 重置节点属性、组件属性、变换属性
|
||||||
|
|
||||||
### 🔧 组件操作
|
### 🔧 组件操作 (component_*)
|
||||||
- 向节点添加/删除组件
|
- **component_manage**: 组件管理 - 添加/删除引擎组件(cc.Sprite、cc.Button等)
|
||||||
- 获取节点的所有组件及属性
|
- **component_script**: 脚本组件 - 挂载/移除自定义脚本组件
|
||||||
- 动态设置组件属性
|
- **component_query**: 组件查询 - 获取组件列表、详细信息、可用组件类型
|
||||||
- 从资源路径挂载脚本组件
|
- **set_component_property**: 属性设置 - 设置单个或多个组件属性值
|
||||||
- 按类别列出可用的组件类型
|
|
||||||
|
|
||||||
### 📦 预制体操作
|
### 📦 预制体操作 (prefab_*)
|
||||||
- 列出项目中的所有预制体,支持文件夹组织
|
- **prefab_browse**: 预制体浏览 - 列出预制体、查看信息、验证文件
|
||||||
- 加载、实例化和创建预制体
|
- **prefab_lifecycle**: 预制体生命周期 - 从节点创建预制体、删除预制体
|
||||||
- 更新现有预制体并还原预制体实例
|
- **prefab_instance**: 预制体实例 - 实例化到场景、解除链接、应用更改、还原原始
|
||||||
- 获取详细的预制体信息,包括依赖关系
|
- **prefab_edit**: 预制体编辑 - 进入/退出编辑模式、保存预制体、测试更改
|
||||||
|
|
||||||
### 🚀 项目控制
|
### 🚀 项目控制 (project_*)
|
||||||
- 在预览模式下运行项目(浏览器/模拟器)
|
- **project_manage**: 项目管理 - 运行项目、构建项目、获取项目信息和设置
|
||||||
- 为不同平台构建项目(Web、移动端、桌面端)
|
- **project_build_system**: 构建系统 - 控制构建面板、检查构建状态、预览服务器管理
|
||||||
- 获取项目信息和设置
|
|
||||||
- 刷新资源数据库并导入新资源
|
|
||||||
- 获取详细的资源信息
|
|
||||||
|
|
||||||
### 🔍 调试工具
|
### 🔍 调试工具 (debug_*)
|
||||||
- 获取编辑器控制台日志,支持过滤
|
- **debug_console**: 控制台管理 - 获取/清空控制台日志,支持过滤和限制
|
||||||
- 清空控制台并在场景上下文中执行 JavaScript
|
- **debug_logs**: 日志分析 - 读取/搜索/分析项目日志文件,支持模式匹配
|
||||||
- 获取详细的节点树用于调试
|
- **debug_system**: 系统调试 - 获取编辑器信息、性能统计、环境信息
|
||||||
- 性能统计和场景验证
|
|
||||||
- 获取编辑器和环境信息
|
|
||||||
|
|
||||||
### ⚙️ 其他功能
|
### 📁 资源管理 (asset_*)
|
||||||
- **偏好设置管理**: 获取/设置编辑器偏好和全局设置
|
- **asset_manage**: 资源管理 - 批量导入/删除资源、保存元数据、生成URL
|
||||||
- **服务器控制**: 服务器信息、项目详情和编辑器控制
|
- **asset_analyze**: 资源分析 - 获取依赖关系、导出资源清单
|
||||||
- **消息广播**: 监听和广播自定义消息
|
- **asset_system**: 资源系统 - 刷新资源、查询资源数据库状态
|
||||||
- **资源管理**: 创建、复制、移动、删除和查询资源
|
- **asset_query**: 资源查询 - 按类型/文件夹查询资源、获取详细信息
|
||||||
- **构建系统**: 项目构建和预览服务器控制
|
- **asset_operations**: 资源操作 - 创建/复制/移动/删除/保存/重新导入资源
|
||||||
- **参考图片管理**: 在场景视图中添加、删除和管理参考图片
|
|
||||||
- **场景视图控制**: 控制Gizmo工具、坐标系和视图模式
|
### ⚙️ 偏好设置 (preferences_*)
|
||||||
- **高级场景操作**: 撤销/重做、快照和高级节点操作
|
- **preferences_manage**: 偏好管理 - 获取/设置编辑器偏好设置
|
||||||
- **🆕 工具管理**: 选择性启用/禁用工具、保存配置和管理工具状态
|
- **preferences_global**: 全局设置 - 管理全局配置和系统设置
|
||||||
|
|
||||||
|
### 🌐 服务器与广播 (server_* / broadcast_*)
|
||||||
|
- **server_info**: 服务器信息 - 获取服务器状态、项目详情、环境信息
|
||||||
|
- **broadcast_message**: 消息广播 - 监听和广播自定义消息
|
||||||
|
|
||||||
|
### 🖼️ 参考图片 (referenceImage_*)
|
||||||
|
- **reference_image_manage**: 参考图片管理 - 添加/删除/管理场景视图中的参考图片
|
||||||
|
- **reference_image_view**: 参考图片视图 - 控制参考图片的显示和编辑
|
||||||
|
|
||||||
|
### 🎨 场景视图 (sceneView_*)
|
||||||
|
- **scene_view_control**: 场景视图控制 - 控制Gizmo工具、坐标系、视图模式
|
||||||
|
- **scene_view_tools**: 场景视图工具 - 管理场景视图的各种工具和选项
|
||||||
|
|
||||||
|
### ✅ 验证工具 (validation_*)
|
||||||
|
- **validation_scene**: 场景验证 - 验证场景完整性、检查缺失资源
|
||||||
|
- **validation_asset**: 资源验证 - 验证资源引用、检查资源完整性
|
||||||
|
|
||||||
|
### 🛠️ 工具管理
|
||||||
|
- **工具配置系统**: 选择性启用/禁用工具,支持多套配置
|
||||||
|
- **配置持久化**: 自动保存和加载工具配置
|
||||||
|
- **配置导入导出**: 支持工具配置的导入导出功能
|
||||||
|
- **实时状态管理**: 工具状态实时更新和同步
|
||||||
|
|
||||||
|
### 🚀 核心优势
|
||||||
|
- **操作码统一**: 所有工具采用"类别_操作"命名,参数Schema统一
|
||||||
|
- **高复用性**: 50个核心工具覆盖99%编辑器功能
|
||||||
|
- **AI友好**: 参数清晰、文档完善、调用简单
|
||||||
|
- **性能优化**: 降低50% token消耗,提升AI调用成功率
|
||||||
|
- **完全兼容**: 与Cocos Creator官方API 100%对齐
|
||||||
|
|
||||||
## 安装说明
|
## 安装说明
|
||||||
|
|
||||||
### 1. 复制插件文件
|
### 1. 复制插件文件
|
||||||
|
|
||||||
将整个 `cocos-mcp-server` 文件夹复制到您的 Cocos Creator 项目的 `extensions` 目录中:
|
将整个 `cocos-mcp-server` 文件夹复制到您的 Cocos Creator 项目的 `extensions` 目录中,您也可以直接在扩展管理器中导入项目:
|
||||||
|
|
||||||
```
|
```
|
||||||
您的项目/
|
您的项目/
|
||||||
@@ -255,117 +320,6 @@ npm run build
|
|||||||
|
|
||||||
AI 助手可以使用 MCP 协议连接并访问所有可用工具。
|
AI 助手可以使用 MCP 协议连接并访问所有可用工具。
|
||||||
|
|
||||||
### 工具分类
|
|
||||||
|
|
||||||
工具按类别组织,命名约定为:`category_toolname`
|
|
||||||
|
|
||||||
- **scene_\***: 场景相关操作 (8个工具)
|
|
||||||
- **node_\***: 节点操作 (9个工具)
|
|
||||||
- **component_\***: 组件管理 (7个工具)
|
|
||||||
- **prefab_\***: 预制体操作 (11个工具)
|
|
||||||
- **project_\***: 项目控制 (22个工具)
|
|
||||||
- **debug_\***: 调试工具 (10个工具)
|
|
||||||
- **preferences_\***: 编辑器偏好设置 (7个工具)
|
|
||||||
- **server_\***: 服务器信息 (6个工具)
|
|
||||||
- **broadcast_\***: 消息广播 (5个工具)
|
|
||||||
- **assetAdvanced_\***: 高级资源操作 (10个工具)
|
|
||||||
- **referenceImage_\***: 参考图片管理 (12个工具)
|
|
||||||
- **sceneAdvanced_\***: 高级场景操作 (23个工具)
|
|
||||||
- **sceneView_\***: 场景视图控制 (14个工具)
|
|
||||||
|
|
||||||
|
|
||||||
📖 **[查看完整工具文档](FEATURE_GUIDE_CN.md)** 了解详细的使用示例和参数。
|
|
||||||
|
|
||||||
## 工具使用示例
|
|
||||||
|
|
||||||
### 创建新的精灵节点
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "node_create_node",
|
|
||||||
"arguments": {
|
|
||||||
"name": "MySprite",
|
|
||||||
"nodeType": "2DNode",
|
|
||||||
"parentUuid": "parent-node-uuid"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 添加 Sprite 组件
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "component_add_component",
|
|
||||||
"arguments": {
|
|
||||||
"nodeUuid": "node-uuid",
|
|
||||||
"componentType": "cc.Sprite"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 实例化预制体
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "prefab_instantiate_prefab",
|
|
||||||
"arguments": {
|
|
||||||
"prefabPath": "db://assets/prefabs/Enemy.prefab",
|
|
||||||
"position": { "x": 100, "y": 200, "z": 0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 在浏览器中运行项目
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"tool": "project_run_project",
|
|
||||||
"arguments": {
|
|
||||||
"platform": "browser"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 配置
|
|
||||||
|
|
||||||
设置存储在 `您的项目/settings/mcp-server.json` 中:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"port": 3000,
|
|
||||||
"autoStart": false,
|
|
||||||
"enableDebugLog": true,
|
|
||||||
"allowedOrigins": ["*"],
|
|
||||||
"maxConnections": 10
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
工具配置存储在 `您的项目/settings/tool-manager.json` 中:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"currentConfigId": "default",
|
|
||||||
"configurations": {
|
|
||||||
"default": {
|
|
||||||
"id": "default",
|
|
||||||
"name": "默认配置",
|
|
||||||
"description": "默认工具配置",
|
|
||||||
"tools": [
|
|
||||||
{
|
|
||||||
"category": "scene",
|
|
||||||
"name": "get_current_scene",
|
|
||||||
"enabled": true,
|
|
||||||
"description": "获取当前场景信息"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 图标设置
|
|
||||||
|
|
||||||
为插件面板添加图标:
|
|
||||||
|
|
||||||
1. 创建 PNG 图标文件(推荐尺寸:32x32 或 64x64)
|
|
||||||
2. 将其放在 `static/` 目录中:`static/icon.png`
|
|
||||||
3. 图标路径已在 `package.json`
|
|
||||||
|
|
||||||
## 开发
|
## 开发
|
||||||
|
|
||||||
@@ -387,7 +341,7 @@ cocos-mcp-server/
|
|||||||
│ │ ├── preferences-tools.ts
|
│ │ ├── preferences-tools.ts
|
||||||
│ │ ├── server-tools.ts
|
│ │ ├── server-tools.ts
|
||||||
│ │ ├── broadcast-tools.ts
|
│ │ ├── broadcast-tools.ts
|
||||||
│ │ ├── scene-advanced-tools.ts
|
│ │ ├── scene-advanced-tools.ts (已整合到 node-tools.ts 和 scene-tools.ts)
|
||||||
│ │ ├── scene-view-tools.ts
|
│ │ ├── scene-view-tools.ts
|
||||||
│ │ ├── reference-image-tools.ts
|
│ │ ├── reference-image-tools.ts
|
||||||
│ │ └── asset-advanced-tools.ts
|
│ │ └── asset-advanced-tools.ts
|
||||||
@@ -468,7 +422,6 @@ npm run build
|
|||||||
本插件供 Cocos Creator 项目使用,并且源代码一并打包,可以用于学习和交流。没有加密。可以支持你自己二次开发优化,任何本项目代码或者衍生代码均不能用于任何商用、转售,如果需要商用,请联系本人。
|
本插件供 Cocos Creator 项目使用,并且源代码一并打包,可以用于学习和交流。没有加密。可以支持你自己二次开发优化,任何本项目代码或者衍生代码均不能用于任何商用、转售,如果需要商用,请联系本人。
|
||||||
|
|
||||||
## 联系我加入群
|
## 联系我加入群
|
||||||
<img src="https://github.com/user-attachments/assets/2e3f043a-0b03-4b27-a175-e9c31fbed981" style="max-width: 400px; border-radius: 8px;"/>
|
<img alt="image" src="https://github.com/user-attachments/assets/a276682c-4586-480c-90e5-6db132e89e0f" width="400" height="400" />
|
||||||
|
|
||||||
<img src="https://github.com/user-attachments/assets/5ef6172c-2968-499e-9edf-7da133016cd2" style="max-width: 400px; border-radius: 8px;" />
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,230 +0,0 @@
|
|||||||
const http = require('http');
|
|
||||||
|
|
||||||
const SERVER_URL = 'http://localhost:8585';
|
|
||||||
|
|
||||||
class MCPTester {
|
|
||||||
constructor() {
|
|
||||||
this.testResults = [];
|
|
||||||
this.currentCategory = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
async makeRequest(toolName, args = {}) {
|
|
||||||
const payload = {
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
id: Date.now(),
|
|
||||||
method: 'tools/call',
|
|
||||||
params: {
|
|
||||||
name: toolName,
|
|
||||||
arguments: args
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const data = JSON.stringify(payload);
|
|
||||||
const options = {
|
|
||||||
hostname: '127.0.0.1',
|
|
||||||
port: 8585,
|
|
||||||
path: '/mcp',
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Content-Length': data.length
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const req = http.request(options, (res) => {
|
|
||||||
let responseData = '';
|
|
||||||
res.on('data', chunk => responseData += chunk);
|
|
||||||
res.on('end', () => {
|
|
||||||
try {
|
|
||||||
const response = JSON.parse(responseData);
|
|
||||||
resolve(response);
|
|
||||||
} catch (e) {
|
|
||||||
reject(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
req.on('error', reject);
|
|
||||||
req.write(data);
|
|
||||||
req.end();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async testTool(toolName, args = {}, description = '') {
|
|
||||||
const testName = description || toolName.replace(/_/g, ' ');
|
|
||||||
process.stdout.write(` ${testName}... `);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await this.makeRequest(toolName, args);
|
|
||||||
|
|
||||||
if (response.result && response.result.success !== false) {
|
|
||||||
console.log('✅ 通过');
|
|
||||||
this.testResults.push({ tool: toolName, status: 'pass', category: this.currentCategory });
|
|
||||||
return response.result;
|
|
||||||
} else {
|
|
||||||
const error = response.result?.error || response.error?.message || 'Unknown error';
|
|
||||||
console.log(`❌ 失败: ${error}`);
|
|
||||||
this.testResults.push({ tool: toolName, status: 'fail', error, category: this.currentCategory });
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`❌ 错误: ${error.message}`);
|
|
||||||
this.testResults.push({ tool: toolName, status: 'error', error: error.message, category: this.currentCategory });
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
printCategory(categoryName) {
|
|
||||||
this.currentCategory = categoryName;
|
|
||||||
console.log(`\n📁 ${categoryName}:`);
|
|
||||||
}
|
|
||||||
|
|
||||||
printSummary() {
|
|
||||||
console.log('\n' + '='.repeat(60));
|
|
||||||
console.log('📊 测试结果汇总:');
|
|
||||||
console.log('='.repeat(60));
|
|
||||||
|
|
||||||
const categories = [...new Set(this.testResults.map(r => r.category))];
|
|
||||||
|
|
||||||
for (const category of categories) {
|
|
||||||
const categoryResults = this.testResults.filter(r => r.category === category);
|
|
||||||
const passed = categoryResults.filter(r => r.status === 'pass').length;
|
|
||||||
const failed = categoryResults.filter(r => r.status === 'fail').length;
|
|
||||||
const errors = categoryResults.filter(r => r.status === 'error').length;
|
|
||||||
|
|
||||||
console.log(`\n${category}:`);
|
|
||||||
console.log(` ✅ 通过: ${passed}`);
|
|
||||||
console.log(` ❌ 失败: ${failed}`);
|
|
||||||
console.log(` ⚠️ 错误: ${errors}`);
|
|
||||||
console.log(` 📊 总计: ${categoryResults.length}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalPassed = this.testResults.filter(r => r.status === 'pass').length;
|
|
||||||
const totalFailed = this.testResults.filter(r => r.status === 'fail').length;
|
|
||||||
const totalErrors = this.testResults.filter(r => r.status === 'error').length;
|
|
||||||
const total = this.testResults.length;
|
|
||||||
|
|
||||||
console.log(`\n总体结果:`);
|
|
||||||
console.log(` ✅ 通过: ${totalPassed}/${total} (${((totalPassed/total)*100).toFixed(1)}%)`);
|
|
||||||
console.log(` ❌ 失败: ${totalFailed}/${total} (${((totalFailed/total)*100).toFixed(1)}%)`);
|
|
||||||
console.log(` ⚠️ 错误: ${totalErrors}/${total} (${((totalErrors/total)*100).toFixed(1)}%)`);
|
|
||||||
|
|
||||||
// 显示失败的工具
|
|
||||||
const failedTools = this.testResults.filter(r => r.status === 'fail' || r.status === 'error');
|
|
||||||
if (failedTools.length > 0) {
|
|
||||||
console.log('\n❌ 失败的工具:');
|
|
||||||
failedTools.forEach(tool => {
|
|
||||||
console.log(` - ${tool.tool}: ${tool.error}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async runAllTests() {
|
|
||||||
console.log('🚀 开始全面测试 Cocos MCP 工具...\n');
|
|
||||||
|
|
||||||
// 1. 场景管理工具
|
|
||||||
this.printCategory('场景管理');
|
|
||||||
await this.testTool('scene_create_scene', {
|
|
||||||
sceneName: 'TestScene2',
|
|
||||||
savePath: 'db://assets/scenes/TestScene2.scene'
|
|
||||||
}, '创建场景');
|
|
||||||
await this.testTool('scene_get_current_scene', {}, '获取当前场景');
|
|
||||||
await this.testTool('scene_save_scene', {}, '保存场景');
|
|
||||||
await this.testTool('scene_get_scene_list', {}, '获取场景列表');
|
|
||||||
await this.testTool('scene_get_scene_hierarchy', {}, '获取场景层次结构');
|
|
||||||
|
|
||||||
// 2. 节点操作工具
|
|
||||||
this.printCategory('节点操作');
|
|
||||||
const nodeResult = await this.testTool('node_create_node', { name: 'TestNode' }, '创建节点');
|
|
||||||
let testNodeUuid = null;
|
|
||||||
if (nodeResult && nodeResult.data && nodeResult.data.uuid) {
|
|
||||||
testNodeUuid = nodeResult.data.uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.testTool('node_get_all_nodes', {}, '获取所有节点');
|
|
||||||
await this.testTool('node_find_node_by_name', { name: 'TestNode' }, '按名称查找节点');
|
|
||||||
|
|
||||||
if (testNodeUuid) {
|
|
||||||
await this.testTool('node_get_node_info', { uuid: testNodeUuid }, '获取节点信息');
|
|
||||||
await this.testTool('node_set_node_property', {
|
|
||||||
uuid: testNodeUuid,
|
|
||||||
property: 'position',
|
|
||||||
value: { x: 100, y: 100, z: 0 }
|
|
||||||
}, '设置节点属性');
|
|
||||||
await this.testTool('node_duplicate_node', { uuid: testNodeUuid }, '复制节点');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 组件管理工具
|
|
||||||
this.printCategory('组件管理');
|
|
||||||
if (testNodeUuid) {
|
|
||||||
await this.testTool('component_add_component', {
|
|
||||||
nodeUuid: testNodeUuid,
|
|
||||||
componentType: 'cc.Sprite'
|
|
||||||
}, '添加组件');
|
|
||||||
await this.testTool('component_get_components', { nodeUuid: testNodeUuid }, '获取组件列表');
|
|
||||||
await this.testTool('component_get_component_info', {
|
|
||||||
nodeUuid: testNodeUuid,
|
|
||||||
componentType: 'cc.Sprite'
|
|
||||||
}, '获取组件信息');
|
|
||||||
}
|
|
||||||
await this.testTool('component_get_available_components', {}, '获取可用组件');
|
|
||||||
|
|
||||||
// 4. 预制体工具
|
|
||||||
this.printCategory('预制体管理');
|
|
||||||
if (testNodeUuid) {
|
|
||||||
await this.testTool('prefab_create_prefab', {
|
|
||||||
nodeUuid: testNodeUuid,
|
|
||||||
prefabPath: 'db://assets/prefabs/TestPrefab.prefab'
|
|
||||||
}, '创建预制体');
|
|
||||||
}
|
|
||||||
await this.testTool('prefab_get_prefab_list', {}, '获取预制体列表');
|
|
||||||
await this.testTool('prefab_instantiate_prefab', {
|
|
||||||
prefabPath: 'db://assets/prefabs/TestPrefab.prefab'
|
|
||||||
}, '实例化预制体');
|
|
||||||
|
|
||||||
// 5. 项目和资源管理
|
|
||||||
this.printCategory('项目资源管理');
|
|
||||||
await this.testTool('project_get_project_info', {}, '获取项目信息');
|
|
||||||
await this.testTool('project_get_project_settings', {}, '获取项目设置');
|
|
||||||
await this.testTool('project_get_assets', { type: 'all' }, '获取资源列表');
|
|
||||||
await this.testTool('project_refresh_assets', {}, '刷新资源');
|
|
||||||
await this.testTool('project_create_asset', {
|
|
||||||
url: 'db://assets/test-folder',
|
|
||||||
content: null
|
|
||||||
}, '创建资源文件夹');
|
|
||||||
|
|
||||||
// 6. 调试工具
|
|
||||||
this.printCategory('调试工具');
|
|
||||||
await this.testTool('debug_get_console_logs', {}, '获取控制台日志');
|
|
||||||
await this.testTool('debug_get_performance_stats', {}, '获取性能统计');
|
|
||||||
await this.testTool('debug_validate_scene', {}, '验证场景');
|
|
||||||
await this.testTool('debug_get_editor_info', {}, '获取编辑器信息');
|
|
||||||
|
|
||||||
// 7. 偏好设置工具
|
|
||||||
this.printCategory('偏好设置');
|
|
||||||
await this.testTool('preferences_get_preferences', {}, '获取偏好设置');
|
|
||||||
await this.testTool('preferences_get_global_preferences', {}, '获取全局偏好设置');
|
|
||||||
await this.testTool('preferences_get_recent_projects', {}, '获取最近项目');
|
|
||||||
|
|
||||||
// 8. 服务器控制工具
|
|
||||||
this.printCategory('服务器控制');
|
|
||||||
await this.testTool('server_get_server_info', {}, '获取服务器信息');
|
|
||||||
await this.testTool('server_get_editor_version', {}, '获取编辑器版本');
|
|
||||||
|
|
||||||
// 9. 广播消息工具
|
|
||||||
this.printCategory('广播消息');
|
|
||||||
await this.testTool('broadcast_get_broadcast_log', {}, '获取广播日志');
|
|
||||||
|
|
||||||
// 清理测试节点
|
|
||||||
if (testNodeUuid) {
|
|
||||||
await this.testTool('node_delete_node', { uuid: testNodeUuid }, '删除测试节点');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.printSummary();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 运行测试
|
|
||||||
const tester = new MCPTester();
|
|
||||||
tester.runAllTests().catch(console.error);
|
|
||||||
46
debug-api.js
46
debug-api.js
@@ -1,46 +0,0 @@
|
|||||||
// 测试可用的 Editor API
|
|
||||||
const testMethods = [
|
|
||||||
'scene.query-node-tree',
|
|
||||||
'scene.create-node',
|
|
||||||
'scene.remove-node',
|
|
||||||
'scene.set-property',
|
|
||||||
'scene.create-component',
|
|
||||||
'scene.remove-component',
|
|
||||||
'scene.add-component',
|
|
||||||
'scene.query-node',
|
|
||||||
'scene.query-scene',
|
|
||||||
'scene.query-hierarchy'
|
|
||||||
];
|
|
||||||
|
|
||||||
async function testAPI() {
|
|
||||||
console.log('Testing available Editor API methods...');
|
|
||||||
|
|
||||||
for (const method of testMethods) {
|
|
||||||
console.log(`\nTesting: ${method}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch('http://localhost:8585/mcp', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({
|
|
||||||
jsonrpc: '2.0',
|
|
||||||
id: 1,
|
|
||||||
method: 'tools/call',
|
|
||||||
params: {
|
|
||||||
name: 'debug_test_editor_api',
|
|
||||||
arguments: {
|
|
||||||
method: method.replace('.', ' - ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const data = await response.json();
|
|
||||||
console.log(`Response: ${JSON.stringify(data)}`);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(`Error: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
testAPI();
|
|
||||||
2
dist/main.js
vendored
2
dist/main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/mcp-server.js
vendored
2
dist/mcp-server.js
vendored
File diff suppressed because one or more lines are too long
2
dist/panels/default/index.js
vendored
2
dist/panels/default/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/panels/tool-manager/index.js
vendored
2
dist/panels/tool-manager/index.js
vendored
File diff suppressed because one or more lines are too long
2
dist/scene.js
vendored
2
dist/scene.js
vendored
File diff suppressed because one or more lines are too long
2
dist/settings.js
vendored
2
dist/settings.js
vendored
File diff suppressed because one or more lines are too long
2
dist/test/manual-test.js
vendored
2
dist/test/manual-test.js
vendored
File diff suppressed because one or more lines are too long
2
dist/test/mcp-tool-tester.js
vendored
2
dist/test/mcp-tool-tester.js
vendored
File diff suppressed because one or more lines are too long
2
dist/test/prefab-tools-test.js
vendored
2
dist/test/prefab-tools-test.js
vendored
File diff suppressed because one or more lines are too long
2
dist/test/tool-tester.js
vendored
2
dist/test/tool-tester.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/asset-advanced-tools.js
vendored
2
dist/tools/asset-advanced-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/broadcast-tools.js
vendored
2
dist/tools/broadcast-tools.js
vendored
File diff suppressed because one or more lines are too long
879
dist/tools/component-tools.js
vendored
879
dist/tools/component-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/debug-tools.js
vendored
2
dist/tools/debug-tools.js
vendored
File diff suppressed because one or more lines are too long
355
dist/tools/node-tools.js
vendored
355
dist/tools/node-tools.js
vendored
File diff suppressed because one or more lines are too long
1586
dist/tools/prefab-tools.js
vendored
1586
dist/tools/prefab-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/preferences-tools.js
vendored
2
dist/tools/preferences-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/project-tools.js
vendored
2
dist/tools/project-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/reference-image-tools.js
vendored
2
dist/tools/reference-image-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/scene-advanced-tools.js
vendored
2
dist/tools/scene-advanced-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/scene-tools.js
vendored
2
dist/tools/scene-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/scene-view-tools.js
vendored
2
dist/tools/scene-view-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/server-tools.js
vendored
2
dist/tools/server-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/tool-manager.js
vendored
2
dist/tools/tool-manager.js
vendored
File diff suppressed because one or more lines are too long
2
dist/tools/validation-tools.js
vendored
2
dist/tools/validation-tools.js
vendored
File diff suppressed because one or more lines are too long
2
dist/types/index.js
vendored
2
dist/types/index.js
vendored
File diff suppressed because one or more lines are too long
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cocos-mcp-server",
|
"name": "cocos-mcp-server",
|
||||||
"version": "1.0.0",
|
"version": "1.4.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cocos-mcp-server",
|
"name": "cocos-mcp-server",
|
||||||
"version": "1.0.0",
|
"version": "1.4.0",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fs-extra": "^11.3.0",
|
"fs-extra": "^11.3.0",
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
"$schema": "./@types/schema/package/index.json",
|
"$schema": "./@types/schema/package/index.json",
|
||||||
"package_version": 2,
|
"package_version": 2,
|
||||||
"name": "cocos-mcp-server",
|
"name": "cocos-mcp-server",
|
||||||
"version": "1.0.0",
|
"version": "1.4.0",
|
||||||
"author": "Cocos Creator",
|
"author": "LiDaxian",
|
||||||
"editor": ">=3.8.6",
|
"editor": ">=3.8.6",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "node ./scripts/preinstall.js",
|
"preinstall": "node ./scripts/preinstall.js",
|
||||||
|
|||||||
@@ -1,308 +0,0 @@
|
|||||||
import { PrefabTools } from '../tools/prefab-tools';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 预制体实例化使用示例
|
|
||||||
* 展示如何在实际项目中使用预制体工具
|
|
||||||
*/
|
|
||||||
export class PrefabInstantiationExample {
|
|
||||||
private prefabTools: PrefabTools;
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.prefabTools = new PrefabTools();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例1: 基本预制体实例化
|
|
||||||
*/
|
|
||||||
async basicInstantiationExample() {
|
|
||||||
console.log('=== 基本预制体实例化示例 ===');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await this.prefabTools.execute('instantiate_prefab', {
|
|
||||||
prefabPath: 'db://assets/prefabs/Player.prefab',
|
|
||||||
position: { x: 0, y: 0, z: 0 }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
console.log('✅ 预制体实例化成功');
|
|
||||||
console.log(`节点UUID: ${result.data.nodeUuid}`);
|
|
||||||
console.log(`节点名称: ${result.data.name}`);
|
|
||||||
console.log('使用的API: create-node with assetUuid');
|
|
||||||
} else {
|
|
||||||
console.log('❌ 预制体实例化失败');
|
|
||||||
console.log(`错误: ${result.error}`);
|
|
||||||
if (result.instruction) {
|
|
||||||
console.log(`建议: ${result.instruction}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('实例化过程中发生错误:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例2: 在指定父节点下实例化预制体
|
|
||||||
*/
|
|
||||||
async instantiateWithParentExample() {
|
|
||||||
console.log('=== 在父节点下实例化预制体示例 ===');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await this.prefabTools.execute('instantiate_prefab', {
|
|
||||||
prefabPath: 'db://assets/prefabs/Enemy.prefab',
|
|
||||||
parentUuid: 'canvas-uuid-here',
|
|
||||||
position: { x: 100, y: 200, z: 0 }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
console.log('✅ 在父节点下实例化成功');
|
|
||||||
console.log(`节点UUID: ${result.data.nodeUuid}`);
|
|
||||||
} else {
|
|
||||||
console.log('❌ 实例化失败');
|
|
||||||
console.log(`错误: ${result.error}`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('实例化过程中发生错误:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例3: 批量实例化预制体
|
|
||||||
*/
|
|
||||||
async batchInstantiationExample() {
|
|
||||||
console.log('=== 批量实例化预制体示例 ===');
|
|
||||||
|
|
||||||
const prefabPaths = [
|
|
||||||
'db://assets/prefabs/Item1.prefab',
|
|
||||||
'db://assets/prefabs/Item2.prefab',
|
|
||||||
'db://assets/prefabs/Item3.prefab'
|
|
||||||
];
|
|
||||||
|
|
||||||
const positions = [
|
|
||||||
{ x: 0, y: 0, z: 0 },
|
|
||||||
{ x: 100, y: 0, z: 0 },
|
|
||||||
{ x: 200, y: 0, z: 0 }
|
|
||||||
];
|
|
||||||
|
|
||||||
const results = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < prefabPaths.length; i++) {
|
|
||||||
try {
|
|
||||||
const result = await this.prefabTools.execute('instantiate_prefab', {
|
|
||||||
prefabPath: prefabPaths[i],
|
|
||||||
position: positions[i]
|
|
||||||
});
|
|
||||||
|
|
||||||
results.push({
|
|
||||||
index: i,
|
|
||||||
prefabPath: prefabPaths[i],
|
|
||||||
success: result.success,
|
|
||||||
data: result.data,
|
|
||||||
error: result.error
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
console.log(`✅ 预制体 ${i + 1} 实例化成功`);
|
|
||||||
} else {
|
|
||||||
console.log(`❌ 预制体 ${i + 1} 实例化失败: ${result.error}`);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`预制体 ${i + 1} 实例化时发生错误:`, error);
|
|
||||||
results.push({
|
|
||||||
index: i,
|
|
||||||
prefabPath: prefabPaths[i],
|
|
||||||
success: false,
|
|
||||||
error: error instanceof Error ? error.message : String(error)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const successCount = results.filter(r => r.success).length;
|
|
||||||
console.log(`批量实例化完成: ${successCount}/${results.length} 成功`);
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例4: 错误处理和重试机制
|
|
||||||
*/
|
|
||||||
async instantiationWithRetryExample() {
|
|
||||||
console.log('=== 带重试机制的实例化示例 ===');
|
|
||||||
|
|
||||||
const maxRetries = 3;
|
|
||||||
let attempt = 0;
|
|
||||||
|
|
||||||
while (attempt < maxRetries) {
|
|
||||||
try {
|
|
||||||
const result = await this.prefabTools.execute('instantiate_prefab', {
|
|
||||||
prefabPath: 'db://assets/prefabs/ComplexPrefab.prefab',
|
|
||||||
position: { x: 0, y: 0, z: 0 }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (result.success) {
|
|
||||||
console.log(`✅ 预制体实例化成功 (尝试 ${attempt + 1})`);
|
|
||||||
return result;
|
|
||||||
} else {
|
|
||||||
console.log(`❌ 尝试 ${attempt + 1} 失败: ${result.error}`);
|
|
||||||
attempt++;
|
|
||||||
|
|
||||||
if (attempt < maxRetries) {
|
|
||||||
console.log(`等待 1 秒后重试...`);
|
|
||||||
await this.delay(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`尝试 ${attempt + 1} 时发生错误:`, error);
|
|
||||||
attempt++;
|
|
||||||
|
|
||||||
if (attempt < maxRetries) {
|
|
||||||
console.log(`等待 1 秒后重试...`);
|
|
||||||
await this.delay(1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('❌ 所有重试都失败了');
|
|
||||||
return { success: false, error: '达到最大重试次数' };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例5: 预制体实例化前的验证
|
|
||||||
*/
|
|
||||||
async instantiationWithValidationExample() {
|
|
||||||
console.log('=== 带验证的实例化示例 ===');
|
|
||||||
|
|
||||||
const prefabPath = 'db://assets/prefabs/ValidatedPrefab.prefab';
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 首先验证预制体
|
|
||||||
const validationResult = await this.prefabTools.execute('validate_prefab', {
|
|
||||||
prefabPath: prefabPath
|
|
||||||
});
|
|
||||||
|
|
||||||
if (validationResult.success && validationResult.data.isValid) {
|
|
||||||
console.log('✅ 预制体验证通过');
|
|
||||||
console.log(`节点数量: ${validationResult.data.nodeCount}`);
|
|
||||||
console.log(`组件数量: ${validationResult.data.componentCount}`);
|
|
||||||
|
|
||||||
// 验证通过后实例化
|
|
||||||
const instantiationResult = await this.prefabTools.execute('instantiate_prefab', {
|
|
||||||
prefabPath: prefabPath,
|
|
||||||
position: { x: 0, y: 0, z: 0 }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (instantiationResult.success) {
|
|
||||||
console.log('✅ 预制体实例化成功');
|
|
||||||
return instantiationResult;
|
|
||||||
} else {
|
|
||||||
console.log('❌ 预制体实例化失败:', instantiationResult.error);
|
|
||||||
return instantiationResult;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('❌ 预制体验证失败');
|
|
||||||
if (validationResult.data && validationResult.data.issues) {
|
|
||||||
console.log('问题列表:');
|
|
||||||
validationResult.data.issues.forEach((issue: string, index: number) => {
|
|
||||||
console.log(` ${index + 1}. ${issue}`);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return validationResult;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('验证和实例化过程中发生错误:', error);
|
|
||||||
return { success: false, error: error instanceof Error ? error.message : String(error) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 示例6: API参数构建示例
|
|
||||||
*/
|
|
||||||
demonstrateAPIParameters() {
|
|
||||||
console.log('=== API参数构建示例 ===');
|
|
||||||
|
|
||||||
// 模拟从asset-db获取的预制体信息
|
|
||||||
const assetInfo = {
|
|
||||||
uuid: 'prefab-uuid-123',
|
|
||||||
name: 'PlayerCharacter'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 基本实例化参数
|
|
||||||
const basicOptions = {
|
|
||||||
assetUuid: assetInfo.uuid,
|
|
||||||
name: assetInfo.name
|
|
||||||
};
|
|
||||||
console.log('基本实例化参数:', JSON.stringify(basicOptions, null, 2));
|
|
||||||
|
|
||||||
// 带父节点的实例化参数
|
|
||||||
const withParentOptions = {
|
|
||||||
assetUuid: assetInfo.uuid,
|
|
||||||
name: assetInfo.name,
|
|
||||||
parent: 'canvas-uuid-456'
|
|
||||||
};
|
|
||||||
console.log('带父节点参数:', JSON.stringify(withParentOptions, null, 2));
|
|
||||||
|
|
||||||
// 带位置设置的实例化参数
|
|
||||||
const withPositionOptions = {
|
|
||||||
assetUuid: assetInfo.uuid,
|
|
||||||
name: assetInfo.name,
|
|
||||||
dump: {
|
|
||||||
position: { x: 100, y: 200, z: 0 }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
console.log('带位置参数:', JSON.stringify(withPositionOptions, null, 2));
|
|
||||||
|
|
||||||
// 完整实例化参数
|
|
||||||
const fullOptions = {
|
|
||||||
assetUuid: assetInfo.uuid,
|
|
||||||
name: assetInfo.name,
|
|
||||||
parent: 'canvas-uuid-456',
|
|
||||||
dump: {
|
|
||||||
position: { x: 100, y: 200, z: 0 }
|
|
||||||
},
|
|
||||||
keepWorldTransform: false,
|
|
||||||
unlinkPrefab: false
|
|
||||||
};
|
|
||||||
console.log('完整参数:', JSON.stringify(fullOptions, null, 2));
|
|
||||||
|
|
||||||
console.log('这些参数将传递给 Editor.Message.request("scene", "create-node", options)');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 延迟函数
|
|
||||||
*/
|
|
||||||
private delay(ms: number): Promise<void> {
|
|
||||||
return new Promise(resolve => setTimeout(resolve, ms));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 运行所有示例
|
|
||||||
*/
|
|
||||||
async runAllExamples() {
|
|
||||||
console.log('🚀 开始运行预制体实例化示例...\n');
|
|
||||||
|
|
||||||
await this.basicInstantiationExample();
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
await this.instantiateWithParentExample();
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
await this.batchInstantiationExample();
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
await this.instantiationWithRetryExample();
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
await this.instantiationWithValidationExample();
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
this.demonstrateAPIParameters();
|
|
||||||
console.log('');
|
|
||||||
|
|
||||||
console.log('🎉 所有示例运行完成!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果直接运行此文件
|
|
||||||
if (typeof module !== 'undefined' && module.exports) {
|
|
||||||
const example = new PrefabInstantiationExample();
|
|
||||||
example.runAllExamples();
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,13 @@
|
|||||||
import { ToolDefinition, ToolResponse, ToolExecutor, NodeInfo } from '../types';
|
import { ToolDefinition, ToolResponse, ToolExecutor, NodeInfo } from '../types';
|
||||||
|
import { ComponentTools } from './component-tools';
|
||||||
|
|
||||||
export class NodeTools implements ToolExecutor {
|
export class NodeTools implements ToolExecutor {
|
||||||
|
private componentTools = new ComponentTools();
|
||||||
getTools(): ToolDefinition[] {
|
getTools(): ToolDefinition[] {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
name: 'create_node',
|
name: 'create_node',
|
||||||
description: 'Create a new node in the scene. IMPORTANT: You should always provide parentUuid to specify where to create the node. If parentUuid is not provided, the node will be created at the scene root.',
|
description: 'Create a new node in the scene. Supports creating empty nodes, nodes with components, or instantiating from assets (prefabs, etc.). IMPORTANT: You should always provide parentUuid to specify where to create the node.',
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@@ -27,6 +29,59 @@ export class NodeTools implements ToolExecutor {
|
|||||||
type: 'number',
|
type: 'number',
|
||||||
description: 'Sibling index for ordering (-1 means append at end)',
|
description: 'Sibling index for ordering (-1 means append at end)',
|
||||||
default: -1
|
default: -1
|
||||||
|
},
|
||||||
|
assetUuid: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Asset UUID to instantiate from (e.g., prefab UUID). When provided, creates a node instance from the asset instead of an empty node.'
|
||||||
|
},
|
||||||
|
assetPath: {
|
||||||
|
type: 'string',
|
||||||
|
description: 'Asset path to instantiate from (e.g., "db://assets/prefabs/MyPrefab.prefab"). Alternative to assetUuid.'
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
type: 'array',
|
||||||
|
items: { type: 'string' },
|
||||||
|
description: 'Array of component type names to add to the new node (e.g., ["cc.Sprite", "cc.Button"])'
|
||||||
|
},
|
||||||
|
unlinkPrefab: {
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'If true and creating from prefab, unlink from prefab to create a regular node',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
keepWorldTransform: {
|
||||||
|
type: 'boolean',
|
||||||
|
description: 'Whether to keep world transform when creating the node',
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
initialTransform: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
position: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
x: { type: 'number' },
|
||||||
|
y: { type: 'number' },
|
||||||
|
z: { type: 'number' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rotation: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
x: { type: 'number' },
|
||||||
|
y: { type: 'number' },
|
||||||
|
z: { type: 'number' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scale: {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
x: { type: 'number' },
|
||||||
|
y: { type: 'number' },
|
||||||
|
z: { type: 'number' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
description: 'Initial transform to apply to the created node'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
required: ['name']
|
required: ['name']
|
||||||
@@ -89,7 +144,7 @@ export class NodeTools implements ToolExecutor {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'set_node_property',
|
name: 'set_node_property',
|
||||||
description: 'Set node property value (prefer using set_node_transform for position/rotation/scale)',
|
description: 'Set node property value (prefer using set_node_transform for active/layer/mobility/position/rotation/scale)',
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
@@ -253,150 +308,190 @@ export class NodeTools implements ToolExecutor {
|
|||||||
|
|
||||||
private async createNode(args: any): Promise<ToolResponse> {
|
private async createNode(args: any): Promise<ToolResponse> {
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
let targetParentUuid = args.parentUuid;
|
try {
|
||||||
|
let targetParentUuid = args.parentUuid;
|
||||||
// 如果没有提供父节点UUID,获取场景根节点
|
|
||||||
if (!targetParentUuid) {
|
// 如果没有提供父节点UUID,获取场景根节点
|
||||||
try {
|
if (!targetParentUuid) {
|
||||||
const sceneInfo = await Editor.Message.request('scene', 'query-node-tree');
|
try {
|
||||||
if (sceneInfo && typeof sceneInfo === 'object' && !Array.isArray(sceneInfo) && Object.prototype.hasOwnProperty.call(sceneInfo, 'uuid')) {
|
const sceneInfo = await Editor.Message.request('scene', 'query-node-tree');
|
||||||
targetParentUuid = (sceneInfo as any).uuid;
|
if (sceneInfo && typeof sceneInfo === 'object' && !Array.isArray(sceneInfo) && Object.prototype.hasOwnProperty.call(sceneInfo, 'uuid')) {
|
||||||
console.log(`No parent specified, using scene root: ${targetParentUuid}`);
|
targetParentUuid = (sceneInfo as any).uuid;
|
||||||
} else if (Array.isArray(sceneInfo) && sceneInfo.length > 0 && sceneInfo[0].uuid) {
|
console.log(`No parent specified, using scene root: ${targetParentUuid}`);
|
||||||
// 如果返回的是数组,使用第一个元素(通常是场景根节点)
|
} else if (Array.isArray(sceneInfo) && sceneInfo.length > 0 && sceneInfo[0].uuid) {
|
||||||
targetParentUuid = sceneInfo[0].uuid;
|
targetParentUuid = sceneInfo[0].uuid;
|
||||||
console.log(`No parent specified, using scene root: ${targetParentUuid}`);
|
console.log(`No parent specified, using scene root: ${targetParentUuid}`);
|
||||||
} else {
|
} else {
|
||||||
// 备用方案:尝试获取当前场景
|
const currentScene = await Editor.Message.request('scene', 'query-current-scene');
|
||||||
const currentScene = await Editor.Message.request('scene', 'query-current-scene');
|
if (currentScene && currentScene.uuid) {
|
||||||
if (currentScene && currentScene.uuid) {
|
targetParentUuid = currentScene.uuid;
|
||||||
targetParentUuid = currentScene.uuid;
|
}
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Failed to get scene root, will use default behavior');
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
console.warn('Failed to get scene root, will use default behavior');
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 如果指定了父节点,先验证父节点是否存在
|
// 如果提供了assetPath,先解析为assetUuid
|
||||||
if (targetParentUuid) {
|
let finalAssetUuid = args.assetUuid;
|
||||||
try {
|
if (args.assetPath && !finalAssetUuid) {
|
||||||
const parentNode = await Editor.Message.request('scene', 'query-node', targetParentUuid);
|
try {
|
||||||
if (!parentNode) {
|
const assetInfo = await Editor.Message.request('asset-db', 'query-asset-info', args.assetPath);
|
||||||
|
if (assetInfo && assetInfo.uuid) {
|
||||||
|
finalAssetUuid = assetInfo.uuid;
|
||||||
|
console.log(`Asset path '${args.assetPath}' resolved to UUID: ${finalAssetUuid}`);
|
||||||
|
} else {
|
||||||
|
resolve({
|
||||||
|
success: false,
|
||||||
|
error: `Asset not found at path: ${args.assetPath}`
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
resolve({
|
resolve({
|
||||||
success: false,
|
success: false,
|
||||||
error: `Parent node with UUID '${targetParentUuid}' not found`
|
error: `Failed to resolve asset path '${args.assetPath}': ${err}`
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
|
||||||
resolve({
|
|
||||||
success: false,
|
|
||||||
error: `Failed to verify parent node: ${err}`
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const nodeData: any = {
|
// 构建create-node选项
|
||||||
name: args.name,
|
const createNodeOptions: any = {
|
||||||
type: args.nodeType || 'cc.Node'
|
name: args.name
|
||||||
};
|
|
||||||
|
|
||||||
// 使用正确的create-node API参数结构
|
|
||||||
if (targetParentUuid) {
|
|
||||||
const createNodeOptions = {
|
|
||||||
parent: targetParentUuid,
|
|
||||||
name: args.name,
|
|
||||||
components: args.nodeType && args.nodeType !== 'Node' ? [args.nodeType] : undefined
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Editor.Message.request('scene', 'create-node', createNodeOptions).then((nodeUuid: any) => {
|
// 设置父节点
|
||||||
// 如果需要设置特定的兄弟索引,使用set-parent API
|
if (targetParentUuid) {
|
||||||
// 添加延迟以避免内部状态竞争
|
createNodeOptions.parent = targetParentUuid;
|
||||||
if (args.siblingIndex !== undefined && args.siblingIndex >= 0 && nodeUuid) {
|
}
|
||||||
setTimeout(() => {
|
|
||||||
Editor.Message.request('scene', 'set-parent', {
|
// 从资源实例化
|
||||||
parent: targetParentUuid,
|
if (finalAssetUuid) {
|
||||||
uuids: [nodeUuid],
|
createNodeOptions.assetUuid = finalAssetUuid;
|
||||||
keepWorldTransform: false
|
if (args.unlinkPrefab) {
|
||||||
}).then(() => {
|
createNodeOptions.unlinkPrefab = true;
|
||||||
resolve({
|
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
uuid: nodeUuid,
|
|
||||||
name: args.name,
|
|
||||||
parentUuid: targetParentUuid,
|
|
||||||
message: args.parentUuid
|
|
||||||
? `Node '${args.name}' created under specified parent`
|
|
||||||
: `Node '${args.name}' created at scene root (no parent specified)`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
// 即使移动失败,节点已创建,返回成功但带警告
|
|
||||||
resolve({
|
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
uuid: nodeUuid,
|
|
||||||
name: args.name,
|
|
||||||
message: `Node '${args.name}' created but may not be under intended parent`,
|
|
||||||
warning: 'Failed to move node to specified parent'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, 100); // 100ms延迟
|
|
||||||
} else {
|
|
||||||
// Get complete node info for verification
|
|
||||||
this.getNodeInfo(nodeUuid).then((nodeInfo) => {
|
|
||||||
resolve({
|
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
uuid: nodeUuid,
|
|
||||||
name: args.name,
|
|
||||||
message: `Node '${args.name}' created successfully`
|
|
||||||
},
|
|
||||||
verificationData: {
|
|
||||||
nodeInfo: nodeInfo.data,
|
|
||||||
creationDetails: {
|
|
||||||
parentUuid: targetParentUuid,
|
|
||||||
nodeType: args.nodeType || 'Node',
|
|
||||||
timestamp: new Date().toISOString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).catch(() => {
|
|
||||||
resolve({
|
|
||||||
success: true,
|
|
||||||
data: {
|
|
||||||
uuid: nodeUuid,
|
|
||||||
name: args.name,
|
|
||||||
message: `Node '${args.name}' created successfully (verification failed)`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}).catch((err: Error) => {
|
}
|
||||||
resolve({ success: false, error: err.message });
|
|
||||||
});
|
// 添加组件
|
||||||
} else {
|
if (args.components && args.components.length > 0) {
|
||||||
// 没有找到场景根节点,使用默认行为(创建在场景根节点)
|
createNodeOptions.components = args.components;
|
||||||
const createNodeOptions = {
|
} else if (args.nodeType && args.nodeType !== 'Node' && !finalAssetUuid) {
|
||||||
name: args.name,
|
// 只有在不从资源实例化时才添加nodeType组件
|
||||||
components: args.nodeType && args.nodeType !== 'Node' ? [args.nodeType] : undefined
|
createNodeOptions.components = [args.nodeType];
|
||||||
};
|
}
|
||||||
|
|
||||||
Editor.Message.request('scene', 'create-node', createNodeOptions).then((result: any) => {
|
// 保持世界变换
|
||||||
resolve({
|
if (args.keepWorldTransform) {
|
||||||
success: true,
|
createNodeOptions.keepWorldTransform = true;
|
||||||
data: {
|
}
|
||||||
uuid: result,
|
|
||||||
name: args.name,
|
// 不使用dump参数处理初始变换,创建后使用set_node_transform设置
|
||||||
message: `Node '${args.name}' created at default location (scene root not found)`,
|
|
||||||
warning: 'Could not determine scene root, node created at default location'
|
console.log('Creating node with options:', createNodeOptions);
|
||||||
|
|
||||||
|
// 创建节点
|
||||||
|
const nodeUuid = await Editor.Message.request('scene', 'create-node', createNodeOptions);
|
||||||
|
const uuid = Array.isArray(nodeUuid) ? nodeUuid[0] : nodeUuid;
|
||||||
|
|
||||||
|
// 处理兄弟索引
|
||||||
|
if (args.siblingIndex !== undefined && args.siblingIndex >= 0 && uuid && targetParentUuid) {
|
||||||
|
try {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100)); // 等待内部状态更新
|
||||||
|
await Editor.Message.request('scene', 'set-parent', {
|
||||||
|
parent: targetParentUuid,
|
||||||
|
uuids: [uuid],
|
||||||
|
keepWorldTransform: args.keepWorldTransform || false
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Failed to set sibling index:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加组件(如果提供的话)
|
||||||
|
if (args.components && args.components.length > 0 && uuid) {
|
||||||
|
try {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100)); // 等待节点创建完成
|
||||||
|
for (const componentType of args.components) {
|
||||||
|
try {
|
||||||
|
const result = await this.componentTools.execute('add_component', {
|
||||||
|
nodeUuid: uuid,
|
||||||
|
componentType: componentType
|
||||||
|
});
|
||||||
|
if (result.success) {
|
||||||
|
console.log(`Component ${componentType} added successfully`);
|
||||||
|
} else {
|
||||||
|
console.warn(`Failed to add component ${componentType}:`, result.error);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`Failed to add component ${componentType}:`, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
} catch (err) {
|
||||||
}).catch((err: Error) => {
|
console.warn('Failed to add components:', err);
|
||||||
resolve({ success: false, error: err.message });
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置初始变换(如果提供的话)
|
||||||
|
if (args.initialTransform && uuid) {
|
||||||
|
try {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 150)); // 等待节点和组件创建完成
|
||||||
|
await this.setNodeTransform({
|
||||||
|
uuid: uuid,
|
||||||
|
position: args.initialTransform.position,
|
||||||
|
rotation: args.initialTransform.rotation,
|
||||||
|
scale: args.initialTransform.scale
|
||||||
|
});
|
||||||
|
console.log('Initial transform applied successfully');
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Failed to set initial transform:', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取创建后的节点信息进行验证
|
||||||
|
let verificationData: any = null;
|
||||||
|
try {
|
||||||
|
const nodeInfo = await this.getNodeInfo(uuid);
|
||||||
|
if (nodeInfo.success) {
|
||||||
|
verificationData = {
|
||||||
|
nodeInfo: nodeInfo.data,
|
||||||
|
creationDetails: {
|
||||||
|
parentUuid: targetParentUuid,
|
||||||
|
nodeType: args.nodeType || 'Node',
|
||||||
|
fromAsset: !!finalAssetUuid,
|
||||||
|
assetUuid: finalAssetUuid,
|
||||||
|
assetPath: args.assetPath,
|
||||||
|
timestamp: new Date().toISOString()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Failed to get verification data:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
const successMessage = finalAssetUuid
|
||||||
|
? `Node '${args.name}' instantiated from asset successfully`
|
||||||
|
: `Node '${args.name}' created successfully`;
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
success: true,
|
||||||
|
data: {
|
||||||
|
uuid: uuid,
|
||||||
|
name: args.name,
|
||||||
|
parentUuid: targetParentUuid,
|
||||||
|
nodeType: args.nodeType || 'Node',
|
||||||
|
fromAsset: !!finalAssetUuid,
|
||||||
|
assetUuid: finalAssetUuid,
|
||||||
|
message: successMessage
|
||||||
|
},
|
||||||
|
verificationData: verificationData
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (err: any) {
|
||||||
|
resolve({
|
||||||
|
success: false,
|
||||||
|
error: `Failed to create node: ${err.message}. Args: ${JSON.stringify(args)}`
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user