ygopro-msg-encode 1.0.1

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 (178) hide show
  1. package/.eslintignore +4 -0
  2. package/.eslintrc.js +25 -0
  3. package/.prettierrc +4 -0
  4. package/AGENTS.md +12 -0
  5. package/CHANGES.md +270 -0
  6. package/CTOS_STOC_IMPLEMENTATION.md +279 -0
  7. package/FINAL_SUMMARY.md +357 -0
  8. package/FULL_PAYLOAD_SUMMARY.md +491 -0
  9. package/FULL_PAYLOAD_UPDATE.md +598 -0
  10. package/IMPLEMENTATION_SUMMARY.md +294 -0
  11. package/LICENSE +22 -0
  12. package/MSG_IMPLEMENTATION_SUMMARY.md +358 -0
  13. package/OPPONENT_VIEW_SUMMARY.md +387 -0
  14. package/PROJECT_COMPLETE.md +565 -0
  15. package/QUICK_REFERENCE.md +352 -0
  16. package/README.md +494 -0
  17. package/REAL_IP_STRING_UPDATE.md +289 -0
  18. package/TESTS_MIGRATION.md +342 -0
  19. package/VARIABLE_LENGTH_STRINGS.md +224 -0
  20. package/VARIABLE_LENGTH_UPDATE.md +229 -0
  21. package/dist/index.cjs +5131 -0
  22. package/dist/index.cjs.map +7 -0
  23. package/dist/index.d.ts +6 -0
  24. package/dist/index.mjs +5185 -0
  25. package/dist/index.mjs.map +7 -0
  26. package/dist/src/binary/binary-meta.d.ts +18 -0
  27. package/dist/src/binary/fill-binary-fields.d.ts +2 -0
  28. package/dist/src/metadata.d.ts +10 -0
  29. package/dist/src/proto-base/payload-base.d.ts +8 -0
  30. package/dist/src/proto-base/registry-base.d.ts +13 -0
  31. package/dist/src/protos/common/host-info.d.ts +12 -0
  32. package/dist/src/protos/common/index.d.ts +1 -0
  33. package/dist/src/protos/ctos/base.d.ts +17 -0
  34. package/dist/src/protos/ctos/index.d.ts +3 -0
  35. package/dist/src/protos/ctos/proto/chat.d.ts +9 -0
  36. package/dist/src/protos/ctos/proto/create-game.d.ts +8 -0
  37. package/dist/src/protos/ctos/proto/external-address.d.ts +12 -0
  38. package/dist/src/protos/ctos/proto/hand-result.d.ts +5 -0
  39. package/dist/src/protos/ctos/proto/hs-notready.d.ts +4 -0
  40. package/dist/src/protos/ctos/proto/hs-ready.d.ts +4 -0
  41. package/dist/src/protos/ctos/proto/hs-start.d.ts +4 -0
  42. package/dist/src/protos/ctos/proto/hs-toduelist.d.ts +4 -0
  43. package/dist/src/protos/ctos/proto/hs-toobserver.d.ts +4 -0
  44. package/dist/src/protos/ctos/proto/index.d.ts +19 -0
  45. package/dist/src/protos/ctos/proto/join-game.d.ts +7 -0
  46. package/dist/src/protos/ctos/proto/kick.d.ts +5 -0
  47. package/dist/src/protos/ctos/proto/leave-game.d.ts +4 -0
  48. package/dist/src/protos/ctos/proto/player-info.d.ts +5 -0
  49. package/dist/src/protos/ctos/proto/request-field.d.ts +4 -0
  50. package/dist/src/protos/ctos/proto/response.d.ts +7 -0
  51. package/dist/src/protos/ctos/proto/surrender.d.ts +4 -0
  52. package/dist/src/protos/ctos/proto/time-confirm.d.ts +4 -0
  53. package/dist/src/protos/ctos/proto/tp-result.d.ts +5 -0
  54. package/dist/src/protos/ctos/proto/update-deck.d.ts +11 -0
  55. package/dist/src/protos/ctos/registry.d.ts +3 -0
  56. package/dist/src/protos/msg/base.d.ts +9 -0
  57. package/dist/src/protos/msg/index.d.ts +3 -0
  58. package/dist/src/protos/msg/proto/add-counter.d.ts +9 -0
  59. package/dist/src/protos/msg/proto/announce-attrib.d.ts +7 -0
  60. package/dist/src/protos/msg/proto/announce-card.d.ts +7 -0
  61. package/dist/src/protos/msg/proto/announce-number.d.ts +7 -0
  62. package/dist/src/protos/msg/proto/announce-race.d.ts +7 -0
  63. package/dist/src/protos/msg/proto/attack-disabled.d.ts +4 -0
  64. package/dist/src/protos/msg/proto/attack.d.ts +12 -0
  65. package/dist/src/protos/msg/proto/battle.d.ts +18 -0
  66. package/dist/src/protos/msg/proto/become-target.d.ts +6 -0
  67. package/dist/src/protos/msg/proto/cancel-target.d.ts +11 -0
  68. package/dist/src/protos/msg/proto/card-hint.d.ts +10 -0
  69. package/dist/src/protos/msg/proto/card-query.d.ts +38 -0
  70. package/dist/src/protos/msg/proto/card-target.d.ts +11 -0
  71. package/dist/src/protos/msg/proto/chain-disabled.d.ts +5 -0
  72. package/dist/src/protos/msg/proto/chain-end.d.ts +4 -0
  73. package/dist/src/protos/msg/proto/chain-negated.d.ts +5 -0
  74. package/dist/src/protos/msg/proto/chain-solved.d.ts +5 -0
  75. package/dist/src/protos/msg/proto/chain-solving.d.ts +5 -0
  76. package/dist/src/protos/msg/proto/chained.d.ts +5 -0
  77. package/dist/src/protos/msg/proto/chaining.d.ts +12 -0
  78. package/dist/src/protos/msg/proto/confirm-cards.d.ts +16 -0
  79. package/dist/src/protos/msg/proto/confirm-decktop.d.ts +14 -0
  80. package/dist/src/protos/msg/proto/confirm-extratop.d.ts +14 -0
  81. package/dist/src/protos/msg/proto/damage-step-end.d.ts +4 -0
  82. package/dist/src/protos/msg/proto/damage-step-start.d.ts +4 -0
  83. package/dist/src/protos/msg/proto/damage.d.ts +6 -0
  84. package/dist/src/protos/msg/proto/deck-top.d.ts +8 -0
  85. package/dist/src/protos/msg/proto/draw.d.ts +8 -0
  86. package/dist/src/protos/msg/proto/equip.d.ts +12 -0
  87. package/dist/src/protos/msg/proto/field-disabled.d.ts +5 -0
  88. package/dist/src/protos/msg/proto/flipsummoned.d.ts +4 -0
  89. package/dist/src/protos/msg/proto/flipsummoning.d.ts +9 -0
  90. package/dist/src/protos/msg/proto/hand-res.d.ts +5 -0
  91. package/dist/src/protos/msg/proto/hint.d.ts +7 -0
  92. package/dist/src/protos/msg/proto/index.d.ts +85 -0
  93. package/dist/src/protos/msg/proto/lpupdate.d.ts +6 -0
  94. package/dist/src/protos/msg/proto/match-kill.d.ts +5 -0
  95. package/dist/src/protos/msg/proto/missed-effect.d.ts +7 -0
  96. package/dist/src/protos/msg/proto/move.d.ts +14 -0
  97. package/dist/src/protos/msg/proto/new-phase.d.ts +5 -0
  98. package/dist/src/protos/msg/proto/new-turn.d.ts +5 -0
  99. package/dist/src/protos/msg/proto/pay-lpcost.d.ts +6 -0
  100. package/dist/src/protos/msg/proto/player-hint.d.ts +7 -0
  101. package/dist/src/protos/msg/proto/pos-change.d.ts +12 -0
  102. package/dist/src/protos/msg/proto/random-selected.d.ts +7 -0
  103. package/dist/src/protos/msg/proto/recover.d.ts +6 -0
  104. package/dist/src/protos/msg/proto/reload-field.d.ts +36 -0
  105. package/dist/src/protos/msg/proto/remove-counter.d.ts +9 -0
  106. package/dist/src/protos/msg/proto/reset-time.d.ts +6 -0
  107. package/dist/src/protos/msg/proto/retry.d.ts +4 -0
  108. package/dist/src/protos/msg/proto/reverse-deck.d.ts +4 -0
  109. package/dist/src/protos/msg/proto/rock-paper-scissors.d.ts +5 -0
  110. package/dist/src/protos/msg/proto/select-battlecmd.d.ts +25 -0
  111. package/dist/src/protos/msg/proto/select-card.d.ts +17 -0
  112. package/dist/src/protos/msg/proto/select-chain.d.ts +19 -0
  113. package/dist/src/protos/msg/proto/select-counter.d.ts +17 -0
  114. package/dist/src/protos/msg/proto/select-disfield.d.ts +7 -0
  115. package/dist/src/protos/msg/proto/select-effectyn.d.ts +11 -0
  116. package/dist/src/protos/msg/proto/select-idlecmd.d.ts +37 -0
  117. package/dist/src/protos/msg/proto/select-option.d.ts +7 -0
  118. package/dist/src/protos/msg/proto/select-place.d.ts +7 -0
  119. package/dist/src/protos/msg/proto/select-position.d.ts +7 -0
  120. package/dist/src/protos/msg/proto/select-sum.d.ts +20 -0
  121. package/dist/src/protos/msg/proto/select-tribute.d.ts +18 -0
  122. package/dist/src/protos/msg/proto/select-unselect-card.d.ts +20 -0
  123. package/dist/src/protos/msg/proto/select-yesno.d.ts +6 -0
  124. package/dist/src/protos/msg/proto/set.d.ts +5 -0
  125. package/dist/src/protos/msg/proto/shuffle-deck.d.ts +5 -0
  126. package/dist/src/protos/msg/proto/shuffle-extra.d.ts +8 -0
  127. package/dist/src/protos/msg/proto/shuffle-hand.d.ts +8 -0
  128. package/dist/src/protos/msg/proto/shuffle-set-card.d.ts +17 -0
  129. package/dist/src/protos/msg/proto/sort-card.d.ts +13 -0
  130. package/dist/src/protos/msg/proto/spsummoned.d.ts +4 -0
  131. package/dist/src/protos/msg/proto/spsummoning.d.ts +9 -0
  132. package/dist/src/protos/msg/proto/start.d.ts +14 -0
  133. package/dist/src/protos/msg/proto/summoned.d.ts +4 -0
  134. package/dist/src/protos/msg/proto/summoning.d.ts +9 -0
  135. package/dist/src/protos/msg/proto/swap-grave-deck.d.ts +5 -0
  136. package/dist/src/protos/msg/proto/swap.d.ts +12 -0
  137. package/dist/src/protos/msg/proto/tag-swap.d.ts +14 -0
  138. package/dist/src/protos/msg/proto/toss-coin.d.ts +7 -0
  139. package/dist/src/protos/msg/proto/toss-dice.d.ts +7 -0
  140. package/dist/src/protos/msg/proto/update-card.d.ts +14 -0
  141. package/dist/src/protos/msg/proto/update-data.d.ts +12 -0
  142. package/dist/src/protos/msg/proto/waiting.d.ts +4 -0
  143. package/dist/src/protos/msg/proto/win.d.ts +6 -0
  144. package/dist/src/protos/msg/registry.d.ts +3 -0
  145. package/dist/src/protos/stoc/base.d.ts +17 -0
  146. package/dist/src/protos/stoc/index.d.ts +3 -0
  147. package/dist/src/protos/stoc/proto/change-side.d.ts +4 -0
  148. package/dist/src/protos/stoc/proto/chat.d.ts +10 -0
  149. package/dist/src/protos/stoc/proto/create-game.d.ts +5 -0
  150. package/dist/src/protos/stoc/proto/deck-count.d.ts +5 -0
  151. package/dist/src/protos/stoc/proto/duel-end.d.ts +4 -0
  152. package/dist/src/protos/stoc/proto/duel-start.d.ts +4 -0
  153. package/dist/src/protos/stoc/proto/error-msg.d.ts +6 -0
  154. package/dist/src/protos/stoc/proto/field-finish.d.ts +4 -0
  155. package/dist/src/protos/stoc/proto/game-msg.d.ts +9 -0
  156. package/dist/src/protos/stoc/proto/hand-result.d.ts +6 -0
  157. package/dist/src/protos/stoc/proto/hs-player-change.d.ts +5 -0
  158. package/dist/src/protos/stoc/proto/hs-player-enter.d.ts +6 -0
  159. package/dist/src/protos/stoc/proto/hs-watch-change.d.ts +5 -0
  160. package/dist/src/protos/stoc/proto/index.d.ts +24 -0
  161. package/dist/src/protos/stoc/proto/join-game.d.ts +6 -0
  162. package/dist/src/protos/stoc/proto/leave-game.d.ts +5 -0
  163. package/dist/src/protos/stoc/proto/replay.d.ts +11 -0
  164. package/dist/src/protos/stoc/proto/select-hand.d.ts +4 -0
  165. package/dist/src/protos/stoc/proto/select-tp.d.ts +4 -0
  166. package/dist/src/protos/stoc/proto/srvpro-roomlist.d.ts +18 -0
  167. package/dist/src/protos/stoc/proto/teammate-surrender.d.ts +4 -0
  168. package/dist/src/protos/stoc/proto/time-limit.d.ts +6 -0
  169. package/dist/src/protos/stoc/proto/tp-result.d.ts +4 -0
  170. package/dist/src/protos/stoc/proto/type-change.d.ts +5 -0
  171. package/dist/src/protos/stoc/proto/waiting-side.d.ts +4 -0
  172. package/dist/src/protos/stoc/registry.d.ts +3 -0
  173. package/dist/src/vendor/ocgcore-constants.d.ts +360 -0
  174. package/dist/src/vendor/script-constants.d.ts +836 -0
  175. package/index.ts +6 -0
  176. package/package.json +74 -0
  177. package/scripts/gen-constants.js +156 -0
  178. package/tsconfig.json +20 -0
@@ -0,0 +1,352 @@
1
+ # toFullPayload / fromFullPayload 快速参考
2
+
3
+ ## 快速开始 ⚡
4
+
5
+ ```typescript
6
+ import { YGOProCtosChat } from 'ygopro-msg-encode';
7
+
8
+ // 序列化(旧方式 ❌)
9
+ const chat = new YGOProCtosChat();
10
+ chat.msg = "Hello";
11
+ const body = chat.toPayload();
12
+ // 还需要手动添加 header...
13
+
14
+ // 序列化(新方式 ✅)
15
+ const chat = new YGOProCtosChat();
16
+ chat.msg = "Hello";
17
+ const fullPayload = chat.toFullPayload(); // 一行搞定!
18
+
19
+ // 反序列化(新方式 ✅)
20
+ const parsed = new YGOProCtosChat();
21
+ parsed.fromFullPayload(fullPayload);
22
+ console.log(parsed.msg); // "Hello"
23
+ ```
24
+
25
+ ## API 参考
26
+
27
+ ### toFullPayload()
28
+
29
+ 序列化为完整数据包(包含 header)。
30
+
31
+ ```typescript
32
+ toFullPayload(): Uint8Array
33
+ ```
34
+
35
+ **返回**: `[length 2 bytes LE][identifier 1 byte][body]`
36
+
37
+ **示例**:
38
+ ```typescript
39
+ const protocol = new YGOProCtosPlayerInfo();
40
+ protocol.name = [0x41, 0x42, ...];
41
+ const fullPayload = protocol.toFullPayload();
42
+ // fullPayload[0-1]: length (LE)
43
+ // fullPayload[2]: identifier (0x10)
44
+ // fullPayload[3+]: body
45
+ ```
46
+
47
+ ### fromFullPayload(data)
48
+
49
+ 从完整数据包反序列化。
50
+
51
+ ```typescript
52
+ fromFullPayload(data: Uint8Array): this
53
+ ```
54
+
55
+ **参数**:
56
+ - `data`: 完整数据包(包含 header)
57
+
58
+ **返回**: `this`(链式调用)
59
+
60
+ **异常**:
61
+ - 数据太短 → `Error: payload too short`
62
+ - identifier 不匹配 → `Error: identifier mismatch`
63
+
64
+ **示例**:
65
+ ```typescript
66
+ const protocol = new YGOProCtosPlayerInfo();
67
+ try {
68
+ protocol.fromFullPayload(fullPayload);
69
+ console.log(protocol.name);
70
+ } catch (error) {
71
+ console.error('Parse error:', error.message);
72
+ }
73
+ ```
74
+
75
+ ## 常见用例
76
+
77
+ ### 1. 发送消息
78
+
79
+ ```typescript
80
+ const chat = new YGOProCtosChat();
81
+ chat.msg = "GG!";
82
+ socket.send(chat.toFullPayload()); // ✅ 直接发送
83
+ ```
84
+
85
+ ### 2. 接收消息
86
+
87
+ ```typescript
88
+ socket.on('data', (data: Uint8Array) => {
89
+ const chat = new YGOProStocChat();
90
+ try {
91
+ chat.fromFullPayload(data);
92
+ console.log(`[${chat.player_type}] ${chat.msg}`);
93
+ } catch (error) {
94
+ console.error('Invalid packet:', error.message);
95
+ }
96
+ });
97
+ ```
98
+
99
+ ### 3. 往返测试
100
+
101
+ ```typescript
102
+ const original = new YGOProCtosHandResult();
103
+ original.res = 1;
104
+
105
+ const fullPayload = original.toFullPayload();
106
+
107
+ const parsed = new YGOProCtosHandResult();
108
+ parsed.fromFullPayload(fullPayload);
109
+
110
+ expect(parsed.res).toBe(original.res); // ✅ Pass
111
+ ```
112
+
113
+ ### 4. 批量处理
114
+
115
+ ```typescript
116
+ const messages = ["msg1", "msg2", "msg3"];
117
+ const payloads = messages.map(msg => {
118
+ const chat = new YGOProCtosChat();
119
+ chat.msg = msg;
120
+ return chat.toFullPayload();
121
+ });
122
+ ```
123
+
124
+ ## 错误处理
125
+
126
+ ### 数据太短
127
+
128
+ ```typescript
129
+ const shortData = new Uint8Array([1, 0]); // 只有 2 字节
130
+ const protocol = new YGOProCtosChat();
131
+
132
+ try {
133
+ protocol.fromFullPayload(shortData);
134
+ } catch (error) {
135
+ // Error: CTOS payload too short: expected at least 3 bytes, got 2
136
+ }
137
+ ```
138
+
139
+ ### identifier 不匹配
140
+
141
+ ```typescript
142
+ const wrongData = new Uint8Array([5, 0, 0xFF, ...]); // identifier = 0xFF
143
+ const protocol = new YGOProCtosChat(); // 期望 0x16
144
+
145
+ try {
146
+ protocol.fromFullPayload(wrongData);
147
+ } catch (error) {
148
+ // Error: CTOS identifier mismatch: expected 0x16, got 0xff
149
+ }
150
+ ```
151
+
152
+ ### 自动截断
153
+
154
+ ```typescript
155
+ // 声明长度 5,但实际有 100 字节
156
+ const extended = new Uint8Array(100);
157
+ extended[0] = 5; // length
158
+ extended[1] = 0;
159
+ extended[2] = 0x03; // identifier
160
+ // ... body 2 bytes ...
161
+ // ... extra 93 bytes ...
162
+
163
+ const protocol = new YGOProCtosHandResult();
164
+ protocol.fromFullPayload(extended); // ✅ 成功!自动截断
165
+ ```
166
+
167
+ ## 数据包格式
168
+
169
+ ```
170
+ 完整数据包格式:
171
+ ┌────────────────┬──────────────┬─────────────────┐
172
+ │ Byte 0-1 │ Byte 2 │ Byte 3+ │
173
+ ├────────────────┼──────────────┼─────────────────┤
174
+ │ Length (u16) │ Identifier │ Body │
175
+ │ Little Endian │ (u8) │ (Variable) │
176
+ └────────────────┴──────────────┴─────────────────┘
177
+
178
+ Length = 1 (identifier) + body.length
179
+ ```
180
+
181
+ **示例**:
182
+ ```
183
+ 数据: [05 00 16 48 00 65 00 00 00]
184
+ ^^^^^ length = 5
185
+ ^^ identifier = 0x16 (CTOS_CHAT)
186
+ ^^^^^^^^^^^^^ body (5-1=4 bytes)
187
+ ```
188
+
189
+ ## 性能提示
190
+
191
+ ### ✅ 好的做法
192
+
193
+ ```typescript
194
+ // 1. 重用对象
195
+ const protocol = new YGOProCtosChat();
196
+ for (const msg of messages) {
197
+ protocol.msg = msg;
198
+ send(protocol.toFullPayload());
199
+ }
200
+
201
+ // 2. 使用 try-catch
202
+ try {
203
+ protocol.fromFullPayload(data);
204
+ } catch (error) {
205
+ handleError(error);
206
+ }
207
+
208
+ // 3. 验证长度
209
+ if (data.length >= 3) {
210
+ protocol.fromFullPayload(data);
211
+ }
212
+ ```
213
+
214
+ ### ❌ 避免的做法
215
+
216
+ ```typescript
217
+ // 1. 不要每次创建新对象
218
+ for (const msg of messages) {
219
+ const protocol = new YGOProCtosChat(); // ❌ 浪费内存
220
+ protocol.msg = msg;
221
+ send(protocol.toFullPayload());
222
+ }
223
+
224
+ // 2. 不要忽略错误
225
+ protocol.fromFullPayload(data); // ❌ 没有错误处理
226
+
227
+ // 3. 不要混用 API
228
+ const body = protocol.toPayload(); // ❌
229
+ const fullPayload = new Uint8Array(3 + body.length);
230
+ // ... 手动构建 header
231
+ // 应该直接用 toFullPayload()
232
+ ```
233
+
234
+ ## 与 Registry 配合
235
+
236
+ ```typescript
237
+ import { YGOProCtos } from 'ygopro-msg-encode';
238
+
239
+ // 方式 1: Registry 自动识别
240
+ const fullPayload = receivedData;
241
+ const parsed = YGOProCtos.getInstanceFromPayload(fullPayload);
242
+
243
+ if (parsed instanceof YGOProCtosChat) {
244
+ console.log('Chat:', parsed.msg);
245
+ }
246
+
247
+ // 方式 2: 直接解析
248
+ const chat = new YGOProCtosChat();
249
+ chat.fromFullPayload(fullPayload);
250
+ console.log('Chat:', chat.msg);
251
+ ```
252
+
253
+ ## 类型判断
254
+
255
+ ```typescript
256
+ // 检查 identifier
257
+ const identifier = data[2];
258
+ switch (identifier) {
259
+ case 0x16: // CTOS_CHAT
260
+ const chat = new YGOProCtosChat();
261
+ chat.fromFullPayload(data);
262
+ break;
263
+ case 0x10: // CTOS_PLAYER_INFO
264
+ const playerInfo = new YGOProCtosPlayerInfo();
265
+ playerInfo.fromFullPayload(data);
266
+ break;
267
+ }
268
+
269
+ // 或使用 Registry
270
+ const parsed = YGOProCtos.getInstanceFromPayload(data);
271
+ if (parsed) {
272
+ console.log('Parsed:', parsed.constructor.name);
273
+ }
274
+ ```
275
+
276
+ ## 调试技巧
277
+
278
+ ```typescript
279
+ // 1. 查看完整数据包
280
+ const fullPayload = protocol.toFullPayload();
281
+ console.log('Full payload:', Array.from(fullPayload).map(b => b.toString(16)));
282
+
283
+ // 2. 解析 header
284
+ const length = fullPayload[0] | (fullPayload[1] << 8);
285
+ const identifier = fullPayload[2];
286
+ console.log('Length:', length, 'Identifier:', `0x${identifier.toString(16)}`);
287
+
288
+ // 3. 验证往返
289
+ const original = new YGOProCtosChat();
290
+ original.msg = "test";
291
+ const fullPayload = original.toFullPayload();
292
+ const parsed = new YGOProCtosChat();
293
+ parsed.fromFullPayload(fullPayload);
294
+ console.log('Match:', original.msg === parsed.msg);
295
+ ```
296
+
297
+ ## 所有支持的协议
298
+
299
+ ### CTOS (19 个)
300
+ ✅ 所有 CTOS 协议都支持 `toFullPayload()` / `fromFullPayload()`
301
+
302
+ - CTOS_RESPONSE (0x01)
303
+ - CTOS_UPDATE_DECK (0x02)
304
+ - CTOS_HAND_RESULT (0x03)
305
+ - CTOS_TP_RESULT (0x04)
306
+ - CTOS_PLAYER_INFO (0x10)
307
+ - CTOS_CREATE_GAME (0x11)
308
+ - CTOS_JOIN_GAME (0x12)
309
+ - CTOS_LEAVE_GAME (0x13)
310
+ - CTOS_SURRENDER (0x14)
311
+ - CTOS_TIME_CONFIRM (0x15)
312
+ - CTOS_CHAT (0x16)
313
+ - CTOS_EXTERNAL_ADDRESS (0x17)
314
+ - ... 以及其他 CTOS 协议
315
+
316
+ ### STOC (24 个)
317
+ ✅ 所有 STOC 协议都支持 `toFullPayload()` / `fromFullPayload()`
318
+
319
+ - STOC_GAME_MSG (0x01)
320
+ - STOC_ERROR_MSG (0x02)
321
+ - STOC_SELECT_HAND (0x03)
322
+ - STOC_SELECT_TP (0x04)
323
+ - STOC_HAND_RESULT (0x05)
324
+ - STOC_CHAT (0x19)
325
+ - STOC_SRVPRO_ROOMLIST (0x31)
326
+ - ... 以及其他 STOC 协议
327
+
328
+ ## 常见问题 FAQ
329
+
330
+ ### Q: 什么时候用 `toPayload()` vs `toFullPayload()`?
331
+
332
+ **A**:
333
+ - `toPayload()`: 只需要 body(例如与 Registry 配合)
334
+ - `toFullPayload()`: 需要完整数据包(例如直接发送到网络)
335
+
336
+ ### Q: 可以修改 identifier 吗?
337
+
338
+ **A**: 不行,identifier 是类的静态属性,每个协议类都有固定的 identifier。
339
+
340
+ ### Q: 为什么会自动截断数据?
341
+
342
+ **A**: 网络传输可能会附带额外数据(例如多个数据包粘在一起)。`fromFullPayload()` 会根据声明的 length 自动截断,确保只解析当前协议的数据。
343
+
344
+ ### Q: 向后兼容吗?
345
+
346
+ **A**: 是的!100% 向后兼容。原有的 `toPayload()` / `fromPayload()` 方法不受影响。
347
+
348
+ ---
349
+
350
+ **需要更多帮助?** 查看完整文档:
351
+ - `FULL_PAYLOAD_UPDATE.md` - 详细实现文档
352
+ - `CTOS_STOC_IMPLEMENTATION.md` - 协议实现说明