@esengine/behavior-tree 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/{index.d.ts → dist/index.d.ts} +361 -73
- package/dist/index.js +4692 -0
- package/dist/index.js.map +1 -0
- package/package.json +35 -29
- package/index.cjs +0 -2
- package/index.cjs.map +0 -1
- package/index.es5.js +0 -4
- package/index.es5.js.map +0 -1
- package/index.mjs +0 -2
- package/index.mjs.map +0 -1
- package/index.umd.js +0 -2
- package/index.umd.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@esengine/behavior-tree",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "
|
|
5
|
-
"main": "index.
|
|
6
|
-
"module": "index.
|
|
7
|
-
"
|
|
8
|
-
"
|
|
3
|
+
"version": "1.0.3",
|
|
4
|
+
"description": "ECS-based AI behavior tree system - works with any ECS framework (ESEngine, Cocos, Laya, etc.)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"type": "module",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"types": "./index.d.ts"
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
14
13
|
}
|
|
15
14
|
},
|
|
16
15
|
"files": [
|
|
17
|
-
"
|
|
18
|
-
"index.mjs.map",
|
|
19
|
-
"index.cjs",
|
|
20
|
-
"index.cjs.map",
|
|
21
|
-
"index.umd.js",
|
|
22
|
-
"index.umd.js.map",
|
|
23
|
-
"index.es5.js",
|
|
24
|
-
"index.es5.js.map",
|
|
25
|
-
"index.d.ts"
|
|
16
|
+
"dist"
|
|
26
17
|
],
|
|
27
18
|
"keywords": [
|
|
28
19
|
"ecs",
|
|
@@ -30,27 +21,42 @@
|
|
|
30
21
|
"ai",
|
|
31
22
|
"game-ai",
|
|
32
23
|
"entity-component-system",
|
|
33
|
-
"
|
|
34
|
-
"cocos-creator",
|
|
24
|
+
"cocos",
|
|
35
25
|
"laya",
|
|
36
|
-
"
|
|
26
|
+
"esengine"
|
|
37
27
|
],
|
|
38
28
|
"author": "yhh",
|
|
39
29
|
"license": "MIT",
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/jest": "^29.5.14",
|
|
32
|
+
"@types/node": "^20.19.17",
|
|
33
|
+
"jest": "^29.7.0",
|
|
34
|
+
"rimraf": "^5.0.0",
|
|
35
|
+
"ts-jest": "^29.4.0",
|
|
36
|
+
"tsup": "^8.0.0",
|
|
37
|
+
"typescript": "^5.8.3",
|
|
38
|
+
"@esengine/ecs-framework": "2.4.4",
|
|
39
|
+
"@esengine/build-config": "1.0.0"
|
|
44
40
|
},
|
|
45
41
|
"peerDependencies": {
|
|
46
|
-
"@esengine/ecs-framework": "
|
|
42
|
+
"@esengine/ecs-framework": "2.4.4"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"tslib": "^2.8.1"
|
|
47
46
|
},
|
|
48
47
|
"publishConfig": {
|
|
49
48
|
"access": "public",
|
|
50
49
|
"registry": "https://registry.npmjs.org/"
|
|
51
50
|
},
|
|
52
|
-
"
|
|
53
|
-
"
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "https://github.com/esengine/esengine.git",
|
|
54
|
+
"directory": "packages/framework/behavior-tree"
|
|
54
55
|
},
|
|
55
|
-
"
|
|
56
|
+
"scripts": {
|
|
57
|
+
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
|
58
|
+
"build": "tsup",
|
|
59
|
+
"build:watch": "tsup --watch",
|
|
60
|
+
"type-check": "tsc --noEmit"
|
|
61
|
+
}
|
|
56
62
|
}
|
package/index.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";var e,t=require("@esengine/ecs-framework");exports.TaskStatus=void 0,(e=exports.TaskStatus||(exports.TaskStatus={}))[e.Invalid=0]="Invalid",e[e.Success=1]="Success",e[e.Failure=2]="Failure",e[e.Running=3]="Running";const r={Composite:"composite",Decorator:"decorator",Action:"action",Condition:"condition"};var o,s,a,n;function i(){return{status:exports.TaskStatus.Invalid,currentChildIndex:0}}function c(e,t,r,o){var s,a=arguments.length,n=a<3?t:null===o?o=Object.getOwnPropertyDescriptor(t,r):o;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)n=Reflect.decorate(e,t,r,o);else for(var i=e.length-1;i>=0;i--)(s=e[i])&&(n=(a<3?s(n):a>3?s(t,r,n):s(t,r))||n);return a>3&&n&&Object.defineProperty(t,r,n),n}function d(e,t){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(e,t)}exports.CompositeType=void 0,(o=exports.CompositeType||(exports.CompositeType={})).Sequence="sequence",o.Selector="selector",o.Parallel="parallel",o.ParallelSelector="parallel-selector",o.RandomSequence="random-sequence",o.RandomSelector="random-selector",exports.DecoratorType=void 0,(s=exports.DecoratorType||(exports.DecoratorType={})).Inverter="inverter",s.Repeater="repeater",s.UntilSuccess="until-success",s.UntilFail="until-fail",s.AlwaysSucceed="always-succeed",s.AlwaysFail="always-fail",s.Conditional="conditional",s.Cooldown="cooldown",s.Timeout="timeout",exports.AbortType=void 0,(a=exports.AbortType||(exports.AbortType={})).None="none",a.Self="self",a.LowerPriority="lower-priority",a.Both="both",exports.BlackboardValueType=void 0,(n=exports.BlackboardValueType||(exports.BlackboardValueType={})).String="string",n.Number="number",n.Boolean="boolean",n.Vector2="vector2",n.Vector3="vector3",n.Object="object",n.Array="array","function"==typeof SuppressedError&&SuppressedError,exports.BehaviorTreeRuntimeComponent=class extends t.Component{constructor(){super(...arguments),this.treeAssetId="",this.autoStart=!0,this.isRunning=!1,this.nodeStates=new Map,this.blackboard=new Map,this.blackboardObservers=new Map,this.activeNodeIds=new Set,this.needsReset=!1,this.nodesToAbort=new Set}getNodeState(e){return this.nodeStates.has(e)||this.nodeStates.set(e,i()),this.nodeStates.get(e)}resetNodeState(e){const t=this.getNodeState(e);t.status=exports.TaskStatus.Invalid,t.currentChildIndex=0,delete t.startTime,delete t.lastExecutionTime,delete t.repeatCount,delete t.cachedResult,delete t.shuffledIndices,delete t.isAborted,delete t.lastConditionResult,delete t.observedKeys}resetAllStates(){this.nodeStates.clear(),this.activeNodeIds.clear()}getBlackboardValue(e){return this.blackboard.get(e)}setBlackboardValue(e,t){const r=this.blackboard.get(e);this.blackboard.set(e,t),r!==t&&this.notifyBlackboardChange(e,t,r)}hasBlackboardKey(e){return this.blackboard.has(e)}initializeBlackboard(e){e&&e.forEach(((e,t)=>{this.blackboard.has(t)||this.blackboard.set(t,e)}))}clearBlackboard(){this.blackboard.clear()}start(){this.isRunning=!0,this.resetAllStates()}stop(){this.isRunning=!1,this.activeNodeIds.clear()}pause(){this.isRunning=!1}resume(){this.isRunning=!0}observeBlackboard(e,t,r){const o={nodeId:e,keys:new Set(t),callback:r};for(const e of t)this.blackboardObservers.has(e)||this.blackboardObservers.set(e,[]),this.blackboardObservers.get(e).push(o)}unobserveBlackboard(e){for(const t of this.blackboardObservers.values()){const r=t.findIndex((t=>t.nodeId===e));-1!==r&&t.splice(r,1)}}notifyBlackboardChange(e,t,r){const o=this.blackboardObservers.get(e);if(o)for(const s of o)try{s.callback(e,t,r)}catch(e){console.error(`黑板观察者回调错误 (节点: ${s.nodeId}):`,e)}}requestAbort(e){this.nodesToAbort.add(e)}shouldAbort(e){return this.nodesToAbort.has(e)}clearAbortRequest(e){this.nodesToAbort.delete(e)}clearAllAbortRequests(){this.nodesToAbort.clear()}},c([t.Serialize(),d("design:type",String)],exports.BehaviorTreeRuntimeComponent.prototype,"treeAssetId",void 0),c([t.Serialize(),d("design:type",Boolean)],exports.BehaviorTreeRuntimeComponent.prototype,"autoStart",void 0),c([t.IgnoreSerialization(),d("design:type",Boolean)],exports.BehaviorTreeRuntimeComponent.prototype,"isRunning",void 0),c([t.IgnoreSerialization(),d("design:type",Map)],exports.BehaviorTreeRuntimeComponent.prototype,"nodeStates",void 0),c([t.IgnoreSerialization(),d("design:type",Map)],exports.BehaviorTreeRuntimeComponent.prototype,"blackboard",void 0),c([t.IgnoreSerialization(),d("design:type",Map)],exports.BehaviorTreeRuntimeComponent.prototype,"blackboardObservers",void 0),c([t.IgnoreSerialization(),d("design:type",Set)],exports.BehaviorTreeRuntimeComponent.prototype,"activeNodeIds",void 0),c([t.IgnoreSerialization(),d("design:type",Boolean)],exports.BehaviorTreeRuntimeComponent.prototype,"needsReset",void 0),c([t.IgnoreSerialization(),d("design:type",Set)],exports.BehaviorTreeRuntimeComponent.prototype,"nodesToAbort",void 0),exports.BehaviorTreeRuntimeComponent=c([t.ECSComponent("BehaviorTreeRuntime"),t.Serializable({version:1})],exports.BehaviorTreeRuntimeComponent);const l=t.createLogger("BehaviorTreeAssetManager");class u{constructor(){this.assets=new Map}loadAsset(e){this.assets.has(e.id)&&l.warn(`行为树资产已存在,将被覆盖: ${e.id}`),this.assets.set(e.id,e),l.info(`行为树资产已加载: ${e.name} (${e.nodes.size}个节点)`)}getAsset(e){return this.assets.get(e)}hasAsset(e){return this.assets.has(e)}unloadAsset(e){const t=this.assets.delete(e);return t&&l.info(`行为树资产已卸载: ${e}`),t}clearAll(){this.assets.clear(),l.info("所有行为树资产已清空")}getAssetCount(){return this.assets.size}getAllAssetIds(){return Array.from(this.assets.keys())}dispose(){this.clearAll()}}class p{static getValue(e,t,r){const{nodeData:o,runtime:s}=e;if(o.bindings&&o.bindings[t]){const e=o.bindings[t],a=s.getBlackboardValue(e);return void 0!==a?a:r}const a=o.config[t];return void 0!==a?a:r}static hasBinding(e,t){return!(!e.nodeData.bindings||!e.nodeData.bindings[t])}static getBindingKey(e,t){return e.nodeData.bindings?.[t]}}class h{constructor(){this.executors=new Map}register(e,t){this.executors.has(e)&&console.warn(`执行器已存在,将被覆盖: ${e}`),this.executors.set(e,t)}get(e){return this.executors.get(e)}has(e){return this.executors.has(e)}unregister(e){return this.executors.delete(e)}clear(){this.executors.clear()}}class m{static register(e,t){this.metadataMap.set(t.implementationType,t),this.executorClassMap.set(e,t.implementationType),this.executorConstructors.set(t.implementationType,e)}static getMetadata(e){return this.metadataMap.get(e)}static getAllMetadata(){return Array.from(this.metadataMap.values())}static getByCategory(e){return this.getAllMetadata().filter((t=>t.category===e))}static getByNodeType(e){return this.getAllMetadata().filter((t=>t.nodeType===e))}static getImplementationType(e){return this.executorClassMap.get(e)}static getExecutorConstructor(e){return this.executorConstructors.get(e)}static getAllExecutorConstructors(){return new Map(this.executorConstructors)}}function g(e){return function(t){m.register(t,e)}}m.metadataMap=new Map,m.executorClassMap=new Map,m.executorConstructors=new Map,exports.SequenceExecutor=class{execute(e){const{nodeData:t,state:r}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Success;for(;r.currentChildIndex<t.children.length;){const o=t.children[r.currentChildIndex],s=e.executeChild(o);if(s===exports.TaskStatus.Running)return exports.TaskStatus.Running;if(s===exports.TaskStatus.Failure)return r.currentChildIndex=0,exports.TaskStatus.Failure;r.currentChildIndex++}return r.currentChildIndex=0,exports.TaskStatus.Success}reset(e){e.state.currentChildIndex=0}},exports.SequenceExecutor=c([g({implementationType:"Sequence",nodeType:r.Composite,displayName:"序列",description:"按顺序执行子节点,全部成功才成功",category:"Composite"})],exports.SequenceExecutor),exports.SelectorExecutor=class{execute(e){const{nodeData:t,state:r}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;for(;r.currentChildIndex<t.children.length;){const o=t.children[r.currentChildIndex],s=e.executeChild(o);if(s===exports.TaskStatus.Running)return exports.TaskStatus.Running;if(s===exports.TaskStatus.Success)return r.currentChildIndex=0,exports.TaskStatus.Success;r.currentChildIndex++}return r.currentChildIndex=0,exports.TaskStatus.Failure}reset(e){e.state.currentChildIndex=0}},exports.SelectorExecutor=c([g({implementationType:"Selector",nodeType:r.Composite,displayName:"选择器",description:"按顺序执行子节点,任一成功则成功",category:"Composite"})],exports.SelectorExecutor),exports.ParallelExecutor=class{execute(e){const{nodeData:t}=e,r=p.getValue(e,"successPolicy","all"),o=p.getValue(e,"failurePolicy","one");if(!t.children||0===t.children.length)return exports.TaskStatus.Success;let s=!1,a=0,n=0;for(const r of t.children){const t=e.executeChild(r);t===exports.TaskStatus.Running?s=!0:t===exports.TaskStatus.Success?a++:t===exports.TaskStatus.Failure&&n++}return"one"===r&&a>0?(this.stopAllChildren(e),exports.TaskStatus.Success):"all"===r&&a===t.children.length?exports.TaskStatus.Success:"one"===o&&n>0?(this.stopAllChildren(e),exports.TaskStatus.Failure):"all"===o&&n===t.children.length?exports.TaskStatus.Failure:s?exports.TaskStatus.Running:exports.TaskStatus.Success}stopAllChildren(e){const{nodeData:t,runtime:r}=e;if(t.children)for(const e of t.children)r.activeNodeIds.delete(e),r.resetNodeState(e)}reset(e){const{nodeData:t,runtime:r}=e;if(t.children)for(const e of t.children)r.resetNodeState(e)}},exports.ParallelExecutor=c([g({implementationType:"Parallel",nodeType:r.Composite,displayName:"并行",description:"同时执行所有子节点",category:"Composite",configSchema:{successPolicy:{type:"string",default:"all",description:"成功策略",options:["all","one"]},failurePolicy:{type:"string",default:"one",description:"失败策略",options:["all","one"]}}})],exports.ParallelExecutor),exports.ParallelSelectorExecutor=class{execute(e){const{nodeData:t}=e,r=p.getValue(e,"failurePolicy","all");if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;let o=!1,s=0,a=0;for(const r of t.children){const t=e.executeChild(r);t===exports.TaskStatus.Running?o=!0:t===exports.TaskStatus.Success?s++:t===exports.TaskStatus.Failure&&a++}return s>0?(this.stopAllChildren(e),exports.TaskStatus.Success):"one"===r&&a>0?(this.stopAllChildren(e),exports.TaskStatus.Failure):"all"===r&&a===t.children.length?exports.TaskStatus.Failure:o?exports.TaskStatus.Running:exports.TaskStatus.Failure}stopAllChildren(e){const{nodeData:t,runtime:r}=e;if(t.children)for(const e of t.children)r.activeNodeIds.delete(e),r.resetNodeState(e)}reset(e){const{nodeData:t,runtime:r}=e;if(t.children)for(const e of t.children)r.resetNodeState(e)}},exports.ParallelSelectorExecutor=c([g({implementationType:"ParallelSelector",nodeType:r.Composite,displayName:"并行选择器",description:"并行执行子节点,任一成功则成功",category:"Composite",configSchema:{failurePolicy:{type:"string",default:"all",description:"失败策略",options:["all","one"]}}})],exports.ParallelSelectorExecutor),exports.RandomSequenceExecutor=class{execute(e){const{nodeData:t,state:r}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Success;for(r.shuffledIndices&&0!==r.shuffledIndices.length||(r.shuffledIndices=this.shuffleIndices(t.children.length));r.currentChildIndex<r.shuffledIndices.length;){const o=r.shuffledIndices[r.currentChildIndex],s=t.children[o],a=e.executeChild(s);if(a===exports.TaskStatus.Running)return exports.TaskStatus.Running;if(a===exports.TaskStatus.Failure)return r.currentChildIndex=0,delete r.shuffledIndices,exports.TaskStatus.Failure;r.currentChildIndex++}return r.currentChildIndex=0,delete r.shuffledIndices,exports.TaskStatus.Success}shuffleIndices(e){const t=Array.from({length:e},((e,t)=>t));for(let e=t.length-1;e>0;e--){const r=Math.floor(Math.random()*(e+1)),o=t[e];t[e]=t[r],t[r]=o}return t}reset(e){e.state.currentChildIndex=0,delete e.state.shuffledIndices}},exports.RandomSequenceExecutor=c([g({implementationType:"RandomSequence",nodeType:r.Composite,displayName:"随机序列",description:"随机顺序执行子节点,全部成功才成功",category:"Composite"})],exports.RandomSequenceExecutor),exports.RandomSelectorExecutor=class{execute(e){const{nodeData:t,state:r}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;for(r.shuffledIndices&&0!==r.shuffledIndices.length||(r.shuffledIndices=this.shuffleIndices(t.children.length));r.currentChildIndex<r.shuffledIndices.length;){const o=r.shuffledIndices[r.currentChildIndex],s=t.children[o],a=e.executeChild(s);if(a===exports.TaskStatus.Running)return exports.TaskStatus.Running;if(a===exports.TaskStatus.Success)return r.currentChildIndex=0,delete r.shuffledIndices,exports.TaskStatus.Success;r.currentChildIndex++}return r.currentChildIndex=0,delete r.shuffledIndices,exports.TaskStatus.Failure}shuffleIndices(e){const t=Array.from({length:e},((e,t)=>t));for(let e=t.length-1;e>0;e--){const r=Math.floor(Math.random()*(e+1)),o=t[e];t[e]=t[r],t[r]=o}return t}reset(e){e.state.currentChildIndex=0,delete e.state.shuffledIndices}},exports.RandomSelectorExecutor=c([g({implementationType:"RandomSelector",nodeType:r.Composite,displayName:"随机选择器",description:"随机顺序执行子节点,任一成功则成功",category:"Composite"})],exports.RandomSelectorExecutor),exports.InverterExecutor=class{execute(e){const{nodeData:t}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;const r=t.children[0],o=e.executeChild(r);return o===exports.TaskStatus.Running?exports.TaskStatus.Running:o===exports.TaskStatus.Success?exports.TaskStatus.Failure:o===exports.TaskStatus.Failure?exports.TaskStatus.Success:exports.TaskStatus.Failure}reset(e){e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.InverterExecutor=c([g({implementationType:"Inverter",nodeType:r.Decorator,displayName:"反转",description:"反转子节点的执行结果",category:"Decorator"})],exports.InverterExecutor),exports.RepeaterExecutor=class{execute(e){const{nodeData:t,state:r,runtime:o}=e,s=p.getValue(e,"repeatCount",1),a=p.getValue(e,"endOnFailure",!1);if(!t.children||0===t.children.length)return exports.TaskStatus.Success;const n=t.children[0];r.repeatCount||(r.repeatCount=0);const i=e.executeChild(n);if(i===exports.TaskStatus.Running)return exports.TaskStatus.Running;if(i===exports.TaskStatus.Failure&&a)return r.repeatCount=0,exports.TaskStatus.Failure;r.repeatCount++,o.resetNodeState(n);return-1===s||r.repeatCount<s?exports.TaskStatus.Running:(r.repeatCount=0,exports.TaskStatus.Success)}reset(e){delete e.state.repeatCount,e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.RepeaterExecutor=c([g({implementationType:"Repeater",nodeType:r.Decorator,displayName:"重复",description:"重复执行子节点指定次数",category:"Decorator",configSchema:{repeatCount:{type:"number",default:1,description:"重复次数(-1表示无限循环)",supportBinding:!0},endOnFailure:{type:"boolean",default:!1,description:"子节点失败时是否结束"}}})],exports.RepeaterExecutor),exports.AlwaysSucceedExecutor=class{execute(e){const{nodeData:t}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Success;const r=t.children[0];return e.executeChild(r)===exports.TaskStatus.Running?exports.TaskStatus.Running:exports.TaskStatus.Success}reset(e){e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.AlwaysSucceedExecutor=c([g({implementationType:"AlwaysSucceed",nodeType:r.Decorator,displayName:"总是成功",description:"无论子节点结果如何都返回成功",category:"Decorator"})],exports.AlwaysSucceedExecutor),exports.AlwaysFailExecutor=class{execute(e){const{nodeData:t}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;const r=t.children[0];return e.executeChild(r)===exports.TaskStatus.Running?exports.TaskStatus.Running:exports.TaskStatus.Failure}reset(e){e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.AlwaysFailExecutor=c([g({implementationType:"AlwaysFail",nodeType:r.Decorator,displayName:"总是失败",description:"无论子节点结果如何都返回失败",category:"Decorator"})],exports.AlwaysFailExecutor),exports.UntilSuccessExecutor=class{execute(e){const{nodeData:t,runtime:r}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;const o=t.children[0],s=e.executeChild(o);return s===exports.TaskStatus.Running?exports.TaskStatus.Running:s===exports.TaskStatus.Success?exports.TaskStatus.Success:(r.resetNodeState(o),exports.TaskStatus.Running)}reset(e){e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.UntilSuccessExecutor=c([g({implementationType:"UntilSuccess",nodeType:r.Decorator,displayName:"直到成功",description:"重复执行子节点直到成功",category:"Decorator"})],exports.UntilSuccessExecutor),exports.UntilFailExecutor=class{execute(e){const{nodeData:t,runtime:r}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Success;const o=t.children[0],s=e.executeChild(o);return s===exports.TaskStatus.Running?exports.TaskStatus.Running:s===exports.TaskStatus.Failure?exports.TaskStatus.Failure:(r.resetNodeState(o),exports.TaskStatus.Running)}reset(e){e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.UntilFailExecutor=c([g({implementationType:"UntilFail",nodeType:r.Decorator,displayName:"直到失败",description:"重复执行子节点直到失败",category:"Decorator"})],exports.UntilFailExecutor),exports.ConditionalExecutor=class{execute(e){const{nodeData:t,runtime:r,state:o}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;const s=p.getValue(e,"blackboardKey",""),a=p.getValue(e,"expectedValue"),n=p.getValue(e,"operator","equals"),i=t.abortType||exports.AbortType.None;if(!s)return exports.TaskStatus.Failure;const c=r.getBlackboardValue(s),d=this.evaluateCondition(c,a,n),l=o.status===exports.TaskStatus.Running;if(i!==exports.AbortType.None&&(o.observedKeys&&0!==o.observedKeys.length||(o.observedKeys=[s],this.setupObserver(e,s,a,n,i)),void 0!==o.lastConditionResult&&o.lastConditionResult!==d&&(d?this.handleConditionBecameTrue(e,i):l&&this.handleConditionBecameFalse(e,i))),o.lastConditionResult=d,!d)return exports.TaskStatus.Failure;const u=t.children[0];return e.executeChild(u)}evaluateCondition(e,t,r){switch(r){case"equals":return e===t;case"notEquals":return e!==t;case"greaterThan":return e>t;case"lessThan":return e<t;case"greaterOrEqual":return e>=t;case"lessOrEqual":return e<=t;default:return!1}}setupObserver(e,t,r,o,s){const{nodeData:a,runtime:n}=e;n.observeBlackboard(a.id,[t],((t,a)=>{const n=this.evaluateCondition(a,r,o),i=e.state.lastConditionResult;void 0!==i&&i!==n&&(n?this.handleConditionBecameTrue(e,s):this.handleConditionBecameFalse(e,s)),e.state.lastConditionResult=n}))}handleConditionBecameTrue(e,t){t!==exports.AbortType.LowerPriority&&t!==exports.AbortType.Both||this.requestAbortLowerPriority(e)}handleConditionBecameFalse(e,t){const{nodeData:r,runtime:o}=e;t!==exports.AbortType.Self&&t!==exports.AbortType.Both||r.children&&r.children.length>0&&o.requestAbort(r.children[0])}requestAbortLowerPriority(e){const{runtime:t}=e;t.requestAbort("__lower_priority__")}reset(e){const{nodeData:t,runtime:r,state:o}=e;o.observedKeys&&o.observedKeys.length>0&&(r.unobserveBlackboard(t.id),delete o.observedKeys),delete o.lastConditionResult,t.children&&t.children.length>0&&r.resetNodeState(t.children[0])}},exports.ConditionalExecutor=c([g({implementationType:"Conditional",nodeType:r.Decorator,displayName:"条件",description:"根据条件决定是否执行子节点",category:"Decorator",configSchema:{blackboardKey:{type:"string",default:"",description:"黑板变量名"},expectedValue:{type:"object",description:"期望值",supportBinding:!0},operator:{type:"string",default:"equals",description:"比较运算符",options:["equals","notEquals","greaterThan","lessThan","greaterOrEqual","lessOrEqual"]},abortType:{type:"string",default:"none",description:"中止类型",options:["none","self","lower-priority","both"]}}})],exports.ConditionalExecutor),exports.CooldownExecutor=class{execute(e){const{nodeData:t,state:r,totalTime:o}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;const s=p.getValue(e,"cooldownTime",1);if(void 0!==r.lastExecutionTime){if(o-r.lastExecutionTime<s)return exports.TaskStatus.Failure}const a=t.children[0],n=e.executeChild(a);return n===exports.TaskStatus.Running?exports.TaskStatus.Running:n===exports.TaskStatus.Success?(r.lastExecutionTime=o,exports.TaskStatus.Success):exports.TaskStatus.Failure}reset(e){delete e.state.lastExecutionTime,e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.CooldownExecutor=c([g({implementationType:"Cooldown",nodeType:r.Decorator,displayName:"冷却",description:"子节点执行成功后进入冷却时间",category:"Decorator",configSchema:{cooldownTime:{type:"number",default:1,description:"冷却时间(秒)",min:0,supportBinding:!0}}})],exports.CooldownExecutor),exports.TimeoutExecutor=class{execute(e){const{nodeData:t,state:r,totalTime:o}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;const s=p.getValue(e,"timeout",1);void 0===r.startTime&&(r.startTime=o);if(o-r.startTime>=s)return delete r.startTime,exports.TaskStatus.Failure;const a=t.children[0],n=e.executeChild(a);return n===exports.TaskStatus.Running?exports.TaskStatus.Running:(delete r.startTime,n)}reset(e){delete e.state.startTime,e.nodeData.children&&e.nodeData.children.length>0&&e.runtime.resetNodeState(e.nodeData.children[0])}},exports.TimeoutExecutor=c([g({implementationType:"Timeout",nodeType:r.Decorator,displayName:"超时",description:"限制子节点的执行时间",category:"Decorator",configSchema:{timeout:{type:"number",default:1,description:"超时时间(秒)",min:0,supportBinding:!0}}})],exports.TimeoutExecutor);class x{static register(e,t){this.services.set(e,t)}static get(e){return this.services.get(e)}static has(e){return this.services.has(e)}static unregister(e){return this.services.delete(e)}}x.services=new Map,exports.ServiceDecorator=class{execute(e){const{nodeData:t,state:r,totalTime:o}=e;if(!t.children||0===t.children.length)return exports.TaskStatus.Failure;const s=p.getValue(e,"serviceName",""),a=p.getValue(e,"tickInterval",0);if(!s)return exports.TaskStatus.Failure;const n=x.get(s);if(!n)return console.warn(`未找到Service: ${s}`),exports.TaskStatus.Failure;r.status!==exports.TaskStatus.Running&&(r.startTime=o,r.lastExecutionTime=o,n.onServiceStart&&n.onServiceStart(e));(0===a||void 0!==r.lastExecutionTime&&o-r.lastExecutionTime>=a)&&(n.onServiceTick(e),r.lastExecutionTime=o);const i=t.children[0],c=e.executeChild(i);return c!==exports.TaskStatus.Running&&n.onServiceEnd&&n.onServiceEnd(e),c}reset(e){const{nodeData:t,runtime:r,state:o}=e,s=p.getValue(e,"serviceName","");if(s){const t=x.get(s);t&&t.onServiceEnd&&t.onServiceEnd(e)}delete o.startTime,delete o.lastExecutionTime,t.children&&t.children.length>0&&r.resetNodeState(t.children[0])}},exports.ServiceDecorator=c([g({implementationType:"Service",nodeType:r.Decorator,displayName:"Service",description:"在子节点执行期间持续运行后台逻辑",category:"Decorator",configSchema:{serviceName:{type:"string",default:"",description:"Service名称"},tickInterval:{type:"number",default:0,description:"Service更新间隔(秒,0表示每帧更新)",supportBinding:!0}}})],exports.ServiceDecorator),exports.WaitAction=class{execute(e){const{state:t,totalTime:r}=e,o=p.getValue(e,"duration",1);return t.startTime?r-t.startTime>=o?exports.TaskStatus.Success:exports.TaskStatus.Running:(t.startTime=r,exports.TaskStatus.Running)}reset(e){delete e.state.startTime}},exports.WaitAction=c([g({implementationType:"Wait",nodeType:r.Action,displayName:"等待",description:"等待指定时间后返回成功",category:"Action",configSchema:{duration:{type:"number",default:1,description:"等待时长(秒)",min:0,supportBinding:!0}}})],exports.WaitAction),exports.LogAction=class{execute(e){const{runtime:t}=e,r=p.getValue(e,"message",""),o=p.getValue(e,"logLevel","info"),s=this.replaceBlackboardVariables(r,t);return this.log(s,o),exports.TaskStatus.Success}replaceBlackboardVariables(e,t){return e.includes("{")&&e.includes("}")?e.replace(/\{([\w.]{1,100})\}/g,((e,r)=>{const o=t.getBlackboardValue(r.trim());return void 0!==o?String(o):`{${r}}`})):e}log(e,t){switch(t){case"error":console.error(e);break;case"warn":console.warn(e);break;default:console.log(e)}}},exports.LogAction=c([g({implementationType:"Log",nodeType:r.Action,displayName:"日志",description:"输出日志信息",category:"Action",configSchema:{message:{type:"string",default:"",description:"日志消息,支持{key}占位符引用黑板变量",supportBinding:!0},logLevel:{type:"string",default:"info",description:"日志级别",options:["info","warn","error"]}}})],exports.LogAction),exports.SetBlackboardValue=class{execute(e){const{runtime:t}=e,r=p.getValue(e,"key",""),o=p.getValue(e,"value");return r?(t.setBlackboardValue(r,o),exports.TaskStatus.Success):exports.TaskStatus.Failure}},exports.SetBlackboardValue=c([g({implementationType:"SetBlackboardValue",nodeType:r.Action,displayName:"设置黑板值",description:"设置黑板中的变量值",category:"Action",configSchema:{key:{type:"string",default:"",description:"黑板变量名"},value:{type:"object",description:"要设置的值",supportBinding:!0}}})],exports.SetBlackboardValue),exports.ModifyBlackboardValue=class{execute(e){const{runtime:t}=e,r=p.getValue(e,"key",""),o=p.getValue(e,"operation","add"),s=p.getValue(e,"value",0);if(!r)return exports.TaskStatus.Failure;const a=t.getBlackboardValue(r)||0;let n;switch(o){case"add":n=a+s;break;case"subtract":n=a-s;break;case"multiply":n=a*s;break;case"divide":n=0!==s?a/s:a;break;case"set":n=s;break;default:return exports.TaskStatus.Failure}return t.setBlackboardValue(r,n),exports.TaskStatus.Success}},exports.ModifyBlackboardValue=c([g({implementationType:"ModifyBlackboardValue",nodeType:r.Action,displayName:"修改黑板值",description:"对黑板中的数值进行运算",category:"Action",configSchema:{key:{type:"string",default:"",description:"黑板变量名"},operation:{type:"string",default:"add",description:"运算类型",options:["add","subtract","multiply","divide","set"]},value:{type:"number",default:0,description:"操作数",supportBinding:!0}}})],exports.ModifyBlackboardValue),exports.ExecuteAction=class{execute(e){const{runtime:t,entity:r}=e,o=p.getValue(e,"actionName","");if(!o)return exports.TaskStatus.Failure;const s=t.getBlackboardValue(`action_${o}`);if(!s||"function"!=typeof s)return exports.TaskStatus.Failure;try{return s(r)}catch(e){return console.error(`ExecuteAction failed: ${e}`),exports.TaskStatus.Failure}}},exports.ExecuteAction=c([g({implementationType:"ExecuteAction",nodeType:r.Action,displayName:"执行动作",description:"执行自定义动作逻辑",category:"Action",configSchema:{actionName:{type:"string",default:"",description:"动作名称(黑板中action_前缀的函数)"}}})],exports.ExecuteAction),exports.SubTreeExecutor=class{constructor(){this.assetManager=null}getAssetManager(){return this.assetManager||(this.assetManager=t.Core.services.resolve(u)),this.assetManager}execute(e){const{runtime:t,state:r,entity:o}=e,s=p.getValue(e,"treeAssetId",""),a=p.getValue(e,"shareBlackboard",!0);if(!s)return exports.TaskStatus.Failure;const n=this.getAssetManager().getAsset(s);if(!n)return console.warn(`未找到子树资产: ${s}`),exports.TaskStatus.Failure;const i=n.nodes.get(n.rootNodeId);if(!i)return console.warn(`子树根节点未找到: ${n.rootNodeId}`),exports.TaskStatus.Failure;if(!a&&r.status!==exports.TaskStatus.Running&&n.blackboardVariables)for(const[e,r]of n.blackboardVariables.entries())t.hasBlackboardKey(e)||t.setBlackboardValue(e,r);const c={entity:o,nodeData:i,state:t.getNodeState(i.id),runtime:t,treeData:n,deltaTime:e.deltaTime,totalTime:e.totalTime,executeChild:r=>{const s=n.nodes.get(r);if(!s)return console.warn(`子树节点未找到: ${r}`),exports.TaskStatus.Failure;const a={entity:o,nodeData:s,state:t.getNodeState(r),runtime:t,treeData:n,deltaTime:e.deltaTime,totalTime:e.totalTime,executeChild:c.executeChild};return this.executeSubTreeNode(a)}};return this.executeSubTreeNode(c)}executeSubTreeNode(e){const{nodeData:t,runtime:r}=e,o=r.getNodeState(t.id);if(!t.children||0===t.children.length)return exports.TaskStatus.Success;const s=t.children[o.currentChildIndex],a=e.executeChild(s);return a===exports.TaskStatus.Running?exports.TaskStatus.Running:a===exports.TaskStatus.Failure?(o.currentChildIndex=0,exports.TaskStatus.Failure):(o.currentChildIndex++,o.currentChildIndex>=t.children.length?(o.currentChildIndex=0,exports.TaskStatus.Success):exports.TaskStatus.Running)}reset(e){const t=p.getValue(e,"treeAssetId","");if(t){const r=this.getAssetManager().getAsset(t);if(r){const t=r.nodes.get(r.rootNodeId);if(t&&(e.runtime.resetNodeState(t.id),t.children))for(const r of t.children)e.runtime.resetNodeState(r)}}}},exports.SubTreeExecutor=c([g({implementationType:"SubTree",nodeType:r.Action,displayName:"子树",description:"引用并执行其他行为树",category:"Special",configSchema:{treeAssetId:{type:"string",default:"",description:"要执行的行为树资产ID",supportBinding:!0},shareBlackboard:{type:"boolean",default:!0,description:"是否共享黑板数据"}}})],exports.SubTreeExecutor),exports.BlackboardCompare=class{execute(e){const{runtime:t}=e,r=p.getValue(e,"key",""),o=p.getValue(e,"compareValue"),s=p.getValue(e,"operator","equals");if(!r)return exports.TaskStatus.Failure;const a=t.getBlackboardValue(r);return this.compare(a,o,s)?exports.TaskStatus.Success:exports.TaskStatus.Failure}compare(e,t,r){switch(r){case"equals":return e===t;case"notEquals":return e!==t;case"greaterThan":return e>t;case"lessThan":return e<t;case"greaterOrEqual":return e>=t;case"lessOrEqual":return e<=t;default:return!1}}},exports.BlackboardCompare=c([g({implementationType:"BlackboardCompare",nodeType:r.Condition,displayName:"黑板比较",description:"比较黑板中的值",category:"Condition",configSchema:{key:{type:"string",default:"",description:"黑板变量名"},compareValue:{type:"object",description:"比较值",supportBinding:!0},operator:{type:"string",default:"equals",description:"比较运算符",options:["equals","notEquals","greaterThan","lessThan","greaterOrEqual","lessOrEqual"]}}})],exports.BlackboardCompare),exports.BlackboardExists=class{execute(e){const{runtime:t}=e,r=p.getValue(e,"key",""),o=p.getValue(e,"checkNull",!1);if(!r)return exports.TaskStatus.Failure;const s=t.getBlackboardValue(r);return void 0===s||o&&null===s?exports.TaskStatus.Failure:exports.TaskStatus.Success}},exports.BlackboardExists=c([g({implementationType:"BlackboardExists",nodeType:r.Condition,displayName:"黑板存在",description:"检查黑板中是否存在指定的键",category:"Condition",configSchema:{key:{type:"string",default:"",description:"黑板变量名"},checkNull:{type:"boolean",default:!1,description:"检查是否为null"}}})],exports.BlackboardExists),exports.RandomProbability=class{execute(e){const t=p.getValue(e,"probability",.5),r=Math.max(0,Math.min(1,t));return Math.random()<r?exports.TaskStatus.Success:exports.TaskStatus.Failure}},exports.RandomProbability=c([g({implementationType:"RandomProbability",nodeType:r.Condition,displayName:"随机概率",description:"根据概率返回成功或失败",category:"Condition",configSchema:{probability:{type:"number",default:.5,description:"成功概率(0-1)",min:0,max:1,supportBinding:!0}}})],exports.RandomProbability),exports.ExecuteCondition=class{execute(e){const{runtime:t,entity:r}=e,o=p.getValue(e,"conditionName","");if(!o)return exports.TaskStatus.Failure;const s=t.getBlackboardValue(`condition_${o}`);if(!s||"function"!=typeof s)return exports.TaskStatus.Failure;try{return s(r)?exports.TaskStatus.Success:exports.TaskStatus.Failure}catch(e){return console.error(`ExecuteCondition failed: ${e}`),exports.TaskStatus.Failure}}},exports.ExecuteCondition=c([g({implementationType:"ExecuteCondition",nodeType:r.Condition,displayName:"执行条件",description:"执行自定义条件逻辑",category:"Condition",configSchema:{conditionName:{type:"string",default:"",description:"条件名称(黑板中condition_前缀的函数)"}}})],exports.ExecuteCondition),exports.BehaviorTreeExecutionSystem=class extends t.EntitySystem{constructor(){super(t.Matcher.empty().all(exports.BehaviorTreeRuntimeComponent)),this.assetManager=t.Core.services.resolve(u),this.executorRegistry=new h,this.registerBuiltInExecutors()}registerBuiltInExecutors(){const e=m.getAllExecutorConstructors();for(const[t,r]of e)try{const e=new r;this.executorRegistry.register(t,e)}catch(e){this.logger.error(`注册执行器失败: ${t}`,e)}}getExecutorRegistry(){return this.executorRegistry}process(e){for(const t of e){const e=t.getComponent(exports.BehaviorTreeRuntimeComponent);if(!e.isRunning)continue;const r=this.assetManager.getAsset(e.treeAssetId);r?(e.needsReset&&(e.resetAllStates(),e.needsReset=!1),this.executeTree(t,e,r)):this.logger.warn(`未找到行为树资产: ${e.treeAssetId}`)}}executeTree(e,t,r){const o=r.nodes.get(r.rootNodeId);if(!o)return void this.logger.error(`未找到根节点: ${r.rootNodeId}`);this.executeNode(e,t,o,r)!==exports.TaskStatus.Running?t.needsReset=!0:t.needsReset=!1}executeNode(e,t,r,o){const s=t.getNodeState(r.id);if(t.shouldAbort(r.id)){t.clearAbortRequest(r.id),s.isAborted=!0;const a=this.executorRegistry.get(r.implementationType);if(a&&a.reset){const s=this.createContext(e,t,r,o);a.reset(s)}return t.activeNodeIds.delete(r.id),s.status=exports.TaskStatus.Failure,exports.TaskStatus.Failure}t.activeNodeIds.add(r.id),s.isAborted=!1;const a=this.executorRegistry.get(r.implementationType);if(!a)return this.logger.error(`未找到执行器: ${r.implementationType}`),s.status=exports.TaskStatus.Failure,exports.TaskStatus.Failure;const n=this.createContext(e,t,r,o);try{const e=a.execute(n);return s.status=e,e!==exports.TaskStatus.Running&&(t.activeNodeIds.delete(r.id),a.reset&&a.reset(n)),e}catch(e){return this.logger.error(`执行节点时发生错误: ${r.name}`,e),s.status=exports.TaskStatus.Failure,t.activeNodeIds.delete(r.id),exports.TaskStatus.Failure}}createContext(e,r,o,s){return{entity:e,nodeData:o,state:r.getNodeState(o.id),runtime:r,treeData:s,deltaTime:t.Time.deltaTime,totalTime:t.Time.totalTime,executeChild:t=>{const o=s.nodes.get(t);return o?this.executeNode(e,r,o,s):(this.logger.warn(`未找到子节点: ${t}`),exports.TaskStatus.Failure)}}}executeChildren(e,t){const{nodeData:r,treeData:o,entity:s,runtime:a}=e;if(!r.children||0===r.children.length)return[];const n=[],i=t||Array.from({length:r.children.length},((e,t)=>t));for(const e of i){if(e>=r.children.length)continue;const t=r.children[e],i=o.nodes.get(t);if(!i){this.logger.warn(`未找到子节点: ${t}`),n.push(exports.TaskStatus.Failure);continue}const c=this.executeNode(s,a,i,o);n.push(c)}return n}},exports.BehaviorTreeExecutionSystem=c([t.ECSSystem("BehaviorTreeExecution"),d("design:paramtypes",[])],exports.BehaviorTreeExecutionSystem);class y{constructor(e){this.nodeStack=[],this.nodeIdCounter=0,this.treeData={id:`tree_${Date.now()}`,name:e,rootNodeId:"",nodes:new Map,blackboardVariables:new Map}}static create(e="BehaviorTree"){return new y(e)}defineBlackboardVariable(e,t){return this.treeData.blackboardVariables||(this.treeData.blackboardVariables=new Map),this.treeData.blackboardVariables.set(e,t),this}sequence(e){return this.addCompositeNode("Sequence",e||"Sequence")}selector(e){return this.addCompositeNode("Selector",e||"Selector")}parallel(e,t){return this.addCompositeNode("Parallel",e||"Parallel",t)}parallelSelector(e,t){return this.addCompositeNode("ParallelSelector",e||"ParallelSelector",t)}randomSequence(e){return this.addCompositeNode("RandomSequence",e||"RandomSequence")}randomSelector(e){return this.addCompositeNode("RandomSelector",e||"RandomSelector")}inverter(e){return this.addDecoratorNode("Inverter",e||"Inverter")}repeater(e,t){return this.addDecoratorNode("Repeater",t||"Repeater",{repeatCount:e})}alwaysSucceed(e){return this.addDecoratorNode("AlwaysSucceed",e||"AlwaysSucceed")}alwaysFail(e){return this.addDecoratorNode("AlwaysFail",e||"AlwaysFail")}untilSuccess(e){return this.addDecoratorNode("UntilSuccess",e||"UntilSuccess")}untilFail(e){return this.addDecoratorNode("UntilFail",e||"UntilFail")}conditional(e,t,r,o){return this.addDecoratorNode("Conditional",o||"Conditional",{blackboardKey:e,expectedValue:t,operator:r||"equals"})}cooldown(e,t){return this.addDecoratorNode("Cooldown",t||"Cooldown",{cooldownTime:e})}timeout(e,t){return this.addDecoratorNode("Timeout",t||"Timeout",{timeout:e})}wait(e,t){return this.addActionNode("Wait",t||"Wait",{duration:e})}log(e,t){return this.addActionNode("Log",t||"Log",{message:e})}setBlackboardValue(e,t,r){return this.addActionNode("SetBlackboardValue",r||"SetBlackboardValue",{key:e,value:t})}modifyBlackboardValue(e,t,r,o){return this.addActionNode("ModifyBlackboardValue",o||"ModifyBlackboardValue",{key:e,operation:t,value:r})}executeAction(e,t){return this.addActionNode("ExecuteAction",t||"ExecuteAction",{actionName:e})}blackboardCompare(e,t,r,o){return this.addConditionNode("BlackboardCompare",o||"BlackboardCompare",{key:e,compareValue:t,operator:r||"equals"})}blackboardExists(e,t){return this.addConditionNode("BlackboardExists",t||"BlackboardExists",{key:e})}randomProbability(e,t){return this.addConditionNode("RandomProbability",t||"RandomProbability",{probability:e})}executeCondition(e,t){return this.addConditionNode("ExecuteCondition",t||"ExecuteCondition",{conditionName:e})}end(){return this.nodeStack.length>0&&this.nodeStack.pop(),this}build(){if(!this.treeData.rootNodeId)throw new Error("No root node defined. Add at least one node to the tree.");return this.treeData}addCompositeNode(e,t,o={}){const s=this.generateNodeId(),a={id:s,name:t,nodeType:r.Composite,implementationType:e,children:[],config:o};if(this.treeData.nodes.set(s,a),this.treeData.rootNodeId||(this.treeData.rootNodeId=s),this.nodeStack.length>0){const e=this.nodeStack[this.nodeStack.length-1],t=this.treeData.nodes.get(e);t&&t.children&&t.children.push(s)}return this.nodeStack.push(s),this}addDecoratorNode(e,t,o={}){const s=this.generateNodeId(),a={id:s,name:t,nodeType:r.Decorator,implementationType:e,children:[],config:o};if(this.treeData.nodes.set(s,a),this.treeData.rootNodeId||(this.treeData.rootNodeId=s),this.nodeStack.length>0){const e=this.nodeStack[this.nodeStack.length-1],t=this.treeData.nodes.get(e);t&&t.children&&t.children.push(s)}return this.nodeStack.push(s),this}addActionNode(e,t,o={}){const s=this.generateNodeId(),a={id:s,name:t,nodeType:r.Action,implementationType:e,config:o};if(this.treeData.nodes.set(s,a),this.treeData.rootNodeId||(this.treeData.rootNodeId=s),this.nodeStack.length>0){const e=this.nodeStack[this.nodeStack.length-1],t=this.treeData.nodes.get(e);t&&t.children&&t.children.push(s)}return this}addConditionNode(e,t,o={}){const s=this.generateNodeId(),a={id:s,name:t,nodeType:r.Condition,implementationType:e,config:o};if(this.treeData.nodes.set(s,a),this.treeData.rootNodeId||(this.treeData.rootNodeId=s),this.nodeStack.length>0){const e=this.nodeStack[this.nodeStack.length-1],t=this.treeData.nodes.get(e);t&&t.children&&t.children.push(s)}return this}generateNodeId(){return"node_"+this.nodeIdCounter++}}const S={String:"string",Number:"number",Boolean:"boolean",Select:"select",Blackboard:"blackboard",Code:"code",Variable:"variable",Asset:"asset"};class f{static validate(e){const t=[],r=[];if(e.version||t.push("Missing version field"),e.metadata&&e.metadata.name||t.push("Missing or invalid metadata"),e.rootNodeId||t.push("Missing rootNodeId"),e.nodes&&Array.isArray(e.nodes)){const o=new Set;e.nodes.find((t=>t.id===e.rootNodeId))||t.push(`Root node '${e.rootNodeId}' not found in nodes array`);for(const r of e.nodes)if(r.id){if(o.has(r.id)&&t.push(`Duplicate node id: ${r.id}`),o.add(r.id),r.nodeType||t.push(`Node ${r.id} missing nodeType`),r.children)for(const o of r.children)e.nodes.find((e=>e.id===o))||t.push(`Node ${r.id} references non-existent child: ${o}`)}else t.push("Node missing id field");const s=new Set([e.rootNodeId]),a=t=>{const r=e.nodes.find((e=>e.id===t));if(r&&r.children)for(const e of r.children)s.add(e),a(e)};a(e.rootNodeId);for(const t of e.nodes)s.has(t.id)||r.push(`Orphaned node detected: ${t.id} (${t.name})`)}else t.push("Missing or invalid nodes array");if(e.blackboard&&Array.isArray(e.blackboard)){const r=new Set;for(const o of e.blackboard)o.name?(r.has(o.name)&&t.push(`Duplicate blackboard variable: ${o.name}`),r.add(o.name),o.type||t.push(`Blackboard variable ${o.name} missing type`)):t.push("Blackboard variable missing name")}if(e.propertyBindings&&Array.isArray(e.propertyBindings)){const r=new Set(e.nodes.map((e=>e.id))),o=new Set(e.blackboard?.map((e=>e.name))||[]);for(const s of e.propertyBindings)r.has(s.nodeId)||t.push(`Property binding references non-existent node: ${s.nodeId}`),o.has(s.variableName)||t.push(`Property binding references non-existent variable: ${s.variableName}`),s.propertyName||t.push("Property binding missing propertyName")}const o={valid:0===t.length};return t.length>0&&(o.errors=t),r.length>0&&(o.warnings=r),o}static getStats(e){let t=0,o=0,s=0,a=0;for(const n of e.nodes)switch(n.nodeType){case r.Action:t++;break;case r.Condition:o++;break;case r.Composite:s++;break;case r.Decorator:a++}const n=(t,r=0)=>{const o=e.nodes.find((e=>e.id===t));if(!o||!o.children||0===o.children.length)return r;let s=r;for(const e of o.children){const t=n(e,r+1);s=Math.max(s,t)}return s};return{nodeCount:e.nodes.length,actionCount:t,conditionCount:o,compositeCount:s,decoratorCount:a,blackboardVariableCount:e.blackboard?.length||0,propertyBindingCount:e.propertyBindings?.length||0,maxDepth:n(e.rootNodeId)}}}const T=t.createLogger("EditorFormatConverter");class b{static toAsset(e,t){T.info("开始转换编辑器格式到资产格式");const r=this.findRootNode(e.nodes);if(!r)throw new Error("未找到根节点");const o={name:t?.name||e.metadata?.name||"Untitled Behavior Tree",version:t?.version||e.version||"1.0.0"},s=t?.description||e.metadata?.description;s&&(o.description=s);const a=t?.createdAt||e.metadata?.createdAt;a&&(o.createdAt=a);const n=t?.modifiedAt||(new Date).toISOString();n&&(o.modifiedAt=n);const i=this.convertNodes(e.nodes),c=this.convertBlackboard(e.blackboard),d=this.convertPropertyBindings(e.connections,e.nodes,c),l={version:"1.0.0",metadata:o,rootNodeId:r.id,nodes:i,blackboard:c};return d.length>0&&(l.propertyBindings=d),T.info(`转换完成: ${i.length}个节点, ${c.length}个黑板变量, ${d.length}个属性绑定`),l}static findRootNode(e){return e.find((e=>"根节点"===e.template.category||"root"===e.data.nodeType))||null}static convertNodes(e){return e.map((e=>this.convertNode(e)))}static convertNode(e){const t={...e.data};return delete t.nodeType,e.template.className&&(t.className=e.template.className),{id:e.id,name:e.template.displayName||e.data.name||"Node",nodeType:e.template.type,data:t,children:e.children||[]}}static convertBlackboard(e){const t=[];for(const[r,o]of Object.entries(e)){const e=this.inferBlackboardType(o);t.push({name:r,type:e,defaultValue:o})}return t}static inferBlackboardType(e){return"number"==typeof e?exports.BlackboardValueType.Number:"string"==typeof e?exports.BlackboardValueType.String:"boolean"==typeof e?exports.BlackboardValueType.Boolean:exports.BlackboardValueType.Object}static convertPropertyBindings(e,t,r){const o=[],s=new Set(r.map((e=>e.name))),a=e.filter((e=>"property"===e.connectionType));for(const e of a){const r=t.find((t=>t.id===e.from)),a=t.find((t=>t.id===e.to));if(!r||!a||!e.toProperty){T.warn(`跳过无效的属性连接: from=${e.from}, to=${e.to}`);continue}let n;"blackboard-variable"===r.data.nodeType?n=r.data.variableName:e.fromProperty&&(n=e.fromProperty),n?s.has(n)?o.push({nodeId:a.id,propertyName:e.toProperty,variableName:n}):T.warn(`属性绑定引用了不存在的黑板变量: ${n}`):T.warn(`无法确定变量名: from节点=${r.template.displayName}`)}return o}static fromAsset(e){T.info("开始转换资产格式到编辑器格式");const t=this.convertNodesFromAsset(e.nodes),r={};for(const t of e.blackboard)r[t.name]=t.defaultValue;const o=this.convertPropertyBindingsToConnections(e.propertyBindings||[]),s=this.buildNodeConnections(e.nodes);o.push(...s);const a={name:e.metadata.name};e.metadata.description&&(a.description=e.metadata.description),e.metadata.createdAt&&(a.createdAt=e.metadata.createdAt),e.metadata.modifiedAt&&(a.modifiedAt=e.metadata.modifiedAt);const n={version:e.metadata.version,metadata:a,nodes:t,connections:o,blackboard:r,canvasState:{offset:{x:0,y:0},scale:1}};return T.info(`转换完成: ${t.length}个节点, ${o.length}个连接`),n}static convertNodesFromAsset(e){return e.map(((e,t)=>{const r={x:100+t%5*250,y:100+150*Math.floor(t/5)},o={displayName:e.name,category:this.inferCategory(e.nodeType),type:e.nodeType};return e.data.className&&(o.className=e.data.className),{id:e.id,template:o,data:{...e.data},position:r,children:e.children}}))}static inferCategory(e){switch(e){case r.Action:return"动作";case r.Condition:return"条件";case r.Composite:return"组合";case r.Decorator:return"装饰器";default:return"其他"}}static convertPropertyBindingsToConnections(e){const t=[];for(const r of e)t.push({from:"blackboard",to:r.nodeId,toProperty:r.propertyName,connectionType:"property"});return t}static buildNodeConnections(e){const t=[];for(const r of e)for(const e of r.children)t.push({from:r.id,to:e,connectionType:"node"});return t}}const k=t.createLogger("BehaviorTreeAssetSerializer");class C{constructor(){this.variables=new Map}dispose(){this.variables.clear()}defineVariable(e,t,r,o){const s={name:e,type:t,value:r,readonly:o?.readonly??!1};void 0!==o?.description&&(s.description=o.description),this.variables.set(e,s)}getValue(e){const t=this.variables.get(e);return t?.value}setValue(e,t,r=!1){const o=this.variables.get(e);return!!o&&(!(o.readonly&&!r)&&(o.value=t,!0))}hasVariable(e){return this.variables.has(e)}removeVariable(e){return this.variables.delete(e)}getVariableNames(){return Array.from(this.variables.keys())}getAllVariables(){return Array.from(this.variables.values())}clear(){this.variables.clear()}setVariables(e){for(const[t,r]of Object.entries(e)){const e=this.variables.get(t);e&&!e.readonly&&(e.value=r)}}getVariables(e){const t={};for(const r of e){const e=this.getValue(r);void 0!==e&&(t[r]=e)}return t}exportConfig(){return{version:"1.0",variables:Array.from(this.variables.values())}}importConfig(e){this.variables.clear();for(const t of e.variables)this.variables.set(t.name,t)}toJSON(){return JSON.stringify(this.exportConfig(),null,2)}static fromJSON(e){return JSON.parse(e)}}exports.BehaviorTreeAssetManager=u,exports.BehaviorTreeAssetSerializer=class{static serialize(e,t={format:"json",pretty:!0}){if(!1!==t.validate){const t=f.validate(e);if(!t.valid){const e=t.errors?.join(", ")||"Unknown error";throw new Error(`资产验证失败: ${e}`)}t.warnings&&t.warnings.length>0&&k.warn(`资产验证警告: ${t.warnings.join(", ")}`)}return"json"===t.format?this.serializeToJSON(e,t.pretty):this.serializeToBinary(e)}static serializeToJSON(e,t=!0){try{const r=t?JSON.stringify(e,null,2):JSON.stringify(e);return k.info(`已序列化为JSON: ${r.length} 字符`),r}catch(e){throw new Error(`JSON序列化失败: ${e}`)}}static serializeToBinary(e){try{const r=t.BinarySerializer.encode(e);return k.info(`已序列化为二进制: ${r.length} 字节`),r}catch(e){throw new Error(`二进制序列化失败: ${e}`)}}static deserialize(e,t={validate:!0,strict:!0}){let r;try{r="string"==typeof e?this.deserializeFromJSON(e):this.deserializeFromBinary(e)}catch(e){throw new Error(`反序列化失败: ${e}`)}if(!1!==t.validate){const e=f.validate(r);if(!e.valid){const r=e.errors?.join(", ")||"Unknown error";if(t.strict)throw new Error(`资产验证失败: ${r}`);k.error(`资产验证失败: ${r}`)}e.warnings&&e.warnings.length>0&&k.warn(`资产验证警告: ${e.warnings.join(", ")}`)}return r}static deserializeFromJSON(e){try{const t=JSON.parse(e);if(!t.rootNodeId&&t.nodes&&t.connections){k.info("检测到编辑器格式,正在转换为运行时资产格式...");const e=t,r=b.toAsset(e);return k.info(`已从编辑器格式转换: ${r.nodes.length} 个节点`),r}{const e=t;return k.info(`已从运行时资产格式反序列化: ${e.nodes.length} 个节点`),e}}catch(e){throw new Error(`JSON解析失败: ${e}`)}}static deserializeFromBinary(e){try{const r=t.BinarySerializer.decode(e);return k.info(`已从二进制反序列化: ${r.nodes.length} 个节点`),r}catch(e){throw new Error(`二进制解码失败: ${e}`)}}static detectFormat(e){return"string"==typeof e?"json":"binary"}static getInfo(e){try{const r=this.detectFormat(e);let o;o="json"===r?JSON.parse(e):t.BinarySerializer.decode(e);const s=e.length;return{format:r,name:o.metadata.name,version:o.version,nodeCount:o.nodes.length,blackboardVariableCount:o.blackboard.length,size:s}}catch(e){return k.error(`获取资产信息失败: ${e}`),null}}static convert(e,t,r=!0){const o=this.deserialize(e,{validate:!1});return this.serialize(o,{format:t,pretty:r,validate:!1})}static compareSize(e,t){const r=e.length,o=t.length,s=r-o;return{jsonSize:r,binarySize:o,compressionRatio:s/r*100,savedBytes:s}}},exports.BehaviorTreeAssetValidator=f,exports.BehaviorTreeBuilder=y,exports.BehaviorTreePlugin=class{constructor(){this.name="@esengine/behavior-tree",this.version="1.0.0",this.worldManager=null,this.services=null}async install(e,r){this.services=r,r.registerSingleton(C),r.registerSingleton(u),this.worldManager=r.resolve(t.WorldManager)}async uninstall(){this.services&&(this.services.unregister(C),this.services.unregister(u)),this.worldManager=null,this.services=null}setupScene(e){e.addSystem(new exports.BehaviorTreeExecutionSystem)}setupAllScenes(){if(!this.worldManager)throw new Error("Plugin not installed");const e=this.worldManager.getAllWorlds();for(const t of e)for(const e of t.getAllScenes())this.setupScene(e)}},exports.BehaviorTreeStarter=class{static start(e,r,o=!0){t.Core.services.resolve(u).loadAsset(r);let s=e.getComponent(exports.BehaviorTreeRuntimeComponent);if(s||(s=new exports.BehaviorTreeRuntimeComponent,e.addComponent(s)),s.treeAssetId=r.id,s.autoStart=o,r.blackboardVariables)for(const[e,t]of r.blackboardVariables.entries())s.setBlackboardValue(e,t);o&&(s.isRunning=!0)}static stop(e){const t=e.getComponent(exports.BehaviorTreeRuntimeComponent);t&&(t.isRunning=!1,t.resetAllStates())}static pause(e){const t=e.getComponent(exports.BehaviorTreeRuntimeComponent);t&&(t.isRunning=!1)}static resume(e){const t=e.getComponent(exports.BehaviorTreeRuntimeComponent);t&&(t.isRunning=!0)}static restart(e){const t=e.getComponent(exports.BehaviorTreeRuntimeComponent);t&&(t.resetAllStates(),t.isRunning=!0)}},exports.BindingHelper=p,exports.EditorFormatConverter=b,exports.GlobalBlackboardService=C,exports.NodeExecutorMetadata=g,exports.NodeExecutorRegistry=h,exports.NodeMetadataRegistry=m,exports.NodeTemplates=class{static getAllTemplates(){return m.getAllMetadata().map((e=>this.convertMetadataToTemplate(e)))}static getTemplate(e,t){return this.getAllTemplates().find((o=>{if(o.type!==e)return!1;const s=o.defaultConfig;switch(e){case r.Composite:return s.compositeType===t;case r.Decorator:return s.decoratorType===t;case r.Action:return s.actionType===t;case r.Condition:return s.conditionType===t;default:return!1}}))}static convertMetadataToTemplate(e){const t=this.convertConfigSchemaToProperties(e.configSchema||{}),o={nodeType:this.nodeTypeToString(e.nodeType)};switch(e.nodeType){case r.Composite:o.compositeType=e.implementationType;break;case r.Decorator:o.decoratorType=e.implementationType;break;case r.Action:o.actionType=e.implementationType;break;case r.Condition:o.conditionType=e.implementationType}if(e.configSchema)for(const[t,r]of Object.entries(e.configSchema)){const e=r;void 0!==e.default&&(o[t]=e.default)}const{icon:s,color:a}=this.getIconAndColorByType(e.nodeType,e.category||"");return{type:e.nodeType,displayName:e.displayName,category:e.category||this.getCategoryByNodeType(e.nodeType),description:e.description||"",className:e.implementationType,icon:s,color:a,defaultConfig:o,properties:t}}static convertConfigSchemaToProperties(e){const t=[];for(const[r,o]of Object.entries(e)){const e={name:r,type:this.mapFieldTypeToPropertyType(o),label:r};void 0!==o.description&&(e.description=o.description),void 0!==o.default&&(e.defaultValue=o.default),void 0!==o.min&&(e.min=o.min),void 0!==o.max&&(e.max=o.max),void 0!==o.allowMultipleConnections&&(e.allowMultipleConnections=o.allowMultipleConnections),o.options&&(e.options=o.options.map((e=>({label:e,value:e})))),o.supportBinding&&(e.renderConfig={component:"BindableInput",props:{supportBinding:!0}}),t.push(e)}return t}static mapFieldTypeToPropertyType(e){if(e.options&&e.options.length>0)return S.Select;switch(e.type){case"string":case"array":case"object":default:return S.String;case"number":return S.Number;case"boolean":return S.Boolean}}static nodeTypeToString(e){switch(e){case r.Composite:return"composite";case r.Decorator:return"decorator";case r.Action:return"action";case r.Condition:return"condition";default:return"unknown"}}static getCategoryByNodeType(e){switch(e){case r.Composite:return"组合";case r.Decorator:return"装饰器";case r.Action:return"动作";case r.Condition:return"条件";default:return"其他"}}static getIconAndColorByType(e,t){switch(e){case r.Composite:return{icon:"GitBranch",color:"#1976d2"};case r.Decorator:return{icon:"Settings",color:"#fb8c00"};case r.Action:return{icon:"Play",color:"#388e3c"};case r.Condition:return{icon:"HelpCircle",color:"#d32f2f"};default:return{icon:"Circle",color:"#757575"}}}},exports.NodeType=r,exports.PropertyType=S,exports.ServiceRegistry=x,exports.createDefaultRuntimeState=i;
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|