@vaitosoi/minejs 0.5.1 → 0.6.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 (67) hide show
  1. package/README.md +4 -0
  2. package/assets/minecraft/26.2/components.json +113 -0
  3. package/assets/minecraft/26.2/packets.json +8 -16
  4. package/assets/minecraft/26.3/packets.json +4767 -0
  5. package/assets/minecraft/versionMapping.json +16 -0
  6. package/dist/binary/decoder.d.ts +35 -0
  7. package/dist/binary/decoder.d.ts.map +1 -1
  8. package/dist/binary/decoder.js +665 -2
  9. package/dist/binary/decoder.js.map +1 -1
  10. package/dist/binary/encoder.d.ts +3 -3
  11. package/dist/binary/encoder.d.ts.map +1 -1
  12. package/dist/binary/encoder.js.map +1 -1
  13. package/dist/client/client.d.ts +58 -1
  14. package/dist/client/client.d.ts.map +1 -1
  15. package/dist/client/client.js +38 -0
  16. package/dist/client/client.js.map +1 -1
  17. package/dist/net/tcp.d.ts +6 -2
  18. package/dist/net/tcp.d.ts.map +1 -1
  19. package/dist/net/tcp.js +5 -2
  20. package/dist/net/tcp.js.map +1 -1
  21. package/dist/packet/listener.d.ts +5 -0
  22. package/dist/packet/listener.d.ts.map +1 -1
  23. package/dist/packet/listener.js +78 -5
  24. package/dist/packet/listener.js.map +1 -1
  25. package/dist/packet/sender.d.ts +3 -1
  26. package/dist/packet/sender.d.ts.map +1 -1
  27. package/dist/packet/sender.js +15 -0
  28. package/dist/packet/sender.js.map +1 -1
  29. package/dist/physics/aabb.js +7 -7
  30. package/dist/physics/aabb.js.map +1 -1
  31. package/dist/physics/player.js +1 -5
  32. package/dist/physics/player.js.map +1 -1
  33. package/dist/version/codec.d.ts.map +1 -1
  34. package/dist/version/codec.js +25 -14
  35. package/dist/version/codec.js.map +1 -1
  36. package/dist/version/registry.d.ts +21 -5
  37. package/dist/version/registry.d.ts.map +1 -1
  38. package/dist/version/registry.js +55 -18
  39. package/dist/version/registry.js.map +1 -1
  40. package/dist/world/block.d.ts +10 -8
  41. package/dist/world/block.d.ts.map +1 -1
  42. package/dist/world/block.js +17 -11
  43. package/dist/world/block.js.map +1 -1
  44. package/dist/world/container.d.ts +106 -0
  45. package/dist/world/container.d.ts.map +1 -0
  46. package/dist/world/container.js +240 -0
  47. package/dist/world/container.js.map +1 -0
  48. package/dist/world/state.d.ts +8 -5
  49. package/dist/world/state.d.ts.map +1 -1
  50. package/dist/world/state.js +2 -0
  51. package/dist/world/state.js.map +1 -1
  52. package/package.json +2 -2
  53. package/src/binary/decoder.ts +691 -2
  54. package/src/binary/encoder.ts +3 -3
  55. package/src/client/client.ts +81 -4
  56. package/src/net/tcp.ts +16 -5
  57. package/src/packet/listener.ts +103 -6
  58. package/src/packet/sender.ts +26 -2
  59. package/src/physics/aabb.ts +7 -7
  60. package/src/physics/player.ts +5 -5
  61. package/src/version/codec.ts +24 -14
  62. package/src/version/registry.ts +61 -17
  63. package/src/world/block.ts +19 -17
  64. package/src/world/container.ts +180 -0
  65. package/src/world/state.ts +11 -6
  66. package/test/client/index.ts +49 -21
  67. package/test/client/registry.json +1735 -0
@@ -1,4 +1,4 @@
1
- import { Vec3 } from "../physics/direction";
1
+ import { BaseVec3 } from "../physics/direction";
2
2
  import { CONTINUATION_FLAG, CONTINUE_BIT, isFixedSizeTag, isTag, MAX_QUANTIZED_VALUE, SCALE_BITS, SEGMENT_BITS } from "./static";
3
3
  import { InvalidValue, NumberTooBig, UnexpectedValue } from "../base/error";
4
4
  import { FixedSizeTag, Tag } from "./static";
@@ -163,7 +163,7 @@ export class BinaryEncoder {
163
163
  *
164
164
  * @returns a Position
165
165
  */
166
- public writePosition(position: Vec3) {
166
+ public writePosition(position: BaseVec3) {
167
167
  const val = BigInt(
168
168
  ((position.x & 0x3FFFFFF) << 38) |
169
169
  ((position.z & 0x3FFFFFF) << 12) |
@@ -219,7 +219,7 @@ export class BinaryEncoder {
219
219
  *
220
220
  * Read this article for more information: https://minecraft.wiki/w/Java_Edition_protocol/Data_types#LpVec3
221
221
  */
222
- public writeLpVec3(vec3: Vec3) {
222
+ public writeLpVec3(vec3: BaseVec3) {
223
223
  const maxCoordinate = Math.max(Math.abs(vec3.x), Math.max(Math.abs(vec3.y), Math.abs(vec3.z)));
224
224
 
225
225
  // Checking for NaN values in our maxCoordinate
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from "node:events";
2
- import { BlockManager, BlockState } from "../world/block";
2
+ import { BlockGetter, BlockManager, BlockState } from "../world/block";
3
3
  import { EntitiesManager } from "../world/entity";
4
4
  import { Input, Player } from "../physics/player";
5
5
  import { TickLoop } from "../world/tick";
@@ -16,6 +16,7 @@ import { computeUUID } from "../base/math";
16
16
  import { HaveSignatureButNotIndex } from "../base/error";
17
17
  import { Sender } from "../packet/sender";
18
18
  import { CacheImplementation } from "../base/cache";
19
+ import { Container, Slot } from "../world/container";
19
20
 
20
21
  export type ClientOption = Omit<TCPClientOption, "protocolVersion"> & {
21
22
  version: string,
@@ -103,12 +104,29 @@ export interface ClientEvents {
103
104
  actionBar: [message: string],
104
105
  /** The raw action bar */
105
106
  actionBarRaw: [textComponent: TextComponent],
107
+
108
+ // Container
109
+ /** When a container is opened */
110
+ openContainer: [container: Container],
111
+ /** When the opening container is closed */
112
+ closeContainer: [],
113
+ /** When the packet contain the content of the container is received */
114
+ containerContent: [container: Container, carryingItem: Slot],
115
+ /** When the packet contain the property of the container is received */
116
+ containerProperty: [container: Container],
117
+
118
+ /**
119
+ * When tab list is updated
120
+ *
121
+ * `{"text":""}` mean remove header or footer.
122
+ */
123
+ tablist: [newTablist: { header: { text: string, raw: TextComponent }, footer: { text: string, raw: TextComponent } }]
106
124
  }
107
125
 
108
126
  /**
109
127
  * High-level client.
110
128
  */
111
- export class Client<IsReady extends boolean = boolean> extends (EventEmitter as new () => TypedEmitter<ClientEvents>) {
129
+ export class Client extends (EventEmitter as new () => TypedEmitter<ClientEvents>) {
112
130
  private static loadRegistry: boolean = false;
113
131
 
114
132
  private tickLoop: TickLoop;
@@ -118,7 +136,7 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
118
136
  private player: Player;
119
137
 
120
138
  private tcp: TCPClient;
121
- private state: SharedState<IsReady>;
139
+ private state: SharedState;
122
140
  private packetListener: Listener;
123
141
  private packetSender: Sender;
124
142
 
@@ -182,7 +200,7 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
182
200
  this.tcp.on("destroy", () => this.emit("destroy"));
183
201
  this.on("loadChunk", (sx, sy, sz) => this.blocks.deleteChunkCache(sx, sy, sz));
184
202
  this.on("unloadChunk", (sx, sz) => {
185
- for (let sy = 0; sy < 16; sy++)
203
+ for (let sy = 0; sy < 16; sy++)
186
204
  this.blocks.deleteChunkCache(sx, sy, sz);
187
205
  });
188
206
  }
@@ -287,10 +305,69 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
287
305
 
288
306
  /**
289
307
  * Rotate your face
308
+ *
309
+ * @see https://minecraft.wiki/w/Java_Edition_protocol/Packets#Synchronize_Player_Position For Yaw and Pitch definition:
310
+ *
311
+ * "Yaw is measured in degrees and does not follow classical trigonometry rules.
312
+ * The unit circle of yaw on the XZ-plane starts at (0, 1) and turns counterclockwise, with 90 at (-1, 0), 180 at (0, -1) and 270 at (1, 0).
313
+ *
314
+ * Pitch is measured in degrees, where 0 is looking straight ahead, -90 is looking straight up, and 90 is looking straight down."
315
+ *
290
316
  * @param yaw In degree
291
317
  * @param pitch In degree
292
318
  */
293
319
  public lookAt(yaw: number, pitch: number) {
294
320
  this.player.setAngle(yaw, pitch);
295
321
  }
322
+
323
+ /**
324
+ * Get opening container.
325
+ *
326
+ * Return `undefined` if not any is opening
327
+ */
328
+ public getOpeningContainer() { return this.state.openingContainer; }
329
+ /**
330
+ * Get carrying item.
331
+ *
332
+ * Return `undefined` if not any is carried
333
+ */
334
+ public getCarryingItem() { return this.state.player?.carryingItem; }
335
+ /**
336
+ * Get player's inventory
337
+ */
338
+ public getInventory() { return this.state.player?.inventory; }
339
+
340
+ /**
341
+ * Open a block.
342
+ *
343
+ * **NOTE** Not working for now
344
+ *
345
+ * @returns `true` if the target block is a solid block, or else, return `false`
346
+ */
347
+ public openBlock(x: number, y: number, z: number): boolean;
348
+ public openBlock(position: BaseVec3): boolean;
349
+ public openBlock(a: BaseVec3 | number, b?: number, c?: number): boolean {
350
+ this.state.checkReady();
351
+ const vec3 = Vec3.loadArgs(a, b, c);
352
+ const clipResult = BlockGetter.clip(
353
+ new Vec3(this.state.player!.position),
354
+ new Vec3(vec3),
355
+ (pos) => this.blocks.at(pos)!.shape
356
+ )!;
357
+ console.log(clipResult);
358
+ if (clipResult.miss) return false;
359
+ this.packetSender.sendUseItemOn(
360
+ "main",
361
+ vec3,
362
+ clipResult.direction,
363
+ {
364
+ x: Math.abs(clipResult.location.x - vec3.x),
365
+ y: Math.abs(clipResult.location.y - vec3.y),
366
+ z: Math.abs(clipResult.location.z - vec3.z),
367
+ },
368
+ false,
369
+ false
370
+ );
371
+ return true;
372
+ }
296
373
  }
package/src/net/tcp.ts CHANGED
@@ -34,7 +34,11 @@ export interface TCPClientOption {
34
34
 
35
35
  debug?: {
36
36
  /** Log the incoming packet */
37
- packetLogger: boolean
37
+ packetLogger: boolean,
38
+ /** Packet to ignore */
39
+ ignorePackets?: string[],
40
+ /** Ignore logs from TCP client (`packet X length Y`) */
41
+ ignoreTCPPacketLogs?: number[] | true
38
42
  },
39
43
 
40
44
  // For premium account
@@ -52,8 +56,8 @@ export interface Message {
52
56
  target: string | undefined,
53
57
  content: string,
54
58
  raw: {
55
- sender: TextComponent,
56
- target: TextComponent | undefined,
59
+ sender: string | TextComponent,
60
+ target: string | TextComponent | undefined,
57
61
  content: TextComponent | undefined
58
62
  }
59
63
  }
@@ -159,7 +163,7 @@ export class TCPClient extends (EventEmitter as new () => TypedEmmiter<TCPClient
159
163
  if (dataLength === 0) {
160
164
  packetID = decoder.readVarInt();
161
165
  } else {
162
- const dataBuffer = this.bufferPool.subarray(decoder.offset, expectedPacketEnd);
166
+ const dataBuffer = decoder.buffer.subarray(decoder.offset, expectedPacketEnd);
163
167
  const decompressed = inflateSync(dataBuffer);
164
168
  if (decompressed.length !== dataLength)
165
169
  throw new UnexpectedValue("decompressed packet data", decompressed.length.toString(), dataLength.toString());
@@ -167,7 +171,14 @@ export class TCPClient extends (EventEmitter as new () => TypedEmmiter<TCPClient
167
171
  packetID = decoder.readVarInt();
168
172
  }
169
173
  }
170
- if (this.state.clientOptions.debug?.packetLogger == true)
174
+ if (
175
+ this.state.clientOptions.debug &&
176
+ this.state.clientOptions.debug.packetLogger &&
177
+ (
178
+ (Array.isArray(this.state.clientOptions.debug.ignoreTCPPacketLogs) && !this.state.clientOptions.debug.ignoreTCPPacketLogs.includes(packetID)) ||
179
+ (!this.state.clientOptions.debug.ignoreTCPPacketLogs)
180
+ )
181
+ )
171
182
  console.log("packet", packetID, "length", decoder.buffer.length);
172
183
  this.forwardPacket(packetID, decoder);
173
184
 
@@ -12,6 +12,7 @@ import { AuthRelatedNotFound, HaveSignatureButNotIndex, MessageLinkNotFound, Not
12
12
  import { uuidToBuffer } from "../base/math";
13
13
  import { MessageLink } from "../message/link";
14
14
  import { Sender } from "./sender";
15
+ import { Container, Slot } from "../world/container";
15
16
 
16
17
  function zodParse<Type extends zod.ZodType>(data: object, zod: Type): zod.infer<Type> {
17
18
  return zod.parse(data);
@@ -62,6 +63,13 @@ export class Listener {
62
63
  "play:remove_mob_effect": this.handleRemoveMobEffect,
63
64
  // "play:rotate_head": ,
64
65
  "play:set_entity_motion": this.handleSetEntityVelocity,
66
+
67
+ "play:open_screen": this.handleOpenScreen,
68
+ "play:container_close": this.handleCloseContainer,
69
+ "play:container_set_content": this.handleContainerContent,
70
+ "play:container_set_data": this.handleContainerProperty,
71
+
72
+ "play:tab_list": this.handleSetTablist
65
73
  };
66
74
  }
67
75
 
@@ -76,7 +84,11 @@ export class Listener {
76
84
  // Login
77
85
 
78
86
  private handleLoginDisconnect(data: object) {
79
- const { reason } = zodParse(data, zod.object({ reason: zod.record(zod.string(), zod.any()) }));
87
+ const { reason } = zodParse(data, zod.object({ reason: zod.record(zod.string(), zod.any()).or(zod.string()) }));
88
+
89
+ if (typeof reason === "string")
90
+ return this.disconnect(reason);
91
+
80
92
  const text = getTextFromTextComponent(reason);
81
93
 
82
94
  this.disconnect(text, reason);
@@ -146,7 +158,9 @@ export class Listener {
146
158
  yaw: 0,
147
159
  pitch: 0,
148
160
  },
149
- effects: {}
161
+ effects: {},
162
+ inventory: new Container(0, -1, {}),
163
+ carryingItem: undefined
150
164
  } satisfies ClientPlayer as any;
151
165
  this.sender.sendLoginAck();
152
166
  }
@@ -693,12 +707,16 @@ export class Listener {
693
707
  filter_type: zod.int(),
694
708
  filter_type_bits: zod.array(zod.bigint()).nullable(),
695
709
  chat_type: zod.int().or(zod.record(zod.string(), zod.any())),
696
- sender_name: zod.record(zod.string(), zod.any()),
697
- target_name: zod.record(zod.string(), zod.any()).nullable()
710
+ sender_name: zod.record(zod.string(), zod.any()).or(zod.string()),
711
+ target_name: zod.record(zod.string(), zod.any()).or(zod.string()).nullable()
698
712
  }));
699
713
 
700
- const senderNameText = getTextFromTextComponent(sender_name).toString(),
701
- targetNameText = target_name ? getTextFromTextComponent(target_name).toString() : undefined;
714
+ const senderNameText = typeof sender_name === "string" ? sender_name : getTextFromTextComponent(sender_name).toString(),
715
+ targetNameText = target_name
716
+ ? typeof target_name === "string"
717
+ ? target_name
718
+ : getTextFromTextComponent(target_name).toString()
719
+ : undefined;
702
720
 
703
721
  const emitObject = {
704
722
  sender: senderNameText,
@@ -834,4 +852,83 @@ export class Listener {
834
852
  }
835
853
  });
836
854
  }
855
+
856
+ // Container
857
+ private handleOpenScreen(data: object) {
858
+ const {
859
+ window_id,
860
+ window_type,
861
+ window_title
862
+ } = zodParse(data, zod.object({
863
+ window_id: zod.int(),
864
+ window_type: zod.int(),
865
+ window_title: zod.record(zod.string(), zod.any())
866
+ }));
867
+ this.state.enqueueMutation(state => {
868
+ state.openingContainer = new Container(window_id, window_type, window_title);
869
+ this.emit("openContainer", this.state.openingContainer!);
870
+ });
871
+ }
872
+
873
+ private handleCloseContainer(data: object) {
874
+ // Not used by vanilla client
875
+ const { window_id } = zodParse(data, zod.object({ window_id: zod.int() }));
876
+
877
+ this.state.enqueueMutation(state => {
878
+ state.openingContainer = undefined;
879
+ this.emit("closeContainer");
880
+ });
881
+ }
882
+
883
+ private handleContainerContent(data: object) {
884
+ const {
885
+ window_id,
886
+ state_id,
887
+ slot_data,
888
+ carried_item
889
+ } = zodParse(data, zod.object({
890
+ window_id: zod.int(),
891
+ state_id: zod.int(),
892
+ slot_data: zod.array(zod.any() as zod.ZodType<Slot>),
893
+ carried_item: zod.any() as zod.ZodType<Slot>,
894
+ }));
895
+ this.state.enqueueMutation(state => {
896
+ if (!state.openingContainer) return;
897
+ state.openingContainer.stateId = state_id;
898
+ state.openingContainer.slots = slot_data;
899
+ state.player!.carryingItem = carried_item;
900
+ this.emit("containerContent", state.openingContainer, state.player!.carryingItem);
901
+ });
902
+ }
903
+
904
+ private handleContainerProperty(data: object) {
905
+ const {
906
+ window_id,
907
+ property,
908
+ value
909
+ } = zodParse(data, zod.object({
910
+ window_id: zod.number(),
911
+ property: zod.number(),
912
+ value: zod.number(),
913
+ }));
914
+ this.state.enqueueMutation(state => {
915
+ if (!state.openingContainer) return;
916
+ state.openingContainer.setProperty(property, value);
917
+ this.emit("containerProperty", state.openingContainer);
918
+ });
919
+ }
920
+
921
+ private handleSetTablist(data: object) {
922
+ const { header, footer } = zodParse(data, zod.object({
923
+ header: zod.record(zod.string(), zod.any()),
924
+ footer: zod.record(zod.string(), zod.any()),
925
+ }));
926
+ this.emit(
927
+ "tablist",
928
+ {
929
+ header: { text: getTextFromTextComponent(header), raw: header },
930
+ footer: { text: getTextFromTextComponent(footer), raw: footer },
931
+ }
932
+ );
933
+ }
837
934
  }
@@ -1,14 +1,15 @@
1
- import { createPublicKey, publicEncrypt, constants as crypto_constants, randomBytes } from "node:crypto";
1
+ import { createPublicKey, publicEncrypt, constants as crypto_constants, randomBytes, randomInt } from "node:crypto";
2
2
  import { TypedEmmiter } from "../base/event";
3
3
  import { ClientEvents } from "../client/client";
4
4
  import { ProtocolVersionMapping } from "../version/registry";
5
5
  import { ClientStatus, ConnectionState, ServerKnownPack, SharedState } from "../world/state";
6
6
  import { sliceBuffer } from "../base/buffer";
7
7
  import { randomUUIDBytes } from "../base/math";
8
- import { Angle, BaseVec3 } from "../physics/direction";
8
+ import { Angle, BaseVec3, Direction } from "../physics/direction";
9
9
  import { MessageTooLong, NotImplemented } from "../base/error";
10
10
  import BitSet from "../base/bitset";
11
11
  import { makeMovementFlag } from "../binary/encoder";
12
+ import { BlockFace } from "../world/block";
12
13
 
13
14
  /**
14
15
  * Packet sender
@@ -176,4 +177,27 @@ export class Sender {
176
177
  });
177
178
  this.state.messageCount = 0;
178
179
  }
180
+
181
+ public sendUseItemOn(
182
+ hand: "main" | "off",
183
+ position: BaseVec3,
184
+ face: BlockFace | Direction,
185
+ cursorPositionOnBlock: BaseVec3,
186
+ isInsideBlock: boolean,
187
+ worldBorderHit: boolean,
188
+ sequence: number = randomInt(1024),
189
+ ) {
190
+ const face_ = (face instanceof Direction ? face.index3D : face) as number;
191
+ this.sendPacket("use_item_on", {
192
+ hand: hand === "off" ? 1 : 0,
193
+ location: position,
194
+ face: face_,
195
+ cursor_position_x: cursorPositionOnBlock.x,
196
+ cursor_position_y: cursorPositionOnBlock.y,
197
+ cursor_position_z: cursorPositionOnBlock.z,
198
+ inside_block: isInsideBlock,
199
+ world_border_hit: worldBorderHit,
200
+ sequence
201
+ });
202
+ }
179
203
  }
@@ -209,7 +209,7 @@ export class AABB implements BaseAABB {
209
209
  * Cliping math. Find smallest distance to reach a face of this AABB.
210
210
  */
211
211
  public static getDirection(aabb: BaseAABB, from: BaseVec3, delta: BaseVec3, direction_: Direction | null, scaleRef: [number]) {
212
- let direction = structuredClone(direction_);
212
+ let direction = direction_;
213
213
  const { minX, maxX, minY, maxY, minZ, maxZ } = aabb;
214
214
  if (delta.x > Epsilon)
215
215
  direction = this.clipPoint(
@@ -217,7 +217,7 @@ export class AABB implements BaseAABB {
217
217
  scaleRef,
218
218
  { a: delta.x, b: delta.y, c: delta.z },
219
219
  minX,
220
- minY, maxX,
220
+ minY, maxY,
221
221
  minZ, maxZ,
222
222
  from.x, from.y, from.z
223
223
  );
@@ -227,7 +227,7 @@ export class AABB implements BaseAABB {
227
227
  scaleRef,
228
228
  { a: delta.x, b: delta.y, c: delta.z },
229
229
  maxX,
230
- minY, maxX,
230
+ minY, maxY,
231
231
  minZ, maxZ,
232
232
  from.x, from.y, from.z
233
233
  );
@@ -292,7 +292,7 @@ export class AABB implements BaseAABB {
292
292
  /**
293
293
  * `s` come from this equation:
294
294
  * ```
295
- * fromA + s * deltaA = minA (or point here)
295
+ * fromA + s * deltaA = minA (or `point` here)
296
296
  * ```
297
297
  * Which find "how far the ray travels to reach a face of this bounding box".
298
298
  *
@@ -305,7 +305,7 @@ export class AABB implements BaseAABB {
305
305
  pb = fromB + s * delta.b,
306
306
  pc = fromC + s * delta.c;
307
307
  if (
308
- 0 < s && s < scaleRef[0] &&
308
+ 0 < s && s < scaleRef[0] + Epsilon &&
309
309
  minB - Epsilon < pb && pb < maxB + Epsilon &&
310
310
  minC - Epsilon < pc && pc < maxC + Epsilon
311
311
  ) {
@@ -599,9 +599,9 @@ export class VoxelShape {
599
599
  minZ: z,
600
600
  maxZ: z + 1
601
601
  });
602
- else if (lastStartZ !== -1)
602
+ else if (lastStartZ === -1)
603
603
  lastStartZ = z;
604
- } else if (lastStartZ === -1) {
604
+ } else if (lastStartZ !== -1) {
605
605
  let endX = x,
606
606
  endY = y;
607
607
  shape.clearZStrip(lastStartZ, z, endX, endY);
@@ -473,11 +473,11 @@ export class Player {
473
473
  if (this.fallDistance != 0 && movement.length() >= 1) {
474
474
  const checkDistance = Math.min(movement.length(), 8);
475
475
  const checkTo = this.getPos().add(movement.normalize().scale(checkDistance));
476
- const hitResult = BlockGetter.clip(this.getPos(), checkTo, {
477
- from: this.getPos(),
478
- to: checkTo,
479
- getBlockState: (position) => this.blocks.at(position)!.shape
480
- });
476
+ const hitResult = BlockGetter.clip(
477
+ this.getPos(),
478
+ checkTo,
479
+ (position) => this.blocks.at(position)!.shape
480
+ );
481
481
  if (hitResult?.miss !== false)
482
482
  this.fallDistance = 0;
483
483
  }
@@ -49,11 +49,14 @@ export class VersionCodec {
49
49
  if (err instanceof NotImplemented) return;
50
50
  throw err;
51
51
  }
52
- if (this.state.clientOptions.debug?.packetLogger)
52
+ if (this.state.clientOptions.debug &&
53
+ this.state.clientOptions.debug.packetLogger &&
54
+ (this.state.clientOptions.debug.ignorePackets &&
55
+ !this.state.clientOptions.debug.ignorePackets.includes(packet.name)))
53
56
  console.dir({
54
57
  dir: "to client",
55
58
  state: mappedState,
56
- name,
59
+ name: packet.name,
57
60
  data: resolvedObject,
58
61
  });
59
62
 
@@ -66,11 +69,15 @@ export class VersionCodec {
66
69
  const packet = PacketRegistry.getPacket(mappedState, "serverbound", packetId);
67
70
  if (!packet) throw new UnexpectedValue("valid serverbound packet id", packetId.toString());
68
71
 
69
- if (this.state.clientOptions.debug?.packetLogger)
72
+ if (this.state.clientOptions.debug &&
73
+ this.state.clientOptions.debug.packetLogger &&
74
+ (this.state.clientOptions.debug.ignorePackets &&
75
+ !this.state.clientOptions.debug.ignorePackets.includes(packet.name)))
70
76
  console.dir({
71
77
  dir: "to server",
72
78
  state: mappedState,
73
- id: packetId,
79
+ id: packet.id,
80
+ name: packet.name,
74
81
  data,
75
82
  });
76
83
 
@@ -144,7 +151,17 @@ export class VersionCodec {
144
151
  case "chat_type_decoration": return decoder.readChatTypeDecoration();
145
152
  case "chat_type": return decoder.readChatType();
146
153
  case "enum": return this.readField(packetId, readObject, fieldName, field.subType, decoder);
147
- case "json_text": return JSON.parse(decoder.readString());
154
+ case "json_text": {
155
+ const str = decoder.readString();
156
+ try {
157
+ return JSON.parse(str);
158
+ } catch (err) {
159
+ if (err instanceof SyntaxError)
160
+ return str;
161
+ else
162
+ throw err;
163
+ }
164
+ }
148
165
  case "object": {
149
166
  const obj: Record<string, any> = {};
150
167
  for (const [key, type] of Object.entries(field.fields))
@@ -152,15 +169,7 @@ export class VersionCodec {
152
169
  return obj;
153
170
  }
154
171
  case "game_profile": {
155
- return {
156
- uuid: decoder.readUUID(),
157
- username: decoder.readString(),
158
- pproperties: decoder.readPrefixedArray((decoder) => ({
159
- name: decoder.readString(),
160
- value: decoder.readString(),
161
- signature: decoder.readPrefixedOptional((decoder) => decoder.readString())
162
- }))
163
- };
172
+ return decoder.readProfile();
164
173
  }
165
174
  case "heightmap": {
166
175
  return {
@@ -170,6 +179,7 @@ export class VersionCodec {
170
179
  }
171
180
  case "bitset": return decoder.readPrefixedArray((decoder) => decoder.readLong());
172
181
  case "teleport_flags": return decoder.readTeleportFlag();
182
+ case "slot": return decoder.readSlot();
173
183
  case "null": return null;
174
184
  case "not_implemented": {
175
185
  if (field.skip_able === true)