@lzpenguin/server 1.0.6 → 1.0.8

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 (4) hide show
  1. package/README.md +20 -190
  2. package/index.d.ts +5 -4
  3. package/index.js +24 -14
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -22,7 +22,7 @@ const server = new RiffleServer({
22
22
  // 监听数据更新
23
23
  server.onData((data) => {
24
24
  console.log('World:', data.world);
25
- console.log('Self:', data.self);
25
+ console.log('Self:', data.self); // self 现在直接是公开数据,与 players[i] 结构一致
26
26
  console.log('Players:', data.players);
27
27
  });
28
28
 
@@ -31,86 +31,11 @@ server.init({
31
31
  hash: 'game-version-hash-123',
32
32
  world: { score: 0, level: 1 },
33
33
  self: {
34
- public: { name: 'Player1' },
35
- private: { health: 100 }
34
+ public: { name: 'Player1', x: 100, y: 100 }
36
35
  }
37
36
  });
38
37
  ```
39
38
 
40
- ## 新特性 🎉
41
-
42
- ### 同步优化(v2.0+)
43
-
44
- 我们对同步机制进行了全面优化,提供更可靠和高效的数据同步:
45
-
46
- #### 1. **时间戳和序列号**
47
- - ✅ 每条消息都包含服务器时间戳和序列号
48
- - ✅ 自动检测消息丢失和延迟警告
49
- - ✅ 确保数据按正确顺序处理
50
- - ✅ 实时显示网络延迟和序列号状态
51
-
52
- ```javascript
53
- server.onData((data) => {
54
- console.log('时间戳:', data.timestamp);
55
- console.log('序列号:', data.sequence);
56
- console.log('数据:', data.world);
57
- });
58
- ```
59
-
60
- #### 2. **操作确认机制**
61
- - 支持回调确认每个更新操作
62
- - 自动超时检测(5秒)
63
- - 返回唯一操作ID用于追踪
64
-
65
- ```javascript
66
- server.update({
67
- world: { score: 100 }
68
- }, (error, result) => {
69
- if (error) {
70
- console.error('更新失败:', error);
71
- } else {
72
- console.log('更新已确认:', result);
73
- }
74
- });
75
- ```
76
-
77
- #### 3. **增量更新**
78
- - 只发送变化的数据,节省带宽
79
- - 支持数组追加操作
80
- - 特别适合笔画等增量数据
81
-
82
- ```javascript
83
- server.updateDelta({
84
- world: {
85
- strokes: {
86
- $append: [newStroke] // 只追加新笔画
87
- }
88
- }
89
- }, (error, result) => {
90
- console.log('增量更新完成');
91
- });
92
- ```
93
-
94
- #### 4. **自适应推送频率**
95
- - 服务器根据活动情况动态调整推送频率
96
- - 高活动:50ms 推送一次
97
- - 中活动:100ms 推送一次
98
- - 低活动:200ms 推送一次
99
- - 无活动:500ms 推送一次
100
-
101
- #### 5. **统计信息**
102
- - 实时查看连接状态和同步统计
103
- - 监控消息丢失和延迟
104
-
105
- ```javascript
106
- const stats = server.getStats();
107
- console.log('连接状态:', stats.connected);
108
- console.log('本地序列号:', stats.localSequence);
109
- console.log('最后接收序列号:', stats.lastReceivedSequence);
110
- console.log('待确认操作数:', stats.pendingOperations);
111
- console.log('更新次数:', stats.updateCount);
112
- ```
113
-
114
39
  ## API
115
40
 
116
41
  ### 构造函数
@@ -136,8 +61,7 @@ server.init({
136
61
  hash: 'game-version-hash-123', // 必需:游戏版本哈希值
137
62
  world: { score: 0, level: 1 }, // 可选:世界初始数据
138
63
  self: {
139
- public: { name: 'Player1' }, // 可选:公开数据
140
- private: { health: 100 } // 可选:私有数据
64
+ public: { name: 'Player1', x: 100, y: 100 } // 可选:公开数据
141
65
  }
142
66
  });
143
67
  ```
@@ -146,16 +70,15 @@ server.init({
146
70
  ```json
147
71
  {
148
72
  "world": { "score": 0, "level": 1 },
149
- "self": {
150
- "public": { "name": "Player1" },
151
- "private": { "health": 100 }
152
- },
73
+ "self": { "name": "Player1", "x": 100, "y": 100 },
153
74
  "players": [
154
- { "name": "Player2", "position": { "x": 10, "y": 20 } }
75
+ { "name": "Player2", "x": 10, "y": 20 }
155
76
  ]
156
77
  }
157
78
  ```
158
79
 
80
+ **注意:** `self` 和 `players[i]` 现在具有相同的结构,都只包含公开数据。
81
+
159
82
  **关于 hash:**
160
83
  - **hash 相同**:传入的值不生效,直接返回现有数据
161
84
  - **hash 不同**:删除旧服务器并重新创建,使用传入的值初始化数据
@@ -168,50 +91,29 @@ server.init({
168
91
  部分更新数据(合并到现有数据,不替换)。
169
92
 
170
93
  ```javascript
171
- // 基本更新(不带确认)
94
+ // 更新世界数据
172
95
  server.update({ world: { score: 200 } });
173
96
 
174
- // 带确认回调的更新(推荐)
175
- server.update({
176
- world: { score: 200 }
177
- }, (error, result) => {
178
- if (error) {
179
- console.error('更新失败:', error);
180
- } else {
181
- console.log('更新已确认');
182
- }
183
- });
184
-
185
97
  // 更新玩家数据
186
98
  server.update({
187
99
  self: {
188
- public: { position: { x: 15, y: 25 } },
189
- private: { health: 90 }
100
+ public: { x: 15, y: 25, rotation: 90 }
190
101
  }
191
102
  });
192
103
 
193
104
  // 同时更新世界和玩家数据
194
105
  server.update({
195
106
  world: { score: 200 },
196
- self: { public: { position: { x: 15, y: 25 } } }
107
+ self: { public: { x: 15, y: 25 } }
197
108
  });
198
109
  ```
199
110
 
200
- **参数:**
201
- - `updateData`: 要更新的数据对象
202
- - `callback` (可选): 确认回调函数 `(error, result) => {}`
203
-
204
- **返回值:** 操作ID(字符串),可用于追踪操作
205
-
206
111
  **响应数据(通过 onData 接收):**
207
112
  ```json
208
113
  {
209
114
  "world": { "score": 200, "level": 1 },
210
- "self": {
211
- "public": { "name": "Player1", "position": { "x": 15, "y": 25 } },
212
- "private": { "health": 90, "mana": 50 }
213
- },
214
- "players": [{ "name": "Player2", "position": { "x": 10, "y": 20 } }]
115
+ "self": { "name": "Player1", "x": 15, "y": 25, "rotation": 90 },
116
+ "players": [{ "name": "Player2", "x": 10, "y": 20 }]
215
117
  }
216
118
  ```
217
119
 
@@ -235,87 +137,16 @@ unsubscribe();
235
137
  **数据格式:**
236
138
  ```json
237
139
  {
238
- "timestamp": 1705123456789,
239
- "sequence": 42,
240
140
  "world": { "score": 200, "level": 1 },
241
- "self": {
242
- "public": { "name": "Player1", "position": { "x": 15, y: 25 } },
243
- "private": { "health": 90, "mana": 50 }
244
- },
141
+ "self": { "name": "Player1", "x": 15, "y": 25 },
245
142
  "players": [
246
- { "name": "Player2", "position": { "x": 10, "y": 20 } },
247
- { "name": "Player3", "position": { "x": 30, "y": 40 } }
143
+ { "name": "Player2", "x": 10, "y": 20 },
144
+ { "name": "Player3", "x": 30, "y": 40 }
248
145
  ]
249
146
  }
250
147
  ```
251
148
 
252
- **字段说明:**
253
- - `timestamp`: 服务器时间戳(毫秒)
254
- - `sequence`: 消息序列号(用于检测消息丢失)
255
- - `world`: 世界数据
256
- - `self`: 当前玩家数据
257
- - `players`: 其他玩家数据
258
-
259
- ### 4. updateDelta() - 增量更新 ✨
260
-
261
- 只发送变化的数据,适合频繁更新的场景(如画板笔画)。
262
-
263
- ```javascript
264
- // 追加新笔画(不发送整个数组)
265
- const newStroke = {
266
- id: 'stroke_123',
267
- points: [{ x: 0, y: 0 }, { x: 10, y: 10 }],
268
- color: '#FF0000',
269
- width: 2
270
- };
271
-
272
- server.updateDelta({
273
- world: {
274
- strokes: {
275
- $append: [newStroke] // 使用 $append 标记表示追加
276
- }
277
- }
278
- }, (error, result) => {
279
- if (!error) {
280
- console.log('笔画已添加');
281
- }
282
- });
283
- ```
284
-
285
- **参数:**
286
- - `delta`: 增量数据对象(支持 `$append` 等特殊操作)
287
- - `callback` (可选): 确认回调函数
288
-
289
- **返回值:** 操作ID
290
-
291
- ### 5. getStats() - 获取统计信息 ✨
292
-
293
- 获取实时同步统计信息,用于监控和调试。
294
-
295
- ```javascript
296
- const stats = server.getStats();
297
- console.log(stats);
298
- // {
299
- // connected: true,
300
- // initialized: true,
301
- // localSequence: 10,
302
- // lastReceivedSequence: 8,
303
- // lastReceivedTimestamp: 1705123456789,
304
- // pendingOperations: 2,
305
- // updateCount: 10,
306
- // lastUpdateTime: 1705123456789
307
- // }
308
- ```
309
-
310
- **返回值:**
311
- - `connected`: 是否已连接
312
- - `initialized`: 是否已初始化
313
- - `localSequence`: 本地发送的序列号
314
- - `lastReceivedSequence`: 最后接收的序列号
315
- - `lastReceivedTimestamp`: 最后接收的时间戳
316
- - `pendingOperations`: 待确认的操作数量
317
- - `updateCount`: 总更新次数
318
- - `lastUpdateTime`: 最后更新时间
149
+ **注意:** `self` 和 `players[i]` 具有相同的数据结构,都只包含公开数据。
319
150
 
320
151
  **推送时机:** init 响应、定时推送(每 0.2 秒)、init/update 后立即推送
321
152
 
@@ -334,8 +165,8 @@ const server = new RiffleServer({
334
165
 
335
166
  // 监听服务器推送,更新游戏状态
336
167
  server.onData((data) => {
337
- // 更新自己的位置
338
- const myPosition = data.self?.public?.position;
168
+ // 更新自己的位置(self 现在直接是公开数据对象)
169
+ const myPosition = { x: data.self.x, y: data.self.y };
339
170
 
340
171
  // 更新其他玩家列表
341
172
  const otherPlayers = data.players || [];
@@ -354,8 +185,7 @@ server.init({
354
185
  hash: 'v1.0.0',
355
186
  world: { score: 0, level: 1 },
356
187
  self: {
357
- public: { name: 'Player1', position: { x: 0, y: 0 } },
358
- private: { health: 100 }
188
+ public: { name: 'Player1', x: 0, y: 0 }
359
189
  }
360
190
  });
361
191
 
@@ -363,7 +193,7 @@ server.init({
363
193
  function movePlayer(x, y) {
364
194
  server.update({
365
195
  self: {
366
- public: { position: { x, y } }
196
+ public: { x, y }
367
197
  }
368
198
  });
369
199
  }
package/index.d.ts CHANGED
@@ -19,12 +19,13 @@ export interface RiffleServerOptions {
19
19
  }
20
20
 
21
21
  /**
22
- * 玩家数据
22
+ * 玩家数据(用于发送 init/update 请求)
23
+ * 注意:此格式仅用于客户端发送数据,服务端返回的 self 已不再使用此结构
23
24
  */
24
25
  export interface PlayerSelfData {
25
26
  /** 公开数据 */
26
27
  public?: Record<string, any>;
27
- /** 私有数据 */
28
+ /** 私有数据(已弃用,服务端不再使用) */
28
29
  private?: Record<string, any>;
29
30
  }
30
31
 
@@ -56,8 +57,8 @@ export interface UpdateData {
56
57
  export interface ServerData {
57
58
  /** 世界数据 */
58
59
  world: Record<string, any>;
59
- /** 当前玩家数据 */
60
- self: PlayerSelfData;
60
+ /** 当前玩家数据(仅公开数据,与 players[i] 结构一致) */
61
+ self: Record<string, any>;
61
62
  /** 其他玩家列表(仅公开数据) */
62
63
  players: Array<Record<string, any>>;
63
64
  }
package/index.js CHANGED
@@ -44,7 +44,7 @@ if (typeof window !== 'undefined' && window.WebSocket) {
44
44
  * // 监听服务器推送的最新数据
45
45
  * server.onData((data) => {
46
46
  * console.log('World:', data.world);
47
- * console.log('Self:', data.self);
47
+ * console.log('Self:', data.self); // self 现在直接是公开数据,与 players[i] 结构一致
48
48
  * console.log('Players:', data.players);
49
49
  * });
50
50
  *
@@ -53,8 +53,7 @@ if (typeof window !== 'undefined' && window.WebSocket) {
53
53
  * hash: 'game-version-hash-123', // 游戏版本哈希值
54
54
  * world: { score: 0, level: 1 }, // 世界初始数据(可选)
55
55
  * self: {
56
- * public: { name: 'Player1' }, // 公开数据(可选)
57
- * private: { health: 100 } // 私有数据(可选)
56
+ * public: { name: 'Player1', x: 100, y: 100 } // 公开数据(可选)
58
57
  * }
59
58
  * });
60
59
  *
@@ -62,8 +61,7 @@ if (typeof window !== 'undefined' && window.WebSocket) {
62
61
  * server.update({
63
62
  * world: { score: 200 },
64
63
  * self: {
65
- * public: { position: { x: 15, y: 25 } },
66
- * private: { health: 90 }
64
+ * public: { x: 15, y: 25, rotation: 90 }
67
65
  * }
68
66
  * });
69
67
  * ```
@@ -269,15 +267,25 @@ export class RiffleServer {
269
267
  * @param {string} initData.hash - 游戏版本哈希值(必需)
270
268
  * @param {Object} [initData.world] - 世界初始数据(可选)
271
269
  * @param {Object} [initData.self] - 玩家初始数据(可选)
272
- * @param {Object} [initData.self.public] - 公开数据(可选)
273
- * @param {Object} [initData.self.private] - 私有数据(可选)
270
+ * @param {Object} [initData.self.public] - 公开数据(可选,旧格式)
271
+ * @param {Object} [initData.self.private] - 私有数据(已弃用)
274
272
  * @example
273
+ * // 推荐:直接传递公开数据
275
274
  * server.init({
276
275
  * hash: 'game-version-hash-123',
277
276
  * world: { score: 0, level: 1 },
278
- * self: {
279
- * public: { name: 'Player1' },
280
- * private: { health: 100 }
277
+ * self: {
278
+ * public: { name: 'Player1', x: 100, y: 100 }
279
+ * }
280
+ * });
281
+ *
282
+ * @example
283
+ * // 也支持直接传递对象(服务端会将其作为 public 数据处理)
284
+ * server.init({
285
+ * hash: 'game-version-hash-123',
286
+ * world: { score: 0 },
287
+ * self: {
288
+ * public: { name: 'Player1' }
281
289
  * }
282
290
  * });
283
291
  */
@@ -322,13 +330,12 @@ export class RiffleServer {
322
330
  * @param {Object} [updateData.world] - 世界数据(可选)
323
331
  * @param {Object} [updateData.self] - 玩家数据(可选)
324
332
  * @param {Object} [updateData.self.public] - 公开数据(可选)
325
- * @param {Object} [updateData.self.private] - 私有数据(可选)
333
+ * @param {Object} [updateData.self.private] - 私有数据(已弃用)
326
334
  * @example
327
335
  * server.update({
328
336
  * world: { score: 200 },
329
337
  * self: {
330
- * public: { position: { x: 15, y: 25 } },
331
- * private: { health: 90 }
338
+ * public: { x: 15, y: 25, rotation: 90 }
332
339
  * }
333
340
  * });
334
341
  */
@@ -343,8 +350,11 @@ export class RiffleServer {
343
350
  * @example
344
351
  * const unsubscribe = server.onData((data) => {
345
352
  * console.log('World:', data.world);
346
- * console.log('Self:', data.self);
353
+ * console.log('Self:', data.self); // self 现在直接是公开数据对象,与 players[i] 结构一致
347
354
  * console.log('Players:', data.players);
355
+ *
356
+ * // 例如:data.self = { id: 'abc123', name: 'Player1', x: 100, y: 200 }
357
+ * // 而 data.players[0] 也是相同结构:{ id: 'def456', name: 'Player2', x: 150, y: 250 }
348
358
  * });
349
359
  *
350
360
  * // 取消监听
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lzpenguin/server",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Riffle 游戏服务器 WebSocket 客户端 SDK",
5
5
  "license": "ISC",
6
6
  "author": "lzpenguin",