@lzpenguin/server 1.1.10 → 1.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +56 -54
  2. package/index.js +22 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,126 +1,128 @@
1
1
  # @lzpenguin/server
2
2
 
3
- Riffle 游戏服务器 WebSocket 客户端 SDK
3
+ Riffle game server WebSocket client SDK
4
4
 
5
- ## 安装
5
+ ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install @lzpenguin/server
9
9
  ```
10
10
 
11
- ## 快速开始
11
+ ## Quick Start
12
12
 
13
13
  ```javascript
14
14
  import { RiffleServer } from '@lzpenguin/server';
15
15
 
16
- // 创建服务器实例
16
+ // Create a server instance
17
17
  const server = new RiffleServer({
18
- timestamp: 1234567890, // 必需:游戏时间戳(数字类型),直接使用上下文中给出的值
19
- autoReconnect: true, // 可选:自动重连,默认 true
20
- reconnectInterval: 3000 // 可选:重连间隔(毫秒),默认 3000
18
+ timestamp: 1234567890, // Required: game timestamp (number). Use the value provided in the context
19
+ autoReconnect: true, // Optional: auto reconnect, default true
20
+ reconnectInterval: 3000 // Optional: reconnect interval (ms), default 3000
21
21
  });
22
22
 
23
- // 1. 监听数据推送(init 成功后每 0.2 秒自动推送,调用 init/update 后立即推送)
23
+ // 1. Listen to data push (after init succeeds, auto-pushes every 0.2s; pushes immediately after init/update)
24
24
  server.onData((data) => {
25
- console.log('World:', data.world); // 世界数据
26
- console.log('Self:', data.self); // 自己的公开数据(包含 name 字段)
27
- console.log('Players:', data.players); // 其他玩家的公开数据(包含 name 字段)
28
- // 注意:self players[i] 结构相同,都只包含公开数据
25
+ console.log('World:', data.world); // World data
26
+ console.log('Self:', data.self); // Your public data (includes name / avatar / online fields)
27
+ console.log('Players:', data.players); // Other players' public data (includes name / avatar / online fields)
28
+ // Note: self and players[i] have the same structure and contain only public data
29
29
  });
30
30
 
31
- // 2. 初始化服务器(必需,连接后必须先调用)
31
+ // 2. Initialize the server (required, must be called after connecting)
32
32
  server.init({
33
33
  world: { score: 0, level: 1 },
34
34
  self: {
35
35
  public: { x: 100, y: 100 }
36
- // name 字段不需要设置,服务器返回数据会包含
36
+ // The name field does not need to be set; it is included in the server response
37
37
  }
38
38
  });
39
39
 
40
- // 3. 更新数据(部分更新,合并到现有数据)
40
+ // 3. Update data (partial update, merged into existing data)
41
41
  server.update({
42
42
  world: { score: 200 },
43
43
  self: { public: { x: 150, y: 150 } }
44
44
  });
45
45
  ```
46
46
 
47
- ## 数据格式
47
+ ## Data Format
48
48
 
49
- 服务器推送的数据格式(通过 `onData` 接收):
49
+ Data format pushed by the server (received via `onData`):
50
50
 
51
51
  ```json
52
52
  {
53
53
  "world": { "score": 0, "level": 1 },
54
- "self": { "name": "Player1", "x": 100, "y": 100 },
54
+ "self": { "name": "Player1", "avatar": "https://...", "online": true, "x": 100, "y": 100 },
55
55
  "players": [
56
- { "name": "Player2", "x": 10, "y": 20 },
57
- { "name": "Player3", "x": 30, "y": 40 }
56
+ { "name": "Player2", "avatar": "https://...", "online": true, "x": 10, "y": 20 },
57
+ { "name": "Player3", "avatar": "https://...", "online": false, "x": 30, "y": 40 }
58
58
  ]
59
59
  }
60
60
  ```
61
61
 
62
- **关于 name 字段:**
63
- - `self.name` `players[i].name` 字段**一定会存在**,包含用户的昵称或用户名
64
- - 你不需要在 `init()` `update()` 时设置 name 字段,服务器会直接返回
62
+ **About the name / avatar / online fields:**
63
+ - `self.name` and `players[i].name` **always exist** and contain the user's nickname or username
64
+ - `self.avatar` and `players[i].avatar` are overridden by the server based on the user's avatar
65
+ - `self.online` and `players[i].online` are stored in player data and are set to true when `/api/v1/server/ws` connects, and false when it disconnects
66
+ - You do not need to set name / avatar / online in `init()` or `update()`; the server returns them directly
65
67
 
66
- ## API 说明
68
+ ## API Reference
67
69
 
68
- ### init(data) - 初始化服务器
70
+ ### init(data) - Initialize Server
69
71
 
70
- 必需,连接后必须先调用。根据 timestamp 判断是否重新初始化。
72
+ Required. Must be called after connecting. Uses timestamp to determine whether to re-initialize.
71
73
 
72
74
  ```javascript
73
75
  server.init({
74
- world: { score: 0, level: 1 }, // 可选:世界初始数据
76
+ world: { score: 0, level: 1 }, // Optional: initial world data
75
77
  self: {
76
- public: { x: 100, y: 100 } // 可选:玩家公开数据
77
- // 注意:name 字段不需要设置,服务器返回的数据会包含该字段
78
+ public: { x: 100, y: 100 } // Optional: player public data
79
+ // Note: the name field does not need to be set; it is included in the server response
78
80
  }
79
81
  });
80
82
  ```
81
83
 
82
- ### update(data) - 更新数据
84
+ ### update(data) - Update Data
83
85
 
84
- 部分更新数据(合并,不替换)。只更新提供的字段,未提供的字段保持不变。
86
+ Partially updates data (merged, not replaced). Only provided fields are updated; missing fields remain unchanged.
85
87
 
86
88
  ```javascript
87
- // 更新世界数据
89
+ // Update world data
88
90
  server.update({ world: { score: 200 } });
89
91
 
90
- // 更新玩家数据
92
+ // Update player data
91
93
  server.update({ self: { public: { x: 15, y: 25 } } });
92
94
 
93
- // 同时更新
95
+ // Update both
94
96
  server.update({
95
97
  world: { score: 200 },
96
98
  self: { public: { x: 15, y: 25 } }
97
99
  });
98
100
  ```
99
101
 
100
- ### onData(callback) - 监听数据推送
102
+ ### onData(callback) - Listen to Data Pushes
101
103
 
102
- 监听服务器推送的数据。返回取消监听函数。
104
+ Listens to data pushed by the server. Returns an unsubscribe function.
103
105
 
104
106
  ```javascript
105
107
  const unsubscribe = server.onData((data) => {
106
- // 处理数据
108
+ // Handle data
107
109
  });
108
110
 
109
- // 取消监听
111
+ // Unsubscribe
110
112
  unsubscribe();
111
113
  ```
112
114
 
113
- **推送时机:** init 成功后每 0.2 秒自动推送,调用 init/update 后立即推送
115
+ **Push timing:** after init succeeds, auto-pushes every 0.2s; pushes immediately after init/update
114
116
 
115
- ## 关于 timestamp
117
+ ## About timestamp
116
118
 
117
- - **类型要求**:必须是数字类型(number/int),不能是字符串
118
- - **如何获取**:直接使用上下文中给出的 timestamp
119
- - **较小或相等**:不生效,返回现有数据
120
- - **较大**:删除旧服务器并重新创建
121
- - **何时更新**:改动角色或世界字段设计(新增/删除/改变类型)时,需使用更大的 timestamp 重新初始化
119
+ - **Type requirement**: must be a number (number/int), not a string
120
+ - **How to get it**: use the timestamp value provided in the context directly
121
+ - **Smaller or equal**: no effect; returns existing data
122
+ - **Larger**: deletes the old server and recreates it
123
+ - **When to update**: when changing character or world field design (add/remove/change type), use a larger timestamp to re-initialize
122
124
 
123
- ## 完整示例
125
+ ## Complete Example
124
126
 
125
127
  ```javascript
126
128
  import { RiffleServer } from '@lzpenguin/server';
@@ -129,33 +131,33 @@ const server = new RiffleServer({
129
131
  timestamp: 1234567890
130
132
  });
131
133
 
132
- // 监听推送
134
+ // Listen to pushes
133
135
  server.onData((data) => {
134
- // data.self.name data.players[i].name 一定会存在
135
- console.log('我的名字:', data.self.name);
136
+ // data.self.name and data.players[i].name always exist
137
+ console.log('My name:', data.self.name);
136
138
 
137
139
  const myPosition = { x: data.self.x, y: data.self.y };
138
140
  const otherPlayers = data.players || [];
139
141
  renderPlayers(myPosition, otherPlayers);
140
142
 
141
143
  if (data.world?.gameOver) {
142
- console.log('游戏结束!分数:', data.world.score);
144
+ console.log('Game over! Score:', data.world.score);
143
145
  }
144
146
  });
145
147
 
146
- // 初始化
148
+ // Initialize
147
149
  server.init({
148
150
  world: { score: 0, level: 1 },
149
151
  self: { public: { x: 0, y: 0 } }
150
- // name 字段不需要设置,返回的数据会包含
152
+ // The name field does not need to be set; it is included in the response
151
153
  });
152
154
 
153
- // 更新玩家位置
155
+ // Update player position
154
156
  function movePlayer(x, y) {
155
157
  server.update({ self: { public: { x, y } } });
156
158
  }
157
159
 
158
- // 更新分数
160
+ // Update score
159
161
  function updateScore(score) {
160
162
  server.update({ world: { score } });
161
163
  }
package/index.js CHANGED
@@ -204,6 +204,28 @@ export class RiffleServer {
204
204
 
205
205
  // 检查是否是数据消息(包含 world、self、players 字段)
206
206
  if (message.world !== undefined && message.self !== undefined && message.players !== undefined) {
207
+ if (message.self && typeof message.self === 'object') {
208
+ if (message.self.online === undefined) {
209
+ message.self.online = false;
210
+ }
211
+ if (message.self.avatar === undefined) {
212
+ message.self.avatar = '';
213
+ }
214
+ }
215
+ if (Array.isArray(message.players)) {
216
+ message.players = message.players.map((player) => {
217
+ if (player && typeof player === 'object') {
218
+ if (player.online === undefined) {
219
+ player.online = false;
220
+ }
221
+ if (player.avatar === undefined) {
222
+ player.avatar = '';
223
+ }
224
+ }
225
+ return player;
226
+ });
227
+ }
228
+
207
229
  // 如果还未初始化,这可能是 init 响应
208
230
  if (!this.isInitialized && message.self) {
209
231
  this.isInitialized = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lzpenguin/server",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "Riffle 游戏服务器 WebSocket 客户端 SDK",
5
5
  "license": "ISC",
6
6
  "author": "lzpenguin",