feat(blueprint): 添加蓝图触发器系统 (#323)
* feat(blueprint): 添加蓝图触发器系统 - TriggerTypes: 定义触发器类型和上下文接口 - tick/input/collision/message/timer/stateEnter/stateExit/custom - 各类型的上下文接口和工厂函数 - TriggerCondition: 触发条件系统 - ITriggerCondition 接口 - 复合条件 (CompositeCondition, NotCondition) - 通用条件 (AlwaysTrue, AlwaysFalse, TriggerType, EntityId) - 特定类型条件 (InputAction, MessageName, StateName, TimerId, CollisionEntity, CustomEvent) - ConditionBuilder 链式 API - BlueprintTrigger: 触发器核心实现 - IBlueprintTrigger 接口 - BlueprintTrigger 实现类 - TriggerRegistry 触发器注册表 - 各类型触发器工厂函数 - TriggerDispatcher: 触发器调度系统 - ITriggerDispatcher 调度器接口 - TriggerDispatcher 实现 - EntityTriggerManager 实体触发器管理器 * feat(blueprint): 添加触发器相关事件节点 - EventInput: 输入事件节点 (action/value/pressed/released) - EventCollisionEnter/Exit: 碰撞事件节点 - EventMessage: 消息事件节点 - EventTimer: 定时器事件节点 - EventStateEnter/Exit: 状态机事件节点
This commit is contained in:
@@ -9,6 +9,9 @@ export * from './types';
|
|||||||
// Runtime
|
// Runtime
|
||||||
export * from './runtime';
|
export * from './runtime';
|
||||||
|
|
||||||
|
// Triggers
|
||||||
|
export * from './triggers';
|
||||||
|
|
||||||
// Nodes (import to register)
|
// Nodes (import to register)
|
||||||
import './nodes';
|
import './nodes';
|
||||||
|
|
||||||
|
|||||||
118
packages/blueprint/src/nodes/events/EventCollision.ts
Normal file
118
packages/blueprint/src/nodes/events/EventCollision.ts
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* @zh 碰撞事件节点 - 碰撞发生时触发
|
||||||
|
* @en Event Collision Node - Triggered on collision events
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BlueprintNodeTemplate, BlueprintNode } from '../../types/nodes';
|
||||||
|
import { ExecutionResult } from '../../runtime/ExecutionContext';
|
||||||
|
import { INodeExecutor, RegisterNode } from '../../runtime/NodeRegistry';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventCollisionEnter 节点模板
|
||||||
|
* @en EventCollisionEnter node template
|
||||||
|
*/
|
||||||
|
export const EventCollisionEnterTemplate: BlueprintNodeTemplate = {
|
||||||
|
type: 'EventCollisionEnter',
|
||||||
|
title: 'Event Collision Enter',
|
||||||
|
category: 'event',
|
||||||
|
color: '#CC0000',
|
||||||
|
description: 'Triggered when collision starts / 碰撞开始时触发',
|
||||||
|
keywords: ['collision', 'enter', 'hit', 'overlap', 'event'],
|
||||||
|
menuPath: ['Event', 'Collision', 'Enter'],
|
||||||
|
inputs: [],
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'exec',
|
||||||
|
type: 'exec',
|
||||||
|
displayName: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'otherEntityId',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Other Entity'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pointX',
|
||||||
|
type: 'float',
|
||||||
|
displayName: 'Point X'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pointY',
|
||||||
|
type: 'float',
|
||||||
|
displayName: 'Point Y'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'normalX',
|
||||||
|
type: 'float',
|
||||||
|
displayName: 'Normal X'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'normalY',
|
||||||
|
type: 'float',
|
||||||
|
displayName: 'Normal Y'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventCollisionEnter 节点执行器
|
||||||
|
* @en EventCollisionEnter node executor
|
||||||
|
*/
|
||||||
|
@RegisterNode(EventCollisionEnterTemplate)
|
||||||
|
export class EventCollisionEnterExecutor implements INodeExecutor {
|
||||||
|
execute(_node: BlueprintNode): ExecutionResult {
|
||||||
|
return {
|
||||||
|
nextExec: 'exec',
|
||||||
|
outputs: {
|
||||||
|
otherEntityId: '',
|
||||||
|
pointX: 0,
|
||||||
|
pointY: 0,
|
||||||
|
normalX: 0,
|
||||||
|
normalY: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventCollisionExit 节点模板
|
||||||
|
* @en EventCollisionExit node template
|
||||||
|
*/
|
||||||
|
export const EventCollisionExitTemplate: BlueprintNodeTemplate = {
|
||||||
|
type: 'EventCollisionExit',
|
||||||
|
title: 'Event Collision Exit',
|
||||||
|
category: 'event',
|
||||||
|
color: '#CC0000',
|
||||||
|
description: 'Triggered when collision ends / 碰撞结束时触发',
|
||||||
|
keywords: ['collision', 'exit', 'end', 'separate', 'event'],
|
||||||
|
menuPath: ['Event', 'Collision', 'Exit'],
|
||||||
|
inputs: [],
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'exec',
|
||||||
|
type: 'exec',
|
||||||
|
displayName: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'otherEntityId',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Other Entity'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventCollisionExit 节点执行器
|
||||||
|
* @en EventCollisionExit node executor
|
||||||
|
*/
|
||||||
|
@RegisterNode(EventCollisionExitTemplate)
|
||||||
|
export class EventCollisionExitExecutor implements INodeExecutor {
|
||||||
|
execute(_node: BlueprintNode): ExecutionResult {
|
||||||
|
return {
|
||||||
|
nextExec: 'exec',
|
||||||
|
outputs: {
|
||||||
|
otherEntityId: ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
79
packages/blueprint/src/nodes/events/EventInput.ts
Normal file
79
packages/blueprint/src/nodes/events/EventInput.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* @zh 输入事件节点 - 输入触发时触发
|
||||||
|
* @en Event Input Node - Triggered on input events
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BlueprintNodeTemplate, BlueprintNode } from '../../types/nodes';
|
||||||
|
import { ExecutionContext, ExecutionResult } from '../../runtime/ExecutionContext';
|
||||||
|
import { INodeExecutor, RegisterNode } from '../../runtime/NodeRegistry';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventInput 节点模板
|
||||||
|
* @en EventInput node template
|
||||||
|
*/
|
||||||
|
export const EventInputTemplate: BlueprintNodeTemplate = {
|
||||||
|
type: 'EventInput',
|
||||||
|
title: 'Event Input',
|
||||||
|
category: 'event',
|
||||||
|
color: '#CC0000',
|
||||||
|
description: 'Triggered when input action occurs / 输入动作发生时触发',
|
||||||
|
keywords: ['input', 'key', 'button', 'action', 'event'],
|
||||||
|
menuPath: ['Event', 'Input'],
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
name: 'action',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Action',
|
||||||
|
defaultValue: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'exec',
|
||||||
|
type: 'exec',
|
||||||
|
displayName: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'action',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Action'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'value',
|
||||||
|
type: 'float',
|
||||||
|
displayName: 'Value'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'pressed',
|
||||||
|
type: 'bool',
|
||||||
|
displayName: 'Pressed'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'released',
|
||||||
|
type: 'bool',
|
||||||
|
displayName: 'Released'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventInput 节点执行器
|
||||||
|
* @en EventInput node executor
|
||||||
|
*
|
||||||
|
* @zh 注意:事件节点的输出由 VM 在触发时通过 setOutputs 设置
|
||||||
|
* @en Note: Event node outputs are set by VM via setOutputs when triggered
|
||||||
|
*/
|
||||||
|
@RegisterNode(EventInputTemplate)
|
||||||
|
export class EventInputExecutor implements INodeExecutor {
|
||||||
|
execute(node: BlueprintNode, _context: ExecutionContext): ExecutionResult {
|
||||||
|
return {
|
||||||
|
nextExec: 'exec',
|
||||||
|
outputs: {
|
||||||
|
action: node.data?.action ?? '',
|
||||||
|
value: 0,
|
||||||
|
pressed: false,
|
||||||
|
released: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
70
packages/blueprint/src/nodes/events/EventMessage.ts
Normal file
70
packages/blueprint/src/nodes/events/EventMessage.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* @zh 消息事件节点 - 接收消息时触发
|
||||||
|
* @en Event Message Node - Triggered when message is received
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BlueprintNodeTemplate, BlueprintNode } from '../../types/nodes';
|
||||||
|
import { ExecutionResult } from '../../runtime/ExecutionContext';
|
||||||
|
import { INodeExecutor, RegisterNode } from '../../runtime/NodeRegistry';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventMessage 节点模板
|
||||||
|
* @en EventMessage node template
|
||||||
|
*/
|
||||||
|
export const EventMessageTemplate: BlueprintNodeTemplate = {
|
||||||
|
type: 'EventMessage',
|
||||||
|
title: 'Event Message',
|
||||||
|
category: 'event',
|
||||||
|
color: '#CC0000',
|
||||||
|
description: 'Triggered when a message is received / 接收到消息时触发',
|
||||||
|
keywords: ['message', 'receive', 'broadcast', 'event', 'signal'],
|
||||||
|
menuPath: ['Event', 'Message'],
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
name: 'messageName',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Message Name',
|
||||||
|
defaultValue: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'exec',
|
||||||
|
type: 'exec',
|
||||||
|
displayName: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'messageName',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Message'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'senderId',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Sender ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'payload',
|
||||||
|
type: 'any',
|
||||||
|
displayName: 'Payload'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventMessage 节点执行器
|
||||||
|
* @en EventMessage node executor
|
||||||
|
*/
|
||||||
|
@RegisterNode(EventMessageTemplate)
|
||||||
|
export class EventMessageExecutor implements INodeExecutor {
|
||||||
|
execute(node: BlueprintNode): ExecutionResult {
|
||||||
|
return {
|
||||||
|
nextExec: 'exec',
|
||||||
|
outputs: {
|
||||||
|
messageName: node.data?.messageName ?? '',
|
||||||
|
senderId: '',
|
||||||
|
payload: null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
132
packages/blueprint/src/nodes/events/EventState.ts
Normal file
132
packages/blueprint/src/nodes/events/EventState.ts
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
/**
|
||||||
|
* @zh 状态事件节点 - 状态机状态变化时触发
|
||||||
|
* @en Event State Node - Triggered on state machine state changes
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BlueprintNodeTemplate, BlueprintNode } from '../../types/nodes';
|
||||||
|
import { ExecutionResult } from '../../runtime/ExecutionContext';
|
||||||
|
import { INodeExecutor, RegisterNode } from '../../runtime/NodeRegistry';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventStateEnter 节点模板
|
||||||
|
* @en EventStateEnter node template
|
||||||
|
*/
|
||||||
|
export const EventStateEnterTemplate: BlueprintNodeTemplate = {
|
||||||
|
type: 'EventStateEnter',
|
||||||
|
title: 'Event State Enter',
|
||||||
|
category: 'event',
|
||||||
|
color: '#CC0000',
|
||||||
|
description: 'Triggered when entering a state / 进入状态时触发',
|
||||||
|
keywords: ['state', 'enter', 'fsm', 'machine', 'event'],
|
||||||
|
menuPath: ['Event', 'State', 'Enter'],
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
name: 'stateName',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'State Name',
|
||||||
|
defaultValue: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'exec',
|
||||||
|
type: 'exec',
|
||||||
|
displayName: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'stateMachineId',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'State Machine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'currentState',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Current State'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'previousState',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Previous State'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventStateEnter 节点执行器
|
||||||
|
* @en EventStateEnter node executor
|
||||||
|
*/
|
||||||
|
@RegisterNode(EventStateEnterTemplate)
|
||||||
|
export class EventStateEnterExecutor implements INodeExecutor {
|
||||||
|
execute(node: BlueprintNode): ExecutionResult {
|
||||||
|
return {
|
||||||
|
nextExec: 'exec',
|
||||||
|
outputs: {
|
||||||
|
stateMachineId: '',
|
||||||
|
currentState: node.data?.stateName ?? '',
|
||||||
|
previousState: ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventStateExit 节点模板
|
||||||
|
* @en EventStateExit node template
|
||||||
|
*/
|
||||||
|
export const EventStateExitTemplate: BlueprintNodeTemplate = {
|
||||||
|
type: 'EventStateExit',
|
||||||
|
title: 'Event State Exit',
|
||||||
|
category: 'event',
|
||||||
|
color: '#CC0000',
|
||||||
|
description: 'Triggered when exiting a state / 退出状态时触发',
|
||||||
|
keywords: ['state', 'exit', 'leave', 'fsm', 'machine', 'event'],
|
||||||
|
menuPath: ['Event', 'State', 'Exit'],
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
name: 'stateName',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'State Name',
|
||||||
|
defaultValue: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'exec',
|
||||||
|
type: 'exec',
|
||||||
|
displayName: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'stateMachineId',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'State Machine'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'currentState',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Current State'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'previousState',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Previous State'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventStateExit 节点执行器
|
||||||
|
* @en EventStateExit node executor
|
||||||
|
*/
|
||||||
|
@RegisterNode(EventStateExitTemplate)
|
||||||
|
export class EventStateExitExecutor implements INodeExecutor {
|
||||||
|
execute(node: BlueprintNode): ExecutionResult {
|
||||||
|
return {
|
||||||
|
nextExec: 'exec',
|
||||||
|
outputs: {
|
||||||
|
stateMachineId: '',
|
||||||
|
currentState: '',
|
||||||
|
previousState: node.data?.stateName ?? ''
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
70
packages/blueprint/src/nodes/events/EventTimer.ts
Normal file
70
packages/blueprint/src/nodes/events/EventTimer.ts
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/**
|
||||||
|
* @zh 定时器事件节点 - 定时器触发时调用
|
||||||
|
* @en Event Timer Node - Triggered when timer fires
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { BlueprintNodeTemplate, BlueprintNode } from '../../types/nodes';
|
||||||
|
import { ExecutionResult } from '../../runtime/ExecutionContext';
|
||||||
|
import { INodeExecutor, RegisterNode } from '../../runtime/NodeRegistry';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventTimer 节点模板
|
||||||
|
* @en EventTimer node template
|
||||||
|
*/
|
||||||
|
export const EventTimerTemplate: BlueprintNodeTemplate = {
|
||||||
|
type: 'EventTimer',
|
||||||
|
title: 'Event Timer',
|
||||||
|
category: 'event',
|
||||||
|
color: '#CC0000',
|
||||||
|
description: 'Triggered when a timer fires / 定时器触发时执行',
|
||||||
|
keywords: ['timer', 'delay', 'schedule', 'event', 'interval'],
|
||||||
|
menuPath: ['Event', 'Timer'],
|
||||||
|
inputs: [
|
||||||
|
{
|
||||||
|
name: 'timerId',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Timer ID',
|
||||||
|
defaultValue: ''
|
||||||
|
}
|
||||||
|
],
|
||||||
|
outputs: [
|
||||||
|
{
|
||||||
|
name: 'exec',
|
||||||
|
type: 'exec',
|
||||||
|
displayName: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'timerId',
|
||||||
|
type: 'string',
|
||||||
|
displayName: 'Timer ID'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'isRepeating',
|
||||||
|
type: 'bool',
|
||||||
|
displayName: 'Is Repeating'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'timesFired',
|
||||||
|
type: 'int',
|
||||||
|
displayName: 'Times Fired'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh EventTimer 节点执行器
|
||||||
|
* @en EventTimer node executor
|
||||||
|
*/
|
||||||
|
@RegisterNode(EventTimerTemplate)
|
||||||
|
export class EventTimerExecutor implements INodeExecutor {
|
||||||
|
execute(node: BlueprintNode): ExecutionResult {
|
||||||
|
return {
|
||||||
|
nextExec: 'exec',
|
||||||
|
outputs: {
|
||||||
|
timerId: node.data?.timerId ?? '',
|
||||||
|
isRepeating: false,
|
||||||
|
timesFired: 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,16 @@
|
|||||||
/**
|
/**
|
||||||
* Event Nodes - Entry points for blueprint execution
|
* @zh 事件节点 - 蓝图执行的入口点
|
||||||
* 事件节点 - 蓝图执行的入口点
|
* @en Event Nodes - Entry points for blueprint execution
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// 生命周期事件 | Lifecycle events
|
||||||
export * from './EventBeginPlay';
|
export * from './EventBeginPlay';
|
||||||
export * from './EventTick';
|
export * from './EventTick';
|
||||||
export * from './EventEndPlay';
|
export * from './EventEndPlay';
|
||||||
|
|
||||||
|
// 触发器事件 | Trigger events
|
||||||
|
export * from './EventInput';
|
||||||
|
export * from './EventCollision';
|
||||||
|
export * from './EventMessage';
|
||||||
|
export * from './EventTimer';
|
||||||
|
export * from './EventState';
|
||||||
|
|||||||
497
packages/blueprint/src/triggers/BlueprintTrigger.ts
Normal file
497
packages/blueprint/src/triggers/BlueprintTrigger.ts
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
/**
|
||||||
|
* @zh 蓝图触发器
|
||||||
|
* @en Blueprint Trigger
|
||||||
|
*
|
||||||
|
* @zh 定义触发器的核心实现
|
||||||
|
* @en Defines core trigger implementation
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { TriggerType, ITriggerContext } from './TriggerTypes';
|
||||||
|
import type { ITriggerCondition } from './TriggerCondition';
|
||||||
|
import { AlwaysTrueCondition } from './TriggerCondition';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器接口 | Trigger Interface
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器回调函数类型
|
||||||
|
* @en Trigger callback function type
|
||||||
|
*/
|
||||||
|
export type TriggerCallback = (context: ITriggerContext) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 蓝图触发器接口
|
||||||
|
* @en Blueprint trigger interface
|
||||||
|
*/
|
||||||
|
export interface IBlueprintTrigger {
|
||||||
|
/**
|
||||||
|
* @zh 触发器唯一标识
|
||||||
|
* @en Trigger unique identifier
|
||||||
|
*/
|
||||||
|
readonly id: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器类型
|
||||||
|
* @en Trigger type
|
||||||
|
*/
|
||||||
|
readonly type: TriggerType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器条件
|
||||||
|
* @en Trigger conditions
|
||||||
|
*/
|
||||||
|
readonly condition: ITriggerCondition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 是否启用
|
||||||
|
* @en Is enabled
|
||||||
|
*/
|
||||||
|
enabled: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 优先级(越高越先执行)
|
||||||
|
* @en Priority (higher executes first)
|
||||||
|
*/
|
||||||
|
readonly priority: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 检查是否应该触发
|
||||||
|
* @en Check if should fire
|
||||||
|
*/
|
||||||
|
shouldFire(context: ITriggerContext): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 执行触发器
|
||||||
|
* @en Execute trigger
|
||||||
|
*/
|
||||||
|
fire(context: ITriggerContext): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器配置
|
||||||
|
* @en Trigger configuration
|
||||||
|
*/
|
||||||
|
export interface TriggerConfig {
|
||||||
|
/**
|
||||||
|
* @zh 触发器 ID
|
||||||
|
* @en Trigger ID
|
||||||
|
*/
|
||||||
|
id?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器类型
|
||||||
|
* @en Trigger type
|
||||||
|
*/
|
||||||
|
type: TriggerType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发条件
|
||||||
|
* @en Trigger condition
|
||||||
|
*/
|
||||||
|
condition?: ITriggerCondition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 是否启用
|
||||||
|
* @en Is enabled
|
||||||
|
*/
|
||||||
|
enabled?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 优先级
|
||||||
|
* @en Priority
|
||||||
|
*/
|
||||||
|
priority?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 回调函数
|
||||||
|
* @en Callback function
|
||||||
|
*/
|
||||||
|
callback?: TriggerCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器实现 | Trigger Implementation
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
let _triggerId = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 生成唯一触发器 ID
|
||||||
|
* @en Generate unique trigger ID
|
||||||
|
*/
|
||||||
|
function generateTriggerId(): string {
|
||||||
|
return `trigger_${++_triggerId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 蓝图触发器实现
|
||||||
|
* @en Blueprint trigger implementation
|
||||||
|
*/
|
||||||
|
export class BlueprintTrigger implements IBlueprintTrigger {
|
||||||
|
readonly id: string;
|
||||||
|
readonly type: TriggerType;
|
||||||
|
readonly condition: ITriggerCondition;
|
||||||
|
readonly priority: number;
|
||||||
|
enabled: boolean;
|
||||||
|
|
||||||
|
private readonly _callback?: TriggerCallback;
|
||||||
|
private readonly _callbacks: Set<TriggerCallback> = new Set();
|
||||||
|
|
||||||
|
constructor(config: TriggerConfig) {
|
||||||
|
this.id = config.id ?? generateTriggerId();
|
||||||
|
this.type = config.type;
|
||||||
|
this.condition = config.condition ?? new AlwaysTrueCondition();
|
||||||
|
this.priority = config.priority ?? 0;
|
||||||
|
this.enabled = config.enabled ?? true;
|
||||||
|
this._callback = config.callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 检查是否应该触发
|
||||||
|
* @en Check if should fire
|
||||||
|
*/
|
||||||
|
shouldFire(context: ITriggerContext): boolean {
|
||||||
|
if (!this.enabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.type !== this.type && this.type !== 'custom') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.condition.evaluate(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 执行触发器
|
||||||
|
* @en Execute trigger
|
||||||
|
*/
|
||||||
|
fire(context: ITriggerContext): void {
|
||||||
|
if (this._callback) {
|
||||||
|
this._callback(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const callback of this._callbacks) {
|
||||||
|
callback(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加回调
|
||||||
|
* @en Add callback
|
||||||
|
*/
|
||||||
|
addCallback(callback: TriggerCallback): void {
|
||||||
|
this._callbacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 移除回调
|
||||||
|
* @en Remove callback
|
||||||
|
*/
|
||||||
|
removeCallback(callback: TriggerCallback): void {
|
||||||
|
this._callbacks.delete(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 清除所有回调
|
||||||
|
* @en Clear all callbacks
|
||||||
|
*/
|
||||||
|
clearCallbacks(): void {
|
||||||
|
this._callbacks.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器注册表 | Trigger Registry
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器注册表接口
|
||||||
|
* @en Trigger registry interface
|
||||||
|
*/
|
||||||
|
export interface ITriggerRegistry {
|
||||||
|
/**
|
||||||
|
* @zh 注册触发器
|
||||||
|
* @en Register trigger
|
||||||
|
*/
|
||||||
|
register(trigger: IBlueprintTrigger): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 注销触发器
|
||||||
|
* @en Unregister trigger
|
||||||
|
*/
|
||||||
|
unregister(triggerId: string): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取触发器
|
||||||
|
* @en Get trigger
|
||||||
|
*/
|
||||||
|
get(triggerId: string): IBlueprintTrigger | undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取所有触发器
|
||||||
|
* @en Get all triggers
|
||||||
|
*/
|
||||||
|
getAll(): IBlueprintTrigger[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 按类型获取触发器
|
||||||
|
* @en Get triggers by type
|
||||||
|
*/
|
||||||
|
getByType(type: TriggerType): IBlueprintTrigger[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 清除所有触发器
|
||||||
|
* @en Clear all triggers
|
||||||
|
*/
|
||||||
|
clear(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器注册表实现
|
||||||
|
* @en Trigger registry implementation
|
||||||
|
*/
|
||||||
|
export class TriggerRegistry implements ITriggerRegistry {
|
||||||
|
private readonly _triggers: Map<string, IBlueprintTrigger> = new Map();
|
||||||
|
private readonly _triggersByType: Map<TriggerType, Set<string>> = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 注册触发器
|
||||||
|
* @en Register trigger
|
||||||
|
*/
|
||||||
|
register(trigger: IBlueprintTrigger): void {
|
||||||
|
if (this._triggers.has(trigger.id)) {
|
||||||
|
console.warn(`Trigger ${trigger.id} already registered, overwriting`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._triggers.set(trigger.id, trigger);
|
||||||
|
|
||||||
|
if (!this._triggersByType.has(trigger.type)) {
|
||||||
|
this._triggersByType.set(trigger.type, new Set());
|
||||||
|
}
|
||||||
|
this._triggersByType.get(trigger.type)!.add(trigger.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 注销触发器
|
||||||
|
* @en Unregister trigger
|
||||||
|
*/
|
||||||
|
unregister(triggerId: string): boolean {
|
||||||
|
const trigger = this._triggers.get(triggerId);
|
||||||
|
if (!trigger) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._triggers.delete(triggerId);
|
||||||
|
|
||||||
|
const typeSet = this._triggersByType.get(trigger.type);
|
||||||
|
if (typeSet) {
|
||||||
|
typeSet.delete(triggerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取触发器
|
||||||
|
* @en Get trigger
|
||||||
|
*/
|
||||||
|
get(triggerId: string): IBlueprintTrigger | undefined {
|
||||||
|
return this._triggers.get(triggerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取所有触发器
|
||||||
|
* @en Get all triggers
|
||||||
|
*/
|
||||||
|
getAll(): IBlueprintTrigger[] {
|
||||||
|
return Array.from(this._triggers.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 按类型获取触发器
|
||||||
|
* @en Get triggers by type
|
||||||
|
*/
|
||||||
|
getByType(type: TriggerType): IBlueprintTrigger[] {
|
||||||
|
const typeSet = this._triggersByType.get(type);
|
||||||
|
if (!typeSet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const triggers: IBlueprintTrigger[] = [];
|
||||||
|
for (const id of typeSet) {
|
||||||
|
const trigger = this._triggers.get(id);
|
||||||
|
if (trigger) {
|
||||||
|
triggers.push(trigger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return triggers.sort((a, b) => b.priority - a.priority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 清除所有触发器
|
||||||
|
* @en Clear all triggers
|
||||||
|
*/
|
||||||
|
clear(): void {
|
||||||
|
this._triggers.clear();
|
||||||
|
this._triggersByType.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取触发器数量
|
||||||
|
* @en Get trigger count
|
||||||
|
*/
|
||||||
|
get count(): number {
|
||||||
|
return this._triggers.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 工厂函数 | Factory Functions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建触发器
|
||||||
|
* @en Create trigger
|
||||||
|
*/
|
||||||
|
export function createTrigger(config: TriggerConfig): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建 Tick 触发器
|
||||||
|
* @en Create tick trigger
|
||||||
|
*/
|
||||||
|
export function createTickTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'tick',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建输入触发器
|
||||||
|
* @en Create input trigger
|
||||||
|
*/
|
||||||
|
export function createInputTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'input',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建碰撞触发器
|
||||||
|
* @en Create collision trigger
|
||||||
|
*/
|
||||||
|
export function createCollisionTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'collision',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建消息触发器
|
||||||
|
* @en Create message trigger
|
||||||
|
*/
|
||||||
|
export function createMessageTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'message',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建定时器触发器
|
||||||
|
* @en Create timer trigger
|
||||||
|
*/
|
||||||
|
export function createTimerTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'timer',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建状态进入触发器
|
||||||
|
* @en Create state enter trigger
|
||||||
|
*/
|
||||||
|
export function createStateEnterTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'stateEnter',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建状态退出触发器
|
||||||
|
* @en Create state exit trigger
|
||||||
|
*/
|
||||||
|
export function createStateExitTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'stateExit',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建自定义触发器
|
||||||
|
* @en Create custom trigger
|
||||||
|
*/
|
||||||
|
export function createCustomTrigger(
|
||||||
|
callback?: TriggerCallback,
|
||||||
|
options?: { id?: string; condition?: ITriggerCondition; priority?: number }
|
||||||
|
): BlueprintTrigger {
|
||||||
|
return new BlueprintTrigger({
|
||||||
|
id: options?.id,
|
||||||
|
type: 'custom',
|
||||||
|
condition: options?.condition,
|
||||||
|
priority: options?.priority,
|
||||||
|
callback
|
||||||
|
});
|
||||||
|
}
|
||||||
479
packages/blueprint/src/triggers/TriggerCondition.ts
Normal file
479
packages/blueprint/src/triggers/TriggerCondition.ts
Normal file
@@ -0,0 +1,479 @@
|
|||||||
|
/**
|
||||||
|
* @zh 触发器条件系统
|
||||||
|
* @en Trigger Condition System
|
||||||
|
*
|
||||||
|
* @zh 提供触发器触发前的条件检查能力
|
||||||
|
* @en Provides condition checking before trigger fires
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {
|
||||||
|
ITriggerContext,
|
||||||
|
TriggerType,
|
||||||
|
IInputTriggerContext,
|
||||||
|
IMessageTriggerContext,
|
||||||
|
IStateTriggerContext,
|
||||||
|
ITimerTriggerContext,
|
||||||
|
ICollisionTriggerContext,
|
||||||
|
ICustomTriggerContext
|
||||||
|
} from './TriggerTypes';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 条件接口 | Condition Interface
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器条件接口
|
||||||
|
* @en Trigger condition interface
|
||||||
|
*/
|
||||||
|
export interface ITriggerCondition {
|
||||||
|
/**
|
||||||
|
* @zh 条件类型标识
|
||||||
|
* @en Condition type identifier
|
||||||
|
*/
|
||||||
|
readonly type: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 评估条件是否满足
|
||||||
|
* @en Evaluate if condition is met
|
||||||
|
*
|
||||||
|
* @param context - @zh 触发器上下文 @en Trigger context
|
||||||
|
* @returns @zh 条件是否满足 @en Whether condition is met
|
||||||
|
*/
|
||||||
|
evaluate(context: ITriggerContext): boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 条件组合逻辑
|
||||||
|
* @en Condition combination logic
|
||||||
|
*/
|
||||||
|
export type ConditionLogic = 'and' | 'or';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 复合条件 | Composite Conditions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 复合条件 - 组合多个条件
|
||||||
|
* @en Composite condition - combines multiple conditions
|
||||||
|
*/
|
||||||
|
export class CompositeCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'composite';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly _conditions: ITriggerCondition[],
|
||||||
|
private readonly _logic: ConditionLogic = 'and'
|
||||||
|
) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (this._conditions.length === 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._logic === 'and') {
|
||||||
|
return this._conditions.every(c => c.evaluate(context));
|
||||||
|
} else {
|
||||||
|
return this._conditions.some(c => c.evaluate(context));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 非条件 - 取反
|
||||||
|
* @en Not condition - negates
|
||||||
|
*/
|
||||||
|
export class NotCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'not';
|
||||||
|
|
||||||
|
constructor(private readonly _condition: ITriggerCondition) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
return !this._condition.evaluate(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 通用条件 | Generic Conditions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 始终为真的条件
|
||||||
|
* @en Always true condition
|
||||||
|
*/
|
||||||
|
export class AlwaysTrueCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'alwaysTrue';
|
||||||
|
|
||||||
|
evaluate(_context: ITriggerContext): boolean {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 始终为假的条件
|
||||||
|
* @en Always false condition
|
||||||
|
*/
|
||||||
|
export class AlwaysFalseCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'alwaysFalse';
|
||||||
|
|
||||||
|
evaluate(_context: ITriggerContext): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器类型条件
|
||||||
|
* @en Trigger type condition
|
||||||
|
*/
|
||||||
|
export class TriggerTypeCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'triggerType';
|
||||||
|
|
||||||
|
constructor(private readonly _allowedTypes: TriggerType[]) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
return this._allowedTypes.includes(context.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 实体 ID 条件
|
||||||
|
* @en Entity ID condition
|
||||||
|
*/
|
||||||
|
export class EntityIdCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'entityId';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly _entityId: string,
|
||||||
|
private readonly _checkSource: boolean = true
|
||||||
|
) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (this._checkSource) {
|
||||||
|
return context.sourceEntityId === this._entityId;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 自定义函数条件
|
||||||
|
* @en Custom function condition
|
||||||
|
*/
|
||||||
|
export class FunctionCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'function';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly _predicate: (context: ITriggerContext) => boolean
|
||||||
|
) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
return this._predicate(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 特定类型条件 | Type-Specific Conditions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 输入动作条件
|
||||||
|
* @en Input action condition
|
||||||
|
*/
|
||||||
|
export class InputActionCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'inputAction';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly _action: string,
|
||||||
|
private readonly _checkPressed?: boolean,
|
||||||
|
private readonly _checkReleased?: boolean
|
||||||
|
) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (context.type !== 'input') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputContext = context as unknown as IInputTriggerContext;
|
||||||
|
|
||||||
|
if (inputContext.action !== this._action) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._checkPressed !== undefined && inputContext.pressed !== this._checkPressed) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._checkReleased !== undefined && inputContext.released !== this._checkReleased) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 消息名称条件
|
||||||
|
* @en Message name condition
|
||||||
|
*/
|
||||||
|
export class MessageNameCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'messageName';
|
||||||
|
|
||||||
|
constructor(private readonly _messageName: string) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (context.type !== 'message') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const messageContext = context as unknown as IMessageTriggerContext;
|
||||||
|
return messageContext.messageName === this._messageName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 状态名称条件
|
||||||
|
* @en State name condition
|
||||||
|
*/
|
||||||
|
export class StateNameCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'stateName';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly _stateName: string,
|
||||||
|
private readonly _checkCurrent: boolean = true
|
||||||
|
) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (context.type !== 'stateEnter' && context.type !== 'stateExit') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const stateContext = context as unknown as IStateTriggerContext;
|
||||||
|
|
||||||
|
if (this._checkCurrent) {
|
||||||
|
return stateContext.currentState === this._stateName;
|
||||||
|
} else {
|
||||||
|
return stateContext.previousState === this._stateName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 定时器 ID 条件
|
||||||
|
* @en Timer ID condition
|
||||||
|
*/
|
||||||
|
export class TimerIdCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'timerId';
|
||||||
|
|
||||||
|
constructor(private readonly _timerId: string) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (context.type !== 'timer') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timerContext = context as unknown as ITimerTriggerContext;
|
||||||
|
return timerContext.timerId === this._timerId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 碰撞实体条件
|
||||||
|
* @en Collision entity condition
|
||||||
|
*/
|
||||||
|
export class CollisionEntityCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'collisionEntity';
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly _otherEntityId?: string,
|
||||||
|
private readonly _checkEnter?: boolean,
|
||||||
|
private readonly _checkExit?: boolean
|
||||||
|
) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (context.type !== 'collision') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const collisionContext = context as unknown as ICollisionTriggerContext;
|
||||||
|
|
||||||
|
if (this._otherEntityId !== undefined && collisionContext.otherEntityId !== this._otherEntityId) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._checkEnter !== undefined && collisionContext.isEnter !== this._checkEnter) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._checkExit !== undefined && collisionContext.isExit !== this._checkExit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 自定义事件名称条件
|
||||||
|
* @en Custom event name condition
|
||||||
|
*/
|
||||||
|
export class CustomEventCondition implements ITriggerCondition {
|
||||||
|
readonly type = 'customEvent';
|
||||||
|
|
||||||
|
constructor(private readonly _eventName: string) {}
|
||||||
|
|
||||||
|
evaluate(context: ITriggerContext): boolean {
|
||||||
|
if (context.type !== 'custom') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const customContext = context as unknown as ICustomTriggerContext;
|
||||||
|
return customContext.eventName === this._eventName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 条件构建器 | Condition Builder
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 条件构建器 - 链式 API
|
||||||
|
* @en Condition builder - fluent API
|
||||||
|
*/
|
||||||
|
export class ConditionBuilder {
|
||||||
|
private _conditions: ITriggerCondition[] = [];
|
||||||
|
private _logic: ConditionLogic = 'and';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 设置组合逻辑为 AND
|
||||||
|
* @en Set combination logic to AND
|
||||||
|
*/
|
||||||
|
and(): this {
|
||||||
|
this._logic = 'and';
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 设置组合逻辑为 OR
|
||||||
|
* @en Set combination logic to OR
|
||||||
|
*/
|
||||||
|
or(): this {
|
||||||
|
this._logic = 'or';
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加触发器类型条件
|
||||||
|
* @en Add trigger type condition
|
||||||
|
*/
|
||||||
|
ofType(...types: TriggerType[]): this {
|
||||||
|
this._conditions.push(new TriggerTypeCondition(types));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加实体 ID 条件
|
||||||
|
* @en Add entity ID condition
|
||||||
|
*/
|
||||||
|
fromEntity(entityId: string): this {
|
||||||
|
this._conditions.push(new EntityIdCondition(entityId));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加输入动作条件
|
||||||
|
* @en Add input action condition
|
||||||
|
*/
|
||||||
|
onInput(action: string, options?: { pressed?: boolean; released?: boolean }): this {
|
||||||
|
this._conditions.push(new InputActionCondition(action, options?.pressed, options?.released));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加消息条件
|
||||||
|
* @en Add message condition
|
||||||
|
*/
|
||||||
|
onMessage(messageName: string): this {
|
||||||
|
this._conditions.push(new MessageNameCondition(messageName));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加状态条件
|
||||||
|
* @en Add state condition
|
||||||
|
*/
|
||||||
|
onState(stateName: string, checkCurrent: boolean = true): this {
|
||||||
|
this._conditions.push(new StateNameCondition(stateName, checkCurrent));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加定时器条件
|
||||||
|
* @en Add timer condition
|
||||||
|
*/
|
||||||
|
onTimer(timerId: string): this {
|
||||||
|
this._conditions.push(new TimerIdCondition(timerId));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加碰撞条件
|
||||||
|
* @en Add collision condition
|
||||||
|
*/
|
||||||
|
onCollision(options?: { entityId?: string; isEnter?: boolean; isExit?: boolean }): this {
|
||||||
|
this._conditions.push(new CollisionEntityCondition(
|
||||||
|
options?.entityId,
|
||||||
|
options?.isEnter,
|
||||||
|
options?.isExit
|
||||||
|
));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加自定义事件条件
|
||||||
|
* @en Add custom event condition
|
||||||
|
*/
|
||||||
|
onCustomEvent(eventName: string): this {
|
||||||
|
this._conditions.push(new CustomEventCondition(eventName));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加自定义函数条件
|
||||||
|
* @en Add custom function condition
|
||||||
|
*/
|
||||||
|
where(predicate: (context: ITriggerContext) => boolean): this {
|
||||||
|
this._conditions.push(new FunctionCondition(predicate));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 添加取反条件
|
||||||
|
* @en Add negated condition
|
||||||
|
*/
|
||||||
|
not(condition: ITriggerCondition): this {
|
||||||
|
this._conditions.push(new NotCondition(condition));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 构建条件
|
||||||
|
* @en Build condition
|
||||||
|
*/
|
||||||
|
build(): ITriggerCondition {
|
||||||
|
if (this._conditions.length === 0) {
|
||||||
|
return new AlwaysTrueCondition();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this._conditions.length === 1) {
|
||||||
|
return this._conditions[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CompositeCondition(this._conditions, this._logic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建条件构建器
|
||||||
|
* @en Create condition builder
|
||||||
|
*/
|
||||||
|
export function condition(): ConditionBuilder {
|
||||||
|
return new ConditionBuilder();
|
||||||
|
}
|
||||||
461
packages/blueprint/src/triggers/TriggerDispatcher.ts
Normal file
461
packages/blueprint/src/triggers/TriggerDispatcher.ts
Normal file
@@ -0,0 +1,461 @@
|
|||||||
|
/**
|
||||||
|
* @zh 触发器调度器
|
||||||
|
* @en Trigger Dispatcher
|
||||||
|
*
|
||||||
|
* @zh 负责分发触发器事件到订阅者
|
||||||
|
* @en Responsible for dispatching trigger events to subscribers
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { TriggerType, ITriggerContext } from './TriggerTypes';
|
||||||
|
import type { IBlueprintTrigger, ITriggerRegistry, TriggerCallback } from './BlueprintTrigger';
|
||||||
|
import { TriggerRegistry } from './BlueprintTrigger';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 调度器接口 | Dispatcher Interface
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发结果
|
||||||
|
* @en Trigger result
|
||||||
|
*/
|
||||||
|
export interface TriggerResult {
|
||||||
|
/**
|
||||||
|
* @zh 触发器 ID
|
||||||
|
* @en Trigger ID
|
||||||
|
*/
|
||||||
|
triggerId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 是否成功
|
||||||
|
* @en Is successful
|
||||||
|
*/
|
||||||
|
success: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 错误信息
|
||||||
|
* @en Error message
|
||||||
|
*/
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 调度结果
|
||||||
|
* @en Dispatch result
|
||||||
|
*/
|
||||||
|
export interface DispatchResult {
|
||||||
|
/**
|
||||||
|
* @zh 上下文
|
||||||
|
* @en Context
|
||||||
|
*/
|
||||||
|
context: ITriggerContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发的触发器数量
|
||||||
|
* @en Number of triggers fired
|
||||||
|
*/
|
||||||
|
triggeredCount: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 各触发器结果
|
||||||
|
* @en Results of each trigger
|
||||||
|
*/
|
||||||
|
results: TriggerResult[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器调度器接口
|
||||||
|
* @en Trigger dispatcher interface
|
||||||
|
*/
|
||||||
|
export interface ITriggerDispatcher {
|
||||||
|
/**
|
||||||
|
* @zh 调度触发器
|
||||||
|
* @en Dispatch trigger
|
||||||
|
*/
|
||||||
|
dispatch(context: ITriggerContext): DispatchResult;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 异步调度触发器
|
||||||
|
* @en Async dispatch trigger
|
||||||
|
*/
|
||||||
|
dispatchAsync(context: ITriggerContext): Promise<DispatchResult>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 订阅触发器类型
|
||||||
|
* @en Subscribe to trigger type
|
||||||
|
*/
|
||||||
|
subscribe(type: TriggerType, callback: TriggerCallback): () => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 取消订阅
|
||||||
|
* @en Unsubscribe
|
||||||
|
*/
|
||||||
|
unsubscribe(type: TriggerType, callback: TriggerCallback): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取注册表
|
||||||
|
* @en Get registry
|
||||||
|
*/
|
||||||
|
readonly registry: ITriggerRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 调度器实现 | Dispatcher Implementation
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器调度器实现
|
||||||
|
* @en Trigger dispatcher implementation
|
||||||
|
*/
|
||||||
|
export class TriggerDispatcher implements ITriggerDispatcher {
|
||||||
|
private readonly _registry: ITriggerRegistry;
|
||||||
|
private readonly _typeSubscribers: Map<TriggerType, Set<TriggerCallback>> = new Map();
|
||||||
|
private readonly _globalSubscribers: Set<TriggerCallback> = new Set();
|
||||||
|
private _isDispatching: boolean = false;
|
||||||
|
private _pendingContexts: ITriggerContext[] = [];
|
||||||
|
|
||||||
|
constructor(registry?: ITriggerRegistry) {
|
||||||
|
this._registry = registry ?? new TriggerRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
|
get registry(): ITriggerRegistry {
|
||||||
|
return this._registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 调度触发器
|
||||||
|
* @en Dispatch trigger
|
||||||
|
*/
|
||||||
|
dispatch(context: ITriggerContext): DispatchResult {
|
||||||
|
if (this._isDispatching) {
|
||||||
|
this._pendingContexts.push(context);
|
||||||
|
return {
|
||||||
|
context,
|
||||||
|
triggeredCount: 0,
|
||||||
|
results: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this._isDispatching = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = this._doDispatch(context);
|
||||||
|
|
||||||
|
while (this._pendingContexts.length > 0) {
|
||||||
|
const pendingContext = this._pendingContexts.shift()!;
|
||||||
|
this._doDispatch(pendingContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
this._isDispatching = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 执行调度
|
||||||
|
* @en Do dispatch
|
||||||
|
*/
|
||||||
|
private _doDispatch(context: ITriggerContext): DispatchResult {
|
||||||
|
const results: TriggerResult[] = [];
|
||||||
|
let triggeredCount = 0;
|
||||||
|
|
||||||
|
const triggers = this._registry.getByType(context.type);
|
||||||
|
|
||||||
|
for (const trigger of triggers) {
|
||||||
|
if (trigger.shouldFire(context)) {
|
||||||
|
try {
|
||||||
|
trigger.fire(context);
|
||||||
|
triggeredCount++;
|
||||||
|
results.push({
|
||||||
|
triggerId: trigger.id,
|
||||||
|
success: true
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
results.push({
|
||||||
|
triggerId: trigger.id,
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : String(error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._notifySubscribers(context);
|
||||||
|
|
||||||
|
return {
|
||||||
|
context,
|
||||||
|
triggeredCount,
|
||||||
|
results
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 通知订阅者
|
||||||
|
* @en Notify subscribers
|
||||||
|
*/
|
||||||
|
private _notifySubscribers(context: ITriggerContext): void {
|
||||||
|
const typeSubscribers = this._typeSubscribers.get(context.type);
|
||||||
|
if (typeSubscribers) {
|
||||||
|
for (const callback of typeSubscribers) {
|
||||||
|
try {
|
||||||
|
callback(context);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Trigger subscriber error: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const callback of this._globalSubscribers) {
|
||||||
|
try {
|
||||||
|
callback(context);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Global trigger subscriber error: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 异步调度触发器
|
||||||
|
* @en Async dispatch trigger
|
||||||
|
*/
|
||||||
|
async dispatchAsync(context: ITriggerContext): Promise<DispatchResult> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
queueMicrotask(() => {
|
||||||
|
resolve(this.dispatch(context));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 订阅触发器类型
|
||||||
|
* @en Subscribe to trigger type
|
||||||
|
*/
|
||||||
|
subscribe(type: TriggerType, callback: TriggerCallback): () => void {
|
||||||
|
if (!this._typeSubscribers.has(type)) {
|
||||||
|
this._typeSubscribers.set(type, new Set());
|
||||||
|
}
|
||||||
|
|
||||||
|
this._typeSubscribers.get(type)!.add(callback);
|
||||||
|
|
||||||
|
return () => this.unsubscribe(type, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 取消订阅
|
||||||
|
* @en Unsubscribe
|
||||||
|
*/
|
||||||
|
unsubscribe(type: TriggerType, callback: TriggerCallback): void {
|
||||||
|
const subscribers = this._typeSubscribers.get(type);
|
||||||
|
if (subscribers) {
|
||||||
|
subscribers.delete(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 订阅所有触发器
|
||||||
|
* @en Subscribe to all triggers
|
||||||
|
*/
|
||||||
|
subscribeAll(callback: TriggerCallback): () => void {
|
||||||
|
this._globalSubscribers.add(callback);
|
||||||
|
return () => this.unsubscribeAll(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 取消订阅所有
|
||||||
|
* @en Unsubscribe from all
|
||||||
|
*/
|
||||||
|
unsubscribeAll(callback: TriggerCallback): void {
|
||||||
|
this._globalSubscribers.delete(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 清除所有订阅
|
||||||
|
* @en Clear all subscriptions
|
||||||
|
*/
|
||||||
|
clearSubscriptions(): void {
|
||||||
|
this._typeSubscribers.clear();
|
||||||
|
this._globalSubscribers.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 实体触发器管理器 | Entity Trigger Manager
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 实体触发器管理器接口
|
||||||
|
* @en Entity trigger manager interface
|
||||||
|
*/
|
||||||
|
export interface IEntityTriggerManager {
|
||||||
|
/**
|
||||||
|
* @zh 为实体注册触发器
|
||||||
|
* @en Register trigger for entity
|
||||||
|
*/
|
||||||
|
registerForEntity(entityId: string, trigger: IBlueprintTrigger): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 注销实体的触发器
|
||||||
|
* @en Unregister trigger from entity
|
||||||
|
*/
|
||||||
|
unregisterFromEntity(entityId: string, triggerId: string): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取实体的所有触发器
|
||||||
|
* @en Get all triggers for entity
|
||||||
|
*/
|
||||||
|
getEntityTriggers(entityId: string): IBlueprintTrigger[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 清除实体的所有触发器
|
||||||
|
* @en Clear all triggers for entity
|
||||||
|
*/
|
||||||
|
clearEntityTriggers(entityId: string): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 调度器
|
||||||
|
* @en Dispatcher
|
||||||
|
*/
|
||||||
|
readonly dispatcher: ITriggerDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 实体触发器管理器实现
|
||||||
|
* @en Entity trigger manager implementation
|
||||||
|
*/
|
||||||
|
export class EntityTriggerManager implements IEntityTriggerManager {
|
||||||
|
private readonly _dispatcher: ITriggerDispatcher;
|
||||||
|
private readonly _entityTriggers: Map<string, Set<string>> = new Map();
|
||||||
|
|
||||||
|
constructor(dispatcher?: ITriggerDispatcher) {
|
||||||
|
this._dispatcher = dispatcher ?? new TriggerDispatcher();
|
||||||
|
}
|
||||||
|
|
||||||
|
get dispatcher(): ITriggerDispatcher {
|
||||||
|
return this._dispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 为实体注册触发器
|
||||||
|
* @en Register trigger for entity
|
||||||
|
*/
|
||||||
|
registerForEntity(entityId: string, trigger: IBlueprintTrigger): void {
|
||||||
|
this._dispatcher.registry.register(trigger);
|
||||||
|
|
||||||
|
if (!this._entityTriggers.has(entityId)) {
|
||||||
|
this._entityTriggers.set(entityId, new Set());
|
||||||
|
}
|
||||||
|
|
||||||
|
this._entityTriggers.get(entityId)!.add(trigger.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 注销实体的触发器
|
||||||
|
* @en Unregister trigger from entity
|
||||||
|
*/
|
||||||
|
unregisterFromEntity(entityId: string, triggerId: string): boolean {
|
||||||
|
const entitySet = this._entityTriggers.get(entityId);
|
||||||
|
if (!entitySet) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entitySet.has(triggerId)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
entitySet.delete(triggerId);
|
||||||
|
return this._dispatcher.registry.unregister(triggerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 获取实体的所有触发器
|
||||||
|
* @en Get all triggers for entity
|
||||||
|
*/
|
||||||
|
getEntityTriggers(entityId: string): IBlueprintTrigger[] {
|
||||||
|
const entitySet = this._entityTriggers.get(entityId);
|
||||||
|
if (!entitySet) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const triggers: IBlueprintTrigger[] = [];
|
||||||
|
for (const triggerId of entitySet) {
|
||||||
|
const trigger = this._dispatcher.registry.get(triggerId);
|
||||||
|
if (trigger) {
|
||||||
|
triggers.push(trigger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return triggers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 清除实体的所有触发器
|
||||||
|
* @en Clear all triggers for entity
|
||||||
|
*/
|
||||||
|
clearEntityTriggers(entityId: string): void {
|
||||||
|
const entitySet = this._entityTriggers.get(entityId);
|
||||||
|
if (!entitySet) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const triggerId of entitySet) {
|
||||||
|
this._dispatcher.registry.unregister(triggerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._entityTriggers.delete(entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 调度触发器到实体
|
||||||
|
* @en Dispatch trigger to entity
|
||||||
|
*/
|
||||||
|
dispatchToEntity(entityId: string, context: ITriggerContext): DispatchResult {
|
||||||
|
const entityTriggers = this.getEntityTriggers(entityId);
|
||||||
|
const results: TriggerResult[] = [];
|
||||||
|
let triggeredCount = 0;
|
||||||
|
|
||||||
|
for (const trigger of entityTriggers) {
|
||||||
|
if (trigger.shouldFire(context)) {
|
||||||
|
try {
|
||||||
|
trigger.fire(context);
|
||||||
|
triggeredCount++;
|
||||||
|
results.push({
|
||||||
|
triggerId: trigger.id,
|
||||||
|
success: true
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
results.push({
|
||||||
|
triggerId: trigger.id,
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : String(error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
context,
|
||||||
|
triggeredCount,
|
||||||
|
results
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 工厂函数 | Factory Functions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建触发器调度器
|
||||||
|
* @en Create trigger dispatcher
|
||||||
|
*/
|
||||||
|
export function createTriggerDispatcher(registry?: ITriggerRegistry): TriggerDispatcher {
|
||||||
|
return new TriggerDispatcher(registry);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建实体触发器管理器
|
||||||
|
* @en Create entity trigger manager
|
||||||
|
*/
|
||||||
|
export function createEntityTriggerManager(dispatcher?: ITriggerDispatcher): EntityTriggerManager {
|
||||||
|
return new EntityTriggerManager(dispatcher);
|
||||||
|
}
|
||||||
400
packages/blueprint/src/triggers/TriggerTypes.ts
Normal file
400
packages/blueprint/src/triggers/TriggerTypes.ts
Normal file
@@ -0,0 +1,400 @@
|
|||||||
|
/**
|
||||||
|
* @zh 蓝图触发器类型定义
|
||||||
|
* @en Blueprint Trigger Type Definitions
|
||||||
|
*
|
||||||
|
* @zh 定义触发器的核心类型和接口
|
||||||
|
* @en Defines core types and interfaces for triggers
|
||||||
|
*/
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器类型 | Trigger Types
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器类型枚举
|
||||||
|
* @en Trigger type enumeration
|
||||||
|
*/
|
||||||
|
export type TriggerType =
|
||||||
|
| 'tick' // 每帧触发 | Every frame
|
||||||
|
| 'input' // 输入事件 | Input event
|
||||||
|
| 'collision' // 碰撞事件 | Collision event
|
||||||
|
| 'message' // 消息事件 | Message event
|
||||||
|
| 'timer' // 定时器事件 | Timer event
|
||||||
|
| 'stateEnter' // 状态进入 | State enter
|
||||||
|
| 'stateExit' // 状态退出 | State exit
|
||||||
|
| 'custom'; // 自定义事件 | Custom event
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器类型常量
|
||||||
|
* @en Trigger type constants
|
||||||
|
*/
|
||||||
|
export const TriggerTypes = {
|
||||||
|
TICK: 'tick' as const,
|
||||||
|
INPUT: 'input' as const,
|
||||||
|
COLLISION: 'collision' as const,
|
||||||
|
MESSAGE: 'message' as const,
|
||||||
|
TIMER: 'timer' as const,
|
||||||
|
STATE_ENTER: 'stateEnter' as const,
|
||||||
|
STATE_EXIT: 'stateExit' as const,
|
||||||
|
CUSTOM: 'custom' as const
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器上下文 | Trigger Context
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发器上下文基础接口
|
||||||
|
* @en Trigger context base interface
|
||||||
|
*/
|
||||||
|
export interface ITriggerContext {
|
||||||
|
/**
|
||||||
|
* @zh 触发器类型
|
||||||
|
* @en Trigger type
|
||||||
|
*/
|
||||||
|
readonly type: TriggerType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发时间戳
|
||||||
|
* @en Trigger timestamp
|
||||||
|
*/
|
||||||
|
readonly timestamp: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 触发源实体 ID
|
||||||
|
* @en Source entity ID
|
||||||
|
*/
|
||||||
|
readonly sourceEntityId?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 附加数据
|
||||||
|
* @en Additional data
|
||||||
|
*/
|
||||||
|
readonly data?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh Tick 触发器上下文
|
||||||
|
* @en Tick trigger context
|
||||||
|
*/
|
||||||
|
export interface ITickTriggerContext extends ITriggerContext {
|
||||||
|
readonly type: 'tick';
|
||||||
|
/**
|
||||||
|
* @zh 增量时间(秒)
|
||||||
|
* @en Delta time (seconds)
|
||||||
|
*/
|
||||||
|
readonly deltaTime: number;
|
||||||
|
/**
|
||||||
|
* @zh 帧计数
|
||||||
|
* @en Frame count
|
||||||
|
*/
|
||||||
|
readonly frameCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 输入触发器上下文
|
||||||
|
* @en Input trigger context
|
||||||
|
*/
|
||||||
|
export interface IInputTriggerContext extends ITriggerContext {
|
||||||
|
readonly type: 'input';
|
||||||
|
/**
|
||||||
|
* @zh 输入动作名称
|
||||||
|
* @en Input action name
|
||||||
|
*/
|
||||||
|
readonly action: string;
|
||||||
|
/**
|
||||||
|
* @zh 输入值
|
||||||
|
* @en Input value
|
||||||
|
*/
|
||||||
|
readonly value: number | boolean;
|
||||||
|
/**
|
||||||
|
* @zh 是否刚按下
|
||||||
|
* @en Is just pressed
|
||||||
|
*/
|
||||||
|
readonly pressed?: boolean;
|
||||||
|
/**
|
||||||
|
* @zh 是否刚释放
|
||||||
|
* @en Is just released
|
||||||
|
*/
|
||||||
|
readonly released?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 碰撞触发器上下文
|
||||||
|
* @en Collision trigger context
|
||||||
|
*/
|
||||||
|
export interface ICollisionTriggerContext extends ITriggerContext {
|
||||||
|
readonly type: 'collision';
|
||||||
|
/**
|
||||||
|
* @zh 碰撞的另一个实体 ID
|
||||||
|
* @en Other entity ID in collision
|
||||||
|
*/
|
||||||
|
readonly otherEntityId: string;
|
||||||
|
/**
|
||||||
|
* @zh 碰撞点
|
||||||
|
* @en Collision point
|
||||||
|
*/
|
||||||
|
readonly point?: { x: number; y: number };
|
||||||
|
/**
|
||||||
|
* @zh 碰撞法线
|
||||||
|
* @en Collision normal
|
||||||
|
*/
|
||||||
|
readonly normal?: { x: number; y: number };
|
||||||
|
/**
|
||||||
|
* @zh 是否开始碰撞
|
||||||
|
* @en Is collision start
|
||||||
|
*/
|
||||||
|
readonly isEnter: boolean;
|
||||||
|
/**
|
||||||
|
* @zh 是否结束碰撞
|
||||||
|
* @en Is collision end
|
||||||
|
*/
|
||||||
|
readonly isExit: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 消息触发器上下文
|
||||||
|
* @en Message trigger context
|
||||||
|
*/
|
||||||
|
export interface IMessageTriggerContext extends ITriggerContext {
|
||||||
|
readonly type: 'message';
|
||||||
|
/**
|
||||||
|
* @zh 消息名称
|
||||||
|
* @en Message name
|
||||||
|
*/
|
||||||
|
readonly messageName: string;
|
||||||
|
/**
|
||||||
|
* @zh 发送者 ID
|
||||||
|
* @en Sender ID
|
||||||
|
*/
|
||||||
|
readonly senderId?: string;
|
||||||
|
/**
|
||||||
|
* @zh 消息负载
|
||||||
|
* @en Message payload
|
||||||
|
*/
|
||||||
|
readonly payload?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 定时器触发器上下文
|
||||||
|
* @en Timer trigger context
|
||||||
|
*/
|
||||||
|
export interface ITimerTriggerContext extends ITriggerContext {
|
||||||
|
readonly type: 'timer';
|
||||||
|
/**
|
||||||
|
* @zh 定时器 ID
|
||||||
|
* @en Timer ID
|
||||||
|
*/
|
||||||
|
readonly timerId: string;
|
||||||
|
/**
|
||||||
|
* @zh 是否循环触发
|
||||||
|
* @en Is repeating
|
||||||
|
*/
|
||||||
|
readonly isRepeating: boolean;
|
||||||
|
/**
|
||||||
|
* @zh 已触发次数
|
||||||
|
* @en Times fired
|
||||||
|
*/
|
||||||
|
readonly timesFired: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 状态触发器上下文
|
||||||
|
* @en State trigger context
|
||||||
|
*/
|
||||||
|
export interface IStateTriggerContext extends ITriggerContext {
|
||||||
|
readonly type: 'stateEnter' | 'stateExit';
|
||||||
|
/**
|
||||||
|
* @zh 状态机 ID
|
||||||
|
* @en State machine ID
|
||||||
|
*/
|
||||||
|
readonly stateMachineId: string;
|
||||||
|
/**
|
||||||
|
* @zh 当前状态
|
||||||
|
* @en Current state
|
||||||
|
*/
|
||||||
|
readonly currentState: string;
|
||||||
|
/**
|
||||||
|
* @zh 之前状态
|
||||||
|
* @en Previous state
|
||||||
|
*/
|
||||||
|
readonly previousState?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 自定义触发器上下文
|
||||||
|
* @en Custom trigger context
|
||||||
|
*/
|
||||||
|
export interface ICustomTriggerContext extends ITriggerContext {
|
||||||
|
readonly type: 'custom';
|
||||||
|
/**
|
||||||
|
* @zh 事件名称
|
||||||
|
* @en Event name
|
||||||
|
*/
|
||||||
|
readonly eventName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 所有触发器上下文的联合类型
|
||||||
|
* @en Union type of all trigger contexts
|
||||||
|
*/
|
||||||
|
export type TriggerContext =
|
||||||
|
| ITickTriggerContext
|
||||||
|
| IInputTriggerContext
|
||||||
|
| ICollisionTriggerContext
|
||||||
|
| IMessageTriggerContext
|
||||||
|
| ITimerTriggerContext
|
||||||
|
| IStateTriggerContext
|
||||||
|
| ICustomTriggerContext;
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 工厂函数 | Factory Functions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建 Tick 触发器上下文
|
||||||
|
* @en Create tick trigger context
|
||||||
|
*/
|
||||||
|
export function createTickContext(
|
||||||
|
deltaTime: number,
|
||||||
|
frameCount: number,
|
||||||
|
sourceEntityId?: string
|
||||||
|
): ITickTriggerContext {
|
||||||
|
return {
|
||||||
|
type: 'tick',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
deltaTime,
|
||||||
|
frameCount,
|
||||||
|
sourceEntityId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建输入触发器上下文
|
||||||
|
* @en Create input trigger context
|
||||||
|
*/
|
||||||
|
export function createInputContext(
|
||||||
|
action: string,
|
||||||
|
value: number | boolean,
|
||||||
|
options?: {
|
||||||
|
pressed?: boolean;
|
||||||
|
released?: boolean;
|
||||||
|
sourceEntityId?: string;
|
||||||
|
}
|
||||||
|
): IInputTriggerContext {
|
||||||
|
return {
|
||||||
|
type: 'input',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
action,
|
||||||
|
value,
|
||||||
|
pressed: options?.pressed,
|
||||||
|
released: options?.released,
|
||||||
|
sourceEntityId: options?.sourceEntityId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建碰撞触发器上下文
|
||||||
|
* @en Create collision trigger context
|
||||||
|
*/
|
||||||
|
export function createCollisionContext(
|
||||||
|
otherEntityId: string,
|
||||||
|
isEnter: boolean,
|
||||||
|
options?: {
|
||||||
|
point?: { x: number; y: number };
|
||||||
|
normal?: { x: number; y: number };
|
||||||
|
sourceEntityId?: string;
|
||||||
|
}
|
||||||
|
): ICollisionTriggerContext {
|
||||||
|
return {
|
||||||
|
type: 'collision',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
otherEntityId,
|
||||||
|
isEnter,
|
||||||
|
isExit: !isEnter,
|
||||||
|
point: options?.point,
|
||||||
|
normal: options?.normal,
|
||||||
|
sourceEntityId: options?.sourceEntityId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建消息触发器上下文
|
||||||
|
* @en Create message trigger context
|
||||||
|
*/
|
||||||
|
export function createMessageContext(
|
||||||
|
messageName: string,
|
||||||
|
payload?: unknown,
|
||||||
|
options?: {
|
||||||
|
senderId?: string;
|
||||||
|
sourceEntityId?: string;
|
||||||
|
}
|
||||||
|
): IMessageTriggerContext {
|
||||||
|
return {
|
||||||
|
type: 'message',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
messageName,
|
||||||
|
payload,
|
||||||
|
senderId: options?.senderId,
|
||||||
|
sourceEntityId: options?.sourceEntityId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建定时器触发器上下文
|
||||||
|
* @en Create timer trigger context
|
||||||
|
*/
|
||||||
|
export function createTimerContext(
|
||||||
|
timerId: string,
|
||||||
|
isRepeating: boolean,
|
||||||
|
timesFired: number,
|
||||||
|
sourceEntityId?: string
|
||||||
|
): ITimerTriggerContext {
|
||||||
|
return {
|
||||||
|
type: 'timer',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
timerId,
|
||||||
|
isRepeating,
|
||||||
|
timesFired,
|
||||||
|
sourceEntityId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建状态触发器上下文
|
||||||
|
* @en Create state trigger context
|
||||||
|
*/
|
||||||
|
export function createStateContext(
|
||||||
|
type: 'stateEnter' | 'stateExit',
|
||||||
|
stateMachineId: string,
|
||||||
|
currentState: string,
|
||||||
|
previousState?: string,
|
||||||
|
sourceEntityId?: string
|
||||||
|
): IStateTriggerContext {
|
||||||
|
return {
|
||||||
|
type,
|
||||||
|
timestamp: Date.now(),
|
||||||
|
stateMachineId,
|
||||||
|
currentState,
|
||||||
|
previousState,
|
||||||
|
sourceEntityId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @zh 创建自定义触发器上下文
|
||||||
|
* @en Create custom trigger context
|
||||||
|
*/
|
||||||
|
export function createCustomContext(
|
||||||
|
eventName: string,
|
||||||
|
data?: Record<string, unknown>,
|
||||||
|
sourceEntityId?: string
|
||||||
|
): ICustomTriggerContext {
|
||||||
|
return {
|
||||||
|
type: 'custom',
|
||||||
|
timestamp: Date.now(),
|
||||||
|
eventName,
|
||||||
|
data,
|
||||||
|
sourceEntityId
|
||||||
|
};
|
||||||
|
}
|
||||||
105
packages/blueprint/src/triggers/index.ts
Normal file
105
packages/blueprint/src/triggers/index.ts
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/**
|
||||||
|
* @zh 蓝图触发器模块
|
||||||
|
* @en Blueprint Triggers Module
|
||||||
|
*
|
||||||
|
* @zh 提供蓝图触发器系统的所有导出
|
||||||
|
* @en Provides all exports for the blueprint trigger system
|
||||||
|
*/
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器类型 | Trigger Types
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
export type {
|
||||||
|
TriggerType,
|
||||||
|
ITriggerContext,
|
||||||
|
ITickTriggerContext,
|
||||||
|
IInputTriggerContext,
|
||||||
|
ICollisionTriggerContext,
|
||||||
|
IMessageTriggerContext,
|
||||||
|
ITimerTriggerContext,
|
||||||
|
IStateTriggerContext,
|
||||||
|
ICustomTriggerContext,
|
||||||
|
TriggerContext
|
||||||
|
} from './TriggerTypes';
|
||||||
|
|
||||||
|
export {
|
||||||
|
TriggerTypes,
|
||||||
|
createTickContext,
|
||||||
|
createInputContext,
|
||||||
|
createCollisionContext,
|
||||||
|
createMessageContext,
|
||||||
|
createTimerContext,
|
||||||
|
createStateContext,
|
||||||
|
createCustomContext
|
||||||
|
} from './TriggerTypes';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器条件 | Trigger Conditions
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
export type {
|
||||||
|
ITriggerCondition,
|
||||||
|
ConditionLogic
|
||||||
|
} from './TriggerCondition';
|
||||||
|
|
||||||
|
export {
|
||||||
|
CompositeCondition,
|
||||||
|
NotCondition,
|
||||||
|
AlwaysTrueCondition,
|
||||||
|
AlwaysFalseCondition,
|
||||||
|
TriggerTypeCondition,
|
||||||
|
EntityIdCondition,
|
||||||
|
FunctionCondition,
|
||||||
|
InputActionCondition,
|
||||||
|
MessageNameCondition,
|
||||||
|
StateNameCondition,
|
||||||
|
TimerIdCondition,
|
||||||
|
CollisionEntityCondition,
|
||||||
|
CustomEventCondition,
|
||||||
|
ConditionBuilder,
|
||||||
|
condition
|
||||||
|
} from './TriggerCondition';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 蓝图触发器 | Blueprint Trigger
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
export type {
|
||||||
|
TriggerCallback,
|
||||||
|
IBlueprintTrigger,
|
||||||
|
TriggerConfig,
|
||||||
|
ITriggerRegistry
|
||||||
|
} from './BlueprintTrigger';
|
||||||
|
|
||||||
|
export {
|
||||||
|
BlueprintTrigger,
|
||||||
|
TriggerRegistry,
|
||||||
|
createTrigger,
|
||||||
|
createTickTrigger,
|
||||||
|
createInputTrigger,
|
||||||
|
createCollisionTrigger,
|
||||||
|
createMessageTrigger,
|
||||||
|
createTimerTrigger,
|
||||||
|
createStateEnterTrigger,
|
||||||
|
createStateExitTrigger,
|
||||||
|
createCustomTrigger
|
||||||
|
} from './BlueprintTrigger';
|
||||||
|
|
||||||
|
// =============================================================================
|
||||||
|
// 触发器调度器 | Trigger Dispatcher
|
||||||
|
// =============================================================================
|
||||||
|
|
||||||
|
export type {
|
||||||
|
TriggerResult,
|
||||||
|
DispatchResult,
|
||||||
|
ITriggerDispatcher,
|
||||||
|
IEntityTriggerManager
|
||||||
|
} from './TriggerDispatcher';
|
||||||
|
|
||||||
|
export {
|
||||||
|
TriggerDispatcher,
|
||||||
|
EntityTriggerManager,
|
||||||
|
createTriggerDispatcher,
|
||||||
|
createEntityTriggerManager
|
||||||
|
} from './TriggerDispatcher';
|
||||||
Reference in New Issue
Block a user