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
package/README.md ADDED
@@ -0,0 +1,494 @@
1
+ # ygopro-msg-encode
2
+
3
+ [![npm version](https://img.shields.io/npm/v/ygopro-msg-encode.svg)](https://www.npmjs.com/package/ygopro-msg-encode)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A TypeScript library for encoding and decoding YGOPro network protocols.
7
+
8
+ ## Features
9
+
10
+ - 🎯 **Complete Protocol Support**: Implements all YGOPro network protocols (MSG, CTOS, STOC)
11
+ - 🔒 **Type-Safe**: Full TypeScript support with detailed type definitions
12
+ - ⚡ **High Performance**: Efficient binary serialization/deserialization
13
+ - 🎨 **Modern API**: Clean and intuitive API design with `toFullPayload()` / `fromFullPayload()`
14
+ - 📦 **Zero Config**: Works out of the box with sensible defaults
15
+ - 🧪 **Well Tested**: 100+ unit tests with comprehensive coverage
16
+ - 🌍 **Universal**: Supports both CommonJS and ES Modules
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install ygopro-msg-encode
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### CTOS (Client to Server) Protocols
27
+
28
+ ```typescript
29
+ import { YGOProCtosChat, YGOProCtos } from 'ygopro-msg-encode';
30
+
31
+ // Serialize a chat message
32
+ const chat = new YGOProCtosChat();
33
+ chat.msg = "Hello, YGOPro!";
34
+ const payload = chat.toFullPayload();
35
+
36
+ // Send to server
37
+ socket.send(payload);
38
+
39
+ // Deserialize received data
40
+ const received = new YGOProCtosChat();
41
+ received.fromFullPayload(payload);
42
+ console.log(received.msg); // "Hello, YGOPro!"
43
+
44
+ // Auto-detect protocol type using Registry
45
+ const parsed = YGOProCtos.getInstanceFromPayload(payload);
46
+ if (parsed instanceof YGOProCtosChat) {
47
+ console.log('Chat message:', parsed.msg);
48
+ }
49
+ ```
50
+
51
+ ### STOC (Server to Client) Protocols
52
+
53
+ ```typescript
54
+ import { YGOProStocChat, YGOProStoc } from 'ygopro-msg-encode';
55
+
56
+ // Serialize a server chat message
57
+ const chat = new YGOProStocChat();
58
+ chat.player_type = 0x10; // System message
59
+ chat.msg = "Welcome to the duel!";
60
+ const payload = chat.toFullPayload();
61
+
62
+ // Deserialize
63
+ const received = new YGOProStocChat();
64
+ received.fromFullPayload(payload);
65
+ console.log(`[${received.player_type}] ${received.msg}`);
66
+
67
+ // Auto-detect using Registry
68
+ const parsed = YGOProStoc.getInstanceFromPayload(payload);
69
+ ```
70
+
71
+ ### MSG (Game Messages) Protocols
72
+
73
+ ```typescript
74
+ import { YGOProMsgHint, YGOProMessages } from 'ygopro-msg-encode';
75
+
76
+ // Create a hint message
77
+ const hint = new YGOProMsgHint();
78
+ hint.type = 1;
79
+ hint.player = 0;
80
+ hint.desc = 0x1234;
81
+
82
+ // Serialize
83
+ const payload = hint.toPayload();
84
+
85
+ // Deserialize with auto-detection
86
+ const parsed = YGOProMessages.getInstanceFromPayload(payload);
87
+ if (parsed instanceof YGOProMsgHint) {
88
+ console.log('Hint type:', parsed.type);
89
+ }
90
+ ```
91
+
92
+ ## Protocol Format
93
+
94
+ ### CTOS/STOC Packet Structure
95
+
96
+ ```
97
+ ┌────────────┬────────────────┬──────────────┐
98
+ │ Length │ Identifier │ Body │
99
+ │ 2 bytes LE │ 1 byte │ Variable │
100
+ └────────────┴────────────────┴──────────────┘
101
+
102
+ Length = 1 (identifier) + body.length
103
+ ```
104
+
105
+ ### MSG Packet Structure
106
+
107
+ ```
108
+ ┌────────────────┬──────────────┐
109
+ │ Identifier │ Body │
110
+ │ 1 byte │ Variable │
111
+ └────────────────┴──────────────┘
112
+ ```
113
+
114
+ ## API Reference
115
+
116
+ ### Base Classes
117
+
118
+ #### `toFullPayload(): Uint8Array`
119
+
120
+ Serializes the protocol instance to a complete packet including header.
121
+
122
+ ```typescript
123
+ const protocol = new YGOProCtosPlayerInfo();
124
+ protocol.name = [0x41, 0x42, 0x43, ...]; // "ABC"
125
+ const fullPayload = protocol.toFullPayload();
126
+ ```
127
+
128
+ #### `fromFullPayload(data: Uint8Array): this`
129
+
130
+ Deserializes a complete packet including header.
131
+
132
+ ```typescript
133
+ const protocol = new YGOProCtosPlayerInfo();
134
+ protocol.fromFullPayload(fullPayload);
135
+ console.log(protocol.name);
136
+ ```
137
+
138
+ **Features:**
139
+ - Automatically validates packet length
140
+ - Automatically validates identifier
141
+ - Auto-truncates extra data if packet is longer than declared
142
+ - Throws clear errors if packet is invalid
143
+
144
+ **Error Handling:**
145
+
146
+ ```typescript
147
+ try {
148
+ protocol.fromFullPayload(data);
149
+ } catch (error) {
150
+ if (error.message.includes('too short')) {
151
+ console.error('Incomplete packet');
152
+ } else if (error.message.includes('identifier mismatch')) {
153
+ console.error('Wrong protocol type');
154
+ }
155
+ }
156
+ ```
157
+
158
+ #### `toPayload(): Uint8Array`
159
+
160
+ Serializes only the body part (without header).
161
+
162
+ ```typescript
163
+ const body = protocol.toPayload();
164
+ ```
165
+
166
+ #### `fromPayload(data: Uint8Array): this`
167
+
168
+ Deserializes only the body part (without header).
169
+
170
+ ```typescript
171
+ protocol.fromPayload(bodyData);
172
+ ```
173
+
174
+ ### Registry System
175
+
176
+ #### Auto-Detection
177
+
178
+ ```typescript
179
+ import { YGOProCtos, YGOProStoc, YGOProMessages } from 'ygopro-msg-encode';
180
+
181
+ // CTOS protocols
182
+ const ctosProtocol = YGOProCtos.getInstanceFromPayload(fullPayload);
183
+
184
+ // STOC protocols
185
+ const stocProtocol = YGOProStoc.getInstanceFromPayload(fullPayload);
186
+
187
+ // MSG protocols
188
+ const msgProtocol = YGOProMessages.getInstanceFromPayload(bodyPayload);
189
+ ```
190
+
191
+ ## Supported Protocols
192
+
193
+ ### CTOS Protocols (19)
194
+
195
+ | ID | Protocol | Description |
196
+ |----|----------|-------------|
197
+ | 0x01 | CTOS_RESPONSE | Response with data |
198
+ | 0x02 | CTOS_UPDATE_DECK | Update deck (using ygopro-deck-encode) |
199
+ | 0x03 | CTOS_HAND_RESULT | Hand result |
200
+ | 0x04 | CTOS_TP_RESULT | Turn player result |
201
+ | 0x10 | CTOS_PLAYER_INFO | Player information |
202
+ | 0x11 | CTOS_CREATE_GAME | Create game |
203
+ | 0x12 | CTOS_JOIN_GAME | Join game |
204
+ | 0x13 | CTOS_LEAVE_GAME | Leave game |
205
+ | 0x14 | CTOS_SURRENDER | Surrender |
206
+ | 0x15 | CTOS_TIME_CONFIRM | Time confirm |
207
+ | 0x16 | CTOS_CHAT | Chat message (variable length) |
208
+ | 0x17 | CTOS_EXTERNAL_ADDRESS | External address (variable length) |
209
+ | 0x20 | CTOS_HS_TODUELIST | Host: to duelist |
210
+ | 0x21 | CTOS_HS_TOOBSERVER | Host: to observer |
211
+ | 0x22 | CTOS_HS_READY | Host: ready |
212
+ | 0x23 | CTOS_HS_NOTREADY | Host: not ready |
213
+ | 0x24 | CTOS_HS_KICK | Host: kick player |
214
+ | 0x25 | CTOS_HS_START | Host: start duel |
215
+ | 0x30 | CTOS_REQUEST_FIELD | Request field |
216
+
217
+ ### STOC Protocols (24)
218
+
219
+ | ID | Protocol | Description |
220
+ |----|----------|-------------|
221
+ | 0x01 | STOC_GAME_MSG | Game message (wraps MSG protocol) |
222
+ | 0x02 | STOC_ERROR_MSG | Error message |
223
+ | 0x03 | STOC_SELECT_HAND | Select hand |
224
+ | 0x04 | STOC_SELECT_TP | Select turn player |
225
+ | 0x05 | STOC_HAND_RESULT | Hand result |
226
+ | 0x06 | STOC_TP_RESULT | Turn player result |
227
+ | 0x07 | STOC_CHANGE_SIDE | Change side |
228
+ | 0x08 | STOC_WAITING_SIDE | Waiting for side deck |
229
+ | 0x09 | STOC_DECK_COUNT | Deck count |
230
+ | 0x11 | STOC_CREATE_GAME | Game created |
231
+ | 0x12 | STOC_JOIN_GAME | Join game |
232
+ | 0x13 | STOC_TYPE_CHANGE | Type change |
233
+ | 0x14 | STOC_LEAVE_GAME | Leave game |
234
+ | 0x15 | STOC_DUEL_START | Duel start |
235
+ | 0x16 | STOC_DUEL_END | Duel end |
236
+ | 0x17 | STOC_REPLAY | Replay data (using ygopro-yrp-encode) |
237
+ | 0x18 | STOC_TIME_LIMIT | Time limit |
238
+ | 0x19 | STOC_CHAT | Chat message (variable length) |
239
+ | 0x20 | STOC_HS_PLAYER_ENTER | Host: player enter |
240
+ | 0x21 | STOC_HS_PLAYER_CHANGE | Host: player change |
241
+ | 0x22 | STOC_HS_WATCH_CHANGE | Host: watch change |
242
+ | 0x23 | STOC_TEAMMATE_SURRENDER | Teammate surrender |
243
+ | 0x30 | STOC_FIELD_FINISH | Field finish |
244
+ | 0x31 | STOC_SRVPRO_ROOMLIST | SRVPro room list |
245
+
246
+ ### MSG Protocols (100+)
247
+
248
+ All YGOPro game messages are supported. See [MSG Protocol List](./CTOS_STOC_IMPLEMENTATION.md) for details.
249
+
250
+ ## Advanced Usage
251
+
252
+ ### Special Protocols
253
+
254
+ #### CTOS_UPDATE_DECK
255
+
256
+ Uses `ygopro-deck-encode` library for deck encoding:
257
+
258
+ ```typescript
259
+ import { YGOProCtosUpdateDeck } from 'ygopro-msg-encode';
260
+ import YGOProDeck from 'ygopro-deck-encode';
261
+
262
+ const updateDeck = new YGOProCtosUpdateDeck();
263
+ updateDeck.deck = new YGOProDeck({
264
+ main: [12345, 67890],
265
+ extra: [11111],
266
+ side: [22222],
267
+ });
268
+
269
+ const payload = updateDeck.toFullPayload();
270
+ ```
271
+
272
+ #### STOC_REPLAY
273
+
274
+ Uses `ygopro-yrp-encode` library for replay encoding:
275
+
276
+ ```typescript
277
+ import { YGOProStocReplay } from 'ygopro-msg-encode';
278
+ import { YGOProYrp } from 'ygopro-yrp-encode';
279
+
280
+ const replay = new YGOProStocReplay();
281
+ replay.replay = new YGOProYrp({
282
+ /* replay data */
283
+ });
284
+
285
+ const payload = replay.toFullPayload();
286
+ ```
287
+
288
+ #### STOC_GAME_MSG
289
+
290
+ Wraps MSG protocol messages:
291
+
292
+ ```typescript
293
+ import { YGOProStocGameMsg, YGOProMsgHint } from 'ygopro-msg-encode';
294
+
295
+ const gameMsg = new YGOProStocGameMsg();
296
+ const hint = new YGOProMsgHint();
297
+ hint.type = 1;
298
+ hint.player = 0;
299
+ hint.desc = 0x1234;
300
+ gameMsg.msg = hint;
301
+
302
+ const payload = gameMsg.toFullPayload();
303
+ ```
304
+
305
+ ### Variable-Length Strings
306
+
307
+ Three protocols use variable-length encoding for bandwidth optimization:
308
+
309
+ ```typescript
310
+ import { YGOProCtosChat } from 'ygopro-msg-encode';
311
+
312
+ const chat = new YGOProCtosChat();
313
+ chat.msg = "Hi"; // Only 6 bytes instead of fixed 512 bytes!
314
+ const payload = chat.toFullPayload();
315
+ ```
316
+
317
+ Protocols with variable-length strings:
318
+ - `CTOS_CHAT`
319
+ - `STOC_CHAT`
320
+ - `CTOS_EXTERNAL_ADDRESS`
321
+
322
+ ### IPv4 Address Handling
323
+
324
+ `CTOS_EXTERNAL_ADDRESS` supports string-based IPv4 addresses:
325
+
326
+ ```typescript
327
+ import { YGOProCtosExternalAddress } from 'ygopro-msg-encode';
328
+
329
+ const ext = new YGOProCtosExternalAddress();
330
+ ext.real_ip = "192.168.1.1"; // Standard IPv4
331
+ ext.real_ip = "::ffff:192.168.1.1"; // IPv6-mapped IPv4 (auto-converted)
332
+ ext.hostname = "example.com";
333
+
334
+ const payload = ext.toFullPayload();
335
+ ```
336
+
337
+ The IP address is automatically converted to/from network byte order (big-endian).
338
+
339
+ ### Room List (SRVPro)
340
+
341
+ ```typescript
342
+ import { YGOProStocSrvproRoomlist, SrvproRoomInfo } from 'ygopro-msg-encode';
343
+
344
+ const roomlist = new YGOProStocSrvproRoomlist();
345
+ roomlist.count = 2;
346
+
347
+ const room1 = new SrvproRoomInfo();
348
+ room1.roomname = 'Room 1';
349
+ room1.room_status = 0; // Waiting
350
+ room1.player1 = 'Player A';
351
+ room1.player2 = 'Player B';
352
+
353
+ const room2 = new SrvproRoomInfo();
354
+ room2.roomname = 'Room 2';
355
+ room2.room_status = 1; // Dueling
356
+ room2.room_duel_count = 1;
357
+
358
+ roomlist.rooms = [room1, room2];
359
+
360
+ const payload = roomlist.toFullPayload();
361
+ ```
362
+
363
+ ## Performance
364
+
365
+ ### Optimization Tips
366
+
367
+ #### ✅ Good Practices
368
+
369
+ ```typescript
370
+ // 1. Reuse protocol instances
371
+ const protocol = new YGOProCtosChat();
372
+ for (const msg of messages) {
373
+ protocol.msg = msg;
374
+ send(protocol.toFullPayload());
375
+ }
376
+
377
+ // 2. Use try-catch for error handling
378
+ try {
379
+ protocol.fromFullPayload(data);
380
+ } catch (error) {
381
+ handleError(error);
382
+ }
383
+
384
+ // 3. Batch processing
385
+ const payloads = messages.map(msg => {
386
+ const chat = new YGOProCtosChat();
387
+ chat.msg = msg;
388
+ return chat.toFullPayload();
389
+ });
390
+ ```
391
+
392
+ #### ❌ Bad Practices
393
+
394
+ ```typescript
395
+ // 1. Don't create new instances in loops
396
+ for (const msg of messages) {
397
+ const protocol = new YGOProCtosChat(); // ❌ Wasteful
398
+ protocol.msg = msg;
399
+ send(protocol.toFullPayload());
400
+ }
401
+
402
+ // 2. Don't ignore errors
403
+ protocol.fromFullPayload(data); // ❌ No error handling
404
+
405
+ // 3. Don't mix APIs unnecessarily
406
+ const body = protocol.toPayload(); // ❌
407
+ const fullPayload = new Uint8Array(3 + body.length);
408
+ // ... manual header construction
409
+ // Use toFullPayload() instead!
410
+ ```
411
+
412
+ ## Testing
413
+
414
+ ```bash
415
+ # Run all tests
416
+ npm test
417
+
418
+ # Run tests with coverage
419
+ npm test -- --coverage
420
+
421
+ # Run specific test suite
422
+ npm test ctos-stoc
423
+ ```
424
+
425
+ ## Building
426
+
427
+ ```bash
428
+ # Build everything
429
+ npm run build
430
+
431
+ # Build specific format
432
+ npm run build:cjs # CommonJS
433
+ npm run build:esm # ES Modules
434
+ npm run build:types # Type definitions
435
+
436
+ # Clean build output
437
+ npm run clean
438
+ ```
439
+
440
+ ## Documentation
441
+
442
+ - [CTOS/STOC Implementation](./CTOS_STOC_IMPLEMENTATION.md) - Detailed protocol implementation
443
+ - [MSG Implementation](./MSG_IMPLEMENTATION_SUMMARY.md) - MSG protocol details
444
+ - [Full Payload API](./FULL_PAYLOAD_UPDATE.md) - `toFullPayload()` / `fromFullPayload()` documentation
445
+ - [Quick Reference](./QUICK_REFERENCE.md) - Quick API reference
446
+ - [Tests Migration](./TESTS_MIGRATION.md) - Testing guide
447
+
448
+ ## Dependencies
449
+
450
+ - **Runtime Dependencies**:
451
+ - `typed-reflector` - Decorator metadata support
452
+ - `ygopro-deck-encode` - Deck encoding/decoding
453
+ - `ygopro-yrp-encode` - Replay encoding/decoding
454
+
455
+ - **Development Dependencies**:
456
+ - TypeScript, ESLint, Prettier
457
+ - Jest for testing
458
+ - esbuild for bundling
459
+
460
+ ## Contributing
461
+
462
+ Contributions are welcome! Please follow these guidelines:
463
+
464
+ 1. Fork the repository
465
+ 2. Create a feature branch
466
+ 3. Write tests for your changes
467
+ 4. Ensure all tests pass (`npm test`)
468
+ 5. Ensure code is properly formatted (`npm run lint`)
469
+ 6. Submit a pull request
470
+
471
+ ## License
472
+
473
+ MIT © [Nanahira](https://github.com/purerosefallen)
474
+
475
+ ## Credits
476
+
477
+ - Based on [YGOPro](https://github.com/Fluorohydride/ygopro) protocol specifications
478
+ - Implements protocols from `ocgcore/network.h` and `gframe/duelclient.cpp`
479
+
480
+ ## Support
481
+
482
+ - 🐛 [Report Issues](https://github.com/purerosefallen/ygopro-msg-encode/issues)
483
+ - 💬 [Discussions](https://github.com/purerosefallen/ygopro-msg-encode/discussions)
484
+ - 📧 Email: nanahira@momobako.com
485
+
486
+ ## Related Projects
487
+
488
+ - [ygopro-deck-encode](https://github.com/purerosefallen/ygopro-deck-encode) - YGOPro deck encoding
489
+ - [ygopro-yrp-encode](https://github.com/purerosefallen/ygopro-yrp-encode) - YGOPro replay encoding
490
+ - [YGOPro](https://github.com/Fluorohydride/ygopro) - The original YGOPro client
491
+
492
+ ---
493
+
494
+ Made with ❤️ for the YGOPro community