@eva/plugin-trigger 2.1.0-beta.1 → 2.1.0-beta.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/dist/plugin-trigger.cjs.js +175 -0
- package/dist/plugin-trigger.cjs.prod.js +1 -0
- package/dist/plugin-trigger.d.ts +89 -0
- package/dist/plugin-trigger.esm.js +171 -0
- package/index.js +7 -0
- package/package.json +8 -7
- package/lib/Trigger.ts +0 -127
- package/lib/TriggerSystem.ts +0 -6
- package/lib/index.ts +0 -3
- package/lib/types.ts +0 -22
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var eva_js = require('@eva/eva.js');
|
|
6
|
+
var pluginSignalBus = require('@eva/plugin-signal-bus');
|
|
7
|
+
|
|
8
|
+
/******************************************************************************
|
|
9
|
+
Copyright (c) Microsoft Corporation.
|
|
10
|
+
|
|
11
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
12
|
+
purpose with or without fee is hereby granted.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
15
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
16
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
17
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
18
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
19
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
20
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
21
|
+
***************************************************************************** */
|
|
22
|
+
|
|
23
|
+
function __decorate(decorators, target, key, desc) {
|
|
24
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
25
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
26
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
27
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
31
|
+
var e = new Error(message);
|
|
32
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Trigger 组件 — 把信号映射成 DSL 动作。
|
|
37
|
+
*
|
|
38
|
+
* DSL 用法:
|
|
39
|
+
* ```json
|
|
40
|
+
* {
|
|
41
|
+
* "type": "Trigger",
|
|
42
|
+
* "props": {
|
|
43
|
+
* "rules": [
|
|
44
|
+
* { "on": "input:fire:press",
|
|
45
|
+
* "do": [
|
|
46
|
+
* { "type": "emit", "signal": "rocket:spawn" },
|
|
47
|
+
* { "type": "incStore", "key": "shotsFired" }
|
|
48
|
+
* ] },
|
|
49
|
+
* { "on": "rocket:hit",
|
|
50
|
+
* "guard": "ctx.allowedScene === true",
|
|
51
|
+
* "do": [
|
|
52
|
+
* { "type": "incStore", "key": "score" },
|
|
53
|
+
* { "type": "emit", "signal": "monster:hurt" }
|
|
54
|
+
* ] }
|
|
55
|
+
* ]
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* 这是 plugin-state-machine 的"无状态弟弟":只配 input → output,不维护 state。
|
|
61
|
+
* 适合写 80% 的"按钮按下→记分"业务,大幅减少自定义 Component 数量。
|
|
62
|
+
*/
|
|
63
|
+
exports.Trigger = class Trigger extends eva_js.Component {
|
|
64
|
+
constructor() {
|
|
65
|
+
super(...arguments);
|
|
66
|
+
this.rules = [];
|
|
67
|
+
this.subs = [];
|
|
68
|
+
this.ctx = {};
|
|
69
|
+
}
|
|
70
|
+
init(params) {
|
|
71
|
+
var _a, _b;
|
|
72
|
+
if (!params)
|
|
73
|
+
return;
|
|
74
|
+
this.rules = (_a = params.rules) !== null && _a !== void 0 ? _a : [];
|
|
75
|
+
this.ctx = (_b = params.context) !== null && _b !== void 0 ? _b : {};
|
|
76
|
+
}
|
|
77
|
+
awake() {
|
|
78
|
+
const bus = pluginSignalBus.getSignalBus();
|
|
79
|
+
for (const rule of this.rules) {
|
|
80
|
+
const h = bus.on(rule.on, (payload) => {
|
|
81
|
+
if (rule.guard && !this.evalGuard(rule.guard, payload))
|
|
82
|
+
return;
|
|
83
|
+
for (const a of rule.do)
|
|
84
|
+
this.exec(a, payload);
|
|
85
|
+
});
|
|
86
|
+
this.subs.push(h);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exec(action, payload) {
|
|
90
|
+
var _a, _b, _c, _d;
|
|
91
|
+
try {
|
|
92
|
+
switch (action.type) {
|
|
93
|
+
case 'emit':
|
|
94
|
+
pluginSignalBus.getSignalBus().emit(action.signal, (_a = action.payload) !== null && _a !== void 0 ? _a : payload);
|
|
95
|
+
break;
|
|
96
|
+
case 'setStore':
|
|
97
|
+
if (typeof mx !== 'undefined' && ((_b = mx === null || mx === void 0 ? void 0 : mx.store) === null || _b === void 0 ? void 0 : _b.update)) {
|
|
98
|
+
mx.store.update(action.key, () => action.value);
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
case 'incStore':
|
|
102
|
+
if (typeof mx !== 'undefined' && ((_c = mx === null || mx === void 0 ? void 0 : mx.store) === null || _c === void 0 ? void 0 : _c.update)) {
|
|
103
|
+
mx.store.update(action.key, (v) => { var _a; return (v !== null && v !== void 0 ? v : 0) + ((_a = action.delta) !== null && _a !== void 0 ? _a : 1); });
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
case 'log':
|
|
107
|
+
// eslint-disable-next-line no-console
|
|
108
|
+
console.log('[trigger]', action.message, payload);
|
|
109
|
+
break;
|
|
110
|
+
case 'callMethod':
|
|
111
|
+
this.callMethod(action.entity, action.component, action.method, (_d = action.args) !== null && _d !== void 0 ? _d : []);
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
// eslint-disable-next-line no-console
|
|
117
|
+
console.warn('[plugin-trigger] action failed', action, err);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
callMethod(entity, compName, method, args) {
|
|
121
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
122
|
+
const game = (_b = (_a = this.gameObject) === null || _a === void 0 ? void 0 : _a.scene) === null || _b === void 0 ? void 0 : _b.game;
|
|
123
|
+
if (!game)
|
|
124
|
+
return;
|
|
125
|
+
const stack = [...((_d = (_c = game.scene) === null || _c === void 0 ? void 0 : _c.gameObjects) !== null && _d !== void 0 ? _d : [])];
|
|
126
|
+
while (stack.length) {
|
|
127
|
+
const go = stack.pop();
|
|
128
|
+
if (!go)
|
|
129
|
+
continue;
|
|
130
|
+
if (go.name === entity) {
|
|
131
|
+
const comps = (_e = go.components) !== null && _e !== void 0 ? _e : [];
|
|
132
|
+
const c = comps.find((c) => { var _a; return ((_a = c === null || c === void 0 ? void 0 : c.constructor) === null || _a === void 0 ? void 0 : _a.componentName) === compName; });
|
|
133
|
+
if (c && typeof c[method] === 'function') {
|
|
134
|
+
c[method](...args);
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if ((_g = (_f = go.transform) === null || _f === void 0 ? void 0 : _f.children) === null || _g === void 0 ? void 0 : _g.length) {
|
|
139
|
+
for (const ch of go.transform.children)
|
|
140
|
+
stack.push(ch.gameObject);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
evalGuard(guard, payload) {
|
|
145
|
+
try {
|
|
146
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
|
|
147
|
+
const fn = new Function('payload', 'ctx', `return (${guard});`);
|
|
148
|
+
return Boolean(fn(payload, this.ctx));
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
// eslint-disable-next-line no-console
|
|
152
|
+
console.warn(`[plugin-trigger] bad guard "${guard}":`, err);
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
onDestroy() {
|
|
157
|
+
for (const h of this.subs)
|
|
158
|
+
h.dispose();
|
|
159
|
+
this.subs = [];
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
exports.Trigger.componentName = 'Trigger';
|
|
163
|
+
exports.Trigger = __decorate([
|
|
164
|
+
eva_js.decorators.componentObserver({})
|
|
165
|
+
], exports.Trigger);
|
|
166
|
+
|
|
167
|
+
class TriggerSystem extends eva_js.System {
|
|
168
|
+
constructor() {
|
|
169
|
+
super(...arguments);
|
|
170
|
+
this.name = 'Trigger';
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
TriggerSystem.systemName = 'Trigger';
|
|
174
|
+
|
|
175
|
+
exports.TriggerSystem = TriggerSystem;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("@eva/eva.js"),t=require("@eva/plugin-signal-bus");"function"==typeof SuppressedError&&SuppressedError,exports.Trigger=class extends e.Component{constructor(){super(...arguments),this.rules=[],this.subs=[],this.ctx={}}init(e){var t,o;e&&(this.rules=null!==(t=e.rules)&&void 0!==t?t:[],this.ctx=null!==(o=e.context)&&void 0!==o?o:{})}awake(){const e=t.getSignalBus();for(const t of this.rules){const o=e.on(t.on,e=>{if(!t.guard||this.evalGuard(t.guard,e))for(const o of t.do)this.exec(o,e)});this.subs.push(o)}}exec(e,o){var r,n,s,i;try{switch(e.type){case"emit":t.getSignalBus().emit(e.signal,null!==(r=e.payload)&&void 0!==r?r:o);break;case"setStore":"undefined"!=typeof mx&&(null===(n=null===mx||void 0===mx?void 0:mx.store)||void 0===n?void 0:n.update)&&mx.store.update(e.key,()=>e.value);break;case"incStore":"undefined"!=typeof mx&&(null===(s=null===mx||void 0===mx?void 0:mx.store)||void 0===s?void 0:s.update)&&mx.store.update(e.key,t=>{var o;return(null!=t?t:0)+(null!==(o=e.delta)&&void 0!==o?o:1)});break;case"log":console.log("[trigger]",e.message,o);break;case"callMethod":this.callMethod(e.entity,e.component,e.method,null!==(i=e.args)&&void 0!==i?i:[])}}catch(t){console.warn("[plugin-trigger] action failed",e,t)}}callMethod(e,t,o,r){var n,s,i,l,a,c,u;const d=null===(s=null===(n=this.gameObject)||void 0===n?void 0:n.scene)||void 0===s?void 0:s.game;if(!d)return;const g=[...null!==(l=null===(i=d.scene)||void 0===i?void 0:i.gameObjects)&&void 0!==l?l:[]];for(;g.length;){const n=g.pop();if(n){if(n.name===e){const e=(null!==(a=n.components)&&void 0!==a?a:[]).find(e=>{var o;return(null===(o=null==e?void 0:e.constructor)||void 0===o?void 0:o.componentName)===t});return void(e&&"function"==typeof e[o]&&e[o](...r))}if(null===(u=null===(c=n.transform)||void 0===c?void 0:c.children)||void 0===u?void 0:u.length)for(const e of n.transform.children)g.push(e.gameObject)}}}evalGuard(e,t){try{const o=new Function("payload","ctx",`return (${e});`);return Boolean(o(t,this.ctx))}catch(t){return console.warn(`[plugin-trigger] bad guard "${e}":`,t),!1}}onDestroy(){for(const e of this.subs)e.dispose();this.subs=[]}},exports.Trigger.componentName="Trigger",exports.Trigger=function(e,t,o,r){var n,s=arguments.length,i=s<3?t:null===r?r=Object.getOwnPropertyDescriptor(t,o):r;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)i=Reflect.decorate(e,t,o,r);else for(var l=e.length-1;l>=0;l--)(n=e[l])&&(i=(s<3?n(i):s>3?n(t,o,i):n(t,o))||i);return s>3&&i&&Object.defineProperty(t,o,i),i}([e.decorators.componentObserver({})],exports.Trigger);class o extends e.System{constructor(){super(...arguments),this.name="Trigger"}}o.systemName="Trigger",exports.TriggerSystem=o;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Component } from '@eva/eva.js';
|
|
2
|
+
import { System } from '@eva/eva.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Trigger 组件 — 把信号映射成 DSL 动作。
|
|
6
|
+
*
|
|
7
|
+
* DSL 用法:
|
|
8
|
+
* ```json
|
|
9
|
+
* {
|
|
10
|
+
* "type": "Trigger",
|
|
11
|
+
* "props": {
|
|
12
|
+
* "rules": [
|
|
13
|
+
* { "on": "input:fire:press",
|
|
14
|
+
* "do": [
|
|
15
|
+
* { "type": "emit", "signal": "rocket:spawn" },
|
|
16
|
+
* { "type": "incStore", "key": "shotsFired" }
|
|
17
|
+
* ] },
|
|
18
|
+
* { "on": "rocket:hit",
|
|
19
|
+
* "guard": "ctx.allowedScene === true",
|
|
20
|
+
* "do": [
|
|
21
|
+
* { "type": "incStore", "key": "score" },
|
|
22
|
+
* { "type": "emit", "signal": "monster:hurt" }
|
|
23
|
+
* ] }
|
|
24
|
+
* ]
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* 这是 plugin-state-machine 的"无状态弟弟":只配 input → output,不维护 state。
|
|
30
|
+
* 适合写 80% 的"按钮按下→记分"业务,大幅减少自定义 Component 数量。
|
|
31
|
+
*/
|
|
32
|
+
export declare class Trigger extends Component<TriggerParams> {
|
|
33
|
+
static componentName: string;
|
|
34
|
+
private rules;
|
|
35
|
+
private subs;
|
|
36
|
+
ctx: Record<string, any>;
|
|
37
|
+
init(params?: TriggerParams): void;
|
|
38
|
+
awake(): void;
|
|
39
|
+
private exec;
|
|
40
|
+
private callMethod;
|
|
41
|
+
private evalGuard;
|
|
42
|
+
onDestroy(): void;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** 单条 action,DSL 描述时只填 type + 字段 */
|
|
46
|
+
export declare type TriggerAction = {
|
|
47
|
+
type: 'emit';
|
|
48
|
+
signal: string;
|
|
49
|
+
payload?: any;
|
|
50
|
+
} | {
|
|
51
|
+
type: 'setStore';
|
|
52
|
+
key: string;
|
|
53
|
+
value: any;
|
|
54
|
+
} | {
|
|
55
|
+
type: 'incStore';
|
|
56
|
+
key: string;
|
|
57
|
+
delta?: number;
|
|
58
|
+
} | {
|
|
59
|
+
type: 'log';
|
|
60
|
+
message: string;
|
|
61
|
+
} | {
|
|
62
|
+
type: 'callMethod';
|
|
63
|
+
entity: string;
|
|
64
|
+
component: string;
|
|
65
|
+
method: string;
|
|
66
|
+
args?: any[];
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export declare interface TriggerParams {
|
|
70
|
+
rules: TriggerRule[];
|
|
71
|
+
/** ctx 变量,可在 guard 中读 */
|
|
72
|
+
context?: Record<string, any>;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export declare interface TriggerRule {
|
|
76
|
+
/** 监听的信号名 */
|
|
77
|
+
on: string;
|
|
78
|
+
/** 命中后执行的动作列表 */
|
|
79
|
+
do: TriggerAction[];
|
|
80
|
+
/** 可选:JS 表达式;以 (payload, ctx) 为变量,假则跳过 */
|
|
81
|
+
guard?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export declare class TriggerSystem extends System {
|
|
85
|
+
static systemName: string;
|
|
86
|
+
readonly name = "Trigger";
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { }
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { Component, decorators, System } from '@eva/eva.js';
|
|
2
|
+
import { getSignalBus } from '@eva/plugin-signal-bus';
|
|
3
|
+
|
|
4
|
+
/******************************************************************************
|
|
5
|
+
Copyright (c) Microsoft Corporation.
|
|
6
|
+
|
|
7
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
8
|
+
purpose with or without fee is hereby granted.
|
|
9
|
+
|
|
10
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
11
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
12
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
13
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
14
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
15
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
16
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
17
|
+
***************************************************************************** */
|
|
18
|
+
|
|
19
|
+
function __decorate(decorators, target, key, desc) {
|
|
20
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
21
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
22
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
23
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
27
|
+
var e = new Error(message);
|
|
28
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Trigger 组件 — 把信号映射成 DSL 动作。
|
|
33
|
+
*
|
|
34
|
+
* DSL 用法:
|
|
35
|
+
* ```json
|
|
36
|
+
* {
|
|
37
|
+
* "type": "Trigger",
|
|
38
|
+
* "props": {
|
|
39
|
+
* "rules": [
|
|
40
|
+
* { "on": "input:fire:press",
|
|
41
|
+
* "do": [
|
|
42
|
+
* { "type": "emit", "signal": "rocket:spawn" },
|
|
43
|
+
* { "type": "incStore", "key": "shotsFired" }
|
|
44
|
+
* ] },
|
|
45
|
+
* { "on": "rocket:hit",
|
|
46
|
+
* "guard": "ctx.allowedScene === true",
|
|
47
|
+
* "do": [
|
|
48
|
+
* { "type": "incStore", "key": "score" },
|
|
49
|
+
* { "type": "emit", "signal": "monster:hurt" }
|
|
50
|
+
* ] }
|
|
51
|
+
* ]
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* ```
|
|
55
|
+
*
|
|
56
|
+
* 这是 plugin-state-machine 的"无状态弟弟":只配 input → output,不维护 state。
|
|
57
|
+
* 适合写 80% 的"按钮按下→记分"业务,大幅减少自定义 Component 数量。
|
|
58
|
+
*/
|
|
59
|
+
let Trigger = class Trigger extends Component {
|
|
60
|
+
constructor() {
|
|
61
|
+
super(...arguments);
|
|
62
|
+
this.rules = [];
|
|
63
|
+
this.subs = [];
|
|
64
|
+
this.ctx = {};
|
|
65
|
+
}
|
|
66
|
+
init(params) {
|
|
67
|
+
var _a, _b;
|
|
68
|
+
if (!params)
|
|
69
|
+
return;
|
|
70
|
+
this.rules = (_a = params.rules) !== null && _a !== void 0 ? _a : [];
|
|
71
|
+
this.ctx = (_b = params.context) !== null && _b !== void 0 ? _b : {};
|
|
72
|
+
}
|
|
73
|
+
awake() {
|
|
74
|
+
const bus = getSignalBus();
|
|
75
|
+
for (const rule of this.rules) {
|
|
76
|
+
const h = bus.on(rule.on, (payload) => {
|
|
77
|
+
if (rule.guard && !this.evalGuard(rule.guard, payload))
|
|
78
|
+
return;
|
|
79
|
+
for (const a of rule.do)
|
|
80
|
+
this.exec(a, payload);
|
|
81
|
+
});
|
|
82
|
+
this.subs.push(h);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
exec(action, payload) {
|
|
86
|
+
var _a, _b, _c, _d;
|
|
87
|
+
try {
|
|
88
|
+
switch (action.type) {
|
|
89
|
+
case 'emit':
|
|
90
|
+
getSignalBus().emit(action.signal, (_a = action.payload) !== null && _a !== void 0 ? _a : payload);
|
|
91
|
+
break;
|
|
92
|
+
case 'setStore':
|
|
93
|
+
if (typeof mx !== 'undefined' && ((_b = mx === null || mx === void 0 ? void 0 : mx.store) === null || _b === void 0 ? void 0 : _b.update)) {
|
|
94
|
+
mx.store.update(action.key, () => action.value);
|
|
95
|
+
}
|
|
96
|
+
break;
|
|
97
|
+
case 'incStore':
|
|
98
|
+
if (typeof mx !== 'undefined' && ((_c = mx === null || mx === void 0 ? void 0 : mx.store) === null || _c === void 0 ? void 0 : _c.update)) {
|
|
99
|
+
mx.store.update(action.key, (v) => { var _a; return (v !== null && v !== void 0 ? v : 0) + ((_a = action.delta) !== null && _a !== void 0 ? _a : 1); });
|
|
100
|
+
}
|
|
101
|
+
break;
|
|
102
|
+
case 'log':
|
|
103
|
+
// eslint-disable-next-line no-console
|
|
104
|
+
console.log('[trigger]', action.message, payload);
|
|
105
|
+
break;
|
|
106
|
+
case 'callMethod':
|
|
107
|
+
this.callMethod(action.entity, action.component, action.method, (_d = action.args) !== null && _d !== void 0 ? _d : []);
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
// eslint-disable-next-line no-console
|
|
113
|
+
console.warn('[plugin-trigger] action failed', action, err);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
callMethod(entity, compName, method, args) {
|
|
117
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
118
|
+
const game = (_b = (_a = this.gameObject) === null || _a === void 0 ? void 0 : _a.scene) === null || _b === void 0 ? void 0 : _b.game;
|
|
119
|
+
if (!game)
|
|
120
|
+
return;
|
|
121
|
+
const stack = [...((_d = (_c = game.scene) === null || _c === void 0 ? void 0 : _c.gameObjects) !== null && _d !== void 0 ? _d : [])];
|
|
122
|
+
while (stack.length) {
|
|
123
|
+
const go = stack.pop();
|
|
124
|
+
if (!go)
|
|
125
|
+
continue;
|
|
126
|
+
if (go.name === entity) {
|
|
127
|
+
const comps = (_e = go.components) !== null && _e !== void 0 ? _e : [];
|
|
128
|
+
const c = comps.find((c) => { var _a; return ((_a = c === null || c === void 0 ? void 0 : c.constructor) === null || _a === void 0 ? void 0 : _a.componentName) === compName; });
|
|
129
|
+
if (c && typeof c[method] === 'function') {
|
|
130
|
+
c[method](...args);
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
if ((_g = (_f = go.transform) === null || _f === void 0 ? void 0 : _f.children) === null || _g === void 0 ? void 0 : _g.length) {
|
|
135
|
+
for (const ch of go.transform.children)
|
|
136
|
+
stack.push(ch.gameObject);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
evalGuard(guard, payload) {
|
|
141
|
+
try {
|
|
142
|
+
// eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
|
|
143
|
+
const fn = new Function('payload', 'ctx', `return (${guard});`);
|
|
144
|
+
return Boolean(fn(payload, this.ctx));
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
// eslint-disable-next-line no-console
|
|
148
|
+
console.warn(`[plugin-trigger] bad guard "${guard}":`, err);
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
onDestroy() {
|
|
153
|
+
for (const h of this.subs)
|
|
154
|
+
h.dispose();
|
|
155
|
+
this.subs = [];
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
Trigger.componentName = 'Trigger';
|
|
159
|
+
Trigger = __decorate([
|
|
160
|
+
decorators.componentObserver({})
|
|
161
|
+
], Trigger);
|
|
162
|
+
|
|
163
|
+
class TriggerSystem extends System {
|
|
164
|
+
constructor() {
|
|
165
|
+
super(...arguments);
|
|
166
|
+
this.name = 'Trigger';
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
TriggerSystem.systemName = 'Trigger';
|
|
170
|
+
|
|
171
|
+
export { Trigger, TriggerSystem };
|
package/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eva/plugin-trigger",
|
|
3
|
-
"version": "2.1.0-beta.
|
|
3
|
+
"version": "2.1.0-beta.3",
|
|
4
4
|
"description": "Trigger — 信号 → DSL 动作的执行器,DSL 配置 \"on signal\" + \"do actions\",emit/setStore/transitionState/playSound 等。",
|
|
5
|
-
"main": "
|
|
6
|
-
"module": "
|
|
7
|
-
"types": "
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"module": "dist/plugin-trigger.esm.js",
|
|
7
|
+
"types": "dist/plugin-trigger.d.ts",
|
|
8
8
|
"files": [
|
|
9
|
-
"
|
|
9
|
+
"index.js",
|
|
10
|
+
"dist"
|
|
10
11
|
],
|
|
11
12
|
"keywords": [
|
|
12
13
|
"eva.js",
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
],
|
|
17
18
|
"license": "MIT",
|
|
18
19
|
"dependencies": {
|
|
19
|
-
"@eva/eva.js": "2.1.0-beta.
|
|
20
|
-
"@eva/plugin-signal-bus": "2.1.0-beta.
|
|
20
|
+
"@eva/eva.js": "2.1.0-beta.3",
|
|
21
|
+
"@eva/plugin-signal-bus": "2.1.0-beta.3"
|
|
21
22
|
}
|
|
22
23
|
}
|
package/lib/Trigger.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import { Component, decorators } from '@eva/eva.js';
|
|
2
|
-
import { getSignalBus, SignalHandle } from '@eva/plugin-signal-bus';
|
|
3
|
-
import type { TriggerParams, TriggerRule, TriggerAction } from './types';
|
|
4
|
-
|
|
5
|
-
declare const mx: any;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Trigger 组件 — 把信号映射成 DSL 动作。
|
|
9
|
-
*
|
|
10
|
-
* DSL 用法:
|
|
11
|
-
* ```json
|
|
12
|
-
* {
|
|
13
|
-
* "type": "Trigger",
|
|
14
|
-
* "props": {
|
|
15
|
-
* "rules": [
|
|
16
|
-
* { "on": "input:fire:press",
|
|
17
|
-
* "do": [
|
|
18
|
-
* { "type": "emit", "signal": "rocket:spawn" },
|
|
19
|
-
* { "type": "incStore", "key": "shotsFired" }
|
|
20
|
-
* ] },
|
|
21
|
-
* { "on": "rocket:hit",
|
|
22
|
-
* "guard": "ctx.allowedScene === true",
|
|
23
|
-
* "do": [
|
|
24
|
-
* { "type": "incStore", "key": "score" },
|
|
25
|
-
* { "type": "emit", "signal": "monster:hurt" }
|
|
26
|
-
* ] }
|
|
27
|
-
* ]
|
|
28
|
-
* }
|
|
29
|
-
* }
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* 这是 plugin-state-machine 的"无状态弟弟":只配 input → output,不维护 state。
|
|
33
|
-
* 适合写 80% 的"按钮按下→记分"业务,大幅减少自定义 Component 数量。
|
|
34
|
-
*/
|
|
35
|
-
@decorators.componentObserver({})
|
|
36
|
-
export class Trigger extends Component<TriggerParams> {
|
|
37
|
-
static componentName = 'Trigger';
|
|
38
|
-
|
|
39
|
-
private rules: TriggerRule[] = [];
|
|
40
|
-
private subs: SignalHandle[] = [];
|
|
41
|
-
ctx: Record<string, any> = {};
|
|
42
|
-
|
|
43
|
-
init(params?: TriggerParams) {
|
|
44
|
-
if (!params) return;
|
|
45
|
-
this.rules = params.rules ?? [];
|
|
46
|
-
this.ctx = params.context ?? {};
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
awake() {
|
|
50
|
-
const bus = getSignalBus();
|
|
51
|
-
for (const rule of this.rules) {
|
|
52
|
-
const h = bus.on(rule.on, (payload: any) => {
|
|
53
|
-
if (rule.guard && !this.evalGuard(rule.guard, payload)) return;
|
|
54
|
-
for (const a of rule.do) this.exec(a, payload);
|
|
55
|
-
});
|
|
56
|
-
this.subs.push(h);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
private exec(action: TriggerAction, payload: any) {
|
|
61
|
-
try {
|
|
62
|
-
switch (action.type) {
|
|
63
|
-
case 'emit':
|
|
64
|
-
getSignalBus().emit(action.signal, action.payload ?? payload);
|
|
65
|
-
break;
|
|
66
|
-
case 'setStore':
|
|
67
|
-
if (typeof mx !== 'undefined' && mx?.store?.update) {
|
|
68
|
-
mx.store.update(action.key, () => action.value);
|
|
69
|
-
}
|
|
70
|
-
break;
|
|
71
|
-
case 'incStore':
|
|
72
|
-
if (typeof mx !== 'undefined' && mx?.store?.update) {
|
|
73
|
-
mx.store.update(action.key, (v: number) => (v ?? 0) + (action.delta ?? 1));
|
|
74
|
-
}
|
|
75
|
-
break;
|
|
76
|
-
case 'log':
|
|
77
|
-
// eslint-disable-next-line no-console
|
|
78
|
-
console.log('[trigger]', action.message, payload);
|
|
79
|
-
break;
|
|
80
|
-
case 'callMethod':
|
|
81
|
-
this.callMethod(action.entity, action.component, action.method, action.args ?? []);
|
|
82
|
-
break;
|
|
83
|
-
}
|
|
84
|
-
} catch (err) {
|
|
85
|
-
// eslint-disable-next-line no-console
|
|
86
|
-
console.warn('[plugin-trigger] action failed', action, err);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
private callMethod(entity: string, compName: string, method: string, args: any[]) {
|
|
91
|
-
const game: any = (this as any).gameObject?.scene?.game;
|
|
92
|
-
if (!game) return;
|
|
93
|
-
const stack: any[] = [...(game.scene?.gameObjects ?? [])];
|
|
94
|
-
while (stack.length) {
|
|
95
|
-
const go = stack.pop();
|
|
96
|
-
if (!go) continue;
|
|
97
|
-
if (go.name === entity) {
|
|
98
|
-
const comps: any[] = go.components ?? [];
|
|
99
|
-
const c = comps.find((c) => c?.constructor?.componentName === compName);
|
|
100
|
-
if (c && typeof c[method] === 'function') {
|
|
101
|
-
c[method](...args);
|
|
102
|
-
}
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
if (go.transform?.children?.length) {
|
|
106
|
-
for (const ch of go.transform.children) stack.push(ch.gameObject);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
private evalGuard(guard: string, payload: any): boolean {
|
|
112
|
-
try {
|
|
113
|
-
// eslint-disable-next-line @typescript-eslint/no-implied-eval, no-new-func
|
|
114
|
-
const fn = new Function('payload', 'ctx', `return (${guard});`);
|
|
115
|
-
return Boolean(fn(payload, this.ctx));
|
|
116
|
-
} catch (err) {
|
|
117
|
-
// eslint-disable-next-line no-console
|
|
118
|
-
console.warn(`[plugin-trigger] bad guard "${guard}":`, err);
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
onDestroy() {
|
|
124
|
-
for (const h of this.subs) h.dispose();
|
|
125
|
-
this.subs = [];
|
|
126
|
-
}
|
|
127
|
-
}
|
package/lib/TriggerSystem.ts
DELETED
package/lib/index.ts
DELETED
package/lib/types.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/** 单条 action,DSL 描述时只填 type + 字段 */
|
|
2
|
-
export type TriggerAction =
|
|
3
|
-
| { type: 'emit'; signal: string; payload?: any }
|
|
4
|
-
| { type: 'setStore'; key: string; value: any }
|
|
5
|
-
| { type: 'incStore'; key: string; delta?: number }
|
|
6
|
-
| { type: 'log'; message: string }
|
|
7
|
-
| { type: 'callMethod'; entity: string; component: string; method: string; args?: any[] };
|
|
8
|
-
|
|
9
|
-
export interface TriggerRule {
|
|
10
|
-
/** 监听的信号名 */
|
|
11
|
-
on: string;
|
|
12
|
-
/** 命中后执行的动作列表 */
|
|
13
|
-
do: TriggerAction[];
|
|
14
|
-
/** 可选:JS 表达式;以 (payload, ctx) 为变量,假则跳过 */
|
|
15
|
-
guard?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export interface TriggerParams {
|
|
19
|
-
rules: TriggerRule[];
|
|
20
|
-
/** ctx 变量,可在 guard 中读 */
|
|
21
|
-
context?: Record<string, any>;
|
|
22
|
-
}
|