Compare commits
7 Commits
@esengine/
...
@esengine/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87f71e2251 | ||
|
|
b9ea8d14cf | ||
|
|
10d0fb1d5c | ||
|
|
71e111415f | ||
|
|
0de45279e6 | ||
|
|
cc6f12d470 | ||
|
|
902c0a1074 |
@@ -182,6 +182,70 @@ export class IsHealthLow implements INodeExecutor {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Using Custom Executors in BehaviorTreeBuilder
|
||||||
|
|
||||||
|
After defining a custom executor with `@NodeExecutorMetadata`, use the `.action()` method in the builder:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { BehaviorTreeBuilder, BehaviorTreeStarter } from '@esengine/behavior-tree';
|
||||||
|
|
||||||
|
// Use custom executor in behavior tree
|
||||||
|
const tree = BehaviorTreeBuilder.create('CombatAI')
|
||||||
|
.defineBlackboardVariable('health', 100)
|
||||||
|
.defineBlackboardVariable('target', null)
|
||||||
|
.selector('Root')
|
||||||
|
.sequence('AttackSequence')
|
||||||
|
// Use custom action - matches implementationType in decorator
|
||||||
|
.action('AttackAction', 'Attack', { damage: 25 })
|
||||||
|
.action('MoveToTarget', 'Chase')
|
||||||
|
.end()
|
||||||
|
.action('WaitAction', 'Idle', { duration: 1000 })
|
||||||
|
.end()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Start the behavior tree
|
||||||
|
const entity = scene.createEntity('Enemy');
|
||||||
|
BehaviorTreeStarter.start(entity, tree);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Builder Methods for Custom Nodes
|
||||||
|
|
||||||
|
| Method | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `.action(type, name?, config?)` | Add custom action node |
|
||||||
|
| `.condition(type, name?, config?)` | Add custom condition node |
|
||||||
|
| `.executeAction(name)` | Use blackboard function `action_{name}` |
|
||||||
|
| `.executeCondition(name)` | Use blackboard function `condition_{name}` |
|
||||||
|
|
||||||
|
### Complete Example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1. Define custom executor
|
||||||
|
@NodeExecutorMetadata({
|
||||||
|
implementationType: 'AttackAction',
|
||||||
|
nodeType: NodeType.Action,
|
||||||
|
displayName: 'Attack',
|
||||||
|
category: 'Combat',
|
||||||
|
configSchema: {
|
||||||
|
damage: { type: 'number', default: 10, supportBinding: true }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class AttackAction implements INodeExecutor {
|
||||||
|
execute(context: NodeExecutionContext): TaskStatus {
|
||||||
|
const damage = BindingHelper.getValue<number>(context, 'damage', 10);
|
||||||
|
console.log(`Attacking with ${damage} damage!`);
|
||||||
|
return TaskStatus.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Build and use
|
||||||
|
const tree = BehaviorTreeBuilder.create('AI')
|
||||||
|
.selector('Root')
|
||||||
|
.action('AttackAction', 'Attack', { damage: 50 })
|
||||||
|
.end()
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
## Registering Custom Executors
|
## Registering Custom Executors
|
||||||
|
|
||||||
Executors are auto-registered via the decorator. To manually register:
|
Executors are auto-registered via the decorator. To manually register:
|
||||||
|
|||||||
@@ -606,6 +606,107 @@ export class RetryDecorator implements INodeExecutor {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 在代码中使用自定义执行器
|
||||||
|
|
||||||
|
定义了自定义执行器后,可以通过 `BehaviorTreeBuilder` 的 `.action()` 和 `.condition()` 方法在代码中使用:
|
||||||
|
|
||||||
|
### 使用 action() 方法
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { BehaviorTreeBuilder, BehaviorTreeStarter } from '@esengine/behavior-tree';
|
||||||
|
|
||||||
|
// 使用自定义执行器构建行为树
|
||||||
|
const tree = BehaviorTreeBuilder.create('CombatAI')
|
||||||
|
.defineBlackboardVariable('health', 100)
|
||||||
|
.defineBlackboardVariable('target', null)
|
||||||
|
.selector('Root')
|
||||||
|
.sequence('AttackSequence')
|
||||||
|
// 使用自定义动作 - implementationType 匹配装饰器中的定义
|
||||||
|
.action('AttackAction', 'Attack', { damage: 25 })
|
||||||
|
.action('MoveToPosition', 'Chase', { speed: 10 })
|
||||||
|
.end()
|
||||||
|
.action('DelayAction', 'Idle', { duration: 1.0 })
|
||||||
|
.end()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 启动行为树
|
||||||
|
const entity = scene.createEntity('Enemy');
|
||||||
|
BehaviorTreeStarter.start(entity, tree);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 使用 condition() 方法
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const tree = BehaviorTreeBuilder.create('AI')
|
||||||
|
.selector('Root')
|
||||||
|
.sequence('AttackBranch')
|
||||||
|
// 使用自定义条件
|
||||||
|
.condition('CheckHealth', 'IsHealthy', { threshold: 50, operator: 'greater' })
|
||||||
|
.action('AttackAction', 'Attack')
|
||||||
|
.end()
|
||||||
|
.end()
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
### Builder 方法对照表
|
||||||
|
|
||||||
|
| 方法 | 说明 | 使用场景 |
|
||||||
|
|------|------|----------|
|
||||||
|
| `.action(type, name?, config?)` | 使用自定义动作执行器 | 自定义 Action 类 |
|
||||||
|
| `.condition(type, name?, config?)` | 使用自定义条件执行器 | 自定义 Condition 类 |
|
||||||
|
| `.executeAction(name)` | 调用黑板函数 `action_{name}` | 简单逻辑、快速原型 |
|
||||||
|
| `.executeCondition(name)` | 调用黑板函数 `condition_{name}` | 简单条件判断 |
|
||||||
|
|
||||||
|
### 完整示例
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {
|
||||||
|
BehaviorTreeBuilder,
|
||||||
|
BehaviorTreeStarter,
|
||||||
|
NodeExecutorMetadata,
|
||||||
|
INodeExecutor,
|
||||||
|
NodeExecutionContext,
|
||||||
|
TaskStatus,
|
||||||
|
NodeType,
|
||||||
|
BindingHelper
|
||||||
|
} from '@esengine/behavior-tree';
|
||||||
|
|
||||||
|
// 1. 定义自定义执行器
|
||||||
|
@NodeExecutorMetadata({
|
||||||
|
implementationType: 'AttackAction',
|
||||||
|
nodeType: NodeType.Action,
|
||||||
|
displayName: '攻击',
|
||||||
|
category: 'Combat',
|
||||||
|
configSchema: {
|
||||||
|
damage: { type: 'number', default: 10, supportBinding: true }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
class AttackAction implements INodeExecutor {
|
||||||
|
execute(context: NodeExecutionContext): TaskStatus {
|
||||||
|
const damage = BindingHelper.getValue<number>(context, 'damage', 10);
|
||||||
|
console.log(`执行攻击,造成 ${damage} 点伤害!`);
|
||||||
|
return TaskStatus.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 构建行为树
|
||||||
|
const enemyAI = BehaviorTreeBuilder.create('EnemyAI')
|
||||||
|
.defineBlackboardVariable('health', 100)
|
||||||
|
.defineBlackboardVariable('target', null)
|
||||||
|
.selector('MainBehavior')
|
||||||
|
.sequence('AttackBranch')
|
||||||
|
.condition('CheckHealth', 'HasEnoughHealth', { threshold: 20, operator: 'greater' })
|
||||||
|
.action('AttackAction', 'Attack', { damage: 50 })
|
||||||
|
.end()
|
||||||
|
.log('逃跑', 'Flee')
|
||||||
|
.end()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// 3. 启动行为树
|
||||||
|
const entity = scene.createEntity('Enemy');
|
||||||
|
BehaviorTreeStarter.start(entity, enemyAI);
|
||||||
|
```
|
||||||
|
|
||||||
## 注册执行器
|
## 注册执行器
|
||||||
|
|
||||||
### 自动注册
|
### 自动注册
|
||||||
|
|||||||
@@ -1,5 +1,54 @@
|
|||||||
# @esengine/behavior-tree
|
# @esengine/behavior-tree
|
||||||
|
|
||||||
|
## 4.2.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- [#408](https://github.com/esengine/esengine/pull/408) [`b9ea8d1`](https://github.com/esengine/esengine/commit/b9ea8d14cf38e1480f638c229f9ee150b65f0c60) Thanks [@esengine](https://github.com/esengine)! - feat: add action() and condition() methods to BehaviorTreeBuilder
|
||||||
|
|
||||||
|
Added new methods to support custom executor types directly in the builder:
|
||||||
|
- `action(implementationType, name?, config?)` - Use custom action executors registered via `@NodeExecutorMetadata`
|
||||||
|
- `condition(implementationType, name?, config?)` - Use custom condition executors
|
||||||
|
|
||||||
|
This provides a cleaner API for using custom node executors compared to the existing `executeAction()` which only supports blackboard functions.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Define custom executor
|
||||||
|
@NodeExecutorMetadata({
|
||||||
|
implementationType: 'AttackAction',
|
||||||
|
nodeType: NodeType.Action,
|
||||||
|
displayName: 'Attack',
|
||||||
|
category: 'Combat'
|
||||||
|
})
|
||||||
|
class AttackAction implements INodeExecutor {
|
||||||
|
execute(context: NodeExecutionContext): TaskStatus {
|
||||||
|
return TaskStatus.Success;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use in builder
|
||||||
|
const tree = BehaviorTreeBuilder.create('AI')
|
||||||
|
.selector('Root')
|
||||||
|
.action('AttackAction', 'Attack', { damage: 50 })
|
||||||
|
.end()
|
||||||
|
.build();
|
||||||
|
```
|
||||||
|
|
||||||
|
## 4.1.2
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#406](https://github.com/esengine/esengine/pull/406) [`0de4527`](https://github.com/esengine/esengine/commit/0de45279e612c04ae9be7fbd65ce496e4797a43c) Thanks [@esengine](https://github.com/esengine)! - fix(behavior-tree): export NodeExecutorMetadata as value instead of type
|
||||||
|
|
||||||
|
Fixed the export of `NodeExecutorMetadata` decorator in `execution/index.ts`.
|
||||||
|
Previously it was exported as `export type { NodeExecutorMetadata }` which only
|
||||||
|
exported the type signature, not the actual function. This caused runtime errors
|
||||||
|
in Cocos Creator: "TypeError: (intermediate value) is not a function".
|
||||||
|
|
||||||
|
Changed to `export { NodeExecutorMetadata }` to properly export the decorator function.
|
||||||
|
|
||||||
## 4.1.1
|
## 4.1.1
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@esengine/behavior-tree",
|
"name": "@esengine/behavior-tree",
|
||||||
"version": "4.1.1",
|
"version": "4.2.0",
|
||||||
"description": "ECS-based AI behavior tree system - works with any ECS framework (ESEngine, Cocos, Laya, etc.)",
|
"description": "ECS-based AI behavior tree system - works with any ECS framework (ESEngine, Cocos, Laya, etc.)",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"module": "dist/index.js",
|
"module": "dist/index.js",
|
||||||
@@ -29,7 +29,8 @@
|
|||||||
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
"clean": "rimraf dist tsconfig.tsbuildinfo",
|
||||||
"build": "tsup",
|
"build": "tsup",
|
||||||
"build:watch": "tsup --watch",
|
"build:watch": "tsup --watch",
|
||||||
"type-check": "tsc --noEmit"
|
"type-check": "tsc --noEmit",
|
||||||
|
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
|
||||||
},
|
},
|
||||||
"author": "yhh",
|
"author": "yhh",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -181,12 +181,73 @@ export class BehaviorTreeBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加执行动作
|
* 添加执行动作(通过黑板函数)
|
||||||
|
*
|
||||||
|
* @zh 使用黑板中的 action_{actionName} 函数执行动作
|
||||||
|
* @en Execute action using action_{actionName} function from blackboard
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* BehaviorTreeBuilder.create("AI")
|
||||||
|
* .defineBlackboardVariable("action_Attack", (entity) => TaskStatus.Success)
|
||||||
|
* .selector("Root")
|
||||||
|
* .executeAction("Attack")
|
||||||
|
* .end()
|
||||||
|
* .build();
|
||||||
|
* ```
|
||||||
*/
|
*/
|
||||||
executeAction(actionName: string, name?: string): BehaviorTreeBuilder {
|
executeAction(actionName: string, name?: string): BehaviorTreeBuilder {
|
||||||
return this.addActionNode('ExecuteAction', name || 'ExecuteAction', { actionName });
|
return this.addActionNode('ExecuteAction', name || 'ExecuteAction', { actionName });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加自定义动作节点
|
||||||
|
*
|
||||||
|
* @zh 直接使用注册的执行器类型(通过 @NodeExecutorMetadata 装饰器注册的类)
|
||||||
|
* @en Use a registered executor type directly (class registered via @NodeExecutorMetadata decorator)
|
||||||
|
*
|
||||||
|
* @param implementationType - 执行器类型名称(@NodeExecutorMetadata 中的 implementationType)
|
||||||
|
* @param name - 节点显示名称
|
||||||
|
* @param config - 节点配置参数
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* ```typescript
|
||||||
|
* // 1. 定义自定义执行器
|
||||||
|
* @NodeExecutorMetadata({
|
||||||
|
* implementationType: 'AttackAction',
|
||||||
|
* nodeType: NodeType.Action,
|
||||||
|
* displayName: '攻击动作',
|
||||||
|
* category: 'Action'
|
||||||
|
* })
|
||||||
|
* class AttackAction implements INodeExecutor {
|
||||||
|
* execute(context: NodeExecutionContext): TaskStatus {
|
||||||
|
* console.log("执行攻击!");
|
||||||
|
* return TaskStatus.Success;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* // 2. 在行为树中使用
|
||||||
|
* BehaviorTreeBuilder.create("AI")
|
||||||
|
* .selector("Root")
|
||||||
|
* .action("AttackAction", "Attack")
|
||||||
|
* .end()
|
||||||
|
* .build();
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
action(implementationType: string, name?: string, config?: Record<string, any>): BehaviorTreeBuilder {
|
||||||
|
return this.addActionNode(implementationType, name || implementationType, config || {});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加自定义条件节点
|
||||||
|
*
|
||||||
|
* @zh 直接使用注册的条件执行器类型
|
||||||
|
* @en Use a registered condition executor type directly
|
||||||
|
*/
|
||||||
|
condition(implementationType: string, name?: string, config?: Record<string, any>): BehaviorTreeBuilder {
|
||||||
|
return this.addConditionNode(implementationType, name || implementationType, config || {});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 添加黑板比较条件
|
* 添加黑板比较条件
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ export { BehaviorTreeAssetManager } from './BehaviorTreeAssetManager';
|
|||||||
export type { INodeExecutor, NodeExecutionContext } from './NodeExecutor';
|
export type { INodeExecutor, NodeExecutionContext } from './NodeExecutor';
|
||||||
export { NodeExecutorRegistry, BindingHelper } from './NodeExecutor';
|
export { NodeExecutorRegistry, BindingHelper } from './NodeExecutor';
|
||||||
export { BehaviorTreeExecutionSystem } from './BehaviorTreeExecutionSystem';
|
export { BehaviorTreeExecutionSystem } from './BehaviorTreeExecutionSystem';
|
||||||
export type { NodeMetadata, ConfigFieldDefinition, NodeExecutorMetadata } from './NodeMetadata';
|
export type { NodeMetadata, ConfigFieldDefinition } from './NodeMetadata';
|
||||||
export { NodeMetadataRegistry } from './NodeMetadata';
|
export { NodeMetadataRegistry, NodeExecutorMetadata } from './NodeMetadata';
|
||||||
|
|
||||||
export * from './Executors';
|
export * from './Executors';
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# @esengine/network
|
# @esengine/network
|
||||||
|
|
||||||
|
## 5.0.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`902c0a1`](https://github.com/esengine/esengine/commit/902c0a10749f80bd8f499b44154646379d359704)]:
|
||||||
|
- @esengine/rpc@1.1.3
|
||||||
|
|
||||||
## 5.0.2
|
## 5.0.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@esengine/network",
|
"name": "@esengine/network",
|
||||||
"version": "5.0.2",
|
"version": "5.0.3",
|
||||||
"description": "Network synchronization for multiplayer games",
|
"description": "Network synchronization for multiplayer games",
|
||||||
"esengine": {
|
"esengine": {
|
||||||
"plugin": true,
|
"plugin": true,
|
||||||
|
|||||||
@@ -1,5 +1,49 @@
|
|||||||
# @esengine/rpc
|
# @esengine/rpc
|
||||||
|
|
||||||
|
## 1.1.3
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#404](https://github.com/esengine/esengine/pull/404) [`902c0a1`](https://github.com/esengine/esengine/commit/902c0a10749f80bd8f499b44154646379d359704) Thanks [@esengine](https://github.com/esengine)! - feat(server): add HTTP file-based routing support / 添加 HTTP 文件路由支持
|
||||||
|
|
||||||
|
New feature that allows organizing HTTP routes in separate files, similar to API and message handlers.
|
||||||
|
新功能:支持将 HTTP 路由组织在独立文件中,类似于 API 和消息处理器的文件路由方式。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/http/login.ts
|
||||||
|
import { defineHttp } from '@esengine/server';
|
||||||
|
|
||||||
|
export default defineHttp<{ username: string; password: string }>({
|
||||||
|
method: 'POST',
|
||||||
|
handler(req, res) {
|
||||||
|
const { username, password } = req.body;
|
||||||
|
res.json({ token: '...', userId: '...' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Server configuration / 服务器配置:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const server = await createServer({
|
||||||
|
port: 8080,
|
||||||
|
httpDir: 'src/http', // HTTP routes directory / HTTP 路由目录
|
||||||
|
httpPrefix: '/api', // Route prefix / 路由前缀
|
||||||
|
cors: true
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
File naming convention / 文件命名规则:
|
||||||
|
- `login.ts` → POST /api/login
|
||||||
|
- `users/profile.ts` → POST /api/users/profile
|
||||||
|
- `users/[id].ts` → POST /api/users/:id (dynamic routes / 动态路由)
|
||||||
|
- Set `method: 'GET'` in defineHttp for GET requests / 在 defineHttp 中设置 `method: 'GET'` 以处理 GET 请求
|
||||||
|
|
||||||
|
Also includes / 还包括:
|
||||||
|
- `defineHttp<TBody>()` helper for type-safe route definitions / 类型安全的路由定义辅助函数
|
||||||
|
- Support for merging file routes with inline `http` config / 支持文件路由与内联 `http` 配置合并
|
||||||
|
- RPC server supports attaching to existing HTTP server via `server` option / RPC 服务器支持通过 `server` 选项附加到现有 HTTP 服务器
|
||||||
|
|
||||||
## 1.1.2
|
## 1.1.2
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@esengine/rpc",
|
"name": "@esengine/rpc",
|
||||||
"version": "1.1.2",
|
"version": "1.1.3",
|
||||||
"description": "Elegant type-safe RPC library for ESEngine",
|
"description": "Elegant type-safe RPC library for ESEngine",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
|||||||
@@ -1,5 +1,54 @@
|
|||||||
# @esengine/server
|
# @esengine/server
|
||||||
|
|
||||||
|
## 4.2.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- [#404](https://github.com/esengine/esengine/pull/404) [`902c0a1`](https://github.com/esengine/esengine/commit/902c0a10749f80bd8f499b44154646379d359704) Thanks [@esengine](https://github.com/esengine)! - feat(server): add HTTP file-based routing support / 添加 HTTP 文件路由支持
|
||||||
|
|
||||||
|
New feature that allows organizing HTTP routes in separate files, similar to API and message handlers.
|
||||||
|
新功能:支持将 HTTP 路由组织在独立文件中,类似于 API 和消息处理器的文件路由方式。
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// src/http/login.ts
|
||||||
|
import { defineHttp } from '@esengine/server';
|
||||||
|
|
||||||
|
export default defineHttp<{ username: string; password: string }>({
|
||||||
|
method: 'POST',
|
||||||
|
handler(req, res) {
|
||||||
|
const { username, password } = req.body;
|
||||||
|
res.json({ token: '...', userId: '...' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Server configuration / 服务器配置:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const server = await createServer({
|
||||||
|
port: 8080,
|
||||||
|
httpDir: 'src/http', // HTTP routes directory / HTTP 路由目录
|
||||||
|
httpPrefix: '/api', // Route prefix / 路由前缀
|
||||||
|
cors: true
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
File naming convention / 文件命名规则:
|
||||||
|
- `login.ts` → POST /api/login
|
||||||
|
- `users/profile.ts` → POST /api/users/profile
|
||||||
|
- `users/[id].ts` → POST /api/users/:id (dynamic routes / 动态路由)
|
||||||
|
- Set `method: 'GET'` in defineHttp for GET requests / 在 defineHttp 中设置 `method: 'GET'` 以处理 GET 请求
|
||||||
|
|
||||||
|
Also includes / 还包括:
|
||||||
|
- `defineHttp<TBody>()` helper for type-safe route definitions / 类型安全的路由定义辅助函数
|
||||||
|
- Support for merging file routes with inline `http` config / 支持文件路由与内联 `http` 配置合并
|
||||||
|
- RPC server supports attaching to existing HTTP server via `server` option / RPC 服务器支持通过 `server` 选项附加到现有 HTTP 服务器
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`902c0a1`](https://github.com/esengine/esengine/commit/902c0a10749f80bd8f499b44154646379d359704)]:
|
||||||
|
- @esengine/rpc@1.1.3
|
||||||
|
|
||||||
## 4.1.0
|
## 4.1.0
|
||||||
|
|
||||||
### Minor Changes
|
### Minor Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@esengine/server",
|
"name": "@esengine/server",
|
||||||
"version": "4.1.0",
|
"version": "4.2.0",
|
||||||
"description": "Game server framework for ESEngine with file-based routing",
|
"description": "Game server framework for ESEngine with file-based routing",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
# @esengine/transaction
|
# @esengine/transaction
|
||||||
|
|
||||||
|
## 2.0.7
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- Updated dependencies [[`902c0a1`](https://github.com/esengine/esengine/commit/902c0a10749f80bd8f499b44154646379d359704)]:
|
||||||
|
- @esengine/server@4.2.0
|
||||||
|
|
||||||
## 2.0.6
|
## 2.0.6
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@esengine/transaction",
|
"name": "@esengine/transaction",
|
||||||
"version": "2.0.6",
|
"version": "2.0.7",
|
||||||
"description": "Game transaction system with distributed support | 游戏事务系统,支持分布式事务",
|
"description": "Game transaction system with distributed support | 游戏事务系统,支持分布式事务",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export default defineConfig({
|
|||||||
dts: true,
|
dts: true,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
clean: true,
|
clean: true,
|
||||||
external: ["../pkg/rapier_wasm2d.js"],
|
external: [/\.\.\/pkg\/rapier_wasm2d/],
|
||||||
loader: {
|
loader: {
|
||||||
".wasm": "base64",
|
".wasm": "base64",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user