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:
214
packages/engine/script-runtime/src/intent/IntentCollector.ts
Normal file
214
packages/engine/script-runtime/src/intent/IntentCollector.ts
Normal file
@@ -0,0 +1,214 @@
|
||||
/**
|
||||
* @zh 意图收集器
|
||||
* @en Intent Collector
|
||||
*
|
||||
* @zh 收集玩家蓝图执行过程中产生的所有意图
|
||||
* @en Collects all intents generated during player blueprint execution
|
||||
*/
|
||||
|
||||
import type { IIntent, IntentKeyExtractor } from './IntentTypes';
|
||||
import { defaultIntentKeyExtractor } from './IntentTypes';
|
||||
|
||||
/**
|
||||
* @zh 意图收集器接口
|
||||
* @en Intent collector interface
|
||||
*/
|
||||
export interface IIntentCollector<T extends IIntent = IIntent> {
|
||||
/**
|
||||
* @zh 添加一个意图
|
||||
* @en Add an intent
|
||||
*/
|
||||
addIntent(intent: T): boolean;
|
||||
|
||||
/**
|
||||
* @zh 获取所有收集的意图
|
||||
* @en Get all collected intents
|
||||
*/
|
||||
getIntents(): T[];
|
||||
|
||||
/**
|
||||
* @zh 按类型获取意图
|
||||
* @en Get intents by type
|
||||
*/
|
||||
getIntentsByType(type: string): T[];
|
||||
|
||||
/**
|
||||
* @zh 清除所有意图
|
||||
* @en Clear all intents
|
||||
*/
|
||||
clear(): void;
|
||||
|
||||
/**
|
||||
* @zh 获取意图数量
|
||||
* @en Get intent count
|
||||
*/
|
||||
readonly count: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 意图收集器
|
||||
* @en Intent Collector
|
||||
*
|
||||
* @zh 在蓝图执行过程中收集玩家的操作意图,执行完成后由服务器统一处理
|
||||
* @en Collects player operation intents during blueprint execution, processed by server after execution
|
||||
*
|
||||
* @typeParam T - @zh 意图类型,必须继承 IIntent @en Intent type, must extend IIntent
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 游戏项目中定义意图类型 | Define intent types in game project
|
||||
* interface MyGameIntent extends IIntent {
|
||||
* readonly type: 'unit.move' | 'unit.attack';
|
||||
* unitId: string;
|
||||
* }
|
||||
*
|
||||
* // 创建收集器时提供键提取器 | Provide key extractor when creating collector
|
||||
* const collector = new IntentCollector<MyGameIntent>('player1', {
|
||||
* keyExtractor: (intent) => `${intent.type}:${intent.unitId}`
|
||||
* });
|
||||
*
|
||||
* collector.addIntent({ type: 'unit.move', unitId: 'unit1' });
|
||||
* ```
|
||||
*/
|
||||
export class IntentCollector<T extends IIntent = IIntent> implements IIntentCollector<T> {
|
||||
/**
|
||||
* @zh 玩家 ID
|
||||
* @en Player ID
|
||||
*/
|
||||
private readonly _playerId: string;
|
||||
|
||||
/**
|
||||
* @zh 当前 tick
|
||||
* @en Current tick
|
||||
*/
|
||||
private _currentTick: number = 0;
|
||||
|
||||
/**
|
||||
* @zh 收集的意图列表
|
||||
* @en Collected intents list
|
||||
*/
|
||||
private _intents: T[] = [];
|
||||
|
||||
/**
|
||||
* @zh 按类型索引的意图
|
||||
* @en Intents indexed by type
|
||||
*/
|
||||
private _intentsByType: Map<string, T[]> = new Map();
|
||||
|
||||
/**
|
||||
* @zh 已添加的意图键(防止重复)
|
||||
* @en Added intent keys (prevent duplicates)
|
||||
*/
|
||||
private _intentKeys: Set<string> = new Set();
|
||||
|
||||
/**
|
||||
* @zh 意图键提取器
|
||||
* @en Intent key extractor
|
||||
*/
|
||||
private readonly _keyExtractor: IntentKeyExtractor<T>;
|
||||
|
||||
/**
|
||||
* @param playerId - @zh 玩家 ID @en Player ID
|
||||
* @param options - @zh 配置选项 @en Configuration options
|
||||
*/
|
||||
constructor(
|
||||
playerId: string,
|
||||
options: {
|
||||
keyExtractor?: IntentKeyExtractor<T>;
|
||||
} = {}
|
||||
) {
|
||||
this._playerId = playerId;
|
||||
this._keyExtractor = options.keyExtractor ?? (defaultIntentKeyExtractor as IntentKeyExtractor<T>);
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 获取意图数量
|
||||
* @en Get intent count
|
||||
*/
|
||||
get count(): number {
|
||||
return this._intents.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 获取玩家 ID
|
||||
* @en Get player ID
|
||||
*/
|
||||
get playerId(): string {
|
||||
return this._playerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 设置当前 tick
|
||||
* @en Set current tick
|
||||
*/
|
||||
setTick(tick: number): void {
|
||||
this._currentTick = tick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 添加一个意图
|
||||
* @en Add an intent
|
||||
*
|
||||
* @param intent - @zh 要添加的意图 @en Intent to add
|
||||
* @returns @zh 是否添加成功(重复意图返回 false)@en Whether added successfully (duplicate returns false)
|
||||
*/
|
||||
addIntent(intent: T): boolean {
|
||||
const key = this._keyExtractor(intent);
|
||||
|
||||
if (this._intentKeys.has(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 添加元数据 | Add metadata
|
||||
const intentWithMeta: T = {
|
||||
...intent,
|
||||
playerId: this._playerId,
|
||||
tick: this._currentTick
|
||||
};
|
||||
|
||||
this._intents.push(intentWithMeta);
|
||||
this._intentKeys.add(key);
|
||||
|
||||
// 按类型索引 | Index by type
|
||||
if (!this._intentsByType.has(intent.type)) {
|
||||
this._intentsByType.set(intent.type, []);
|
||||
}
|
||||
this._intentsByType.get(intent.type)!.push(intentWithMeta);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 获取所有收集的意图
|
||||
* @en Get all collected intents
|
||||
*/
|
||||
getIntents(): T[] {
|
||||
return [...this._intents];
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 按类型获取意图
|
||||
* @en Get intents by type
|
||||
*/
|
||||
getIntentsByType(type: string): T[] {
|
||||
return [...(this._intentsByType.get(type) ?? [])];
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 检查是否已有指定键的意图
|
||||
* @en Check if intent with specified key exists
|
||||
*/
|
||||
hasIntentKey(key: string): boolean {
|
||||
return this._intentKeys.has(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 清除所有意图
|
||||
* @en Clear all intents
|
||||
*/
|
||||
clear(): void {
|
||||
this._intents = [];
|
||||
this._intentsByType.clear();
|
||||
this._intentKeys.clear();
|
||||
}
|
||||
}
|
||||
138
packages/engine/script-runtime/src/intent/IntentTypes.ts
Normal file
138
packages/engine/script-runtime/src/intent/IntentTypes.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* @zh 意图类型定义(引擎基础接口)
|
||||
* @en Intent type definitions (engine base interface)
|
||||
*
|
||||
* @zh 引擎只提供基础的 IIntent 接口,具体的意图类型由游戏项目定义
|
||||
* @en Engine only provides base IIntent interface, specific intent types are defined by game projects
|
||||
*/
|
||||
|
||||
// =============================================================================
|
||||
// 基础意图接口 | Base Intent Interface
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @zh 基础意图接口
|
||||
* @en Base intent interface
|
||||
*
|
||||
* @zh 所有游戏意图都应该继承这个接口
|
||||
* @en All game intents should extend this interface
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* // 游戏项目中定义具体意图 | Define specific intents in game project
|
||||
* interface UnitMoveIntent extends IIntent {
|
||||
* readonly type: 'unit.move';
|
||||
* unitId: string;
|
||||
* direction: number;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export interface IIntent {
|
||||
/**
|
||||
* @zh 意图类型(唯一标识符)
|
||||
* @en Intent type (unique identifier)
|
||||
*/
|
||||
readonly type: string;
|
||||
|
||||
/**
|
||||
* @zh 发起者玩家 ID(由 IntentCollector 自动填充)
|
||||
* @en Originator player ID (auto-filled by IntentCollector)
|
||||
*/
|
||||
playerId?: string;
|
||||
|
||||
/**
|
||||
* @zh 产生时的 tick(由 IntentCollector 自动填充)
|
||||
* @en Tick when generated (auto-filled by IntentCollector)
|
||||
*/
|
||||
tick?: number;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 意图键提取器 | Intent Key Extractor
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @zh 意图键提取器函数类型
|
||||
* @en Intent key extractor function type
|
||||
*
|
||||
* @zh 用于从意图中提取唯一键,防止同一对象重复操作
|
||||
* @en Used to extract unique key from intent, preventing duplicate operations on same object
|
||||
*/
|
||||
export type IntentKeyExtractor<T extends IIntent = IIntent> = (intent: T) => string;
|
||||
|
||||
/**
|
||||
* @zh 默认的意图键提取器(只使用 type)
|
||||
* @en Default intent key extractor (uses type only)
|
||||
*/
|
||||
export const defaultIntentKeyExtractor: IntentKeyExtractor = (intent) => intent.type;
|
||||
|
||||
// =============================================================================
|
||||
// 通用结果常量 | Common Result Constants
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @zh 操作成功
|
||||
* @en Operation successful
|
||||
*/
|
||||
export const OK = 0;
|
||||
|
||||
/**
|
||||
* @zh 通用错误
|
||||
* @en Generic error
|
||||
*/
|
||||
export const ERR_GENERIC = -1;
|
||||
|
||||
/**
|
||||
* @zh 不是所有者
|
||||
* @en Not the owner
|
||||
*/
|
||||
export const ERR_NOT_OWNER = -2;
|
||||
|
||||
/**
|
||||
* @zh 目标无效
|
||||
* @en Invalid target
|
||||
*/
|
||||
export const ERR_INVALID_TARGET = -3;
|
||||
|
||||
/**
|
||||
* @zh 不在范围内
|
||||
* @en Not in range
|
||||
*/
|
||||
export const ERR_NOT_IN_RANGE = -4;
|
||||
|
||||
/**
|
||||
* @zh 资源不足
|
||||
* @en Not enough resources
|
||||
*/
|
||||
export const ERR_NOT_ENOUGH_RESOURCES = -5;
|
||||
|
||||
/**
|
||||
* @zh 正忙
|
||||
* @en Currently busy
|
||||
*/
|
||||
export const ERR_BUSY = -6;
|
||||
|
||||
/**
|
||||
* @zh 参数无效
|
||||
* @en Invalid arguments
|
||||
*/
|
||||
export const ERR_INVALID_ARGS = -7;
|
||||
|
||||
// =============================================================================
|
||||
// 通用方向常量 | Common Direction Constants
|
||||
// =============================================================================
|
||||
|
||||
export const TOP = 1;
|
||||
export const TOP_RIGHT = 2;
|
||||
export const RIGHT = 3;
|
||||
export const BOTTOM_RIGHT = 4;
|
||||
export const BOTTOM = 5;
|
||||
export const BOTTOM_LEFT = 6;
|
||||
export const LEFT = 7;
|
||||
export const TOP_LEFT = 8;
|
||||
|
||||
/**
|
||||
* @zh 方向类型
|
||||
* @en Direction type
|
||||
*/
|
||||
export type Direction = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
||||
Reference in New Issue
Block a user