refactor: reorganize package structure and decouple framework packages (#338)

* refactor: reorganize package structure and decouple framework packages

## Package Structure Reorganization
- Reorganized 55 packages into categorized subdirectories:
  - packages/framework/ - Generic framework (Laya/Cocos compatible)
  - packages/engine/ - ESEngine core modules
  - packages/rendering/ - Rendering modules (WASM dependent)
  - packages/physics/ - Physics modules
  - packages/streaming/ - World streaming
  - packages/network-ext/ - Network extensions
  - packages/editor/ - Editor framework and plugins
  - packages/rust/ - Rust WASM engine
  - packages/tools/ - Build tools and SDK

## Framework Package Decoupling
- Decoupled behavior-tree and blueprint packages from ESEngine dependencies
- Created abstracted interfaces (IBTAssetManager, IBehaviorTreeAssetContent)
- ESEngine-specific code moved to esengine/ subpath exports
- Framework packages now usable with Cocos/Laya without ESEngine

## CI Configuration
- Updated CI to only type-check and lint framework packages
- Added type-check:framework and lint:framework scripts

## Breaking Changes
- Package import paths changed due to directory reorganization
- ESEngine integrations now use subpath imports (e.g., '@esengine/behavior-tree/esengine')

* fix: update es-engine file path after directory reorganization

* docs: update README to focus on framework over engine

* ci: only build framework packages, remove Rust/WASM dependencies

* fix: remove esengine subpath from behavior-tree and blueprint builds

ESEngine integration code will only be available in full engine builds.
Framework packages are now purely engine-agnostic.

* fix: move network-protocols to framework, build both in CI

* fix: update workflow paths from packages/core to packages/framework/core

* fix: exclude esengine folder from type-check in behavior-tree and blueprint

* fix: update network tsconfig references to new paths

* fix: add test:ci:framework to only test framework packages in CI

* fix: only build core and math npm packages in CI

* fix: exclude test files from CodeQL and fix string escaping security issue
This commit is contained in:
YHH
2025-12-26 14:50:35 +08:00
committed by GitHub
parent a84ff902e4
commit 155411e743
1936 changed files with 4147 additions and 11578 deletions

View File

@@ -0,0 +1,543 @@
/**
* @zh 定时器蓝图节点
* @en Timer Blueprint Nodes
*
* @zh 提供定时器和冷却功能的蓝图节点
* @en Provides blueprint nodes for timer and cooldown functionality
*/
import type { BlueprintNodeTemplate, BlueprintNode, INodeExecutor, ExecutionResult } from '@esengine/blueprint';
import type { ITimerService } from '../ITimerService';
// =============================================================================
// 执行上下文接口 | Execution Context Interface
// =============================================================================
/**
* @zh 定时器上下文
* @en Timer context
*/
interface TimerContext {
timerService: ITimerService;
evaluateInput(nodeId: string, pinName: string, defaultValue?: unknown): unknown;
setOutputs(nodeId: string, outputs: Record<string, unknown>): void;
}
// =============================================================================
// StartCooldown 节点 | StartCooldown Node
// =============================================================================
/**
* @zh StartCooldown 节点模板
* @en StartCooldown node template
*/
export const StartCooldownTemplate: BlueprintNodeTemplate = {
type: 'StartCooldown',
title: 'Start Cooldown',
category: 'time',
description: 'Start a cooldown timer / 开始冷却计时',
keywords: ['timer', 'cooldown', 'start', 'delay'],
menuPath: ['Timer', 'Start Cooldown'],
isPure: false,
inputs: [
{
name: 'exec',
displayName: '',
type: 'exec'
},
{
name: 'id',
displayName: 'Cooldown ID',
type: 'string',
defaultValue: ''
},
{
name: 'duration',
displayName: 'Duration (ms)',
type: 'float',
defaultValue: 1000
}
],
outputs: [
{
name: 'exec',
displayName: '',
type: 'exec'
}
],
color: '#00bcd4'
};
/**
* @zh StartCooldown 节点执行器
* @en StartCooldown node executor
*/
export class StartCooldownExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
const duration = ctx.evaluateInput(node.id, 'duration', 1000) as number;
if (id && ctx.timerService) {
ctx.timerService.startCooldown(id, duration);
}
return {
outputs: {},
nextExec: 'exec'
};
}
}
// =============================================================================
// IsCooldownReady 节点 | IsCooldownReady Node
// =============================================================================
/**
* @zh IsCooldownReady 节点模板
* @en IsCooldownReady node template
*/
export const IsCooldownReadyTemplate: BlueprintNodeTemplate = {
type: 'IsCooldownReady',
title: 'Is Cooldown Ready',
category: 'time',
description: 'Check if cooldown is ready / 检查冷却是否就绪',
keywords: ['timer', 'cooldown', 'ready', 'check'],
menuPath: ['Timer', 'Is Cooldown Ready'],
isPure: true,
inputs: [
{
name: 'id',
displayName: 'Cooldown ID',
type: 'string',
defaultValue: ''
}
],
outputs: [
{
name: 'isReady',
displayName: 'Is Ready',
type: 'bool'
},
{
name: 'isOnCooldown',
displayName: 'Is On Cooldown',
type: 'bool'
}
],
color: '#00bcd4'
};
/**
* @zh IsCooldownReady 节点执行器
* @en IsCooldownReady node executor
*/
export class IsCooldownReadyExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
const isReady = id ? ctx.timerService?.isCooldownReady(id) ?? true : true;
const isOnCooldown = !isReady;
return {
outputs: {
isReady,
isOnCooldown
}
};
}
}
// =============================================================================
// GetCooldownProgress 节点 | GetCooldownProgress Node
// =============================================================================
/**
* @zh GetCooldownProgress 节点模板
* @en GetCooldownProgress node template
*/
export const GetCooldownProgressTemplate: BlueprintNodeTemplate = {
type: 'GetCooldownProgress',
title: 'Get Cooldown Progress',
category: 'time',
description: 'Get cooldown progress (0-1) / 获取冷却进度 (0-1)',
keywords: ['timer', 'cooldown', 'progress', 'remaining'],
menuPath: ['Timer', 'Get Cooldown Progress'],
isPure: true,
inputs: [
{
name: 'id',
displayName: 'Cooldown ID',
type: 'string',
defaultValue: ''
}
],
outputs: [
{
name: 'progress',
displayName: 'Progress',
type: 'float'
},
{
name: 'remaining',
displayName: 'Remaining (ms)',
type: 'float'
},
{
name: 'isReady',
displayName: 'Is Ready',
type: 'bool'
}
],
color: '#00bcd4'
};
/**
* @zh GetCooldownProgress 节点执行器
* @en GetCooldownProgress node executor
*/
export class GetCooldownProgressExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
const progress = id ? ctx.timerService?.getCooldownProgress(id) ?? 1 : 1;
const remaining = id ? ctx.timerService?.getCooldownRemaining(id) ?? 0 : 0;
const isReady = remaining <= 0;
return {
outputs: {
progress,
remaining,
isReady
}
};
}
}
// =============================================================================
// ResetCooldown 节点 | ResetCooldown Node
// =============================================================================
/**
* @zh ResetCooldown 节点模板
* @en ResetCooldown node template
*/
export const ResetCooldownTemplate: BlueprintNodeTemplate = {
type: 'ResetCooldown',
title: 'Reset Cooldown',
category: 'time',
description: 'Reset a cooldown (make it ready) / 重置冷却(使其就绪)',
keywords: ['timer', 'cooldown', 'reset', 'clear'],
menuPath: ['Timer', 'Reset Cooldown'],
isPure: false,
inputs: [
{
name: 'exec',
displayName: '',
type: 'exec'
},
{
name: 'id',
displayName: 'Cooldown ID',
type: 'string',
defaultValue: ''
}
],
outputs: [
{
name: 'exec',
displayName: '',
type: 'exec'
}
],
color: '#00bcd4'
};
/**
* @zh ResetCooldown 节点执行器
* @en ResetCooldown node executor
*/
export class ResetCooldownExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
if (id && ctx.timerService) {
ctx.timerService.resetCooldown(id);
}
return {
outputs: {},
nextExec: 'exec'
};
}
}
// =============================================================================
// GetCooldownInfo 节点 | GetCooldownInfo Node
// =============================================================================
/**
* @zh GetCooldownInfo 节点模板
* @en GetCooldownInfo node template
*/
export const GetCooldownInfoTemplate: BlueprintNodeTemplate = {
type: 'GetCooldownInfo',
title: 'Get Cooldown Info',
category: 'time',
description: 'Get detailed cooldown information / 获取详细冷却信息',
keywords: ['timer', 'cooldown', 'info', 'details'],
menuPath: ['Timer', 'Get Cooldown Info'],
isPure: true,
inputs: [
{
name: 'id',
displayName: 'Cooldown ID',
type: 'string',
defaultValue: ''
}
],
outputs: [
{
name: 'exists',
displayName: 'Exists',
type: 'bool'
},
{
name: 'duration',
displayName: 'Duration (ms)',
type: 'float'
},
{
name: 'remaining',
displayName: 'Remaining (ms)',
type: 'float'
},
{
name: 'progress',
displayName: 'Progress',
type: 'float'
},
{
name: 'isReady',
displayName: 'Is Ready',
type: 'bool'
}
],
color: '#00bcd4'
};
/**
* @zh GetCooldownInfo 节点执行器
* @en GetCooldownInfo node executor
*/
export class GetCooldownInfoExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
const info = id ? ctx.timerService?.getCooldownInfo(id) : null;
return {
outputs: {
exists: info !== null,
duration: info?.duration ?? 0,
remaining: info?.remaining ?? 0,
progress: info?.progress ?? 1,
isReady: info?.isReady ?? true
}
};
}
}
// =============================================================================
// HasTimer 节点 | HasTimer Node
// =============================================================================
/**
* @zh HasTimer 节点模板
* @en HasTimer node template
*/
export const HasTimerTemplate: BlueprintNodeTemplate = {
type: 'HasTimer',
title: 'Has Timer',
category: 'time',
description: 'Check if a timer exists / 检查定时器是否存在',
keywords: ['timer', 'exists', 'check', 'has'],
menuPath: ['Timer', 'Has Timer'],
isPure: true,
inputs: [
{
name: 'id',
displayName: 'Timer ID',
type: 'string',
defaultValue: ''
}
],
outputs: [
{
name: 'exists',
displayName: 'Exists',
type: 'bool'
}
],
color: '#00bcd4'
};
/**
* @zh HasTimer 节点执行器
* @en HasTimer node executor
*/
export class HasTimerExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
const exists = id ? ctx.timerService?.hasTimer(id) ?? false : false;
return {
outputs: {
exists
}
};
}
}
// =============================================================================
// CancelTimer 节点 | CancelTimer Node
// =============================================================================
/**
* @zh CancelTimer 节点模板
* @en CancelTimer node template
*/
export const CancelTimerTemplate: BlueprintNodeTemplate = {
type: 'CancelTimer',
title: 'Cancel Timer',
category: 'time',
description: 'Cancel a timer by ID / 通过 ID 取消定时器',
keywords: ['timer', 'cancel', 'stop', 'clear'],
menuPath: ['Timer', 'Cancel Timer'],
isPure: false,
inputs: [
{
name: 'exec',
displayName: '',
type: 'exec'
},
{
name: 'id',
displayName: 'Timer ID',
type: 'string',
defaultValue: ''
}
],
outputs: [
{
name: 'exec',
displayName: '',
type: 'exec'
}
],
color: '#00bcd4'
};
/**
* @zh CancelTimer 节点执行器
* @en CancelTimer node executor
*/
export class CancelTimerExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
if (id && ctx.timerService) {
ctx.timerService.cancelById(id);
}
return {
outputs: {},
nextExec: 'exec'
};
}
}
// =============================================================================
// GetTimerRemaining 节点 | GetTimerRemaining Node
// =============================================================================
/**
* @zh GetTimerRemaining 节点模板
* @en GetTimerRemaining node template
*/
export const GetTimerRemainingTemplate: BlueprintNodeTemplate = {
type: 'GetTimerRemaining',
title: 'Get Timer Remaining',
category: 'time',
description: 'Get remaining time for a timer / 获取定时器剩余时间',
keywords: ['timer', 'remaining', 'time', 'left'],
menuPath: ['Timer', 'Get Timer Remaining'],
isPure: true,
inputs: [
{
name: 'id',
displayName: 'Timer ID',
type: 'string',
defaultValue: ''
}
],
outputs: [
{
name: 'remaining',
displayName: 'Remaining (ms)',
type: 'float'
},
{
name: 'exists',
displayName: 'Exists',
type: 'bool'
}
],
color: '#00bcd4'
};
/**
* @zh GetTimerRemaining 节点执行器
* @en GetTimerRemaining node executor
*/
export class GetTimerRemainingExecutor implements INodeExecutor {
execute(node: BlueprintNode, context: unknown): ExecutionResult {
const ctx = context as TimerContext;
const id = ctx.evaluateInput(node.id, 'id', '') as string;
const info = id ? ctx.timerService?.getTimerInfo(id) : null;
return {
outputs: {
remaining: info?.remaining ?? 0,
exists: info !== null
}
};
}
}
// =============================================================================
// 节点定义集合 | Node Definition Collection
// =============================================================================
/**
* @zh 定时器节点定义
* @en Timer node definitions
*/
export const TimerNodeDefinitions = [
{ template: StartCooldownTemplate, executor: new StartCooldownExecutor() },
{ template: IsCooldownReadyTemplate, executor: new IsCooldownReadyExecutor() },
{ template: GetCooldownProgressTemplate, executor: new GetCooldownProgressExecutor() },
{ template: ResetCooldownTemplate, executor: new ResetCooldownExecutor() },
{ template: GetCooldownInfoTemplate, executor: new GetCooldownInfoExecutor() },
{ template: HasTimerTemplate, executor: new HasTimerExecutor() },
{ template: CancelTimerTemplate, executor: new CancelTimerExecutor() },
{ template: GetTimerRemainingTemplate, executor: new GetTimerRemainingExecutor() }
];

View File

@@ -0,0 +1,27 @@
/**
* @zh 定时器蓝图节点导出
* @en Timer Blueprint Nodes Export
*/
export {
// Templates
StartCooldownTemplate,
IsCooldownReadyTemplate,
GetCooldownProgressTemplate,
ResetCooldownTemplate,
GetCooldownInfoTemplate,
HasTimerTemplate,
CancelTimerTemplate,
GetTimerRemainingTemplate,
// Executors
StartCooldownExecutor,
IsCooldownReadyExecutor,
GetCooldownProgressExecutor,
ResetCooldownExecutor,
GetCooldownInfoExecutor,
HasTimerExecutor,
CancelTimerExecutor,
GetTimerRemainingExecutor,
// Collection
TimerNodeDefinitions
} from './TimerNodes';