feat(ecs): 添加 @NetworkEntity 装饰器,支持自动广播实体生成/销毁 (#395)
* docs: add editor-app README with setup instructions * docs: add separate EN/CN editor setup guides * feat(ecs): add @NetworkEntity decorator for auto spawn/despawn broadcasting - Add @NetworkEntity decorator to mark components for automatic network broadcasting - ECSRoom now auto-broadcasts spawn on component:added event - ECSRoom now auto-broadcasts despawn on entity:destroyed event - Entity.destroy() emits entity:destroyed event via ECSEventType - Entity active state changes emit ENTITY_ENABLED/ENTITY_DISABLED events - Add enableAutoNetworkEntity config option to ECSRoom (default true) - Update documentation for both Chinese and English
This commit is contained in:
@@ -3,6 +3,102 @@ title: "State Sync"
|
||||
description: "Component sync, interpolation, prediction and snapshot buffers"
|
||||
---
|
||||
|
||||
## @NetworkEntity Decorator
|
||||
|
||||
The `@NetworkEntity` decorator marks components for automatic spawn/despawn broadcasting. When an entity containing this component is created or destroyed, ECSRoom automatically broadcasts the corresponding message to all clients.
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```typescript
|
||||
import { Component, ECSComponent, sync, NetworkEntity } from '@esengine/ecs-framework';
|
||||
|
||||
@ECSComponent('Enemy')
|
||||
@NetworkEntity('Enemy')
|
||||
class EnemyComponent extends Component {
|
||||
@sync('float32') x: number = 0;
|
||||
@sync('float32') y: number = 0;
|
||||
@sync('uint16') health: number = 100;
|
||||
}
|
||||
```
|
||||
|
||||
When adding this component to an entity, ECSRoom automatically broadcasts the spawn message:
|
||||
|
||||
```typescript
|
||||
// Server-side
|
||||
const entity = scene.createEntity('Enemy');
|
||||
entity.addComponent(new EnemyComponent()); // Auto-broadcasts spawn
|
||||
|
||||
// Destroying auto-broadcasts despawn
|
||||
entity.destroy(); // Auto-broadcasts despawn
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
|
||||
```typescript
|
||||
@NetworkEntity('Bullet', {
|
||||
autoSpawn: true, // Auto-broadcast spawn (default true)
|
||||
autoDespawn: false // Disable auto-broadcast despawn
|
||||
})
|
||||
class BulletComponent extends Component { }
|
||||
```
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|--------|------|---------|-------------|
|
||||
| `autoSpawn` | `boolean` | `true` | Auto-broadcast spawn when component is added |
|
||||
| `autoDespawn` | `boolean` | `true` | Auto-broadcast despawn when entity is destroyed |
|
||||
|
||||
### Initialization Order
|
||||
|
||||
When using `@NetworkEntity`, initialize data **before** adding the component:
|
||||
|
||||
```typescript
|
||||
// ✅ Correct: Initialize first, then add
|
||||
const comp = new PlayerComponent();
|
||||
comp.playerId = player.id;
|
||||
comp.x = 100;
|
||||
comp.y = 200;
|
||||
entity.addComponent(comp); // Data is correct at spawn
|
||||
|
||||
// ❌ Wrong: Add first, then initialize
|
||||
const comp = entity.addComponent(new PlayerComponent());
|
||||
comp.playerId = player.id; // Data has default values at spawn
|
||||
```
|
||||
|
||||
### Simplified GameRoom
|
||||
|
||||
With `@NetworkEntity`, GameRoom becomes much cleaner:
|
||||
|
||||
```typescript
|
||||
// No manual callbacks needed
|
||||
class GameRoom extends ECSRoom {
|
||||
private setupSystems(): void {
|
||||
// Enemy spawn system (auto-broadcasts spawn)
|
||||
this.addSystem(new EnemySpawnSystem());
|
||||
|
||||
// Enemy AI system
|
||||
const enemyAI = new EnemyAISystem();
|
||||
enemyAI.onDeath((enemy) => {
|
||||
enemy.destroy(); // Auto-broadcasts despawn
|
||||
});
|
||||
this.addSystem(enemyAI);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ECSRoom Configuration
|
||||
|
||||
You can disable the auto network entity feature in ECSRoom:
|
||||
|
||||
```typescript
|
||||
class GameRoom extends ECSRoom {
|
||||
constructor() {
|
||||
super({
|
||||
enableAutoNetworkEntity: false // Disable auto-broadcasting
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Component Sync System
|
||||
|
||||
ECS component state synchronization based on `@sync` decorator.
|
||||
|
||||
@@ -3,6 +3,102 @@ title: "状态同步"
|
||||
description: "组件同步、插值、预测和快照缓冲区"
|
||||
---
|
||||
|
||||
## @NetworkEntity 装饰器
|
||||
|
||||
`@NetworkEntity` 装饰器用于标记需要自动广播生成/销毁的组件。当包含此组件的实体被创建或销毁时,ECSRoom 会自动广播相应的消息给所有客户端。
|
||||
|
||||
### 基本用法
|
||||
|
||||
```typescript
|
||||
import { Component, ECSComponent, sync, NetworkEntity } from '@esengine/ecs-framework';
|
||||
|
||||
@ECSComponent('Enemy')
|
||||
@NetworkEntity('Enemy')
|
||||
class EnemyComponent extends Component {
|
||||
@sync('float32') x: number = 0;
|
||||
@sync('float32') y: number = 0;
|
||||
@sync('uint16') health: number = 100;
|
||||
}
|
||||
```
|
||||
|
||||
当添加此组件到实体时,ECSRoom 会自动广播 spawn 消息:
|
||||
|
||||
```typescript
|
||||
// 服务端
|
||||
const entity = scene.createEntity('Enemy');
|
||||
entity.addComponent(new EnemyComponent()); // 自动广播 spawn
|
||||
|
||||
// 销毁时自动广播 despawn
|
||||
entity.destroy(); // 自动广播 despawn
|
||||
```
|
||||
|
||||
### 配置选项
|
||||
|
||||
```typescript
|
||||
@NetworkEntity('Bullet', {
|
||||
autoSpawn: true, // 自动广播生成(默认 true)
|
||||
autoDespawn: false // 禁用自动广播销毁
|
||||
})
|
||||
class BulletComponent extends Component { }
|
||||
```
|
||||
|
||||
| 选项 | 类型 | 默认值 | 描述 |
|
||||
|------|------|--------|------|
|
||||
| `autoSpawn` | `boolean` | `true` | 添加组件时自动广播 spawn |
|
||||
| `autoDespawn` | `boolean` | `true` | 销毁实体时自动广播 despawn |
|
||||
|
||||
### 初始化顺序
|
||||
|
||||
使用 `@NetworkEntity` 时,应在添加组件**之前**初始化数据:
|
||||
|
||||
```typescript
|
||||
// ✅ 正确:先初始化,再添加
|
||||
const comp = new PlayerComponent();
|
||||
comp.playerId = player.id;
|
||||
comp.x = 100;
|
||||
comp.y = 200;
|
||||
entity.addComponent(comp); // spawn 时数据已正确
|
||||
|
||||
// ❌ 错误:先添加,再初始化
|
||||
const comp = entity.addComponent(new PlayerComponent());
|
||||
comp.playerId = player.id; // spawn 时数据是默认值
|
||||
```
|
||||
|
||||
### 简化 GameRoom
|
||||
|
||||
使用 `@NetworkEntity` 后,GameRoom 变得更加简洁:
|
||||
|
||||
```typescript
|
||||
// 无需手动回调
|
||||
class GameRoom extends ECSRoom {
|
||||
private setupSystems(): void {
|
||||
// 敌人生成系统(自动广播 spawn)
|
||||
this.addSystem(new EnemySpawnSystem());
|
||||
|
||||
// 敌人 AI 系统
|
||||
const enemyAI = new EnemyAISystem();
|
||||
enemyAI.onDeath((enemy) => {
|
||||
enemy.destroy(); // 自动广播 despawn
|
||||
});
|
||||
this.addSystem(enemyAI);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ECSRoom 配置
|
||||
|
||||
可以在 ECSRoom 中禁用自动网络实体功能:
|
||||
|
||||
```typescript
|
||||
class GameRoom extends ECSRoom {
|
||||
constructor() {
|
||||
super({
|
||||
enableAutoNetworkEntity: false // 禁用自动广播
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 组件同步系统
|
||||
|
||||
基于 `@sync` 装饰器的 ECS 组件状态同步。
|
||||
|
||||
Reference in New Issue
Block a user