@vaitosoi/minejs 0.2.2 → 0.4.0

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 (149) hide show
  1. package/README.md +1 -1
  2. package/assets/minecraft/26.2/packets.json +4758 -0
  3. package/dist/base/buffer.d.ts +2 -0
  4. package/dist/base/buffer.d.ts.map +1 -0
  5. package/dist/base/buffer.js +12 -0
  6. package/dist/base/buffer.js.map +1 -0
  7. package/dist/base/error.d.ts +59 -3
  8. package/dist/base/error.d.ts.map +1 -1
  9. package/dist/base/error.js +123 -7
  10. package/dist/base/error.js.map +1 -1
  11. package/dist/base/http.d.ts +2 -0
  12. package/dist/base/http.d.ts.map +1 -0
  13. package/dist/base/http.js +14 -0
  14. package/dist/base/http.js.map +1 -0
  15. package/dist/base/math.d.ts +22 -1
  16. package/dist/base/math.d.ts.map +1 -1
  17. package/dist/base/math.js +49 -2
  18. package/dist/base/math.js.map +1 -1
  19. package/dist/base/typing.d.ts +7 -1
  20. package/dist/base/typing.d.ts.map +1 -1
  21. package/dist/client/auth.d.ts +41 -7
  22. package/dist/client/auth.d.ts.map +1 -1
  23. package/dist/client/auth.js +96 -39
  24. package/dist/client/auth.js.map +1 -1
  25. package/dist/client/client.d.ts +73 -17
  26. package/dist/client/client.d.ts.map +1 -1
  27. package/dist/client/client.js +111 -44
  28. package/dist/client/client.js.map +1 -1
  29. package/dist/client/tcp.d.ts +17 -206
  30. package/dist/client/tcp.d.ts.map +1 -1
  31. package/dist/client/tcp.js +37 -715
  32. package/dist/client/tcp.js.map +1 -1
  33. package/dist/index.d.ts +12 -12
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +12 -12
  36. package/dist/index.js.map +1 -1
  37. package/dist/message/link.d.ts +10 -0
  38. package/dist/message/link.d.ts.map +1 -0
  39. package/dist/message/link.js +22 -0
  40. package/dist/message/link.js.map +1 -0
  41. package/dist/message/sigCache.d.ts +13 -0
  42. package/dist/message/sigCache.d.ts.map +1 -0
  43. package/dist/message/sigCache.js +26 -0
  44. package/dist/message/sigCache.js.map +1 -0
  45. package/dist/{translator → packet}/decoder.d.ts +14 -1
  46. package/dist/packet/decoder.d.ts.map +1 -0
  47. package/dist/{translator → packet}/decoder.js +24 -3
  48. package/dist/packet/decoder.js.map +1 -0
  49. package/dist/packet/dispatcher.d.ts +53 -0
  50. package/dist/packet/dispatcher.d.ts.map +1 -0
  51. package/dist/packet/dispatcher.js +738 -0
  52. package/dist/packet/dispatcher.js.map +1 -0
  53. package/dist/{translator → packet}/encoder.d.ts +4 -3
  54. package/dist/packet/encoder.d.ts.map +1 -0
  55. package/dist/{translator → packet}/encoder.js +18 -7
  56. package/dist/packet/encoder.js.map +1 -0
  57. package/dist/packet/static.d.ts.map +1 -0
  58. package/dist/packet/static.js.map +1 -0
  59. package/dist/{base → physics}/aabb.d.ts +2 -2
  60. package/dist/physics/aabb.d.ts.map +1 -0
  61. package/dist/{base → physics}/aabb.js +5 -5
  62. package/dist/physics/aabb.js.map +1 -0
  63. package/dist/physics/direction.d.ts.map +1 -0
  64. package/dist/physics/direction.js.map +1 -0
  65. package/dist/{base → physics}/player.d.ts +25 -28
  66. package/dist/physics/player.d.ts.map +1 -0
  67. package/dist/{base → physics}/player.js +81 -68
  68. package/dist/physics/player.js.map +1 -0
  69. package/dist/version/codec.d.ts +18 -0
  70. package/dist/version/codec.d.ts.map +1 -0
  71. package/dist/version/codec.js +235 -0
  72. package/dist/version/codec.js.map +1 -0
  73. package/dist/version/registry.d.ts +236 -0
  74. package/dist/version/registry.d.ts.map +1 -0
  75. package/dist/version/registry.js +284 -0
  76. package/dist/version/registry.js.map +1 -0
  77. package/dist/{base → world}/block.d.ts +5 -5
  78. package/dist/world/block.d.ts.map +1 -0
  79. package/dist/{base → world}/block.js +13 -13
  80. package/dist/world/block.js.map +1 -0
  81. package/dist/{base → world}/entity.d.ts +4 -4
  82. package/dist/world/entity.d.ts.map +1 -0
  83. package/dist/{base → world}/entity.js +6 -6
  84. package/dist/world/entity.js.map +1 -0
  85. package/dist/world/state.d.ts +175 -0
  86. package/dist/world/state.d.ts.map +1 -0
  87. package/dist/world/state.js +163 -0
  88. package/dist/world/state.js.map +1 -0
  89. package/dist/world/tick.d.ts.map +1 -0
  90. package/dist/world/tick.js.map +1 -0
  91. package/package.json +7 -2
  92. package/src/base/buffer.ts +12 -0
  93. package/src/base/error.ts +93 -4
  94. package/src/base/http.ts +10 -0
  95. package/src/base/math.ts +55 -3
  96. package/src/base/typing.ts +9 -1
  97. package/src/client/auth.ts +130 -52
  98. package/src/client/client.ts +182 -50
  99. package/src/client/tcp.ts +45 -967
  100. package/src/index.ts +12 -12
  101. package/src/message/link.ts +17 -0
  102. package/src/message/sigCache.ts +25 -0
  103. package/src/{translator → packet}/decoder.ts +24 -3
  104. package/src/packet/dispatcher.ts +919 -0
  105. package/src/{translator → packet}/encoder.ts +20 -9
  106. package/src/{base → physics}/aabb.ts +5 -5
  107. package/src/{base → physics}/player.ts +106 -65
  108. package/src/version/codec.ts +248 -0
  109. package/src/version/registry.ts +328 -0
  110. package/src/{base → world}/block.ts +12 -11
  111. package/src/{base → world}/entity.ts +5 -5
  112. package/src/world/state.ts +300 -0
  113. package/test/adapter/index.ts +14 -0
  114. package/test/client/index.ts +28 -21
  115. package/test/json/index.ts +3 -0
  116. package/dist/base/aabb.d.ts.map +0 -1
  117. package/dist/base/aabb.js.map +0 -1
  118. package/dist/base/block.d.ts.map +0 -1
  119. package/dist/base/block.js.map +0 -1
  120. package/dist/base/direction.d.ts.map +0 -1
  121. package/dist/base/direction.js.map +0 -1
  122. package/dist/base/entity.d.ts.map +0 -1
  123. package/dist/base/entity.js.map +0 -1
  124. package/dist/base/player.d.ts.map +0 -1
  125. package/dist/base/player.js.map +0 -1
  126. package/dist/base/registry.d.ts +0 -50
  127. package/dist/base/registry.d.ts.map +0 -1
  128. package/dist/base/registry.js +0 -89
  129. package/dist/base/registry.js.map +0 -1
  130. package/dist/base/tick.d.ts.map +0 -1
  131. package/dist/base/tick.js.map +0 -1
  132. package/dist/translator/decoder.d.ts.map +0 -1
  133. package/dist/translator/decoder.js.map +0 -1
  134. package/dist/translator/encoder.d.ts.map +0 -1
  135. package/dist/translator/encoder.js.map +0 -1
  136. package/dist/translator/static.d.ts.map +0 -1
  137. package/dist/translator/static.js.map +0 -1
  138. package/src/base/registry.ts +0 -87
  139. /package/assets/minecraft/{blocks.json → 26.2/blocks.json} +0 -0
  140. /package/assets/minecraft/{entities.json → 26.2/entities.json} +0 -0
  141. /package/dist/{translator → packet}/static.d.ts +0 -0
  142. /package/dist/{translator → packet}/static.js +0 -0
  143. /package/dist/{base → physics}/direction.d.ts +0 -0
  144. /package/dist/{base → physics}/direction.js +0 -0
  145. /package/dist/{base → world}/tick.d.ts +0 -0
  146. /package/dist/{base → world}/tick.js +0 -0
  147. /package/src/{translator → packet}/static.ts +0 -0
  148. /package/src/{base → physics}/direction.ts +0 -0
  149. /package/src/{base → world}/tick.ts +0 -0
@@ -0,0 +1,738 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Dispatcher = void 0;
7
+ const zod_1 = __importDefault(require("zod"));
8
+ const node_crypto_1 = require("node:crypto");
9
+ const state_1 = require("../world/state");
10
+ const decoder_1 = require("./decoder");
11
+ const static_1 = require("../client/static");
12
+ const direction_1 = require("../physics/direction");
13
+ const registry_1 = require("../version/registry");
14
+ const encoder_1 = require("./encoder");
15
+ const error_1 = require("../base/error");
16
+ const math_1 = require("../base/math");
17
+ const link_1 = require("../message/link");
18
+ const buffer_1 = require("../base/buffer");
19
+ function zodParse(data, zod) {
20
+ return zod.parse(data);
21
+ }
22
+ class Dispatcher {
23
+ state;
24
+ emit;
25
+ mapping;
26
+ constructor(state, emit) {
27
+ this.state = state;
28
+ this.emit = emit;
29
+ this.mapping = {
30
+ "login:login_disconnect": this.handleLoginDisconnect,
31
+ "login:hello": this.handleEncryption,
32
+ "login:login_finished": this.handleLoginSucess,
33
+ "login:login_compression": this.handleSetCompression,
34
+ "configuration:disconnect": this.handleConfiguarionPlayDisconnect,
35
+ "configuration:keep_alive": this.handleKeepAlive,
36
+ "configuration:registry_data": this.handleRegistryData,
37
+ "configuration:select_known_packs": this.handleKnownPack,
38
+ "configuration:finish_configuration": this.handleFinishConfiguration,
39
+ "play:add_entity": this.handleSpawnEntity,
40
+ "play:disconnect": this.handleConfiguarionPlayDisconnect,
41
+ "play:disguised_chat": this.handleDisguisedChatMessage,
42
+ "play:entity_position_sync": this.handleTeleportEntity,
43
+ "play:forget_level_chunk": this.handleUnloadChunk,
44
+ "play:keep_alive": this.handleKeepAlive,
45
+ "play:level_chunk_with_light": this.handleChunkData,
46
+ "play:login": this.handlePlayLogin,
47
+ "play:move_entity_pos": this.handleUpdateEntityPosition,
48
+ "play:move_entity_pos_rot": this.handleUpdateEntityPositionRotation,
49
+ "play:player_chat": this.handlePlayerChat,
50
+ "play:player_position": this.handleSynchronizePlayerPosition,
51
+ "play:remove_entities": this.handleRemoveEntity,
52
+ // "play:rotate_head":
53
+ "play:set_action_bar_text": this.handleSetActionBar,
54
+ "play:set_entity_motion": this.handleSetEntityVelocity,
55
+ "play:system_chat": this.handleSystemMessage,
56
+ };
57
+ }
58
+ sendPacket = () => { throw new error_1.NotImplemented(); };
59
+ disconnect = () => { throw new error_1.NotImplemented(); };
60
+ handlePacket(packetId, data) {
61
+ if (packetId in this.mapping)
62
+ this.mapping[packetId].bind(this)(data);
63
+ }
64
+ // Login
65
+ handleLoginDisconnect(data) {
66
+ const { reason } = zodParse(data, zod_1.default.object({ reason: zod_1.default.record(zod_1.default.string(), zod_1.default.any()) }));
67
+ const text = (0, decoder_1.getTextFromTextComponent)(reason);
68
+ this.disconnect(text, reason);
69
+ }
70
+ handleEncryption(data) {
71
+ const { server_id, public_key, verify_token, should_authenticate } = zodParse(data, zod_1.default.object({
72
+ server_id: zod_1.default.string(),
73
+ public_key: zod_1.default.array(zod_1.default.number()),
74
+ verify_token: zod_1.default.array(zod_1.default.number()),
75
+ should_authenticate: zod_1.default.boolean()
76
+ }));
77
+ const sharedSecret = (0, node_crypto_1.randomBytes)(16);
78
+ this.state.sharedSecret = sharedSecret;
79
+ this.state.cipher = (0, node_crypto_1.createCipheriv)("aes-128-cfb8", sharedSecret, sharedSecret);
80
+ this.state.decipher = (0, node_crypto_1.createDecipheriv)("aes-128-cfb8", sharedSecret, sharedSecret);
81
+ this.state.useEncryption = true;
82
+ const publicKey = Buffer.from(public_key), verifyToken = Buffer.from(verify_token);
83
+ if (should_authenticate)
84
+ if (!this.state.authClient)
85
+ throw new error_1.AuthRelatedNotFound("auth client");
86
+ else
87
+ this.state.authClient.sendAuth(server_id, sharedSecret, publicKey)
88
+ .then(() => this.sendEncryptionResponse(publicKey, verifyToken));
89
+ else
90
+ this.sendEncryptionResponse(publicKey, verifyToken);
91
+ }
92
+ handleSetCompression(data) {
93
+ const { threshold } = zodParse(data, zod_1.default.object({ threshold: zod_1.default.number() }));
94
+ if (threshold < 0)
95
+ this.state.compressionThreshold = -1;
96
+ else
97
+ this.state.compressionThreshold = threshold;
98
+ }
99
+ handleLoginSucess(data) {
100
+ const { profile: { uuid, username } } = zodParse(data, zod_1.default.object({
101
+ profile: zod_1.default.object({ uuid: zod_1.default.string(), username: zod_1.default.string() }),
102
+ session_id: zod_1.default.string()
103
+ }));
104
+ this.state.player = {
105
+ uuid,
106
+ username,
107
+ entityId: 0,
108
+ dimension: "",
109
+ gameMode: state_1.GameMode.Survival,
110
+ position: {
111
+ x: 0,
112
+ y: 0,
113
+ z: 0,
114
+ },
115
+ velocity: {
116
+ x: 0,
117
+ y: 0,
118
+ z: 0,
119
+ },
120
+ angle: {
121
+ yaw: 0,
122
+ pitch: 0,
123
+ }
124
+ };
125
+ this.sendLoginAck();
126
+ }
127
+ // Configure
128
+ handleKnownPack(data) {
129
+ const { known_packs } = zodParse(data, zod_1.default.object({
130
+ known_packs: zod_1.default.array(zod_1.default.object({
131
+ namespace: zod_1.default.string(),
132
+ id: zod_1.default.string(),
133
+ version: zod_1.default.string(),
134
+ }))
135
+ }));
136
+ this.state.server.knownPacks = known_packs;
137
+ this.sendKnownPack(this.state.clientOptions.loadRegistry === true ? [] : known_packs);
138
+ // this.sendKnownPack([]);
139
+ }
140
+ handleRegistryData(data) {
141
+ const { registry_id, entries } = zodParse(data, zod_1.default.object({
142
+ registry_id: zod_1.default.string(),
143
+ entries: zod_1.default.array(zod_1.default.object({
144
+ entry_id: zod_1.default.string(),
145
+ data: zod_1.default.record(zod_1.default.string(), zod_1.default.any()).nullable()
146
+ }))
147
+ }));
148
+ if (!this.state.registry)
149
+ this.state.registry = {};
150
+ const registry = this.state.registry;
151
+ if (!(registry_id in registry))
152
+ registry[registry_id] = [];
153
+ registry[registry_id].push(...entries);
154
+ }
155
+ handleFinishConfiguration(data) {
156
+ this.sendConfigureAck();
157
+ }
158
+ handleConfiguarionPlayDisconnect(data) {
159
+ const { reason } = zodParse(data, zod_1.default.object({ reason: zod_1.default.record(zod_1.default.string(), zod_1.default.any()) }));
160
+ const text = (0, decoder_1.getTextFromTextComponent)(reason);
161
+ this.disconnect(text, reason);
162
+ }
163
+ // Play
164
+ handlePlayLogin(data) {
165
+ const { entity_id, is_hardcore, dimension_names, max_players, view_distance, simulation_distance, dimension_name, game_mode } = zodParse(data, zod_1.default.object({
166
+ entity_id: zod_1.default.int(),
167
+ is_hardcore: zod_1.default.boolean(),
168
+ dimension_names: zod_1.default.array(zod_1.default.string()),
169
+ max_players: zod_1.default.int(),
170
+ view_distance: zod_1.default.int(),
171
+ simulation_distance: zod_1.default.int(),
172
+ dimension_name: zod_1.default.string(),
173
+ game_mode: zod_1.default.int()
174
+ }));
175
+ this.state.world = {
176
+ hardcore: is_hardcore,
177
+ dimensions: dimension_names,
178
+ maxPlayers: max_players,
179
+ viewDistance: view_distance,
180
+ simulationDistance: simulation_distance,
181
+ chunks: {},
182
+ entities: {}
183
+ }; // To avoid type conflict
184
+ this.state.player.dimension = dimension_name;
185
+ this.state.player.entityId = entity_id;
186
+ this.state.player.gameMode = game_mode;
187
+ this.state.status = state_1.ClientStatus.Ready;
188
+ if (this.state.useEncryption)
189
+ this.sendPlayerSession();
190
+ this.emit("ready");
191
+ }
192
+ handleSynchronizePlayerPosition(data) {
193
+ const { teleport_id, x, y, z, velocity_x, velocity_y, velocity_z, yaw, pitch, flags } = zodParse(data, zod_1.default.object({
194
+ teleport_id: zod_1.default.int(),
195
+ x: zod_1.default.number(),
196
+ y: zod_1.default.number(),
197
+ z: zod_1.default.number(),
198
+ velocity_x: zod_1.default.number(),
199
+ velocity_y: zod_1.default.number(),
200
+ velocity_z: zod_1.default.number(),
201
+ yaw: zod_1.default.number(),
202
+ pitch: zod_1.default.number(),
203
+ flags: zod_1.default.object({
204
+ x: zod_1.default.boolean(),
205
+ y: zod_1.default.boolean(),
206
+ z: zod_1.default.boolean(),
207
+ yaw: zod_1.default.boolean(),
208
+ pitch: zod_1.default.boolean(),
209
+ velX: zod_1.default.boolean(),
210
+ velY: zod_1.default.boolean(),
211
+ velZ: zod_1.default.boolean(),
212
+ rotateVelocity: zod_1.default.boolean(),
213
+ }),
214
+ }));
215
+ const { position, velocity, angle } = this.state.player;
216
+ let { x: newPosX, y: newPosY, z: newPosZ } = position;
217
+ let { x: newVelX, y: newVelY, z: newVelZ } = velocity;
218
+ let { yaw: newYaw, pitch: newPitch } = angle;
219
+ if (flags.x)
220
+ newPosX += x;
221
+ else
222
+ newPosX = x;
223
+ if (flags.y)
224
+ newPosY += y;
225
+ else
226
+ newPosY = y;
227
+ if (flags.z)
228
+ newPosZ += z;
229
+ else
230
+ newPosZ = z;
231
+ if (flags.velX)
232
+ newVelX += velocity_x;
233
+ else
234
+ newVelX = velocity_x;
235
+ if (flags.velY)
236
+ newVelY += velocity_y;
237
+ else
238
+ newVelY = velocity_y;
239
+ if (flags.velZ)
240
+ newVelZ += velocity_z;
241
+ else
242
+ newVelZ = velocity_z;
243
+ if (flags.yaw)
244
+ newYaw += yaw;
245
+ else
246
+ newYaw = yaw;
247
+ if (flags.pitch)
248
+ newPitch += pitch;
249
+ else
250
+ newPitch = pitch;
251
+ const newPosition = { x: newPosX, y: newPosY, z: newPosZ }, newVelocity = { x: newVelX, y: newVelY, z: newVelZ }, newAngle = { yaw: newYaw, pitch: newPitch };
252
+ this.state.enqueueMutation(state => state.player = {
253
+ ...state.player,
254
+ position: newPosition,
255
+ velocity: newVelocity,
256
+ angle: newAngle,
257
+ });
258
+ this.state.enqueueEvent("playerPosition", { x: newPosX, y: newPosY, z: newPosZ });
259
+ this.sendConfirmTeleportation(teleport_id);
260
+ this.sendPacket("move_player_pos_rot", {
261
+ x: newPosition.x,
262
+ feet_y: newPosition.y,
263
+ z: newPosition.z,
264
+ yaw: newAngle.yaw,
265
+ pitch: newAngle.pitch,
266
+ flags: (0, encoder_1.makeMovementFlag)(true, false)
267
+ });
268
+ }
269
+ handleKeepAlive(data) {
270
+ const { keep_alive_id } = zodParse(data, zod_1.default.object({
271
+ keep_alive_id: zod_1.default.bigint().or(zod_1.default.number())
272
+ }));
273
+ this.sendKeepAlive(BigInt(keep_alive_id));
274
+ }
275
+ handleChangeGameMode(data) {
276
+ const { gameMode } = zodParse(data, zod_1.default.object({ gameMode: zod_1.default.number() }));
277
+ this.state.enqueueMutation(state => state.player.gameMode = gameMode);
278
+ }
279
+ // Chunk
280
+ handleChunkData(data_) {
281
+ const { chunk_x, chunk_z, heightmaps, data, block_entities, light, } = zodParse(data_, zod_1.default.object({
282
+ chunk_x: zod_1.default.int(),
283
+ chunk_z: zod_1.default.int(),
284
+ heightmaps: zod_1.default.array(zod_1.default.any()),
285
+ data: zod_1.default.array(zod_1.default.int()),
286
+ block_entities: zod_1.default.array(zod_1.default.object({
287
+ packed_xz: zod_1.default.int(),
288
+ y: zod_1.default.int(),
289
+ type: zod_1.default.int(),
290
+ data: zod_1.default.record(zod_1.default.string(), zod_1.default.any())
291
+ })),
292
+ light: zod_1.default.any(),
293
+ }));
294
+ const chunkSections = {};
295
+ const chunkDataDecoder = new decoder_1.BinaryDecoder(Buffer.from(data));
296
+ for (let height = 0; height < (static_1.SectionsPerChunk[this.state.player.dimension] || 0); height++) {
297
+ const blockCount = chunkDataDecoder.readShort();
298
+ const fluidCount = chunkDataDecoder.readShort();
299
+ // Blocks
300
+ let blockStateBPE = chunkDataDecoder.readUByte();
301
+ let blockStatePalettes = [];
302
+ if (blockStateBPE === 0) {
303
+ blockStatePalettes = [chunkDataDecoder.readVarInt()];
304
+ }
305
+ else if (blockStateBPE <= 8) {
306
+ // Indirect palette
307
+ if (blockStateBPE < 4)
308
+ blockStateBPE = 4; // BPE smaller than 4 will be rounđe up to 4
309
+ blockStatePalettes = chunkDataDecoder.readPrefixedArray(decoder => decoder.readVarInt());
310
+ }
311
+ else {
312
+ // Direct palette (no palette array)
313
+ }
314
+ const blockEntriesPerSection = 4096;
315
+ const blockEntriesPerLong = Math.floor(64 / blockStateBPE);
316
+ let blockDataArray = null;
317
+ if (blockStateBPE !== 0) {
318
+ const blockDataArrayLength = Math.floor((blockEntriesPerSection + blockEntriesPerLong - 1) / blockEntriesPerLong);
319
+ blockDataArray = new BigInt64Array(chunkDataDecoder.readArray(blockDataArrayLength, (decoder) => decoder.readLong()));
320
+ }
321
+ // Biomes - Not used yet, but need to be read to advance decoder
322
+ const biomeBPE = chunkDataDecoder.readUByte();
323
+ let biomePalettes = [];
324
+ if (biomeBPE === 0) {
325
+ biomePalettes = [chunkDataDecoder.readVarInt()]; // Palette value
326
+ }
327
+ else if (biomeBPE <= 3) {
328
+ // Indirect palette
329
+ biomePalettes = chunkDataDecoder.readPrefixedArray(decoder => decoder.readVarInt());
330
+ }
331
+ else {
332
+ // Direct palette (no palette array)
333
+ }
334
+ const biomeEntriesPerSection = 64;
335
+ const biomeEntriesPerLong = Math.floor(64 / biomeBPE);
336
+ let biomeDataArray = null;
337
+ if (biomeBPE !== 0) {
338
+ const biomeDataArrayLength = Math.floor((biomeEntriesPerSection + biomeEntriesPerLong - 1) / biomeEntriesPerLong);
339
+ biomeDataArray = new BigInt64Array(chunkDataDecoder.readArray(biomeDataArrayLength, (decoder) => decoder.readLong()));
340
+ }
341
+ chunkSections[height] = {
342
+ block: {
343
+ bpe: blockStateBPE,
344
+ palette: blockStatePalettes,
345
+ data: blockDataArray
346
+ },
347
+ biome: {
348
+ bpe: biomeBPE,
349
+ palette: biomePalettes,
350
+ data: biomeDataArray
351
+ }
352
+ };
353
+ this.state.enqueueEvent("loadChunk", chunk_x, height, chunk_z);
354
+ }
355
+ const blockEntitiesObj = Object.fromEntries(block_entities.map(val => [val.packed_xz, { type: val.type, data: val.data }]));
356
+ this.state.enqueueMutation(state => state.world.chunks[`${state.player.dimension}:${chunk_x}:${chunk_z}`] = {
357
+ sections: chunkSections,
358
+ blockEntities: blockEntitiesObj
359
+ });
360
+ }
361
+ handleUnloadChunk(data) {
362
+ const { chunk_x, chunk_z } = zodParse(data, zod_1.default.object({
363
+ chunk_x: zod_1.default.number(),
364
+ chunk_z: zod_1.default.number()
365
+ }));
366
+ this.state.enqueueMutation(state => delete state.world.chunks[`${state.player.dimension}:${chunk_x}:${chunk_z}`]);
367
+ this.state.enqueueEvent("unloadChunk", chunk_x, chunk_z);
368
+ }
369
+ handleBlockEntityData(data_) {
370
+ const { location, type, data } = zodParse(data_, zod_1.default.object({
371
+ location: zod_1.default.object({ x: zod_1.default.number(), y: zod_1.default.number(), z: zod_1.default.number() }),
372
+ type: zod_1.default.int(),
373
+ data: zod_1.default.record(zod_1.default.string(), zod_1.default.any())
374
+ }));
375
+ const chunkX = Math.floor(location.x / 16), chunkZ = Math.floor(location.z / 16);
376
+ const xWitinChunk = location.x % 16, zWitinChunk = location.z % 16;
377
+ const packedPosition = (0, static_1.packBlockPos)(xWitinChunk, location.y, zWitinChunk);
378
+ if (`${this.state.player.dimension}:${chunkX}:${chunkZ}` in this.state.world.chunks)
379
+ this.state.enqueueMutation(state => state.world.chunks[`${state.player.dimension}:${chunkX}:${chunkZ}`].blockEntities[packedPosition] = {
380
+ type,
381
+ data
382
+ });
383
+ }
384
+ // Entity
385
+ handleSpawnEntity(data_) {
386
+ const { entity_id, entity_uuid, type, x, y, z, velocity, pitch, yaw, head_yaw, data } = zodParse(data_, zod_1.default.object({
387
+ entity_id: zod_1.default.int(),
388
+ entity_uuid: zod_1.default.string(),
389
+ type: zod_1.default.int(),
390
+ x: zod_1.default.number(),
391
+ y: zod_1.default.number(),
392
+ z: zod_1.default.number(),
393
+ velocity: zod_1.default.instanceof(direction_1.Vec3),
394
+ pitch: zod_1.default.number(),
395
+ yaw: zod_1.default.number(),
396
+ head_yaw: zod_1.default.number(),
397
+ data: zod_1.default.int(),
398
+ }));
399
+ const entity = {
400
+ id: entity_id,
401
+ type,
402
+ position: { x, y, z },
403
+ velocity,
404
+ angle: {
405
+ pitch,
406
+ yaw
407
+ },
408
+ data
409
+ };
410
+ this.state.enqueueMutation(state => state.world.entities[entity_id] = entity);
411
+ this.state.enqueueEvent("spawnEntity", entity);
412
+ }
413
+ handleTeleportEntity(data) {
414
+ const { entity_id, x, y, z, velocity_x, velocity_y, velocity_z, pitch, yaw } = zodParse(data, zod_1.default.object({
415
+ entity_id: zod_1.default.int(),
416
+ x: zod_1.default.number(),
417
+ y: zod_1.default.number(),
418
+ z: zod_1.default.number(),
419
+ velocity_x: zod_1.default.number(),
420
+ velocity_y: zod_1.default.number(),
421
+ velocity_z: zod_1.default.number(),
422
+ pitch: zod_1.default.number(),
423
+ yaw: zod_1.default.number(),
424
+ }));
425
+ if (entity_id in this.state.world.entities)
426
+ this.state.enqueueMutation(state => {
427
+ state.world.entities[entity_id].position = { x, y, z };
428
+ state.world.entities[entity_id].velocity = { x: velocity_x, y: velocity_y, z: velocity_z };
429
+ state.world.entities[entity_id].angle = { pitch, yaw };
430
+ });
431
+ this.state.enqueueEvent("updateEntity", entity_id);
432
+ }
433
+ handleUpdateEntityPosition(data) {
434
+ const { entity_id, delta_x, delta_y, delta_z } = zodParse(data, zod_1.default.object({
435
+ entity_id: zod_1.default.number(),
436
+ delta_x: zod_1.default.number(),
437
+ delta_y: zod_1.default.number(),
438
+ delta_z: zod_1.default.number(),
439
+ }));
440
+ if (entity_id in this.state.world.entities)
441
+ this.state.enqueueMutation(state => {
442
+ let { x, y, z } = state.world.entities[entity_id].position;
443
+ x += delta_x;
444
+ y += delta_y;
445
+ z += delta_z;
446
+ state.world.entities[entity_id].position = { x, y, z };
447
+ });
448
+ this.state.enqueueEvent("updateEntity", entity_id);
449
+ }
450
+ handleUpdateEntityPositionRotation(data) {
451
+ const { entity_id, delta_x, delta_y, delta_z, pitch, yaw } = zodParse(data, zod_1.default.object({
452
+ entity_id: zod_1.default.number(),
453
+ delta_x: zod_1.default.number(),
454
+ delta_y: zod_1.default.number(),
455
+ delta_z: zod_1.default.number(),
456
+ pitch: zod_1.default.number(),
457
+ yaw: zod_1.default.number(),
458
+ }));
459
+ if (entity_id in this.state.world.entities) {
460
+ this.state.enqueueMutation(state => {
461
+ let { x, y, z } = state.world.entities[entity_id].position;
462
+ x += delta_x;
463
+ y += delta_y;
464
+ z += delta_z;
465
+ state.world.entities[entity_id].position = { x, y, z };
466
+ state.world.entities[entity_id].angle = { yaw, pitch };
467
+ });
468
+ this.state.enqueueEvent("updateEntity", entity_id);
469
+ }
470
+ }
471
+ handleSetEntityVelocity(data) {
472
+ const { entity_id, velocity } = zodParse(data, zod_1.default.object({
473
+ entity_id: zod_1.default.number(),
474
+ velocity: zod_1.default.instanceof(direction_1.Vec3)
475
+ }));
476
+ if (entity_id in this.state.world.entities)
477
+ this.state.enqueueMutation(state => state.world.entities[entity_id].velocity = velocity);
478
+ }
479
+ handleRemoveEntity(data) {
480
+ const { entity_ids } = zodParse(data, zod_1.default.object({ entity_ids: zod_1.default.array(zod_1.default.number()) }));
481
+ this.state.enqueueMutation(state => {
482
+ for (const entityId of entity_ids) {
483
+ delete state.world.entities[entityId];
484
+ this.state.enqueueEvent("removeEntity", entityId);
485
+ }
486
+ });
487
+ }
488
+ // Chat
489
+ handlePlayerChat(data) {
490
+ const { global_index, sender, index, message_signature_bytes, message, timestamp, salt, previous_messages, unsigned_content, filter_type, filter_type_bits, chat_type, sender_name, target_name } = zodParse(data, zod_1.default.object({
491
+ global_index: zod_1.default.int(),
492
+ sender: zod_1.default.string(),
493
+ index: zod_1.default.int(),
494
+ message_signature_bytes: zod_1.default.array(zod_1.default.number()).nullable(),
495
+ message: zod_1.default.string(),
496
+ timestamp: zod_1.default.bigint(),
497
+ salt: zod_1.default.bigint(),
498
+ previous_messages: zod_1.default.array(zod_1.default.object({
499
+ message_id: zod_1.default.number(),
500
+ signature: zod_1.default.array(zod_1.default.number()).optional()
501
+ })),
502
+ unsigned_content: zod_1.default.record(zod_1.default.string(), zod_1.default.any()).nullable(),
503
+ filter_type: zod_1.default.int(),
504
+ filter_type_bits: zod_1.default.array(zod_1.default.bigint()).nullable(),
505
+ chat_type: zod_1.default.int().or(zod_1.default.record(zod_1.default.string(), zod_1.default.any())),
506
+ sender_name: zod_1.default.record(zod_1.default.string(), zod_1.default.any()),
507
+ target_name: zod_1.default.record(zod_1.default.string(), zod_1.default.any()).nullable()
508
+ }));
509
+ const senderNameText = (0, decoder_1.getTextFromTextComponent)(sender_name).toString(), targetNameText = target_name ? (0, decoder_1.getTextFromTextComponent)(target_name).toString() : undefined;
510
+ const emitObject = {
511
+ sender: senderNameText,
512
+ target: targetNameText,
513
+ content: (0, decoder_1.getTextFromTextComponent)(unsigned_content),
514
+ raw: {
515
+ sender: sender_name,
516
+ target: target_name || undefined,
517
+ content: unsigned_content || undefined,
518
+ }
519
+ };
520
+ let link = undefined;
521
+ if (this.state.clientOptions.shouldVerifyMessageOrder && this.state.messageLinks) {
522
+ if (index === 0) {
523
+ if (this.state.sessionID)
524
+ link = link_1.MessageLink.root(sender, this.state.sessionID.toString("hex"));
525
+ else
526
+ link = link_1.MessageLink.unsinged(sender);
527
+ this.state.messageLinks[sender] = link;
528
+ }
529
+ else {
530
+ const oldLink = this.state.messageLinks[sender];
531
+ if (!oldLink)
532
+ throw new error_1.MessageLinkNotFound(sender);
533
+ let newLink;
534
+ if (this.state.sessionID)
535
+ newLink = new link_1.MessageLink(global_index, sender, this.state.sessionID.toString("hex"));
536
+ else
537
+ newLink = link_1.MessageLink.unsinged(sender);
538
+ if (!newLink.isDescendantOf(oldLink))
539
+ throw new error_1.UnexpectedValue("message order", newLink.index.toString(), (oldLink.index + 1).toString());
540
+ this.state.messageLinks[sender] = newLink;
541
+ link = newLink;
542
+ }
543
+ }
544
+ if (this.state.clientOptions.shouldVerifyMessageSignature === true && message_signature_bytes) {
545
+ if (!this.state.sessionID)
546
+ throw new error_1.AuthRelatedNotFound("session uuid");
547
+ if (!this.state.messageSignatureCache)
548
+ throw new error_1.AuthRelatedNotFound("signature cache");
549
+ if (!link)
550
+ throw new error_1.HaveSignatureButNotIndex();
551
+ const { publicKey } = this.state.getSignature();
552
+ const formatVersion = Buffer.alloc(4);
553
+ formatVersion.writeInt32BE(1);
554
+ const senderUUIDBuf = (0, math_1.uuidToBuffer)(sender);
555
+ const sessionUUIDBuf = this.state.sessionID;
556
+ const indexBuf = Buffer.alloc(4);
557
+ indexBuf.writeInt32BE(link.index);
558
+ const saltBuf = Buffer.alloc(8);
559
+ saltBuf.writeBigInt64BE(salt);
560
+ const timestampBuf = Buffer.alloc(8);
561
+ timestampBuf.writeBigInt64BE(timestamp);
562
+ const _messageBuf = Buffer.from(message, "utf-8");
563
+ const lengthBuf = Buffer.alloc(4);
564
+ lengthBuf.writeInt32BE(_messageBuf.length);
565
+ const messageBuf = _messageBuf;
566
+ const previousMessagesLenghtBuf = Buffer.alloc(4);
567
+ previousMessagesLenghtBuf.writeInt32BE(previous_messages.length);
568
+ const previousMessagesBuf = Buffer.concat(this.state.messageSignatureCache.unpack(previous_messages));
569
+ const signaturePayload = Buffer.concat([
570
+ formatVersion,
571
+ senderUUIDBuf,
572
+ sessionUUIDBuf,
573
+ indexBuf,
574
+ saltBuf,
575
+ timestampBuf,
576
+ lengthBuf,
577
+ messageBuf,
578
+ previousMessagesLenghtBuf,
579
+ previousMessagesBuf
580
+ ]);
581
+ const verify = (0, node_crypto_1.createVerify)("RSA-SHA256");
582
+ verify.update(signaturePayload);
583
+ verify.end();
584
+ const signature = Buffer.from(message_signature_bytes);
585
+ if (!verify.verify(publicKey, signature))
586
+ this.emit("failedMessage", emitObject);
587
+ }
588
+ this.emit("message", emitObject);
589
+ }
590
+ handleSystemMessage(data) {
591
+ const { content, overlay: isActionbar } = zodParse(data, zod_1.default.object({
592
+ content: zod_1.default.record(zod_1.default.string(), zod_1.default.any()),
593
+ overlay: zod_1.default.boolean()
594
+ }));
595
+ const text = (0, decoder_1.getTextFromTextComponent)(content);
596
+ if (isActionbar) {
597
+ this.emit("actionBar", text.toString());
598
+ this.emit("actionBarRaw", content);
599
+ }
600
+ else {
601
+ this.emit("systemMessage", text.toString());
602
+ this.emit("systemMessageRaw", content);
603
+ }
604
+ }
605
+ handleSetActionBar(data) {
606
+ const { action_bar_text: content } = zodParse(data, zod_1.default.object({ action_bar_text: zod_1.default.record(zod_1.default.string(), zod_1.default.any()) }));
607
+ const text = (0, decoder_1.getTextFromTextComponent)(content);
608
+ this.emit("actionBar", text.toString());
609
+ this.emit("actionBarRaw", content);
610
+ }
611
+ handleDisguisedChatMessage(data) {
612
+ const { message, chatType, senderName, targetName } = zodParse(data, zod_1.default.object({
613
+ message: zod_1.default.record(zod_1.default.string(), zod_1.default.any()),
614
+ chatType: zod_1.default.string().or(zod_1.default.record(zod_1.default.string(), zod_1.default.any())),
615
+ senderName: zod_1.default.record(zod_1.default.string(), zod_1.default.any()),
616
+ targetName: zod_1.default.record(zod_1.default.string(), zod_1.default.any()).nullable(),
617
+ }));
618
+ const messageText = (0, decoder_1.getTextFromTextComponent)(message).toString(), senderNameText = (0, decoder_1.getTextFromTextComponent)(senderName).toString(), targetNameText = targetName ? (0, decoder_1.getTextFromTextComponent)(targetName).toString() : undefined;
619
+ this.emit("message", {
620
+ sender: senderNameText,
621
+ target: targetNameText,
622
+ content: messageText,
623
+ raw: {
624
+ sender: senderName,
625
+ target: targetName || undefined,
626
+ content: message,
627
+ }
628
+ });
629
+ }
630
+ /*
631
+ * Send packet
632
+ */
633
+ // Login
634
+ sendHandshake() {
635
+ this.state.state = state_1.ConnectionState.Handshake;
636
+ this.sendPacket("intention", {
637
+ protocol_version: registry_1.ProtocolVersionMapping[this.state.clientOptions.version],
638
+ server_address: this.state.clientOptions.host,
639
+ server_port: this.state.clientOptions.port,
640
+ intent: 2
641
+ });
642
+ }
643
+ sendLoginStart() {
644
+ this.state.state = state_1.ConnectionState.Login;
645
+ this.state.status = state_1.ClientStatus.Logining;
646
+ this.sendPacket("hello", {
647
+ name: this.state.clientOptions.playerName,
648
+ player_uuid: Buffer.from(this.state.playerUUID, "hex")
649
+ });
650
+ }
651
+ sendEncryptionResponse(publicKey, verifyToken) {
652
+ const encryptedSecret = (0, node_crypto_1.publicEncrypt)({
653
+ key: (0, node_crypto_1.createPublicKey)({ key: publicKey, format: 'der', type: 'spki' }),
654
+ padding: node_crypto_1.constants.RSA_PKCS1_PADDING
655
+ }, this.state.sharedSecret);
656
+ const encryptedVerifyToken = (0, node_crypto_1.publicEncrypt)({
657
+ key: (0, node_crypto_1.createPublicKey)({ key: publicKey, format: 'der', type: 'spki' }),
658
+ padding: node_crypto_1.constants.RSA_PKCS1_PADDING
659
+ }, verifyToken);
660
+ const secretBuf = (0, buffer_1.sliceBuffer)(encryptedSecret, 1, (buf) => buf.readInt8());
661
+ const token = (0, buffer_1.sliceBuffer)(encryptedVerifyToken, 1, (buf) => buf.readInt8());
662
+ this.sendPacket("key", {
663
+ shared_secret: { value: secretBuf, length: secretBuf.length },
664
+ verify_token: { value: token, length: token.length }
665
+ });
666
+ }
667
+ sendLoginAck() {
668
+ this.sendPacket("login_acknowledged", {});
669
+ this.state.state = state_1.ConnectionState.Configure;
670
+ this.state.server = {};
671
+ }
672
+ // Configuring
673
+ sendKnownPack(knownPacks) {
674
+ this.sendPacket("select_known_packs", {
675
+ known_packs: {
676
+ value: knownPacks,
677
+ length: knownPacks.length
678
+ }
679
+ });
680
+ }
681
+ sendConfigureAck() {
682
+ this.sendPacket("finish_configuration", {});
683
+ this.state.state = state_1.ConnectionState.Play;
684
+ }
685
+ // Play
686
+ sendPlayerSession() {
687
+ const sessionUUID = (0, math_1.randomUUIDBytes)();
688
+ const expireTime = 15 * 60 * 1000; // 15min in ms
689
+ const expiredAt = Date.now() + expireTime;
690
+ const { publicKey, signature } = this.state.getSignature();
691
+ this.state.sessionID = sessionUUID;
692
+ this.sendPacket("chat_session_update", {
693
+ session_id: sessionUUID,
694
+ expire_at: expiredAt,
695
+ public_key: publicKey,
696
+ signature
697
+ });
698
+ }
699
+ sendConfirmTeleportation(teleportId) {
700
+ this.sendPacket("accept_teleportation", {
701
+ teleport_id: teleportId
702
+ });
703
+ }
704
+ sendKeepAlive(id) {
705
+ this.sendPacket("keep_alive", {
706
+ keep_alive_id: id
707
+ });
708
+ }
709
+ sendPlayerPos(position, onGround, horizontalCollision) {
710
+ const { x, y, z } = position;
711
+ this.state.enqueuePacket("move_player_pos", {
712
+ x, feet_y: y, z,
713
+ flags: (0, encoder_1.makeMovementFlag)(onGround, horizontalCollision)
714
+ });
715
+ }
716
+ sendPlayerPosRot(position, angle, onGround, horizontalCollision) {
717
+ const { x, y, z } = position, { yaw, pitch } = angle;
718
+ this.state.enqueuePacket("move_player_pos_rot", {
719
+ x, feet_y: y, z,
720
+ yaw, pitch,
721
+ flags: (0, encoder_1.makeMovementFlag)(onGround, horizontalCollision)
722
+ });
723
+ }
724
+ sendPlayerRot(angle, onGround, horizontalCollision) {
725
+ const { yaw, pitch } = angle;
726
+ this.state.enqueuePacket("move_player_rot", {
727
+ yaw, pitch,
728
+ flags: (0, encoder_1.makeMovementFlag)(onGround, horizontalCollision)
729
+ });
730
+ }
731
+ sendPlayerStatus(onGround, horizontalCollision) {
732
+ this.state.enqueuePacket("move_player_status_only", {
733
+ flags: (0, encoder_1.makeMovementFlag)(onGround, horizontalCollision)
734
+ });
735
+ }
736
+ }
737
+ exports.Dispatcher = Dispatcher;
738
+ //# sourceMappingURL=dispatcher.js.map