diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 00000000..59928c09
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,61 @@
+name: Deploy Documentation
+
+on:
+ push:
+ branches: [master]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: '20.x'
+ cache: 'npm'
+
+ - name: Setup Pages
+ uses: actions/configure-pages@v4
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build core package
+ run: npm run build:core
+
+ - name: Generate API documentation
+ run: npm run docs:api
+
+ - name: Build documentation
+ run: npm run docs:build
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: docs/.vitepress/dist
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 18327e16..20fffb0e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,8 @@ pnpm-lock.yaml
# 文档生成
docs/api/
docs/build/
+docs/.vitepress/cache/
+docs/.vitepress/dist/
# 备份文件
*.bak
diff --git a/README.md b/README.md
index 6b0ad2e4..a69c5624 100644
--- a/README.md
+++ b/README.md
@@ -1,180 +1,20 @@
# ECS Framework
-[](https://git.io/typing-svg)
-
[](https://github.com/esengine/ecs-framework/actions)
[](https://badge.fury.io/js/%40esengine%2Fecs-framework)
-[](https://www.typescriptlang.org/)
+[](https://www.typescriptlang.org/)
[](https://opensource.org/licenses/MIT)
[](https://github.com/esengine/ecs-framework/stargazers)
-TypeScript ECS (Entity-Component-System) 框架,专为游戏开发设计。
-
-## 项目特色
-
-
-
-[](https://store.cocos.com/app/detail/7823)
-[](https://jq.qq.com/?_wv=1027&k=29w1Nud6)
-
-
-
-## 架构原理
-
-ECS Framework 采用多World + 多Scene的现代化架构设计:
-
-```mermaid
-graph TD
- subgraph Main["🎮 ECS Framework - 多World・多Scene架构"]
- direction TB
-
- subgraph CoreLayer["⚙️ 核心层 (Core Foundation)"]
- direction LR
- Core["🔧 Core
📋 生命周期管理
⚙️ 配置系统
🔗 平台兼容"]
- Registry["📝 ComponentRegistry
🏷️ 类型注册
✨ 装饰器支持
🔒 类型安全"]
- Pool["🔢 IdentifierPool
🆔 实体ID分配
♻️ ID回收
📊 BigInt兼容"]
- PoolMgr["♻️ PoolManager
🎯 对象池
⚡ 内存优化
📈 性能提升"]
- EventBus["📡 EventBus
🔄 事件系统
⚡ 异步/同步
🎭 类型安全"]
- end
-
- subgraph WorldLayer["🌍 世界管理层 (World Management)"]
- direction TB
- WorldMgr["🗺️ WorldManager
🚀 多World调度
📊 资源管理
🔍 统计监控
🧹 自动清理"]
-
- subgraph WorldsContainer["多World容器"]
- direction LR
- World1["🌐 GameWorld
🎮 游戏逻辑
🌟 全局系统
🔄 跨Scene业务"]
- World2["🌐 UIWorld
🎨 界面管理
⚡ 独立更新
🔒 资源隔离"]
- end
-
- GlobalSys["🎭 Global Systems
🌐 NetworkSync
👥 PlayerMgmt
📡 跨Scene通信"]
- end
-
- subgraph SceneLayer["🎬 场景层 (Scene Management)"]
- direction LR
- Scene1["🎯 BattleScene
⚔️ 实体管理
🎪 系统调度
⚡ 高性能处理"]
- Scene2["🎯 MenuScene
🎨 界面逻辑
🔄 生命周期
💾 状态管理"]
- Scene3["🎯 UIScene
📦 组件存储
🔍 查询引擎
🎭 交互处理"]
- end
-
- subgraph ECLayer["🤖 实体组件层 (Entity-Component System)"]
- direction TB
-
- subgraph EntityMgmt["📦 实体管理 (Entity Management)"]
- direction LR
- EntityMgr["👥 EntityManager
📋 集合管理
🌳 层次结构
⚡ 高效操作"]
- Entities["🎭 Entities
👤 Player
👹 Enemy
💥 Bullet
🎯 轻量容器"]
- end
-
- subgraph ComponentStore["🧩 组件存储 (Component Storage)"]
- direction LR
- Storage["💾 ComponentStorage
📊 SoA模式
📚 AoS模式
⚡ 内存优化"]
- StorageMgr["🗄️ StorageManager
🏷️ 类型管理
🔄 脏标记
📈 性能监控"]
- Components["🎲 Components
📍 Position
🏃 Velocity
❤️ Health
📊 纯数据"]
- end
- end
-
- subgraph SystemLayer["⚡ 系统层 (System Processing)"]
- direction TB
-
- subgraph EntitySys["🔄 实体系统 (Entity Systems)"]
- direction LR
- EntitySystems["🎪 EntitySystems
🏃 MovementSystem
🎨 RenderSystem
🧠 AISystem
⚡ 业务逻辑"]
- Processors["📋 EntityProcessors
🎯 调度管理
📊 优先级
⚡ 批量处理"]
- end
- end
-
- subgraph QueryLayer["🔍 查询优化层 (Query & Optimization)"]
- direction LR
- Matcher["🎯 Matcher
✅ withAll
🔄 withAny
❌ withNone
🌊 流式API
💾 智能缓存"]
- QuerySys["🔎 QuerySystem
⚡ 实时查询
📦 批量优化
🔄 自动更新"]
- Archetype["🏗️ ArchetypeSystem
📊 组件分组
🎯 原型缓存
💻 BitSet优化"]
- end
-
- subgraph DebugLayer["📊 监控调试层 (Debug & Monitoring)"]
- direction LR
- Debug["🐛 DebugManager
🌐 WebSocket调试
🎮 Cocos Creator插件
📸 内存快照"]
- Perf["📈 PerformanceMonitor
📊 性能统计
⚠️ 阈值告警
📱 实时监控"]
- Logger["📋 Logger
📊 分级日志
🎨 彩色输出
🔧 自定义处理器"]
- end
- end
-
- %% 连接关系 - 使用更丰富的箭头样式
- Core -.->|初始化| WorldMgr
- Core -.->|注册| Registry
- Core -.->|分配| Pool
- Core -.->|管理| PoolMgr
- Core -.->|事件| EventBus
-
- WorldMgr ==>|调度| World1
- WorldMgr ==>|调度| World2
- World1 -.->|管理| GlobalSys
-
- World1 ==>|包含| Scene1
- World1 ==>|包含| Scene2
- World2 ==>|包含| Scene3
-
- Scene1 -->|使用| EntityMgr
- Scene2 -->|使用| EntityMgr
- Scene3 -->|使用| EntityMgr
-
- EntityMgr -->|管理| Entities
- Entities -->|附加| Components
-
- Scene1 -->|存储| Storage
- Scene2 -->|存储| Storage
- Scene3 -->|存储| Storage
- Storage -->|管理| StorageMgr
-
- Scene1 -->|调度| EntitySystems
- Scene2 -->|调度| EntitySystems
- Scene3 -->|调度| EntitySystems
- EntitySystems -->|处理| Processors
-
- EntitySystems -->|查询| Matcher
- Matcher -->|缓存| QuerySys
- QuerySys -->|优化| Archetype
-
- Core -.->|调试| Debug
- Core -.->|监控| Perf
- Core -.->|日志| Logger
-
- %% 样式定义 - 使用Mermaid支持的语法
- classDef coreStyle fill:#E3F2FD,stroke:#1976D2,stroke-width:3px,color:#0D47A1
- classDef worldStyle fill:#F3E5F5,stroke:#7B1FA2,stroke-width:3px,color:#4A148C
- classDef sceneStyle fill:#FFF3E0,stroke:#F57C00,stroke-width:3px,color:#E65100
- classDef entityStyle fill:#E8F5E8,stroke:#388E3C,stroke-width:3px,color:#1B5E20
- classDef systemStyle fill:#FCE4EC,stroke:#C2185B,stroke-width:3px,color:#880E4F
- classDef queryStyle fill:#E0F2F1,stroke:#00695C,stroke-width:3px,color:#004D40
- classDef debugStyle fill:#FFF8E1,stroke:#F9A825,stroke-width:3px,color:#FF8F00
-
- class Core,Registry,Pool,PoolMgr,EventBus coreStyle
- class WorldMgr,World1,World2,GlobalSys worldStyle
- class Scene1,Scene2,Scene3 sceneStyle
- class EntityMgr,Entities,Storage,StorageMgr,Components entityStyle
- class EntitySystems,Processors systemStyle
- class Matcher,QuerySys,Archetype queryStyle
- class Debug,Perf,Logger debugStyle
-```
-
-### 核心概念
-
-| 概念 | 职责 | 特点 |
-|------|------|------|
-| **Entity** | 游戏对象唯一标识 | 轻量级容器,无业务逻辑 |
-| **Component** | 纯数据结构 | 描述实体属性,支持SoA优化 |
-| **System** | 业务逻辑处理 | 操作组件数据,可热插拔 |
-| **Scene** | 实体和系统容器 | 独立的游戏场景 |
-| **World** | Scene和全局系统容器 | 支持跨Scene的全局逻辑 |
-| **WorldManager** | 多World管理 | 统一调度和资源管理 |
+一个高性能的 TypeScript ECS (Entity-Component-System) 框架,专为现代游戏开发而设计。
## 特性
-- **完整的 TypeScript 支持** - 强类型检查和代码提示
-- **高效查询系统** - 流式 API 和智能缓存
-- **性能优化技术** - SparseSet索引、Archetype 系统、脏标记
-- **事件系统** - 类型安全的事件处理
-- **调试工具** - 内置性能监控和 [Cocos Creator 可视化调试插件](https://store.cocos.com/app/detail/7823)
+- **高性能** - 针对大规模实体优化,支持SoA存储和批量处理
+- **类型安全** - 完整的TypeScript支持,编译时类型检查
+- **现代架构** - 支持多World、多Scene的分层架构设计
+- **开发友好** - 内置调试工具和性能监控
+- **跨平台** - 支持Cocos Creator、Laya引擎和Web平台
## 安装
@@ -184,271 +24,101 @@ npm install @esengine/ecs-framework
## 快速开始
-### 1. 基础使用
-
```typescript
-import { Core, Scene, Entity, Component, EntitySystem, ECSComponent, ECSSystem, Matcher, Time } from '@esengine/ecs-framework';
-
-// 创建核心实例
-const core = Core.create({ debug: true });
-const scene = new Scene();
-Core.setScene(scene);
+import { Core, Scene, Component, EntitySystem, ECSComponent, ECSSystem, Matcher, Time } from '@esengine/ecs-framework';
// 定义组件
-@ECSComponent('PositionComponent')
-class PositionComponent extends Component {
- public x: number = 0;
- public y: number = 0;
-
- constructor(x: number = 0, y: number = 0) {
+@ECSComponent('Position')
+class Position extends Component {
+ constructor(public x = 0, public y = 0) {
super();
- this.x = x;
- this.y = y;
}
}
-@ECSComponent('VelocityComponent')
-class VelocityComponent extends Component {
- public x: number = 0;
- public y: number = 0;
-
- constructor(x: number = 0, y: number = 0) {
+@ECSComponent('Velocity')
+class Velocity extends Component {
+ constructor(public dx = 0, public dy = 0) {
super();
- this.x = x;
- this.y = y;
}
}
-// 创建实体
-const entity = scene.createEntity("Player");
-entity.addComponent(new PositionComponent(100, 100));
-entity.addComponent(new VelocityComponent(5, 0));
-
// 创建系统
-@ECSSystem('MovementSystem')
+@ECSSystem('Movement')
class MovementSystem extends EntitySystem {
constructor() {
- super(Matcher.all(PositionComponent, VelocityComponent));
+ super(Matcher.all(Position, Velocity));
}
-
- protected override process(entities: Entity[]) {
+
+ protected process(entities: readonly Entity[]): void {
for (const entity of entities) {
- const position = entity.getComponent(PositionComponent)!;
- const velocity = entity.getComponent(VelocityComponent)!;
-
- position.x += velocity.x * Time.deltaTime;
- position.y += velocity.y * Time.deltaTime;
+ const position = entity.getComponent(Position)!;
+ const velocity = entity.getComponent(Velocity)!;
+
+ position.x += velocity.dx * Time.deltaTime;
+ position.y += velocity.dy * Time.deltaTime;
}
}
}
-scene.addEntityProcessor(new MovementSystem());
+// 创建场景并启动
+class GameScene extends Scene {
+ protected initialize(): void {
+ this.addSystem(new MovementSystem());
-// 游戏循环
-Core.update(deltaTime);
-```
-
-### 2. 类型装饰器
-
-在代码压缩混淆后,类名会改变导致框架无法识别组件类型。使用装饰器确保稳定性:
-
-```typescript
-import { ECSComponent, ECSSystem } from '@esengine/ecs-framework';
-
-// 组件装饰器
-@ECSComponent('PositionComponent')
-class PositionComponent extends Component {
- public x: number = 0;
- public y: number = 0;
-}
-
-@ECSComponent('VelocityComponent')
-class VelocityComponent extends Component {
- public x: number = 0;
- public y: number = 0;
-}
-
-// 系统装饰器
-@ECSSystem('MovementSystem')
-class MovementSystem extends EntitySystem {
- constructor() {
- super(Matcher.all(PositionComponent, VelocityComponent));
- }
-
- protected override process(entities: Entity[]) {
- // 处理逻辑
- }
-}
-```
-
-## 高级特性
-
-### 查询系统
-
-```typescript
-import { Matcher, ECSSystem } from '@esengine/ecs-framework';
-
-// 使用Matcher和EntitySystem进行高效查询
-@ECSSystem('QuerySystem')
-class QuerySystem extends EntitySystem {
- constructor() {
- super(Matcher.all(PositionComponent, VelocityComponent).none(HealthComponent));
- }
-
- protected override process(entities: Entity[]) {
- // 处理匹配的实体
- console.log(`Found ${entities.length} entities`);
+ const player = this.createEntity("Player");
+ player.addComponent(new Position(100, 100));
+ player.addComponent(new Velocity(50, 0));
}
}
-// 更复杂的查询条件
-@ECSSystem('CombatSystem')
-class CombatSystem extends EntitySystem {
- constructor() {
- super(
- Matcher
- .all(PositionComponent, HealthComponent) // 必须有位置和血量
- .any(WeaponComponent, MagicComponent) // 有武器或魔法
- .none(DeadComponent) // 不能是死亡状态
- );
- }
-
- protected override process(entities: Entity[]) {
- // 处理战斗逻辑
- }
-}
-```
+// 启动游戏
+Core.create();
+Core.setScene(new GameScene());
-### 事件系统
-
-```typescript
-import { EventHandler, ECSEventType, IEntityEventData } from '@esengine/ecs-framework';
-
-class GameSystem {
- @EventHandler(ECSEventType.ENTITY_DESTROYED)
- onEntityDestroyed(data: IEntityEventData) {
- console.log('实体销毁:', data.entityName, '实体ID:', data.entityId);
- }
-
- @EventHandler(ECSEventType.ENTITY_CREATED)
- onEntityCreated(data: IEntityEventData) {
- console.log('实体创建:', data.entityName, '标签:', data.entityTag);
- }
-}
-```
-
-### SoA 存储优化
-
-针对大规模实体处理的内存布局优化:
-
-| 存储方式 | 内存布局 | 适用场景 | 性能特点 |
-|----------|----------|----------|----------|
-| **AoS** (Array of Structures) | `[{x,y,z}, {x,y,z}, {x,y,z}]` | 通用场景 | 访问灵活,缓存效率一般 |
-| **SoA** (Structure of Arrays) | `{x:[1,2,3], y:[4,5,6], z:[7,8,9]}` | 批量处理 | SIMD优化,缓存友好 |
-
-**SoA 优势:**
-- 🚀 提升 2-4x 批量处理性能
-- 💾 更好的CPU缓存利用率
-- 🔧 支持SIMD向量化操作
-- ⚡ 减少内存访问跳跃
-
-用法示例:
-
-```typescript
-import { EnableSoA, Float32, Int32 } from '@esengine/ecs-framework';
-
-@EnableSoA
-class OptimizedTransformComponent extends Component {
- @Float32 public x: number = 0;
- @Float32 public y: number = 0;
- @Float32 public rotation: number = 0;
-}
-```
-
-**性能优势**:
-- **缓存友好** - 连续内存访问,缓存命中率提升85%
-- **批量处理** - 同类型数据处理速度提升2-3倍
-- **热切换** - 开发期AoS便于调试,生产期SoA提升性能
-- **自动优化** - `@EnableSoA`装饰器自动转换存储结构
-
-## 平台集成
-
-### Cocos Creator
-
-```typescript
-update(deltaTime: number) {
+// 游戏循环中更新
+function gameLoop(deltaTime: number) {
Core.update(deltaTime);
}
```
-**专用调试插件**:
-- [ECS 可视化调试插件](https://store.cocos.com/app/detail/7823) - 提供完整的可视化调试界面
-- 实体查看器、组件编辑器、系统监控
-- 性能分析和实时数据监控
+## 核心特性
-### Laya 引擎
-```typescript
-Laya.timer.frameLoop(1, this, () => {
- Core.update(Laya.timer.delta / 1000);
-});
-```
+- **实体查询** - 使用 Matcher API 进行高效的实体过滤
+- **事件系统** - 类型安全的事件发布/订阅机制
+- **性能优化** - SoA 存储优化,支持大规模实体处理
+- **多场景** - 支持 World/Scene 分层架构
+- **时间管理** - 内置定时器和时间控制系统
-### 原生浏览器
-```typescript
-function gameLoop(currentTime: number) {
- const deltaTime = (currentTime - lastTime) / 1000;
- Core.update(deltaTime);
- requestAnimationFrame(gameLoop);
-}
-```
+## 平台支持
+
+支持主流游戏引擎和 Web 平台:
+
+- **Cocos Creator** - 内置引擎集成支持,提供[专用调试插件](https://store.cocos.com/app/detail/7823)
+- **Laya 引擎** - 完整的生命周期管理
+- **原生 Web** - 浏览器环境直接运行
+- **小游戏平台** - 微信、支付宝等小游戏
-## API 参考
+## 示例项目
-### 核心类
-
-| 类 | 描述 |
-|---|---|
-| `Core` | 框架核心管理 |
-| `Scene` | 场景容器 |
-| `Entity` | 实体对象 |
-| `Component` | 组件基类 |
-| `EntitySystem` | 系统基类 |
-| `EntityManager` | 实体管理器 |
-
-### 查询 API
-
-```typescript
-// Matcher API - 推荐方式,高效且类型安全
-Matcher.all(...components) // 包含所有组件
-Matcher.any(...components) // 包含任意组件
-Matcher.none(...components) // 不包含组件
-
-// 组合查询示例
-Matcher
- .all(PositionComponent, VelocityComponent) // 必须有这些组件
- .any(PlayerComponent, AIComponent) // 其中之一
- .none(DeadComponent, DisabledComponent); // 排除这些
-```
+- [割草机演示](https://github.com/esengine/lawn-mower-demo) - 完整的游戏示例
## 文档
-- [快速入门](docs/getting-started.md) - 详细教程和平台集成
-- [技术概念](docs/concepts-explained.md) - ECS 架构和框架特性
-- [组件设计](docs/component-design-guide.md) - 组件设计最佳实践
-- [性能优化](docs/performance-optimization.md) - 性能优化技术
-- [API 参考](docs/core-concepts.md) - 完整 API 文档
+- [快速入门](https://esengine.github.io/ecs-framework/guide/getting-started.html) - 详细教程和平台集成
+- [完整指南](https://esengine.github.io/ecs-framework/guide/) - ECS 概念和使用指南
+- [API 参考](https://esengine.github.io/ecs-framework/api/) - 完整 API 文档
-## 扩展库
+## 生态系统
- [路径寻找](https://github.com/esengine/ecs-astar) - A*、BFS、Dijkstra 算法
- [AI 系统](https://github.com/esengine/BehaviourTree-ai) - 行为树、效用 AI
-## 社区
+## 社区与支持
-- QQ 群:[ecs游戏框架交流](https://jq.qq.com/?_wv=1027&k=29w1Nud6)
-- GitHub:[提交 Issue](https://github.com/esengine/ecs-framework/issues)
+- [问题反馈](https://github.com/esengine/ecs-framework/issues) - Bug 报告和功能建议
+- [QQ 交流群](https://jq.qq.com/?_wv=1027&k=29w1Nud6) - ecs游戏框架交流
## 许可证
-[MIT](LICENSE)
\ No newline at end of file
+[MIT](LICENSE) © 2025 ECS Framework
\ No newline at end of file
diff --git a/docs/.vitepress/config.mjs b/docs/.vitepress/config.mjs
new file mode 100644
index 00000000..0a1d816f
--- /dev/null
+++ b/docs/.vitepress/config.mjs
@@ -0,0 +1,167 @@
+import { defineConfig } from 'vitepress'
+import Icons from 'unplugin-icons/vite'
+import { readFileSync } from 'fs'
+import { join, dirname } from 'path'
+import { fileURLToPath } from 'url'
+
+const __dirname = dirname(fileURLToPath(import.meta.url))
+const corePackageJson = JSON.parse(
+ readFileSync(join(__dirname, '../../packages/core/package.json'), 'utf-8')
+)
+
+export default defineConfig({
+ vite: {
+ plugins: [
+ Icons({
+ compiler: 'vue3',
+ autoInstall: true
+ })
+ ]
+ },
+ title: 'ECS Framework',
+ description: '高性能TypeScript ECS框架 - 为游戏开发而生',
+ lang: 'zh-CN',
+
+ themeConfig: {
+ nav: [
+ { text: '首页', link: '/' },
+ { text: '快速开始', link: '/guide/getting-started' },
+ { text: '指南', link: '/guide/' },
+ { text: 'API', link: '/api/README' },
+ { text: '示例', link: 'https://github.com/esengine/lawn-mower-demo' },
+ {
+ text: `v${corePackageJson.version}`,
+ link: 'https://github.com/esengine/ecs-framework/releases'
+ }
+ ],
+
+ sidebar: {
+ '/guide/': [
+ {
+ text: '开始使用',
+ items: [
+ { text: '快速开始', link: '/guide/getting-started' },
+ { text: '指南概览', link: '/guide/' }
+ ]
+ },
+ {
+ text: '核心概念',
+ collapsed: false,
+ items: [
+ { text: '实体类 (Entity)', link: '/guide/entity' },
+ { text: '组件系统 (Component)', link: '/guide/component' },
+ { text: '系统架构 (System)', link: '/guide/system' },
+ { text: '场景管理 (Scene)', link: '/guide/scene' },
+ { text: '事件系统 (Event)', link: '/guide/event-system' },
+ { text: '时间和定时器 (Time)', link: '/guide/time-and-timers' },
+ { text: '日志系统 (Logger)', link: '/guide/logging' }
+ ]
+ }
+ ],
+ '/api/': [
+ {
+ text: 'API 参考',
+ items: [
+ { text: '概述', link: '/api/README' },
+ {
+ text: '核心类',
+ collapsed: false,
+ items: [
+ { text: 'Core', link: '/api/classes/Core' },
+ { text: 'Scene', link: '/api/classes/Scene' },
+ { text: 'World', link: '/api/classes/World' },
+ { text: 'Entity', link: '/api/classes/Entity' },
+ { text: 'Component', link: '/api/classes/Component' },
+ { text: 'EntitySystem', link: '/api/classes/EntitySystem' }
+ ]
+ },
+ {
+ text: '系统类',
+ collapsed: true,
+ items: [
+ { text: 'PassiveSystem', link: '/api/classes/PassiveSystem' },
+ { text: 'ProcessingSystem', link: '/api/classes/ProcessingSystem' },
+ { text: 'IntervalSystem', link: '/api/classes/IntervalSystem' }
+ ]
+ },
+ {
+ text: '工具类',
+ collapsed: true,
+ items: [
+ { text: 'Matcher', link: '/api/classes/Matcher' },
+ { text: 'Time', link: '/api/classes/Time' },
+ { text: 'PerformanceMonitor', link: '/api/classes/PerformanceMonitor' },
+ { text: 'DebugManager', link: '/api/classes/DebugManager' }
+ ]
+ },
+ {
+ text: '接口',
+ collapsed: true,
+ items: [
+ { text: 'IScene', link: '/api/interfaces/IScene' },
+ { text: 'IComponent', link: '/api/interfaces/IComponent' },
+ { text: 'ISystemBase', link: '/api/interfaces/ISystemBase' },
+ { text: 'ICoreConfig', link: '/api/interfaces/ICoreConfig' }
+ ]
+ },
+ {
+ text: '装饰器',
+ collapsed: true,
+ items: [
+ { text: '@ECSComponent', link: '/api/functions/ECSComponent' },
+ { text: '@ECSSystem', link: '/api/functions/ECSSystem' }
+ ]
+ },
+ {
+ text: '枚举',
+ collapsed: true,
+ items: [
+ { text: 'ECSEventType', link: '/api/enumerations/ECSEventType' },
+ { text: 'LogLevel', link: '/api/enumerations/LogLevel' }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+
+ socialLinks: [
+ { icon: 'github', link: 'https://github.com/esengine/ecs-framework' }
+ ],
+
+ footer: {
+ message: 'Released under the MIT License.',
+ copyright: 'Copyright © 2025 ECS Framework'
+ },
+
+ editLink: {
+ pattern: 'https://github.com/esengine/ecs-framework/edit/master/docs/:path',
+ text: '在 GitHub 上编辑此页'
+ },
+
+ search: {
+ provider: 'local'
+ },
+
+ outline: {
+ level: [2, 3],
+ label: '目录'
+ }
+ },
+
+ head: [
+ ['meta', { name: 'theme-color', content: '#646cff' }],
+ ['link', { rel: 'icon', href: '/favicon.ico' }]
+ ],
+
+ base: '/',
+ cleanUrls: true,
+
+ markdown: {
+ lineNumbers: true,
+ theme: {
+ light: 'github-light',
+ dark: 'github-dark'
+ }
+ }
+})
\ No newline at end of file
diff --git a/docs/beginner-tutorials.md b/docs/beginner-tutorials.md
deleted file mode 100644
index 96d6343c..00000000
--- a/docs/beginner-tutorials.md
+++ /dev/null
@@ -1,187 +0,0 @@
-# 新手教程完整指南
-
-欢迎使用ECS框架!本指南为新手提供了完整的学习路径,从基础概念到高级应用,帮你快速掌握ECS框架开发游戏。
-
-## 学习路径
-
-### 第一阶段:基础入门(必读)
-
-#### 1. [快速开始](getting-started.md)
-- **5分钟入门** - 创建你的第一个ECS游戏
-- **环境搭建** - 安装和配置框架
-- **第一个游戏** - 完整的示例游戏
-- **基础API** - 核心功能介绍
-
-#### 2. [核心概念](core-concepts.md)
-- **ECS架构** - 实体、组件、系统的关系
-- **API参考** - 核心类和方法
-- **最佳实践** - 代码规范和设计模式
-- **查询系统** - 如何高效查找实体
-
-#### 3. [概念详解](concepts-explained.md) **新手必读**
-- **通俗解释** - 用简单语言解释复杂概念
-- **性能优化技术** - 组件索引、Archetype、脏标记
-- **索引选择指南** - 何时使用哈希索引vs位图索引
-- **应用场景** - 不同游戏类型的选择建议
-
-### 第二阶段:核心功能掌握
-
-#### 4. [实体管理指南](entity-guide.md)
-- **实体基础** - 什么是实体,如何创建和使用
-- **标签系统** - 实体分类和查找
-- **生命周期** - 实体的创建、更新、销毁
-- **简单示例** - 玩家、敌人、道具实体
-
-#### 5. [组件设计最佳实践](component-design-guide.md) **设计必读**
-- **组件设计原则** - 单一职责、数据为主
-- **组件类型** - 数据组件、标记组件、行为组件
-- **组件通信** - 如何让组件协同工作
-- **性能优化** - 对象池和数据紧凑性
-- **测试和调试** - 如何测试你的组件
-
-#### 6. [系统详解指南](system-guide.md) **逻辑必读**
-- **四种系统类型** - EntitySystem、ProcessingSystem、IntervalSystem、PassiveSystem
-- **使用场景** - 什么时候用哪种系统
-- **执行顺序** - 系统间的依赖关系
-- **系统通信** - 事件驱动的松耦合设计
-- **性能优化** - 批量处理和频率控制
-
-### 第三阶段:高级功能应用
-
-#### 7. [场景管理指南](scene-management-guide.md)
-- **场景概念** - 什么是场景,如何组织游戏世界
-- **场景切换** - 菜单、游戏、暂停场景的切换
-- **数据传递** - 场景间如何传递数据
-- **实际应用** - 完整的游戏场景设计
-- **性能优化** - 场景级别的性能监控
-
-#### 8. [定时器系统指南](timer-guide.md)
-- **定时器基础** - 延迟执行、重复执行
-- **定时器链** - 顺序执行多个任务
-- **条件定时器** - 等待特定条件满足
-- **可暂停定时器** - 游戏暂停功能
-- **游戏应用** - Buff系统、技能冷却、关卡限时
-
-#### 9. [查询系统使用](query-system-usage.md)
-- **基础查询** - 按组件查找实体
-- **复杂查询** - 组合条件和排除条件
-- **性能监控** - 查询性能统计
-- **优化技巧** - 提高查询效率
-
-#### 10. [事件系统示例](event-system-example.md)
-- **事件基础** - 发送和监听事件
-- **游戏事件** - 玩家输入、碰撞、分数等
-- **系统解耦** - 用事件实现系统间通信
-- **事件统计** - 监控事件系统性能
-
-### 第四阶段:实战应用
-
-#### 11. [实体管理器高级功能](entity-manager-example.md)
-- 🏭 **批量操作** - 高效创建和管理大量实体
-- **高级查询** - EntityQueryBuilder的使用
-- **性能监控** - 实体管理性能统计
-- **实际案例** - 弹幕游戏、RTS游戏的实体管理
-
-#### 12. [应用案例集合](use-cases.md)
-- **不同游戏类型** - 休闲游戏、动作游戏、策略游戏
-- **具体实现** - 完整的代码示例
-- **性能分析** - 各种应用的性能特点
-- **设计思路** - 如何选择合适的架构
-
-### 第五阶段:性能优化
-
-#### 13. [性能基准测试](performance.md)
-- **基准数据** - 框架性能表现
-- **对比分析** - 与其他框架的比较
-- **优化建议** - 针对不同规模的优化策略
-- **性能检查清单** - 确保最佳性能的要点
-
-#### 14. [性能优化技术](performance-optimization.md)
-- **核心优化** - 组件索引、Archetype、脏标记
-- **内存优化** - 对象池、数据紧凑性
-- **批量处理** - 减少单次操作开销
-- **监控工具** - 性能分析和调试
-
-## 推荐学习顺序
-
-### 适合完全新手(第一次接触ECS)
-
-```
-1. 快速开始 → 2. 概念详解 → 3. 核心概念 → 4. 实体管理指南
-→ 5. 组件设计指南 → 6. 系统详解指南 → 7. 应用案例
-```
-
-### 适合有游戏开发经验的开发者
-
-```
-1. 快速开始 → 2. 核心概念 → 3. 组件设计指南 → 4. 系统详解指南
-→ 5. 场景管理指南 → 6. 性能优化技术
-```
-
-### 适合追求高性能的开发者
-
-```
-1. 快速开始 → 2. 概念详解(重点看性能优化) → 3. 性能基准测试
-→ 4. 性能优化技术 → 5. 实体管理器高级功能
-```
-
-## 常见学习问题
-
-### Q: 我应该从哪里开始?
-
-A: 建议先阅读[快速开始](getting-started.md),然后根据你的背景选择学习路径:
-- **新手**:重点看概念详解
-- **有经验**:直接看核心概念和设计指南
-- **追求性能**:重点看性能相关文档
-
-### Q: ECS和传统OOP有什么区别?
-
-A: 详见[概念详解](concepts-explained.md)的"ECS vs 传统架构"部分,用简单例子解释两者差异。
-
-### Q: 如何选择组件索引类型?
-
-A: [概念详解](concepts-explained.md)有详细的索引选择指南,包括决策流程图和具体示例。
-
-### Q: 系统的执行顺序重要吗?
-
-A: 非常重要详细解释了系统顺序的重要性和设置方法。
-
-### Q: 如何调试性能问题?
-
-A:
-1. 使用[性能基准测试](performance.md)中的工具
-2. 参考[性能优化技术](performance-optimization.md)的监控方法
-3. 查看[实体管理器示例](entity-manager-example.md)的统计功能
-
-## 📖 扩展阅读
-
-### 设计模式和架构
-- [组件设计最佳实践](component-design-guide.md) - 如何设计可维护的组件
-- [系统详解指南](system-guide.md) - 系统间的协作模式
-
-### 性能和优化
-- [概念详解](concepts-explained.md) - 性能优化技术原理
-- [性能优化技术](performance-optimization.md) - 具体优化实现
-
-### 实际应用
-- [应用案例集合](use-cases.md) - 不同类型游戏的实现
-- [场景管理指南](scene-management-guide.md) - 复杂游戏的场景组织
-
-## 学习建议
-
-### 实践为主
-- **边学边做** - 每学一个概念都尝试写代码实现
-- **从小做起** - 先做简单的游戏,再逐步增加复杂度
-- **多做实验** - 尝试不同的设计方案,体会优劣
-
-### 理解原理
-- **思考为什么** - 不只学怎么做,更要理解为什么这样做
-- **关注性能** - 了解各种操作的性能影响
-- **深入源码** - 有疑问时查看框架源码
-
-### 循序渐进
-- **按顺序学习** - 先掌握基础,再学高级功能
-- **专注重点** - 每次只专注一个主题,不要贪多
-- **反复练习** - 重要概念要多练习才能熟练
-
-开始你的ECS学习之旅吧!
\ No newline at end of file
diff --git a/docs/component-design-guide.md b/docs/component-design-guide.md
deleted file mode 100644
index 9d4d2166..00000000
--- a/docs/component-design-guide.md
+++ /dev/null
@@ -1,704 +0,0 @@
-# 组件设计最佳实践指南
-
-组件是ECS架构的核心,设计良好的组件是构建高质量游戏的基础。本指南将教你如何设计出清晰、高效、可维护的组件。
-
-## 组件设计原则
-
-### 1. 数据为主,逻辑为辅
-
-**核心理念:** 组件主要存储数据,复杂逻辑放在系统中处理。
-
-```typescript
-// 好的设计:主要是数据
-class HealthComponent extends Component {
- public maxHealth: number;
- public currentHealth: number;
- public regenRate: number = 0;
- public lastDamageTime: number = 0;
-
- constructor(maxHealth: number = 100) {
- super();
- this.maxHealth = maxHealth;
- this.currentHealth = maxHealth;
- }
-
- // 简单的辅助方法是可以的
- isDead(): boolean {
- return this.currentHealth <= 0;
- }
-
- getHealthPercentage(): number {
- return this.currentHealth / this.maxHealth;
- }
-}
-
-// ❌ 不好的设计:包含太多逻辑
-class BadHealthComponent extends Component {
- public maxHealth: number;
- public currentHealth: number;
-
- takeDamage(damage: number) {
- this.currentHealth -= damage;
-
- // 这些逻辑应该在系统中处理
- if (this.currentHealth <= 0) {
- this.entity.destroy(); // 销毁逻辑
- this.playDeathSound(); // 音效逻辑
- this.createDeathEffect(); // 特效逻辑
- this.updatePlayerScore(100); // 分数逻辑
- }
- }
-}
-```
-
-### 2. 单一职责原则
-
-每个组件只负责一个方面的数据。
-
-```typescript
-// 好的设计:单一职责
-class PositionComponent extends Component {
- public x: number = 0;
- public y: number = 0;
-
- constructor(x: number = 0, y: number = 0) {
- super();
- this.x = x;
- this.y = y;
- }
-}
-
-class VelocityComponent extends Component {
- public x: number = 0;
- public y: number = 0;
- public maxSpeed: number = 100;
-
- constructor(x: number = 0, y: number = 0) {
- super();
- this.x = x;
- this.y = y;
- }
-}
-
-class RotationComponent extends Component {
- public angle: number = 0;
- public angularVelocity: number = 0;
-
- constructor(angle: number = 0) {
- super();
- this.angle = angle;
- }
-}
-
-// ❌ 不好的设计:职责混乱
-class TransformComponent extends Component {
- public x: number = 0;
- public y: number = 0;
- public velocityX: number = 0;
- public velocityY: number = 0;
- public angle: number = 0;
- public scale: number = 1;
- public health: number = 100; // 和变换无关
- public ammo: number = 30; // 和变换无关
-}
-```
-
-### 3. 组合优于继承
-
-使用多个小组件组合,而不是大而全的组件继承。
-
-```typescript
-// 好的设计:组合方式
-class Player {
- constructor(scene: Scene) {
- const player = scene.createEntity("Player");
-
- // 通过组合不同组件实现功能
- player.addComponent(new PositionComponent(100, 100));
- player.addComponent(new VelocityComponent());
- player.addComponent(new HealthComponent(100));
- player.addComponent(new PlayerInputComponent());
- player.addComponent(new WeaponComponent());
- player.addComponent(new InventoryComponent());
-
- return player;
- }
-}
-
-// 创建不同类型的实体很容易
-class Enemy {
- constructor(scene: Scene) {
- const enemy = scene.createEntity("Enemy");
-
- // 复用相同的组件,但组合不同
- enemy.addComponent(new PositionComponent(200, 200));
- enemy.addComponent(new VelocityComponent());
- enemy.addComponent(new HealthComponent(50));
- enemy.addComponent(new AIComponent()); // 不同:AI而不是玩家输入
- enemy.addComponent(new WeaponComponent()); // 相同:都有武器
- // 没有库存组件
-
- return enemy;
- }
-}
-
-// ❌ 不好的设计:继承方式
-class GameObject {
- public x: number;
- public y: number;
- public health: number;
- // ... 很多属性
-}
-
-class PlayerGameObject extends GameObject {
- public input: InputData;
- public inventory: Item[];
- // 强制继承了不需要的属性
-}
-
-class EnemyGameObject extends GameObject {
- public ai: AIData;
- // 继承了不需要的库存等属性
-}
-```
-
-## 常见组件类型和设计
-
-### 1. 数据组件(Data Components)
-
-纯数据存储,没有或很少有方法。
-
-```typescript
-// 位置信息
-class PositionComponent extends Component {
- public x: number;
- public y: number;
-
- constructor(x: number = 0, y: number = 0) {
- super();
- this.x = x;
- this.y = y;
- }
-
- // 简单的辅助方法
- distanceTo(other: PositionComponent): number {
- const dx = this.x - other.x;
- const dy = this.y - other.y;
- return Math.sqrt(dx * dx + dy * dy);
- }
-
- set(x: number, y: number) {
- this.x = x;
- this.y = y;
- }
-}
-
-// 统计信息
-class StatsComponent extends Component {
- public strength: number = 10;
- public agility: number = 10;
- public intelligence: number = 10;
- public vitality: number = 10;
-
- // 计算派生属性
- getMaxHealth(): number {
- return this.vitality * 10;
- }
-
- getDamage(): number {
- return this.strength * 2;
- }
-
- getMoveSpeed(): number {
- return this.agility * 5;
- }
-}
-
-// 渲染信息
-class SpriteComponent extends Component {
- public textureName: string;
- public width: number;
- public height: number;
- public tint: number = 0xFFFFFF;
- public alpha: number = 1.0;
- public visible: boolean = true;
-
- constructor(textureName: string, width: number = 0, height: number = 0) {
- super();
- this.textureName = textureName;
- this.width = width;
- this.height = height;
- }
-}
-```
-
-### 2. 标记组件(Tag Components)
-
-用于标识实体状态或类型的空组件。
-
-```typescript
-// 标记组件通常不包含数据
-class PlayerComponent extends Component {
- // 空组件,仅用于标记这是玩家实体
-}
-
-class EnemyComponent extends Component {
- // 空组件,仅用于标记这是敌人实体
-}
-
-class DeadComponent extends Component {
- // 标记实体已死亡
- public deathTime: number;
-
- constructor() {
- super();
- this.deathTime = Time.totalTime;
- }
-}
-
-class InvincibleComponent extends Component {
- // 标记实体无敌状态
- public duration: number;
-
- constructor(duration: number = 2.0) {
- super();
- this.duration = duration;
- }
-}
-
-// 使用标记组件进行查询
-class PlayerSystem extends EntitySystem {
- constructor() {
- super(Matcher.all(PlayerComponent));
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是玩家实体
- for (const entity of entities) {
- // 处理玩家逻辑
- }
- }
-}
-
-class EnemySystem extends EntitySystem {
- constructor() {
- super(Matcher.all(EnemyComponent));
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是敌人实体
- for (const entity of entities) {
- // 处理敌人逻辑
- }
- }
-}
-```
-
-### 3. 行为组件(Behavior Components)
-
-包含简单行为逻辑的组件。
-
-```typescript
-class WeaponComponent extends Component {
- public damage: number;
- public fireRate: number;
- public ammo: number;
- public maxAmmo: number;
- public lastFireTime: number = 0;
-
- constructor(damage: number = 10, fireRate: number = 0.5) {
- super();
- this.damage = damage;
- this.fireRate = fireRate;
- this.maxAmmo = 30;
- this.ammo = this.maxAmmo;
- }
-
- canFire(): boolean {
- return this.ammo > 0 &&
- Time.totalTime - this.lastFireTime >= this.fireRate;
- }
-
- fire(): boolean {
- if (this.canFire()) {
- this.ammo--;
- this.lastFireTime = Time.totalTime;
- return true;
- }
- return false;
- }
-
- reload() {
- this.ammo = this.maxAmmo;
- }
-
- getAmmoPercentage(): number {
- return this.ammo / this.maxAmmo;
- }
-}
-
-class InventoryComponent extends Component {
- private items: Map = new Map();
- public maxCapacity: number = 20;
-
- addItem(itemType: string, quantity: number = 1): boolean {
- if (this.getTotalItems() + quantity > this.maxCapacity) {
- return false;
- }
-
- const current = this.items.get(itemType) || 0;
- this.items.set(itemType, current + quantity);
- return true;
- }
-
- removeItem(itemType: string, quantity: number = 1): boolean {
- const current = this.items.get(itemType) || 0;
- if (current < quantity) {
- return false;
- }
-
- const newAmount = current - quantity;
- if (newAmount === 0) {
- this.items.delete(itemType);
- } else {
- this.items.set(itemType, newAmount);
- }
- return true;
- }
-
- hasItem(itemType: string, quantity: number = 1): boolean {
- const current = this.items.get(itemType) || 0;
- return current >= quantity;
- }
-
- getTotalItems(): number {
- let total = 0;
- this.items.forEach(quantity => total += quantity);
- return total;
- }
-
- getItems(): Map {
- return new Map(this.items); // 返回副本
- }
-}
-```
-
-## 组件通信和依赖
-
-### 1. 组件间通信
-
-组件间不应直接通信,通过系统或事件系统进行通信。
-
-```typescript
-// 好的设计:通过事件通信
-class HealthComponent extends Component {
- public currentHealth: number;
- public maxHealth: number;
-
- takeDamage(damage: number) {
- this.currentHealth -= damage;
-
- // 发送事件,让其他系统响应
- // 注意:需要在实际使用中获取EntityManager实例
- // 示例:entityManager.eventBus.emit('health:damaged', {...});
-
- if (this.currentHealth <= 0) {
- // 示例:entityManager.eventBus.emit('health:died', {...});
- console.log('实体死亡');
- }
- }
-}
-
-// 其他组件响应事件
-class AnimationComponent extends Component {
- onAddedToEntity() {
- super.onAddedToEntity();
-
- // 监听受伤事件(需要在实际使用中获取EntityManager实例)
- // 示例:entityManager.eventBus.on('health:damaged', this.onDamaged, { context: this });
- }
-
- onRemovedFromEntity() {
- // 事件监听会在组件移除时自动清理
- // 如需手动清理,保存listenerId并调用eventBus.off()
- super.onRemovedFromEntity();
- }
-
- private onDamaged(data: any) {
- if (data.entity === this.entity) {
- this.playHurtAnimation();
- }
- }
-}
-
-// ❌ 不好的设计:直接依赖其他组件
-class BadHealthComponent extends Component {
- takeDamage(damage: number) {
- this.currentHealth -= damage;
-
- // 直接操作其他组件
- const animation = this.entity.getComponent(AnimationComponent);
- if (animation) {
- animation.playHurtAnimation(); // 紧耦合
- }
-
- const sound = this.entity.getComponent(SoundComponent);
- if (sound) {
- sound.playHurtSound(); // 紧耦合
- }
- }
-}
-```
-
-### 2. 可选依赖
-
-有时组件需要其他组件配合工作,但应该优雅处理缺失的情况。
-
-```typescript
-class MovementComponent extends Component {
- public speed: number = 100;
-
- update() {
- // 可选依赖:输入组件
- const input = this.entity.getComponent(InputComponent);
- const velocity = this.entity.getComponent(VelocityComponent);
-
- if (input && velocity) {
- // 根据输入设置速度
- velocity.x = input.horizontal * this.speed;
- velocity.y = input.vertical * this.speed;
- }
-
- // 可选依赖:AI组件
- const ai = this.entity.getComponent(AIComponent);
- if (ai && velocity && !input) {
- // AI控制移动(如果没有输入)
- velocity.x = ai.moveDirection.x * this.speed;
- velocity.y = ai.moveDirection.y * this.speed;
- }
- }
-}
-```
-
-## 组件性能优化
-
-### 1. 对象池优化
-
-对于频繁创建/销毁的组件,使用对象池。
-
-```typescript
-class PooledBulletComponent extends Component {
- public damage: number = 10;
- public speed: number = 200;
- public direction: { x: number; y: number } = { x: 0, y: 0 };
- public lifetime: number = 5.0;
- private currentLifetime: number = 0;
-
- // 重置组件状态,用于对象池
- reset() {
- this.damage = 10;
- this.speed = 200;
- this.direction.set(0, 0);
- this.lifetime = 5.0;
- this.currentLifetime = 0;
- }
-
- // 配置子弹
- configure(damage: number, speed: number, direction: { x: number; y: number }) {
- this.damage = damage;
- this.speed = speed;
- this.direction = direction.copy();
- }
-
- update() {
- this.currentLifetime += Time.deltaTime;
-
- if (this.currentLifetime >= this.lifetime) {
- // 生命周期结束,回收到对象池
- BulletPool.release(this.entity);
- }
- }
-}
-
-// 对象池管理
-class BulletPool {
- private static pool: Entity[] = [];
-
- static get(): Entity {
- if (this.pool.length > 0) {
- const bullet = this.pool.pop()!;
- bullet.enabled = true;
- return bullet;
- } else {
- return this.createBullet();
- }
- }
-
- static release(bullet: Entity) {
- bullet.enabled = false;
- bullet.getComponent(PooledBulletComponent)?.reset();
- this.pool.push(bullet);
- }
-
- private static createBullet(): Entity {
- const bullet = Core.scene.createEntity("Bullet");
- bullet.addComponent(new PooledBulletComponent());
- bullet.addComponent(new PositionComponent());
- bullet.addComponent(new VelocityComponent());
- return bullet;
- }
-}
-```
-
-### 2. 数据紧凑性
-
-保持组件数据紧凑,避免不必要的对象分配。
-
-```typescript
-// 好的设计:紧凑的数据结构
-class ParticleComponent extends Component {
- // 使用基本类型,避免对象分配
- public x: number = 0;
- public y: number = 0;
- public velocityX: number = 0;
- public velocityY: number = 0;
- public life: number = 1.0;
- public maxLife: number = 1.0;
- public size: number = 1.0;
- public color: number = 0xFFFFFF;
-
- // 计算属性,避免存储冗余数据
- get alpha(): number {
- return this.life / this.maxLife;
- }
-}
-
-// ❌ 不好的设计:过多对象分配
-class BadParticleComponent extends Component {
- public position: { x: number; y: number } = { x: 0, y: 0 }; // 对象分配
- public velocity: { x: number; y: number } = { x: 0, y: 0 }; // 对象分配
- public color: Color = new Color(); // 对象分配
- public transform: Transform = new Transform(); // 对象分配
-
- // 冗余数据
- public alpha: number = 1.0;
- public life: number = 1.0;
- public maxLife: number = 1.0;
-}
-```
-
-## 组件调试和测试
-
-### 1. 调试友好的组件
-
-```typescript
-class DebugFriendlyComponent extends Component {
- public someValue: number = 0;
- private debugName: string;
-
- constructor(debugName: string = "Unknown") {
- super();
- this.debugName = debugName;
- }
-
- // 提供有用的调试信息
- toString(): string {
- return `${this.constructor.name}(${this.debugName}): value=${this.someValue}`;
- }
-
- // 验证组件状态
- validate(): boolean {
- if (this.someValue < 0) {
- console.warn(`${this} has invalid value: ${this.someValue}`);
- return false;
- }
- return true;
- }
-
- // 获取调试信息
- getDebugInfo(): any {
- return {
- name: this.debugName,
- value: this.someValue,
- entityId: this.entity?.id,
- isValid: this.validate()
- };
- }
-}
-```
-
-### 2. 单元测试
-
-```typescript
-// 组件测试示例
-describe('HealthComponent', () => {
- let healthComponent: HealthComponent;
-
- beforeEach(() => {
- healthComponent = new HealthComponent(100);
- });
-
- test('初始状态正确', () => {
- expect(healthComponent.currentHealth).toBe(100);
- expect(healthComponent.maxHealth).toBe(100);
- expect(healthComponent.isDead()).toBe(false);
- });
-
- test('受伤功能正确', () => {
- healthComponent.takeDamage(30);
- expect(healthComponent.currentHealth).toBe(70);
- expect(healthComponent.getHealthPercentage()).toBe(0.7);
- });
-
- test('死亡检测正确', () => {
- healthComponent.takeDamage(100);
- expect(healthComponent.isDead()).toBe(true);
- });
-});
-```
-
-## 常见问题和最佳实践
-
-### Q: 组件应该有多大?
-
-A: 组件应该尽可能小和专注。如果一个组件有超过10个字段,考虑拆分。
-
-### Q: 组件可以包含方法吗?
-
-A: 可以,但应该是简单的辅助方法。复杂逻辑应该在系统中处理。
-
-### Q: 如何处理组件之间的依赖?
-
-A:
-1. 优先使用组合而不是依赖
-2. 通过事件系统通信
-3. 在系统中处理组件间的协调
-
-### Q: 什么时候使用继承?
-
-A: 很少使用。只在有明确的"是一个"关系时使用,如:
-
-```typescript
-abstract class ColliderComponent extends Component {
- abstract checkCollision(other: ColliderComponent): boolean;
-}
-
-class CircleColliderComponent extends ColliderComponent {
- public radius: number;
-
- checkCollision(other: ColliderComponent): boolean {
- // 圆形碰撞检测
- }
-}
-
-class BoxColliderComponent extends ColliderComponent {
- public width: number;
- public height: number;
-
- checkCollision(other: ColliderComponent): boolean {
- // 方形碰撞检测
- }
-}
-```
-
-遵循这些原则,你就能设计出高质量、易维护的组件系统!
\ No newline at end of file
diff --git a/docs/concepts-explained.md b/docs/concepts-explained.md
deleted file mode 100644
index 4d765e19..00000000
--- a/docs/concepts-explained.md
+++ /dev/null
@@ -1,513 +0,0 @@
-# 技术概念详解
-
-本文档用通俗易懂的语言解释ECS框架中的关键技术概念,帮助开发者理解这些技术的作用和应用场景。
-
-## 目录
-
-- [ECS 架构基础](#ecs-架构基础)
-- [性能优化技术](#性能优化技术)
-- [事件系统](#事件系统)
-- [实体管理](#实体管理)
-
-## ECS 架构基础
-
-### 什么是 ECS?
-
-ECS (Entity-Component-System) 是一种编程架构模式,将游戏对象分解为三个独立的部分:
-
-**传统面向对象方式:**
-```typescript
-// 传统继承方式 - 问题很多
-class GameObject {
- x: number; y: number;
- render() { ... }
- update() { ... }
-}
-
-class Player extends GameObject {
- health: number;
- shoot() { ... }
-}
-
-class Enemy extends Player { // 敌人需要射击但不需要玩家控制?
- ai() { ... }
-}
-```
-
-**ECS 方式:**
-```typescript
-// 数据和逻辑分离,灵活组合
-const player = scene.createEntity("Player")
- .addComponent(new PositionComponent()) // 位置数据
- .addComponent(new HealthComponent()) // 生命值数据
- .addComponent(new PlayerInputComponent()) // 玩家输入标记
-
-const enemy = scene.createEntity("Enemy")
- .addComponent(new PositionComponent()) // 复用位置数据
- .addComponent(new HealthComponent()) // 复用生命值数据
- .addComponent(new AIComponent()) // AI标记
-
-// 系统自动处理具有特定组件的实体
-class MovementSystem extends EntitySystem {
- onUpdate() {
- // 处理具有Position和Velocity组件的实体
- }
-}
-```
-
-### ECS 的优势
-
-1. **灵活组合** - 像搭积木一样组装功能
-2. **代码复用** - 组件可以在不同实体间复用
-3. **性能优化** - 数据连续存储,缓存友好
-4. **并行处理** - 系统间相互独立,可以并行执行
-5. **易于测试** - 组件和系统可以独立测试
-
-### 实际应用场景
-
-**游戏开发中的例子:**
-- **RPG游戏**:玩家、NPC、怪物都有位置和生命值,但只有玩家有输入组件
-- **射击游戏**:子弹、玩家、敌人都有位置和碰撞体,但行为完全不同
-- **策略游戏**:建筑、单位、资源都是实体,通过不同组件组合实现功能
-
-## 性能优化技术
-
-### 组件索引系统
-
-**问题:** 没有索引时,查找组件需要遍历所有实体
-```typescript
-// 慢的方式:线性搜索 O(n)
-function findEntitiesWithHealth() {
- const result = [];
- for (const entity of allEntities) { // 遍历10万个实体
- if (entity.hasComponent(HealthComponent)) {
- result.push(entity);
- }
- }
- return result;
-}
-```
-
-**解决方案:** 查询系统,直接访问
-```typescript
-// 快的方式:使用查询系统 O(1)
-const entitiesWithHealth = entityManager.query()
- .withAll(HealthComponent)
- .execute(); // 直接获取,SparseSet自动优化
-```
-
-**应用场景:**
-- 频繁查询特定组件的实体
-- 大规模实体场景(数千到数万个实体)
-- 实时游戏中的系统更新
-
-### SparseSet 组件索引
-
-**什么是 SparseSet?**
-SparseSet是一种高效的数据结构,结合了哈希表的快速访问和数组的缓存友好特性。
-
-**SparseSet 的优势:**
-- **O(1) 添加/删除/查找** - 所有基本操作都是常数时间
-- **缓存友好遍历** - 密集数组存储,提高遍历性能
-- **内存高效** - 自动管理稀疏和密集数据
-- **无需配置** - 框架自动选择最优策略
-
-```typescript
-// 统一的查询API,无需手动配置
-const entitiesWithHealth = entityManager.query()
- .withAll(HealthComponent)
- .execute(); // O(1) 访问,SparseSet自动优化
-```
-
-**应用场景:**
-- 任意规模的实体场景(从几十到数万)
-- 频繁的组件添加/删除操作
-- 高性能的批量查询需求
-
-### Archetype 系统
-
-**什么是 Archetype?**
-Archetype(原型)是具有相同组件组合的实体分组。
-
-**没有 Archetype 的问题:**
-```typescript
-// 每次都要检查每个实体的组件组合
-for (const entity of allEntities) {
- if (entity.has(Position) && entity.has(Velocity) && !entity.has(Frozen)) {
- // 处理移动
- }
-}
-```
-
-**Archetype 的解决方案:**
-```typescript
-// 实体按组件组合自动分组
-const movableArchetype = [Position, Velocity, !Frozen];
-const movableEntities = archetypeSystem.getEntities(movableArchetype);
-// 直接处理,无需逐个检查
-```
-
-**应用场景:**
-- 大量实体的游戏(RTS、MMO)
-- 频繁的实体查询操作
-- 批量处理相同类型的实体
-
-### 脏标记系统
-
-**什么是脏标记?**
-脏标记(Dirty Tracking)追踪哪些数据发生了变化,避免处理未变化的数据。
-
-**没有脏标记的问题:**
-```typescript
-// 每帧都重新计算所有实体,即使它们没有移动
-function renderSystem() {
- for (const entity of entities) {
- updateRenderPosition(entity); // 浪费计算
- updateRenderRotation(entity); // 浪费计算
- updateRenderScale(entity); // 浪费计算
- }
-}
-```
-
-**脏标记的解决方案:**
-```typescript
-// 只处理发生变化的实体
-function renderSystem() {
- const dirtyEntities = dirtyTracking.getDirtyEntities();
- for (const entity of dirtyEntities) {
- if (dirtyTracking.isDirty(entity, PositionComponent)) {
- updateRenderPosition(entity); // 只在需要时计算
- }
- if (dirtyTracking.isDirty(entity, RotationComponent)) {
- updateRenderRotation(entity);
- }
- }
- dirtyTracking.clearDirtyFlags();
-}
-```
-
-**应用场景:**
-- 渲染系统优化(只更新变化的物体)
-- 物理系统优化(只计算移动的物体)
-- UI更新优化(只刷新变化的界面元素)
-- 网络同步优化(只发送变化的数据)
-
-**实际例子:**
-```typescript
-// 游戏中的应用
-class MovementSystem {
- process() {
- // 玩家移动时标记为脏
- if (playerInput.moved) {
- dirtyTracking.markDirty(player, PositionComponent);
- }
-
- // 静止的敌人不会被标记为脏,渲染系统会跳过它们
- }
-}
-```
-
-## 事件系统
-
-### 类型安全事件
-
-**传统事件的问题:**
-```typescript
-// 类型不安全,容易出错
-eventEmitter.emit('player_died', playerData);
-eventEmitter.on('player_dead', handler); // 事件名拼写错误!
-```
-
-**类型安全事件的解决方案:**
-```typescript
-// 编译时检查,避免错误
-enum GameEvents {
- PLAYER_DIED = 'player:died',
- LEVEL_COMPLETED = 'level:completed'
-}
-
-eventBus.emit(GameEvents.PLAYER_DIED, { playerId: 123 });
-eventBus.on(GameEvents.PLAYER_DIED, (data) => {
- // data 类型自动推断
-});
-```
-
-### 事件装饰器
-
-**什么是装饰器?**
-装饰器让你用简单的语法自动注册事件监听器。
-
-**传统方式:**
-```typescript
-class GameManager {
- constructor() {
- // 手动注册事件
- eventBus.on('entity:created', this.onEntityCreated.bind(this));
- eventBus.on('entity:destroyed', this.onEntityDestroyed.bind(this));
- eventBus.on('component:added', this.onComponentAdded.bind(this));
- }
-
- onEntityCreated(data) { ... }
- onEntityDestroyed(data) { ... }
- onComponentAdded(data) { ... }
-}
-```
-
-**装饰器方式:**
-```typescript
-class GameManager {
- @EventHandler('entity:created')
- onEntityCreated(data) { ... } // 自动注册
-
- @EventHandler('entity:destroyed')
- onEntityDestroyed(data) { ... } // 自动注册
-
- @EventHandler('component:added')
- onComponentAdded(data) { ... } // 自动注册
-}
-```
-
-**应用场景:**
-- 游戏状态管理
-- UI更新响应
-- 音效播放触发
-- 成就系统检查
-
-## 实体管理
-
-### 实体生命周期
-
-**创建实体的方式:**
-```typescript
-// 单个创建 - 适用于重要实体
-const player = scene.createEntity("Player");
-player.addComponent(new PositionComponent());
-player.addComponent(new HealthComponent());
-
-// 批量创建 - 需要循环处理
-const bullets: Entity[] = [];
-for (let i = 0; i < 100; i++) {
- const bullet = scene.createEntity(`Bullet_${i}`);
- bullet.addComponent(new PositionComponent());
- bullet.addComponent(new VelocityComponent());
- bullets.push(bullet);
-}
-```
-
-### 查询系统
-
-**流式API的优势:**
-```typescript
-// 传统方式:复杂的条件判断
-const result = [];
-for (const entity of entities) {
- if (entity.has(Position) &&
- entity.has(Velocity) &&
- !entity.has(Frozen) &&
- entity.tag === EntityTag.ENEMY) {
- result.push(entity);
- }
-}
-
-// 流式API:清晰表达意图
-const result = entityManager
- .query()
- .withAll(Position, Velocity)
- .withNone(Frozen)
- .withTag(EntityTag.ENEMY)
- .execute();
-```
-
-### 批量操作
-
-**批量操作的优化:**
-```typescript
-// 优化的批量创建方式
-const bullets: Entity[] = [];
-for (let i = 0; i < 1000; i++) {
- const bullet = scene.createEntity(`Bullet_${i}`);
- bullet.addComponent(new PositionComponent());
- bullet.addComponent(new VelocityComponent());
- bullets.push(bullet);
-}
-
-// 批量查询操作
-const allMovableEntities = entityManager.query()
- .withAll(PositionComponent, VelocityComponent)
- .execute();
-```
-
-**应用场景:**
-- 生成大量子弹/粒子
-- 加载关卡时创建大量实体
-- 清理场景时删除大量实体
-
-
-## 总结
-
-ECS框架包含以下核心技术概念:
-
-1. **ECS架构** - 组件化设计模式
-2. **SparseSet索引** - 高效的组件查询
-3. **Archetype系统** - 实体分组优化
-4. **脏标记系统** - 变化检测机制
-5. **事件系统** - 组件间通信
-6. **实体管理** - 生命周期管理
-
-## 框架类型系统
-
-### TypeScript接口设计
-
-ECS框架采用了精简的TypeScript接口设计,提供类型安全保障的同时保持实现的灵活性。
-
-#### 核心接口
-
-**IComponent接口**
-```typescript
-interface IComponent {
- readonly id: number;
- enabled: boolean;
- updateOrder: number;
-
- onAddedToEntity(): void;
- onRemovedFromEntity(): void;
- onEnabled(): void;
- onDisabled(): void;
- update(): void;
-}
-```
-- 定义所有组件的基本契约
-- Component基类实现此接口
-- 确保组件生命周期方法的一致性
-
-**ISystemBase接口**
-```typescript
-interface ISystemBase {
- readonly systemName: string;
- readonly entities: readonly any[];
- updateOrder: number;
- enabled: boolean;
-
- initialize(): void;
- update(): void;
- lateUpdate?(): void;
-}
-```
-- 为EntitySystem类提供类型约束
-- 定义系统的核心执行方法
-- 支持可选的延迟更新
-
-**IEventBus接口**
-```typescript
-interface IEventBus {
- emit(eventType: string, data: T): void;
- emitAsync(eventType: string, data: T): Promise;
- on(eventType: string, handler: (data: T) => void, config?: IEventListenerConfig): string;
- // ... 其他事件方法
-}
-```
-- 提供类型安全的事件系统契约
-- 支持同步和异步事件处理
-- EventBus类完整实现此接口
-
-#### 事件数据接口
-
-**事件数据层次结构**
-```typescript
-// 基础事件数据
-interface IEventData {
- timestamp: number;
- source?: string;
- eventId?: string;
-}
-
-// 实体相关事件
-interface IEntityEventData extends IEventData {
- entityId: number;
- entityName?: string;
- entityTag?: string;
-}
-
-// 组件相关事件
-interface IComponentEventData extends IEntityEventData {
- componentType: string;
- component?: IComponent;
-}
-```
-- 清晰的继承层次
-- 类型安全的事件数据传递
-- 便于事件处理器的实现
-
-#### 类型别名
-
-**ComponentType**
-```typescript
-type ComponentType = new (...args: any[]) => T;
-```
-- 用于类型安全的组件操作
-- 支持泛型约束
-- 广泛用于实体和查询系统
-
-### 设计原则
-
-#### 1. 接口简化原则
-- 只保留实际使用的接口
-- 移除了未使用的复杂接口(如IEntityManager、IEntityQueryBuilder等)
-- 减少认知负担,提高开发效率
-
-#### 2. 实现灵活性原则
-- 接口作为类型约束而非强制实现
-- 允许具体类有更丰富的实现
-- 保持向后兼容性
-
-#### 3. 类型安全原则
-- 编译时类型检查
-- 泛型支持提供精确的类型推断
-- 事件系统的完整类型安全
-
-### 使用指南
-
-#### 在项目中使用接口
-```typescript
-// 作为类型约束
-function processComponent(component: T) {
- if (component.enabled) {
- component.update();
- }
-}
-
-// 作为参数类型
-function registerSystem(system: ISystemBase) {
- scene.addEntityProcessor(system);
-}
-
-// 作为泛型约束
-function getComponent(type: ComponentType): T | null {
- return entity.getComponent(type);
-}
-```
-
-#### 扩展框架接口
-```typescript
-// 如果需要扩展组件接口
-interface IAdvancedComponent extends IComponent {
- priority: number;
- category: string;
-}
-
-class AdvancedComponent extends Component implements IAdvancedComponent {
- public priority: number = 0;
- public category: string = "default";
-
- // 实现基础接口方法
-}
-```
-
-### 接口维护
-
-当前的接口设计已经过精心清理,包含:
-- **12个核心接口** - 涵盖组件、系统、事件等核心概念
-- **0个冗余接口** - 移除了所有未使用的接口定义
-- **完整的类型覆盖** - 为所有主要功能提供类型支持
-
-这种设计确保了框架的类型安全性,同时保持了代码的简洁性和可维护性。
\ No newline at end of file
diff --git a/docs/core-concepts.md b/docs/core-concepts.md
deleted file mode 100644
index 20e8aee5..00000000
--- a/docs/core-concepts.md
+++ /dev/null
@@ -1,926 +0,0 @@
-# 核心 API 参考
-
-本文档详细介绍 ECS Framework 的核心 API 和使用方法。
-
-> **不熟悉ECS概念?** 建议先阅读 [技术概念详解](concepts-explained.md) 了解ECS架构基础和性能优化原理
-
-## ECS 架构概述
-
-ECS 架构将传统的面向对象设计分解为三个核心部分:
-
-- **Entity(实体)** - 游戏世界中的对象,包含基本属性如位置、旋转、缩放
-- **Component(组件)** - 包含数据和行为的功能模块
-- **System(系统)** - 处理实体集合的逻辑处理单元
-
-## Core(核心)
-
-Core 是框架的核心管理类,负责游戏的生命周期管理。框架采用融合设计,既支持传统的单Scene模式(向后兼容),也支持高级的多World/多Scene架构。
-
-### 创建和配置
-
-```typescript
-import { Core, ICoreConfig } from '@esengine/ecs-framework';
-
-// 创建核心实例(使用配置对象 - 推荐)
-const config: ICoreConfig = {
- debug: true, // 启用调试模式
- enableEntitySystems: true, // 启用实体系统
- debugConfig: { // 可选:远程调试配置
- enabled: true,
- websocketUrl: 'ws://localhost:8080',
- autoReconnect: true,
- updateInterval: 1000,
- channels: {
- entities: true,
- systems: true,
- performance: true,
- components: true,
- scenes: true
- }
- }
-};
-const core = Core.create(config);
-
-// 简化创建(向后兼容)
-const core1 = Core.create(true); // 调试模式
-const core2 = Core.create(false); // 发布模式
-const core3 = Core.create(); // 默认调试模式
-```
-
-### 场景管理API
-
-```typescript
-// 单Scene模式(默认,向后兼容)
-const scene = new Scene();
-Core.setScene(scene); // 设置场景
-const currentScene = Core.getScene(); // 获取当前场景
-
-// 多World模式(高级功能)
-Core.enableWorldManager(); // 启用World管理器
-const worldManager = Core.getWorldManager();
-
-// 创建World
-const gameWorld = worldManager.createWorld('GameWorld', {
- name: 'GameWorld',
- maxScenes: 10,
- autoCleanup: true
-});
-
-// 在World中管理Scene
-const battleScene = gameWorld.createScene('battle', new Scene());
-const uiScene = gameWorld.createScene('ui', new Scene());
-
-gameWorld.setSceneActive('battle', true);
-gameWorld.setSceneActive('ui', true);
-
-// 启动World
-gameWorld.start();
-
-// 获取World统计
-const worldStats = gameWorld.getStats();
-console.log('World状态:', worldStats);
-```
-
-### 事件系统
-
-```typescript
-import { EntityManager, ECSEventType } from '@esengine/ecs-framework';
-
-// 获取EntityManager的事件系统
-const entityManager = new EntityManager();
-const eventBus = entityManager.eventBus;
-
-// 监听实体事件
-eventBus.onEntityCreated((data) => {
- console.log(`实体创建: ${data.entityName}`);
-});
-
-eventBus.onComponentAdded((data) => {
- console.log(`组件添加: ${data.componentType}`);
-});
-
-// 发送自定义事件
-eventBus.emit("customEvent", { data: "value" });
-
-// 使用事件装饰器(推荐)
-import { EventHandler } from '@esengine/ecs-framework';
-
-class GameSystem {
- @EventHandler('entity:died')
- onEntityDied(data: any) {
- console.log('实体死亡:', data);
- }
-}
-```
-
-### 定时器系统
-
-```typescript
-// 延迟执行
-Core.schedule(2.0, false, this, (timer) => {
- console.log("2秒后执行");
-});
-
-// 重复执行
-Core.schedule(1.0, true, this, (timer) => {
- console.log("每秒执行一次");
-});
-```
-
-## Scene(场景)
-
-场景是游戏世界的容器,管理实体和系统的生命周期。
-
-### 创建和使用场景
-
-```typescript
-import { Scene } from '@esengine/ecs-framework';
-
-// 创建场景
-const scene = new Scene();
-scene.name = "GameScene";
-
-// 设置为当前场景
-Core.setScene(scene;
-
-// 场景生命周期
-scene.begin(); // 开始场景
-scene.update(); // 更新场景
-scene.end(); // 结束场景
-```
-
-### 批量实体管理
-
-```typescript
-// 批量创建实体 - 高性能
-const entities = scene.createEntities(1000, "Enemy");
-
-// 批量添加实体(延迟缓存清理)
-entities.forEach(entity => {
- scene.addEntity(entity, false); // 延迟清理
-});
-scene.querySystem.clearCache(); // 手动清理缓存
-
-// 获取性能统计
-const stats = scene.getStats();
-console.log(`实体数量: ${stats.entityCount}`);
-```
-
-## Entity(实体)
-
-实体是游戏世界中的基本对象,包含位置、旋转、缩放等基本属性。
-
-### 实体的基本属性
-
-```typescript
-const entity = scene.createEntity("MyEntity");
-
-// 标签(用于分类)
-entity.tag = 1;
-
-// 启用状态
-entity.enabled = true;
-
-// 活跃状态
-entity.active = true;
-
-// 更新顺序
-entity.updateOrder = 10;
-
-// 注意:框架专注于ECS架构,不提供Transform相关功能
-// 位置、旋转、缩放等Transform功能需要通过组件实现
-class TransformComponent extends Component {
- public x: number = 0;
- public y: number = 0;
- public rotation: number = 0;
- public scaleX: number = 1;
- public scaleY: number = 1;
-}
-
-// 使用Transform组件
-const transform = entity.addComponent(new TransformComponent());
-transform.x = 100;
-transform.y = 200;
-transform.rotation = Math.PI / 4;
-```
-
-### 实体层级关系
-
-```typescript
-// 添加子实体
-const parent = scene.createEntity("Parent");
-const child = scene.createEntity("Child");
-parent.addChild(child);
-
-// 获取父实体
-const parentEntity = child.parent;
-
-// 获取所有子实体
-const children = parent.children;
-
-// 查找子实体
-const foundChild = parent.findChild("Child");
-
-// 按标签查找子实体
-const taggedChildren = parent.findChildrenByTag(1);
-
-// 移除子实体
-parent.removeChild(child);
-
-// 移除所有子实体
-parent.removeAllChildren();
-```
-
-### 实体生命周期
-
-```typescript
-// 检查实体是否被销毁
-if (!entity.isDestroyed) {
- // 实体仍然有效
-}
-
-// 销毁实体
-entity.destroy();
-
-// 获取实体调试信息
-const debugInfo = entity.getDebugInfo();
-console.log(debugInfo);
-```
-
-## Component(组件)
-
-组件包含数据和行为,定义了实体的特性和能力。
-
-### 创建组件
-
-```typescript
-import { Component } from '@esengine/ecs-framework';
-
-class HealthComponent extends Component {
- public maxHealth: number = 100;
- public currentHealth: number = 100;
-
- public takeDamage(damage: number) {
- this.currentHealth -= damage;
- if (this.currentHealth <= 0) {
- this.entity.destroy();
- }
- }
-
- public heal(amount: number) {
- this.currentHealth = Math.min(this.maxHealth, this.currentHealth + amount);
- }
-}
-```
-
-### 组件生命周期
-
-```typescript
-class MyComponent extends Component {
- public onAddedToEntity() {
- // 组件被添加到实体时调用
- console.log("组件已添加到实体:", this.entity.name);
- }
-
- public onRemovedFromEntity() {
- // 组件从实体移除时调用
- console.log("组件已从实体移除");
- }
-
- public onEnabled() {
- // 组件启用时调用
- console.log("组件已启用");
- }
-
- public onDisabled() {
- // 组件禁用时调用
- console.log("组件已禁用");
- }
-
- public update() {
- // 每帧更新(如果组件启用)
- console.log("组件更新");
- }
-}
-```
-
-### 组件管理
-
-```typescript
-// 添加组件
-const health = entity.addComponent(new HealthComponent());
-
-// 创建并添加组件
-const movement = entity.createComponent(MovementComponent, 200); // 传递构造参数
-
-// 获取组件
-const healthComp = entity.getComponent(HealthComponent);
-
-// 检查组件是否存在
-if (entity.hasComponent(HealthComponent)) {
- // 处理逻辑
-}
-
-// 获取或创建组件
-const weapon = entity.getOrCreateComponent(WeaponComponent);
-
-// 获取多个同类型组件
-const allHealthComps = entity.getComponents(HealthComponent);
-
-// 移除组件
-entity.removeComponent(healthComp);
-
-// 按类型移除组件
-entity.removeComponentByType(HealthComponent);
-
-// 移除所有组件
-entity.removeAllComponents();
-```
-
-### 组件对象池优化
-
-```typescript
-import { Component, ComponentPoolManager } from '@esengine/ecs-framework';
-
-class BulletComponent extends Component {
- public damage: number = 10;
- public speed: number = 300;
-
- // 对象池重置方法
- public reset() {
- this.damage = 10;
- this.speed = 300;
- }
-}
-
-// 注册组件池
-ComponentPoolManager.getInstance().registerPool(
- 'BulletComponent',
- () => new BulletComponent(),
- (bullet) => bullet.reset(),
- 1000
-);
-
-// 使用对象池获取组件
-const bullet = ComponentPoolManager.getInstance().acquireComponent('BulletComponent');
-if (bullet) {
- entity.addComponent(bullet);
-}
-
-// 释放组件回对象池
-ComponentPoolManager.getInstance().releaseComponent('BulletComponent', bullet);
-
-// 预热所有组件池
-ComponentPoolManager.getInstance().prewarmAll(100);
-
-// 获取池统计
-const stats = ComponentPoolManager.getInstance().getPoolStats();
-console.log('组件池统计:', stats);
-```
-
-## Scene(场景)
-
-场景是实体和系统的容器,管理游戏世界的状态。
-
-### 场景生命周期
-
-```typescript
-import { Scene } from '@esengine/ecs-framework';
-
-class GameScene extends Scene {
- public initialize() {
- // 场景初始化,创建实体和系统
- this.setupEntities();
- this.setupSystems();
- }
-
- public onStart() {
- // 场景开始运行时调用
- console.log("场景开始");
- }
-
- public unload() {
- // 场景卸载时调用
- console.log("场景卸载");
- }
-
- private setupEntities() {
- const player = this.createEntity("Player");
- player.addComponent(new PlayerComponent());
- }
-
- private setupSystems() {
- this.addEntityProcessor(new MovementSystem());
- }
-}
-```
-
-### 实体管理
-
-```typescript
-// 创建实体
-const entity = scene.createEntity("MyEntity");
-
-// 添加现有实体
-scene.addEntity(entity);
-
-// 查找实体
-const player = scene.findEntity("Player");
-const entityById = scene.findEntityById(123);
-const entitiesByTag = scene.findEntitiesByTag(1);
-
-// 销毁所有实体
-scene.destroyAllEntities();
-
-// 获取场景统计信息
-const stats = scene.getStats();
-console.log("实体数量:", stats.entityCount);
-console.log("系统数量:", stats.processorCount);
-```
-
-## World(世界)
-
-World是Scene的容器,提供了更高级的场景管理功能。每个World可以包含多个Scene,适用于复杂的游戏架构。
-
-### World基本使用
-
-```typescript
-import { World, Scene, IWorldConfig } from '@esengine/ecs-framework';
-
-// 创建World配置
-const worldConfig: IWorldConfig = {
- name: 'GameWorld',
- debug: true,
- maxScenes: 10,
- autoCleanup: true
-};
-
-// 创建World
-const gameWorld = new World(worldConfig);
-
-// 在World中创建Scene
-const battleScene = gameWorld.createScene('battle', new Scene());
-const uiScene = gameWorld.createScene('ui', new Scene());
-const menuScene = gameWorld.createScene('menu');
-
-// 激活Scene
-gameWorld.setSceneActive('battle', true);
-gameWorld.setSceneActive('ui', true);
-
-// 启动World
-gameWorld.start();
-```
-
-### World生命周期管理
-
-```typescript
-// 启动World(启动所有全局System)
-gameWorld.start();
-
-// 检查World状态
-if (gameWorld.isActive) {
- console.log('World正在运行');
-}
-
-// 停止World(停止所有Scene和全局System)
-gameWorld.stop();
-
-// 销毁World(清理所有资源)
-gameWorld.destroy();
-```
-
-### Scene管理
-
-```typescript
-// 获取Scene
-const battleScene = gameWorld.getScene('battle');
-
-// 检查Scene是否激活
-if (gameWorld.isSceneActive('battle')) {
- console.log('战斗场景正在运行');
-}
-
-// 移除Scene
-gameWorld.removeScene('menu');
-
-// 获取所有Scene ID
-const sceneIds = gameWorld.getSceneIds();
-console.log('所有Scene:', sceneIds);
-
-// 获取活跃Scene数量
-const activeCount = gameWorld.getActiveSceneCount();
-console.log('活跃Scene数量:', activeCount);
-```
-
-### 全局System管理
-
-World支持全局System,这些System会在所有Scene之前执行,适用于跨Scene的业务逻辑:
-
-```typescript
-import { IGlobalSystem } from '@esengine/ecs-framework';
-
-// 全局网络同步系统
-class GlobalNetworkSystem implements IGlobalSystem {
- public readonly name = 'GlobalNetworkSystem';
-
- public initialize(): void {
- // 初始化网络连接
- console.log('网络系统初始化');
- }
-
- public update(): void {
- // 处理全局网络同步逻辑
- // 注意:全局系统处理的是World级别的逻辑,不直接处理实体
- // 如需处理特定实体,请在Scene中使用EntitySystem
- this.syncGlobalNetworkState();
- }
-
- public reset(): void {
- // 重置系统状态
- }
-
- public destroy(): void {
- // 清理网络连接
- console.log('网络系统销毁');
- }
-
- private syncGlobalNetworkState(): void {
- // 全局网络状态同步
- }
-}
-
-// 添加全局System
-const networkSystem = gameWorld.addGlobalSystem(new GlobalNetworkSystem());
-
-// 获取全局System
-const existingSystem = gameWorld.getGlobalSystem(GlobalNetworkSystem);
-
-// 移除全局System
-gameWorld.removeGlobalSystem(networkSystem);
-```
-
-> **注意**:全局System适用于World级别的业务逻辑(如网络管理、资源管理、全局状态管理等)。如果需要处理具体的实体和组件,请在Scene中使用EntitySystem。
-
-### World状态监控
-
-```typescript
-// 获取World状态
-const status = gameWorld.getStatus();
-console.log('World状态:', {
- name: status.name,
- isActive: status.isActive,
- sceneCount: status.sceneCount,
- activeSceneCount: status.activeSceneCount,
- globalSystemCount: status.globalSystemCount,
- scenes: status.scenes
-});
-
-// 获取World统计信息
-const stats = gameWorld.getStats();
-console.log('World统计:', {
- totalEntities: stats.totalEntities,
- totalSystems: stats.totalSystems,
- memoryUsage: stats.memoryUsage
-});
-```
-
-## WorldManager(世界管理器)
-
-WorldManager是单例模式的World管理器,负责管理多个World实例。
-
-### WorldManager基本使用
-
-```typescript
-import { WorldManager, IWorldManagerConfig } from '@esengine/ecs-framework';
-
-// 获取WorldManager实例
-const worldManager = WorldManager.getInstance({
- maxWorlds: 50,
- autoCleanup: true,
- debug: true
-});
-
-// 或者通过Core获取
-Core.enableWorldManager();
-const worldManager2 = Core.getWorldManager();
-```
-
-### World管理
-
-```typescript
-// 创建World
-const gameWorld = worldManager.createWorld('GameRoom_001', {
- name: 'GameRoom_001',
- maxScenes: 5,
- autoCleanup: true
-});
-
-// 获取World
-const existingWorld = worldManager.getWorld('GameRoom_001');
-
-// 检查World是否存在
-if (worldManager.getWorld('GameRoom_001')) {
- console.log('World存在');
-}
-
-// 销毁World
-worldManager.removeWorld('GameRoom_001');
-
-// 获取所有World ID
-const worldIds = worldManager.getWorldIds();
-console.log('所有World ID:', worldIds);
-
-// 获取活跃World
-const activeWorlds = worldManager.getActiveWorlds();
-console.log('活跃World数量:', activeWorlds.length);
-```
-
-### WorldManager统计和监控
-
-```typescript
-// 获取WorldManager状态
-const managerStatus = worldManager.getStatus();
-console.log('WorldManager状态:', {
- totalWorlds: managerStatus.totalWorlds,
- activeWorlds: managerStatus.activeWorlds,
- maxWorlds: managerStatus.maxWorlds,
- memoryUsage: managerStatus.memoryUsage
-});
-
-// 获取所有World的统计
-const allStats = worldManager.getAllWorldStats();
-allStats.forEach(stat => {
- console.log(`World ${stat.worldName}:`, stat);
-});
-
-// 清理空闲World
-const cleanedCount = worldManager.cleanup();
-console.log(`清理了 ${cleanedCount} 个空闲World`);
-```
-
-### 使用场景
-
-World和WorldManager适用于:
-- **游戏服务器**:每个房间一个独立World
-- **复杂客户端**:按功能分层管理Scene(游戏层、UI层、特效层)
-- **并发世界**:需要同时运行多个独立游戏世界的场景
-
-> **完整示例和最佳实践**:查看 [场景管理完整指南](scene-management-guide.md#world多场景管理) 了解详细的实现方案和架构设计
-
-## System(系统)
-
-系统处理实体集合,实现游戏的核心逻辑。
-
-### EntitySystem
-
-最常用的系统类型,处理实体集合:
-
-```typescript
-import { EntitySystem, Entity, Matcher } from '@esengine/ecs-framework';
-
-class MovementSystem extends EntitySystem {
- constructor() {
- super(Matcher.empty().all(MovementComponent));
- }
-
- protected process(entities: Entity[]) {
- for (const entity of entities) {
- const movement = entity.getComponent(MovementComponent);
- if (movement) {
- movement.update();
- }
- }
- }
-}
-```
-
-### ProcessingSystem
-
-定期处理的系统:
-
-```typescript
-import { ProcessingSystem, Time, Matcher } from '@esengine/ecs-framework';
-
-class HealthRegenerationSystem extends ProcessingSystem {
- constructor() {
- super(Matcher.empty().all(HealthComponent));
- }
-
- public processSystem() {
- // ProcessingSystem不处理具体实体,而是执行全局逻辑
- // 如果需要处理实体,应该使用EntitySystem
- this.regenerateAllPlayerHealth();
- }
-
- private regenerateAllPlayerHealth() {
- // 通过场景查找所有玩家实体并恢复生命值
- const players = this.scene.findEntitiesByTag(PlayerTag);
- for (const player of players) {
- const health = player.getComponent(HealthComponent);
- if (health && health.currentHealth < health.maxHealth) {
- health.currentHealth += 10 * Time.deltaTime;
- }
- }
- }
-}
-```
-
-### IntervalSystem
-
-按时间间隔执行的系统:
-
-```typescript
-import { IntervalSystem, Matcher } from '@esengine/ecs-framework';
-
-class SpawnSystem extends IntervalSystem {
- constructor() {
- // IntervalSystem需要Matcher和间隔时间
- super(Matcher.empty(), 3.0); // 每3秒执行一次
- }
-
- protected process(entities: Entity[]) {
- // 生成敌人
- const enemy = this.scene.createEntity("Enemy");
- enemy.addComponent(new EnemyComponent());
- }
-}
-```
-
-### PassiveSystem
-
-被动系统,不自动处理实体:
-
-```typescript
-import { PassiveSystem, Matcher } from '@esengine/ecs-framework';
-
-class CollisionSystem extends PassiveSystem {
- constructor() {
- super(Matcher.empty());
- }
-
- public checkCollisions() {
- // 手动调用的碰撞检测逻辑
- }
-}
-```
-
-## Time(时间)
-
-时间管理工具类,提供游戏时间相关功能:
-
-```typescript
-import { Time } from '@esengine/ecs-framework';
-
-// 获取时间信息
-console.log("帧时间:", Time.deltaTime);
-console.log("总时间:", Time.totalTime);
-console.log("帧数:", Time.frameCount);
-console.log("时间缩放:", Time.timeScale);
-
-// 设置时间缩放(慢动作效果)
-Time.timeScale = 0.5;
-
-// 检查时间间隔
-if (Time.checkEvery(1.0, lastCheckTime)) {
- // 每秒执行一次
-}
-```
-
-## 性能监控
-
-框架内置性能监控工具:
-
-```typescript
-import { PerformanceMonitor } from '@esengine/ecs-framework';
-
-// 获取性能监控实例
-const monitor = PerformanceMonitor.instance;
-
-// 查看性能数据
-console.log("平均FPS:", monitor.averageFPS);
-console.log("最小FPS:", monitor.minFPS);
-console.log("最大FPS:", monitor.maxFPS);
-console.log("内存使用:", monitor.memoryUsage);
-
-// 重置性能数据
-monitor.reset();
-```
-
-## 对象池
-
-内存管理优化工具:
-
-```typescript
-import { Pool, IPoolable } from '@esengine/ecs-framework';
-
-// 定义可池化的对象(需要实现IPoolable接口)
-class Bullet implements IPoolable {
- public x: number = 0;
- public y: number = 0;
- public speed: number = 0;
-
- // 重置对象状态,准备重用
- public reset(): void {
- this.x = 0;
- this.y = 0;
- this.speed = 0;
- }
-}
-
-// 创建对象池
-const bulletPool = new Pool(() => new Bullet(), 100);
-
-// 预热对象池
-bulletPool.warmUp(20);
-
-// 使用对象池
-const bullet = bulletPool.obtain();
-bullet.x = 100;
-bullet.y = 200;
-bullet.speed = 500;
-
-// 使用完后归还到池中
-bulletPool.free(bullet);
-
-// 查看池统计信息
-console.log(bulletPool.getStats());
-
-// 清空对象池
-bulletPool.clear();
-
-// 使用静态方法(自动管理池)
-const bullet2 = Pool.obtain(Bullet);
-Pool.free(Bullet, bullet2);
-```
-
-## 最佳实践
-
-### 1. 实体设计
-
-- 实体只包含基本属性,功能通过组件实现
-- 合理使用实体层级关系
-- 及时销毁不需要的实体
-
-### 2. 组件设计
-
-- 组件保持单一职责
-- 使用生命周期方法进行初始化和清理
-- 避免组件间直接依赖
-
-### 3. 系统设计
-
-- 系统专注于特定逻辑处理
-- 合理设置系统更新顺序
-- 使用被动系统处理特殊逻辑
-
-### 4. 性能优化
-
-- 使用对象池减少内存分配
-- 监控性能数据
-- 合理使用时间缩放
-
-## 高级性能优化功能
-
-### 查询系统优化
-
-框架内部已集成查询优化,无需手动配置。查询系统会自动使用最优的算法:
-
-```typescript
-// 查询系统会自动优化这些操作
-const movingEntities = scene.querySystem.queryAll(PositionComponent, VelocityComponent);
-const renderableEntities = scene.querySystem.queryAll(PositionComponent, RenderComponent);
-
-// 获取查询统计信息
-const queryStats = scene.querySystem.getStats();
-console.log('查询统计:', queryStats);
-```
-
-### 批量操作API
-
-```typescript
-// 批量创建实体 - 最高性能
-const entities = scene.createEntities(10000, "Bullets");
-
-// 批量查询优化
-const movingEntities = scene.querySystem.queryAll(PositionComponent, VelocityComponent).entities;
-```
-
-## 总结
-
-ECS Framework 提供了完整的实体组件系统架构:
-
-- **Core** 管理游戏生命周期和全局功能,支持单Scene和多World模式
-- **Entity** 作为游戏对象的基础容器
-- **Component** 实现具体的功能模块,支持对象池优化
-- **System** 处理游戏逻辑
-- **Scene** 管理游戏世界状态,支持批量操作
-- **World** 高级场景容器,支持多Scene管理和全局System
-- **WorldManager** 管理多个World实例,适用于复杂架构
-- **高级优化** 位掩码优化器、组件对象池、批量操作等
-
-### 架构选择指南
-
-- **单Scene模式**:适合简单游戏、单机游戏、原型开发
-- **多World模式**:适合多人游戏服务器、复杂应用、需要场景隔离的项目
-
-框架采用融合设计,确保向后兼容性的同时提供强大的扩展能力。通过合理使用这些核心概念和优化功能,可以构建出高性能、结构清晰、易于维护的游戏代码。
\ No newline at end of file
diff --git a/docs/entity-guide.md b/docs/entity-guide.md
deleted file mode 100644
index add89bf0..00000000
--- a/docs/entity-guide.md
+++ /dev/null
@@ -1,370 +0,0 @@
-# 实体基础指南
-
-本指南介绍实体(Entity)的基本概念和基础使用方法。
-
-> 📖 **需要高级实体管理?** 请参考 [EntityManager 指南](entity-manager-example.md) 了解高性能查询和批量操作
-
-## 实体概述
-
-实体(Entity)是 ECS 架构中的核心概念之一,它作为组件的容器存在。实体本身不包含游戏逻辑,所有功能都通过添加不同的组件来实现。
-
-### 实体的特点
-
-- **轻量级容器**:实体只是组件的载体,不包含具体的游戏逻辑
-- **唯一标识**:每个实体都有唯一的ID和名称
-- **层次结构**:支持父子关系,可以构建复杂的实体层次
-- **高性能查询**:基于位掩码的组件查询系统
-- **生命周期管理**:完整的创建、更新、销毁流程
-
-## 创建实体
-
-### 基本创建方式
-
-```typescript
-import { Scene } from '@esengine/ecs-framework';
-
-// 通过场景创建实体
-const scene = new Scene();
-const entity = scene.createEntity("Player");
-
-console.log(entity.name); // "Player"
-console.log(entity.id); // 唯一的数字ID
-```
-
-### 批量创建实体(推荐)
-
-```typescript
-import { Scene } from '@esengine/ecs-framework';
-
-const scene = new Scene();
-
-// 批量创建1000个实体 - 高性能
-const entities = scene.createEntities(1000, "Enemy");
-
-// 批量配置
-entities.forEach((entity, index) => {
- entity.tag = 2; // 敌人标签
- // 添加组件...
-});
-```
-
-### 使用流式API创建
-
-```typescript
-import { Core } from '@esengine/ecs-framework';
-
-// 使用ECS流式API
-const entity = Core.ecsAPI
- ?.entity("Enemy")
- .withComponent(new PositionComponent(100, 200))
- .withComponent(new HealthComponent(50))
- .withTag(2)
- .build();
-```
-
-## 实体属性
-
-### 基本属性
-
-```typescript
-// 实体名称 - 用于调试和标识
-entity.name = "Player";
-
-// 实体ID - 只读,场景内唯一
-console.log(entity.id); // 例如: 1
-
-// 标签 - 用于分类和快速查询
-entity.tag = 1; // 玩家标签
-entity.tag = 2; // 敌人标签
-
-// 更新顺序 - 控制实体在系统中的处理优先级
-entity.updateOrder = 0; // 数值越小优先级越高
-```
-
-### 状态控制
-
-```typescript
-// 启用状态 - 控制实体是否参与更新和处理
-entity.enabled = true; // 启用实体
-entity.enabled = false; // 禁用实体
-
-// 激活状态 - 控制实体及其子实体的活跃状态
-entity.active = true; // 激活实体
-entity.active = false; // 停用实体
-
-// 检查层次结构中的激活状态
-if (entity.activeInHierarchy) {
- // 实体在整个层次结构中都是激活的
-}
-
-// 检查销毁状态
-if (entity.isDestroyed) {
- // 实体已被销毁
-}
-```
-
-### 更新间隔
-
-```typescript
-// 控制实体更新频率
-entity.updateInterval = 1; // 每帧更新
-entity.updateInterval = 2; // 每2帧更新一次
-entity.updateInterval = 5; // 每5帧更新一次
-```
-
-## 组件管理
-
-### 添加组件
-
-```typescript
-// 创建并添加组件
-const healthComponent = entity.addComponent(new HealthComponent(100));
-
-// 使用工厂方法创建组件
-const positionComponent = entity.createComponent(PositionComponent, 100, 200);
-
-// 批量添加组件
-const components = entity.addComponents([
- new PositionComponent(0, 0),
- new VelocityComponent(50, 0),
- new HealthComponent(100)
-]);
-```
-
-### 获取组件
-
-```typescript
-// 获取单个组件
-const health = entity.getComponent(HealthComponent);
-if (health) {
- console.log(`当前生命值: ${health.currentHealth}`);
-}
-
-// 获取或创建组件(如果不存在则创建)
-const position = entity.getOrCreateComponent(PositionComponent, 0, 0);
-
-// 获取多个同类型组件(如果组件可以重复添加)
-const allHealthComponents = entity.getComponents(HealthComponent);
-```
-
-### 检查组件
-
-```typescript
-// 检查是否拥有指定组件
-if (entity.hasComponent(HealthComponent)) {
- // 实体拥有生命值组件
-}
-
-// 检查组件掩码(高性能)
-const mask = entity.componentMask;
-console.log(`组件掩码: ${mask.toString(2)}`); // 二进制表示
-```
-
-### 移除组件
-
-```typescript
-// 移除指定组件实例
-const healthComponent = entity.getComponent(HealthComponent);
-if (healthComponent) {
- entity.removeComponent(healthComponent);
-}
-
-// 按类型移除组件
-const removedHealth = entity.removeComponentByType(HealthComponent);
-
-// 批量移除组件
-const removedComponents = entity.removeComponentsByTypes([
- HealthComponent,
- VelocityComponent
-]);
-
-// 移除所有组件
-entity.removeAllComponents();
-```
-
-## 层次结构管理
-
-### 父子关系
-
-```typescript
-// 创建父子实体
-const player = scene.createEntity("Player");
-const weapon = scene.createEntity("Weapon");
-const shield = scene.createEntity("Shield");
-
-// 添加子实体
-player.addChild(weapon);
-player.addChild(shield);
-
-// 获取父实体
-console.log(weapon.parent === player); // true
-
-// 获取所有子实体
-const children = player.children;
-console.log(children.length); // 2
-
-// 获取子实体数量
-console.log(player.childCount); // 2
-```
-
-### 查找子实体
-
-```typescript
-// 按名称查找子实体
-const weapon = player.findChild("Weapon");
-
-// 递归查找子实体
-const deepChild = player.findChild("DeepChild", true);
-
-// 按标签查找子实体
-const enemies = player.findChildrenByTag(2); // 查找所有敌人标签的子实体
-
-// 递归按标签查找
-const allEnemies = player.findChildrenByTag(2, true);
-```
-
-### 层次结构操作
-
-```typescript
-// 移除子实体
-const removed = player.removeChild(weapon);
-
-// 移除所有子实体
-player.removeAllChildren();
-
-// 获取根实体
-const root = weapon.getRoot();
-
-// 检查祖先关系
-if (player.isAncestorOf(weapon)) {
- // player 是 weapon 的祖先
-}
-
-// 检查后代关系
-if (weapon.isDescendantOf(player)) {
- // weapon 是 player 的后代
-}
-
-// 获取实体在层次结构中的深度
-const depth = weapon.getDepth(); // 从根实体开始计算的深度
-```
-
-### 遍历子实体
-
-```typescript
-// 遍历直接子实体
-player.forEachChild((child, index) => {
- console.log(`子实体 ${index}: ${child.name}`);
-});
-
-// 递归遍历所有子实体
-player.forEachChild((child, index) => {
- console.log(`子实体 ${index}: ${child.name} (深度: ${child.getDepth()})`);
-}, true);
-```
-
-## 实体生命周期
-
-### 更新循环
-
-```typescript
-// 手动更新实体(通常由场景自动调用)
-entity.update();
-
-// 实体会自动调用所有组件的update方法
-class MyComponent extends Component {
- public update(): void {
- // 组件更新逻辑
- }
-}
-```
-
-### 销毁实体
-
-```typescript
-// 销毁实体
-entity.destroy();
-
-// 检查是否已销毁
-if (entity.isDestroyed) {
- console.log("实体已被销毁");
-}
-
-// 销毁实体时会自动:
-// 1. 移除所有组件
-// 2. 从父实体中移除
-// 3. 销毁所有子实体
-// 4. 从场景中移除
-```
-
-# 高级特性请参考其他指南
-
-> **更多功能:**
-> - **高性能查询和批量操作** → [EntityManager 指南](entity-manager-example.md)
-> - **性能优化技术** → [性能优化指南](performance-optimization.md)
-> - **组件索引和缓存** → [技术概念详解](concepts-explained.md)
-
-## 基础最佳实践
-
-### 1. 合理使用标签
-
-```typescript
-// 定义标签常量
-const EntityTags = {
- PLAYER: 1,
- ENEMY: 2,
- PROJECTILE: 3,
- PICKUP: 4
-} as const;
-
-// 使用标签进行分类
-player.tag = EntityTags.PLAYER;
-enemy.tag = EntityTags.ENEMY;
-```
-
-### 2. 正确的销毁处理
-
-```typescript
-// 确保正确销毁实体
-if (!entity.isDestroyed) {
- entity.destroy(); // 自动移除组件和层次关系
-}
-
-// 检查实体状态
-if (entity.isDestroyed) {
- return; // 避免操作已销毁的实体
-}
-```
-
-### 3. 组件生命周期
-
-```typescript
-// 正确添加组件
-const health = entity.addComponent(new HealthComponent(100));
-
-// 安全获取组件
-const healthComp = entity.getComponent(HealthComponent);
-if (healthComp && healthComp.currentHealth <= 0) {
- entity.destroy();
-}
-```
-
-## 常见问题
-
-### Q: 实体如何实现位置、旋转等变换?
-
-A: 通过添加相应的组件:
-
-```typescript
-class TransformComponent extends Component {
- public position = { x: 0, y: 0 };
- public rotation = 0;
- public scale = { x: 1, y: 1 };
-}
-
-entity.addComponent(new TransformComponent());
-```
-
-### Q: 实体可以在场景间移动吗?
-
-A: 不可以。实体与场景绑定,需要在新场景中重新创建。
\ No newline at end of file
diff --git a/docs/entity-manager-example.md b/docs/entity-manager-example.md
deleted file mode 100644
index b2b638f2..00000000
--- a/docs/entity-manager-example.md
+++ /dev/null
@@ -1,370 +0,0 @@
-# EntityManager 使用指南
-
-本文档详细介绍 EntityManager 的使用方法和最佳实践。
-
-## 目录
-
-1. [基础用法](#基础用法)
-2. [查询系统](#查询系统)
-3. [实体管理](#实体管理)
-4. [性能监控](#性能监控)
-5. [最佳实践](#最佳实践)
-
-## 基础用法
-
-### 创建 EntityManager
-
-```typescript
-import { EntityManager, Scene } from '@esengine/ecs-framework';
-
-// 创建场景和实体管理器
-const scene = new Scene();
-const entityManager = new EntityManager();
-
-// 批量创建实体(使用Scene方法)
-const enemies = scene.createEntities(50, "Enemy");
-
-// 为实体添加组件
-enemies.forEach((enemy, index) => {
- enemy.addComponent(new PositionComponent(
- Math.random() * 800,
- Math.random() * 600
- ));
- enemy.addComponent(new HealthComponent(100));
- enemy.addComponent(new VelocityComponent(
- (Math.random() - 0.5) * 100,
- (Math.random() - 0.5) * 100
- ));
- enemy.tag = 2; // 敌人标签
-});
-```
-
-## 查询系统
-
-### 基础查询
-
-```typescript
-// 按组件类型查询
-const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);
-
-// 按标签查询
-const enemies = entityManager.getEntitiesByTag(2);
-const players = entityManager.getEntitiesByTag(1);
-
-// 按名称查询
-const boss = entityManager.getEntityByName("BossEnemy");
-
-// 获取所有实体
-const allEntities = entityManager.getAllEntities();
-```
-
-### 流式查询 API
-
-```typescript
-// 复杂查询条件
-const movingEnemies = entityManager
- .query()
- .withAll(PositionComponent, VelocityComponent, HealthComponent)
- .withTag(2) // 敌人标签
- .execute();
-
-// 查询活跃的玩家
-const activePlayers = entityManager
- .query()
- .withAll(PositionComponent)
- .withTag(1) // 玩家标签
- .active() // 只查询活跃实体
- .execute();
-
-// 排除特定组件的实体
-const nonCombatEntities = entityManager
- .query()
- .withAll(PositionComponent)
- .without(WeaponComponent, HealthComponent)
- .execute();
-
-// 自定义条件查询
-const nearbyEnemies = entityManager
- .query()
- .withAll(PositionComponent)
- .withTag(2)
- .where(entity => {
- const pos = entity.getComponent(PositionComponent);
- return pos && Math.abs(pos.x - playerX) < 100;
- })
- .execute();
-```
-
-## 实体管理
-
-### 创建和销毁实体
-
-```typescript
-// 创建单个实体
-const player = entityManager.createEntity("Player");
-player.addComponent(new PositionComponent(400, 300));
-player.addComponent(new HealthComponent(100));
-player.tag = 1;
-
-// 销毁实体
-entityManager.destroyEntity(player);
-
-// 按名称销毁
-entityManager.destroyEntity("Enemy_1");
-
-// 按ID销毁
-entityManager.destroyEntity(123);
-```
-
-### 实体查找
-
-```typescript
-// 按ID查找
-const entity = entityManager.getEntity(123);
-
-// 按名称查找
-const player = entityManager.getEntityByName("Player");
-
-// 检查实体是否存在
-if (entity && !entity.isDestroyed) {
- // 实体有效
-}
-```
-
-## 性能监控
-
-### 基础统计
-
-```typescript
-// 获取实体数量
-console.log('总实体数:', entityManager.entityCount);
-console.log('活跃实体数:', entityManager.activeEntityCount);
-
-// 获取场景统计
-const sceneStats = scene.getStats();
-console.log('场景统计:', {
- 实体数量: sceneStats.entityCount,
- 系统数量: sceneStats.processorCount
-});
-
-// 获取查询系统统计
-const queryStats = scene.querySystem.getStats();
-console.log('查询统计:', queryStats);
-```
-
-## 最佳实践
-
-### 1. 高效查询
-
-```typescript
-// 好的做法:缓存查询结果
-class CombatSystem extends EntitySystem {
- private cachedEnemies: Entity[] = [];
- private lastUpdateFrame = 0;
-
- protected process(entities: Entity[]): void {
- // 每5帧更新一次缓存
- if (Time.frameCount - this.lastUpdateFrame > 5) {
- this.cachedEnemies = this.entityManager
- .query()
- .withAll(PositionComponent, HealthComponent)
- .withTag(2)
- .execute();
- this.lastUpdateFrame = Time.frameCount;
- }
-
- // 使用缓存的结果
- this.cachedEnemies.forEach(enemy => {
- // 处理敌人逻辑
- });
- }
-}
-```
-
-### 2. 批量操作
-
-```typescript
-// 好的做法:批量创建和配置
-function createBulletWave(count: number): Entity[] {
- // 使用Scene的批量创建
- const bullets = scene.createEntities(count, "Bullet");
-
- // 批量配置组件
- bullets.forEach((bullet, index) => {
- const angle = (index / count) * Math.PI * 2;
- bullet.addComponent(new PositionComponent(400, 300));
- bullet.addComponent(new VelocityComponent(
- Math.cos(angle) * 200,
- Math.sin(angle) * 200
- ));
- bullet.addComponent(new BulletComponent());
- bullet.tag = 3; // 子弹标签
- });
-
- return bullets;
-}
-```
-
-### 3. 内存管理
-
-```typescript
-// 好的做法:及时清理无用实体
-class CleanupSystem extends EntitySystem {
- protected process(entities: Entity[]): void {
- // 清理超出边界的子弹
- const bullets = this.entityManager.getEntitiesByTag(3);
- bullets.forEach(bullet => {
- const pos = bullet.getComponent(PositionComponent);
- if (pos && (pos.x < -100 || pos.x > 900 || pos.y < -100 || pos.y > 700)) {
- this.entityManager.destroyEntity(bullet);
- }
- });
-
- // 清理死亡的敌人
- const deadEnemies = this.entityManager
- .query()
- .withAll(HealthComponent)
- .withTag(2)
- .where(entity => {
- const health = entity.getComponent(HealthComponent);
- return health && health.currentHealth <= 0;
- })
- .execute();
-
- deadEnemies.forEach(enemy => {
- this.entityManager.destroyEntity(enemy);
- });
- }
-}
-```
-
-### 4. 查询优化
-
-```typescript
-// 好的做法:使用合适的查询方法
-class GameSystem extends EntitySystem {
- findTargetsInRange(attacker: Entity, range: number): Entity[] {
- const attackerPos = attacker.getComponent(PositionComponent);
- if (!attackerPos) return [];
-
- // 先按标签快速筛选,再按距离过滤
- return this.entityManager
- .getEntitiesByTag(2) // 敌人标签
- .filter(enemy => {
- const enemyPos = enemy.getComponent(PositionComponent);
- if (!enemyPos) return false;
-
- const distance = Math.sqrt(
- Math.pow(attackerPos.x - enemyPos.x, 2) +
- Math.pow(attackerPos.y - enemyPos.y, 2)
- );
- return distance <= range;
- });
- }
-}
-```
-
-## 完整示例
-
-```typescript
-import {
- EntityManager,
- Scene,
- Entity,
- Component,
- EntitySystem,
- Matcher
-} from '@esengine/ecs-framework';
-
-// 组件定义
-class PositionComponent extends Component {
- constructor(public x: number = 0, public y: number = 0) {
- super();
- }
-}
-
-class HealthComponent extends Component {
- constructor(
- public maxHealth: number = 100,
- public currentHealth: number = 100
- ) {
- super();
- }
-}
-
-// 游戏管理器
-class GameManager {
- private scene: Scene;
- private entityManager: EntityManager;
-
- constructor() {
- this.scene = new Scene();
- this.entityManager = new EntityManager();
- this.setupGame();
- }
-
- private setupGame(): void {
- // 创建玩家
- const player = this.entityManager.createEntity("Player");
- player.addComponent(new PositionComponent(400, 300));
- player.addComponent(new HealthComponent(100));
- player.tag = 1;
-
- // 创建敌人
- const enemies = this.scene.createEntities(10, "Enemy");
- enemies.forEach(enemy => {
- enemy.addComponent(new PositionComponent(
- Math.random() * 800,
- Math.random() * 600
- ));
- enemy.addComponent(new HealthComponent(50));
- enemy.tag = 2;
- });
-
- // 添加系统
- this.scene.addEntityProcessor(new HealthSystem());
- }
-
- public update(): void {
- this.scene.update();
-
- // 输出统计信息
- console.log('实体数量:', this.entityManager.entityCount);
- console.log('活跃实体数:', this.entityManager.activeEntityCount);
- }
-}
-
-// 生命值系统
-class HealthSystem extends EntitySystem {
- constructor() {
- super(Matcher.empty().all(HealthComponent));
- }
-
- protected process(entities: Entity[]): void {
- const healthEntities = this.scene.querySystem.queryAll(HealthComponent);
-
- healthEntities.entities.forEach(entity => {
- const health = entity.getComponent(HealthComponent);
- if (health && health.currentHealth <= 0) {
- console.log(`实体 ${entity.name} 死亡`);
- entity.destroy();
- }
- });
- }
-}
-
-// 启动游戏
-const game = new GameManager();
-setInterval(() => game.update(), 16); // 60 FPS
-```
-
-## 总结
-
-EntityManager 提供了强大的实体管理功能:
-
-- **创建管理**:`createEntity()`, `destroyEntity()`
-- **查询功能**:`getEntitiesWithComponent()`, `getEntitiesByTag()`, `query()`
-- **实体查找**:`getEntity()`, `getEntityByName()`
-- **统计信息**:`entityCount`, `activeEntityCount`
-
-通过合理使用这些API,可以构建高性能的游戏系统。记住要及时清理无用实体,缓存频繁查询的结果,并使用合适的查询方法来优化性能。
\ No newline at end of file
diff --git a/docs/event-system-example.md b/docs/event-system-example.md
deleted file mode 100644
index 5bdb0694..00000000
--- a/docs/event-system-example.md
+++ /dev/null
@@ -1,496 +0,0 @@
-# ECS事件系统使用指南
-
-本文档介绍如何使用ECS框架的增强事件系统,包括类型安全的事件发布订阅、预定义的ECS事件类型和高级功能。
-
-## 目录
-
-1. [基础用法](#基础用法)
-2. [预定义ECS事件](#预定义ecs事件)
-3. [事件装饰器](#事件装饰器)
-4. [高级功能](#高级功能)
-5. [性能优化](#性能优化)
-6. [最佳实践](#最佳实践)
-
-## 基础用法
-
-### 创建事件总线
-
-```typescript
-import { EventBus, GlobalEventBus } from './ECS';
-
-// 方式1:创建独立的事件总线
-const eventBus = new EventBus(true); // true启用调试模式
-
-// 方式2:使用全局事件总线
-const globalEventBus = GlobalEventBus.getInstance(true);
-```
-
-### 基本事件发布订阅
-
-```typescript
-// 定义事件数据类型
-interface PlayerDiedEvent {
- playerId: number;
- cause: string;
- position: { x: number; y: number };
-}
-
-// 监听事件
-const listenerId = eventBus.on('player:died', (data) => {
- console.log(`Player ${data.playerId} died at (${data.position.x}, ${data.position.y})`);
- console.log(`Cause: ${data.cause}`);
-});
-
-// 发射事件
-eventBus.emit('player:died', {
- playerId: 123,
- cause: 'enemy_attack',
- position: { x: 100, y: 200 }
-});
-
-// 移除监听器
-eventBus.off('player:died', listenerId);
-```
-
-### 一次性事件监听
-
-```typescript
-// 只监听一次
-eventBus.once('player:died', (data) => {
- console.log('This will only be called once');
-});
-```
-
-### 异步事件处理
-
-```typescript
-// 异步事件监听
-eventBus.onAsync('player:died', async (data) => {
- await savePlayerDeathToDatabase(data);
- await updateLeaderboard(data.playerId);
-});
-
-// 异步事件发射
-await eventBus.emitAsync('player:died', playerData);
-```
-
-## 预定义ECS事件
-
-框架提供了完整的ECS事件类型定义,支持实体、组件、系统等核心概念的事件。
-
-### 实体事件
-
-```typescript
-import { ECSEventType, IEntityEventData } from './ECS';
-
-// 监听实体创建事件
-eventBus.onEntityCreated((data: IEntityEventData) => {
- console.log(`Entity created: ${data.entityName} (ID: ${data.entityId})`);
-});
-
-// 监听实体销毁事件
-eventBus.on(ECSEventType.ENTITY_DESTROYED, (data) => {
- console.log(`Entity destroyed: ${data.entityName}`);
-});
-
-// 手动发射实体事件
-eventBus.emitEntityCreated({
- timestamp: Date.now(),
- source: 'GameManager',
- entityId: 123,
- entityName: 'Player',
- entityTag: 'player'
-});
-```
-
-### 组件事件
-
-```typescript
-import { IComponentEventData } from './ECS';
-
-// 监听组件添加事件
-eventBus.onComponentAdded((data: IComponentEventData) => {
- console.log(`Component ${data.componentType} added to entity ${data.entityId}`);
-});
-
-// 监听组件移除事件
-eventBus.on(ECSEventType.COMPONENT_REMOVED, (data) => {
- console.log(`Component ${data.componentType} removed from entity ${data.entityId}`);
-});
-```
-
-### 系统事件
-
-```typescript
-import { ISystemEventData } from './ECS';
-
-// 监听系统错误
-eventBus.onSystemError((data: ISystemEventData) => {
- console.error(`System error in ${data.systemName}: ${data.systemType}`);
-});
-
-// 监听系统处理开始/结束
-eventBus.on(ECSEventType.SYSTEM_PROCESSING_START, (data) => {
- console.log(`System ${data.systemName} started processing`);
-});
-```
-
-### 性能事件
-
-```typescript
-import { IPerformanceEventData } from './ECS';
-
-// 监听性能警告
-eventBus.onPerformanceWarning((data: IPerformanceEventData) => {
- console.warn(`Performance warning: ${data.operation} took ${data.executionTime}ms`);
-});
-
-// 监听内存使用过高
-eventBus.on(ECSEventType.MEMORY_USAGE_HIGH, (data) => {
- console.warn(`High memory usage: ${data.memoryUsage}MB`);
-});
-```
-
-## 事件装饰器
-
-使用装饰器可以自动注册事件监听器,简化代码编写。
-
-### 基础装饰器
-
-```typescript
-import { EventHandler, AsyncEventHandler, EventPriority } from './ECS';
-
-class GameManager {
- @EventHandler(ECSEventType.ENTITY_CREATED, { priority: EventPriority.HIGH })
- onEntityCreated(data: IEntityEventData) {
- console.log(`New entity: ${data.entityName}`);
- }
-
- @AsyncEventHandler(ECSEventType.ENTITY_DESTROYED)
- async onEntityDestroyed(data: IEntityEventData) {
- await this.cleanupEntityResources(data.entityId);
- }
-
- @EventHandler('custom:game:event', { once: true })
- onGameStart(data: any) {
- console.log('Game started!');
- }
-
- // 需要手动调用初始化方法
- constructor() {
- // 如果类有initEventListeners方法,会自动注册装饰器定义的监听器
- if (this.initEventListeners) {
- this.initEventListeners();
- }
- }
-
- private async cleanupEntityResources(entityId: number) {
- // 清理实体相关资源
- }
-}
-```
-
-### 优先级和配置
-
-```typescript
-class SystemManager {
- @EventHandler(ECSEventType.SYSTEM_ERROR, {
- priority: EventPriority.CRITICAL,
- context: this
- })
- handleSystemError(data: ISystemEventData) {
- this.logError(data);
- this.restartSystem(data.systemName);
- }
-
- @AsyncEventHandler(ECSEventType.PERFORMANCE_WARNING, {
- priority: EventPriority.LOW,
- async: true
- })
- async handlePerformanceWarning(data: IPerformanceEventData) {
- await this.optimizePerformance(data);
- }
-
- private logError(data: ISystemEventData) {
- // 错误日志记录
- }
-
- private restartSystem(systemName: string) {
- // 重启系统
- }
-
- private async optimizePerformance(data: IPerformanceEventData) {
- // 性能优化逻辑
- }
-}
-```
-
-## 高级功能
-
-### 事件批处理
-
-```typescript
-// 设置批处理配置
-eventBus.setBatchConfig('entity:update', 100, 16); // 批量100个,延迟16ms
-
-// 发射事件(会被批处理)
-for (let i = 0; i < 1000; i++) {
- eventBus.emit('entity:update', { entityId: i, data: 'update' });
-}
-
-// 手动刷新批处理队列
-eventBus.flushBatch('entity:update');
-```
-
-### 事件统计和监控
-
-```typescript
-// 获取单个事件统计
-const stats = eventBus.getStats('entity:created');
-console.log(`Event triggered ${stats.triggerCount} times`);
-console.log(`Average execution time: ${stats.averageExecutionTime}ms`);
-
-// 获取所有事件统计
-const allStats = eventBus.getStats();
-if (allStats instanceof Map) {
- allStats.forEach((stat, eventType) => {
- console.log(`${eventType}: ${stat.triggerCount} triggers`);
- });
-}
-
-// 重置统计
-eventBus.resetStats('entity:created');
-```
-
-### 事件类型验证
-
-```typescript
-import { EventTypeValidator } from './ECS';
-
-// 检查事件类型是否有效
-if (EventTypeValidator.isValid('entity:created')) {
- eventBus.emit('entity:created', data);
-}
-
-// 添加自定义事件类型
-EventTypeValidator.addCustomType('game:custom:event');
-
-// 获取所有有效事件类型
-const validTypes = EventTypeValidator.getAllValidTypes();
-console.log('Valid event types:', validTypes);
-```
-
-### 调试和日志
-
-```typescript
-// 启用调试模式
-eventBus.setDebugMode(true);
-
-// 设置最大监听器数量
-eventBus.setMaxListeners(50);
-
-// 检查是否有监听器
-if (eventBus.hasListeners('entity:created')) {
- console.log('Has listeners for entity:created');
-}
-
-// 获取监听器数量
-const count = eventBus.getListenerCount('entity:created');
-console.log(`${count} listeners for entity:created`);
-```
-
-## 性能优化
-
-### 事件过滤和条件监听
-
-```typescript
-// 使用条件过滤减少不必要的事件处理
-eventBus.on(ECSEventType.ENTITY_CREATED, (data) => {
- // 只处理玩家实体
- if (data.entityTag === 'player') {
- handlePlayerCreated(data);
- }
-});
-
-// 更好的方式:使用具体的事件类型
-eventBus.on('entity:player:created', handlePlayerCreated);
-```
-
-### 内存管理
-
-```typescript
-class EventManager {
- private listeners: string[] = [];
-
- public setupListeners() {
- // 保存监听器ID以便清理
- this.listeners.push(
- eventBus.on('event1', this.handler1.bind(this)),
- eventBus.on('event2', this.handler2.bind(this))
- );
- }
-
- public cleanup() {
- // 清理所有监听器
- this.listeners.forEach(id => {
- eventBus.off('event1', id);
- eventBus.off('event2', id);
- });
- this.listeners.length = 0;
- }
-
- private handler1(data: any) { /* ... */ }
- private handler2(data: any) { /* ... */ }
-}
-```
-
-### 异步事件优化
-
-```typescript
-// 使用Promise.all并行处理多个异步事件
-const promises = [
- eventBus.emitAsync('save:player', playerData),
- eventBus.emitAsync('update:leaderboard', scoreData),
- eventBus.emitAsync('notify:friends', notificationData)
-];
-
-await Promise.all(promises);
-```
-
-## 最佳实践
-
-### 1. 事件命名规范
-
-```typescript
-// 推荐的事件命名格式:模块:对象:动作
-const EVENT_NAMES = {
- // 实体相关
- ENTITY_PLAYER_CREATED: 'entity:player:created',
- ENTITY_ENEMY_DESTROYED: 'entity:enemy:destroyed',
-
- // 游戏逻辑相关
- GAME_LEVEL_COMPLETED: 'game:level:completed',
- GAME_SCORE_UPDATED: 'game:score:updated',
-
- // UI相关
- UI_MENU_OPENED: 'ui:menu:opened',
- UI_BUTTON_CLICKED: 'ui:button:clicked'
-};
-```
-
-### 2. 类型安全
-
-```typescript
-// 定义强类型的事件数据接口
-interface GameEvents {
- 'player:levelup': { playerId: number; newLevel: number; experience: number };
- 'inventory:item:added': { itemId: string; quantity: number; playerId: number };
- 'combat:damage:dealt': { attackerId: number; targetId: number; damage: number };
-}
-
-// 创建类型安全的事件发射器
-class TypedEventBus {
- private eventBus = new EventBus();
-
- emit(eventType: K, data: GameEvents[K]) {
- this.eventBus.emit(eventType, data);
- }
-
- on(
- eventType: K,
- handler: (data: GameEvents[K]) => void
- ) {
- return this.eventBus.on(eventType, handler);
- }
-}
-```
-
-### 3. 错误处理
-
-```typescript
-// 在事件处理器中添加错误处理
-eventBus.on(ECSEventType.ENTITY_CREATED, (data) => {
- try {
- processEntityCreation(data);
- } catch (error) {
- console.error('Error processing entity creation:', error);
- // 发射错误事件
- eventBus.emit(ECSEventType.ERROR_OCCURRED, {
- timestamp: Date.now(),
- source: 'EntityCreationHandler',
- error: error.message,
- context: data
- });
- }
-});
-```
-
-### 4. 模块化事件管理
-
-```typescript
-// 为不同模块创建专门的事件管理器
-class PlayerEventManager {
- constructor(private eventBus: EventBus) {
- this.setupListeners();
- }
-
- private setupListeners() {
- this.eventBus.onEntityCreated(this.onPlayerCreated.bind(this));
- this.eventBus.on('player:levelup', this.onPlayerLevelUp.bind(this));
- this.eventBus.on('player:died', this.onPlayerDied.bind(this));
- }
-
- private onPlayerCreated(data: IEntityEventData) {
- if (data.entityTag === 'player') {
- // 处理玩家创建逻辑
- }
- }
-
- private onPlayerLevelUp(data: any) {
- // 处理玩家升级逻辑
- }
-
- private onPlayerDied(data: any) {
- // 处理玩家死亡逻辑
- }
-}
-```
-
-### 5. 与EntityManager集成
-
-```typescript
-import { EntityManager } from './ECS';
-
-// EntityManager会自动设置事件总线
-const entityManager = new EntityManager();
-
-// 获取事件总线实例
-const eventBus = entityManager.eventBus;
-
-// 监听自动发射的ECS事件
-eventBus.onEntityCreated((data) => {
- console.log('Entity created automatically:', data);
-});
-
-eventBus.onComponentAdded((data) => {
- console.log('Component added automatically:', data);
-});
-
-// 创建实体时会自动发射事件
-const entity = entityManager.createEntity('Player');
-
-// 添加组件时会自动发射事件
-entity.addComponent(new HealthComponent(100));
-```
-
-## 总结
-
-ECS框架的事件系统提供了:
-
-- **类型安全**:完整的TypeScript类型支持
-- **高性能**:批处理、缓存和优化机制
-- **易用性**:装饰器、预定义事件类型
-- **可扩展**:自定义事件类型和验证
-- **调试友好**:详细的统计信息和调试模式
-
-通过合理使用事件系统,可以实现松耦合的模块化架构,提高代码的可维护性和扩展性。
\ No newline at end of file
diff --git a/docs/examples/index.md b/docs/examples/index.md
new file mode 100644
index 00000000..270acc77
--- /dev/null
+++ b/docs/examples/index.md
@@ -0,0 +1,3 @@
+# 示例
+
+代码示例。
\ No newline at end of file
diff --git a/docs/getting-started.md b/docs/getting-started.md
deleted file mode 100644
index 08a1f2cc..00000000
--- a/docs/getting-started.md
+++ /dev/null
@@ -1,689 +0,0 @@
-# 快速入门
-
-本指南将帮助您快速上手 ECS Framework,这是一个专业级的实体组件系统框架,采用现代化架构设计,专为高性能游戏开发打造。
-
-## 安装
-
-```bash
-npm install @esengine/ecs-framework
-```
-
-## 更新机制说明
-
-ECS框架需要在游戏引擎的更新循环中调用,并传入deltaTime:
-
-```typescript
-// 统一的更新方式:让外部引擎传入deltaTime
-Core.update(deltaTime);
-```
-
-**不同平台的集成方式:**
-- **Laya引擎**:使用 `Laya.timer.delta / 1000`
-- **Cocos Creator**:使用组件的 `update(deltaTime)` 参数
-- **原生浏览器**:自己计算deltaTime
-- **Node.js服务器**:自己计算deltaTime
-
-**优势:**
-- 与引擎时间系统完全同步
-- 支持引擎的时间缩放和暂停功能
-- 更精确的时间控制
-- 统一的API,简化集成
-
-## Core配置
-
-### 基础配置
-
-ECS框架提供了灵活的配置选项来满足不同项目需求。框架采用融合设计,既支持传统的单Scene模式(向后兼容),也支持高级的多World/多Scene架构:
-
-```typescript
-import { Core, ICoreConfig } from '@esengine/ecs-framework';
-
-// 方式1:简化配置(向后兼容)
-Core.create(true); // 启用调试模式
-Core.create(false); // 发布模式
-Core.create(); // 默认调试模式
-
-// 方式2:详细配置(推荐)
-const config: ICoreConfig = {
- debug: true, // 启用调试模式
- enableEntitySystems: true, // 启用实体系统(默认true)
- debugConfig: { // 可选:远程调试配置
- enabled: true,
- websocketUrl: 'ws://localhost:8080',
- autoReconnect: true,
- updateInterval: 1000, // 调试数据更新间隔(毫秒)
- channels: { // 调试数据通道
- entities: true, // 实体信息
- systems: true, // 系统信息
- performance: true, // 性能数据
- components: true, // 组件信息
- scenes: true // 场景信息
- }
- }
-};
-
-const core = Core.create(config);
-```
-
-### 架构说明
-
-ECS框架支持两种使用模式:
-
-1. **单Scene模式(默认,向后兼容)**:
- ```typescript
- // 传统用法,无需任何修改
- const scene = new Scene();
- Core.setScene(scene);
- ```
-
-2. **多World模式(高级功能)**:
- ```typescript
- // 启用World管理器,支持多World/多Scene架构
- Core.enableWorldManager();
- const roomWorld = Core.getWorldManager().createWorld('Room_001');
- const battleScene = roomWorld.createScene('battle');
- ```
-
-**使用场景:**
-- **单Scene模式**:适合简单游戏、单机游戏、原型开发
-- **多World模式**:适合多人游戏服务器、复杂应用、需要场景隔离的项目
-
-> **详细了解World系统**:查看 [场景管理完整指南](scene-management-guide.md) 获取完整的多World架构示例和最佳实践
-
-### 调试功能
-
-ECS框架内置了强大的调试功能,支持运行时监控和远程调试:
-
-#### Cocos Creator专用调试插件
-
-** 对于Cocos Creator用户,我们提供了专门的可视化调试插件:**
-
-- **插件地址**:[cocos-ecs-framework 调试插件](https://store.cocos.com/app/detail/7823)
-- **插件版本**:v1.0.0
-- **支持版本**:Cocos Creator v3.0.0+
-- **支持平台**:Android | iOS | HTML5
-
-这个插件提供了完整的ECS可视化调试界面,包括实体查看器、组件编辑器、系统监控、性能分析等功能。
-
-#### 通用调试配置
-
-```typescript
-// 运行时启用调试
-Core.enableDebug({
- enabled: true,
- websocketUrl: 'ws://localhost:8080',
- autoReconnect: true,
- updateInterval: 500,
- channels: {
- entities: true,
- systems: true,
- performance: true,
- components: false, // 可以选择性禁用某些通道
- scenes: true
- }
-});
-
-// 获取调试数据
-const debugData = Core.getDebugData();
-console.log('当前实体数量:', debugData?.entities?.totalEntities);
-
-// 禁用调试
-Core.disableDebug();
-
-// 检查调试状态
-if (Core.isDebugEnabled) {
- console.log('调试模式已启用');
-}
-```
-
-### 生产环境配置建议
-
-```typescript
-// 开发环境 - Cocos Creator
-const devConfigForCocos: ICoreConfig = {
- debug: true,
- enableEntitySystems: true,
- debugConfig: {
- enabled: true,
- websocketUrl: 'ws://localhost:8080', // 连接Cocos插件
- autoReconnect: true,
- updateInterval: 1000,
- channels: {
- entities: true,
- systems: true,
- performance: true,
- components: true,
- scenes: true
- }
- }
-};
-
-// 开发环境 - 其他平台
-const devConfig: ICoreConfig = {
- debug: true,
- enableEntitySystems: true,
- debugConfig: {
- enabled: true,
- websocketUrl: 'ws://localhost:8080',
- autoReconnect: true,
- updateInterval: 1000,
- channels: {
- entities: true,
- systems: true,
- performance: true,
- components: true,
- scenes: true
- }
- }
-};
-
-// 生产环境
-const prodConfig: ICoreConfig = {
- debug: false, // 关闭调试以提升性能
- enableEntitySystems: true,
- // debugConfig 可以省略或设为 undefined
-};
-
-const isDevelopment = process.env.NODE_ENV === 'development';
-Core.create(isDevelopment ? devConfig : prodConfig);
-```
-
-** 调试功能说明:**
-- **Cocos Creator**:推荐使用[官方调试插件](https://store.cocos.com/app/detail/7823)获得最佳调试体验
-- **其他平台**:可以通过WebSocket连接自定义调试工具
-- **生产环境**:建议关闭调试功能以获得最佳性能
-
-## 平台集成
-
-### Laya引擎
-
-```typescript
-import { Scene as LayaScene } from "laya/display/Scene";
-import { Core, Scene as ECSScene, EntityManager, EntitySystem } from '@esengine/ecs-framework';
-
-class LayaECSGame extends LayaScene {
- private ecsScene: ECSScene;
- private entityManager: EntityManager;
-
- constructor() {
- super();
-
- // 初始化ECS框架(简化方式)
- Core.create(true); // 启用调试模式
- // 完整配置示例: Core.create({ debug: true, enableEntitySystems: true, debugConfig: {...} })
-
- this.ecsScene = new ECSScene();
- this.ecsScene.name = "LayaGameScene";
- Core.setScene(this.ecsScene);
-
- this.entityManager = new EntityManager();
- this.setupSystems();
- }
-
- onAwake(): void {
- super.onAwake();
- // 使用Laya的帧循环更新ECS
- Laya.timer.frameLoop(1, this, this.updateECS);
- }
-
- onDestroy(): void {
- Laya.timer.clear(this, this.updateECS);
- super.onDestroy();
- }
-
- private updateECS(): void {
- // 使用Laya的deltaTime更新ECS
- const deltaTime = Laya.timer.delta / 1000; // 转换为秒
- Core.update(deltaTime);
- }
-
- private setupSystems(): void {
- this.ecsScene.addEntityProcessor(new LayaRenderSystem(this));
- this.ecsScene.addEntityProcessor(new MovementSystem());
- }
-}
-
-// Laya渲染系统
-class LayaRenderSystem extends EntitySystem {
- private layaScene: LayaScene;
-
- constructor(layaScene: LayaScene) {
- super(Matcher.all(PositionComponent, SpriteComponent));
- this.layaScene = layaScene;
- }
-
- protected override process(entities: Entity[]): void {
- entities.forEach(entity => {
- const pos = entity.getComponent(PositionComponent)!;
- const sprite = entity.getComponent(SpriteComponent)!;
-
- if (sprite.layaSprite) {
- sprite.layaSprite.x = pos.x;
- sprite.layaSprite.y = pos.y;
- }
- });
- }
-}
-
-// 使用方法
-Laya.Scene.open("GameScene.scene", false, null, null, LayaECSGame);
-```
-
-### Cocos Creator
-
-```typescript
-import { Component as CocosComponent, _decorator, Node } from 'cc';
-import { Core, Scene as ECSScene, EntityManager, EntitySystem } from '@esengine/ecs-framework';
-
-const { ccclass, property } = _decorator;
-
-@ccclass('ECSGameManager')
-export class ECSGameManager extends CocosComponent {
- private ecsScene: ECSScene;
- private entityManager: EntityManager;
-
- start() {
- // 初始化ECS框架(简化方式)
- Core.create(true); // 启用调试模式
- // 完整配置示例: Core.create({ debug: true, enableEntitySystems: true, debugConfig: {...} })
-
- this.ecsScene = new ECSScene();
- this.ecsScene.name = "CocosGameScene";
- Core.setScene(this.ecsScene);
-
- this.entityManager = new EntityManager();
- this.setupSystems();
- }
-
- update(deltaTime: number) {
- // 使用Cocos Creator的deltaTime更新ECS
- Core.update(deltaTime);
- }
-
- onDestroy() {
- if (this.ecsScene) {
- this.ecsScene.onDestroy();
- }
- }
-
- private setupSystems(): void {
- this.ecsScene.addEntityProcessor(new CocosRenderSystem(this.node));
- this.ecsScene.addEntityProcessor(new MovementSystem());
- }
-
- public getEntityManager(): EntityManager {
- return this.entityManager;
- }
-}
-
-// Cocos渲染系统
-class CocosRenderSystem extends EntitySystem {
- private rootNode: Node;
-
- constructor(rootNode: Node) {
- super(Matcher.all(PositionComponent, SpriteComponent));
- this.rootNode = rootNode;
- }
-
- protected override process(entities: Entity[]): void {
- entities.forEach(entity => {
- const pos = entity.getComponent(PositionComponent)!;
- const sprite = entity.getComponent(SpriteComponent)!;
-
- if (sprite.cocosNode) {
- sprite.cocosNode.setPosition(pos.x, pos.y);
- }
- });
- }
-}
-
-// 将ECSGameManager脚本挂载到场景根节点
-```
-
-** Cocos Creator调试提示:**
-为了获得最佳的ECS调试体验,建议安装我们的专用调试插件:
-- 插件地址:[https://store.cocos.com/app/detail/7823](https://store.cocos.com/app/detail/7823)
-- 支持Cocos Creator v3.0.0+
-- 提供实体查看器、组件编辑器、系统监控等功能
-
-### Node.js后端
-
-```typescript
-import { Core, Scene, EntityManager, EntitySystem, Time, World } from '@esengine/ecs-framework';
-
-class ServerGameManager {
- private scene: Scene;
- private entityManager: EntityManager;
- private isRunning: boolean = false;
- private tickRate: number = 60; // 60 TPS
- private lastUpdate: number = Date.now();
-
- constructor() {
- // 初始化ECS框架(简化方式)
- Core.create(true); // 启用调试模式
- // 完整配置示例: Core.create({ debug: true, enableEntitySystems: true, debugConfig: {...} })
-
- // 单Scene模式(简单场景)
- this.scene = new Scene();
- this.scene.name = "ServerScene";
- Core.setScene(this.scene);
-
- this.entityManager = new EntityManager();
- this.setupSystems();
- }
-
- public start(): void {
- this.isRunning = true;
- console.log(`游戏服务器启动,TPS: ${this.tickRate}`);
- this.gameLoop();
- }
-
- public stop(): void {
- this.isRunning = false;
- }
-
- private gameLoop(): void {
- if (!this.isRunning) return;
-
- const now = Date.now();
- const deltaTime = (now - this.lastUpdate) / 1000;
- this.lastUpdate = now;
-
- // 使用计算出的deltaTime更新ECS
- Core.update(deltaTime);
-
- const frameTime = 1000 / this.tickRate;
- const processingTime = Date.now() - now;
- const delay = Math.max(0, frameTime - processingTime);
-
- setTimeout(() => this.gameLoop(), delay);
- }
-
- private setupSystems(): void {
- this.scene.addEntityProcessor(new ServerMovementSystem());
- this.scene.addEntityProcessor(new NetworkSyncSystem());
- this.scene.addEntityProcessor(new AISystem());
- }
-
- public handlePlayerInput(playerId: string, input: any): void {
- const playerEntity = this.findPlayerEntity(playerId);
- if (playerEntity) {
- const inputComp = playerEntity.getComponent(InputComponent);
- if (inputComp) {
- inputComp.updateInput(input);
- }
- }
- }
-
- public getWorldState(): any {
- const entities = this.entityManager
- .query()
- .withAll(PositionComponent, NetworkComponent)
- .execute();
-
- return entities.map(entity => ({
- id: entity.id,
- position: entity.getComponent(PositionComponent),
- }));
- }
-
- private findPlayerEntity(playerId: string): Entity | null {
- const players = this.entityManager
- .query()
- .withAll(PlayerComponent)
- .execute();
-
- return players.find(player =>
- player.getComponent(PlayerComponent).playerId === playerId
- ) || null;
- }
-}
-
-// 启动服务器
-const server = new ServerGameManager();
-server.start();
-```
-
-> **多房间游戏服务器示例**:查看 [场景管理完整指南](scene-management-guide.md#world多场景管理) 了解如何使用多World架构实现复杂的多房间游戏服务器
-
-### 原生浏览器
-
-```typescript
-import { Core, Scene, EntityManager, EntitySystem } from '@esengine/ecs-framework';
-
-class BrowserGame {
- private scene: Scene;
- private entityManager: EntityManager;
-
- constructor() {
- // 初始化ECS框架(简化方式)
- Core.create(true); // 启用调试模式
- // 完整配置示例: Core.create({ debug: true, enableEntitySystems: true, debugConfig: {...} })
-
- this.scene = new Scene();
- this.scene.name = "BrowserScene";
- Core.setScene(this.scene);
-
- this.entityManager = new EntityManager();
- this.setupSystems();
- }
-
- public start(): void {
- this.createEntities();
- this.gameLoop();
- }
-
- private gameLoop(): void {
- let lastTime = 0;
- const update = (currentTime: number) => {
- // 计算deltaTime并更新ECS(原生浏览器环境)
- const deltaTime = lastTime > 0 ? (currentTime - lastTime) / 1000 : 0.016;
- lastTime = currentTime;
- Core.update(deltaTime);
- requestAnimationFrame(update);
- };
- requestAnimationFrame(update);
- }
-
- private setupSystems(): void {
- this.scene.addEntityProcessor(new MovementSystem());
- this.scene.addEntityProcessor(new RenderSystem());
- }
-
- private createEntities(): void {
- const player = this.entityManager.createEntity("Player");
- player.addComponent(new PositionComponent(400, 300));
- player.addComponent(new VelocityComponent(0, 0));
- }
-}
-
-const game = new BrowserGame();
-game.start();
-```
-
-## 基础组件定义
-
-```typescript
-import { Component } from '@esengine/ecs-framework';
-
-// 位置组件
-class PositionComponent extends Component {
- public x: number = 0;
- public y: number = 0;
-
- constructor(...args: unknown[]) {
- super();
- const [x = 0, y = 0] = args as [number?, number?];
- this.x = x;
- this.y = y;
- }
-
- public reset() {
- this.x = 0;
- this.y = 0;
- }
-}
-
-// 速度组件
-class VelocityComponent extends Component {
- public x: number = 0;
- public y: number = 0;
-
- constructor(...args: unknown[]) {
- super();
- const [x = 0, y = 0] = args as [number?, number?];
- this.x = x;
- this.y = y;
- }
-
- public reset() {
- this.x = 0;
- this.y = 0;
- }
-}
-
-// 生命值组件
-class HealthComponent extends Component {
- public maxHealth: number = 100;
- public currentHealth: number = 100;
-
- constructor(...args: unknown[]) {
- super();
- const [maxHealth = 100] = args as [number?];
- this.maxHealth = maxHealth;
- this.currentHealth = maxHealth;
- }
-
- public reset() {
- this.maxHealth = 100;
- this.currentHealth = 100;
- }
-
- public takeDamage(damage: number): void {
- this.currentHealth = Math.max(0, this.currentHealth - damage);
- }
-
- public heal(amount: number): void {
- this.currentHealth = Math.min(this.maxHealth, this.currentHealth + amount);
- }
-
- public isDead(): boolean {
- return this.currentHealth <= 0;
- }
-}
-```
-
-## 基础系统创建
-
-```typescript
-import { EntitySystem, Entity, Matcher, Time } from '@esengine/ecs-framework';
-
-class MovementSystem extends EntitySystem {
- constructor() {
- super(Matcher.all(PositionComponent, VelocityComponent));
- }
-
- protected override process(entities: Entity[]): void {
- entities.forEach(entity => {
- const position = entity.getComponent(PositionComponent)!;
- const velocity = entity.getComponent(VelocityComponent)!;
-
- position.x += velocity.x * Time.deltaTime;
- position.y += velocity.y * Time.deltaTime;
- });
- }
-}
-
-class HealthSystem extends EntitySystem {
- constructor() {
- super(Matcher.all(HealthComponent));
- }
-
- protected override process(entities: Entity[]): void {
- entities.forEach(entity => {
- const health = entity.getComponent(HealthComponent)!;
- if (health.currentHealth <= 0) {
- entity.destroy();
- }
- });
- }
-}
-```
-
-## 实体管理
-
-```typescript
-// 创建实体
-const player = entityManager.createEntity("Player");
-player.addComponent(new PositionComponent(100, 100));
-player.addComponent(new VelocityComponent(5, 0));
-player.addComponent(new HealthComponent(100));
-
-// 批量创建实体
-const enemies = scene.createEntities(50, "Enemy");
-enemies.forEach(enemy => {
- enemy.addComponent(new PositionComponent(Math.random() * 800, Math.random() * 600));
- enemy.addComponent(new HealthComponent(50));
-});
-
-// 查询实体 - 推荐方式
-const movingEntities = entityManager
- .query()
- .withAll(PositionComponent, VelocityComponent)
- .execute();
-
-// 简单查询方式
-const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);
-const taggedEntities = entityManager.getEntitiesByTag(2);
-```
-
-## 事件系统
-
-推荐使用Scene的事件系统或EntityManager的事件系统:
-
-```typescript
-// 使用EntityManager的事件系统(推荐)
-const eventBus = entityManager.eventBus;
-
-// 监听ECS事件
-eventBus.onEntityCreated((data) => {
- console.log(`实体创建: ${data.entityName}`);
-});
-
-eventBus.onComponentAdded((data) => {
- console.log(`组件添加: ${data.componentType}`);
-});
-
-// 发射自定义事件
-eventBus.emit('player:died', { player: entity, score: 1000 });
-
-// 使用装饰器自动注册事件监听器
-import { EventHandler } from '@esengine/ecs-framework';
-
-class GameSystem {
- @EventHandler('player:died')
- onPlayerDied(data: { player: Entity; score: number }) {
- console.log(`玩家死亡,得分: ${data.score}`);
- }
-}
-```
-
-## 性能监控
-
-```typescript
-// 获取场景统计
-const sceneStats = scene.getStats();
-console.log('实体数量:', sceneStats.entityCount);
-console.log('系统数量:', sceneStats.processorCount);
-
-// 获取查询统计
-const queryStats = scene.querySystem.getStats();
-console.log('查询统计:', queryStats);
-```
-
-## 下一步
-
-- [EntityManager 使用指南](entity-manager-example.md) - 详细了解实体管理器的高级功能
-- [性能优化指南](performance-optimization.md) - 深入了解三大性能优化系统
-- [核心概念](core-concepts.md) - 深入了解 ECS 架构和设计原理
-- [查询系统使用指南](query-system-usage.md) - 学习高性能查询系统的详细用法
\ No newline at end of file
diff --git a/docs/guide/component.md b/docs/guide/component.md
new file mode 100644
index 00000000..3a74edd5
--- /dev/null
+++ b/docs/guide/component.md
@@ -0,0 +1,359 @@
+# 组件系统
+
+在 ECS 架构中,组件(Component)是数据和行为的载体。组件定义了实体具有的属性和功能,是 ECS 架构的核心构建块。
+
+## 基本概念
+
+组件是继承自 `Component` 抽象基类的具体类,用于:
+- 存储实体的数据(如位置、速度、健康值等)
+- 定义与数据相关的行为方法
+- 提供生命周期回调钩子
+- 支持序列化和调试
+
+## 创建组件
+
+### 基础组件定义
+
+```typescript
+import { Component, ECSComponent } from '@esengine/ecs-framework';
+
+@ECSComponent('Position')
+class Position extends Component {
+ x: number = 0;
+ y: number = 0;
+
+ constructor(x: number = 0, y: number = 0) {
+ super();
+ this.x = x;
+ this.y = y;
+ }
+}
+
+@ECSComponent('Health')
+class Health extends Component {
+ current: number;
+ max: number;
+
+ constructor(max: number = 100) {
+ super();
+ this.max = max;
+ this.current = max;
+ }
+
+ // 组件可以包含行为方法
+ takeDamage(damage: number): void {
+ this.current = Math.max(0, this.current - damage);
+ }
+
+ heal(amount: number): void {
+ this.current = Math.min(this.max, this.current + amount);
+ }
+
+ isDead(): boolean {
+ return this.current <= 0;
+ }
+}
+```
+
+### 组件装饰器
+
+**必须使用 `@ECSComponent` 装饰器**,这确保了:
+- 组件在代码混淆后仍能正确识别
+- 提供稳定的类型名称用于序列化和调试
+- 框架能正确管理组件注册
+
+```typescript
+// ✅ 正确的用法
+@ECSComponent('Velocity')
+class Velocity extends Component {
+ dx: number = 0;
+ dy: number = 0;
+}
+
+// ❌ 错误的用法 - 没有装饰器
+class BadComponent extends Component {
+ // 这样定义的组件可能在生产环境出现问题
+}
+```
+
+## 组件生命周期
+
+组件提供了生命周期钩子,可以重写来执行特定的逻辑:
+
+```typescript
+@ECSComponent('ExampleComponent')
+class ExampleComponent extends Component {
+ private resource: SomeResource | null = null;
+
+ /**
+ * 组件被添加到实体时调用
+ * 用于初始化资源、建立引用等
+ */
+ onAddedToEntity(): void {
+ console.log(`组件 ${this.constructor.name} 被添加到实体 ${this.entity.name}`);
+ this.resource = new SomeResource();
+ }
+
+ /**
+ * 组件从实体移除时调用
+ * 用于清理资源、断开引用等
+ */
+ onRemovedFromEntity(): void {
+ console.log(`组件 ${this.constructor.name} 从实体 ${this.entity.name} 移除`);
+ if (this.resource) {
+ this.resource.cleanup();
+ this.resource = null;
+ }
+ }
+}
+```
+
+## 访问实体
+
+组件可以通过 `this.entity` 访问其所属的实体:
+
+```typescript
+@ECSComponent('Damage')
+class Damage extends Component {
+ damage: number;
+
+ constructor(damage: number) {
+ super();
+ this.damage = damage;
+ }
+
+ // 在组件方法中访问实体和其他组件
+ applyDamage(): void {
+ const health = this.entity.getComponent(Health);
+ if (health) {
+ health.takeDamage(this.damage);
+
+ // 如果生命值为0,销毁实体
+ if (health.isDead()) {
+ this.entity.destroy();
+ }
+ }
+ }
+}
+```
+
+## 组件属性
+
+每个组件都有一些内置属性:
+
+```typescript
+@ECSComponent('ExampleComponent')
+class ExampleComponent extends Component {
+ someData: string = "example";
+
+ showComponentInfo(): void {
+ console.log(`组件ID: ${this.id}`); // 唯一的组件ID
+ console.log(`所属实体: ${this.entity.name}`); // 所属实体引用
+ }
+}
+```
+
+
+## 复杂组件示例
+
+### 状态机组件
+
+```typescript
+enum EntityState {
+ Idle,
+ Moving,
+ Attacking,
+ Dead
+}
+
+@ECSComponent('StateMachine')
+class StateMachine extends Component {
+ private _currentState: EntityState = EntityState.Idle;
+ private _previousState: EntityState = EntityState.Idle;
+ private _stateTimer: number = 0;
+
+ get currentState(): EntityState {
+ return this._currentState;
+ }
+
+ get previousState(): EntityState {
+ return this._previousState;
+ }
+
+ get stateTimer(): number {
+ return this._stateTimer;
+ }
+
+ changeState(newState: EntityState): void {
+ if (this._currentState !== newState) {
+ this._previousState = this._currentState;
+ this._currentState = newState;
+ this._stateTimer = 0;
+ }
+ }
+
+ updateTimer(deltaTime: number): void {
+ this._stateTimer += deltaTime;
+ }
+
+ isInState(state: EntityState): boolean {
+ return this._currentState === state;
+ }
+}
+```
+
+### 配置数据组件
+
+```typescript
+interface WeaponData {
+ damage: number;
+ range: number;
+ fireRate: number;
+ ammo: number;
+}
+
+@ECSComponent('WeaponConfig')
+class WeaponConfig extends Component {
+ data: WeaponData;
+
+ constructor(weaponData: WeaponData) {
+ super();
+ this.data = { ...weaponData }; // 深拷贝避免共享引用
+ }
+
+ // 提供便捷的访问方法
+ getDamage(): number {
+ return this.data.damage;
+ }
+
+ canFire(): boolean {
+ return this.data.ammo > 0;
+ }
+
+ consumeAmmo(): boolean {
+ if (this.data.ammo > 0) {
+ this.data.ammo--;
+ return true;
+ }
+ return false;
+ }
+}
+```
+
+## 最佳实践
+
+### 1. 保持组件简单
+
+```typescript
+// ✅ 好的组件设计 - 单一职责
+@ECSComponent('Position')
+class Position extends Component {
+ x: number = 0;
+ y: number = 0;
+}
+
+@ECSComponent('Velocity')
+class Velocity extends Component {
+ dx: number = 0;
+ dy: number = 0;
+}
+
+// ❌ 避免的组件设计 - 职责过多
+@ECSComponent('GameObject')
+class GameObject extends Component {
+ x: number;
+ y: number;
+ dx: number;
+ dy: number;
+ health: number;
+ damage: number;
+ sprite: string;
+ // 太多不相关的属性
+}
+```
+
+### 2. 使用构造函数初始化
+
+```typescript
+@ECSComponent('Transform')
+class Transform extends Component {
+ x: number;
+ y: number;
+ rotation: number;
+ scale: number;
+
+ constructor(x = 0, y = 0, rotation = 0, scale = 1) {
+ super();
+ this.x = x;
+ this.y = y;
+ this.rotation = rotation;
+ this.scale = scale;
+ }
+}
+```
+
+### 3. 明确的类型定义
+
+```typescript
+interface InventoryItem {
+ id: string;
+ name: string;
+ quantity: number;
+ type: 'weapon' | 'consumable' | 'misc';
+}
+
+@ECSComponent('Inventory')
+class Inventory extends Component {
+ items: InventoryItem[] = [];
+ maxSlots: number;
+
+ constructor(maxSlots: number = 20) {
+ super();
+ this.maxSlots = maxSlots;
+ }
+
+ addItem(item: InventoryItem): boolean {
+ if (this.items.length < this.maxSlots) {
+ this.items.push(item);
+ return true;
+ }
+ return false;
+ }
+
+ removeItem(itemId: string): InventoryItem | null {
+ const index = this.items.findIndex(item => item.id === itemId);
+ if (index !== -1) {
+ return this.items.splice(index, 1)[0];
+ }
+ return null;
+ }
+}
+```
+
+### 4. 避免在组件中存储实体引用
+
+```typescript
+// ❌ 避免:在组件中存储其他实体的引用
+@ECSComponent('BadFollower')
+class BadFollower extends Component {
+ target: Entity; // 直接引用可能导致内存泄漏
+}
+
+// ✅ 推荐:存储实体ID,通过场景查找
+@ECSComponent('Follower')
+class Follower extends Component {
+ targetId: number;
+ followDistance: number = 50;
+
+ constructor(targetId: number) {
+ super();
+ this.targetId = targetId;
+ }
+
+ getTarget(): Entity | null {
+ return this.entity.scene?.findEntityById(this.targetId) || null;
+ }
+}
+```
+
+组件是 ECS 架构的数据载体,正确设计组件能让你的游戏代码更模块化、可维护和高性能。
\ No newline at end of file
diff --git a/docs/guide/entity.md b/docs/guide/entity.md
new file mode 100644
index 00000000..d0188c3a
--- /dev/null
+++ b/docs/guide/entity.md
@@ -0,0 +1,288 @@
+# 实体类
+
+在 ECS 架构中,实体(Entity)是游戏世界中的基本对象。实体本身不包含游戏逻辑或数据,它只是一个容器,用来组合不同的组件来实现各种功能。
+
+## 基本概念
+
+实体是一个轻量级的对象,主要用于:
+- 作为组件的容器
+- 提供唯一标识(ID)
+- 管理组件的生命周期
+
+## 创建实体
+
+**重要提示:实体必须通过场景创建,不支持手动创建!**
+
+实体必须通过场景的 `createEntity()` 方法来创建,这样才能确保:
+- 实体被正确添加到场景的实体管理系统中
+- 实体被添加到查询系统中,供系统使用
+- 实体获得正确的场景引用
+- 触发相关的生命周期事件
+
+```typescript
+// 正确的方式:通过场景创建实体
+const player = scene.createEntity("Player");
+
+// ❌ 错误的方式:手动创建实体
+// const entity = new Entity("MyEntity", 1); // 这样创建的实体系统无法管理
+```
+
+## 添加组件
+
+实体通过添加组件来获得功能:
+
+```typescript
+import { Component, ECSComponent } from '@esengine/ecs-framework';
+
+// 定义位置组件
+@ECSComponent('Position')
+class Position extends Component {
+ x: number = 0;
+ y: number = 0;
+
+ constructor(x: number = 0, y: number = 0) {
+ super();
+ this.x = x;
+ this.y = y;
+ }
+}
+
+// 定义健康组件
+@ECSComponent('Health')
+class Health extends Component {
+ current: number = 100;
+ max: number = 100;
+
+ constructor(max: number = 100) {
+ super();
+ this.max = max;
+ this.current = max;
+ }
+}
+
+// 给实体添加组件
+const player = scene.createEntity("Player");
+player.addComponent(new Position(100, 200));
+player.addComponent(new Health(150));
+```
+
+## 获取组件
+
+```typescript
+// 获取组件(传入组件类,不是实例)
+const position = player.getComponent(Position); // 返回 Position | null
+const health = player.getComponent(Health); // 返回 Health | null
+
+// 检查组件是否存在
+if (position) {
+ console.log(`玩家位置: x=${position.x}, y=${position.y}`);
+}
+
+// 检查是否有某个组件
+if (player.hasComponent(Position)) {
+ console.log("玩家有位置组件");
+}
+
+// 获取所有组件实例(直接访问 components 属性)
+const allComponents = player.components; // Component[]
+
+// 获取指定类型的所有组件(支持同类型多组件)
+const allHealthComponents = player.getComponents(Health); // Health[]
+
+// 获取或创建组件(如果不存在则自动创建)
+const position = player.getOrCreateComponent(Position, 0, 0); // 传入构造参数
+const health = player.getOrCreateComponent(Health, 100); // 如果存在则返回现有的,不存在则创建新的
+```
+
+## 移除组件
+
+```typescript
+// 方式1:通过组件类型移除
+const removedHealth = player.removeComponentByType(Health);
+if (removedHealth) {
+ console.log("健康组件已被移除");
+}
+
+// 方式2:通过组件实例移除
+const healthComponent = player.getComponent(Health);
+if (healthComponent) {
+ player.removeComponent(healthComponent);
+}
+
+// 批量移除多种组件类型
+const removedComponents = player.removeComponentsByTypes([Position, Health]);
+
+// 检查组件是否被移除
+if (!player.hasComponent(Health)) {
+ console.log("健康组件已被移除");
+}
+```
+
+## 实体查找
+
+场景提供了多种方式来查找实体:
+
+### 通过名称查找
+
+```typescript
+// 查找单个实体
+const player = scene.findEntity("Player");
+// 或使用别名方法
+const player2 = scene.getEntityByName("Player");
+
+if (player) {
+ console.log("找到玩家实体");
+}
+```
+
+### 通过 ID 查找
+
+```typescript
+// 通过实体 ID 查找
+const entity = scene.findEntityById(123);
+```
+
+### 通过标签查找
+
+实体支持标签系统,用于快速分类和查找:
+
+```typescript
+// 设置标签
+player.tag = 1; // 玩家标签
+enemy.tag = 2; // 敌人标签
+
+// 通过标签查找所有相关实体
+const players = scene.findEntitiesByTag(1);
+const enemies = scene.findEntitiesByTag(2);
+// 或使用别名方法
+const allPlayers = scene.getEntitiesByTag(1);
+```
+
+
+## 实体生命周期
+
+```typescript
+// 销毁实体
+player.destroy();
+
+// 检查实体是否已销毁
+if (player.isDestroyed) {
+ console.log("实体已被销毁");
+}
+```
+
+## 实体事件
+
+实体的组件变化会触发事件:
+
+```typescript
+// 监听组件添加事件
+scene.eventSystem.on('component:added', (data) => {
+ console.log('组件已添加:', data);
+});
+
+// 监听实体创建事件
+scene.eventSystem.on('entity:created', (data) => {
+ console.log('实体已创建:', data.entityName);
+});
+```
+
+## 性能优化
+
+
+### 批量创建实体
+
+框架提供了高性能的批量创建方法:
+
+```typescript
+// 批量创建 100 个子弹实体(高性能版本)
+const bullets = scene.createEntities(100, "Bullet");
+
+// 为每个子弹添加组件
+bullets.forEach((bullet, index) => {
+ bullet.addComponent(new Position(Math.random() * 800, Math.random() * 600));
+ bullet.addComponent(new Velocity(Math.random() * 100 - 50, Math.random() * 100 - 50));
+});
+```
+
+`createEntities()` 方法会:
+- 批量分配实体 ID
+- 批量添加到实体列表
+- 优化查询系统更新
+- 减少系统缓存清理次数
+
+## 最佳实践
+
+### 1. 合理的组件粒度
+
+```typescript
+// 好的做法:功能单一的组件
+@ECSComponent('Position')
+class Position extends Component {
+ x: number = 0;
+ y: number = 0;
+}
+
+@ECSComponent('Velocity')
+class Velocity extends Component {
+ dx: number = 0;
+ dy: number = 0;
+}
+
+// 避免:功能过于复杂的组件
+@ECSComponent('Player')
+class Player extends Component {
+ // 避免在一个组件中包含太多不相关的属性
+ x: number;
+ y: number;
+ health: number;
+ inventory: Item[];
+ skills: Skill[];
+}
+```
+
+### 2. 使用装饰器
+
+始终使用 `@ECSComponent` 装饰器:
+
+```typescript
+@ECSComponent('Transform')
+class Transform extends Component {
+ // 组件实现
+}
+```
+
+### 3. 合理命名
+
+```typescript
+// 清晰的实体命名
+const mainCharacter = scene.createEntity("MainCharacter");
+const enemy1 = scene.createEntity("Goblin_001");
+const collectible = scene.createEntity("HealthPotion");
+```
+
+### 4. 及时清理
+
+```typescript
+// 不再需要的实体应该及时销毁
+if (enemy.getComponent(Health).current <= 0) {
+ enemy.destroy();
+}
+```
+
+## 调试实体
+
+框架提供了调试功能来帮助开发:
+
+```typescript
+// 获取实体调试信息
+const debugInfo = entity.getDebugInfo();
+console.log('实体信息:', debugInfo);
+
+// 列出实体的所有组件
+entity.components.forEach(component => {
+ console.log('组件:', component.constructor.name);
+});
+```
+
+实体是 ECS 架构的核心概念之一,理解如何正确使用实体将帮助你构建高效、可维护的游戏代码。
\ No newline at end of file
diff --git a/docs/guide/event-system.md b/docs/guide/event-system.md
new file mode 100644
index 00000000..bbed1688
--- /dev/null
+++ b/docs/guide/event-system.md
@@ -0,0 +1,595 @@
+# 事件系统
+
+ECS 框架内置了强大的类型安全事件系统,支持同步/异步事件、优先级、批处理等高级功能。事件系统是实现组件间通信、系统间协作的核心机制。
+
+## 基本概念
+
+事件系统提供了发布-订阅模式的实现,包含以下核心概念:
+- **事件发布者**:发射事件的对象
+- **事件监听者**:监听并处理特定事件的对象
+- **事件类型**:字符串标识,用于区分不同类型的事件
+- **事件数据**:事件携带的相关信息
+
+## 事件系统架构
+
+框架提供了两层事件系统:
+
+1. **TypeSafeEventSystem** - 底层高性能事件系统
+2. **EventBus** - 上层增强事件总线,提供更多便利功能
+
+## 基本使用
+
+### 在场景中使用事件系统
+
+每个场景都有内置的事件系统:
+
+```typescript
+class GameScene extends Scene {
+ protected initialize(): void {
+ // 监听事件
+ this.eventSystem.on('player_died', this.onPlayerDied.bind(this));
+ this.eventSystem.on('enemy_spawned', this.onEnemySpawned.bind(this));
+ this.eventSystem.on('score_changed', this.onScoreChanged.bind(this));
+ }
+
+ private onPlayerDied(data: { player: Entity, cause: string }): void {
+ console.log(`玩家死亡,原因: ${data.cause}`);
+ // 处理玩家死亡逻辑
+ }
+
+ private onEnemySpawned(data: { enemy: Entity, position: { x: number, y: number } }): void {
+ console.log('敌人生成于:', data.position);
+ // 处理敌人生成逻辑
+ }
+
+ private onScoreChanged(data: { newScore: number, oldScore: number }): void {
+ console.log(`分数变化: ${data.oldScore} -> ${data.newScore}`);
+ // 更新UI显示
+ }
+
+ // 在系统中发射事件
+ someGameLogic(): void {
+ // 发射同步事件
+ this.eventSystem.emitSync('score_changed', {
+ newScore: 1000,
+ oldScore: 800
+ });
+ }
+}
+```
+
+### 在系统中使用事件
+
+系统可以方便地监听和发送事件:
+
+```typescript
+@ECSSystem('Combat')
+class CombatSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(Health, Combat));
+ }
+
+ protected onInitialize(): void {
+ // 使用系统提供的事件监听方法(自动清理)
+ this.addEventListener('player_attack', this.onPlayerAttack.bind(this));
+ this.addEventListener('enemy_death', this.onEnemyDeath.bind(this));
+ }
+
+ private onPlayerAttack(data: { damage: number, target: Entity }): void {
+ // 处理玩家攻击事件
+ const health = data.target.getComponent(Health);
+ if (health) {
+ health.current -= data.damage;
+
+ if (health.current <= 0) {
+ // 发送敌人死亡事件
+ this.scene?.eventSystem.emitSync('enemy_death', {
+ enemy: data.target,
+ killer: 'player'
+ });
+ }
+ }
+ }
+
+ private onEnemyDeath(data: { enemy: Entity, killer: string }): void {
+ // 处理敌人死亡
+ data.enemy.destroy();
+
+ // 发送经验奖励事件
+ this.scene?.eventSystem.emitSync('experience_gained', {
+ amount: 100,
+ source: 'enemy_kill'
+ });
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ const combat = entity.getComponent(Combat);
+ if (combat && combat.shouldAttack()) {
+ // 发射攻击事件
+ this.scene?.eventSystem.emitSync('player_attack', {
+ damage: combat.damage,
+ target: combat.target
+ });
+ }
+ }
+ }
+}
+```
+
+## 高级功能
+
+### 一次性监听器
+
+```typescript
+class GameScene extends Scene {
+ protected initialize(): void {
+ // 只监听一次的事件
+ this.eventSystem.once('game_start', this.onGameStart.bind(this));
+
+ // 或者使用配置对象
+ this.eventSystem.on('level_complete', this.onLevelComplete.bind(this), {
+ once: true // 只执行一次
+ });
+ }
+
+ private onGameStart(): void {
+ console.log('游戏开始!');
+ // 这个方法只会被调用一次
+ }
+
+ private onLevelComplete(): void {
+ console.log('关卡完成!');
+ // 这个方法也只会被调用一次
+ }
+}
+```
+
+### 优先级控制
+
+```typescript
+class GameScene extends Scene {
+ protected initialize(): void {
+ // 高优先级监听器先执行
+ this.eventSystem.on('damage_dealt', this.onDamageDealt.bind(this), {
+ priority: 100 // 高优先级
+ });
+
+ // 普通优先级
+ this.eventSystem.on('damage_dealt', this.updateUI.bind(this), {
+ priority: 0 // 默认优先级
+ });
+
+ // 低优先级最后执行
+ this.eventSystem.on('damage_dealt', this.logDamage.bind(this), {
+ priority: -100 // 低优先级
+ });
+ }
+
+ private onDamageDealt(data: any): void {
+ // 最先执行 - 处理核心游戏逻辑
+ }
+
+ private updateUI(data: any): void {
+ // 中等优先级 - 更新界面
+ }
+
+ private logDamage(data: any): void {
+ // 最后执行 - 记录日志
+ }
+}
+```
+
+### 异步事件处理
+
+```typescript
+class GameScene extends Scene {
+ protected initialize(): void {
+ // 监听异步事件
+ this.eventSystem.onAsync('save_game', this.onSaveGame.bind(this));
+ this.eventSystem.onAsync('load_data', this.onLoadData.bind(this));
+ }
+
+ private async onSaveGame(data: { saveSlot: number }): Promise {
+ console.log(`开始保存游戏到槽位 ${data.saveSlot}`);
+
+ // 模拟异步保存操作
+ await this.saveGameData(data.saveSlot);
+
+ console.log('游戏保存完成');
+ }
+
+ private async onLoadData(data: { url: string }): Promise {
+ try {
+ const response = await fetch(data.url);
+ const gameData = await response.json();
+ // 处理加载的数据
+ } catch (error) {
+ console.error('数据加载失败:', error);
+ }
+ }
+
+ private async saveGameData(slot: number): Promise {
+ // 模拟保存操作
+ return new Promise(resolve => setTimeout(resolve, 1000));
+ }
+
+ // 发射异步事件
+ public async triggerSave(): Promise {
+ // 使用 emit 而不是 emitSync 来触发异步监听器
+ await this.eventSystem.emit('save_game', { saveSlot: 1 });
+ console.log('所有异步保存操作完成');
+ }
+}
+```
+
+### 事件统计和调试
+
+```typescript
+class GameScene extends Scene {
+ protected initialize(): void {
+ this.eventSystem.on('debug_event', this.onDebugEvent.bind(this));
+ }
+
+ private onDebugEvent(): void {
+ // 处理调试事件
+ }
+
+ public showEventStats(): void {
+ // 获取特定事件的统计信息
+ const stats = this.eventSystem.getStats('debug_event') as any;
+ if (stats) {
+ console.log('事件统计:');
+ console.log(`- 事件类型: ${stats.eventType}`);
+ console.log(`- 监听器数量: ${stats.listenerCount}`);
+ console.log(`- 触发次数: ${stats.triggerCount}`);
+ console.log(`- 平均执行时间: ${stats.averageExecutionTime.toFixed(2)}ms`);
+ }
+
+ // 获取所有事件统计
+ const allStats = this.eventSystem.getStats() as Map;
+ console.log(`总共有 ${allStats.size} 种事件类型`);
+ }
+
+ public resetEventStats(): void {
+ // 重置特定事件的统计
+ this.eventSystem.resetStats('debug_event');
+
+ // 或重置所有统计
+ this.eventSystem.resetStats();
+ }
+}
+```
+
+## 全局事件总线
+
+对于跨场景的事件通信,可以使用全局事件总线:
+
+```typescript
+import { GlobalEventBus } from '@esengine/ecs-framework';
+
+class GameManager {
+ private eventBus = GlobalEventBus.getInstance();
+
+ constructor() {
+ this.setupGlobalEvents();
+ }
+
+ private setupGlobalEvents(): void {
+ // 监听全局事件
+ this.eventBus.on('player_level_up', this.onPlayerLevelUp.bind(this));
+ this.eventBus.on('achievement_unlocked', this.onAchievementUnlocked.bind(this));
+ this.eventBus.onAsync('upload_score', this.onUploadScore.bind(this));
+ }
+
+ private onPlayerLevelUp(data: { level: number, experience: number }): void {
+ console.log(`玩家升级到 ${data.level} 级!`);
+ // 处理全局升级逻辑
+ }
+
+ private onAchievementUnlocked(data: { achievementId: string, name: string }): void {
+ console.log(`解锁成就: ${data.name}`);
+ // 显示成就通知
+ }
+
+ private async onUploadScore(data: { score: number, playerName: string }): Promise {
+ // 异步上传分数到服务器
+ try {
+ await this.uploadToServer(data);
+ console.log('分数上传成功');
+ } catch (error) {
+ console.error('分数上传失败:', error);
+ }
+ }
+
+ public triggerGlobalEvent(): void {
+ // 发射全局事件
+ this.eventBus.emit('player_level_up', {
+ level: 10,
+ experience: 2500
+ });
+ }
+
+ private async uploadToServer(data: any): Promise {
+ // 模拟服务器上传
+ return new Promise(resolve => setTimeout(resolve, 2000));
+ }
+}
+```
+
+## 事件装饰器
+
+使用装饰器自动注册事件监听器:
+
+```typescript
+import { EventHandler, AsyncEventHandler } from '@esengine/ecs-framework';
+
+class PlayerController {
+ constructor() {
+ // 自动调用事件监听器注册
+ this.initEventListeners();
+ }
+
+ @EventHandler('player_input')
+ private onPlayerInput(data: { action: string, value: number }): void {
+ console.log(`玩家输入: ${data.action} = ${data.value}`);
+ // 处理玩家输入
+ }
+
+ @EventHandler('player_attack', { priority: 100 })
+ private onPlayerAttack(data: { damage: number, target: string }): void {
+ console.log(`玩家攻击 ${data.target},造成 ${data.damage} 伤害`);
+ // 处理攻击逻辑
+ }
+
+ @AsyncEventHandler('save_progress')
+ private async onSaveProgress(data: { checkpointId: string }): Promise {
+ console.log(`保存进度到检查点: ${data.checkpointId}`);
+ // 异步保存进度
+ await this.saveToCloud(data.checkpointId);
+ }
+
+ @EventHandler('game_over', { once: true })
+ private onGameOver(): void {
+ console.log('游戏结束!');
+ // 这个方法只会被调用一次
+ }
+
+ private async saveToCloud(checkpointId: string): Promise {
+ // 模拟云端保存
+ return new Promise(resolve => setTimeout(resolve, 1500));
+ }
+}
+```
+
+## 批处理事件
+
+对于高频事件,可以使用批处理来提升性能:
+
+```typescript
+class MovementSystem extends EntitySystem {
+ protected onInitialize(): void {
+ // 设置位置更新事件的批处理
+ this.scene?.eventSystem.setBatchConfig('position_updated', {
+ batchSize: 50, // 批处理大小
+ delay: 16, // 延迟时间(毫秒)
+ enabled: true
+ });
+
+ // 监听批处理事件
+ this.addEventListener('position_updated:batch', this.onPositionBatch.bind(this));
+ }
+
+ private onPositionBatch(batchData: any): void {
+ console.log(`批处理位置更新,共 ${batchData.count} 个事件`);
+
+ // 批量处理所有位置更新
+ for (const event of batchData.events) {
+ this.updateMinimap(event.entityId, event.position);
+ }
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ const position = entity.getComponent(Position);
+ if (position && position.hasChanged) {
+ // 发射高频位置更新事件(会被批处理)
+ this.scene?.eventSystem.emitSync('position_updated', {
+ entityId: entity.id,
+ position: { x: position.x, y: position.y }
+ });
+ }
+ }
+ }
+
+ private updateMinimap(entityId: number, position: { x: number, y: number }): void {
+ // 更新小地图显示
+ }
+
+ public flushPositionUpdates(): void {
+ // 立即处理所有待处理的位置更新
+ this.scene?.eventSystem.flushBatch('position_updated');
+ }
+}
+```
+
+## 预定义的 ECS 事件
+
+框架提供了一些预定义的 ECS 生命周期事件:
+
+```typescript
+import { ECSEventType } from '@esengine/ecs-framework';
+
+class ECSMonitor {
+ private eventBus = GlobalEventBus.getInstance();
+
+ constructor() {
+ this.setupECSEvents();
+ }
+
+ private setupECSEvents(): void {
+ // 监听实体生命周期事件
+ this.eventBus.onEntityCreated(this.onEntityCreated.bind(this));
+ this.eventBus.on(ECSEventType.ENTITY_DESTROYED, this.onEntityDestroyed.bind(this));
+
+ // 监听组件生命周期事件
+ this.eventBus.onComponentAdded(this.onComponentAdded.bind(this));
+ this.eventBus.on(ECSEventType.COMPONENT_REMOVED, this.onComponentRemoved.bind(this));
+
+ // 监听系统事件
+ this.eventBus.on(ECSEventType.SYSTEM_ADDED, this.onSystemAdded.bind(this));
+ this.eventBus.onSystemError(this.onSystemError.bind(this));
+
+ // 监听性能警告
+ this.eventBus.onPerformanceWarning(this.onPerformanceWarning.bind(this));
+ }
+
+ private onEntityCreated(data: any): void {
+ console.log(`实体创建: ${data.entityName} (ID: ${data.entity.id})`);
+ }
+
+ private onEntityDestroyed(data: any): void {
+ console.log(`实体销毁: ${data.entity.name} (ID: ${data.entity.id})`);
+ }
+
+ private onComponentAdded(data: any): void {
+ console.log(`组件添加: ${data.componentType} 到实体 ${data.entity.name}`);
+ }
+
+ private onComponentRemoved(data: any): void {
+ console.log(`组件移除: ${data.componentType} 从实体 ${data.entity.name}`);
+ }
+
+ private onSystemAdded(data: any): void {
+ console.log(`系统添加: ${data.systemName}`);
+ }
+
+ private onSystemError(data: any): void {
+ console.error(`系统错误: ${data.systemName}`, data.error);
+ }
+
+ private onPerformanceWarning(data: any): void {
+ console.warn(`性能警告: ${data.systemName} 执行时间过长 (${data.executionTime}ms)`);
+ }
+}
+```
+
+## 最佳实践
+
+### 1. 事件命名规范
+
+```typescript
+// ✅ 好的事件命名
+this.eventSystem.emitSync('player:health_changed', data);
+this.eventSystem.emitSync('enemy:spawned', data);
+this.eventSystem.emitSync('ui:score_updated', data);
+this.eventSystem.emitSync('game:paused', data);
+
+// ❌ 避免的事件命名
+this.eventSystem.emitSync('event1', data);
+this.eventSystem.emitSync('update', data);
+this.eventSystem.emitSync('change', data);
+```
+
+### 2. 类型安全的事件数据
+
+```typescript
+// 定义事件数据接口
+interface PlayerHealthChangedEvent {
+ entityId: number;
+ oldHealth: number;
+ newHealth: number;
+ cause: 'damage' | 'healing';
+}
+
+interface EnemySpawnedEvent {
+ enemyType: string;
+ position: { x: number, y: number };
+ level: number;
+}
+
+// 使用类型安全的事件
+class HealthSystem extends EntitySystem {
+ private onHealthChanged(data: PlayerHealthChangedEvent): void {
+ // TypeScript 会提供完整的类型检查
+ console.log(`生命值变化: ${data.oldHealth} -> ${data.newHealth}`);
+ }
+}
+```
+
+### 3. 避免事件循环
+
+```typescript
+// ❌ 避免:可能导致无限循环
+class BadEventHandler {
+ private onScoreChanged(data: any): void {
+ // 在处理分数变化时又触发分数变化事件
+ this.scene?.eventSystem.emitSync('score_changed', newData); // 危险!
+ }
+}
+
+// ✅ 正确:使用不同的事件类型或条件判断
+class GoodEventHandler {
+ private isProcessingScore = false;
+
+ private onScoreChanged(data: any): void {
+ if (this.isProcessingScore) return; // 防止循环
+
+ this.isProcessingScore = true;
+ // 处理分数变化
+ this.updateUI(data);
+ this.isProcessingScore = false;
+ }
+}
+```
+
+### 4. 及时清理事件监听器
+
+```typescript
+class TemporaryUI {
+ private listenerId: string;
+
+ constructor(scene: Scene) {
+ // 保存监听器ID用于后续清理
+ this.listenerId = scene.eventSystem.on('ui_update', this.onUpdate.bind(this));
+ }
+
+ private onUpdate(data: any): void {
+ // 处理UI更新
+ }
+
+ public destroy(): void {
+ // 清理事件监听器
+ if (this.listenerId) {
+ scene.eventSystem.off('ui_update', this.listenerId);
+ }
+ }
+}
+```
+
+### 5. 性能考虑
+
+```typescript
+class OptimizedEventHandler {
+ protected onInitialize(): void {
+ // 对于高频事件,使用批处理
+ this.scene?.eventSystem.setBatchConfig('movement_update', {
+ batchSize: 100,
+ delay: 16,
+ enabled: true
+ });
+
+ // 对于低频但重要的事件,使用高优先级
+ this.addEventListener('game_over', this.onGameOver.bind(this), {
+ priority: 1000
+ });
+
+ // 对于一次性事件,使用 once
+ this.addEventListener('level_start', this.onLevelStart.bind(this), {
+ once: true
+ });
+ }
+}
+```
+
+事件系统是 ECS 框架中实现松耦合架构的重要工具,正确使用事件系统能让你的游戏代码更加模块化、可维护和可扩展。
\ No newline at end of file
diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md
new file mode 100644
index 00000000..ac5a8320
--- /dev/null
+++ b/docs/guide/getting-started.md
@@ -0,0 +1,394 @@
+# 快速开始
+
+本指南将帮助你快速上手 ECS Framework,从安装到创建第一个 ECS 应用。
+
+## 安装
+
+### NPM 安装
+
+```bash
+# 使用 npm
+npm install @esengine/ecs-framework
+```
+
+## 初始化 Core
+
+### 基础初始化
+
+ECS Framework 的核心是 `Core` 类,它是一个单例模式,负责管理整个框架的生命周期。
+
+```typescript
+import { Core } from '@esengine/ecs-framework'
+
+// 方式1:使用配置对象(推荐)
+const core = Core.create({
+ debug: true, // 启用调试模式,提供详细的日志和性能监控
+ enableEntitySystems: true, // 启用实体系统,这是ECS的核心功能
+ debugConfig: { // 可选:高级调试配置
+ enabled: false, // 是否启用WebSocket调试服务器
+ websocketUrl: 'ws://localhost:8080',
+ debugFrameRate: 30, // 调试数据发送帧率
+ channels: {
+ entities: true,
+ systems: true,
+ performance: true,
+ components: true,
+ scenes: true
+ }
+ }
+});
+
+// 方式2:简化创建(向后兼容)
+const core = Core.create(true); // 等同于 { debug: true, enableEntitySystems: true }
+
+// 方式3:生产环境配置
+const core = Core.create({
+ debug: false, // 生产环境关闭调试
+ enableEntitySystems: true
+});
+```
+
+### Core 配置详解
+
+```typescript
+interface ICoreConfig {
+ /** 是否启用调试模式 - 影响日志级别和性能监控 */
+ debug?: boolean;
+
+ /** 是否启用实体系统 - 核心ECS功能开关 */
+ enableEntitySystems?: boolean;
+
+ /** 高级调试配置 - 用于开发工具集成 */
+ debugConfig?: {
+ enabled: boolean; // 是否启用调试服务器
+ websocketUrl: string; // WebSocket服务器地址
+ autoReconnect?: boolean; // 是否自动重连
+ debugFrameRate?: 60 | 30 | 15; // 调试数据发送帧率
+ channels: { // 数据通道配置
+ entities: boolean; // 实体数据
+ systems: boolean; // 系统数据
+ performance: boolean; // 性能数据
+ components: boolean; // 组件数据
+ scenes: boolean; // 场景数据
+ };
+ };
+}
+```
+
+### Core 实例管理
+
+Core 采用单例模式,创建后可以通过静态属性获取:
+
+```typescript
+// 创建实例
+const core = Core.create(true);
+
+// 获取已创建的实例
+const instance = Core.Instance; // 获取当前实例,如果未创建则为 null
+```
+
+### 游戏循环集成
+
+**重要**: 在创建实体和系统之前,你需要先了解如何将 ECS Framework 集成到你的游戏引擎中。
+
+`Core.update(deltaTime)` 是整个框架的心跳,必须在游戏引擎的每一帧中调用。它负责:
+- 更新框架内置的 Time 类
+- 更新所有全局管理器(定时器、对象池等)
+- 更新所有场景中的实体系统
+- 处理实体的创建和销毁
+- 收集性能数据(调试模式下)
+
+各引擎集成示例请参考:[与游戏引擎集成](#与游戏引擎集成)
+
+## 创建第一个 ECS 应用
+
+### 1. 定义组件
+
+组件是纯数据容器,用于存储实体的状态:
+
+```typescript
+import { Component, ECSComponent } from '@esengine/ecs-framework'
+
+// 位置组件
+@ECSComponent('Position')
+class Position extends Component {
+ x: number = 0
+ y: number = 0
+
+ constructor(x: number = 0, y: number = 0) {
+ super()
+ this.x = x
+ this.y = y
+ }
+}
+
+// 速度组件
+@ECSComponent('Velocity')
+class Velocity extends Component {
+ dx: number = 0
+ dy: number = 0
+
+ constructor(dx: number = 0, dy: number = 0) {
+ super()
+ this.dx = dx
+ this.dy = dy
+ }
+}
+
+// 渲染组件
+@ECSComponent('Sprite')
+class Sprite extends Component {
+ texture: string = ''
+ width: number = 32
+ height: number = 32
+
+ constructor(texture: string, width: number = 32, height: number = 32) {
+ super()
+ this.texture = texture
+ this.width = width
+ this.height = height
+ }
+}
+```
+
+### 2. 创建实体系统
+
+系统包含游戏逻辑,处理具有特定组件的实体。ECS Framework 提供了基于 Matcher 的实体过滤机制:
+
+```typescript
+import { EntitySystem, Matcher, Time, ECSSystem } from '@esengine/ecs-framework'
+
+// 移动系统 - 处理位置和速度
+@ECSSystem('MovementSystem')
+class MovementSystem extends EntitySystem {
+
+ constructor() {
+ // 使用 Matcher 定义要处理的实体:必须同时拥有 Position 和 Velocity 组件
+ super(Matcher.empty().all(Position, Velocity))
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ // process 方法接收所有匹配的实体
+ for (const entity of entities) {
+ const position = entity.getComponent(Position)!
+ const velocity = entity.getComponent(Velocity)!
+
+ // 更新位置(使用框架的Time类)
+ position.x += velocity.dx * Time.deltaTime
+ position.y += velocity.dy * Time.deltaTime
+
+ // 边界检查示例
+ if (position.x < 0) position.x = 0
+ if (position.y < 0) position.y = 0
+ }
+ }
+}
+
+// 渲染系统 - 处理可见对象
+@ECSSystem('RenderSystem')
+class RenderSystem extends EntitySystem {
+
+ constructor() {
+ // 必须有 Position 和 Sprite,可选 Velocity(用于方向判断)
+ super(Matcher.empty().all(Position, Sprite).any(Velocity))
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ const position = entity.getComponent(Position)!
+ const sprite = entity.getComponent(Sprite)!
+ const velocity = entity.getComponent(Velocity) // 可能为 null
+
+ // 根据速度方向翻转精灵(可选逻辑)
+ let flipX = false
+ if (velocity && velocity.dx < 0) {
+ flipX = true
+ }
+
+ // 渲染逻辑(这里是伪代码)
+ this.drawSprite(sprite.texture, position.x, position.y, sprite.width, sprite.height, flipX)
+ }
+ }
+
+ private drawSprite(texture: string, x: number, y: number, width: number, height: number, flipX: boolean = false) {
+ // 实际的渲染实现将取决于你使用的游戏引擎
+ const direction = flipX ? '←' : '→'
+ console.log(`渲染 ${texture} 在位置 (${x.toFixed(1)}, ${y.toFixed(1)}) 方向: ${direction}`)
+ }
+}
+```
+
+
+### 3. 创建场景
+
+推荐继承 Scene 类来创建自定义场景:
+
+```typescript
+import { Scene } from '@esengine/ecs-framework'
+
+// 推荐:继承Scene创建自定义场景
+class GameScene extends Scene {
+
+ initialize(): void {
+ // 场景初始化逻辑
+ this.name = "MainScene";
+
+ // 添加系统到场景
+ this.addSystem(new MovementSystem());
+ this.addSystem(new RenderSystem());
+ }
+
+ onStart(): void {
+ // 场景开始运行时的逻辑
+ console.log("游戏场景已启动");
+ }
+
+ unload(): void {
+ // 场景卸载时的清理逻辑
+ console.log("游戏场景已卸载");
+ }
+}
+
+// 创建并设置场景
+const gameScene = new GameScene();
+Core.setScene(gameScene);
+```
+
+### 4. 创建实体
+
+```typescript
+// 创建玩家实体
+const player = gameScene.createEntity("Player");
+player.addComponent(new Position(100, 100));
+player.addComponent(new Velocity(50, 30)); // 每秒移动 50 像素(x方向),30 像素(y方向)
+player.addComponent(new Sprite("player.png", 64, 64));
+```
+
+## World 概念
+
+World 是 Scene 的容器,用于管理多个独立的游戏世界。这种设计特别适用于:
+- 多人游戏房间(每个房间一个 World)
+- 不同的游戏模式
+- 独立的模拟环境
+
+### 基本用法
+
+```typescript
+import { World, Scene } from '@esengine/ecs-framework'
+
+// 创建游戏房间的World
+const roomWorld = new World({ name: 'Room_001' });
+
+// 在World中创建多个Scene
+class GameScene extends Scene {
+ initialize(): void {
+ this.name = "GamePlay";
+ this.addSystem(new MovementSystem());
+ this.addSystem(new RenderSystem());
+ }
+}
+
+class UIScene extends Scene {
+ initialize(): void {
+ this.name = "UI";
+ // UI相关系统
+ }
+}
+
+// 添加Scene到World
+const gameScene = roomWorld.createScene('game', new GameScene());
+const uiScene = roomWorld.createScene('ui', new UIScene());
+
+// 激活Scene
+roomWorld.setSceneActive('game', true);
+roomWorld.setSceneActive('ui', true);
+
+// 启动World
+roomWorld.start();
+```
+
+### World 生命周期
+
+World 提供了完整的生命周期管理:
+- `start()`: 启动 World 和所有全局系统
+- `updateGlobalSystems()`: 更新全局系统(由 Core.update() 调用)
+- `updateScenes()`: 更新所有激活的 Scene(由 Core.update() 调用)
+- `stop()`: 停止 World
+- `destroy()`: 销毁 World 和所有资源
+
+## 与游戏引擎集成
+
+### Laya 引擎集成
+
+```typescript
+import { Stage } from "laya/display/Stage"
+import { Stat } from "laya/utils/Stat"
+import { Laya } from "Laya"
+
+// 初始化 Laya
+Laya.init(800, 600).then(() => {
+ // 初始化 ECS
+ const core = Core.create(true)
+
+ // 设置场景...
+
+ // 启动游戏循环
+ Laya.timer.frameLoop(1, this, () => {
+ const deltaTime = Laya.timer.delta / 1000 // 转换为秒
+ Core.update(deltaTime)
+ })
+})
+```
+
+### Cocos Creator 集成
+
+```typescript
+import { Component, _decorator } from 'cc'
+
+const { ccclass } = _decorator
+
+@ccclass('ECSGameManager')
+export class ECSGameManager extends Component {
+
+ onLoad() {
+ // 初始化 ECS
+ const core = Core.create(true)
+
+ // 设置场景...
+ }
+
+ update(deltaTime: number) {
+ // 更新 ECS
+ Core.update(deltaTime)
+ }
+}
+```
+
+
+## 下一步
+
+现在你已经成功创建了第一个 ECS 应用!接下来可以:
+
+- 查看完整的 [API 文档](/api/README)
+- 探索更多[实际应用示例](/examples/)
+
+## 常见问题
+
+### 为什么我的系统没有执行?
+
+确保:
+1. 系统已添加到场景:`this.addSystem(system)` (在 Scene 的 initialize 方法中)
+2. 场景已设置为当前场景:`Core.setScene(scene)`
+3. 游戏循环在调用:`Core.update(deltaTime)`
+
+### 如何调试 ECS 应用?
+
+启用调试模式:
+
+```typescript
+Core.create({ debug: true })
+
+// 获取调试数据
+const debugData = Core.getDebugData()
+console.log(debugData)
+```
\ No newline at end of file
diff --git a/docs/guide/index.md b/docs/guide/index.md
new file mode 100644
index 00000000..78796a66
--- /dev/null
+++ b/docs/guide/index.md
@@ -0,0 +1,26 @@
+# 指南
+
+欢迎使用 ECS Framework 指南。这里将详细介绍框架的各个核心概念和使用方法。
+
+## 核心概念
+
+### [实体类 (Entity)](./entity.md)
+了解 ECS 架构的基础 - 实体类的使用方法、生命周期管理和最佳实践。
+
+### [组件系统 (Component)](./component.md)
+学习如何创建和使用组件,实现游戏功能的模块化设计。
+
+### [系统架构 (System)](./system.md)
+掌握系统的编写方法,实现游戏逻辑的处理。
+
+### [场景管理 (Scene)](./scene.md)
+了解场景的生命周期、系统管理和实体容器功能。
+
+### [事件系统 (Event)](./event-system.md)
+掌握类型安全的事件系统,实现组件间通信和系统协作。
+
+### [时间和定时器 (Time)](./time-and-timers.md)
+学习时间管理和定时器系统,实现游戏逻辑的精确时间控制。
+
+### [日志系统 (Logger)](./logging.md)
+掌握分级日志系统,用于调试、监控和错误追踪。
\ No newline at end of file
diff --git a/docs/guide/logging.md b/docs/guide/logging.md
new file mode 100644
index 00000000..495bab91
--- /dev/null
+++ b/docs/guide/logging.md
@@ -0,0 +1,550 @@
+# 日志系统
+
+ECS 框架提供了功能强大的分级日志系统,支持多种日志级别、颜色输出、自定义前缀和灵活的配置选项。日志系统可以帮助开发者调试代码和监控应用运行状态。
+
+## 基本概念
+
+日志系统包含以下核心概念:
+- **日志级别**:Debug < Info < Warn < Error < Fatal < None
+- **日志器**:具名的日志输出器,每个模块可以有自己的日志器
+- **日志管理器**:全局管理所有日志器的单例
+- **颜色配置**:支持控制台颜色输出
+
+## 日志级别
+
+```typescript
+import { LogLevel } from '@esengine/ecs-framework';
+
+// 日志级别从低到高
+LogLevel.Debug // 0 - 调试信息
+LogLevel.Info // 1 - 一般信息
+LogLevel.Warn // 2 - 警告信息
+LogLevel.Error // 3 - 错误信息
+LogLevel.Fatal // 4 - 致命错误
+LogLevel.None // 5 - 不输出任何日志
+```
+
+## 基本使用
+
+### 使用默认日志器
+
+```typescript
+import { Logger } from '@esengine/ecs-framework';
+
+class GameSystem extends EntitySystem {
+ protected process(entities: readonly Entity[]): void {
+ // 输出不同级别的日志
+ Logger.debug('处理实体数量:', entities.length);
+ Logger.info('系统正常运行');
+ Logger.warn('检测到性能问题');
+ Logger.error('处理过程中发生错误', new Error('示例错误'));
+ Logger.fatal('致命错误,系统即将停止');
+ }
+}
+```
+
+### 创建命名日志器
+
+```typescript
+import { createLogger } from '@esengine/ecs-framework';
+
+class MovementSystem extends EntitySystem {
+ private logger = createLogger('MovementSystem');
+
+ protected process(entities: readonly Entity[]): void {
+ this.logger.info(`处理 ${entities.length} 个移动实体`);
+
+ for (const entity of entities) {
+ const position = entity.getComponent(Position);
+ const velocity = entity.getComponent(Velocity);
+
+ if (position && velocity) {
+ position.x += velocity.dx * Time.deltaTime;
+ position.y += velocity.dy * Time.deltaTime;
+
+ this.logger.debug(`实体 ${entity.id} 移动到位置 (${position.x}, ${position.y})`);
+ }
+ }
+ }
+
+ protected onAdded(entity: Entity): void {
+ this.logger.info(`实体 ${entity.name} 加入移动系统`);
+ }
+
+ protected onRemoved(entity: Entity): void {
+ this.logger.warn(`实体 ${entity.name} 离开移动系统`);
+ }
+}
+```
+
+### 系统内置日志器
+
+框架的各个系统都有自己的日志器:
+
+```typescript
+// 框架内部使用示例
+class Scene {
+ private static readonly _logger = createLogger('Scene');
+
+ public addSystem(system: EntitySystem): void {
+ Scene._logger.info(`添加系统: ${system.systemName}`);
+ // 系统添加逻辑
+ }
+
+ public removeSystem(system: EntitySystem): void {
+ Scene._logger.warn(`移除系统: ${system.systemName}`);
+ // 系统移除逻辑
+ }
+}
+```
+
+## 日志配置
+
+### 设置全局日志级别
+
+```typescript
+import { setGlobalLogLevel, LogLevel } from '@esengine/ecs-framework';
+
+// 在开发环境显示所有日志
+setGlobalLogLevel(LogLevel.Debug);
+
+// 在生产环境只显示警告及以上级别
+setGlobalLogLevel(LogLevel.Warn);
+
+// 完全禁用日志输出
+setGlobalLogLevel(LogLevel.None);
+```
+
+### 创建自定义配置的日志器
+
+```typescript
+import { ConsoleLogger, LogLevel } from '@esengine/ecs-framework';
+
+class CustomLoggerExample {
+ private debugLogger: ConsoleLogger;
+ private productionLogger: ConsoleLogger;
+
+ constructor() {
+ // 开发环境日志器
+ this.debugLogger = new ConsoleLogger({
+ level: LogLevel.Debug,
+ enableTimestamp: true,
+ enableColors: true,
+ prefix: 'DEV'
+ });
+
+ // 生产环境日志器
+ this.productionLogger = new ConsoleLogger({
+ level: LogLevel.Error,
+ enableTimestamp: true,
+ enableColors: false,
+ prefix: 'PROD'
+ });
+ }
+
+ public logDevelopmentInfo(): void {
+ this.debugLogger.debug('这是调试信息');
+ this.debugLogger.info('开发环境信息');
+ }
+
+ public logProductionError(): void {
+ this.productionLogger.error('生产环境错误');
+ this.productionLogger.fatal('致命错误');
+ }
+}
+```
+
+## 颜色配置
+
+### 使用预定义颜色
+
+```typescript
+import { Colors, setLoggerColors } from '@esengine/ecs-framework';
+
+// 自定义颜色方案
+setLoggerColors({
+ debug: Colors.BRIGHT_BLACK,
+ info: Colors.BLUE,
+ warn: Colors.YELLOW,
+ error: Colors.RED,
+ fatal: Colors.BRIGHT_RED
+});
+```
+
+### 完整颜色示例
+
+```typescript
+import { LoggerManager, Colors, LogLevel } from '@esengine/ecs-framework';
+
+class ColorLoggerDemo {
+ private logger = createLogger('ColorDemo');
+
+ constructor() {
+ // 设置自定义颜色
+ const manager = LoggerManager.getInstance();
+ manager.setGlobalColors({
+ debug: Colors.CYAN,
+ info: Colors.GREEN,
+ warn: Colors.YELLOW,
+ error: Colors.RED,
+ fatal: `${Colors.BOLD}${Colors.BRIGHT_RED}`
+ });
+ }
+
+ public demonstrateColors(): void {
+ this.logger.debug('这是蓝绿色的调试信息');
+ this.logger.info('这是绿色的信息');
+ this.logger.warn('这是黄色的警告');
+ this.logger.error('这是红色的错误');
+ this.logger.fatal('这是加粗的亮红色致命错误');
+ }
+
+ public resetToDefaults(): void {
+ // 重置为默认颜色
+ LoggerManager.getInstance().resetColors();
+ }
+}
+```
+
+## 高级功能
+
+### 分层日志器
+
+```typescript
+import { LoggerManager } from '@esengine/ecs-framework';
+
+class HierarchicalLoggingExample {
+ private systemLogger = createLogger('GameSystems');
+ private movementLogger: ILogger;
+ private renderLogger: ILogger;
+
+ constructor() {
+ const manager = LoggerManager.getInstance();
+
+ // 创建子日志器
+ this.movementLogger = manager.createChildLogger('GameSystems', 'Movement');
+ this.renderLogger = manager.createChildLogger('GameSystems', 'Render');
+ }
+
+ public demonstrateHierarchy(): void {
+ this.systemLogger.info('游戏系统启动');
+
+ // 子日志器会显示完整路径:[GameSystems.Movement]
+ this.movementLogger.debug('移动系统初始化');
+
+ // 子日志器会显示完整路径:[GameSystems.Render]
+ this.renderLogger.info('渲染系统启动');
+ }
+}
+```
+
+### 自定义输出
+
+```typescript
+import { ConsoleLogger, LogLevel } from '@esengine/ecs-framework';
+
+class CustomOutputLogger {
+ private fileLogger: ConsoleLogger;
+ private networkLogger: ConsoleLogger;
+
+ constructor() {
+ // 输出到文件的日志器(模拟)
+ this.fileLogger = new ConsoleLogger({
+ level: LogLevel.Info,
+ output: (level: LogLevel, message: string) => {
+ this.writeToFile(LogLevel[level], message);
+ }
+ });
+
+ // 发送到网络的日志器(模拟)
+ this.networkLogger = new ConsoleLogger({
+ level: LogLevel.Error,
+ output: (level: LogLevel, message: string) => {
+ this.sendToServer(LogLevel[level], message);
+ }
+ });
+ }
+
+ private writeToFile(level: string, message: string): void {
+ // 模拟文件写入
+ console.log(`[FILE] ${level}: ${message}`);
+ }
+
+ private sendToServer(level: string, message: string): void {
+ // 模拟网络发送
+ console.log(`[NETWORK] ${level}: ${message}`);
+ }
+
+ public logToFile(message: string): void {
+ this.fileLogger.info(message);
+ }
+
+ public logCriticalError(error: Error): void {
+ this.networkLogger.error('Critical error occurred', error);
+ }
+}
+```
+
+## 实际应用示例
+
+### 游戏系统日志
+
+```typescript
+class GameWithLogging {
+ private gameLogger = createLogger('Game');
+ private performanceLogger = createLogger('Performance');
+ private networkLogger = createLogger('Network');
+
+ constructor() {
+ // 在开发环境启用详细日志
+ if (process.env.NODE_ENV === 'development') {
+ setGlobalLogLevel(LogLevel.Debug);
+ } else {
+ setGlobalLogLevel(LogLevel.Warn);
+ }
+ }
+
+ public startGame(): void {
+ this.gameLogger.info('游戏开始启动');
+
+ try {
+ this.initializeSystems();
+ this.loadResources();
+ this.startGameLoop();
+
+ this.gameLogger.info('游戏启动成功');
+ } catch (error) {
+ this.gameLogger.fatal('游戏启动失败', error);
+ throw error;
+ }
+ }
+
+ private initializeSystems(): void {
+ this.gameLogger.debug('初始化游戏系统');
+
+ const systems = [
+ new MovementSystem(),
+ new RenderSystem(),
+ new PhysicsSystem()
+ ];
+
+ for (const system of systems) {
+ const startTime = performance.now();
+
+ // 初始化系统
+ system.initialize();
+
+ const endTime = performance.now();
+ this.performanceLogger.debug(
+ `系统 ${system.systemName} 初始化耗时: ${(endTime - startTime).toFixed(2)}ms`
+ );
+ }
+ }
+
+ private loadResources(): void {
+ this.gameLogger.info('开始加载资源');
+
+ const resources = ['textures', 'sounds', 'data'];
+ for (const resource of resources) {
+ try {
+ this.loadResource(resource);
+ this.gameLogger.debug(`资源 ${resource} 加载成功`);
+ } catch (error) {
+ this.gameLogger.error(`资源 ${resource} 加载失败`, error);
+ }
+ }
+ }
+
+ private startGameLoop(): void {
+ this.gameLogger.info('启动游戏循环');
+ this.performanceLogger.debug('开始性能监控');
+ }
+
+ private loadResource(name: string): void {
+ // 模拟资源加载
+ if (Math.random() < 0.1) {
+ throw new Error(`Failed to load ${name}`);
+ }
+ }
+
+ public handleNetworkEvent(event: string, data: any): void {
+ this.networkLogger.info(`网络事件: ${event}`, data);
+
+ if (event === 'connection_lost') {
+ this.networkLogger.warn('网络连接丢失,尝试重连');
+ } else if (event === 'sync_error') {
+ this.networkLogger.error('数据同步错误', data);
+ }
+ }
+}
+```
+
+### 错误追踪和调试
+
+```typescript
+class ErrorTrackingSystem extends EntitySystem {
+ private logger = createLogger('ErrorTracker');
+ private errorCounts = new Map();
+
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ try {
+ this.processEntity(entity);
+ } catch (error) {
+ this.handleError(entity, error as Error);
+ }
+ }
+ }
+
+ private processEntity(entity: Entity): void {
+ // 模拟可能出错的实体处理
+ if (Math.random() < 0.01) { // 1% 概率出错
+ throw new Error(`Processing error for entity ${entity.id}`);
+ }
+
+ this.logger.debug(`成功处理实体 ${entity.id}`);
+ }
+
+ private handleError(entity: Entity, error: Error): void {
+ const errorKey = error.message;
+ const count = this.errorCounts.get(errorKey) || 0;
+ this.errorCounts.set(errorKey, count + 1);
+
+ this.logger.error(
+ `实体 ${entity.id} 处理失败 (第${count + 1}次): ${error.message}`,
+ {
+ entityId: entity.id,
+ entityName: entity.name,
+ componentCount: entity.components.length,
+ errorStack: error.stack
+ }
+ );
+
+ // 如果同一类型错误发生太多次,升级为警告
+ if (count >= 5) {
+ this.logger.warn(`错误 "${errorKey}" 已发生 ${count + 1} 次,可能需要关注`);
+ }
+
+ // 如果错误次数过多,升级为致命错误
+ if (count >= 20) {
+ this.logger.fatal(`错误 "${errorKey}" 发生次数过多,系统可能存在严重问题`);
+ }
+ }
+
+ public getErrorSummary(): void {
+ this.logger.info('=== 错误统计 ===');
+ for (const [error, count] of this.errorCounts) {
+ this.logger.info(`${error}: ${count} 次`);
+ }
+ }
+}
+```
+
+## 最佳实践
+
+### 1. 合理的日志级别选择
+
+```typescript
+class LoggingBestPractices {
+ private logger = createLogger('BestPractices');
+
+ public demonstrateLogLevels(): void {
+ // ✅ Debug - 详细的调试信息
+ this.logger.debug('变量值', { x: 10, y: 20 });
+
+ // ✅ Info - 重要的状态变化
+ this.logger.info('系统启动完成');
+
+ // ✅ Warn - 异常但不致命的情况
+ this.logger.warn('资源未找到,使用默认值');
+
+ // ✅ Error - 错误但程序可以继续
+ this.logger.error('保存失败,将重试', new Error('Network timeout'));
+
+ // ✅ Fatal - 致命错误,程序无法继续
+ this.logger.fatal('内存不足,程序即将退出');
+ }
+}
+```
+
+### 2. 结构化日志数据
+
+```typescript
+class StructuredLogging {
+ private logger = createLogger('Structured');
+
+ public logWithStructuredData(): void {
+ // ✅ 提供结构化的上下文信息
+ this.logger.info('用户操作', {
+ userId: 12345,
+ action: 'move',
+ position: { x: 100, y: 200 },
+ timestamp: Date.now()
+ });
+
+ // ✅ 包含相关的错误上下文
+ this.logger.error('数据库查询失败', {
+ query: 'SELECT * FROM users',
+ parameters: { id: 123 },
+ connectionId: 'conn_456',
+ retryCount: 3
+ });
+ }
+}
+```
+
+### 3. 避免日志性能问题
+
+```typescript
+class PerformanceConsciousLogging {
+ private logger = createLogger('Performance');
+
+ public efficientLogging(): void {
+ // ✅ 检查日志级别避免不必要的计算
+ if (this.logger.debug) {
+ const expensiveData = this.calculateExpensiveDebugInfo();
+ this.logger.debug('详细调试信息', expensiveData);
+ }
+
+ // ❌ 避免:总是计算昂贵的日志数据
+ // this.logger.debug('调试信息', this.calculateExpensiveDebugInfo());
+ }
+
+ private calculateExpensiveDebugInfo(): any {
+ // 模拟昂贵的计算
+ return { /* 复杂的调试数据 */ };
+ }
+}
+```
+
+### 4. 日志配置管理
+
+```typescript
+class LoggingConfiguration {
+ public static setupLogging(): void {
+ // 根据环境配置日志级别
+ const isDevelopment = process.env.NODE_ENV === 'development';
+ const isProduction = process.env.NODE_ENV === 'production';
+
+ if (isDevelopment) {
+ setGlobalLogLevel(LogLevel.Debug);
+ setLoggerColors({
+ debug: Colors.CYAN,
+ info: Colors.GREEN,
+ warn: Colors.YELLOW,
+ error: Colors.RED,
+ fatal: Colors.BRIGHT_RED
+ });
+ } else if (isProduction) {
+ setGlobalLogLevel(LogLevel.Warn);
+ // 生产环境禁用颜色
+ LoggerManager.getInstance().resetColors();
+ }
+ }
+}
+
+// 在应用启动时配置日志
+LoggingConfiguration.setupLogging();
+```
+
+日志系统是调试和监控应用的重要工具,正确使用日志系统能大大提高开发效率和问题排查能力。
\ No newline at end of file
diff --git a/docs/guide/scene.md b/docs/guide/scene.md
new file mode 100644
index 00000000..6e98f182
--- /dev/null
+++ b/docs/guide/scene.md
@@ -0,0 +1,510 @@
+# 场景管理
+
+在 ECS 架构中,场景(Scene)是游戏世界的容器,负责管理实体、系统和组件的生命周期。场景提供了完整的 ECS 运行环境。
+
+## 基本概念
+
+场景是 ECS 框架的核心容器,提供:
+- 实体的创建、管理和销毁
+- 系统的注册和执行调度
+- 组件的存储和查询
+- 事件系统支持
+- 性能监控和调试信息
+
+## 创建场景
+
+### 继承 Scene 类
+
+**推荐做法:继承 Scene 类来创建自定义场景**
+
+```typescript
+import { Scene, EntitySystem } from '@esengine/ecs-framework';
+
+class GameScene extends Scene {
+ protected initialize(): void {
+ // 设置场景名称
+ this.name = "GameScene";
+
+ // 添加系统
+ this.addSystem(new MovementSystem());
+ this.addSystem(new RenderSystem());
+ this.addSystem(new PhysicsSystem());
+
+ // 创建初始实体
+ this.createInitialEntities();
+ }
+
+ private createInitialEntities(): void {
+ // 创建玩家
+ const player = this.createEntity("Player");
+ player.addComponent(new Position(400, 300));
+ player.addComponent(new Health(100));
+ player.addComponent(new PlayerController());
+
+ // 创建敌人
+ for (let i = 0; i < 5; i++) {
+ const enemy = this.createEntity(`Enemy_${i}`);
+ enemy.addComponent(new Position(Math.random() * 800, Math.random() * 600));
+ enemy.addComponent(new Health(50));
+ enemy.addComponent(new EnemyAI());
+ }
+ }
+
+ public onStart(): void {
+ console.log("游戏场景已启动");
+ // 场景启动时的逻辑
+ }
+
+ public unload(): void {
+ console.log("游戏场景已卸载");
+ // 场景卸载时的清理逻辑
+ }
+}
+```
+
+### 使用场景配置
+
+```typescript
+import { ISceneConfig } from '@esengine/ecs-framework';
+
+const config: ISceneConfig = {
+ name: "MainGame",
+ enableEntityDirectUpdate: false
+};
+
+class ConfiguredScene extends Scene {
+ constructor() {
+ super(config);
+ }
+}
+```
+
+## 场景生命周期
+
+场景提供了完整的生命周期管理:
+
+```typescript
+class ExampleScene extends Scene {
+ protected initialize(): void {
+ // 场景初始化:设置系统和初始实体
+ console.log("场景初始化");
+ }
+
+ public onStart(): void {
+ // 场景开始运行:游戏逻辑开始执行
+ console.log("场景开始运行");
+ }
+
+ public unload(): void {
+ // 场景卸载:清理资源
+ console.log("场景卸载");
+ }
+}
+
+// 使用场景(由框架自动管理生命周期)
+const scene = new ExampleScene();
+// 场景的 initialize(), begin(), update(), end() 由框架自动调用
+```
+
+## 实体管理
+
+### 创建实体
+
+```typescript
+class EntityScene extends Scene {
+ createGameEntities(): void {
+ // 创建单个实体
+ const player = this.createEntity("Player");
+
+ // 批量创建实体(高性能)
+ const bullets = this.createEntities(100, "Bullet");
+
+ // 为批量创建的实体添加组件
+ bullets.forEach((bullet, index) => {
+ bullet.addComponent(new Position(index * 10, 100));
+ bullet.addComponent(new Velocity(Math.random() * 200 - 100, -300));
+ });
+ }
+}
+```
+
+### 查找实体
+
+```typescript
+class SearchScene extends Scene {
+ findEntities(): void {
+ // 按名称查找
+ const player = this.findEntity("Player");
+ const player2 = this.getEntityByName("Player"); // 别名方法
+
+ // 按 ID 查找
+ const entity = this.findEntityById(123);
+
+ // 按标签查找
+ const enemies = this.findEntitiesByTag(2);
+ const enemies2 = this.getEntitiesByTag(2); // 别名方法
+
+ if (player) {
+ console.log(`找到玩家: ${player.name}`);
+ }
+
+ console.log(`找到 ${enemies.length} 个敌人`);
+ }
+}
+```
+
+### 销毁实体
+
+```typescript
+class DestroyScene extends Scene {
+ cleanupEntities(): void {
+ // 销毁所有实体
+ this.destroyAllEntities();
+
+ // 单个实体的销毁通过实体本身
+ const enemy = this.findEntity("Enemy_1");
+ if (enemy) {
+ enemy.destroy(); // 实体会自动从场景中移除
+ }
+ }
+}
+```
+
+## 系统管理
+
+### 添加和移除系统
+
+```typescript
+class SystemScene extends Scene {
+ protected initialize(): void {
+ // 添加系统
+ const movementSystem = new MovementSystem();
+ this.addSystem(movementSystem);
+
+ // 设置系统更新顺序
+ movementSystem.updateOrder = 1;
+
+ // 添加更多系统
+ this.addSystem(new PhysicsSystem());
+ this.addSystem(new RenderSystem());
+ }
+
+ public removeUnnecessarySystems(): void {
+ // 获取系统
+ const physicsSystem = this.getEntityProcessor(PhysicsSystem);
+
+ // 移除系统
+ if (physicsSystem) {
+ this.removeSystem(physicsSystem);
+ }
+ }
+}
+```
+
+### 系统访问
+
+```typescript
+class SystemAccessScene extends Scene {
+ public pausePhysics(): void {
+ const physicsSystem = this.getEntityProcessor(PhysicsSystem);
+ if (physicsSystem) {
+ physicsSystem.enabled = false;
+ }
+ }
+
+ public getAllSystems(): EntitySystem[] {
+ return this.systems; // 获取所有系统
+ }
+}
+```
+
+## 事件系统
+
+场景内置了类型安全的事件系统:
+
+```typescript
+class EventScene extends Scene {
+ protected initialize(): void {
+ // 监听事件
+ this.eventSystem.on('player_died', this.onPlayerDied.bind(this));
+ this.eventSystem.on('enemy_spawned', this.onEnemySpawned.bind(this));
+ this.eventSystem.on('level_complete', this.onLevelComplete.bind(this));
+ }
+
+ private onPlayerDied(data: any): void {
+ console.log('玩家死亡事件');
+ // 处理玩家死亡
+ }
+
+ private onEnemySpawned(data: any): void {
+ console.log('敌人生成事件');
+ // 处理敌人生成
+ }
+
+ private onLevelComplete(data: any): void {
+ console.log('关卡完成事件');
+ // 处理关卡完成
+ }
+
+ public triggerGameEvent(): void {
+ // 发送事件
+ this.eventSystem.emitSync('custom_event', {
+ message: "这是自定义事件",
+ timestamp: Date.now()
+ });
+ }
+}
+```
+
+## 场景统计和调试
+
+### 获取场景统计
+
+```typescript
+class StatsScene extends Scene {
+ public showStats(): void {
+ const stats = this.getStats();
+ console.log(`实体数量: ${stats.entityCount}`);
+ console.log(`系统数量: ${stats.processorCount}`);
+ console.log('组件存储统计:', stats.componentStorageStats);
+ }
+
+ public showDebugInfo(): void {
+ const debugInfo = this.getDebugInfo();
+ console.log('场景调试信息:', debugInfo);
+
+ // 显示所有实体信息
+ debugInfo.entities.forEach(entity => {
+ console.log(`实体 ${entity.name}(${entity.id}): ${entity.componentCount} 个组件`);
+ console.log('组件类型:', entity.componentTypes);
+ });
+
+ // 显示所有系统信息
+ debugInfo.processors.forEach(processor => {
+ console.log(`系统 ${processor.name}: 处理 ${processor.entityCount} 个实体`);
+ });
+ }
+}
+```
+
+## 场景集成到框架
+
+场景可以通过两种方式运行:
+
+### 1. 简单的单场景应用
+
+```typescript
+import { Core } from '@esengine/ecs-framework';
+
+// 创建游戏场景
+class GameScene extends Scene {
+ protected initialize(): void {
+ this.name = "GameScene";
+ this.addSystem(new MovementSystem());
+ this.addSystem(new RenderSystem());
+ }
+}
+
+// 启动游戏
+Core.create();
+const gameScene = new GameScene();
+Core.setScene(gameScene);
+```
+
+### 2. 复杂的多场景应用
+
+```typescript
+import { WorldManager } from '@esengine/ecs-framework';
+
+// 获取WorldManager实例
+const worldManager = WorldManager.getInstance();
+
+// 创建World
+const gameWorld = worldManager.createWorld('game', {
+ name: 'MainGame',
+ maxScenes: 5
+});
+
+// 在World中创建场景
+const menuScene = gameWorld.createScene('menu', new MenuScene());
+const gameScene = gameWorld.createScene('game', new GameScene());
+
+// 激活场景
+gameWorld.setSceneActive('menu', true);
+```
+
+## 多场景管理
+
+在World中可以管理多个场景,通过激活/停用来切换:
+
+```typescript
+class GameWorld extends World {
+ private menuScene: Scene;
+ private gameScene: Scene;
+ private gameOverScene: Scene;
+
+ public initialize(): void {
+ // 创建多个场景
+ this.menuScene = this.createScene('menu', new MenuScene());
+ this.gameScene = this.createScene('game', new GameScene());
+ this.gameOverScene = this.createScene('gameover', new GameOverScene());
+
+ // 设置初始场景
+ this.showMenu();
+ }
+
+ public showMenu(): void {
+ this.deactivateAllScenes();
+ this.setSceneActive('menu', true);
+ }
+
+ public startGame(): void {
+ this.deactivateAllScenes();
+ this.setSceneActive('game', true);
+ }
+
+ public showGameOver(): void {
+ this.deactivateAllScenes();
+ this.setSceneActive('gameover', true);
+ }
+
+ private deactivateAllScenes(): void {
+ this.setSceneActive('menu', false);
+ this.setSceneActive('game', false);
+ this.setSceneActive('gameover', false);
+ }
+}
+```
+
+## 与 World 的关系
+
+Scene 的运行架构层次:
+
+```typescript
+// Core -> WorldManager -> World -> Scene -> EntitySystem -> Entity -> Component
+
+// 1. 简单应用:Core直接管理单个Scene
+Core.setScene(new GameScene());
+
+// 2. 复杂应用:WorldManager管理多个World,每个World管理多个Scene
+const worldManager = WorldManager.getInstance();
+const world = worldManager.createWorld('gameWorld');
+const scene = world.createScene('mainScene', new GameScene());
+world.setSceneActive('mainScene', true);
+```
+
+## 最佳实践
+
+### 1. 场景职责分离
+
+```typescript
+// ✅ 好的场景设计 - 职责清晰
+class MenuScene extends Scene {
+ // 只处理菜单相关逻辑
+}
+
+class GameScene extends Scene {
+ // 只处理游戏玩法逻辑
+}
+
+class InventoryScene extends Scene {
+ // 只处理物品栏逻辑
+}
+
+// ❌ 避免的场景设计 - 职责混乱
+class MegaScene extends Scene {
+ // 包含菜单、游戏、物品栏等所有逻辑
+}
+```
+
+### 2. 合理的系统组织
+
+```typescript
+class OrganizedScene extends Scene {
+ protected initialize(): void {
+ // 按功能和依赖关系添加系统
+ this.addInputSystems();
+ this.addLogicSystems();
+ this.addRenderSystems();
+ }
+
+ private addInputSystems(): void {
+ this.addSystem(new InputSystem());
+ }
+
+ private addLogicSystems(): void {
+ this.addSystem(new MovementSystem());
+ this.addSystem(new PhysicsSystem());
+ this.addSystem(new CollisionSystem());
+ }
+
+ private addRenderSystems(): void {
+ this.addSystem(new RenderSystem());
+ this.addSystem(new UISystem());
+ }
+}
+```
+
+### 3. 资源管理
+
+```typescript
+class ResourceScene extends Scene {
+ private textures: Map = new Map();
+ private sounds: Map = new Map();
+
+ protected initialize(): void {
+ this.loadResources();
+ }
+
+ private loadResources(): void {
+ // 加载场景所需资源
+ }
+
+ public unload(): void {
+ // 清理资源
+ this.textures.clear();
+ this.sounds.clear();
+ }
+}
+```
+
+### 4. 事件处理规范
+
+```typescript
+class EventHandlingScene extends Scene {
+ protected initialize(): void {
+ // 集中管理事件监听
+ this.setupEventListeners();
+ }
+
+ private setupEventListeners(): void {
+ this.eventSystem.on('game_pause', this.onGamePause.bind(this));
+ this.eventSystem.on('game_resume', this.onGameResume.bind(this));
+ this.eventSystem.on('player_input', this.onPlayerInput.bind(this));
+ }
+
+ private onGamePause(): void {
+ // 暂停游戏逻辑
+ this.systems.forEach(system => {
+ if (system instanceof GameLogicSystem) {
+ system.enabled = false;
+ }
+ });
+ }
+
+ private onGameResume(): void {
+ // 恢复游戏逻辑
+ this.systems.forEach(system => {
+ if (system instanceof GameLogicSystem) {
+ system.enabled = true;
+ }
+ });
+ }
+
+ private onPlayerInput(data: any): void {
+ // 处理玩家输入
+ }
+}
+```
+
+场景是 ECS 框架的核心容器,正确使用场景管理能让你的游戏架构更加清晰、模块化和易于维护。
\ No newline at end of file
diff --git a/docs/guide/system.md b/docs/guide/system.md
new file mode 100644
index 00000000..2d51e96b
--- /dev/null
+++ b/docs/guide/system.md
@@ -0,0 +1,596 @@
+# 系统架构
+
+在 ECS 架构中,系统(System)是处理业务逻辑的地方。系统负责对拥有特定组件组合的实体执行操作,是 ECS 架构的逻辑处理单元。
+
+## 基本概念
+
+系统是继承自 `EntitySystem` 抽象基类的具体类,用于:
+- 定义实体的处理逻辑(如移动、碰撞检测、渲染等)
+- 根据组件组合筛选需要处理的实体
+- 提供生命周期管理和性能监控
+- 管理实体的添加、移除事件
+
+## 系统类型
+
+框架提供了几种不同类型的系统基类:
+
+### EntitySystem - 基础系统
+
+最基础的系统类,所有其他系统都继承自它:
+
+```typescript
+import { EntitySystem, ECSSystem, Matcher } from '@esengine/ecs-framework';
+
+@ECSSystem('Movement')
+class MovementSystem extends EntitySystem {
+ constructor() {
+ // 使用 Matcher 定义需要处理的实体条件
+ super(Matcher.all(Position, Velocity));
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ const position = entity.getComponent(Position);
+ const velocity = entity.getComponent(Velocity);
+
+ if (position && velocity) {
+ position.x += velocity.dx * Time.deltaTime;
+ position.y += velocity.dy * Time.deltaTime;
+ }
+ }
+ }
+}
+```
+
+### ProcessingSystem - 处理系统
+
+适用于不需要逐个处理实体的系统:
+
+```typescript
+@ECSSystem('Physics')
+class PhysicsSystem extends ProcessingSystem {
+ constructor() {
+ super(); // 不需要指定 Matcher
+ }
+
+ public processSystem(): void {
+ // 执行物理世界步进
+ this.physicsWorld.step(Time.deltaTime);
+ }
+}
+```
+
+### PassiveSystem - 被动系统
+
+被动系统不进行主动处理,主要用于监听实体的添加和移除事件:
+
+```typescript
+@ECSSystem('EntityTracker')
+class EntityTrackerSystem extends PassiveSystem {
+ constructor() {
+ super(Matcher.all(Health));
+ }
+
+ protected onAdded(entity: Entity): void {
+ console.log(`生命值实体被添加: ${entity.name}`);
+ }
+
+ protected onRemoved(entity: Entity): void {
+ console.log(`生命值实体被移除: ${entity.name}`);
+ }
+}
+```
+
+### IntervalSystem - 间隔系统
+
+按固定时间间隔执行的系统:
+
+```typescript
+@ECSSystem('AutoSave')
+class AutoSaveSystem extends IntervalSystem {
+ constructor() {
+ // 每 5 秒执行一次
+ super(5.0, Matcher.all(SaveData));
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ console.log('执行自动保存...');
+ // 保存游戏数据
+ this.saveGameData(entities);
+ }
+
+ private saveGameData(entities: readonly Entity[]): void {
+ // 保存逻辑
+ }
+}
+```
+
+## 实体匹配器 (Matcher)
+
+Matcher 用于定义系统需要处理哪些实体。它提供了灵活的条件组合:
+
+### 基本匹配条件
+
+```typescript
+// 必须同时拥有 Position 和 Velocity 组件
+const matcher1 = Matcher.all(Position, Velocity);
+
+// 至少拥有 Health 或 Shield 组件之一
+const matcher2 = Matcher.any(Health, Shield);
+
+// 不能拥有 Dead 组件
+const matcher3 = Matcher.none(Dead);
+```
+
+### 复合匹配条件
+
+```typescript
+// 复杂的组合条件
+const complexMatcher = Matcher.all(Position, Velocity)
+ .any(Player, Enemy)
+ .none(Dead, Disabled);
+
+@ECSSystem('Combat')
+class CombatSystem extends EntitySystem {
+ constructor() {
+ super(complexMatcher);
+ }
+}
+```
+
+### 特殊匹配条件
+
+```typescript
+// 按标签匹配
+const tagMatcher = Matcher.byTag(1); // 匹配标签为 1 的实体
+
+// 按名称匹配
+const nameMatcher = Matcher.byName("Player"); // 匹配名称为 "Player" 的实体
+
+// 单组件匹配
+const componentMatcher = Matcher.byComponent(Health); // 匹配拥有 Health 组件的实体
+```
+
+## 系统生命周期
+
+系统提供了完整的生命周期回调:
+
+```typescript
+@ECSSystem('Example')
+class ExampleSystem extends EntitySystem {
+ protected onInitialize(): void {
+ console.log('系统初始化');
+ // 系统被添加到场景时调用,用于初始化资源
+ }
+
+ protected onBegin(): void {
+ // 每帧处理开始前调用
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ // 主要的处理逻辑
+ for (const entity of entities) {
+ // 处理每个实体
+ }
+ }
+
+ protected lateProcess(entities: readonly Entity[]): void {
+ // 主处理之后的后期处理
+ }
+
+ protected onEnd(): void {
+ // 每帧处理结束后调用
+ }
+
+ protected onDestroy(): void {
+ console.log('系统销毁');
+ // 系统从场景移除时调用,用于清理资源
+ }
+}
+```
+
+## 实体事件监听
+
+系统可以监听实体的添加和移除事件:
+
+```typescript
+@ECSSystem('EnemyManager')
+class EnemyManagerSystem extends EntitySystem {
+ private enemyCount = 0;
+
+ constructor() {
+ super(Matcher.all(Enemy, Health));
+ }
+
+ protected onAdded(entity: Entity): void {
+ this.enemyCount++;
+ console.log(`敌人加入战斗,当前敌人数量: ${this.enemyCount}`);
+
+ // 可以在这里为新敌人设置初始状态
+ const health = entity.getComponent(Health);
+ if (health) {
+ health.current = health.max;
+ }
+ }
+
+ protected onRemoved(entity: Entity): void {
+ this.enemyCount--;
+ console.log(`敌人被移除,剩余敌人数量: ${this.enemyCount}`);
+
+ // 检查是否所有敌人都被消灭
+ if (this.enemyCount === 0) {
+ this.scene?.eventSystem.emitSync('all_enemies_defeated');
+ }
+ }
+}
+```
+
+## 系统属性和方法
+
+### 重要属性
+
+```typescript
+@ECSSystem('Example')
+class ExampleSystem extends EntitySystem {
+ showSystemInfo(): void {
+ console.log(`系统名称: ${this.systemName}`); // 系统名称
+ console.log(`更新顺序: ${this.updateOrder}`); // 更新时序
+ console.log(`是否启用: ${this.enabled}`); // 启用状态
+ console.log(`实体数量: ${this.entities.length}`); // 匹配的实体数量
+ console.log(`所属场景: ${this.scene?.name}`); // 所属场景
+ }
+}
+```
+
+### 实体访问
+
+```typescript
+protected process(entities: readonly Entity[]): void {
+ // 方式1:使用参数中的实体列表
+ for (const entity of entities) {
+ // 处理实体
+ }
+
+ // 方式2:使用 this.entities 属性(与参数相同)
+ for (const entity of this.entities) {
+ // 处理实体
+ }
+}
+```
+
+### 控制系统执行
+
+```typescript
+@ECSSystem('Conditional')
+class ConditionalSystem extends EntitySystem {
+ private shouldProcess = true;
+
+ protected onCheckProcessing(): boolean {
+ // 返回 false 时跳过本次处理
+ return this.shouldProcess && this.entities.length > 0;
+ }
+
+ public pause(): void {
+ this.shouldProcess = false;
+ }
+
+ public resume(): void {
+ this.shouldProcess = true;
+ }
+}
+```
+
+## 事件系统集成
+
+系统可以方便地监听和发送事件:
+
+```typescript
+@ECSSystem('GameLogic')
+class GameLogicSystem extends EntitySystem {
+ protected onInitialize(): void {
+ // 添加事件监听器(系统销毁时自动清理)
+ this.addEventListener('player_died', this.onPlayerDied.bind(this));
+ this.addEventListener('level_complete', this.onLevelComplete.bind(this));
+ }
+
+ private onPlayerDied(data: any): void {
+ console.log('玩家死亡,重新开始游戏');
+ // 处理玩家死亡逻辑
+ }
+
+ private onLevelComplete(data: any): void {
+ console.log('关卡完成,加载下一关');
+ // 处理关卡完成逻辑
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ // 在处理过程中发送事件
+ for (const entity of entities) {
+ const health = entity.getComponent(Health);
+ if (health && health.current <= 0) {
+ this.scene?.eventSystem.emitSync('entity_died', { entity });
+ }
+ }
+ }
+}
+```
+
+## 性能监控
+
+系统内置了性能监控功能:
+
+```typescript
+@ECSSystem('Performance')
+class PerformanceSystem extends EntitySystem {
+ protected onEnd(): void {
+ // 获取性能数据
+ const perfData = this.getPerformanceData();
+ if (perfData) {
+ console.log(`执行时间: ${perfData.executionTime.toFixed(2)}ms`);
+ }
+
+ // 获取性能统计
+ const stats = this.getPerformanceStats();
+ if (stats) {
+ console.log(`平均执行时间: ${stats.averageTime.toFixed(2)}ms`);
+ }
+ }
+
+ public resetPerformance(): void {
+ this.resetPerformanceData();
+ }
+}
+```
+
+## 系统管理
+
+### 添加系统到场景
+
+```typescript
+// 在场景子类中添加系统
+class GameScene extends Scene {
+ protected initialize(): void {
+ // 添加系统
+ this.addSystem(new MovementSystem());
+ this.addSystem(new RenderSystem());
+ this.addSystem(new PhysicsSystem());
+
+ // 设置系统更新顺序
+ const movementSystem = this.getSystem(MovementSystem);
+ if (movementSystem) {
+ movementSystem.updateOrder = 1;
+ }
+ }
+}
+```
+
+### 系统更新顺序
+
+```typescript
+@ECSSystem('Input')
+class InputSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(InputComponent));
+ this.updateOrder = -100; // 输入系统优先执行
+ }
+}
+
+@ECSSystem('Physics')
+class PhysicsSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(RigidBody));
+ this.updateOrder = 0; // 默认顺序
+ }
+}
+
+@ECSSystem('Render')
+class RenderSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(Sprite, Transform));
+ this.updateOrder = 100; // 渲染系统最后执行
+ }
+}
+```
+
+## 复杂系统示例
+
+### 碰撞检测系统
+
+```typescript
+@ECSSystem('Collision')
+class CollisionSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(Transform, Collider));
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ // 简单的 n² 碰撞检测
+ for (let i = 0; i < entities.length; i++) {
+ for (let j = i + 1; j < entities.length; j++) {
+ this.checkCollision(entities[i], entities[j]);
+ }
+ }
+ }
+
+ private checkCollision(entityA: Entity, entityB: Entity): void {
+ const transformA = entityA.getComponent(Transform);
+ const transformB = entityB.getComponent(Transform);
+ const colliderA = entityA.getComponent(Collider);
+ const colliderB = entityB.getComponent(Collider);
+
+ if (this.isColliding(transformA, colliderA, transformB, colliderB)) {
+ // 发送碰撞事件
+ this.scene?.eventSystem.emitSync('collision', {
+ entityA,
+ entityB
+ });
+ }
+ }
+
+ private isColliding(transformA: Transform, colliderA: Collider,
+ transformB: Transform, colliderB: Collider): boolean {
+ // 碰撞检测逻辑
+ return false; // 简化示例
+ }
+}
+```
+
+### 状态机系统
+
+```typescript
+@ECSSystem('StateMachine')
+class StateMachineSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(StateMachine));
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ const stateMachine = entity.getComponent(StateMachine);
+ if (stateMachine) {
+ stateMachine.updateTimer(Time.deltaTime);
+ this.updateState(entity, stateMachine);
+ }
+ }
+ }
+
+ private updateState(entity: Entity, stateMachine: StateMachine): void {
+ switch (stateMachine.currentState) {
+ case EntityState.Idle:
+ this.handleIdleState(entity, stateMachine);
+ break;
+ case EntityState.Moving:
+ this.handleMovingState(entity, stateMachine);
+ break;
+ case EntityState.Attacking:
+ this.handleAttackingState(entity, stateMachine);
+ break;
+ }
+ }
+
+ private handleIdleState(entity: Entity, stateMachine: StateMachine): void {
+ // 空闲状态逻辑
+ }
+
+ private handleMovingState(entity: Entity, stateMachine: StateMachine): void {
+ // 移动状态逻辑
+ }
+
+ private handleAttackingState(entity: Entity, stateMachine: StateMachine): void {
+ // 攻击状态逻辑
+ }
+}
+```
+
+## 最佳实践
+
+### 1. 系统单一职责
+
+```typescript
+// ✅ 好的系统设计 - 职责单一
+@ECSSystem('Movement')
+class MovementSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(Position, Velocity));
+ }
+}
+
+@ECSSystem('Rendering')
+class RenderingSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(Sprite, Transform));
+ }
+}
+
+// ❌ 避免的系统设计 - 职责过多
+@ECSSystem('GameSystem')
+class GameSystem extends EntitySystem {
+ // 一个系统处理移动、渲染、音效等多种逻辑
+}
+```
+
+### 2. 使用装饰器
+
+**必须使用 `@ECSSystem` 装饰器**:
+
+```typescript
+// ✅ 正确的用法
+@ECSSystem('Physics')
+class PhysicsSystem extends EntitySystem {
+ // 系统实现
+}
+
+// ❌ 错误的用法 - 没有装饰器
+class BadSystem extends EntitySystem {
+ // 这样定义的系统可能在生产环境出现问题
+}
+```
+
+### 3. 合理的更新顺序
+
+```typescript
+// 按逻辑顺序设置系统的更新时序
+@ECSSystem('Input')
+class InputSystem extends EntitySystem {
+ constructor() {
+ super();
+ this.updateOrder = -100; // 最先处理输入
+ }
+}
+
+@ECSSystem('Logic')
+class GameLogicSystem extends EntitySystem {
+ constructor() {
+ super();
+ this.updateOrder = 0; // 处理游戏逻辑
+ }
+}
+
+@ECSSystem('Render')
+class RenderSystem extends EntitySystem {
+ constructor() {
+ super();
+ this.updateOrder = 100; // 最后进行渲染
+ }
+}
+```
+
+### 4. 避免在系统间直接引用
+
+```typescript
+// ❌ 避免:系统间直接引用
+@ECSSystem('Bad')
+class BadSystem extends EntitySystem {
+ private otherSystem: SomeOtherSystem; // 避免直接引用其他系统
+}
+
+// ✅ 推荐:通过事件系统通信
+@ECSSystem('Good')
+class GoodSystem extends EntitySystem {
+ protected process(entities: readonly Entity[]): void {
+ // 通过事件系统与其他系统通信
+ this.scene?.eventSystem.emitSync('data_updated', { entities });
+ }
+}
+```
+
+### 5. 及时清理资源
+
+```typescript
+@ECSSystem('Resource')
+class ResourceSystem extends EntitySystem {
+ private resources: Map = new Map();
+
+ protected onDestroy(): void {
+ // 清理资源
+ for (const [key, resource] of this.resources) {
+ if (resource.dispose) {
+ resource.dispose();
+ }
+ }
+ this.resources.clear();
+ }
+}
+```
+
+系统是 ECS 架构的逻辑处理核心,正确设计和使用系统能让你的游戏代码更加模块化、高效和易于维护。
\ No newline at end of file
diff --git a/docs/guide/time-and-timers.md b/docs/guide/time-and-timers.md
new file mode 100644
index 00000000..70b6c331
--- /dev/null
+++ b/docs/guide/time-and-timers.md
@@ -0,0 +1,553 @@
+# 时间和定时器系统
+
+ECS 框架提供了完整的时间管理和定时器系统,包括时间缩放、帧时间计算和灵活的定时器调度功能。
+
+## Time 类
+
+Time 类是框架的时间管理核心,提供了游戏时间相关的所有功能。
+
+### 基本时间属性
+
+```typescript
+import { Time } from '@esengine/ecs-framework';
+
+class GameSystem extends EntitySystem {
+ protected process(entities: readonly Entity[]): void {
+ // 获取帧时间(秒)
+ const deltaTime = Time.deltaTime;
+
+ // 获取未缩放的帧时间
+ const unscaledDelta = Time.unscaledDeltaTime;
+
+ // 获取游戏总时间
+ const totalTime = Time.totalTime;
+
+ // 获取当前帧数
+ const frameCount = Time.frameCount;
+
+ console.log(`第 ${frameCount} 帧,帧时间: ${deltaTime}s,总时间: ${totalTime}s`);
+ }
+}
+```
+
+### 时间缩放
+
+Time 类支持时间缩放功能,可以实现慢动作、快进等效果:
+
+```typescript
+class TimeControlSystem extends EntitySystem {
+ public enableSlowMotion(): void {
+ // 设置为慢动作(50%速度)
+ Time.timeScale = 0.5;
+ console.log('慢动作模式启用');
+ }
+
+ public enableFastForward(): void {
+ // 设置为快进(200%速度)
+ Time.timeScale = 2.0;
+ console.log('快进模式启用');
+ }
+
+ public pauseGame(): void {
+ // 暂停游戏(时间静止)
+ Time.timeScale = 0;
+ console.log('游戏暂停');
+ }
+
+ public resumeNormalSpeed(): void {
+ // 恢复正常速度
+ Time.timeScale = 1.0;
+ console.log('恢复正常速度');
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ // deltaTime 会受到 timeScale 影响
+ const scaledDelta = Time.deltaTime; // 受时间缩放影响
+ const realDelta = Time.unscaledDeltaTime; // 不受时间缩放影响
+
+ for (const entity of entities) {
+ const movement = entity.getComponent(Movement);
+ if (movement) {
+ // 使用缩放时间进行游戏逻辑更新
+ movement.update(scaledDelta);
+ }
+
+ const ui = entity.getComponent(UIComponent);
+ if (ui) {
+ // UI 动画使用真实时间,不受游戏时间缩放影响
+ ui.update(realDelta);
+ }
+ }
+ }
+}
+```
+
+### 时间检查工具
+
+```typescript
+class CooldownSystem extends EntitySystem {
+ private lastAttackTime = 0;
+ private lastSpawnTime = 0;
+
+ constructor() {
+ super(Matcher.all(Weapon));
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ // 检查攻击冷却
+ if (Time.checkEvery(1.5, this.lastAttackTime)) {
+ this.performAttack();
+ this.lastAttackTime = Time.totalTime;
+ }
+
+ // 检查生成间隔
+ if (Time.checkEvery(3.0, this.lastSpawnTime)) {
+ this.spawnEnemy();
+ this.lastSpawnTime = Time.totalTime;
+ }
+ }
+
+ private performAttack(): void {
+ console.log('执行攻击!');
+ }
+
+ private spawnEnemy(): void {
+ console.log('生成敌人!');
+ }
+}
+```
+
+## Core.schedule 定时器系统
+
+Core 提供了强大的定时器调度功能,可以创建一次性或重复执行的定时器。
+
+### 基本定时器使用
+
+```typescript
+import { Core } from '@esengine/ecs-framework';
+
+class GameScene extends Scene {
+ protected initialize(): void {
+ // 创建一次性定时器
+ this.createOneTimeTimers();
+
+ // 创建重复定时器
+ this.createRepeatingTimers();
+
+ // 创建带上下文的定时器
+ this.createContextTimers();
+ }
+
+ private createOneTimeTimers(): void {
+ // 2秒后执行一次
+ Core.schedule(2.0, false, null, (timer) => {
+ console.log('2秒延迟执行');
+ });
+
+ // 5秒后显示提示
+ Core.schedule(5.0, false, this, (timer) => {
+ const scene = timer.getContext();
+ scene.showTip('游戏提示:5秒已过!');
+ });
+ }
+
+ private createRepeatingTimers(): void {
+ // 每秒重复执行
+ const heartbeatTimer = Core.schedule(1.0, true, null, (timer) => {
+ console.log(`游戏心跳 - 总时间: ${Time.totalTime.toFixed(1)}s`);
+ });
+
+ // 可以保存定时器引用用于后续控制
+ this.saveTimerReference(heartbeatTimer);
+ }
+
+ private createContextTimers(): void {
+ const gameData = { score: 0, level: 1 };
+
+ // 每2秒增加分数
+ Core.schedule(2.0, true, gameData, (timer) => {
+ const data = timer.getContext();
+ data.score += 10;
+ console.log(`分数增加!当前分数: ${data.score}`);
+ });
+ }
+
+ private saveTimerReference(timer: any): void {
+ // 可以稍后停止定时器
+ setTimeout(() => {
+ timer.stop();
+ console.log('定时器已停止');
+ }, 10000); // 10秒后停止
+ }
+
+ private showTip(message: string): void {
+ console.log('提示:', message);
+ }
+}
+```
+
+### 定时器控制
+
+```typescript
+class TimerControlExample {
+ private attackTimer: any;
+ private spawnerTimer: any;
+
+ public startCombat(): void {
+ // 启动攻击定时器
+ this.attackTimer = Core.schedule(0.5, true, this, (timer) => {
+ const self = timer.getContext();
+ self.performAttack();
+ });
+
+ // 启动敌人生成定时器
+ this.spawnerTimer = Core.schedule(3.0, true, null, (timer) => {
+ this.spawnEnemy();
+ });
+ }
+
+ public stopCombat(): void {
+ // 停止所有战斗相关定时器
+ if (this.attackTimer) {
+ this.attackTimer.stop();
+ console.log('攻击定时器已停止');
+ }
+
+ if (this.spawnerTimer) {
+ this.spawnerTimer.stop();
+ console.log('生成定时器已停止');
+ }
+ }
+
+ public resetAttackTimer(): void {
+ // 重置攻击定时器
+ if (this.attackTimer) {
+ this.attackTimer.reset();
+ console.log('攻击定时器已重置');
+ }
+ }
+
+ private performAttack(): void {
+ console.log('执行攻击');
+ }
+
+ private spawnEnemy(): void {
+ console.log('生成敌人');
+ }
+}
+```
+
+### 复杂定时器场景
+
+```typescript
+class AdvancedTimerUsage {
+ private powerUpDuration = 0;
+ private powerUpActive = false;
+
+ public activatePowerUp(): void {
+ if (this.powerUpActive) {
+ console.log('能力提升已激活');
+ return;
+ }
+
+ this.powerUpActive = true;
+ this.powerUpDuration = 10; // 10秒持续时间
+
+ console.log('能力提升激活!');
+
+ // 每秒更新剩余时间
+ const countdownTimer = Core.schedule(1.0, true, this, (timer) => {
+ const self = timer.getContext();
+ self.powerUpDuration--;
+
+ console.log(`能力提升剩余时间: ${self.powerUpDuration}秒`);
+
+ if (self.powerUpDuration <= 0) {
+ self.deactivatePowerUp();
+ timer.stop(); // 停止倒计时
+ }
+ });
+
+ // 能力提升结束定时器(备用)
+ Core.schedule(10.0, false, this, (timer) => {
+ const self = timer.getContext();
+ if (self.powerUpActive) {
+ self.deactivatePowerUp();
+ }
+ });
+ }
+
+ private deactivatePowerUp(): void {
+ this.powerUpActive = false;
+ this.powerUpDuration = 0;
+ console.log('能力提升结束');
+ }
+
+ // 创建波次攻击定时器
+ public startWaveAttack(): void {
+ let waveCount = 0;
+ const maxWaves = 5;
+
+ const waveTimer = Core.schedule(2.0, true, { waveCount, maxWaves }, (timer) => {
+ const context = timer.getContext<{ waveCount: number, maxWaves: number }>();
+ context.waveCount++;
+
+ console.log(`第 ${context.waveCount} 波攻击!`);
+
+ if (context.waveCount >= context.maxWaves) {
+ console.log('所有波次攻击完成');
+ timer.stop();
+ }
+ });
+ }
+
+ // 创建条件定时器
+ public startConditionalTimer(): void {
+ Core.schedule(0.1, true, this, (timer) => {
+ const self = timer.getContext();
+
+ // 检查某个条件
+ if (self.shouldStopTimer()) {
+ console.log('条件满足,停止定时器');
+ timer.stop();
+ return;
+ }
+
+ // 继续执行定时器逻辑
+ self.performTimerAction();
+ });
+ }
+
+ private shouldStopTimer(): boolean {
+ // 检查停止条件
+ return Time.totalTime > 30; // 30秒后停止
+ }
+
+ private performTimerAction(): void {
+ console.log('执行定时器动作');
+ }
+}
+```
+
+## 实际应用示例
+
+### 技能冷却系统
+
+```typescript
+class SkillCooldownSystem extends EntitySystem {
+ constructor() {
+ super(Matcher.all(SkillComponent));
+ }
+
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ const skill = entity.getComponent(SkillComponent);
+
+ // 更新技能冷却
+ if (skill.isOnCooldown) {
+ skill.cooldownRemaining -= Time.deltaTime;
+
+ if (skill.cooldownRemaining <= 0) {
+ skill.cooldownRemaining = 0;
+ skill.isOnCooldown = false;
+ console.log(`技能 ${skill.name} 冷却完成`);
+ }
+ }
+ }
+ }
+
+ public useSkill(entity: Entity, skillName: string): boolean {
+ const skill = entity.getComponent(SkillComponent);
+
+ if (skill.isOnCooldown) {
+ console.log(`技能 ${skillName} 还在冷却中,剩余 ${skill.cooldownRemaining.toFixed(1)}秒`);
+ return false;
+ }
+
+ // 执行技能
+ this.executeSkill(entity, skill);
+
+ // 开始冷却
+ skill.isOnCooldown = true;
+ skill.cooldownRemaining = skill.cooldownDuration;
+
+ return true;
+ }
+
+ private executeSkill(entity: Entity, skill: SkillComponent): void {
+ console.log(`执行技能: ${skill.name}`);
+ // 技能效果逻辑
+ }
+}
+```
+
+### 游戏状态定时器
+
+```typescript
+class GameStateManager {
+ private gamePhase = 'preparation';
+ private phaseTimer: any;
+
+ public startGame(): void {
+ this.startPreparationPhase();
+ }
+
+ private startPreparationPhase(): void {
+ this.gamePhase = 'preparation';
+ console.log('准备阶段开始 - 10秒准备时间');
+
+ this.phaseTimer = Core.schedule(10.0, false, this, (timer) => {
+ const self = timer.getContext();
+ self.startCombatPhase();
+ });
+ }
+
+ private startCombatPhase(): void {
+ this.gamePhase = 'combat';
+ console.log('战斗阶段开始 - 60秒战斗时间');
+
+ this.phaseTimer = Core.schedule(60.0, false, this, (timer) => {
+ const self = timer.getContext();
+ self.startResultPhase();
+ });
+
+ // 每10秒刷新一波敌人
+ Core.schedule(10.0, true, null, (timer) => {
+ if (this.gamePhase === 'combat') {
+ this.spawnEnemyWave();
+ } else {
+ timer.stop(); // 战斗阶段结束时停止刷新
+ }
+ });
+ }
+
+ private startResultPhase(): void {
+ this.gamePhase = 'result';
+ console.log('结算阶段开始 - 5秒结算时间');
+
+ this.phaseTimer = Core.schedule(5.0, false, this, (timer) => {
+ const self = timer.getContext();
+ self.endGame();
+ });
+ }
+
+ private endGame(): void {
+ console.log('游戏结束');
+ this.gamePhase = 'ended';
+ }
+
+ private spawnEnemyWave(): void {
+ console.log('刷新敌人波次');
+ }
+
+ public getCurrentPhase(): string {
+ return this.gamePhase;
+ }
+}
+```
+
+## 最佳实践
+
+### 1. 合理使用时间类型
+
+```typescript
+class MovementSystem extends EntitySystem {
+ protected process(entities: readonly Entity[]): void {
+ for (const entity of entities) {
+ const movement = entity.getComponent(Movement);
+
+ // ✅ 游戏逻辑使用缩放时间
+ movement.position.x += movement.velocity.x * Time.deltaTime;
+
+ // ✅ UI动画使用真实时间(不受游戏暂停影响)
+ const ui = entity.getComponent(UIAnimation);
+ if (ui) {
+ ui.update(Time.unscaledDeltaTime);
+ }
+ }
+ }
+}
+```
+
+### 2. 定时器管理
+
+```typescript
+class TimerManager {
+ private timers: any[] = [];
+
+ public createManagedTimer(duration: number, repeats: boolean, callback: () => void): any {
+ const timer = Core.schedule(duration, repeats, null, callback);
+ this.timers.push(timer);
+ return timer;
+ }
+
+ public stopAllTimers(): void {
+ for (const timer of this.timers) {
+ timer.stop();
+ }
+ this.timers = [];
+ }
+
+ public cleanupCompletedTimers(): void {
+ this.timers = this.timers.filter(timer => !timer.isDone);
+ }
+}
+```
+
+### 3. 避免过多的定时器
+
+```typescript
+// ❌ 避免:为每个实体创建定时器
+class BadExample extends EntitySystem {
+ protected onAdded(entity: Entity): void {
+ Core.schedule(1.0, true, entity, (timer) => {
+ // 每个实体一个定时器,性能差
+ });
+ }
+}
+
+// ✅ 推荐:在系统中统一管理时间
+class GoodExample extends EntitySystem {
+ private lastUpdateTime = 0;
+
+ protected process(entities: readonly Entity[]): void {
+ // 每秒执行一次逻辑
+ if (Time.checkEvery(1.0, this.lastUpdateTime)) {
+ this.processAllEntities(entities);
+ this.lastUpdateTime = Time.totalTime;
+ }
+ }
+
+ private processAllEntities(entities: readonly Entity[]): void {
+ // 批量处理所有实体
+ }
+}
+```
+
+### 4. 定时器上下文使用
+
+```typescript
+interface TimerContext {
+ entityId: number;
+ duration: number;
+ onComplete: () => void;
+}
+
+class ContextualTimerExample {
+ public createEntityTimer(entityId: number, duration: number, onComplete: () => void): void {
+ const context: TimerContext = {
+ entityId,
+ duration,
+ onComplete
+ };
+
+ Core.schedule(duration, false, context, (timer) => {
+ const ctx = timer.getContext();
+ console.log(`实体 ${ctx.entityId} 的定时器完成`);
+ ctx.onComplete();
+ });
+ }
+}
+```
+
+时间和定时器系统是游戏开发中的重要工具,正确使用这些功能能让你的游戏逻辑更加精确和可控。
\ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 00000000..01302665
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,23 @@
+---
+layout: home
+
+hero:
+ name: "ECS Framework"
+ text: "高性能ECS框架"
+ tagline: "为Javascript游戏开发而设计"
+ actions:
+ - theme: brand
+ text: 快速开始
+ link: /guide/getting-started
+ - theme: alt
+ text: 查看示例
+ link: https://github.com/esengine/lawn-mower-demo
+
+features:
+ - title: 高性能
+ details: 支持大规模实体处理
+ - title: 类型安全
+ details: 完整的TypeScript支持,编译时类型检查
+ - title: 模块化设计
+ details: 核心功能独立打包,支持多平台
+---
\ No newline at end of file
diff --git a/docs/performance-optimization.md b/docs/performance-optimization.md
deleted file mode 100644
index 232a9a86..00000000
--- a/docs/performance-optimization.md
+++ /dev/null
@@ -1,425 +0,0 @@
-# 性能优化指南
-
-本文档介绍ECS框架的性能优化技术和最佳实践。
-
-## 目录
-
-1. [查询系统优化](#查询系统优化)
-2. [实体管理优化](#实体管理优化)
-3. [组件设计优化](#组件设计优化)
-4. [系统设计优化](#系统设计优化)
-5. [内存管理](#内存管理)
-6. [性能监控](#性能监控)
-
-## 查询系统优化
-
-### 使用高效的查询方法
-
-```typescript
-// 推荐:使用标签查询(快速)
-const enemies = entityManager.getEntitiesByTag(2);
-
-// 推荐:使用组件查询
-const healthEntities = entityManager.getEntitiesWithComponent(HealthComponent);
-
-// 推荐:使用Scene的查询系统
-const movingEntities = scene.querySystem.queryAll(PositionComponent, VelocityComponent);
-
-// 谨慎:自定义条件查询(较慢)
-const nearbyEnemies = entityManager
- .query()
- .withAll(PositionComponent)
- .where(entity => {
- const pos = entity.getComponent(PositionComponent);
- return pos && Math.abs(pos.x - playerX) < 100;
- })
- .execute();
-```
-
-### 查询结果缓存
-
-```typescript
-class OptimizedCombatSystem extends EntitySystem {
- private cachedEnemies: Entity[] = [];
- private lastCacheUpdate = 0;
- private cacheInterval = 5; // 每5帧更新一次
-
- protected process(entities: Entity[]): void {
- // 缓存查询结果
- if (Time.frameCount - this.lastCacheUpdate >= this.cacheInterval) {
- this.cachedEnemies = this.entityManager.getEntitiesByTag(2);
- this.lastCacheUpdate = Time.frameCount;
- }
-
- // 使用缓存的结果
- this.cachedEnemies.forEach(enemy => {
- this.processEnemy(enemy);
- });
- }
-
- private processEnemy(enemy: Entity): void {
- // 处理敌人逻辑
- }
-}
-```
-
-## 实体管理优化
-
-### 批量创建实体
-
-```typescript
-// 推荐:使用Scene的批量创建
-function createEnemyWave(count: number): Entity[] {
- const enemies = scene.createEntities(count, "Enemy");
-
- // 批量配置组件
- enemies.forEach((enemy, index) => {
- enemy.addComponent(new PositionComponent(
- Math.random() * 800,
- Math.random() * 600
- ));
- enemy.addComponent(new HealthComponent(100));
- enemy.addComponent(new AIComponent());
- enemy.tag = 2; // 敌人标签
- });
-
- return enemies;
-}
-
-// ❌ 避免:循环单独创建
-function createEnemyWaveSlow(count: number): Entity[] {
- const enemies: Entity[] = [];
- for (let i = 0; i < count; i++) {
- const enemy = entityManager.createEntity(`Enemy_${i}`);
- enemy.addComponent(new PositionComponent());
- enemy.addComponent(new HealthComponent());
- enemies.push(enemy);
- }
- return enemies;
-}
-```
-
-### 实体复用策略
-
-```typescript
-// 使用简单的实体复用策略
-class EntityReusableManager {
- private inactiveEntities: Entity[] = [];
- private scene: Scene;
-
- constructor(scene: Scene) {
- this.scene = scene;
- }
-
- // 预创建实体
- preCreateEntities(count: number, entityName: string): void {
- const entities = this.scene.createEntities(count, entityName);
- entities.forEach(entity => {
- entity.enabled = false; // 禁用但不销毁
- this.inactiveEntities.push(entity);
- });
- }
-
- // 获取可复用实体
- getReusableEntity(): Entity | null {
- if (this.inactiveEntities.length > 0) {
- const entity = this.inactiveEntities.pop()!;
- entity.enabled = true;
- return entity;
- }
- return null;
- }
-
- // 回收实体
- recycleEntity(entity: Entity): void {
- entity.enabled = false;
- entity.removeAllComponents();
- this.inactiveEntities.push(entity);
- }
-}
-```
-
-## 组件设计优化
-
-### 数据局部性优化
-
-```typescript
-// 推荐:紧凑的数据结构
-class OptimizedPositionComponent extends Component {
- public x: number = 0;
- public y: number = 0;
- public z: number = 0;
-
- // 避免对象分配
- public setPosition(x: number, y: number, z: number = 0): void {
- this.x = x;
- this.y = y;
- this.z = z;
- }
-}
-
-// ❌ 避免:过多对象分配
-class SlowPositionComponent extends Component {
- public position: { x: number; y: number; z: number } = { x: 0, y: 0, z: 0 };
- public velocity: { x: number; y: number; z: number } = { x: 0, y: 0, z: 0 };
- public acceleration: { x: number; y: number; z: number } = { x: 0, y: 0, z: 0 };
-}
-```
-
-### 组件池化
-
-```typescript
-// 使用框架内置的组件池
-ComponentPoolManager.getInstance().registerPool(
- 'BulletComponent',
- () => new BulletComponent(),
- (bullet) => bullet.reset(),
- 1000
-);
-
-// 获取组件
-const bullet = ComponentPoolManager.getInstance().acquireComponent('BulletComponent');
-if (bullet) {
- entity.addComponent(bullet);
-}
-
-// 释放组件
-ComponentPoolManager.getInstance().releaseComponent('BulletComponent', bullet);
-```
-
-## 系统设计优化
-
-### 系统更新顺序优化
-
-```typescript
-class OptimizedGameManager {
- private scene: Scene;
-
- constructor() {
- this.scene = new Scene();
- this.setupSystems();
- }
-
- private setupSystems(): void {
- // 按依赖关系排序系统
- this.scene.addEntityProcessor(new InputSystem()).updateOrder = 10;
- this.scene.addEntityProcessor(new MovementSystem()).updateOrder = 20;
- this.scene.addEntityProcessor(new CollisionSystem()).updateOrder = 30;
- this.scene.addEntityProcessor(new RenderSystem()).updateOrder = 40;
- this.scene.addEntityProcessor(new CleanupSystem()).updateOrder = 50;
- }
-}
-```
-
-### 时间分片处理
-
-```typescript
-class TimeSlicedAISystem extends EntitySystem {
- private aiEntities: Entity[] = [];
- private currentIndex = 0;
- private entitiesPerFrame = 10;
-
- protected process(entities: Entity[]): void {
- // 获取所有AI实体
- if (this.aiEntities.length === 0) {
- this.aiEntities = this.entityManager.getEntitiesByTag(3); // AI标签
- }
-
- // 每帧只处理部分实体
- const endIndex = Math.min(
- this.currentIndex + this.entitiesPerFrame,
- this.aiEntities.length
- );
-
- for (let i = this.currentIndex; i < endIndex; i++) {
- this.processAI(this.aiEntities[i]);
- }
-
- // 更新索引
- this.currentIndex = endIndex;
- if (this.currentIndex >= this.aiEntities.length) {
- this.currentIndex = 0;
- this.aiEntities = []; // 重新获取实体列表
- }
- }
-
- private processAI(entity: Entity): void {
- // AI处理逻辑
- }
-}
-```
-
-## 内存管理
-
-### 及时清理无用实体
-
-```typescript
-class CleanupSystem extends EntitySystem {
- protected process(entities: Entity[]): void {
- // 清理超出边界的子弹
- const bullets = this.entityManager.getEntitiesByTag(4); // 子弹标签
- bullets.forEach(bullet => {
- const pos = bullet.getComponent(PositionComponent);
- if (pos && this.isOutOfBounds(pos)) {
- this.entityManager.destroyEntity(bullet);
- }
- });
-
- // 清理死亡的实体
- const deadEntities = this.entityManager
- .query()
- .withAll(HealthComponent)
- .where(entity => {
- const health = entity.getComponent(HealthComponent);
- return health && health.currentHealth <= 0;
- })
- .execute();
-
- deadEntities.forEach(entity => {
- this.entityManager.destroyEntity(entity);
- });
- }
-
- private isOutOfBounds(pos: PositionComponent): boolean {
- return pos.x < -100 || pos.x > 900 || pos.y < -100 || pos.y > 700;
- }
-}
-```
-
-### 实体复用管理
-
-```typescript
-class GameEntityManager {
- private bulletManager: EntityReusableManager;
- private effectManager: EntityReusableManager;
-
- constructor(scene: Scene) {
- this.bulletManager = new EntityReusableManager(scene);
- this.effectManager = new EntityReusableManager(scene);
-
- // 预创建实体
- this.bulletManager.preCreateEntities(100, "Bullet");
- this.effectManager.preCreateEntities(50, "Effect");
- }
-
- createBullet(): Entity | null {
- const bullet = this.bulletManager.getReusableEntity();
- if (bullet) {
- bullet.addComponent(new BulletComponent());
- bullet.addComponent(new PositionComponent());
- bullet.addComponent(new VelocityComponent());
- }
- return bullet;
- }
-
- destroyBullet(bullet: Entity): void {
- this.bulletManager.recycleEntity(bullet);
- }
-}
-```
-
-## 性能监控
-
-### 基础性能统计
-
-```typescript
-class PerformanceMonitor {
- private scene: Scene;
- private entityManager: EntityManager;
-
- constructor(scene: Scene, entityManager: EntityManager) {
- this.scene = scene;
- this.entityManager = entityManager;
- }
-
- public getPerformanceReport(): any {
- return {
- // 实体统计
- entities: {
- total: this.entityManager.entityCount,
- active: this.entityManager.activeEntityCount
- },
-
- // 场景统计
- scene: this.scene.getStats(),
-
- // 查询系统统计
- querySystem: this.scene.querySystem.getStats(),
-
- // 内存使用
- memory: {
- used: (performance as any).memory?.usedJSHeapSize || 0,
- total: (performance as any).memory?.totalJSHeapSize || 0
- }
- };
- }
-
- public logPerformance(): void {
- const report = this.getPerformanceReport();
- console.log('性能报告:', report);
- }
-}
-```
-
-### 帧率监控
-
-```typescript
-class FPSMonitor {
- private frameCount = 0;
- private lastTime = performance.now();
- private fps = 0;
-
- public update(): void {
- this.frameCount++;
- const currentTime = performance.now();
-
- if (currentTime - this.lastTime >= 1000) {
- this.fps = this.frameCount;
- this.frameCount = 0;
- this.lastTime = currentTime;
-
- if (this.fps < 30) {
- console.warn(`低帧率警告: ${this.fps} FPS`);
- }
- }
- }
-
- public getFPS(): number {
- return this.fps;
- }
-}
-```
-
-## 最佳实践总结
-
-### 查询优化
-1. 优先使用标签查询和组件查询
-2. 缓存频繁使用的查询结果
-3. 避免过度使用自定义条件查询
-4. 合理设置查询缓存更新频率
-
-### 实体管理
-1. 使用批量创建方法
-2. 实现实体池化减少GC压力
-3. 及时清理无用实体
-4. 合理设置实体标签
-
-### 组件设计
-1. 保持组件数据紧凑
-2. 避免在组件中分配大量对象
-3. 使用组件池化
-4. 分离数据和行为
-
-### 系统设计
-1. 合理安排系统更新顺序
-2. 对重计算任务使用时间分片
-3. 避免在系统中进行复杂查询
-4. 缓存系统间的共享数据
-
-### 内存管理
-1. 定期清理无用实体和组件
-2. 使用对象池减少GC
-3. 监控内存使用情况
-4. 避免内存泄漏
-
-通过遵循这些最佳实践,可以显著提升ECS框架的性能表现。
\ No newline at end of file
diff --git a/docs/query-system-usage.md b/docs/query-system-usage.md
deleted file mode 100644
index 860edbe4..00000000
--- a/docs/query-system-usage.md
+++ /dev/null
@@ -1,646 +0,0 @@
- # QuerySystem 使用指南
-
-QuerySystem 是 ECS Framework 中的高性能实体查询系统,支持多级索引、智能缓存和类型安全的查询操作。
-
-## 基本用法
-
-### 1. 获取查询系统
-
-```typescript
-import { Scene, Entity } from '@esengine/ecs-framework';
-
-// 创建场景,查询系统会自动创建
-const scene = new Scene();
-const querySystem = scene.querySystem;
-
-// 或者从Core获取当前场景的查询系统
-import { Core } from '@esengine/ecs-framework';
-const currentQuerySystem = Core.scene?.querySystem;
-```
-
-### 2. 基本查询操作
-
-```typescript
-// 查询包含所有指定组件的实体
-const result = querySystem.queryAll(PositionComponent, VelocityComponent);
-console.log(`找到 ${result.count} 个实体`);
-
-// 查询包含任意指定组件的实体
-const anyResult = querySystem.queryAny(HealthComponent, ManaComponent);
-
-// 查询不包含指定组件的实体
-const noneResult = querySystem.queryNone(DeadComponent);
-```
-
-### 3. 类型安全查询
-
-```typescript
-// 类型安全的查询,返回实体和对应的组件
-const typedResult = querySystem.queryAll(PositionComponent, VelocityComponent);
-for (let i = 0; i < typedResult.entities.length; i++) {
- const entity = typedResult.entities[i];
- const [position, velocity] = typedResult.components[i];
- // position 和 velocity 都是类型安全的
-}
-
-// 查询单个组件类型
-const healthResult = querySystem.queryAll(HealthComponent);
-for (const entity of healthResult.entities) {
- const health = entity.getComponent(HealthComponent);
- if (health) {
- console.log(`实体 ${entity.name} 的生命值: ${health.value}`);
- }
-}
-
-// 查询两个组件类型
-const movableResult = querySystem.queryAll(PositionComponent, VelocityComponent);
-for (const entity of movableResult.entities) {
- const position = entity.getComponent(PositionComponent);
- const velocity = entity.getComponent(VelocityComponent);
- if (position && velocity) {
- // 更新位置
- position.x += velocity.x;
- position.y += velocity.y;
- }
-}
-```
-
-### 4. 使用查询构建器
-
-```typescript
-// QuerySystem不提供查询构建器,请使用Matcher进行复杂查询
-// 推荐使用Matcher配合EntitySystem
-
-import { Matcher } from '@esengine/ecs-framework';
-
-// 创建复杂查询条件
-const visibleMatcher = Matcher.all(PositionComponent, RenderComponent)
- .none(HiddenComponent);
-
-// 通过QuerySystem执行查询
-const visibleEntities = querySystem.query(visibleMatcher.getCondition());
-
-// 过滤和排序需要手动处理
-const sortedEntities = visibleEntities.entities
- .filter(entity => entity.name.startsWith('Boss'))
- .sort((a, b) => a.id - b.id)
- .slice(0, 10); // 限制数量
-
-// 迭代结果
-sortedEntities.forEach((entity, index) => {
- console.log(`敌人 ${index}: ${entity.name}`);
-});
-```
-
-### 5. 高级查询功能
-
-```typescript
-// QuerySystem主要提供基础查询方法
-// 复杂查询推荐使用Matcher和EntitySystem
-
-// 基本查询
-const positionResult = querySystem.queryAll(PositionComponent, VelocityComponent);
-const healthResult = querySystem.queryAll(HealthComponent);
-const manaResult = querySystem.queryAll(ManaComponent);
-
-// 排除死亡实体的移动实体
-const aliveMovingEntities = positionResult.entities.filter(entity =>
- !entity.hasComponent(DeadComponent)
-);
-
-// 如果需要复杂查询,推荐在EntitySystem中使用Matcher
-class ComplexQuerySystem extends EntitySystem {
- constructor() {
- super(Matcher.all(PositionComponent, VelocityComponent).none(DeadComponent));
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是过滤后的结果
- for (const entity of entities) {
- // 处理逻辑
- }
- }
-}
-```
-
-## 场景级别的实体查询
-
-除了使用QuerySystem,您还可以直接使用Scene提供的便捷查询方法:
-
-### 基本场景查询
-
-```typescript
-// 按名称查找实体
-const player = scene.findEntity("Player");
-const playerAlt = scene.getEntityByName("Player"); // 别名方法
-
-// 按ID查找实体
-const entity = scene.findEntityById(123);
-
-// 按标签查找实体
-const enemies = scene.findEntitiesByTag(2);
-const enemiesAlt = scene.getEntitiesByTag(2); // 别名方法
-
-// 获取所有实体
-const allEntities = scene.entities.buffer;
-```
-
-## 性能优化
-
-### 1. 缓存管理
-
-```typescript
-// 设置缓存配置
-querySystem.setCacheConfig(200, 2000); // 最大200个缓存项,2秒超时
-
-// 清空缓存
-querySystem.clearCache();
-
-// 预热常用查询(使用基础查询方法)
-querySystem.queryAll(PositionComponent); // 预热Position查询
-querySystem.queryAll(VelocityComponent); // 预热Velocity查询
-```
-
-### 2. 索引优化
-
-```typescript
-// 获取性能统计
-const stats = querySystem.getStats();
-console.log(`缓存命中率: ${(stats.hitRate * 100).toFixed(1)}%`);
-console.log(`实体数量: ${stats.entityCount}`);
-
-// 获取详细性能报告
-const report = querySystem.getPerformanceReport();
-console.log(report);
-```
-
-### 3. 查询监听和快照
-
-```typescript
-// QuerySystem主要用于基础查询,高级功能请使用EntitySystem和事件系统
-
-// 如需监听实体变化,使用事件系统
-scene.entityManager.eventBus.on('entity:added', (entity) => {
- if (entity.hasComponent(EnemyComponent)) {
- console.log('新增敌人实体');
- }
-});
-
-scene.entityManager.eventBus.on('entity:removed', (entity) => {
- if (entity.hasComponent(EnemyComponent)) {
- console.log('移除敌人实体');
- }
-});
-
-// 手动创建快照进行比较
-const snapshot1 = querySystem.queryAll(PlayerComponent).entities.map(e => e.id);
-// 稍后
-const snapshot2 = querySystem.queryAll(PlayerComponent).entities.map(e => e.id);
-
-// 比较快照
-const added = snapshot2.filter(id => !snapshot1.includes(id));
-const removed = snapshot1.filter(id => !snapshot2.includes(id));
-console.log(`新增: ${added.length}, 移除: ${removed.length}`);
-```
-
-## 使用Matcher进行高级查询
-
-Matcher是一个优雅的查询封装器,提供流畅的API和强大的缓存机制。
-
-### 基本Matcher用法
-
-```typescript
-import { Matcher } from '@esengine/ecs-framework';
-
-// 创建Matcher查询条件
-const movingMatcher = Matcher.all(PositionComponent, VelocityComponent);
-// 在QuerySystem中需要使用基础查询方法
-const movingEntities = scene.querySystem.queryAll(PositionComponent, VelocityComponent).entities;
-
-// 复合查询需要使用EntitySystem或手动过滤
-const aliveEnemiesMatcher = Matcher.all(EnemyComponent, HealthComponent)
- .any(WeaponComponent, MagicComponent)
- .none(DeadComponent, StunnedComponent);
-
-// 在EntitySystem中使用
-class AliveEnemySystem extends EntitySystem {
- constructor() {
- super(aliveEnemiesMatcher);
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是匹配的实体
- for (const entity of entities) {
- // 处理存活的敌人
- }
- }
-}
-
-// 或者手动过滤
-const enemyResult = scene.querySystem.queryAll(EnemyComponent, HealthComponent);
-const aliveEnemies = enemyResult.entities.filter(entity => {
- const hasWeaponOrMagic = entity.hasComponent(WeaponComponent) || entity.hasComponent(MagicComponent);
- const isAlive = !entity.hasComponent(DeadComponent) && !entity.hasComponent(StunnedComponent);
- return hasWeaponOrMagic && isAlive;
-});
-
-// 单个实体检查
-const playerResult = scene.querySystem.queryAll(PlayerComponent);
-if (playerResult.entities.includes(someEntity)) {
- console.log('这是玩家实体');
-}
-
-// 统计信息
-console.log(`玩家数量: ${playerResult.count}`);
-console.log(`是否有玩家: ${playerResult.count > 0}`);
-```
-
-### 系统中使用Matcher
-
-```typescript
-import { EntitySystem, Entity, Matcher } from '@esengine/ecs-framework';
-
-class MovementSystem extends EntitySystem {
- constructor() {
- // 在构造函数中直接传入Matcher
- super(Matcher.all(PositionComponent, VelocityComponent));
- }
-
- protected process(entities: Entity[]): void {
- // entities参数已经是系统自动过滤后的实体
- for (const entity of entities) {
- const position = entity.getComponent(PositionComponent)!;
- const velocity = entity.getComponent(VelocityComponent)!;
-
- // 更新位置
- position.x += velocity.x * Time.deltaTime;
- position.y += velocity.y * Time.deltaTime;
-
- // 边界检查
- if (position.x < 0 || position.x > 800) {
- velocity.x = -velocity.x;
- }
- if (position.y < 0 || position.y > 600) {
- velocity.y = -velocity.y;
- }
- }
- }
-}
-```
-
-### 碰撞检测示例
-
-```typescript
-class CollisionSystem extends EntitySystem {
- constructor() {
- // 在构造函数中传入Matcher
- super(Matcher.all(PositionComponent, ColliderComponent));
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是匹配的实体
- const collidableEntities = entities;
-
- // 检测碰撞
- for (let i = 0; i < collidableEntities.length; i++) {
- for (let j = i + 1; j < collidableEntities.length; j++) {
- const entityA = collidableEntities[i];
- const entityB = collidableEntities[j];
-
- if (this.checkCollision(entityA, entityB)) {
- this.handleCollision(entityA, entityB);
- }
- }
- }
- }
-
- private checkCollision(entityA: Entity, entityB: Entity): boolean {
- const posA = entityA.getComponent(PositionComponent)!;
- const posB = entityB.getComponent(PositionComponent)!;
- const distance = Math.sqrt(
- Math.pow(posA.x - posB.x, 2) + Math.pow(posA.y - posB.y, 2)
- );
- return distance < 50;
- }
-
- private handleCollision(entityA: Entity, entityB: Entity): void {
- console.log(`碰撞检测: ${entityA.name} 与 ${entityB.name}`);
- }
-}
-```
-
-### 生命值管理示例
-
-```typescript
-class HealthSystem extends EntitySystem {
- constructor() {
- // 在构造函数中传入Matcher
- super(Matcher.all(HealthComponent));
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是匹配的实体
- const healthEntities = entities;
- const deadEntities: Entity[] = [];
-
- for (const entity of healthEntities) {
- const health = entity.getComponent(HealthComponent)!;
-
- // 检查死亡
- if (health.currentHealth <= 0) {
- deadEntities.push(entity);
- }
- }
-
- // 移除死亡实体
- deadEntities.forEach(entity => {
- console.log(`实体 ${entity.name} 已死亡`);
- entity.destroy();
- });
- }
-}
-```
-
-### Matcher完整API参考
-
-#### 静态创建方法
-
-```typescript
-// 基础静态方法
-const allMatcher = Matcher.all(PositionComponent, VelocityComponent); // 必须包含所有组件
-const anyMatcher = Matcher.any(WeaponComponent, MagicComponent); // 必须包含任意一个组件
-const noneMatcher = Matcher.none(DeadComponent, DisabledComponent); // 不能包含任何指定组件
-
-// 特殊查询静态方法
-const tagMatcher = Matcher.byTag(1); // 按标签查询
-const nameMatcher = Matcher.byName("Player"); // 按名称查询
-const componentMatcher = Matcher.byComponent(HealthComponent); // 单组件查询
-
-// 构建器方法
-const complexMatcher = Matcher.complex(); // 创建复杂查询构建器
-const emptyMatcher = Matcher.empty(); // 创建空匹配器
-```
-
-#### 实例方法 - 条件构建
-
-```typescript
-// 基础条件方法
-const matcher = Matcher.empty()
- .all(PositionComponent, VelocityComponent) // 必须包含所有组件
- .any(WeaponComponent, MagicComponent) // 必须包含任意一个组件
- .none(DeadComponent, StunnedComponent); // 不能包含任何指定组件
-
-// 别名方法(提供更语义化的API)
-const semanticMatcher = Matcher.empty()
- .all(PositionComponent)
- .exclude(DeadComponent) // exclude() 等同于 none()
- .one(WeaponComponent, MagicComponent); // one() 等同于 any()
-
-// 特殊条件方法
-const advancedMatcher = Matcher.empty()
- .all(EnemyComponent)
- .withTag(2) // 指定标签
- .withName("Boss") // 指定名称
- .withComponent(HealthComponent); // 单组件条件
-```
-
-#### 条件移除方法
-
-```typescript
-// 移除特殊条件
-const matcher = Matcher.byTag(1)
- .withName("Player")
- .withComponent(HealthComponent);
-
-// 移除各种条件
-matcher.withoutTag(); // 移除标签条件
-matcher.withoutName(); // 移除名称条件
-matcher.withoutComponent(); // 移除单组件条件
-```
-
-#### 实用工具方法
-
-```typescript
-// 检查和调试
-const matcher = Matcher.all(PositionComponent, VelocityComponent)
- .none(DeadComponent);
-
-// 检查是否为空条件
-if (matcher.isEmpty()) {
- console.log('匹配器没有设置任何条件');
-}
-
-// 获取条件信息(只读)
-const condition = matcher.getCondition();
-console.log('必须组件:', condition.all.map(c => c.name));
-console.log('任选组件:', condition.any.map(c => c.name));
-console.log('排除组件:', condition.none.map(c => c.name));
-console.log('标签:', condition.tag);
-console.log('名称:', condition.name);
-console.log('单组件:', condition.component?.name);
-
-// 调试输出
-console.log('匹配器描述:', matcher.toString());
-// 输出: "Matcher[all(PositionComponent, VelocityComponent) & none(DeadComponent)]"
-```
-
-#### 克隆和重置
-
-```typescript
-// 克隆匹配器
-const baseMatcher = Matcher.all(PositionComponent);
-const livingMatcher = baseMatcher.clone().all(HealthComponent).none(DeadComponent);
-const deadMatcher = baseMatcher.clone().all(DeadComponent);
-
-// 重置匹配器
-const reusableMatcher = Matcher.all(PositionComponent);
-console.log(reusableMatcher.toString()); // "Matcher[all(PositionComponent)]"
-
-reusableMatcher.reset(); // 清空所有条件
-console.log(reusableMatcher.toString()); // "Matcher[]"
-
-reusableMatcher.all(PlayerComponent); // 重新设置条件
-console.log(reusableMatcher.toString()); // "Matcher[all(PlayerComponent)]"
-```
-
-#### 链式调用示例
-
-```typescript
-// 复杂的链式调用
-const complexMatcher = Matcher.empty()
- .all(PositionComponent, RenderComponent) // 必须有位置和渲染组件
- .any(PlayerComponent, NPCComponent) // 必须是玩家或NPC
- .none(DeadComponent, HiddenComponent) // 不能死亡或隐藏
- .withTag(1) // 标签为1
- .exclude(DisabledComponent); // 不能被禁用
-
-// 在EntitySystem中使用
-class VisibleCharacterSystem extends EntitySystem {
- constructor() {
- super(complexMatcher);
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是符合所有条件的实体
- for (const entity of entities) {
- // 处理可见角色的逻辑
- }
- }
-}
-```
-
-## 最佳实践
-
-### 1. Matcher使用建议
-
-```typescript
-// 推荐的用法:
-const matcher = Matcher.all(Position, Velocity);
-
-// 在系统中使用
-class MySystem extends EntitySystem {
- constructor() {
- super(Matcher.all(RequiredComponent));
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是系统自动过滤的结果
- for (const entity of entities) {
- // 处理逻辑...
- }
- }
-}
-
-// 避免在process方法中重复查询
-class InefficientSystem extends EntitySystem {
- protected process(entities: Entity[]): void {
- // 不必要的额外查询,性能差
- const condition = Matcher.all(RequiredComponent).getCondition();
- const result = this.scene.querySystem.query(condition);
- }
-}
-```
-
-### 2. Matcher API最佳实践
-
-#### 选择合适的创建方式
-
-```typescript
-// 推荐:单一条件使用静态方法
-const movingEntities = Matcher.all(PositionComponent, VelocityComponent);
-const playerEntities = Matcher.byTag(PLAYER_TAG);
-const specificEntity = Matcher.byName("Boss");
-
-// 推荐:复杂条件使用链式调用
-const complexMatcher = Matcher.empty()
- .all(PositionComponent, HealthComponent)
- .any(WeaponComponent, MagicComponent)
- .none(DeadComponent);
-
-// ❌ 不推荐:简单条件使用复杂语法
-const simpleButBad = Matcher.empty().all(PositionComponent);
-// 应该用: Matcher.all(PositionComponent)
-```
-
-#### 合理使用别名方法
-
-```typescript
-// 使用语义化的别名提高可读性
-const combatUnits = Matcher.all(PositionComponent, HealthComponent)
- .one(WeaponComponent, MagicComponent) // one() 比 any() 更语义化
- .exclude(DeadComponent, PacifistComponent); // exclude() 比 none() 更直观
-```
-
-#### 合理的克隆和重用
-
-```typescript
-// 推荐:基础匹配器重用
-const livingEntityMatcher = Matcher.all(HealthComponent).none(DeadComponent);
-const livingPlayerMatcher = livingEntityMatcher.clone().all(PlayerComponent);
-const livingEnemyMatcher = livingEntityMatcher.clone().all(EnemyComponent);
-
-// 推荐:重置匹配器重用
-const reusableMatcher = Matcher.empty();
-
-// 用于玩家系统
-reusableMatcher.reset().all(PlayerComponent);
-const playerSystem = new PlayerSystem(reusableMatcher.clone());
-
-// 用于敌人系统
-reusableMatcher.reset().all(EnemyComponent);
-const enemySystem = new EnemySystem(reusableMatcher.clone());
-```
-
-#### 调试和维护
-
-```typescript
-// 在开发阶段添加调试信息
-const debugMatcher = Matcher.all(ComplexComponent)
- .any(VariantA, VariantB)
- .none(DisabledComponent);
-
-if (DEBUG_MODE) {
- console.log('系统匹配条件:', debugMatcher.toString());
- const condition = debugMatcher.getCondition();
- console.log('预期匹配实体数:',
- scene.querySystem.queryAll(...condition.all).count);
-}
-```
-
-### 3. 查询优化
-
-- **使用Matcher封装复杂查询**:提供更好的可读性和缓存
-- **避免频繁创建查询**:在系统初始化时创建,重复使用
-- **合理使用any()和none()条件**:减少不必要的实体遍历
-- **利用Matcher的缓存机制**:自动优化重复查询性能
-- **使用克隆方法复用基础条件**:避免重复定义相似的匹配条件
-- **选择合适的静态方法**:单一条件优先使用对应的静态方法
-
-### 3. 性能监控
-
-- 定期检查查询性能报告
-- 监控缓存命中率
-- 优化频繁使用的查询
-- 使用性能测试验证优化效果
-
-### 4. 内存管理
-
-- 及时清理不需要的查询监听器
-- 合理设置缓存大小
-- 避免创建过多的查询快照
-- 适当使用Matcher的clone()和reset()方法
-
-### 5. 代码组织
-
-- **系统级别的Matcher**:在系统中创建和管理Matcher
-- **查询逻辑封装**:将复杂查询封装到专门的方法中
-- **条件复用**:使用clone()方法复用基础查询条件
-- **清晰的命名**:给Matcher变量使用描述性的名称
-
-### 6. 迁移指南
-
-系统中Matcher的推荐用法:
-
-```typescript
-// 在EntitySystem中使用Matcher
-class MySystem extends EntitySystem {
- constructor() {
- super(Matcher.all(ComponentA, ComponentB).none(ComponentC));
- }
-
- protected process(entities: Entity[]): void {
- // entities已经是系统自动过滤的结果
- for (const entity of entities) {
- // 处理逻辑
- }
- }
-}
-```
-
-## 使用最佳实践
-
-- 在EntitySystem构造函数中传入Matcher
-- 使用`none()`来排除组件
-- 使用`any()`来匹配任意组件
-- 直接使用EntitySystem的entities参数,避免额外查询
-- 定期检查查询性能和缓存命中率
\ No newline at end of file
diff --git a/docs/scene-management-guide.md b/docs/scene-management-guide.md
deleted file mode 100644
index 5b52091a..00000000
--- a/docs/scene-management-guide.md
+++ /dev/null
@@ -1,1183 +0,0 @@
-# 场景管理完整指南
-
-场景(Scene)是ECS框架中管理游戏对象和系统的核心容器。框架采用融合设计,既支持传统的单Scene模式(向后兼容),也支持高级的多World/多Scene架构。本指南将详细介绍如何有效地使用场景来构建和管理你的游戏。
-
-## 场景基础概念
-
-### 什么是场景?
-
-场景是一个完整的游戏世界容器,它包含:
-- **实体集合** - 所有游戏对象
-- **系统集合** - 处理游戏逻辑的系统
-- **事件系统** - 场景内的事件通信
-- **查询系统** - 高效的实体查询
-- **性能监控** - 场景级别的性能统计
-
-```typescript
-import { Scene, Core } from '@esengine/ecs-framework';
-
-// 创建场景
-const gameScene = new Scene();
-
-// 设置为当前活动场景(推荐使用setScene方法)
-Core.setScene(gameScene);
-```
-
-> **注意**: `Core.scene = ` 设置方式已被标记为废弃,推荐使用 `Core.setScene()` 方法。新方法提供更好的类型安全性和可预测的激活时序。
-
-### 架构选择指南
-
-ECS框架提供两种使用模式:
-
-#### 1. 单Scene模式(默认,向后兼容)
-
-```typescript
-// 传统用法,无需任何修改
-const scene = new Scene();
-Core.setScene(scene);
-```
-
-**适用场景:**
-- 简单游戏、单机游戏
-- 原型开发、快速验证
-- 学习ECS架构
-- 不需要复杂场景管理的项目
-
-#### 2. 多World模式(高级功能)
-
-```typescript
-// 启用World管理器
-Core.enableWorldManager();
-const worldManager = Core.getWorldManager();
-
-// 创建多个World,每个World可包含多个Scene
-const roomWorld = worldManager.createWorld('Room_001');
-const battleScene = roomWorld.createScene('battle');
-const uiScene = roomWorld.createScene('ui');
-
-roomWorld.start();
-roomWorld.setSceneActive('battle', true);
-roomWorld.setSceneActive('ui', true);
-```
-
-**适用场景:**
-- 多人游戏服务器(每个房间一个World)
-- 复杂应用架构(需要场景隔离)
-- 需要并发处理多个游戏世界
-- 高级场景管理需求
-
-### 场景的生命周期
-
-```typescript
-class GameScene extends Scene {
- // 场景开始时调用
- onStart() {
- console.log("场景开始");
- this.initializeScene();
- }
-
- // 场景更新时调用(每帧)
- update() {
- super.update(); // 调用父类更新
-
- // 自定义更新逻辑
- this.updateGameLogic();
- }
-
- // 场景结束时调用
- onDestroy() {
- console.log("场景结束");
- this.cleanup();
- super.onDestroy();
- }
-}
-```
-
-## 基础场景操作
-
-### 1. 创建和配置场景
-
-```typescript
-class MenuScene extends Scene {
- private backgroundMusic: AudioClip;
-
- onStart() {
- this.setupUI();
- this.setupSystems();
- this.setupInput();
- this.playBackgroundMusic();
- }
-
- private setupUI() {
- // 创建菜单UI实体
- const titleEntity = this.createEntity("Title");
- titleEntity.addComponent(new TextComponent("我的游戏", 48));
- titleEntity.addComponent(new PositionComponent(400, 100));
-
- const startButton = this.createEntity("StartButton");
- startButton.addComponent(new ButtonComponent("开始游戏"));
- startButton.addComponent(new PositionComponent(400, 300));
-
- const settingsButton = this.createEntity("SettingsButton");
- settingsButton.addComponent(new ButtonComponent("设置"));
- settingsButton.addComponent(new PositionComponent(400, 400));
-
- const exitButton = this.createEntity("ExitButton");
- exitButton.addComponent(new ButtonComponent("退出"));
- exitButton.addComponent(new PositionComponent(400, 500));
- }
-
- private setupSystems() {
- // 添加UI相关系统
- this.addEntityProcessor(new UIRenderSystem());
- this.addEntityProcessor(new ButtonClickSystem());
- this.addEntityProcessor(new MenuTransitionSystem());
- }
-
- private setupInput() {
- // 监听按钮点击事件
- this.eventBus.on('button:clicked', this.onButtonClicked, this);
- }
-
- private onButtonClicked(data: { buttonName: string }) {
- switch (data.buttonName) {
- case "开始游戏":
- this.transitionToGame();
- break;
- case "设置":
- this.showSettings();
- break;
- case "退出":
- this.exitGame();
- break;
- }
- }
-
- private transitionToGame() {
- // 切换到游戏场景
- const gameScene = new GameScene();
- Core.setScene(gameScene);
- }
-}
-```
-
-### 2. 游戏主场景
-
-```typescript
-class GameScene extends Scene {
- private player: Entity;
- private enemySpawner: Entity;
- private ui: Entity;
-
- onStart() {
- this.setupWorld();
- this.setupPlayer();
- this.setupEnemies();
- this.setupSystems();
- this.setupUI();
- }
-
- private setupWorld() {
- // 创建背景
- const background = this.createEntity("Background");
- background.addComponent(new SpriteComponent("background.png"));
- background.addComponent(new PositionComponent(0, 0));
-
- // 创建边界
- this.createWorldBounds();
- }
-
- private setupPlayer() {
- this.player = this.createEntity("Player");
- this.player.addComponent(new PositionComponent(400, 300));
- this.player.addComponent(new VelocityComponent());
- this.player.addComponent(new HealthComponent(100));
- this.player.addComponent(new SpriteComponent("player.png"));
- this.player.addComponent(new PlayerInputComponent());
- this.player.addComponent(new WeaponComponent());
- this.player.tag = EntityTags.PLAYER;
- }
-
- private setupEnemies() {
- this.enemySpawner = this.createEntity("EnemySpawner");
- this.enemySpawner.addComponent(new SpawnerComponent());
- this.enemySpawner.addComponent(new PositionComponent(0, 0));
- }
-
- private setupSystems() {
- // 输入系统
- this.addEntityProcessor(new PlayerInputSystem()).updateOrder = 0;
-
- // 游戏逻辑系统
- this.addEntityProcessor(new MovementSystem()).updateOrder = 10;
- this.addEntityProcessor(new AISystem()).updateOrder = 15;
- this.addEntityProcessor(new WeaponSystem()).updateOrder = 20;
- this.addEntityProcessor(new CollisionSystem()).updateOrder = 30;
- this.addEntityProcessor(new HealthSystem()).updateOrder = 40;
-
- // 生成和清理系统
- this.addEntityProcessor(new EnemySpawnSystem()).updateOrder = 50;
- this.addEntityProcessor(new EntityCleanupSystem()).updateOrder = 60;
-
- // 渲染系统
- this.addEntityProcessor(new RenderSystem()).updateOrder = 100;
- this.addEntityProcessor(new UIRenderSystem()).updateOrder = 110;
-
- // 特效和音频系统
- this.addEntityProcessor(new ParticleSystem()).updateOrder = 120;
- this.addEntityProcessor(new AudioSystem()).updateOrder = 130;
- }
-
- private setupUI() {
- this.ui = this.createEntity("GameUI");
- this.ui.addComponent(new HealthBarComponent());
- this.ui.addComponent(new ScoreDisplayComponent());
- this.ui.addComponent(new AmmoDisplayComponent());
- }
-
- private createWorldBounds() {
- // 创建世界边界,防止实体跑出屏幕
- const bounds = [
- { x: 0, y: 0, width: 10, height: 600 }, // 左边界
- { x: 790, y: 0, width: 10, height: 600 }, // 右边界
- { x: 0, y: 0, width: 800, height: 10 }, // 上边界
- { x: 0, y: 590, width: 800, height: 10 } // 下边界
- ];
-
- bounds.forEach((bound, index) => {
- const wall = this.createEntity(`Wall_${index}`);
- wall.addComponent(new PositionComponent(bound.x, bound.y));
- wall.addComponent(new ColliderComponent(bound.width, bound.height));
- wall.addComponent(new WallComponent());
- wall.tag = EntityTags.WALL;
- });
- }
-}
-```
-
-## World多场景管理
-
-### 1. World基础使用
-
-对于需要复杂场景管理的项目,可以使用World系统:
-
-```typescript
-import { Core, World, Scene, WorldManager, IGlobalSystem } from '@esengine/ecs-framework';
-
-// 定义全局系统(跨Scene的业务逻辑)
-class NetworkSyncSystem implements IGlobalSystem {
- public readonly name = 'NetworkSyncSystem';
-
- public initialize(): void {
- console.log('网络同步系统初始化');
- }
-
- public update(): void {
- // 同步所有Scene的网络状态
- this.syncNetworkData();
- }
-
- public reset(): void {
- // 重置网络连接
- }
-
- public destroy(): void {
- console.log('网络同步系统销毁');
- }
-
- private syncNetworkData(): void {
- // 网络数据同步逻辑
- }
-}
-
-class PlayerManagementSystem implements IGlobalSystem {
- public readonly name = 'PlayerManagementSystem';
-
- public initialize(): void {
- console.log('玩家管理系统初始化');
- }
-
- public update(): void {
- // 管理跨Scene的玩家数据
- this.managePlayerStates();
- }
-
- public reset(): void {
- // 重置玩家状态
- }
-
- public destroy(): void {
- console.log('玩家管理系统销毁');
- }
-
- private managePlayerStates(): void {
- // 玩家状态管理逻辑
- }
-}
-
-// 启用World管理功能
-Core.enableWorldManager();
-const worldManager = Core.getWorldManager();
-
-// 创建游戏房间World
-const roomWorld = worldManager.createWorld('GameRoom_001', {
- name: 'GameRoom_001',
- maxScenes: 5,
- autoCleanup: true,
- debug: true
-});
-
-// 在World中创建多个Scene
-const gameScene = roomWorld.createScene('game', new GameScene());
-const uiScene = roomWorld.createScene('ui', new UIScene());
-const backgroundScene = roomWorld.createScene('background', new BackgroundScene());
-
-// 添加全局系统(跨Scene的系统)
-roomWorld.addGlobalSystem(new NetworkSyncSystem());
-roomWorld.addGlobalSystem(new PlayerManagementSystem());
-
-// 启动World并激活Scene
-roomWorld.start();
-roomWorld.setSceneActive('game', true);
-roomWorld.setSceneActive('ui', true);
-roomWorld.setSceneActive('background', true);
-```
-
-### 2. 多房间游戏服务器示例
-
-```typescript
-// 房间管理系统
-class RoomManagementSystem implements IGlobalSystem {
- public readonly name = 'RoomManagementSystem';
- private roomId: string;
-
- constructor(roomId: string) {
- this.roomId = roomId;
- }
-
- public initialize(): void {
- console.log(`房间管理系统初始化: ${this.roomId}`);
- }
-
- public update(): void {
- // 管理房间状态、玩家进出等
- this.manageRoomState();
- }
-
- public reset(): void {
- // 重置房间状态
- }
-
- public destroy(): void {
- console.log(`房间管理系统销毁: ${this.roomId}`);
- }
-
- private manageRoomState(): void {
- // 房间状态管理逻辑
- }
-}
-
-// 玩家同步系统
-class PlayerSyncSystem implements IGlobalSystem {
- public readonly name = 'PlayerSyncSystem';
-
- public initialize(): void {
- console.log('玩家同步系统初始化');
- }
-
- public update(): void {
- // 同步房间内所有玩家的状态
- this.syncPlayerData();
- }
-
- public reset(): void {
- // 重置同步状态
- }
-
- public destroy(): void {
- console.log('玩家同步系统销毁');
- }
-
- private syncPlayerData(): void {
- // 玩家数据同步逻辑
- }
-}
-
-class MultiRoomGameServer {
- private worldManager: WorldManager;
- private rooms: Map = new Map();
-
- constructor() {
- Core.create({ debug: false });
- Core.enableWorldManager();
- this.worldManager = Core.getWorldManager();
- }
-
- // 创建游戏房间
- createRoom(roomId: string): World {
- const roomWorld = this.worldManager.createWorld(`Room_${roomId}`, {
- name: `GameRoom_${roomId}`,
- maxScenes: 3,
- autoCleanup: true
- });
-
- // 房间内的Scene设置
- const gameScene = roomWorld.createScene('game', new ServerGameScene());
- const lobbyScene = roomWorld.createScene('lobby', new LobbyScene());
-
- // 设置房间级的全局系统
- roomWorld.addGlobalSystem(new RoomManagementSystem(roomId));
- roomWorld.addGlobalSystem(new PlayerSyncSystem());
-
- // 启动房间
- roomWorld.start();
- roomWorld.setSceneActive('lobby', true); // 默认激活大厅
-
- this.rooms.set(roomId, roomWorld);
- console.log(`创建房间: ${roomId}`);
-
- return roomWorld;
- }
-
- // 开始游戏
- startGame(roomId: string): boolean {
- const roomWorld = this.rooms.get(roomId);
- if (!roomWorld) return false;
-
- // 停用大厅,激活游戏Scene
- roomWorld.setSceneActive('lobby', false);
- roomWorld.setSceneActive('game', true);
-
- console.log(`房间 ${roomId} 开始游戏`);
- return true;
- }
-
- // 销毁房间
- destroyRoom(roomId: string): boolean {
- const roomWorld = this.rooms.get(roomId);
- if (!roomWorld) return false;
-
- roomWorld.destroy();
- this.rooms.delete(roomId);
- console.log(`销毁房间: ${roomId}`);
- return true;
- }
-
- // 获取服务器状态
- getServerStats() {
- return {
- totalRooms: this.rooms.size,
- activeWorlds: this.worldManager.getActiveWorlds().length,
- rooms: Array.from(this.rooms.keys()).map(roomId => ({
- roomId,
- world: this.rooms.get(roomId)?.getStatus()
- }))
- };
- }
-
- // 游戏循环
- start(): void {
- const gameLoop = () => {
- const deltaTime = 1000 / 60; // 60 TPS
- Core.update(deltaTime / 1000);
- setTimeout(gameLoop, deltaTime);
- };
- gameLoop();
- }
-}
-
-// 使用示例
-const gameServer = new MultiRoomGameServer();
-gameServer.start();
-
-// 创建房间
-const room1 = gameServer.createRoom('room_001');
-const room2 = gameServer.createRoom('room_002');
-
-// 开始游戏
-setTimeout(() => {
- gameServer.startGame('room_001');
-}, 5000);
-
-console.log('服务器状态:', gameServer.getServerStats());
-```
-
-### 3. 客户端多Scene管理示例
-
-```typescript
-class GameClient {
- private worldManager: WorldManager;
- private mainWorld: World;
-
- constructor() {
- Core.create({ debug: true });
- Core.enableWorldManager();
- this.worldManager = Core.getWorldManager();
-
- this.setupGameWorld();
- }
-
- private setupGameWorld(): void {
- // 创建主游戏世界
- this.mainWorld = this.worldManager.createWorld('MainWorld', {
- name: 'ClientWorld',
- maxScenes: 10,
- autoCleanup: false // 客户端通常不需要自动清理
- });
-
- // 创建不同层级的Scene
- this.createGameplayScenes();
- this.createUIScenes();
- this.createEffectScenes();
-
- // 启动世界
- this.mainWorld.start();
- this.activateDefaultScenes();
- }
-
- private createGameplayScenes(): void {
- // 游戏主场景
- const gameScene = this.mainWorld.createScene('gameplay', new GameplayScene());
-
- // 背景场景
- const backgroundScene = this.mainWorld.createScene('background', new BackgroundScene());
-
- // 特效场景
- const effectsScene = this.mainWorld.createScene('effects', new EffectsScene());
- }
-
- private createUIScenes(): void {
- // 主UI场景
- const mainUIScene = this.mainWorld.createScene('mainUI', new MainUIScene());
-
- // 菜单场景
- const menuScene = this.mainWorld.createScene('menu', new MenuScene());
-
- // 设置场景
- const settingsScene = this.mainWorld.createScene('settings', new SettingsScene());
- }
-
- private createEffectScenes(): void {
- // 粒子效果场景
- const particleScene = this.mainWorld.createScene('particles', new ParticleScene());
-
- // 音效场景
- const audioScene = this.mainWorld.createScene('audio', new AudioScene());
- }
-
- private activateDefaultScenes(): void {
- // 激活基础Scene
- this.mainWorld.setSceneActive('background', true);
- this.mainWorld.setSceneActive('gameplay', true);
- this.mainWorld.setSceneActive('mainUI', true);
- this.mainWorld.setSceneActive('particles', true);
- this.mainWorld.setSceneActive('audio', true);
-
- // 菜单和设置默认不激活
- this.mainWorld.setSceneActive('menu', false);
- this.mainWorld.setSceneActive('settings', false);
- }
-
- // 切换到菜单
- showMenu(): void {
- this.mainWorld.setSceneActive('gameplay', false);
- this.mainWorld.setSceneActive('menu', true);
- }
-
- // 切换回游戏
- hideMenu(): void {
- this.mainWorld.setSceneActive('menu', false);
- this.mainWorld.setSceneActive('gameplay', true);
- }
-
- // 显示设置
- showSettings(): void {
- this.mainWorld.setSceneActive('settings', true);
- }
-
- // 隐藏设置
- hideSettings(): void {
- this.mainWorld.setSceneActive('settings', false);
- }
-
- // 获取World状态
- getWorldStatus() {
- return this.mainWorld.getStatus();
- }
-}
-
-// 使用示例
-const gameClient = new GameClient();
-
-// 显示菜单
-gameClient.showMenu();
-
-// 5秒后返回游戏
-setTimeout(() => {
- gameClient.hideMenu();
-}, 5000);
-
-console.log('客户端World状态:', gameClient.getWorldStatus());
-```
-
-## 传统场景切换和管理
-
-### 1. 单Scene模式场景管理器
-
-> **注意:** 以下的 SceneManager、TransitionManager 等是自定义的场景管理类示例,不是ECS框架提供的内置API。你可以基于这些示例实现自己的场景管理系统。
-
-```typescript
-enum SceneType {
- MENU = "menu",
- GAME = "game",
- PAUSE = "pause",
- GAME_OVER = "game_over",
- SETTINGS = "settings"
-}
-
-// 自定义场景管理器(示例实现)
-class SceneManager {
- private static instance: SceneManager;
- private currentScene: Scene | null = null;
- private previousScene: Scene | null = null;
- private sceneHistory: Scene[] = [];
-
- static getInstance(): SceneManager {
- if (!this.instance) {
- this.instance = new SceneManager();
- }
- return this.instance;
- }
-
- switchToScene(sceneType: SceneType, data?: any) {
- // 保存当前场景到历史
- if (this.currentScene) {
- this.previousScene = this.currentScene;
- this.sceneHistory.push(this.currentScene);
- this.currentScene.onDestroy();
- }
-
- // 创建新场景
- this.currentScene = this.createScene(sceneType, data);
- Core.setScene(this.currentScene);
-
- console.log(`切换到场景: ${sceneType}`);
- }
-
- goBack(): boolean {
- if (this.sceneHistory.length > 0) {
- const previousScene = this.sceneHistory.pop()!;
-
- if (this.currentScene) {
- this.currentScene.onDestroy();
- }
-
- this.currentScene = previousScene;
- Core.setScene(this.currentScene);
- return true;
- }
- return false;
- }
-
- pushScene(sceneType: SceneType, data?: any) {
- // 暂停当前场景,不销毁
- if (this.currentScene) {
- this.previousScene = this.currentScene;
- this.sceneHistory.push(this.currentScene);
- this.pauseScene(this.currentScene);
- }
-
- this.currentScene = this.createScene(sceneType, data);
- Core.setScene(this.currentScene);
- }
-
- popScene() {
- if (this.sceneHistory.length > 0) {
- if (this.currentScene) {
- this.currentScene.onDestroy();
- }
-
- this.currentScene = this.sceneHistory.pop()!;
- this.resumeScene(this.currentScene);
- Core.setScene(this.currentScene);
- }
- }
-
- private createScene(sceneType: SceneType, data?: any): Scene {
- switch (sceneType) {
- case SceneType.MENU:
- return new MenuScene();
- case SceneType.GAME:
- return new GameScene(data);
- case SceneType.PAUSE:
- return new PauseScene();
- case SceneType.GAME_OVER:
- return new GameOverScene(data);
- case SceneType.SETTINGS:
- return new SettingsScene();
- default:
- throw new Error(`Unknown scene type: ${sceneType}`);
- }
- }
-
- private pauseScene(scene: Scene) {
- // 暂停场景的所有系统
- scene.systems.forEach(system => {
- system.enabled = false;
- });
- }
-
- private resumeScene(scene: Scene) {
- // 恢复场景的所有系统
- scene.systems.forEach(system => {
- system.enabled = true;
- });
- }
-}
-
-// 使用场景管理器
-const sceneManager = SceneManager.getInstance();
-
-// 切换场景
-sceneManager.switchToScene(SceneType.MENU);
-
-// 推入场景(用于暂停菜单等)
-sceneManager.pushScene(SceneType.PAUSE);
-
-// 弹出场景(返回游戏)
-sceneManager.popScene();
-```
-
-### 2. 场景转场效果
-
-```typescript
-class TransitionManager {
- private isTransitioning: boolean = false;
-
- async fadeTransition(fromScene: Scene, toScene: Scene, duration: number = 1.0) {
- if (this.isTransitioning) return;
-
- this.isTransitioning = true;
-
- // 创建转场覆盖层
- const overlay = this.createFadeOverlay();
-
- // 淡出当前场景
- await this.fadeOut(overlay, duration / 2);
-
- // 切换场景
- fromScene.onDestroy();
- Core.setScene(toScene);
-
- // 淡入新场景
- await this.fadeIn(overlay, duration / 2);
-
- // 清理覆盖层
- overlay.destroy();
- this.isTransitioning = false;
- }
-
- async slideTransition(fromScene: Scene, toScene: Scene, direction: 'left' | 'right' | 'up' | 'down') {
- if (this.isTransitioning) return;
-
- this.isTransitioning = true;
-
- // 实现滑动转场效果
- const slideDistance = this.getSlideDistance(direction);
-
- // 移动当前场景
- await this.slideScene(fromScene, slideDistance);
-
- // 切换场景
- fromScene.onDestroy();
- Core.setScene(toScene);
-
- // 从相反方向滑入新场景
- await this.slideScene(toScene, -slideDistance);
-
- this.isTransitioning = false;
- }
-
- private createFadeOverlay(): Entity {
- const overlay = Core.scene.createEntity("TransitionOverlay");
- overlay.addComponent(new SpriteComponent("black_pixel.png"));
- overlay.addComponent(new PositionComponent(0, 0));
-
- const sprite = overlay.getComponent(SpriteComponent);
- sprite.width = 800;
- sprite.height = 600;
- sprite.alpha = 0;
-
- return overlay;
- }
-}
-```
-
-## 场景数据管理
-
-### 1. 场景间数据传递
-
-```typescript
-interface GameData {
- score: number;
- level: number;
- playerName: string;
- difficulty: string;
-}
-
-class GameScene extends Scene {
- private gameData: GameData;
-
- constructor(data?: GameData) {
- super();
- this.gameData = data || {
- score: 0,
- level: 1,
- playerName: "Player",
- difficulty: "normal"
- };
- }
-
- onStart() {
- super.onStart();
-
- // 根据传入数据配置场景
- this.setupPlayerWithData();
- this.setupLevelWithDifficulty();
- }
-
- private setupPlayerWithData() {
- const player = this.createEntity("Player");
- player.addComponent(new NameComponent(this.gameData.playerName));
- player.addComponent(new ScoreComponent(this.gameData.score));
- // ... 其他组件
- }
-
- private setupLevelWithDifficulty() {
- const difficultySettings = {
- easy: { enemySpawnRate: 2.0, enemyHealth: 50 },
- normal: { enemySpawnRate: 1.5, enemyHealth: 75 },
- hard: { enemySpawnRate: 1.0, enemyHealth: 100 }
- };
-
- const settings = difficultySettings[this.gameData.difficulty];
-
- const spawner = this.createEntity("EnemySpawner");
- const spawnerComp = new SpawnerComponent();
- spawnerComp.spawnInterval = settings.enemySpawnRate;
- spawnerComp.enemyHealth = settings.enemyHealth;
- spawner.addComponent(spawnerComp);
- }
-
- // 游戏结束时传递数据到下一个场景
- gameOver() {
- const finalScore = this.getPlayerScore();
- const sceneManager = SceneManager.getInstance();
-
- sceneManager.switchToScene(SceneType.GAME_OVER, {
- score: finalScore,
- level: this.gameData.level,
- playerName: this.gameData.playerName
- });
- }
-}
-
-class GameOverScene extends Scene {
- constructor(private gameData: GameData) {
- super();
- }
-
- onStart() {
- this.displayResults();
- this.setupRestartButton();
- }
-
- private displayResults() {
- const scoreText = this.createEntity("ScoreText");
- scoreText.addComponent(new TextComponent(`最终分数: ${this.gameData.score}`));
- scoreText.addComponent(new PositionComponent(400, 200));
-
- const levelText = this.createEntity("LevelText");
- levelText.addComponent(new TextComponent(`到达关卡: ${this.gameData.level}`));
- levelText.addComponent(new PositionComponent(400, 250));
- }
-}
-```
-
-### 2. 持久化数据管理
-
-```typescript
-class SaveManager {
- private static SAVE_KEY = "game_save_data";
-
- static saveScene(scene: Scene): void {
- const saveData = {
- playerData: this.extractPlayerData(scene),
- sceneState: this.extractSceneState(scene),
- timestamp: Date.now()
- };
-
- localStorage.setItem(this.SAVE_KEY, JSON.stringify(saveData));
- console.log("游戏已保存");
- }
-
- static loadScene(): Scene | null {
- const saveDataStr = localStorage.getItem(this.SAVE_KEY);
- if (!saveDataStr) return null;
-
- try {
- const saveData = JSON.parse(saveDataStr);
- return this.recreateScene(saveData);
- } catch (error) {
- console.error("读取存档失败:", error);
- return null;
- }
- }
-
- private static extractPlayerData(scene: Scene): any {
- const player = scene.findEntitiesWithTag(EntityTags.PLAYER)[0];
- if (!player) return null;
-
- return {
- position: player.getComponent(PositionComponent),
- health: player.getComponent(HealthComponent),
- inventory: player.getComponent(InventoryComponent)?.getItems(),
- score: player.getComponent(ScoreComponent)?.score
- };
- }
-
- private static extractSceneState(scene: Scene): any {
- return {
- enemies: this.extractEnemiesData(scene),
- items: this.extractItemsData(scene),
- level: this.getCurrentLevel(scene)
- };
- }
-
- private static recreateScene(saveData: any): Scene {
- const scene = new GameScene();
-
- // 重建玩家
- this.recreatePlayer(scene, saveData.playerData);
-
- // 重建场景状态
- this.recreateSceneState(scene, saveData.sceneState);
-
- return scene;
- }
-}
-
-// 自动保存系统
-class AutoSaveSystem extends IntervalSystem {
- constructor() {
- super(30.0); // 每30秒自动保存
- }
-
- processSystem() {
- SaveManager.saveScene(this.scene);
- }
-}
-```
-
-## 场景性能优化
-
-### 1. 实体管理优化
-
-```typescript
-class OptimizedScene extends Scene {
- private activeEntities: Set = new Set();
- private inactiveEntities: Set = new Set();
-
- createEntity(name?: string): Entity {
- const entity = super.createEntity(name);
- this.activeEntities.add(entity);
- return entity;
- }
-
- destroyEntity(entity: Entity) {
- this.activeEntities.delete(entity);
- super.destroyEntity(entity);
- }
-
- // 暂时禁用实体而不销毁
- deactivateEntity(entity: Entity) {
- if (this.activeEntities.has(entity)) {
- this.activeEntities.delete(entity);
- this.inactiveEntities.add(entity);
- entity.enabled = false;
- }
- }
-
- // 重新激活实体
- activateEntity(entity: Entity) {
- if (this.inactiveEntities.has(entity)) {
- this.inactiveEntities.delete(entity);
- this.activeEntities.add(entity);
- entity.enabled = true;
- }
- }
-
- // 只更新活跃实体
- update() {
- for (const entity of this.activeEntities) {
- if (entity.enabled) {
- entity.update();
- }
- }
-
- this.updateEntitySystems();
- }
-
- // 批量操作
- deactivateAllEnemies() {
- const enemies = this.findEntitiesWithTag(EntityTags.ENEMY);
- enemies.forEach(enemy => this.deactivateEntity(enemy));
- }
-
- activateAllEnemies() {
- const enemies = Array.from(this.inactiveEntities)
- .filter(entity => entity.hasTag(EntityTags.ENEMY));
- enemies.forEach(enemy => this.activateEntity(enemy));
- }
-}
-```
-
-### 2. 系统性能监控
-
-```typescript
-class PerformanceMonitoredScene extends Scene {
- private systemPerformance: Map = new Map();
-
- addEntityProcessor(system: T): T {
- const wrappedSystem = this.wrapSystemWithMonitoring(system);
- return super.addEntityProcessor(wrappedSystem);
- }
-
- private wrapSystemWithMonitoring(system: T): T {
- const originalUpdate = system.update.bind(system);
- const systemName = system.constructor.name;
-
- system.update = () => {
- const startTime = performance.now();
- originalUpdate();
- const endTime = performance.now();
-
- this.recordSystemPerformance(systemName, endTime - startTime);
- };
-
- return system;
- }
-
- private recordSystemPerformance(systemName: string, duration: number) {
- if (!this.systemPerformance.has(systemName)) {
- this.systemPerformance.set(systemName, []);
- }
-
- const records = this.systemPerformance.get(systemName)!;
- records.push(duration);
-
- // 只保留最近100次记录
- if (records.length > 100) {
- records.shift();
- }
- }
-
- getPerformanceReport(): any {
- const report = {};
-
- this.systemPerformance.forEach((durations, systemName) => {
- const avgDuration = durations.reduce((a, b) => a + b, 0) / durations.length;
- const maxDuration = Math.max(...durations);
- const minDuration = Math.min(...durations);
-
- report[systemName] = {
- average: avgDuration.toFixed(2) + 'ms',
- max: maxDuration.toFixed(2) + 'ms',
- min: minDuration.toFixed(2) + 'ms',
- samples: durations.length
- };
- });
-
- return report;
- }
-
- // 定期输出性能报告
- private performanceReportTimer() {
- Core.schedule(5.0, true, this, () => {
- console.table(this.getPerformanceReport());
- });
- }
-}
-```
-
-## 常见问题和最佳实践
-
-### Q: 何时创建新场景?
-
-A:
-- 游戏的不同阶段(菜单、游戏、设置)
-- 不同的关卡
-- 需要完全不同系统配置的情况
-- 需要清理大量实体时
-
-### Q: 场景切换时如何保持数据?
-
-A:
-1. 使用场景构造函数传递数据
-2. 使用全局数据管理器
-3. 使用本地存储进行持久化
-
-### Q: 如何优化场景性能?
-
-A:
-1. 合理使用实体的启用/禁用
-2. 监控系统性能
-3. 批量操作实体
-4. 使用对象池减少垃圾回收
-
-### Q: 多个场景可以同时存在吗?
-
-A:
-- **单Scene模式**:框架同时只支持一个活跃场景,但可以通过场景栈实现多场景管理(如暂停菜单)
-- **多World模式**:每个World可以包含多个同时激活的Scene,支持复杂的多场景架构
-
-### Q: 什么时候使用World系统?
-
-A:
-- 多人游戏服务器(每个房间独立管理)
-- 需要并发运行多个独立游戏世界
-- 复杂的客户端架构(游戏层、UI层、特效层分离)
-- 需要跨Scene的全局系统支持
-
-### Q: World和Scene的性能影响?
-
-A:
-- **单Scene模式**:最佳性能,适合简单项目
-- **多World模式**:每个World独立更新,合理使用不会显著影响性能
-- **建议**:根据项目复杂度选择合适的架构
-
-### Q: 如何从单Scene迁移到多World?
-
-A:
-```typescript
-// 原始单Scene代码
-const scene = new Scene();
-Core.setScene(scene);
-
-// 迁移到World模式(可选)
-Core.enableWorldManager();
-const world = Core.getWorldManager().createWorld('MainWorld');
-const scene = world.createScene('main', new Scene());
-world.start();
-world.setSceneActive('main', true);
-```
-
-### Q: World系统的最佳实践?
-
-A:
-1. **服务器端**:每个游戏房间使用独立World
-2. **客户端**:按功能层级划分Scene(游戏、UI、特效)
-3. **全局系统**:将跨Scene的逻辑放在World的全局System中
-4. **资源管理**:使用World的autoCleanup功能自动清理空闲资源
-
-通过合理选择单Scene或多World架构,你可以构建出结构清晰、性能优良的游戏架构!
\ No newline at end of file
diff --git a/docs/soa-storage-guide.md b/docs/soa-storage-guide.md
deleted file mode 100644
index 7cc0fa11..00000000
--- a/docs/soa-storage-guide.md
+++ /dev/null
@@ -1,343 +0,0 @@
-# SoA存储优化指南
-
-SoA (Structure of Arrays) 存储模式是ECS框架中的高级性能优化特性,适用于大规模实体系统和批量操作场景。
-
-## 目录
-
-1. [什么是SoA存储](#什么是soa存储)
-2. [适用场景](#适用场景)
-3. [不适用场景](#不适用场景)
-4. [装饰器使用指南](#装饰器使用指南)
-5. [性能对比](#性能对比)
-6. [最佳实践](#最佳实践)
-7. [故障排除](#故障排除)
-
-## 什么是SoA存储
-
-### AoS vs SoA 对比
-
-**传统AoS (Array of Structures):**
-```typescript
-// 数据在内存中的布局
-[{x:1, y:2, z:3}, {x:4, y:5, z:6}, {x:7, y:8, z:9}]
-// 内存布局: x1,y1,z1,x2,y2,z2,x3,y3,z3
-```
-
-**SoA (Structure of Arrays):**
-```typescript
-// 数据在内存中的布局
-{
- x: [1, 4, 7], // Float32Array
- y: [2, 5, 8], // Float32Array
- z: [3, 6, 9] // Float32Array
-}
-// 内存布局: x1,x2,x3,y1,y2,y3,z1,z2,z3
-```
-
-### SoA的优势
-
-- **缓存友好**: 相同类型数据连续存储,提高缓存命中率
-- **向量化优化**: 支持SIMD指令并行处理
-- **内存局部性**: 批量操作时减少缓存miss
-- **类型优化**: 针对不同数据类型使用最优存储格式
-
-## 适用场景
-
-### 推荐使用SoA的场景
-
-1. **大规模实体系统**
- ```typescript
- // 大量相似实体的物理系统
- @EnableSoA
- class PhysicsComponent extends Component {
- @Float64 public x: number = 0;
- @Float64 public y: number = 0;
- @Float32 public velocityX: number = 0;
- @Float32 public velocityY: number = 0;
- }
- ```
-
-2. **频繁批量更新操作**
- ```typescript
- // 每帧更新大量实体位置
- system.performVectorizedOperation((fields, indices) => {
- const x = fields.get('x') as Float32Array;
- const y = fields.get('y') as Float32Array;
- const vx = fields.get('velocityX') as Float32Array;
- const vy = fields.get('velocityY') as Float32Array;
-
- // 向量化更新所有实体
- for (let i = 0; i < indices.length; i++) {
- const idx = indices[i];
- x[idx] += vx[idx] * deltaTime;
- y[idx] += vy[idx] * deltaTime;
- }
- });
- ```
-
-3. **数值密集计算**
- ```typescript
- @EnableSoA
- class AIBrainComponent extends Component {
- @Float32 public neuron1: number = 0;
- @Float32 public neuron2: number = 0;
- @Float32 public output: number = 0;
- }
- ```
-
-## 不适用场景
-
-### ❌ 不推荐使用SoA的场景
-
-1. **小规模系统**
- - SoA的开销大于收益
- - 原始存储更简单高效
-
-2. **随机访问为主**
- ```typescript
- // 经常需要随机获取单个组件
- const component = entityManager.getComponent(randomId, SomeComponent);
- ```
-
-3. **复杂对象为主的组件**
- ```typescript
- // 大量复杂对象,序列化开销大
- class UIComponent extends Component {
- public domElement: HTMLElement;
- public eventHandlers: Map;
- public children: UIComponent[];
- }
- ```
-
-4. **频繁增删实体**
- - SoA在频繁增删时性能不如AoS
- - 适合稳定的实体集合
-
-## 装饰器使用指南
-
-### 基础装饰器
-
-```typescript
-import { Component, EnableSoA, HighPrecision, Float64, Int32, SerializeMap, SerializeSet, SerializeArray, DeepCopy } from '@esengine/ecs-framework';
-
-@EnableSoA // 启用SoA优化
-class GameComponent extends Component {
- // 数值类型装饰器
- @HighPrecision // 高精度数值,保持完整精度
- public entityId: number = 0;
-
- @Float64 // 64位浮点数 (8字节,高精度)
- public precisePosition: number = 0;
-
- @Int32 // 32位整数 (4字节,整数优化)
- public health: number = 100;
-
- // 普通数值 (默认Float32Array,4字节)
- public x: number = 0;
- public y: number = 0;
-
- // 集合类型装饰器
- @SerializeMap
- public playerStats: Map = new Map();
-
- @SerializeSet
- public achievements: Set = new Set();
-
- @SerializeArray
- public inventory: any[] = [];
-
- @DeepCopy
- public config: any = { settings: {} };
-
- // 未装饰的字段自动选择最优存储
- public name: string = ''; // string[] 数组
- public active: boolean = true; // Float32Array (0/1)
- public metadata: any = null; // 复杂对象存储
-}
-```
-
-### 装饰器选择指南
-
-| 装饰器 | 用途 | 存储方式 | 开销 | 适用场景 |
-|--------|------|----------|------|----------|
-| `@HighPrecision` | 高精度数值 | 复杂对象 | 高 | ID、时间戳、大整数 |
-| `@Float64` | 双精度浮点 | Float64Array | 中 | 精密计算 |
-| `@Int32` | 32位整数 | Int32Array | 低 | 整数计数、枚举值 |
-| `@SerializeMap` | Map序列化 | JSON字符串 | 高 | 配置映射、属性集合 |
-| `@SerializeSet` | Set序列化 | JSON字符串 | 高 | 标签集合、ID集合 |
-| `@SerializeArray` | Array序列化 | JSON字符串 | 中 | 列表数据、队列 |
-| `@DeepCopy` | 深拷贝对象 | 复杂对象副本 | 高 | 嵌套配置、独立状态 |
-
-## 性能对比
-
-### 基准测试结果
-
-```
-测试场景: 2000个实体,包含位置、速度、生命值组件
-
-创建性能:
-- 原始存储: 12.45ms
-- SoA存储: 15.72ms (慢26%)
-
-随机访问性能:
-- 原始存储: 8.33ms
-- SoA存储: 14.20ms (慢70%)
-
-批量更新性能:
-- 原始存储: 25.67ms
-- SoA存储: 8.91ms (快188%)
-
-内存使用:
-- 原始存储: ~45KB (对象开销)
-- SoA存储: ~28KB (TypedArray优化)
-```
-
-### 性能权衡总结
-
-- **SoA优势**: 批量操作、内存效率、向量化计算
-- **SoA劣势**: 随机访问、创建开销、复杂度增加
-- **建议**: 大规模批量操作场景使用,小规模随机访问避免使用
-
-## 最佳实践
-
-### 1. 合理的组件设计
-
-```typescript
-// 好的设计:纯数值组件
-@EnableSoA
-class TransformComponent extends Component {
- @Float64 public x: number = 0;
- @Float64 public y: number = 0;
- @Float32 public rotation: number = 0;
- @Float32 public scaleX: number = 1;
- @Float32 public scaleY: number = 1;
-}
-
-// ❌ 不好的设计:混合复杂对象
-@EnableSoA
-class MixedComponent extends Component {
- public x: number = 0;
- public domElement: HTMLElement = null; // 复杂对象开销大
- public callback: Function = null; // 无法序列化
-}
-```
-
-### 2. 批量操作优化
-
-```typescript
-// 使用向量化操作
-const storage = entityManager.getStorage(TransformComponent) as SoAStorage;
-storage.performVectorizedOperation((fields, indices) => {
- const x = fields.get('x') as Float64Array;
- const y = fields.get('y') as Float64Array;
-
- // 批量处理,利用缓存局部性
- for (let i = 0; i < indices.length; i++) {
- const idx = indices[i];
- x[idx] += deltaX;
- y[idx] += deltaY;
- }
-});
-
-// ❌ 避免逐个访问
-for (const entity of entities) {
- const transform = entity.getComponent(TransformComponent);
- transform.x += deltaX;
- transform.y += deltaY;
-}
-```
-
-### 3. 组件分离策略
-
-```typescript
-// 将频繁批量操作的数据分离
-@EnableSoA
-class PositionComponent extends Component {
- @Float32 public x: number = 0;
- @Float32 public y: number = 0;
-}
-
-// 复杂数据使用普通组件
-class MetadataComponent extends Component {
- public name: string = '';
- public config: any = {};
- public references: any[] = [];
-}
-```
-
-### 4. 性能监控
-
-```typescript
-// 监控SoA存储使用情况
-const storage = entityManager.getStorage(MyComponent) as SoAStorage;
-const stats = storage.getStats();
-
-console.log('SoA存储统计:', {
- size: stats.size,
- capacity: stats.capacity,
- memoryUsage: stats.memoryUsage,
- fragmentation: stats.fragmentation,
- fieldStats: stats.fieldStats
-});
-```
-
-## 故障排除
-
-### 常见问题
-
-1. **精度丢失**
- ```typescript
- // 问题:大整数精度丢失
- public bigId: number = Number.MAX_SAFE_INTEGER;
-
- // 解决:使用高精度装饰器
- @HighPrecision
- public bigId: number = Number.MAX_SAFE_INTEGER;
- ```
-
-2. **序列化失败**
- ```typescript
- // 问题:循环引用导致序列化失败
- @SerializeMap
- public cyclicMap: Map = new Map();
-
- // 解决:避免循环引用或使用DeepCopy
- @DeepCopy
- public cyclicData: any = {};
- ```
-
-3. **性能反向优化**
- ```typescript
- // 问题:小规模数据使用SoA
- @EnableSoA // 只有10个实体,不需要SoA
- class SmallComponent extends Component {}
-
- // 解决:移除@EnableSoA装饰器
- class SmallComponent extends Component {}
- ```
-
-### 调试技巧
-
-```typescript
-// 检查存储类型
-const storage = entityManager.getStorage(MyComponent);
-console.log('存储类型:', storage.constructor.name);
-// 输出: 'SoAStorage' 或 'ComponentStorage'
-
-// 检查字段存储方式
-if (storage instanceof SoAStorage) {
- const fieldArray = storage.getFieldArray('myField');
- console.log('字段类型:', fieldArray?.constructor.name);
- // 输出: 'Float32Array', 'Float64Array', 'Int32Array', 或 null
-}
-```
-
-## 总结
-
-SoA存储是一个强大的性能优化工具,但需要在合适的场景下使用:
-
-- **适合**: 大规模、批量操作、数值密集的场景
-- **不适合**: 小规模、随机访问、复杂对象为主的场景
-- **关键**: 通过性能测试验证优化效果,避免过度优化
-
-正确使用SoA存储可以显著提升ECS系统性能,但滥用会带来相反的效果。建议在实际项目中先进行基准测试,确认优化效果后再应用到生产环境。
\ No newline at end of file
diff --git a/docs/system-guide.md b/docs/system-guide.md
deleted file mode 100644
index afb775c7..00000000
--- a/docs/system-guide.md
+++ /dev/null
@@ -1,662 +0,0 @@
-# 系统(System)详解指南
-
-系统是ECS架构中的"S",负责处理拥有特定组件的实体。本指南详细介绍框架中的各种系统类型及其使用方法。
-
-## 系统基础概念
-
-### 什么是系统?
-
-系统是处理游戏逻辑的地方,它们:
-- **专注单一职责** - 每个系统只处理一种类型的逻辑
-- **自动执行** - 系统会在每帧自动被调用
-- **基于组件过滤** - 只处理包含特定组件的实体
-- **高性能** - 利用ECS的数据局部性优势
-
-### 系统的工作原理
-
-```typescript
-// 系统的基本工作流程:
-// 1. 查询符合条件的实体
-// 2. 遍历这些实体
-// 3. 读取/修改实体的组件数据
-// 4. 执行游戏逻辑
-
-class MovementSystem extends EntitySystem {
- process(entities: Entity[]) {
- for (const entity of entities) {
- const position = entity.getComponent(PositionComponent);
- const velocity = entity.getComponent(VelocityComponent);
-
- // 更新位置 = 当前位置 + 速度 * 时间
- position.x += velocity.x * Time.deltaTime;
- position.y += velocity.y * Time.deltaTime;
- }
- }
-}
-```
-
-## 系统类型详解
-
-### 1. EntitySystem - 基础系统
-
-最常用的系统类型,每帧处理所有符合条件的实体。
-
-```typescript
-import { EntitySystem, Entity, Matcher } from '@esengine/ecs-framework';
-
-class HealthSystem extends EntitySystem {
- constructor() {
- // 使用Matcher创建查询条件
- super(Matcher.all(HealthComponent));
- // 或者使用链式语法
- // super(Matcher.empty().all(HealthComponent));
- }
-
- // 主要处理逻辑
- protected process(entities: Entity[]) {
- // 直接使用传入的entities参数,已经是匹配的实体
- for (const entity of entities) {
- const health = entity.getComponent(HealthComponent)!;
-
- // 处理生命值逻辑
- if (health.currentHealth <= 0) {
- this.handleDeath(entity);
- } else if (health.currentHealth < health.maxHealth) {
- this.handleRegeneration(health);
- }
- }
- }
-
- private handleDeath(entity: Entity) {
- // 添加死亡标记
- entity.addComponent(new DeadComponent());
-
- // 触发死亡事件
- const eventBus = this.scene.entityManager.eventBus;
- eventBus.emit('entity:died', {
- entityId: entity.id,
- entityName: entity.name
- });
- }
-
- private handleRegeneration(health: HealthComponent) {
- // 缓慢恢复生命值
- health.currentHealth += health.regenRate * Time.deltaTime;
- health.currentHealth = Math.min(health.currentHealth, health.maxHealth);
- }
-}
-```
-
-**适用场景:**
-- 移动系统
-- 渲染系统
-- 碰撞检测系统
-- AI系统
-
-### 2. ProcessingSystem - 简化处理系统
-
-不需要处理具体实体,主要用于执行全局逻辑或不依赖特定实体的系统处理。
-
-```typescript
-import { ProcessingSystem, Matcher } from '@esengine/ecs-framework';
-
-class GameLogicSystem extends ProcessingSystem {
- constructor() {
- // ProcessingSystem可以不指定Matcher,或使用空Matcher
- super(Matcher.empty());
- }
-
- // 处理系统逻辑(每帧执行)
- public processSystem() {
- // 执行全局游戏逻辑
- this.updateGameState();
- this.checkWinConditions();
- this.updateUI();
- }
-
- private updateGameState() {
- // 更新游戏状态逻辑
- console.log("更新游戏状态");
- }
-
- private checkWinConditions() {
- // 检查胜利条件
- const players = this.scene.findEntitiesByTag(EntityTags.PLAYER);
- const enemies = this.scene.findEntitiesByTag(EntityTags.ENEMY);
-
- if (enemies.length === 0) {
- this.triggerVictory();
- } else if (players.length === 0) {
- this.triggerGameOver();
- }
- }
-
- private updateUI() {
- // 更新UI显示
- const gameTime = Time.totalTime;
- console.log(`游戏时间: ${gameTime.toFixed(1)}秒`);
- }
-
- private triggerVictory() {
- console.log("游戏胜利!");
- // 处理胜利逻辑
- }
-
- private triggerGameOver() {
- console.log("游戏结束!");
- // 处理游戏结束逻辑
- }
-}
-```
-
-**适用场景:**
-- 全局游戏逻辑系统
-- 胜负判断系统
-- UI更新系统
-- 不依赖特定实体的处理
-
-## AI系统示例
-
-下面是一个完整的AI系统示例,展示EntitySystem的典型用法:
-
-```typescript
-import { EntitySystem, Matcher, Entity } from '@esengine/ecs-framework';
-
-enum AIState {
- IDLE,
- PATROL,
- CHASE,
- ATTACK
-}
-
-class AISystem extends EntitySystem {
- constructor() {
- // 复杂匹配条件可以使用链式语法
- super(Matcher.empty().all(AIComponent, PositionComponent));
- // 或者使用简洁语法
- // super(Matcher.all(AIComponent, PositionComponent));
- }
-
- // 处理所有匹配的实体
- protected process(entities: Entity[]) {
- for (const entity of entities) {
- this.processEntity(entity);
- }
- }
-
- // 处理单个实体的逻辑(自定义方法)
- private processEntity(entity: Entity) {
- const ai = entity.getComponent(AIComponent);
- const position = entity.getComponent(PositionComponent);
-
- switch (ai.state) {
- case AIState.IDLE:
- this.processIdle(entity, ai);
- break;
- case AIState.PATROL:
- this.processPatrol(entity, ai, position);
- break;
- case AIState.CHASE:
- this.processChase(entity, ai, position);
- break;
- case AIState.ATTACK:
- this.processAttack(entity, ai);
- break;
- }
- }
-
- private processIdle(entity: Entity, ai: AIComponent) {
- ai.idleTimer += Time.deltaTime;
-
- if (ai.idleTimer >= ai.idleTime) {
- ai.state = AIState.PATROL;
- ai.idleTimer = 0;
- }
-
- // 检查附近是否有玩家
- const nearbyPlayer = this.findNearbyPlayer(entity, ai.detectionRange);
- if (nearbyPlayer) {
- ai.state = AIState.CHASE;
- ai.target = nearbyPlayer;
- }
- }
-
- private processPatrol(entity: Entity, ai: AIComponent, position: PositionComponent) {
- // 简单的来回巡逻
- if (!ai.patrolTarget) {
- ai.patrolTarget = this.getNextPatrolPoint(ai);
- }
-
- const direction = ai.patrolTarget.subtract(position);
- const distance = direction.length();
-
- if (distance < 10) {
- ai.patrolTarget = this.getNextPatrolPoint(ai);
- } else {
- const normalized = direction.normalize();
- position.x += normalized.x * ai.moveSpeed * Time.deltaTime;
- position.y += normalized.y * ai.moveSpeed * Time.deltaTime;
- }
- }
-}
-```
-
-**适用场景:**
-- 全局游戏逻辑系统
-- 胜负判断系统
-- UI更新系统
-- 不依赖特定实体的处理
-
-### 3. IntervalSystem - 间隔执行系统
-
-不是每帧都执行,而是按指定间隔执行的系统,适合不需要高频更新的逻辑。
-
-```typescript
-import { IntervalSystem, Matcher } from '@esengine/ecs-framework';
-
-class SpawnSystem extends IntervalSystem {
- private spawnPoints: { x: number; y: number }[] = [
- { x: 100, y: 100 },
- { x: 700, y: 100 },
- { x: 400, y: 500 }
- ];
-
- // 每2秒执行一次
- constructor() {
- // IntervalSystem需要指定间隔时间和Matcher
- super(2.0, Matcher.all(SpawnerComponent));
- }
-
- // 间隔执行的逻辑(重写process方法)
- protected process(entities: Entity[]) {
- // entities就是匹配的生成器实体
-
- for (const spawner of entities) {
- const spawnerComp = spawner.getComponent(SpawnerComponent);
-
- if (this.shouldSpawn(spawnerComp)) {
- this.spawnEnemy(spawner, spawnerComp);
- }
- }
- }
-
- private shouldSpawn(spawner: SpawnerComponent): boolean {
- // 检查是否应该生成
- const currentEnemyCount = this.getCurrentEnemyCount();
- return currentEnemyCount < spawner.maxEnemies &&
- Math.random() < spawner.spawnChance;
- }
-
- private spawnEnemy(spawnerEntity: Entity, spawner: SpawnerComponent) {
- // 随机选择生成点
- const spawnPoint = this.spawnPoints[
- Math.floor(Math.random() * this.spawnPoints.length)
- ];
-
- // 创建敌人实体
- const enemy = this.scene.createEntity("Enemy");
- enemy.addComponent(new PositionComponent(spawnPoint.x, spawnPoint.y));
- enemy.addComponent(new HealthComponent(50));
- enemy.addComponent(new AIComponent());
- enemy.addComponent(new VelocityComponent(0, 0));
- enemy.tag = EntityTags.ENEMY;
-
- // 更新生成器统计
- spawner.spawnedCount++;
- spawner.lastSpawnTime = Time.totalTime;
-
- // 发送生成事件
- const eventBus = this.scene.entityManager.eventBus;
- eventBus.emit('enemy:spawned', {
- enemyId: enemy.id,
- spawnPoint: spawnPoint,
- spawnerEntity: spawnerEntity.id
- });
- }
-}
-```
-
-**适用场景:**
-- 敌人生成系统
-- 自动保存系统
-- 资源回收系统
-- 定期数据同步
-
-### 4. PassiveSystem - 被动系统
-
-不处理实体的系统,主要用于事件监听和响应。
-
-```typescript
-import { PassiveSystem, Matcher, Core } from '@esengine/ecs-framework';
-
-class ScoreSystem extends PassiveSystem {
- private score: number = 0;
- private multiplier: number = 1;
- private combo: number = 0;
-
- constructor() {
- // PassiveSystem也需要Matcher,即使不使用
- super(Matcher.empty());
- }
-
- initialize() {
- super.initialize();
-
- // 监听游戏事件(使用EntityManager的事件系统)
- const eventBus = this.scene.entityManager.eventBus;
- eventBus.on('enemy:killed', this.onEnemyKilled, { context: this });
- eventBus.on('item:collected', this.onItemCollected, { context: this });
- eventBus.on('combo:broken', this.onComboBroken, { context: this });
- }
-
- // PassiveSystem被移除时清理
- destroy() {
- // 事件监听会在系统销毁时自动清理
- // 如需手动清理,可以保存listenerId并调用eventBus.off()
- }
-
- private onEnemyKilled(data: { enemyType: string; position: { x: number; y: number } }) {
- // 根据敌人类型给分
- let baseScore = this.getScoreForEnemyType(data.enemyType);
-
- // 连击奖励
- this.combo++;
- if (this.combo > 3) {
- this.multiplier = Math.min(this.combo * 0.1, 3.0); // 最多3倍
- }
-
- const finalScore = Math.floor(baseScore * this.multiplier);
- this.addScore(finalScore);
-
- // 显示分数奖励
- this.showScorePopup(data.position, finalScore);
- }
-
- private addScore(points: number) {
- this.score += points;
-
- // 发送分数更新事件
- const eventBus = this.scene.entityManager.eventBus;
- eventBus.emit('score:updated', {
- score: this.score,
- points: points,
- multiplier: this.multiplier,
- combo: this.combo
- });
- }
-}
-```
-
-**适用场景:**
-- 分数统计系统
-- 音效播放系统
-- UI更新系统
-- 成就系统
-
-## 系统生命周期方法
-
-系统提供了多个生命周期方法,可以根据需要重写:
-
-### 重要的生命周期方法
-
-```typescript
-class ExampleSystem extends EntitySystem {
- /**
- * 系统初始化回调 - 系统被添加到场景时调用
- * 用于设置事件监听器、初始化资源等
- * 注意:不要重写initialize()方法,而是重写onInitialize()
- */
- protected onInitialize() {
- // 设置事件监听
- const eventBus = this.scene.entityManager.eventBus;
- eventBus.on('someEvent', this.handleEvent, { context: this });
-
- console.log('系统已初始化');
- }
-
- /**
- * 每帧处理开始前调用
- */
- protected onBegin() {
- // 预处理逻辑,如重置计数器
- this.frameCounter++;
- }
-
- /**
- * 主要处理逻辑 - 每帧调用
- * @param entities 符合条件的实体列表
- */
- protected process(entities: Entity[]) {
- for (const entity of entities) {
- // 处理每个实体
- this.processEntity(entity);
- }
- }
-
- /**
- * 后期处理 - 在process之后调用
- * @param entities 符合条件的实体列表
- */
- protected lateProcess(entities: Entity[]) {
- // 后期处理逻辑,如碰撞检测后的响应
- this.handlePostProcessing();
- }
-
- /**
- * 每帧处理结束后调用
- */
- protected onEnd() {
- // 后处理逻辑,如统计数据更新
- this.updateStatistics();
- }
-}
-```
-
-### 生命周期执行顺序
-
-系统的生命周期方法按以下顺序执行:
-
-1. **initialize()** - 系统被添加到场景时执行一次(框架调用)
- - **onInitialize()** - 用户可重写的初始化回调
-2. 每帧循环:
- - **onBegin()** - 帧开始前(用户可重写)
- - **process(entities)** - 主要处理逻辑(用户必须实现)
- - **lateProcess(entities)** - 后期处理(用户可重写)
- - **onEnd()** - 帧结束后(用户可重写)
-
-## 系统管理和注册
-
-### 在场景中添加系统
-
-```typescript
-import { Scene, Core } from '@esengine/ecs-framework';
-
-const scene = new Scene();
-
-// 添加各种系统(使用addEntityProcessor方法)
-scene.addEntityProcessor(new MovementSystem());
-scene.addEntityProcessor(new GameLogicSystem());
-scene.addEntityProcessor(new SpawnSystem());
-scene.addEntityProcessor(new ScoreSystem());
-
-// 设置系统的执行优先级
-const movementSystem = scene.getEntityProcessor(MovementSystem);
-if (movementSystem) {
- movementSystem.updateOrder = 10; // 数值越小越先执行
-}
-
-const renderSystem = scene.getEntityProcessor(RenderSystem);
-if (renderSystem) {
- renderSystem.updateOrder = 100; // 渲染系统最后执行
-}
-
-// 设置为当前场景
-Core.setScene(scene;
-```
-
-### 系统的启用和禁用
-
-```typescript
-// 暂时禁用某个系统
-const gameLogicSystem = scene.getEntityProcessor(GameLogicSystem);
-if (gameLogicSystem) {
- gameLogicSystem.enabled = false;
-}
-
-// 重新启用
-if (gameLogicSystem) {
- gameLogicSystem.enabled = true;
-}
-
-// 移除系统
-scene.removeEntityProcessor(gameLogicSystem);
-```
-
-## 系统设计最佳实践
-
-### 1. 单一职责原则
-
-```typescript
-// 好的设计:每个系统只负责一件事
-class MovementSystem extends EntitySystem {
- // 只负责移动
-}
-
-class CollisionSystem extends EntitySystem {
- // 只负责碰撞检测
-}
-
-class RenderSystem extends EntitySystem {
- // 只负责渲染
-}
-
-// 不好的设计:一个系统做太多事情
-class GameplaySystem extends EntitySystem {
- // 既处理移动,又处理碰撞,还处理渲染...
-}
-```
-
-### 2. 合理的系统执行顺序
-
-```typescript
-// 设置合理的执行顺序
-scene.addEntityProcessor(new InputSystem()).updateOrder = 0; // 输入最先
-scene.addEntityProcessor(new GameLogicSystem()).updateOrder = 10; // 游戏逻辑
-scene.addEntityProcessor(new MovementSystem()).updateOrder = 20; // 移动计算
-scene.addEntityProcessor(new CollisionSystem()).updateOrder = 30; // 碰撞检测
-scene.addEntityProcessor(new HealthSystem()).updateOrder = 40; // 生命值处理
-scene.addEntityProcessor(new RenderSystem()).updateOrder = 100; // 渲染最后
-```
-
-### 3. 系统间通信
-
-```typescript
-// 使用事件进行系统间通信
-class CollisionSystem extends EntitySystem {
- process(entities: Entity[]) {
- // ... 碰撞检测逻辑
-
- if (collision) {
- // 发送碰撞事件,让其他系统响应
- const eventBus = this.scene.entityManager.eventBus;
- eventBus.emit('collision:detected', {
- entity1: collider1,
- entity2: collider2,
- collisionPoint: point
- });
- }
- }
-}
-
-class HealthSystem extends PassiveSystem {
- initialize() {
- super.initialize();
-
- // 监听碰撞事件
- const eventBus = this.scene.entityManager.eventBus;
- eventBus.on('collision:detected', this.onCollision, { context: this });
- }
-
- private onCollision(data: CollisionEventData) {
- // 处理碰撞伤害
- if (data.entity1.hasComponent(HealthComponent)) {
- const health = data.entity1.getComponent(HealthComponent);
- health.takeDamage(10);
- }
- }
-}
-```
-
-### 4. 性能优化
-
-```typescript
-class OptimizedMovementSystem extends EntitySystem {
- private lastUpdateTime: number = 0;
- private readonly UPDATE_INTERVAL = 16; // 60FPS
-
- process(entities: Entity[]) {
- const currentTime = Time.totalTime;
-
- // 限制更新频率
- if (currentTime - this.lastUpdateTime < this.UPDATE_INTERVAL) {
- return;
- }
-
- // 批量处理
- this.processBatch(entities);
-
- this.lastUpdateTime = currentTime;
- }
-
- private processBatch(entities: Entity[]) {
- // 使用for循环而不是forEach,性能更好
- for (let i = 0; i < entities.length; i++) {
- const entity = entities[i];
- // 处理逻辑...
- }
- }
-}
-```
-
-## 常见问题
-
-### Q: 系统的执行顺序重要吗?
-
-A: 非常重要!合理的执行顺序可以避免逻辑错误:
-
-```typescript
-// 正确顺序:
-// 1. 输入系统(收集玩家输入)
-// 2. AI系统(敌人决策)
-// 3. 移动系统(更新位置)
-// 4. 碰撞系统(检测碰撞)
-// 5. 渲染系统(显示画面)
-```
-
-### Q: 什么时候使用哪种系统类型?
-
-A:
-- **EntitySystem** - 大部分游戏逻辑(移动、AI、碰撞等)
-- **ProcessingSystem** - 不依赖特定实体的全局处理(游戏状态管理、全局逻辑)
-- **IntervalSystem** - 不需要每帧执行的逻辑(生成器、自动保存)
-- **PassiveSystem** - 事件响应系统(分数、音效、UI更新)
-
-### Q: 系统可以访问其他系统吗?
-
-A: 不建议直接访问。推荐使用事件系统进行系统间通信,保持松耦合。
-
-### Q: 如何调试系统性能?
-
-A: 使用框架内置的性能监控:
-
-```typescript
-const monitor = PerformanceMonitor.instance;
-monitor.startFrame('MovementSystem');
-// 系统逻辑...
-monitor.endFrame('MovementSystem');
-
-// 查看性能报告
-console.log(monitor.getReport());
-```
-
-通过合理使用这些系统类型,你可以构建出高性能、易维护的游戏逻辑!
\ No newline at end of file
diff --git a/docs/timer-guide.md b/docs/timer-guide.md
deleted file mode 100644
index a0ac8f10..00000000
--- a/docs/timer-guide.md
+++ /dev/null
@@ -1,653 +0,0 @@
-# 定时器系统使用指南
-
-定时器系统是游戏开发中的重要工具,用于处理延迟执行、重复任务、倒计时等功能。本指南详细介绍如何使用ECS框架的定时器系统。
-
-## 定时器基础概念
-
-### 什么是定时器?
-
-定时器允许你:
-- **延迟执行** - 在指定时间后执行某个操作
-- **重复执行** - 定期重复执行某个操作
-- **取消执行** - 在执行前取消定时器
-- **精确控制** - 精确控制执行时机
-
-### 定时器的优势
-
-相比直接在游戏循环中计时,定时器系统提供:
-- 🧹 **自动管理** - 自动处理定时器的生命周期
-- **游戏时间控制** - 支持游戏暂停、时间缩放
-- 💾 **内存优化** - 自动回收完成的定时器
-- **易于使用** - 简单的API调用
-
-## 基础定时器使用
-
-### 1. 简单延迟执行
-
-```typescript
-import { Core, Timer } from '@esengine/ecs-framework';
-
-// 3秒后执行一次
-Core.schedule(3.0, false, this, (timer) => {
- console.log("3秒钟到了!");
-});
-
-// 实际游戏例子:延迟显示提示
-class GameTutorial {
- startTutorial() {
- // 2秒后显示第一个提示
- Core.schedule(2.0, false, this, () => {
- this.showTip("欢迎来到游戏世界!");
- });
-
- // 5秒后显示移动提示
- Core.schedule(5.0, false, this, () => {
- this.showTip("使用WASD键移动角色");
- });
-
- // 8秒后显示攻击提示
- Core.schedule(8.0, false, this, () => {
- this.showTip("按空格键攻击敌人");
- });
- }
-
- private showTip(message: string) {
- // 显示提示的逻辑
- console.log(`提示: ${message}`);
- }
-}
-```
-
-### 2. 重复执行
-
-```typescript
-// 每1秒执行一次,持续执行
-const repeatTimer = Core.schedule(1.0, true, this, (timer) => {
- console.log("每秒执行一次");
-});
-
-// 实际游戏例子:生命值恢复
-class HealthRegeneration {
- private regenTimer: ITimer;
-
- startRegeneration(entity: Entity) {
- const health = entity.getComponent(HealthComponent);
-
- // 每2秒恢复5点生命值
- this.regenTimer = Core.schedule(2.0, true, this, () => {
- if (health.currentHealth < health.maxHealth) {
- health.currentHealth += 5;
- health.currentHealth = Math.min(health.currentHealth, health.maxHealth);
-
- console.log(`生命值恢复:${health.currentHealth}/${health.maxHealth}`);
-
- // 满血时停止恢复
- if (health.currentHealth >= health.maxHealth) {
- this.stopRegeneration();
- }
- }
- });
- }
-
- stopRegeneration() {
- if (this.regenTimer) {
- this.regenTimer.stop();
- this.regenTimer = null;
- }
- }
-}
-```
-
-### 3. 获取定时器引用进行控制
-
-```typescript
-import { ITimer } from '@esengine/ecs-framework';
-
-class BombTimer {
- private bombTimer: ITimer;
- private explosionTime: number = 5.0;
-
- startBomb(position: { x: number; y: number }) {
- console.log("炸弹已放置!5秒后爆炸...");
-
- // 创建定时器并保存引用
- this.bombTimer = Core.schedule(this.explosionTime, false, this, () => {
- this.explode(position);
- });
- }
-
- defuseBomb() {
- if (this.bombTimer && !this.bombTimer.isDone) {
- // 拆除炸弹
- this.bombTimer.stop();
- console.log("炸弹已被拆除!");
- }
- }
-
- getRemainingTime(): number {
- if (this.bombTimer && !this.bombTimer.isDone) {
- return this.explosionTime - this.bombTimer.elapsedTime;
- }
- return 0;
- }
-
- private explode(position: { x: number; y: number }) {
- console.log("💥 炸弹爆炸了!");
- // 爆炸效果逻辑...
- }
-}
-```
-
-## 高级定时器功能
-
-### 1. 定时器链 - 顺序执行多个任务
-
-```typescript
-class CutsceneManager {
- playCutscene() {
- // 第一个镜头:2秒
- Core.schedule(2.0, false, this, () => {
- this.showScene("开场镜头");
-
- // 第二个镜头:3秒后
- Core.schedule(3.0, false, this, () => {
- this.showScene("角色登场");
-
- // 第三个镜头:2秒后
- Core.schedule(2.0, false, this, () => {
- this.showScene("背景介绍");
-
- // 结束:1秒后
- Core.schedule(1.0, false, this, () => {
- this.endCutscene();
- });
- });
- });
- });
- }
-
- private showScene(sceneName: string) {
- console.log(`播放场景: ${sceneName}`);
- }
-
- private endCutscene() {
- console.log("过场动画结束,开始游戏!");
- }
-}
-
-// 更优雅的链式写法
-class ImprovedCutsceneManager {
- playCutscene() {
- this.scheduleSequence([
- { delay: 2.0, action: () => this.showScene("开场镜头") },
- { delay: 3.0, action: () => this.showScene("角色登场") },
- { delay: 2.0, action: () => this.showScene("背景介绍") },
- { delay: 1.0, action: () => this.endCutscene() }
- ]);
- }
-
- private scheduleSequence(sequence: Array<{delay: number, action: () => void}>) {
- let currentDelay = 0;
-
- sequence.forEach(step => {
- currentDelay += step.delay;
- Core.schedule(currentDelay, false, this, step.action);
- });
- }
-}
-```
-
-### 2. 条件定时器 - 满足条件时执行
-
-```typescript
-class ConditionalTimer {
- waitForCondition(
- condition: () => boolean,
- action: () => void,
- checkInterval: number = 0.1,
- timeout: number = 10.0
- ) {
- let timeElapsed = 0;
-
- const checkTimer = Core.schedule(checkInterval, true, this, () => {
- timeElapsed += checkInterval;
-
- if (condition()) {
- // 条件满足,执行动作并停止检查
- checkTimer.stop();
- action();
- } else if (timeElapsed >= timeout) {
- // 超时,停止检查
- checkTimer.stop();
- console.log("等待条件超时");
- }
- });
- }
-}
-
-// 使用例子
-class WaitForPlayerExample {
- waitForPlayerToReachGoal() {
- const player = this.getPlayer();
- const goalPosition = { x: 500, y: 300 };
-
- this.waitForCondition(
- // 条件:玩家到达目标位置
- () => {
- const playerPos = player.getComponent(PositionComponent);
- return playerPos.distanceTo(goalPosition) < 50;
- },
- // 动作:触发下一关
- () => {
- console.log("玩家到达目标!开始下一关");
- this.loadNextLevel();
- },
- 0.1, // 每0.1秒检查一次
- 30.0 // 30秒后超时
- );
- }
-}
-```
-
-### 3. 可暂停的定时器
-
-```typescript
-class PausableTimer {
- private timers: ITimer[] = [];
- private isPaused: boolean = false;
-
- schedule(delay: number, repeat: boolean, callback: () => void): ITimer {
- const timer = Core.schedule(delay, repeat, this, callback);
- this.timers.push(timer);
- return timer;
- }
-
- pauseAll() {
- this.isPaused = true;
- this.timers.forEach(timer => {
- if (!timer.isDone) {
- timer.stop();
- }
- });
- }
-
- resumeAll() {
- if (!this.isPaused) return;
-
- this.isPaused = false;
- // 重新启动所有未完成的定时器
- // 注意:这是简化实现,实际需要保存剩余时间
- this.timers = this.timers.filter(timer => !timer.isDone);
- }
-
- clearAll() {
- this.timers.forEach(timer => timer.stop());
- this.timers = [];
- }
-}
-
-// 游戏暂停系统
-class GamePauseSystem {
- private gameTimers: PausableTimer = new PausableTimer();
- private isGamePaused: boolean = false;
-
- pauseGame() {
- if (this.isGamePaused) return;
-
- this.isGamePaused = true;
- this.gameTimers.pauseAll();
-
- // 显示暂停菜单
- this.showPauseMenu();
- }
-
- resumeGame() {
- if (!this.isGamePaused) return;
-
- this.isGamePaused = false;
- this.gameTimers.resumeAll();
-
- // 隐藏暂停菜单
- this.hidePauseMenu();
- }
-
- scheduleGameTimer(delay: number, repeat: boolean, callback: () => void) {
- return this.gameTimers.schedule(delay, repeat, callback);
- }
-}
-```
-
-## 实际游戏应用示例
-
-### 1. Buff/Debuff 系统
-
-```typescript
-class BuffSystem {
- applyBuff(entity: Entity, buffType: string, duration: number) {
- const buff = new BuffComponent(buffType, duration);
- entity.addComponent(buff);
-
- // 应用Buff效果
- this.applyBuffEffect(entity, buffType);
-
- // 设置定时器移除Buff
- Core.schedule(duration, false, this, () => {
- if (!entity.isDestroyed && entity.hasComponent(BuffComponent)) {
- this.removeBuff(entity, buffType);
- }
- });
-
- console.log(`应用了 ${buffType} Buff,持续时间 ${duration} 秒`);
- }
-
- private applyBuffEffect(entity: Entity, buffType: string) {
- const stats = entity.getComponent(StatsComponent);
-
- switch (buffType) {
- case 'speed_boost':
- stats.moveSpeed *= 1.5;
- break;
- case 'damage_boost':
- stats.damage *= 2.0;
- break;
- case 'invincible':
- entity.addComponent(new InvincibleComponent());
- break;
- }
- }
-
- private removeBuff(entity: Entity, buffType: string) {
- const buff = entity.getComponent(BuffComponent);
- if (buff && buff.buffType === buffType) {
- entity.removeComponent(buff);
- this.removeBuffEffect(entity, buffType);
- console.log(`${buffType} Buff 已过期`);
- }
- }
-}
-```
-
-### 2. 技能冷却系统
-
-```typescript
-class SkillSystem {
- private cooldowns: Map = new Map();
-
- useSkill(player: Entity, skillName: string): boolean {
- // 检查冷却
- if (this.isOnCooldown(skillName)) {
- const remainingTime = this.getCooldownRemaining(skillName);
- console.log(`技能冷却中,还需 ${remainingTime.toFixed(1)} 秒`);
- return false;
- }
-
- // 执行技能
- this.executeSkill(player, skillName);
-
- // 启动冷却
- const cooldownTime = this.getSkillCooldown(skillName);
- this.startCooldown(skillName, cooldownTime);
-
- return true;
- }
-
- private startCooldown(skillName: string, duration: number) {
- const endTime = Time.totalTime + duration;
- this.cooldowns.set(skillName, endTime);
-
- // 设置定时器清理冷却
- Core.schedule(duration, false, this, () => {
- this.cooldowns.delete(skillName);
- console.log(`技能 ${skillName} 冷却完成!`);
- });
- }
-
- private isOnCooldown(skillName: string): boolean {
- const endTime = this.cooldowns.get(skillName);
- return endTime !== undefined && Time.totalTime < endTime;
- }
-
- private getCooldownRemaining(skillName: string): number {
- const endTime = this.cooldowns.get(skillName);
- return endTime ? Math.max(0, endTime - Time.totalTime) : 0;
- }
-
- private executeSkill(player: Entity, skillName: string) {
- switch (skillName) {
- case 'fireball':
- this.castFireball(player);
- break;
- case 'heal':
- this.castHeal(player);
- break;
- case 'dash':
- this.performDash(player);
- break;
- }
- }
-
- private getSkillCooldown(skillName: string): number {
- const cooldowns = {
- 'fireball': 3.0,
- 'heal': 10.0,
- 'dash': 5.0
- };
- return cooldowns[skillName] || 1.0;
- }
-}
-```
-
-### 3. 关卡时间限制
-
-```typescript
-class LevelTimer {
- private timeLimit: number;
- private timeRemaining: number;
- private timerActive: boolean = false;
- private updateTimer: ITimer;
-
- startLevel(timeLimitSeconds: number) {
- this.timeLimit = timeLimitSeconds;
- this.timeRemaining = timeLimitSeconds;
- this.timerActive = true;
-
- // 每秒更新倒计时
- this.updateTimer = Core.schedule(1.0, true, this, () => {
- this.updateCountdown();
- });
-
- console.log(`关卡开始!时间限制:${timeLimitSeconds} 秒`);
- }
-
- private updateCountdown() {
- if (!this.timerActive) return;
-
- this.timeRemaining--;
-
- // 更新UI显示
- this.updateTimerUI(this.timeRemaining);
-
- // 时间警告
- if (this.timeRemaining === 30) {
- console.log("警告:还剩30秒!");
- this.playWarningSound();
- } else if (this.timeRemaining === 10) {
- console.log("🚨 紧急:还剩10秒!");
- this.playUrgentSound();
- }
-
- // 时间到
- if (this.timeRemaining <= 0) {
- this.timeUp();
- }
- }
-
- private timeUp() {
- this.timerActive = false;
- this.updateTimer.stop();
-
- console.log("⏰ 时间到!游戏结束");
-
- // 触发游戏结束(需要在实际使用中获取EntityManager实例)
- // 示例:entityManager.eventBus.emit('level:timeout');
- console.log('触发关卡超时事件');
- }
-
- completeLevel() {
- if (this.timerActive) {
- this.timerActive = false;
- this.updateTimer.stop();
-
- const completionTime = this.timeLimit - this.timeRemaining;
- console.log(` 关卡完成!用时:${completionTime} 秒`);
-
- // 根据剩余时间给予奖励
- this.calculateTimeBonus(this.timeRemaining);
- }
- }
-
- private calculateTimeBonus(timeLeft: number) {
- const bonus = Math.floor(timeLeft * 10); // 每秒剩余10分
- if (bonus > 0) {
- console.log(`时间奖励:${bonus} 分`);
- // 触发时间奖励事件(需要在实际使用中获取EntityManager实例)
- // 示例:entityManager.eventBus.emit('score:time_bonus', { bonus });
- }
- }
-
- getTimeRemaining(): number {
- return this.timeRemaining;
- }
-
- getTimeRemainingFormatted(): string {
- const minutes = Math.floor(this.timeRemaining / 60);
- const seconds = this.timeRemaining % 60;
- return `${minutes}:${seconds.toString().padStart(2, '0')}`;
- }
-}
-```
-
-## 定时器性能优化
-
-### 1. 定时器池化
-
-```typescript
-class TimerPool {
- private static instance: TimerPool;
- private timerPool: ITimer[] = [];
-
- static getInstance(): TimerPool {
- if (!this.instance) {
- this.instance = new TimerPool();
- }
- return this.instance;
- }
-
- getTimer(): ITimer {
- return this.timerPool.pop() || this.createTimer();
- }
-
- releaseTimer(timer: ITimer) {
- timer.stop();
- this.timerPool.push(timer);
- }
-
- private createTimer(): ITimer {
- // 创建新定时器的逻辑
- return new Timer();
- }
-}
-```
-
-### 2. 批量定时器管理
-
-```typescript
-class BatchTimerManager {
- private timers: Set = new Set();
-
- scheduleMany(configs: Array<{delay: number, repeat: boolean, callback: () => void}>) {
- return configs.map(config => {
- const timer = Core.schedule(config.delay, config.repeat, this, config.callback);
- this.timers.add(timer);
- return timer;
- });
- }
-
- stopAll() {
- this.timers.forEach(timer => timer.stop());
- this.timers.clear();
- }
-
- cleanup() {
- // 清理已完成的定时器
- this.timers.forEach(timer => {
- if (timer.isDone) {
- this.timers.delete(timer);
- }
- });
- }
-}
-```
-
-## 常见问题和最佳实践
-
-### Q: 定时器会自动清理吗?
-
-A: 是的,完成的定时器会自动清理。但如果需要提前停止,记得调用 `timer.stop()`。
-
-### Q: 定时器会受到游戏暂停影响吗?
-
-A: 定时器使用游戏时间,如果实现了时间缩放功能,定时器会相应调整。
-
-### Q: 如何实现精确的帧同步定时器?
-
-A: 使用帧计数而不是时间:
-
-```typescript
-class FrameTimer {
- private frameCount: number = 0;
- private targetFrame: number;
-
- scheduleFrames(frames: number, callback: () => void) {
- this.targetFrame = this.frameCount + frames;
-
- const checkFrame = () => {
- this.frameCount++;
- if (this.frameCount >= this.targetFrame) {
- callback();
- } else {
- requestAnimationFrame(checkFrame);
- }
- };
-
- requestAnimationFrame(checkFrame);
- }
-}
-```
-
-### Q: 如何避免定时器内存泄漏?
-
-A:
-1. 及时停止不需要的定时器
-2. 在对象销毁时清理所有定时器
-3. 使用弱引用避免循环引用
-
-```typescript
-class SafeTimerUser {
- private timers: ITimer[] = [];
-
- scheduleTimer(delay: number, callback: () => void) {
- const timer = Core.schedule(delay, false, this, callback);
- this.timers.push(timer);
- return timer;
- }
-
- destroy() {
- // 清理所有定时器
- this.timers.forEach(timer => timer.stop());
- this.timers = [];
- }
-}
-```
-
-定时器是游戏开发中非常有用的工具,合理使用可以让你的游戏逻辑更加优雅和高效!
\ No newline at end of file
diff --git a/docs/use-cases.md b/docs/use-cases.md
deleted file mode 100644
index ebbf2b94..00000000
--- a/docs/use-cases.md
+++ /dev/null
@@ -1,600 +0,0 @@
-# ECS框架使用场景示例
-
-本文档展示ECS框架在不同类型游戏中的具体应用案例。
-
-## 目录
-
-1. [小型休闲游戏](#小型休闲游戏)
-2. [中型动作游戏](#中型动作游戏)
-3. [大型策略游戏](#大型策略游戏)
-4. [MMO游戏](#mmo游戏)
-
-## 小型休闲游戏
-
-### 场景:简单的飞机大战游戏
-
-```typescript
-import {
- Scene,
- EntityManager,
- Entity,
- Component,
- EntitySystem,
- Matcher
-} from '@esengine/ecs-framework';
-
-// 组件定义
-class PositionComponent extends Component {
- constructor(public x: number = 0, public y: number = 0) {
- super();
- }
-}
-
-class VelocityComponent extends Component {
- constructor(public x: number = 0, public y: number = 0) {
- super();
- }
-}
-
-class PlayerComponent extends Component {}
-class EnemyComponent extends Component {}
-class BulletComponent extends Component {}
-
-// 游戏管理器
-class PlaneWarGame {
- private scene: Scene;
- private entityManager: EntityManager;
-
- constructor() {
- this.scene = new Scene();
- this.entityManager = new EntityManager();
- this.setupGame();
- }
-
- private setupGame(): void {
- // 创建玩家
- const player = this.entityManager.createEntity("Player");
- player.addComponent(new PositionComponent(400, 500));
- player.addComponent(new VelocityComponent(0, 0));
- player.addComponent(new PlayerComponent());
- player.tag = 1; // 玩家标签
-
- // 创建敌人
- this.spawnEnemies(5);
-
- // 添加系统
- this.scene.addEntityProcessor(new MovementSystem());
- this.scene.addEntityProcessor(new CollisionSystem());
- this.scene.addEntityProcessor(new CleanupSystem());
- }
-
- private spawnEnemies(count: number): void {
- const enemies = this.scene.createEntities(count, "Enemy");
- enemies.forEach((enemy, index) => {
- enemy.addComponent(new PositionComponent(
- Math.random() * 800,
- -50
- ));
- enemy.addComponent(new VelocityComponent(0, 100));
- enemy.addComponent(new EnemyComponent());
- enemy.tag = 2; // 敌人标签
- });
- }
-
- public update(): void {
- this.scene.update();
- }
-}
-
-// 移动系统
-class MovementSystem extends EntitySystem {
- constructor() {
- super(Matcher.empty().all(PositionComponent, VelocityComponent));
- }
-
- protected process(entities: Entity[]): void {
- const movingEntities = this.scene.querySystem.queryAll(
- PositionComponent,
- VelocityComponent
- );
-
- movingEntities.entities.forEach(entity => {
- const pos = entity.getComponent(PositionComponent);
- const vel = entity.getComponent(VelocityComponent);
-
- pos.x += vel.x * Time.deltaTime;
- pos.y += vel.y * Time.deltaTime;
- });
- }
-}
-
-## 中型动作游戏
-
-### 场景:2D平台跳跃游戏
-
-```typescript
-// 更复杂的组件
-class HealthComponent extends Component {
- constructor(
- public maxHealth: number = 100,
- public currentHealth: number = 100
- ) {
- super();
- }
-}
-
-class AnimationComponent extends Component {
- constructor(
- public currentAnimation: string = "idle",
- public frameIndex: number = 0,
- public frameTime: number = 0
- ) {
- super();
- }
-}
-
-class PhysicsComponent extends Component {
- constructor(
- public mass: number = 1,
- public friction: number = 0.8,
- public isGrounded: boolean = false
- ) {
- super();
- }
-}
-
-// 平台游戏管理器
-class PlatformGame {
- private scene: Scene;
- private entityManager: EntityManager;
-
- constructor() {
- this.scene = new Scene();
- this.entityManager = new EntityManager();
- this.setupGame();
- }
-
- private setupGame(): void {
- // 创建玩家
- this.createPlayer();
-
- // 创建敌人
- this.createEnemies(10);
-
- // 创建平台
- this.createPlatforms();
-
- // 添加系统(按更新顺序)
- this.scene.addEntityProcessor(new InputSystem()).updateOrder = 10;
- this.scene.addEntityProcessor(new PhysicsSystem()).updateOrder = 20;
- this.scene.addEntityProcessor(new AnimationSystem()).updateOrder = 30;
- this.scene.addEntityProcessor(new CombatSystem()).updateOrder = 40;
- this.scene.addEntityProcessor(new RenderSystem()).updateOrder = 50;
- }
-
- private createPlayer(): void {
- const player = this.entityManager.createEntity("Player");
- player.addComponent(new PositionComponent(100, 300));
- player.addComponent(new VelocityComponent(0, 0));
- player.addComponent(new HealthComponent(100));
- player.addComponent(new AnimationComponent("idle"));
- player.addComponent(new PhysicsComponent(1, 0.8));
- player.tag = 1;
- }
-
- private createEnemies(count: number): void {
- const enemies = this.scene.createEntities(count, "Enemy");
- enemies.forEach((enemy, index) => {
- enemy.addComponent(new PositionComponent(
- 200 + index * 100,
- 300
- ));
- enemy.addComponent(new VelocityComponent(0, 0));
- enemy.addComponent(new HealthComponent(50));
- enemy.addComponent(new AnimationComponent("patrol"));
- enemy.addComponent(new PhysicsComponent(0.8, 0.9));
- enemy.tag = 2;
- });
- }
-
- private createPlatforms(): void {
- const platforms = this.scene.createEntities(5, "Platform");
- platforms.forEach((platform, index) => {
- platform.addComponent(new PositionComponent(
- index * 200,
- 400 + Math.random() * 100
- ));
- platform.tag = 3; // 平台标签
- });
- }
-}
-
-## 大型策略游戏
-
-### 场景:即时战略游戏
-
-```typescript
-// 策略游戏组件
-class UnitComponent extends Component {
- constructor(
- public unitType: string,
- public playerId: number,
- public level: number = 1
- ) {
- super();
- }
-}
-
-class AIComponent extends Component {
- constructor(
- public state: string = "idle",
- public target: Entity | null = null,
- public lastDecisionTime: number = 0
- ) {
- super();
- }
-}
-
-class ResourceComponent extends Component {
- constructor(
- public gold: number = 0,
- public wood: number = 0,
- public food: number = 0
- ) {
- super();
- }
-}
-
-// 策略游戏管理器
-class StrategyGame {
- private scene: Scene;
- private entityManager: EntityManager;
- private players: Map = new Map();
-
- constructor() {
- this.scene = new Scene();
- this.entityManager = new EntityManager();
- this.setupGame();
- }
-
- private setupGame(): void {
- // 创建玩家
- this.createPlayers(4);
-
- // 为每个玩家创建初始单位
- this.players.forEach((player, playerId) => {
- this.createInitialUnits(playerId, 10);
- });
-
- // 添加系统
- this.scene.addEntityProcessor(new AISystem()).updateOrder = 10;
- this.scene.addEntityProcessor(new CombatSystem()).updateOrder = 20;
- this.scene.addEntityProcessor(new ResourceSystem()).updateOrder = 30;
- this.scene.addEntityProcessor(new UnitManagementSystem()).updateOrder = 40;
- }
-
- private createPlayers(count: number): void {
- for (let i = 0; i < count; i++) {
- const player = this.entityManager.createEntity(`Player_${i}`);
- player.addComponent(new ResourceComponent(1000, 500, 100));
- player.tag = 10 + i; // 玩家标签从10开始
- this.players.set(i, player);
- }
- }
-
- private createInitialUnits(playerId: number, count: number): void {
- const units = this.scene.createEntities(count, `Unit_${playerId}`);
-
- units.forEach((unit, index) => {
- unit.addComponent(new PositionComponent(
- playerId * 200 + Math.random() * 100,
- playerId * 200 + Math.random() * 100
- ));
- unit.addComponent(new UnitComponent("warrior", playerId));
- unit.addComponent(new HealthComponent(100));
- unit.addComponent(new AIComponent());
- unit.tag = 20 + playerId; // 单位标签
- });
- }
-
- // 批量单位操作
- public createArmy(playerId: number, unitType: string, count: number): Entity[] {
- const units = this.scene.createEntities(count, `${unitType}_${playerId}`);
-
- // 批量配置组件
- units.forEach(unit => {
- unit.addComponent(new UnitComponent(unitType, playerId));
- unit.addComponent(new HealthComponent(100));
- unit.addComponent(new PositionComponent(
- Math.random() * 1000,
- Math.random() * 1000
- ));
- unit.tag = 20 + playerId;
- });
-
- return units;
- }
-
- // 查询玩家的所有单位
- public getPlayerUnits(playerId: number): Entity[] {
- return this.entityManager
- .query()
- .withAll(UnitComponent)
- .withTag(20 + playerId)
- .execute();
- }
-
- // 查询特定类型的单位
- public getUnitsByType(unitType: string): Entity[] {
- return this.entityManager
- .query()
- .withAll(UnitComponent)
- .where(entity => {
- const unit = entity.getComponent(UnitComponent);
- return unit && unit.unitType === unitType;
- })
- .execute();
- }
-}
-
-// AI系统
-class AISystem extends EntitySystem {
- constructor() {
- super(Matcher.empty().all(AIComponent, UnitComponent));
- }
-
- protected process(entities: Entity[]): void {
- const aiUnits = this.entityManager
- .query()
- .withAll(AIComponent, UnitComponent)
- .execute();
-
- aiUnits.forEach(unit => {
- this.processAI(unit);
- });
- }
-
- private processAI(unit: Entity): void {
- const ai = unit.getComponent(AIComponent);
- const unitComp = unit.getComponent(UnitComponent);
-
- if (!ai || !unitComp) return;
-
- // 简单AI逻辑
- switch (ai.state) {
- case "idle":
- this.findTarget(unit);
- break;
- case "attack":
- this.attackTarget(unit);
- break;
- case "move":
- this.moveToTarget(unit);
- break;
- }
- }
-
- private findTarget(unit: Entity): void {
- const unitComp = unit.getComponent(UnitComponent);
- if (!unitComp) return;
-
- // 查找敌方单位
- const enemies = this.entityManager
- .query()
- .withAll(UnitComponent)
- .where(entity => {
- const enemyUnit = entity.getComponent(UnitComponent);
- return enemyUnit && enemyUnit.playerId !== unitComp.playerId;
- })
- .execute();
-
- if (enemies.length > 0) {
- const ai = unit.getComponent(AIComponent);
- if (ai) {
- ai.target = enemies[0];
- ai.state = "attack";
- }
- }
- }
-
- private attackTarget(unit: Entity): void {
- // 攻击逻辑
- }
-
- private moveToTarget(unit: Entity): void {
- // 移动逻辑
- }
-}
-
-## MMO游戏
-
-### 场景:大型多人在线游戏
-
-```typescript
-// MMO特有组件
-class NetworkComponent extends Component {
- constructor(
- public playerId: string,
- public isLocal: boolean = false,
- public lastSyncTime: number = 0
- ) {
- super();
- }
-}
-
-class InventoryComponent extends Component {
- public items: Map = new Map();
-
- addItem(itemId: string, count: number): void {
- const current = this.items.get(itemId) || 0;
- this.items.set(itemId, current + count);
- }
-}
-
-class GuildComponent extends Component {
- constructor(
- public guildId: string,
- public rank: string = "member"
- ) {
- super();
- }
-}
-
-// MMO游戏管理器
-class MMOGame {
- private scene: Scene;
- private entityManager: EntityManager;
- private localPlayerId: string;
-
- constructor(localPlayerId: string) {
- this.scene = new Scene();
- this.entityManager = new EntityManager();
- this.localPlayerId = localPlayerId;
- this.setupGame();
- }
-
- private setupGame(): void {
- // 添加MMO特有系统
- this.scene.addEntityProcessor(new NetworkSyncSystem()).updateOrder = 5;
- this.scene.addEntityProcessor(new PlayerSystem()).updateOrder = 10;
- this.scene.addEntityProcessor(new NPCSystem()).updateOrder = 15;
- this.scene.addEntityProcessor(new GuildSystem()).updateOrder = 20;
- this.scene.addEntityProcessor(new InventorySystem()).updateOrder = 25;
- }
-
- // 创建玩家角色
- public createPlayer(playerId: string, isLocal: boolean = false): Entity {
- const player = this.entityManager.createEntity(`Player_${playerId}`);
- player.addComponent(new PositionComponent(0, 0));
- player.addComponent(new HealthComponent(1000));
- player.addComponent(new NetworkComponent(playerId, isLocal));
- player.addComponent(new InventoryComponent());
- player.tag = isLocal ? 1 : 2; // 本地玩家标签1,远程玩家标签2
-
- return player;
- }
-
- // 批量创建NPC
- public createNPCs(count: number): Entity[] {
- const npcs = this.scene.createEntities(count, "NPC");
-
- npcs.forEach((npc, index) => {
- npc.addComponent(new PositionComponent(
- Math.random() * 2000,
- Math.random() * 2000
- ));
- npc.addComponent(new HealthComponent(500));
- npc.addComponent(new AIComponent("patrol"));
- npc.tag = 3; // NPC标签
- });
-
- return npcs;
- }
-
- // 查询附近的玩家
- public getNearbyPlayers(centerX: number, centerY: number, radius: number): Entity[] {
- return this.entityManager
- .query()
- .withAll(PositionComponent, NetworkComponent)
- .where(entity => {
- const pos = entity.getComponent(PositionComponent);
- if (!pos) return false;
-
- const distance = Math.sqrt(
- Math.pow(pos.x - centerX, 2) +
- Math.pow(pos.y - centerY, 2)
- );
- return distance <= radius;
- })
- .execute();
- }
-
- // 查询公会成员
- public getGuildMembers(guildId: string): Entity[] {
- return this.entityManager
- .query()
- .withAll(GuildComponent, NetworkComponent)
- .where(entity => {
- const guild = entity.getComponent(GuildComponent);
- return guild && guild.guildId === guildId;
- })
- .execute();
- }
-
- // 获取在线玩家统计
- public getOnlinePlayerStats(): any {
- const allPlayers = this.entityManager.getEntitiesWithComponent(NetworkComponent);
- const localPlayers = this.entityManager.getEntitiesByTag(1);
- const remotePlayers = this.entityManager.getEntitiesByTag(2);
-
- return {
- total: allPlayers.length,
- local: localPlayers.length,
- remote: remotePlayers.length
- };
- }
-}
-
-// 网络同步系统
-class NetworkSyncSystem extends EntitySystem {
- constructor() {
- super(Matcher.empty().all(NetworkComponent));
- }
-
- protected process(entities: Entity[]): void {
- const networkEntities = this.entityManager.getEntitiesWithComponent(NetworkComponent);
-
- networkEntities.forEach(entity => {
- const network = entity.getComponent(NetworkComponent);
- if (!network || network.isLocal) return;
-
- // 同步远程实体数据
- this.syncRemoteEntity(entity);
- });
- }
-
- private syncRemoteEntity(entity: Entity): void {
- // 网络同步逻辑
- const network = entity.getComponent(NetworkComponent);
- if (!network) return;
-
- const currentTime = Date.now();
- if (currentTime - network.lastSyncTime > 100) { // 100ms同步一次
- // 发送同步数据
- network.lastSyncTime = currentTime;
- }
- }
-}
-
-## 性能优化建议
-
-### 小型游戏(< 1000实体)
-- 使用简单的查询方法
-- 不需要复杂的优化
-- 重点关注代码可读性
-
-### 中型游戏(1000-10000实体)
-- 使用标签查询优化性能
-- 实现基础的对象池
-- 缓存频繁查询的结果
-
-### 大型游戏(10000-100000实体)
-- 使用时间分片处理大量实体
-- 实现空间分区优化邻近查询
-- 使用批量操作减少单次调用开销
-
-### MMO游戏(100000+实体)
-- 实现分区管理,只处理相关区域的实体
-- 使用异步处理避免阻塞主线程
-- 实现智能缓存和预加载机制
-
-## 总结
-
-ECS框架的灵活性使其能够适应各种规模的游戏开发需求:
-
-1. **小型游戏**:简单直接,快速开发
-2. **中型游戏**:平衡性能和复杂度
-3. **大型游戏**:充分利用优化特性
-4. **MMO游戏**:处理海量实体和复杂交互
-
-选择合适的架构模式和优化策略,可以让ECS框架在不同场景下都发挥最佳性能。
\ No newline at end of file
diff --git a/examples/lawn-mower-demo b/examples/lawn-mower-demo
index 8f217c95..5a4976b1 160000
--- a/examples/lawn-mower-demo
+++ b/examples/lawn-mower-demo
@@ -1 +1 @@
-Subproject commit 8f217c95dbfeeeeb852b25da6294ed40c5e9e9ba
+Subproject commit 5a4976b192d3901b32bd463ae2898f7456e49a18
diff --git a/package-lock.json b/package-lock.json
index 425f9f89..254b7135 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -19,6 +19,7 @@
"ws": "^8.18.2"
},
"devDependencies": {
+ "@iconify/json": "^2.2.388",
"@rollup/plugin-commonjs": "^28.0.3",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-terser": "^0.4.4",
@@ -32,7 +33,269 @@
"rollup-plugin-dts": "^6.2.1",
"semver": "^7.6.3",
"ts-jest": "^29.4.0",
- "typescript": "^5.8.3"
+ "typedoc": "^0.28.13",
+ "typedoc-plugin-markdown": "^4.9.0",
+ "typescript": "^5.8.3",
+ "unplugin-icons": "^22.3.0",
+ "vitepress": "^1.6.4"
+ }
+ },
+ "node_modules/@algolia/abtesting": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.5.0.tgz",
+ "integrity": "sha512-W/ohRkbKQsqDWALJg28X15KF7Tcyg53L1MfdOkLgvkcCcofdzGHSimHHeNG05ojjFw9HK8+VPhe/Vwq4MozIJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/autocomplete-core": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.17.7.tgz",
+ "integrity": "sha512-BjiPOW6ks90UKl7TwMv7oNQMnzU+t/wk9mgIDi6b1tXpUek7MW0lbNOUHpvam9pe3lVCf4xPFT+lK7s+e+fs7Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-plugin-algolia-insights": "1.17.7",
+ "@algolia/autocomplete-shared": "1.17.7"
+ }
+ },
+ "node_modules/@algolia/autocomplete-plugin-algolia-insights": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.17.7.tgz",
+ "integrity": "sha512-Jca5Ude6yUOuyzjnz57og7Et3aXjbwCSDf/8onLHSQgw1qW3ALl9mrMWaXb5FmPVkV3EtkD2F/+NkT6VHyPu9A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "search-insights": ">= 1 < 3"
+ }
+ },
+ "node_modules/@algolia/autocomplete-preset-algolia": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.17.7.tgz",
+ "integrity": "sha512-ggOQ950+nwbWROq2MOCIL71RE0DdQZsceqrg32UqnhDz8FlO9rL8ONHNsI2R1MH0tkgVIDKI/D0sMiUchsFdWA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-shared": "1.17.7"
+ },
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/autocomplete-shared": {
+ "version": "1.17.7",
+ "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.17.7.tgz",
+ "integrity": "sha512-o/1Vurr42U/qskRSuhBH+VKxMvkkUVTLU6WZQr+L5lGZZLYWyhdzWjW0iGXY7EkwRTjBqvN2EsR81yCTGV/kmg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@algolia/client-search": ">= 4.9.1 < 6",
+ "algoliasearch": ">= 4.9.1 < 6"
+ }
+ },
+ "node_modules/@algolia/client-abtesting": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.39.0.tgz",
+ "integrity": "sha512-Vf0ZVe+qo3sHDrCinouJqlg8VoxM4Qo/KxNIqMYybkuctutfnp3kIY9OmESplOQ/9NGBthU9EG+4d5fBibWK/A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-analytics": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.39.0.tgz",
+ "integrity": "sha512-V16ITZxYIwcv1arNce65JZmn94Ft6vKlBZ//gXw8AvIH32glJz1KcbaVAUr9p7PYlGZ/XVHP6LxDgrpNdtwgcA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-common": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.39.0.tgz",
+ "integrity": "sha512-UCJTuwySEQeiKPWV3wruhuI/wHbDYenHzgL9pYsvh6r/u5Z+g61ip1iwdAlFp02CnywzI9O7+AQPh2ManYyHmQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-insights": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.39.0.tgz",
+ "integrity": "sha512-s0ia8M/ZZR+iO2uLNTBrlQdEb6ZMAMcKMHckp5mcoglxrf8gHifL4LmdhGKdAxAn3UIagtqIP0RCnIymHUbm7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-personalization": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.39.0.tgz",
+ "integrity": "sha512-vZPIt7Lw+toNsHZUiPhNIc1Z3vUjDp7nzn6AMOaPC73gEuTq2iLPNvM06CSB6aHePo5eMeJIP5YEKBUQUA/PJA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-query-suggestions": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.39.0.tgz",
+ "integrity": "sha512-jcPQr3iKTWNVli2NYHPv02aNLwixDjPCpOgMp9CZTvEiPI6Ec4jHX+oFr3LDZagOFY9e1xJhc/JrgMGGW1sHnw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/client-search": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.39.0.tgz",
+ "integrity": "sha512-/IYpF10BpthGZEJQZMhMqV4AqWr5avcWfZm/SIKK1RvUDmzGqLoW/+xeJVX9C8ZnNkIC8hivbIQFaNaRw0BFZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/ingestion": {
+ "version": "1.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.39.0.tgz",
+ "integrity": "sha512-IgSHKUiuecqLfBlXiuCSdRTdsO3/yvpmXrMFz8fAJ8M4QmDtHkOuD769dmybRYqsbYMHivw+lir4BgbRGMtOIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/monitoring": {
+ "version": "1.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.39.0.tgz",
+ "integrity": "sha512-8Xnd4+609SKC/hqVsuFc4evFBmvA2765/4NcH+Dpr756SKPbL1BY0X8kVxlmM3YBLNqnduSQxHxpDJUK58imCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/recommend": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.39.0.tgz",
+ "integrity": "sha512-D7Ye2Ss/5xqUkQUxKm/VqEJLt5kARd9IMmjdzlxaKhGgNlOemTay0lwBmOVFuJRp7UODjp5c9+K+B8g0ORObIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-browser-xhr": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.39.0.tgz",
+ "integrity": "sha512-mgPte1ZJqpk9dkVs44J3wKAbHATvHZNlSpzhMdjMLIg/3qTycSZyDiomLiSlxE8CLsxyBAOJWnyKRHfom+Z1rg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-fetch": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.39.0.tgz",
+ "integrity": "sha512-LIrCkrxu1WnO3ev1+w6NnZ12JZL/o+2H9w6oWnZAjQZIlA/Ym6M9QHkt+OQ/SwkuoiNkW3DAo+Pi4A2V9FPtqg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
+ "node_modules/@algolia/requester-node-http": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.39.0.tgz",
+ "integrity": "sha512-6beG+egPwXmvhAg+m0STCj+ZssDcjrLzf4L05aKm2nGglMXSSPz0cH/rM+kVD9krNfldiMctURd4wjojW1fV0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/client-common": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
}
},
"node_modules/@ampproject/remapping": {
@@ -48,6 +311,30 @@
"node": ">=6.0.0"
}
},
+ "node_modules/@antfu/install-pkg": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@antfu/install-pkg/-/install-pkg-1.1.0.tgz",
+ "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "package-manager-detector": "^1.3.0",
+ "tinyexec": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@antfu/utils": {
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-9.2.1.tgz",
+ "integrity": "sha512-TMilPqXyii1AsiEii6l6ubRzbo76p6oshUSYPaKsmXDavyMLqjzVDkcp3pHp5ELMUNJHATcEOGxKTTsX9yYhGg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
@@ -430,13 +717,13 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.28.3",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
- "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz",
+ "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.28.2"
+ "@babel/types": "^7.28.4"
},
"bin": {
"parser": "bin/babel-parser.js"
@@ -1797,9 +2084,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.28.2",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
- "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
+ "version": "7.28.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz",
+ "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -1840,6 +2127,57 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
+ "node_modules/@docsearch/css": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.8.2.tgz",
+ "integrity": "sha512-y05ayQFyUmCXze79+56v/4HpycYF3uFqB78pLPrSV5ZKAlDuIAAJNhaRi8tTdRNXh05yxX/TyNnzD6LwSM89vQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@docsearch/js": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.8.2.tgz",
+ "integrity": "sha512-Q5wY66qHn0SwA7Taa0aDbHiJvaFJLOJyHmooQ7y8hlwwQLQ/5WwCcoX0g7ii04Qi2DJlHsd0XXzJ8Ypw9+9YmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@docsearch/react": "3.8.2",
+ "preact": "^10.0.0"
+ }
+ },
+ "node_modules/@docsearch/react": {
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.8.2.tgz",
+ "integrity": "sha512-xCRrJQlTt8N9GU0DG4ptwHRkfnSnD/YpdeaXe02iKfqs97TkZJv60yE+1eq/tjPcVnTW8dP5qLP7itifFVV5eg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/autocomplete-core": "1.17.7",
+ "@algolia/autocomplete-preset-algolia": "1.17.7",
+ "@docsearch/css": "3.8.2",
+ "algoliasearch": "^5.14.2"
+ },
+ "peerDependencies": {
+ "@types/react": ">= 16.8.0 < 19.0.0",
+ "react": ">= 16.8.0 < 19.0.0",
+ "react-dom": ">= 16.8.0 < 19.0.0",
+ "search-insights": ">= 1 < 3"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "search-insights": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@emnapi/core": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.5.tgz",
@@ -1871,6 +2209,397 @@
"tslib": "^2.4.0"
}
},
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@esengine/ecs-framework": {
"resolved": "packages/core",
"link": true
@@ -1891,6 +2620,62 @@
"resolved": "packages/network-shared",
"link": true
},
+ "node_modules/@gerrit0/mini-shiki": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.13.0.tgz",
+ "integrity": "sha512-mCrNvZNYNrwKer5PWLF6cOc0OEe2eKzgy976x+IT2tynwJYl+7UpHTSeXQJGijgTcoOf+f359L946unWlYRnsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/engine-oniguruma": "^3.13.0",
+ "@shikijs/langs": "^3.13.0",
+ "@shikijs/themes": "^3.13.0",
+ "@shikijs/types": "^3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/engine-oniguruma": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz",
+ "integrity": "sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/langs": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.13.0.tgz",
+ "integrity": "sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0"
+ }
+ },
+ "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/themes": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.13.0.tgz",
+ "integrity": "sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "3.13.0"
+ }
+ },
+ "node_modules/@gerrit0/mini-shiki/node_modules/@shikijs/types": {
+ "version": "3.13.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz",
+ "integrity": "sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
"node_modules/@hutson/parse-repository-url": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz",
@@ -1901,6 +2686,51 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@iconify-json/simple-icons": {
+ "version": "1.2.53",
+ "resolved": "https://registry.npmjs.org/@iconify-json/simple-icons/-/simple-icons-1.2.53.tgz",
+ "integrity": "sha512-8GEW5mshsPAZpVAJmkBG/niR2qn8t4U03Wmz6aSD9R4VMZKTECqbOxH3z4inA0JfZOoTvP4qoK9T2VXAx2Xg5g==",
+ "dev": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "@iconify/types": "*"
+ }
+ },
+ "node_modules/@iconify/json": {
+ "version": "2.2.388",
+ "resolved": "https://registry.npmjs.org/@iconify/json/-/json-2.2.388.tgz",
+ "integrity": "sha512-sNwZo4oDovAA7IT1XHfJiEP4fLialEFYALrGVQAblbflkICEJFnK6rUK0sHhvkkX2HUTNTMywOX+LG9AGVN3Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@iconify/types": "*",
+ "pathe": "^1.1.2"
+ }
+ },
+ "node_modules/@iconify/types": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
+ "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@iconify/utils": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@iconify/utils/-/utils-3.0.2.tgz",
+ "integrity": "sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@antfu/install-pkg": "^1.1.0",
+ "@antfu/utils": "^9.2.0",
+ "@iconify/types": "^2.0.0",
+ "debug": "^4.4.1",
+ "globals": "^15.15.0",
+ "kolorist": "^1.8.0",
+ "local-pkg": "^1.1.1",
+ "mlly": "^1.7.4"
+ }
+ },
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
@@ -2367,6 +3197,17 @@
"@jridgewell/trace-mapping": "^0.3.24"
}
},
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
@@ -2387,10 +3228,11 @@
}
},
"node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
- "dev": true
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.29",
@@ -3906,6 +4748,93 @@
"win32"
]
},
+ "node_modules/@shikijs/core": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-2.5.0.tgz",
+ "integrity": "sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4",
+ "hast-util-to-html": "^9.0.4"
+ }
+ },
+ "node_modules/@shikijs/engine-javascript": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz",
+ "integrity": "sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "oniguruma-to-es": "^3.1.0"
+ }
+ },
+ "node_modules/@shikijs/engine-oniguruma": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz",
+ "integrity": "sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2"
+ }
+ },
+ "node_modules/@shikijs/langs": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-2.5.0.tgz",
+ "integrity": "sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/themes": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-2.5.0.tgz",
+ "integrity": "sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/transformers": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-2.5.0.tgz",
+ "integrity": "sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/types": "2.5.0"
+ }
+ },
+ "node_modules/@shikijs/types": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-2.5.0.tgz",
+ "integrity": "sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
+ "node_modules/@shikijs/vscode-textmate": {
+ "version": "10.0.2",
+ "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
+ "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@sigstore/bundle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz",
@@ -4175,6 +5104,16 @@
"@types/node": "*"
}
},
+ "node_modules/@types/hast": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+ "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
"node_modules/@types/http-errors": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
@@ -4225,6 +5164,41 @@
"parse5": "^7.0.0"
}
},
+ "node_modules/@types/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/markdown-it": {
+ "version": "14.1.2",
+ "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz",
+ "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/linkify-it": "^5",
+ "@types/mdurl": "^2"
+ }
+ },
+ "node_modules/@types/mdast": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+ "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "*"
+ }
+ },
+ "node_modules/@types/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
@@ -4315,6 +5289,13 @@
"integrity": "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==",
"dev": true
},
+ "node_modules/@types/unist": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+ "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
@@ -4322,6 +5303,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@types/web-bluetooth": {
+ "version": "0.0.21",
+ "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+ "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
@@ -4346,6 +5334,291 @@
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
"dev": true
},
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+ "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@vitejs/plugin-vue": {
+ "version": "5.2.4",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+ "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^5.0.0 || ^6.0.0",
+ "vue": "^3.2.25"
+ }
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.22.tgz",
+ "integrity": "sha512-jQ0pFPmZwTEiRNSb+i9Ow/I/cHv2tXYqsnHKKyCQ08irI2kdF5qmYedmF8si8mA7zepUFmJ2hqzS8CQmNOWOkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.4",
+ "@vue/shared": "3.5.22",
+ "entities": "^4.5.0",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-core/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.22.tgz",
+ "integrity": "sha512-W8RknzUM1BLkypvdz10OVsGxnMAuSIZs9Wdx1vzA3mL5fNMN15rhrSCLiTm6blWeACwUwizzPVqGJgOGBEN/hA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-core": "3.5.22",
+ "@vue/shared": "3.5.22"
+ }
+ },
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.22.tgz",
+ "integrity": "sha512-tbTR1zKGce4Lj+JLzFXDq36K4vcSZbJ1RBu8FxcDv1IGRz//Dh2EBqksyGVypz3kXpshIfWKGOCcqpSbyGWRJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.28.4",
+ "@vue/compiler-core": "3.5.22",
+ "@vue/compiler-dom": "3.5.22",
+ "@vue/compiler-ssr": "3.5.22",
+ "@vue/shared": "3.5.22",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.19",
+ "postcss": "^8.5.6",
+ "source-map-js": "^1.2.1"
+ }
+ },
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.22.tgz",
+ "integrity": "sha512-GdgyLvg4R+7T8Nk2Mlighx7XGxq/fJf9jaVofc3IL0EPesTE86cP/8DD1lT3h1JeZr2ySBvyqKQJgbS54IX1Ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.22",
+ "@vue/shared": "3.5.22"
+ }
+ },
+ "node_modules/@vue/devtools-api": {
+ "version": "7.7.7",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.7.tgz",
+ "integrity": "sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-kit": "^7.7.7"
+ }
+ },
+ "node_modules/@vue/devtools-kit": {
+ "version": "7.7.7",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.7.tgz",
+ "integrity": "sha512-wgoZtxcTta65cnZ1Q6MbAfePVFxfM+gq0saaeytoph7nEa7yMXoi6sCPy4ufO111B9msnw0VOWjPEFCXuAKRHA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/devtools-shared": "^7.7.7",
+ "birpc": "^2.3.0",
+ "hookable": "^5.5.3",
+ "mitt": "^3.0.1",
+ "perfect-debounce": "^1.0.0",
+ "speakingurl": "^14.0.1",
+ "superjson": "^2.2.2"
+ }
+ },
+ "node_modules/@vue/devtools-shared": {
+ "version": "7.7.7",
+ "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.7.tgz",
+ "integrity": "sha512-+udSj47aRl5aKb0memBvcUG9koarqnxNM5yjuREvqwK6T3ap4mn3Zqqc17QrBFTqSMjr3HK1cvStEZpMDpfdyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "rfdc": "^1.4.1"
+ }
+ },
+ "node_modules/@vue/reactivity": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.22.tgz",
+ "integrity": "sha512-f2Wux4v/Z2pqc9+4SmgZC1p73Z53fyD90NFWXiX9AKVnVBEvLFOWCEgJD3GdGnlxPZt01PSlfmLqbLYzY/Fw4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/shared": "3.5.22"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.22.tgz",
+ "integrity": "sha512-EHo4W/eiYeAzRTN5PCextDUZ0dMs9I8mQ2Fy+OkzvRPUYQEyK9yAjbasrMCXbLNhF7P0OUyivLjIy0yc6VrLJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.22",
+ "@vue/shared": "3.5.22"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.22.tgz",
+ "integrity": "sha512-Av60jsryAkI023PlN7LsqrfPvwfxOd2yAwtReCjeuugTJTkgrksYJJstg1e12qle0NarkfhfFu1ox2D+cQotww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/reactivity": "3.5.22",
+ "@vue/runtime-core": "3.5.22",
+ "@vue/shared": "3.5.22",
+ "csstype": "^3.1.3"
+ }
+ },
+ "node_modules/@vue/server-renderer": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.22.tgz",
+ "integrity": "sha512-gXjo+ao0oHYTSswF+a3KRHZ1WszxIqO7u6XwNHqcqb9JfyIL/pbWrrh/xLv7jeDqla9u+LK7yfZKHih1e1RKAQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-ssr": "3.5.22",
+ "@vue/shared": "3.5.22"
+ },
+ "peerDependencies": {
+ "vue": "3.5.22"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.22.tgz",
+ "integrity": "sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@vueuse/core": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-12.8.2.tgz",
+ "integrity": "sha512-HbvCmZdzAu3VGi/pWYm5Ut+Kd9mn1ZHnn4L5G8kOQTPs/IwIAmJoBrmYk2ckLArgMXZj0AW3n5CAejLUO+PhdQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/web-bluetooth": "^0.0.21",
+ "@vueuse/metadata": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/integrations": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-12.8.2.tgz",
+ "integrity": "sha512-fbGYivgK5uBTRt7p5F3zy6VrETlV9RtZjBqd1/HxGdjdckBgBM4ugP8LHpjolqTj14TXTxSK1ZfgPbHYyGuH7g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vueuse/core": "12.8.2",
+ "@vueuse/shared": "12.8.2",
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "async-validator": "^4",
+ "axios": "^1",
+ "change-case": "^5",
+ "drauu": "^0.4",
+ "focus-trap": "^7",
+ "fuse.js": "^7",
+ "idb-keyval": "^6",
+ "jwt-decode": "^4",
+ "nprogress": "^0.2",
+ "qrcode": "^1.5",
+ "sortablejs": "^1",
+ "universal-cookie": "^7"
+ },
+ "peerDependenciesMeta": {
+ "async-validator": {
+ "optional": true
+ },
+ "axios": {
+ "optional": true
+ },
+ "change-case": {
+ "optional": true
+ },
+ "drauu": {
+ "optional": true
+ },
+ "focus-trap": {
+ "optional": true
+ },
+ "fuse.js": {
+ "optional": true
+ },
+ "idb-keyval": {
+ "optional": true
+ },
+ "jwt-decode": {
+ "optional": true
+ },
+ "nprogress": {
+ "optional": true
+ },
+ "qrcode": {
+ "optional": true
+ },
+ "sortablejs": {
+ "optional": true
+ },
+ "universal-cookie": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@vueuse/metadata": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-12.8.2.tgz",
+ "integrity": "sha512-rAyLGEuoBJ/Il5AmFHiziCPdQzRt88VxR+Y/A/QhJ1EWtWqPBBAxTAFaSkviwEuOEZNtW8pvkPgoCZQ+HxqW1A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
+ "node_modules/@vueuse/shared": {
+ "version": "12.8.2",
+ "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-12.8.2.tgz",
+ "integrity": "sha512-dznP38YzxZoNloI0qpEfpkms8knDtaoQ6Y/sfS0L7Yki4zh40LFHEhur0odJC6xTHG5dxWVPiUWBXn+wCG2s5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "vue": "^3.5.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/@yarnpkg/lockfile": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
@@ -4471,6 +5744,32 @@
"node": ">=8"
}
},
+ "node_modules/algoliasearch": {
+ "version": "5.39.0",
+ "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.39.0.tgz",
+ "integrity": "sha512-DzTfhUxzg9QBNGzU/0kZkxEV72TeA4MmPJ7RVfLnQwHNhhliPo7ynglEWJS791rNlLFoTyrKvkapwr/P3EXV9A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@algolia/abtesting": "1.5.0",
+ "@algolia/client-abtesting": "5.39.0",
+ "@algolia/client-analytics": "5.39.0",
+ "@algolia/client-common": "5.39.0",
+ "@algolia/client-insights": "5.39.0",
+ "@algolia/client-personalization": "5.39.0",
+ "@algolia/client-query-suggestions": "5.39.0",
+ "@algolia/client-search": "5.39.0",
+ "@algolia/ingestion": "1.39.0",
+ "@algolia/monitoring": "1.39.0",
+ "@algolia/recommend": "5.39.0",
+ "@algolia/requester-browser-xhr": "5.39.0",
+ "@algolia/requester-fetch": "5.39.0",
+ "@algolia/requester-node-http": "5.39.0"
+ },
+ "engines": {
+ "node": ">= 14.0.0"
+ }
+ },
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
@@ -4867,6 +6166,16 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/birpc": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.6.1.tgz",
+ "integrity": "sha512-LPnFhlDpdSH6FJhJyn4M0kFO7vtQ5iPw24FnG0y21q09xC7e8+1LeR31S1MAIrDAHp4m7aas4bEkTDTvMAtebQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
@@ -5096,6 +6405,17 @@
],
"license": "CC-BY-4.0"
},
+ "node_modules/ccount": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+ "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@@ -5121,6 +6441,28 @@
"node": ">=10"
}
},
+ "node_modules/character-entities-html4": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+ "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
+ "node_modules/character-entities-legacy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+ "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/chardet": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
@@ -5326,6 +6668,17 @@
"node": ">= 0.8"
}
},
+ "node_modules/comma-separated-tokens": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
@@ -5378,6 +6731,13 @@
"typedarray": "^0.0.6"
}
},
+ "node_modules/confbox": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz",
+ "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/console-control-strings": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
@@ -5563,6 +6923,22 @@
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true
},
+ "node_modules/copy-anything": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
+ "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-what": "^4.1.8"
+ },
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
"node_modules/core-js-compat": {
"version": "3.45.1",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.45.1.tgz",
@@ -5727,6 +7103,13 @@
"integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==",
"dev": true
},
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/dargs": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
@@ -5883,6 +7266,16 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/detect-indent": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz",
@@ -5902,6 +7295,20 @@
"node": ">=8"
}
},
+ "node_modules/devlop": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+ "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dequal": "^2.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@@ -6038,6 +7445,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/emoji-regex-xs": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz",
+ "integrity": "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/encoding": {
"version": "0.1.13",
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
@@ -6168,6 +7582,45 @@
"node": ">= 0.4"
}
},
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -6312,6 +7765,13 @@
"dev": true,
"license": "Apache-2.0"
},
+ "node_modules/exsolve": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.7.tgz",
+ "integrity": "sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/external-editor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
@@ -6464,6 +7924,16 @@
"flat": "cli.js"
}
},
+ "node_modules/focus-trap": {
+ "version": "7.6.5",
+ "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.6.5.tgz",
+ "integrity": "sha512-7Ke1jyybbbPZyZXFxEftUtxFGLMpE2n6A+z//m4CRDlj0hW+o3iYSmh8nFlYMurOiJVDmJRilUQtJr08KfIxlg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tabbable": "^6.2.0"
+ }
+ },
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
@@ -6907,6 +8377,19 @@
"node": ">=10.13.0"
}
},
+ "node_modules/globals": {
+ "version": "15.15.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz",
+ "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -7012,6 +8495,51 @@
"node": ">= 0.4"
}
},
+ "node_modules/hast-util-to-html": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz",
+ "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/unist": "^3.0.0",
+ "ccount": "^2.0.0",
+ "comma-separated-tokens": "^2.0.0",
+ "hast-util-whitespace": "^3.0.0",
+ "html-void-elements": "^3.0.0",
+ "mdast-util-to-hast": "^13.0.0",
+ "property-information": "^7.0.0",
+ "space-separated-tokens": "^2.0.0",
+ "stringify-entities": "^4.0.0",
+ "zwitch": "^2.0.4"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hast-util-whitespace": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+ "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/hookable": {
+ "version": "5.5.3",
+ "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
+ "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/hosted-git-info": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-7.0.2.tgz",
@@ -7050,6 +8578,17 @@
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
+ "node_modules/html-void-elements": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz",
+ "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
@@ -7540,6 +9079,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/is-what": {
+ "version": "4.1.16",
+ "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
+ "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.13"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mesqueeb"
+ }
+ },
"node_modules/is-wsl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
@@ -8604,6 +10156,13 @@
"node": ">=6"
}
},
+ "node_modules/kolorist": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
+ "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/lerna": {
"version": "8.2.3",
"resolved": "https://registry.npmjs.org/lerna/-/lerna-8.2.3.tgz",
@@ -9015,6 +10574,16 @@
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"dev": true
},
+ "node_modules/linkify-it": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
+ "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "uc.micro": "^2.0.0"
+ }
+ },
"node_modules/load-json-file": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-6.2.0.tgz",
@@ -9041,6 +10610,24 @@
"node": ">=8"
}
},
+ "node_modules/local-pkg": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.1.2.tgz",
+ "integrity": "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mlly": "^1.7.4",
+ "pkg-types": "^2.3.0",
+ "quansync": "^0.2.11"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ }
+ },
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
@@ -9112,13 +10699,21 @@
"yallist": "^3.0.2"
}
},
- "node_modules/magic-string": {
- "version": "0.30.17",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
- "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
+ "node_modules/lunr": {
+ "version": "2.3.9",
+ "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
+ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.19",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz",
+ "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@jridgewell/sourcemap-codec": "^1.5.0"
+ "@jridgewell/sourcemap-codec": "^1.5.5"
}
},
"node_modules/make-dir": {
@@ -9188,6 +10783,51 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/mark.js": {
+ "version": "8.11.1",
+ "resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz",
+ "integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/markdown-it": {
+ "version": "14.1.0",
+ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
+ "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1",
+ "entities": "^4.4.0",
+ "linkify-it": "^5.0.0",
+ "mdurl": "^2.0.0",
+ "punycode.js": "^2.3.1",
+ "uc.micro": "^2.1.0"
+ },
+ "bin": {
+ "markdown-it": "bin/markdown-it.mjs"
+ }
+ },
+ "node_modules/markdown-it/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/markdown-it/node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -9197,6 +10837,35 @@
"node": ">= 0.4"
}
},
+ "node_modules/mdast-util-to-hast": {
+ "version": "13.2.0",
+ "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz",
+ "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/hast": "^3.0.0",
+ "@types/mdast": "^4.0.0",
+ "@ungap/structured-clone": "^1.0.0",
+ "devlop": "^1.0.0",
+ "micromark-util-sanitize-uri": "^2.0.0",
+ "trim-lines": "^3.0.0",
+ "unist-util-position": "^5.0.0",
+ "unist-util-visit": "^5.0.0",
+ "vfile": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/mdurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
+ "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/meow": {
"version": "8.1.2",
"resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
@@ -9385,6 +11054,100 @@
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
+ "node_modules/micromark-util-character": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+ "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-symbol": "^2.0.0",
+ "micromark-util-types": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-encode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+ "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-sanitize-uri": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+ "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "micromark-util-character": "^2.0.0",
+ "micromark-util-encode": "^2.0.0",
+ "micromark-util-symbol": "^2.0.0"
+ }
+ },
+ "node_modules/micromark-util-symbol": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+ "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/micromark-util-types": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+ "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "GitHub Sponsors",
+ "url": "https://github.com/sponsors/unifiedjs"
+ },
+ {
+ "type": "OpenCollective",
+ "url": "https://opencollective.com/unified"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -9630,6 +11393,13 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/minisearch": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-7.2.0.tgz",
+ "integrity": "sha512-dqT2XBYUOZOiC5t2HRnwADjhNS2cecp9u+TJRiJ1Qp/f5qjkeT5APcGPjHw+bz89Ms8Jp+cG4AlE+QZ/QnDglg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/minizlib": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
@@ -9664,6 +11434,13 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
@@ -9677,6 +11454,45 @@
"node": ">=10"
}
},
+ "node_modules/mlly": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.0.tgz",
+ "integrity": "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "pathe": "^2.0.3",
+ "pkg-types": "^1.3.1",
+ "ufo": "^1.6.1"
+ }
+ },
+ "node_modules/mlly/node_modules/confbox": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz",
+ "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mlly/node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mlly/node_modules/pkg-types": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz",
+ "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "confbox": "^0.1.8",
+ "mlly": "^1.7.4",
+ "pathe": "^2.0.1"
+ }
+ },
"node_modules/modify-values": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz",
@@ -9754,6 +11570,25 @@
"dev": true,
"license": "ISC"
},
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -10171,6 +12006,18 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/oniguruma-to-es": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz",
+ "integrity": "sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex-xs": "^1.0.0",
+ "regex": "^6.0.1",
+ "regex-recursion": "^6.0.2"
+ }
+ },
"node_modules/open": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
@@ -10386,6 +12233,13 @@
"dev": true,
"license": "BlueOak-1.0.0"
},
+ "node_modules/package-manager-detector": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.3.0.tgz",
+ "integrity": "sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/pacote": {
"version": "18.0.6",
"resolved": "https://registry.npmjs.org/pacote/-/pacote-18.0.6.tgz",
@@ -10587,6 +12441,20 @@
"node": ">=4"
}
},
+ "node_modules/pathe": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz",
+ "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/perfect-debounce": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
+ "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -10594,10 +12462,11 @@
"dev": true
},
"node_modules/picomatch": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
- "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -10639,6 +12508,54 @@
"node": ">=8"
}
},
+ "node_modules/pkg-types": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz",
+ "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "confbox": "^0.2.2",
+ "exsolve": "^1.0.7",
+ "pathe": "^2.0.3"
+ }
+ },
+ "node_modules/pkg-types/node_modules/pathe": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/postcss": {
+ "version": "8.5.6",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
+ "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
"node_modules/postcss-selector-parser": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
@@ -10653,6 +12570,17 @@
"node": ">=4"
}
},
+ "node_modules/preact": {
+ "version": "10.27.2",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.27.2.tgz",
+ "integrity": "sha512-5SYSgFKSyhCbk6SrXyMpqjb5+MQBgfvEKE/OC+PujcY34sOpqtr+0AZQtPYx5IA6VxynQ7rUPCtKzyovpj9Bpg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
"node_modules/pretty-format": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
@@ -10773,6 +12701,17 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/property-information": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
+ "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/protobufjs": {
"version": "7.5.3",
"resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.3.tgz",
@@ -10832,6 +12771,16 @@
"node": ">=6"
}
},
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/pure-rand": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
@@ -10848,6 +12797,23 @@
}
]
},
+ "node_modules/quansync": {
+ "version": "0.2.11",
+ "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz",
+ "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/antfu"
+ },
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/sxzz"
+ }
+ ],
+ "license": "MIT"
+ },
"node_modules/querystringify": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
@@ -11172,6 +13138,33 @@
"node": ">=4"
}
},
+ "node_modules/regex": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz",
+ "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-recursion": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz",
+ "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regex-utilities": "^2.3.0"
+ }
+ },
+ "node_modules/regex-utilities": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz",
+ "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/regexpu-core": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz",
@@ -11319,6 +13312,13 @@
"node": ">= 4"
}
},
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/rimraf": {
"version": "5.0.10",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz",
@@ -11460,6 +13460,14 @@
"node": ">=v12.22.7"
}
},
+ "node_modules/search-insights": {
+ "version": "2.17.3",
+ "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.17.3.tgz",
+ "integrity": "sha512-RQPdCYTa8A68uM2jwxoY842xDhvx3E5LFL1LxvxCNMev4o5mLuokczhzjAgGwUZBAmOKZknArSxLKmXtIi2AxQ==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
@@ -11525,6 +13533,23 @@
"node": ">=8"
}
},
+ "node_modules/shiki": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/shiki/-/shiki-2.5.0.tgz",
+ "integrity": "sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@shikijs/core": "2.5.0",
+ "@shikijs/engine-javascript": "2.5.0",
+ "@shikijs/engine-oniguruma": "2.5.0",
+ "@shikijs/langs": "2.5.0",
+ "@shikijs/themes": "2.5.0",
+ "@shikijs/types": "2.5.0",
+ "@shikijs/vscode-textmate": "^10.0.2",
+ "@types/hast": "^3.0.4"
+ }
+ },
"node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
@@ -11650,6 +13675,16 @@
"node": ">=0.10.0"
}
},
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
@@ -11660,6 +13695,17 @@
"source-map": "^0.6.0"
}
},
+ "node_modules/space-separated-tokens": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+ "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/spdx-correct": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
@@ -11696,6 +13742,16 @@
"dev": true,
"license": "CC0-1.0"
},
+ "node_modules/speakingurl": {
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
+ "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/split": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
@@ -11804,6 +13860,21 @@
"node": ">=8"
}
},
+ "node_modules/stringify-entities": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+ "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "character-entities-html4": "^2.0.0",
+ "character-entities-legacy": "^3.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
@@ -11874,6 +13945,19 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/superjson": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz",
+ "integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "copy-anything": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -11904,6 +13988,13 @@
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true
},
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tar": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
@@ -12128,6 +14219,13 @@
"safe-buffer": "~5.1.0"
}
},
+ "node_modules/tinyexec": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.1.tgz",
+ "integrity": "sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/tinyglobby": {
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
@@ -12210,6 +14308,17 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/trim-lines": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+ "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"node_modules/trim-newlines": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
@@ -12403,6 +14512,43 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/typedoc": {
+ "version": "0.28.13",
+ "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.13.tgz",
+ "integrity": "sha512-dNWY8msnYB2a+7Audha+aTF1Pu3euiE7ySp53w8kEsXoYw7dMouV5A1UsTUY345aB152RHnmRMDiovuBi7BD+w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@gerrit0/mini-shiki": "^3.12.0",
+ "lunr": "^2.3.9",
+ "markdown-it": "^14.1.0",
+ "minimatch": "^9.0.5",
+ "yaml": "^2.8.1"
+ },
+ "bin": {
+ "typedoc": "bin/typedoc"
+ },
+ "engines": {
+ "node": ">= 18",
+ "pnpm": ">= 10"
+ },
+ "peerDependencies": {
+ "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x"
+ }
+ },
+ "node_modules/typedoc-plugin-markdown": {
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.9.0.tgz",
+ "integrity": "sha512-9Uu4WR9L7ZBgAl60N/h+jqmPxxvnC9nQAlnnO/OujtG2ubjnKTVUFY1XDhcMY+pCqlX3N2HsQM2QTYZIU9tJuw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "typedoc": "0.28.x"
+ }
+ },
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
@@ -12417,6 +14563,20 @@
"node": ">=14.17"
}
},
+ "node_modules/uc.micro": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
+ "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ufo": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
+ "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/uglify-js": {
"version": "3.19.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
@@ -12507,6 +14667,79 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/unist-util-is": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz",
+ "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-position": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+ "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-stringify-position": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+ "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz",
+ "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0",
+ "unist-util-visit-parents": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/unist-util-visit-parents": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz",
+ "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-is": "^6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
"node_modules/universal-user-agent": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
@@ -12523,6 +14756,67 @@
"node": ">= 4.0.0"
}
},
+ "node_modules/unplugin": {
+ "version": "2.3.10",
+ "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-2.3.10.tgz",
+ "integrity": "sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/remapping": "^2.3.5",
+ "acorn": "^8.15.0",
+ "picomatch": "^4.0.3",
+ "webpack-virtual-modules": "^0.6.2"
+ },
+ "engines": {
+ "node": ">=18.12.0"
+ }
+ },
+ "node_modules/unplugin-icons": {
+ "version": "22.3.0",
+ "resolved": "https://registry.npmjs.org/unplugin-icons/-/unplugin-icons-22.3.0.tgz",
+ "integrity": "sha512-Q7c2RoVUn4LzFADT0H/oT5ApJgiWW+xTK7D5/hi6gYtObmAuEE6ebyvejvfbinJL8tH4wanoNjkWcmlqEsTcXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@antfu/install-pkg": "^1.1.0",
+ "@iconify/utils": "^3.0.1",
+ "debug": "^4.4.1",
+ "local-pkg": "^1.1.2",
+ "unplugin": "^2.3.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@svgr/core": ">=7.0.0",
+ "@svgx/core": "^1.0.1",
+ "@vue/compiler-sfc": "^3.0.2 || ^2.7.0",
+ "svelte": "^3.0.0 || ^4.0.0 || ^5.0.0",
+ "vue-template-compiler": "^2.6.12",
+ "vue-template-es2015-compiler": "^1.9.0"
+ },
+ "peerDependenciesMeta": {
+ "@svgr/core": {
+ "optional": true
+ },
+ "@svgx/core": {
+ "optional": true
+ },
+ "@vue/compiler-sfc": {
+ "optional": true
+ },
+ "svelte": {
+ "optional": true
+ },
+ "vue-template-compiler": {
+ "optional": true
+ },
+ "vue-template-es2015-compiler": {
+ "optional": true
+ }
+ }
+ },
"node_modules/upath": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz",
@@ -12636,6 +14930,160 @@
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
+ "node_modules/vfile": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+ "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "vfile-message": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vfile-message": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+ "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/unist": "^3.0.0",
+ "unist-util-stringify-position": "^4.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/unified"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.4.20",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.20.tgz",
+ "integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vitepress": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.6.4.tgz",
+ "integrity": "sha512-+2ym1/+0VVrbhNyRoFFesVvBvHAVMZMK0rw60E3X/5349M1GuVdKeazuksqopEdvkKwKGs21Q729jX81/bkBJg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@docsearch/css": "3.8.2",
+ "@docsearch/js": "3.8.2",
+ "@iconify-json/simple-icons": "^1.2.21",
+ "@shikijs/core": "^2.1.0",
+ "@shikijs/transformers": "^2.1.0",
+ "@shikijs/types": "^2.1.0",
+ "@types/markdown-it": "^14.1.2",
+ "@vitejs/plugin-vue": "^5.2.1",
+ "@vue/devtools-api": "^7.7.0",
+ "@vue/shared": "^3.5.13",
+ "@vueuse/core": "^12.4.0",
+ "@vueuse/integrations": "^12.4.0",
+ "focus-trap": "^7.6.4",
+ "mark.js": "8.11.1",
+ "minisearch": "^7.1.1",
+ "shiki": "^2.1.0",
+ "vite": "^5.4.14",
+ "vue": "^3.5.13"
+ },
+ "bin": {
+ "vitepress": "bin/vitepress.js"
+ },
+ "peerDependencies": {
+ "markdown-it-mathjax3": "^4",
+ "postcss": "^8"
+ },
+ "peerDependenciesMeta": {
+ "markdown-it-mathjax3": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/vue": {
+ "version": "3.5.22",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz",
+ "integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-dom": "3.5.22",
+ "@vue/compiler-sfc": "3.5.22",
+ "@vue/runtime-dom": "3.5.22",
+ "@vue/server-renderer": "3.5.22",
+ "@vue/shared": "3.5.22"
+ },
+ "peerDependencies": {
+ "typescript": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
@@ -12683,6 +15131,13 @@
"node": ">=12"
}
},
+ "node_modules/webpack-virtual-modules": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+ "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/whatwg-encoding": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz",
@@ -13040,9 +15495,20 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/zwitch": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+ "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/wooorm"
+ }
+ },
"packages/core": {
"name": "@esengine/ecs-framework",
- "version": "2.1.48",
+ "version": "2.1.49",
"license": "MIT",
"devDependencies": {
"@babel/core": "^7.28.3",
diff --git a/package.json b/package.json
index 8654b7d6..bfc6cbd5 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
"publish:all:dist": "npm run publish:core && npm run publish:math && npm run publish:network-shared && npm run publish:network-client && npm run publish:network-server",
"publish:core": "cd packages/core && npm run publish:npm",
"publish:core:patch": "cd packages/core && npm run publish:patch",
- "publish:math": "cd packages/math && npm run publish:npm",
+ "publish:math": "cd packages/math && npm run publish:npm",
"publish:math:patch": "cd packages/math && npm run publish:patch",
"publish:network-shared": "cd packages/network-shared && npm run publish:npm",
"publish:network-shared:patch": "cd packages/network-shared && npm run publish:patch",
@@ -48,11 +48,17 @@
"publish:network-server": "cd packages/network-server && npm run publish:npm",
"publish:network-server:patch": "cd packages/network-server && npm run publish:patch",
"publish": "lerna publish",
- "version": "lerna version"
+ "version": "lerna version",
+ "docs:dev": "vitepress dev docs",
+ "docs:build": "npm run docs:api && vitepress build docs",
+ "docs:preview": "vitepress preview docs",
+ "docs:api": "typedoc",
+ "docs:api:watch": "typedoc --watch"
},
"author": "yhh",
"license": "MIT",
"devDependencies": {
+ "@iconify/json": "^2.2.388",
"@rollup/plugin-commonjs": "^28.0.3",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-terser": "^0.4.4",
@@ -66,7 +72,11 @@
"rollup-plugin-dts": "^6.2.1",
"semver": "^7.6.3",
"ts-jest": "^29.4.0",
- "typescript": "^5.8.3"
+ "typedoc": "^0.28.13",
+ "typedoc-plugin-markdown": "^4.9.0",
+ "typescript": "^5.8.3",
+ "unplugin-icons": "^22.3.0",
+ "vitepress": "^1.6.4"
},
"publishConfig": {
"access": "public"
diff --git a/typedoc.json b/typedoc.json
new file mode 100644
index 00000000..ac729065
--- /dev/null
+++ b/typedoc.json
@@ -0,0 +1,63 @@
+{
+ "entryPoints": ["./packages/core/src/index.ts"],
+ "out": "./docs/api",
+ "plugin": ["typedoc-plugin-markdown"],
+ "readme": "none",
+ "excludePrivate": true,
+ "excludeProtected": false,
+ "excludeInternal": false,
+ "includeVersion": true,
+ "sort": ["source-order"],
+ "kindSortOrder": [
+ "Document",
+ "Project",
+ "Module",
+ "Namespace",
+ "Enum",
+ "EnumMember",
+ "Class",
+ "Interface",
+ "TypeAlias",
+ "Constructor",
+ "Property",
+ "Variable",
+ "Function",
+ "Accessor",
+ "Method",
+ "Parameter",
+ "TypeParameter",
+ "TypeLiteral",
+ "CallSignature",
+ "ConstructorSignature",
+ "IndexSignature",
+ "GetSignature",
+ "SetSignature"
+ ],
+ "categorizeByGroup": false,
+ "defaultCategory": "其他",
+ "categoryOrder": [
+ "核心",
+ "ECS",
+ "组件",
+ "系统",
+ "工具",
+ "*"
+ ],
+ "searchInComments": true,
+ "cleanOutputDir": true,
+ "titleLink": "/",
+ "navigationLinks": {
+ "首页": "/",
+ "指南": "/guide/",
+ "示例": "/examples/"
+ },
+ "sidebarLinks": {
+ "GitHub": "https://github.com/esengine/ecs-framework",
+ "NPM": "https://www.npmjs.com/package/@esengine/ecs-framework"
+ },
+ "hideGenerator": true,
+ "githubPages": false,
+ "disableSources": false,
+ "name": "ECS Framework API",
+ "skipErrorChecking": true
+}
\ No newline at end of file