@vaitosoi/minejs 0.5.1 → 0.6.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 (77) hide show
  1. package/README.md +25 -9
  2. package/assets/minecraft/26.2/components.json +113 -0
  3. package/assets/minecraft/26.2/packets.json +8 -28
  4. package/assets/minecraft/26.3/packets.json +4957 -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 +4 -4
  13. package/dist/binary/encoder.js.map +1 -1
  14. package/dist/client/client.d.ts +178 -22
  15. package/dist/client/client.d.ts.map +1 -1
  16. package/dist/client/client.js +132 -13
  17. package/dist/client/client.js.map +1 -1
  18. package/dist/net/tcp.d.ts +6 -9
  19. package/dist/net/tcp.d.ts.map +1 -1
  20. package/dist/net/tcp.js +16 -19
  21. package/dist/net/tcp.js.map +1 -1
  22. package/dist/packet/listener.d.ts +6 -1
  23. package/dist/packet/listener.d.ts.map +1 -1
  24. package/dist/packet/listener.js +220 -60
  25. package/dist/packet/listener.js.map +1 -1
  26. package/dist/packet/sender.d.ts +4 -1
  27. package/dist/packet/sender.d.ts.map +1 -1
  28. package/dist/packet/sender.js +30 -4
  29. package/dist/packet/sender.js.map +1 -1
  30. package/dist/physics/aabb.d.ts.map +1 -1
  31. package/dist/physics/aabb.js +17 -9
  32. package/dist/physics/aabb.js.map +1 -1
  33. package/dist/physics/direction.js +2 -2
  34. package/dist/physics/direction.js.map +1 -1
  35. package/dist/physics/player.js +1 -5
  36. package/dist/physics/player.js.map +1 -1
  37. package/dist/version/codec.d.ts.map +1 -1
  38. package/dist/version/codec.js +63 -14
  39. package/dist/version/codec.js.map +1 -1
  40. package/dist/version/registry.d.ts +26 -5
  41. package/dist/version/registry.d.ts.map +1 -1
  42. package/dist/version/registry.js +78 -18
  43. package/dist/version/registry.js.map +1 -1
  44. package/dist/world/block.d.ts +54 -10
  45. package/dist/world/block.d.ts.map +1 -1
  46. package/dist/world/block.js +78 -32
  47. package/dist/world/block.js.map +1 -1
  48. package/dist/world/container.d.ts +106 -0
  49. package/dist/world/container.d.ts.map +1 -0
  50. package/dist/world/container.js +240 -0
  51. package/dist/world/container.js.map +1 -0
  52. package/dist/world/entity.d.ts +3 -0
  53. package/dist/world/entity.d.ts.map +1 -1
  54. package/dist/world/entity.js +3 -0
  55. package/dist/world/entity.js.map +1 -1
  56. package/dist/world/state.d.ts +11 -5
  57. package/dist/world/state.d.ts.map +1 -1
  58. package/dist/world/state.js +11 -0
  59. package/dist/world/state.js.map +1 -1
  60. package/package.json +2 -2
  61. package/src/binary/decoder.ts +691 -2
  62. package/src/binary/encoder.ts +8 -9
  63. package/src/client/client.ts +234 -34
  64. package/src/net/tcp.ts +27 -22
  65. package/src/packet/listener.ts +275 -76
  66. package/src/packet/sender.ts +42 -7
  67. package/src/physics/aabb.ts +18 -9
  68. package/src/physics/direction.ts +2 -2
  69. package/src/physics/player.ts +5 -5
  70. package/src/version/codec.ts +56 -14
  71. package/src/version/registry.ts +92 -18
  72. package/src/world/block.ts +83 -39
  73. package/src/world/container.ts +180 -0
  74. package/src/world/entity.ts +3 -0
  75. package/src/world/state.ts +21 -6
  76. package/test/client/index.ts +56 -21
  77. package/test/client/registry.json +1735 -0
@@ -0,0 +1,180 @@
1
+ import { TextComponent } from "../base/typing";
2
+
3
+ /**
4
+ * Represent the data of a slot
5
+ *
6
+ * @see https://minecraft.wiki/w/Java_Edition_protocol/Slot_data#Format
7
+ */
8
+ export interface Slot {
9
+ counts: number,
10
+ itemId: number | undefined,
11
+ addComponents: Record<string, any> | undefined,
12
+ removeComponents: number[] | undefined
13
+ }
14
+
15
+ /**
16
+ * Represent a container (such as inventory, chest, anvil, ...)
17
+ */
18
+ export class Container {
19
+ /**
20
+ * State ID
21
+ *
22
+ * You SHOULD NOT edit this field since this field is for syncing state from client and server
23
+ */
24
+ public stateId: number = 0;
25
+ /**
26
+ * Slots data
27
+ *
28
+ * @see https://minecraft.wiki/w/Java_Edition_protocol/Inventory For more info how how slot are organized
29
+ */
30
+ public slots: Slot[] = [];
31
+ /**
32
+ * Data from Set Container Property packet
33
+ *
34
+ * @see https://minecraft.wiki/w/Java_Edition_protocol/Packets#Set_Container_Property
35
+ *
36
+ * | Field | Meaning |
37
+ * |------------------------------------------|---------|
38
+ * | # **Furnace / Blast furnace / Smoker** | ------- |
39
+ * | fuel_left | counting from fuel burn time down to 0 |
40
+ * | max_burn_time | fuel burn time or 0 (in-game ticks) |
41
+ * | progress_arrow | counting from 0 to maximum progress (in-game ticks) |
42
+ * | max_progress | always 200 on the vanilla server |
43
+ * | # **Enchantment table** | ------- |
44
+ * | level_requirement_for_top_enchantment | |
45
+ * | level_requirement_for_middle_enchantment | The enchantment's xp level requirement |
46
+ * | level_requirement_for_bottom_enchantment | |
47
+ * | enchantment_seed | Used for drawing the enchantment names (in SGA) clientside. The same seed is used to calculate enchantments, but some of the data isn't sent to the client to prevent easily guessing the entire list (the seed value here is the regular seed bitwise and 0xFFFFFFF0). |
48
+ * | enchant_id_of_top_enchantment | |
49
+ * | enchant_id_of_middle_enchantment | The enchantment ID (set to -1 to hide it), see below for values |
50
+ * | enchant_id_of_bottom_enchantment | |
51
+ * | enchant_level_of_top_enchantment | |
52
+ * | enchant_level_of_middle_enchantment | The enchantment level (1 = I, 2 = II, 6 = VI, etc.), or -1 if no enchant |
53
+ * | enchant_level_of_bottom_enchantment | |
54
+ * | # **Beacon** | ------- |
55
+ * | power_level | 0-4, controls what effect buttons are enabled |
56
+ * | first_effect | Potion effect ID for the first effect, or -1 if no effect |
57
+ * | second_level | Potion effect ID for the second effect, or -1 if no effect |
58
+ * | # **Anvil** | ------- |
59
+ * | repair_cost | The repair's cost in XP levels |
60
+ * | # **Brewing stand** | ------- |
61
+ * | brew_time | 0 – 400, with 400 making the arrow empty, and 0 making the arrow full |
62
+ * | fuel_time | 0 - 20, with 0 making the arrow empty, and 20 making the arrow full |
63
+ * | # **Stonecutter** | ------- |
64
+ * | selected_recipe | The index of the selected recipe. -1 means none is selected |
65
+ * | # **Loom** | ------- |
66
+ * | selected_pattern | The index of the selected pattern. 0 means none is selected, 0 is also the internal ID of the "base" pattern |
67
+ * | # **Lectern** | ------- |
68
+ * | page_number | The current page number, starting from 0. |
69
+ * | # **Smithing table** | ------- |
70
+ * | has_recipe_error | True if greater than zero |
71
+ * | # **Crafter** | ------- |
72
+ * | slot_0_disabled | |
73
+ * | slot_1_disabled | |
74
+ * | slot_2_disabled | |
75
+ * | slot_3_disabled | |
76
+ * | slot_4_disabled | 0 If the slot is enabled, 1 if the slot is disabled |
77
+ * | slot_5_disabled | |
78
+ * | slot_6_disabled | |
79
+ * | slot_7_disabled | |
80
+ * | slot_8_disabled | |
81
+ *
82
+ * @see https://minecraft.wiki/w/Java_Edition_data_values#Effects For effect ID
83
+ */
84
+ public properties: Record<string, number> = {};
85
+
86
+ constructor(
87
+ /**
88
+ * This is not used at the moment
89
+ */
90
+ public id: number,
91
+ /**
92
+ * @see https://minecraft.wiki/w/Java_Edition_protocol/Inventory#Types
93
+ */
94
+ public type: number,
95
+ public rawTitle: TextComponent
96
+ ) { }
97
+
98
+ /**
99
+ * @see https://minecraft.wiki/w/Java_Edition_protocol/Packets#Set_Container_Property
100
+ */
101
+ public setProperty(property: number, data: number) {
102
+ switch (this.type) {
103
+ case 14: // Furnace
104
+ case 10: // Blast furnace
105
+ case 22: // Smoker
106
+ switch (property) {
107
+ case 0: this.properties["fuel_left"] = data; break;
108
+ case 1: this.properties["max_burn_time"] = data; break;
109
+ case 2: this.properties["progress_arrow"] = data; break;
110
+ case 3: this.properties["max_progress"] = data; break;
111
+ }
112
+ break;
113
+ case 13: // Enchantment table
114
+ switch (property) {
115
+ case 0: this.properties["level_requirement_for_top_enchantment"] = data; break;
116
+ case 1: this.properties["level_requirement_for_middle_enchantment"] = data; break;
117
+ case 2: this.properties["level_requirement_for_bottom_enchantment"] = data; break;
118
+ case 3: this.properties["enchantment_seed"] = data; break;
119
+ case 4: this.properties["enchant_id_of_top_enchantment"] = data; break;
120
+ case 5: this.properties["enchant_id_of_middle_enchantment"] = data; break;
121
+ case 6: this.properties["enchant_id_of_bottom_enchantment"] = data; break;
122
+ case 7: this.properties["enchant_level_of_top_enchantment"] = data; break;
123
+ case 8: this.properties["enchant_level_of_middle_enchantment"] = data; break;
124
+ case 9: this.properties["enchant_level_of_bottom_enchantment"] = data; break;
125
+ }
126
+ break;
127
+ case 9: // Beacon
128
+ switch (property) {
129
+ case 0: this.properties["power_level"] = data; break;
130
+ case 1: this.properties["first_effect"] = data; break;
131
+ case 2: this.properties["second_level"] = data; break;
132
+ }
133
+ break;
134
+ case 8: // Anvil
135
+ switch (property) {
136
+ case 0: this.properties["repair_cost"] = data; break;
137
+ }
138
+ break;
139
+ case 11: // Brewing stand
140
+ switch (property) {
141
+ case 0: this.properties["brew_time"] = data; break;
142
+ case 1: this.properties["fuel_time"] = data; break;
143
+ }
144
+ break;
145
+ case 24: // Stonecutter
146
+ switch (property) {
147
+ case 0: this.properties["selected_recipe"] = data; break;
148
+ }
149
+ break;
150
+ case 18: // Loom
151
+ switch (property) {
152
+ case 0: this.properties["selected_pattern"] = data; break;
153
+ }
154
+ break;
155
+ case 17: // Lectern
156
+ switch (property) {
157
+ case 0: this.properties["page_number"] = data; break;
158
+ }
159
+ break;
160
+ case 21: // Smithing table
161
+ switch (property) {
162
+ case 0: this.properties["has_recipe_error"] = data; break;
163
+ }
164
+ break;
165
+ case 7: // Crafter
166
+ switch (property) {
167
+ case 0: this.properties["slot_0_disabled"] = data; break;
168
+ case 1: this.properties["slot_1_disabled"] = data; break;
169
+ case 2: this.properties["slot_2_disabled"] = data; break;
170
+ case 3: this.properties["slot_3_disabled"] = data; break;
171
+ case 4: this.properties["slot_4_disabled"] = data; break;
172
+ case 5: this.properties["slot_5_disabled"] = data; break;
173
+ case 6: this.properties["slot_6_disabled"] = data; break;
174
+ case 7: this.properties["slot_7_disabled"] = data; break;
175
+ case 8: this.properties["slot_8_disabled"] = data; break;
176
+ }
177
+ break;
178
+ }
179
+ }
180
+ }
@@ -1,6 +1,9 @@
1
1
  import { AABB } from "../physics/aabb";
2
2
  import { SharedState } from "./state";
3
3
 
4
+ /**
5
+ * This class is for managing entities
6
+ */
4
7
  export class EntitiesManager {
5
8
  /**
6
9
  * Split chunks into 16x16x16 sections, so each chunk sections will contain a set of entities
@@ -1,5 +1,4 @@
1
1
  import { Cipheriv, Decipheriv } from "node:crypto";
2
- import { If } from "../base/typing";
3
2
  import { Angle, BaseVec3 } from "../physics/direction";
4
3
  import { AuthRelatedNotFound, ClientNotReady } from "../base/error";
5
4
  import { ClientEvents, ClientOption } from "../client/client";
@@ -7,6 +6,8 @@ import { AuthClient } from "../client/auth";
7
6
  import { MessageLink } from "../message/link";
8
7
  import { SignatureCache } from "../message/sigCache";
9
8
  import { CacheImplementation, LRUCache } from "../base/cache";
9
+ import { Container, Slot } from "./container";
10
+ import { ProtocolVersionMapping } from "../version/registry";
10
11
 
11
12
  export interface Server {
12
13
  knownPacks?: ServerKnownPack
@@ -125,7 +126,10 @@ export interface ClientPlayer {
125
126
  /** Current dimension */
126
127
  dimension: string,
127
128
 
128
- effects: Record<number, Effect>
129
+ effects: Record<number, Effect>,
130
+
131
+ inventory: Container,
132
+ carryingItem: Slot | undefined,
129
133
  }
130
134
 
131
135
  export enum ClientStatus {
@@ -160,7 +164,7 @@ export type SendingPacket = {
160
164
  /**
161
165
  * For managing shared data between classes
162
166
  */
163
- export class SharedState<IsReady extends boolean = boolean> {
167
+ export class SharedState {
164
168
  private mutationQueue: MutateState[] = [];
165
169
  private eventQueue: EmittedEvent[] = [];
166
170
  private packetQueue: SendingPacket[] = [];
@@ -183,12 +187,14 @@ export class SharedState<IsReady extends boolean = boolean> {
183
187
  public decipher: Decipheriv | undefined = undefined;
184
188
  public useEncryption: boolean = false;
185
189
  public sessionID: Buffer | undefined = undefined;
190
+ public sequence: number = 0;
186
191
 
187
192
  public server: Server | undefined = undefined;
188
193
  public registry: Record<string, ServerRegistryEntry[]> | undefined = undefined;
189
- public world: If<IsReady, ServerWorld> = null as any;
190
- public player: If<IsReady, ClientPlayer> = null as any;
194
+ public world: ServerWorld | null = null;
195
+ public player: ClientPlayer | null = null;
191
196
  public messageCount: number = 0;
197
+ public openingContainer: Container | undefined = undefined;
192
198
 
193
199
  public cache: CacheImplementation<Uint16Array> | undefined = undefined;
194
200
 
@@ -211,7 +217,7 @@ export class SharedState<IsReady extends boolean = boolean> {
211
217
  }
212
218
  }
213
219
 
214
- public isReady(): this is SharedState<true> {
220
+ public isReady() {
215
221
  return this.status === ClientStatus.Ready;
216
222
  }
217
223
 
@@ -246,6 +252,8 @@ export class SharedState<IsReady extends boolean = boolean> {
246
252
  this.world = undefined as any;
247
253
  this.player = undefined as any;
248
254
  this.messageCount = 0;
255
+ this.openingContainer = undefined as any;
256
+ this.sequence = 0;
249
257
 
250
258
  if (this.clientOptions.shouldVerifyMessageSignature)
251
259
  this.messageSignatureCache = SignatureCache.default();
@@ -264,6 +272,10 @@ export class SharedState<IsReady extends boolean = boolean> {
264
272
  }
265
273
  }
266
274
 
275
+ public getProtocolId() {
276
+ return ProtocolVersionMapping[this.clientOptions.version]!;
277
+ }
278
+
267
279
  public getSignature() {
268
280
  if (this.publicKey && this.signature)
269
281
  return {
@@ -272,6 +284,9 @@ export class SharedState<IsReady extends boolean = boolean> {
272
284
  };
273
285
  throw new AuthRelatedNotFound("public key and signature");
274
286
  }
287
+ public nextSequence() {
288
+ return ++this.sequence;
289
+ }
275
290
 
276
291
  private async fetchSignature() {
277
292
  if (!this.authClient)
@@ -1,13 +1,23 @@
1
- import { Input, Client } from "../../src/index";
1
+ import { Input, Client, ClientEvents } from "../../src/index";
2
2
 
3
3
  const client = new Client({
4
4
  playerName: "bot",
5
5
  host: "localhost",
6
6
  port: 25565,
7
7
  version: "26.2",
8
- // debug: {
9
- // packetLogger: true
10
- // },
8
+ debug: {
9
+ packetLogger: true,
10
+ ignorePackets: [
11
+ "move_entity_pos", "move_entity_pos_rot", "move_entity_rot",
12
+ "set_entity_motion", "rotate_head", "set_time",
13
+ "add_entity", "remove_entities", "bundle_delimiter",
14
+ "entity_position_sync", "update_attributes",
15
+ "move_player_pos", "move_player_pos_rot", "move_player_rot",
16
+ "player_chat", "keep_alive", "entity_event", "tab_list",
17
+ "block_event"
18
+ ],
19
+ ignoreTCPPacketLogs: [0, 83, 54, 101, 1, 99, 53, 35, 131, 113, 102, 44, 56, 65, 34, 77, 122, 7, 46]
20
+ },
11
21
  loadRegistry: false,
12
22
  // auth: {
13
23
  // client_id: "d86254d8-edf7-4640-90eb-643c99af188e",
@@ -17,23 +27,30 @@ const client = new Client({
17
27
  // },
18
28
  // shouldVerifyMessageOrder: true,
19
29
  // shouldVerifyMessageSignature: true
20
- loadAndCacheChunk: true
30
+ loadAndCacheChunk: false
21
31
  });
32
+ const forwardEventToConsole = <K extends keyof ClientEvents>(name: K) => client.on(name, ((...args: any[]) => console.dir({ name, args }, { depth: null })) as any);
22
33
  client.connect();
23
- client.on("disconnect", (...args) => console.dir({ name: "disconnect", args }, { depth: null }));
24
- client.on("disconnectRaw", (...args) => console.dir({ name: "disconnectRaw", args }, { depth: null }));
25
- // client.on("loadChunk", (...args) => console.dir({ name: "loadChunk", args }, { depth: null }));
26
- // client.on("unloadChunk", (...args) => console.dir({ name: "unloadChunk", args }, { depth: null }));
27
- // client.on("spawnEntity", (...args) => console.dir({ name: "spawnEntity", args }, { depth: null }));
28
- // client.on("updateEntity", (...args) => console.dir({ name: "updateEntity", args }, { depth: null }));
29
- // client.on("removeEntity", (...args) => console.dir({ name: "removeEntity", args }, { depth: null }));
30
- client.on("playerPosition", (...args) => console.dir({ name: "playerPosition", args }, { depth: null }));
31
- client.on("message", (...args) => console.dir({ name: "message", args }, { depth: null }));
32
- client.on("systemMessage", (...args) => console.dir({ name: "systemMessage", args }, { depth: null }));
33
- client.on("systemMessageRaw", (...args) => console.dir({ name: "systemMessageRaw", args }, { depth: null }));
34
- client.on("actionBar", (...args) => console.dir({ name: "actionBar", args }, { depth: null }));
35
- client.on("actionBarRaw", (...args) => console.dir({ name: "actionBarRaw", args }, { depth: null }));
36
- client.on("message", (message) => {
34
+ forwardEventToConsole("disconnect");
35
+ forwardEventToConsole("disconnectRaw");
36
+ // forwardEventToConsole("loadChunk");
37
+ // forwardEventToConsole("unloadChunk");
38
+ // forwardEventToConsole("spawnEntity");
39
+ // forwardEventToConsole("updateEntity");
40
+ // forwardEventToConsole("removeEntity");
41
+ // forwardEventToConsole("playerPosition");
42
+ // forwardEventToConsole("message");
43
+ forwardEventToConsole("systemMessage");
44
+ forwardEventToConsole("systemMessageRaw");
45
+ forwardEventToConsole("actionBar");
46
+ forwardEventToConsole("actionBarRaw");
47
+ forwardEventToConsole("openContainer");
48
+ forwardEventToConsole("closeContainer");
49
+ forwardEventToConsole("containerContent");
50
+ forwardEventToConsole("containerProperty");
51
+ forwardEventToConsole("tablist");
52
+
53
+ client.on("message", async (message) => {
37
54
  if (!message.content.startsWith("_")) return;
38
55
  const args = message.content.slice(1).split(" ");
39
56
  switch (args[0]) {
@@ -58,9 +75,21 @@ client.on("message", (message) => {
58
75
  case "at": {
59
76
  const [, x, y, z] = args.map(val => parseInt(val)) as [any, number, number, number];
60
77
  console.time("get_block");
61
- const state = client.at(x, y, z);
78
+ const state = client.getBlock(x, y, z);
62
79
  console.timeEnd("get_block");
63
- console.log(state);
80
+ if (state) {
81
+ console.dir(state);
82
+ client.chat(state!.owner.type);
83
+ } else
84
+ client.chat("no block");
85
+ break;
86
+ }
87
+
88
+ case "open": {
89
+ const [, x, y, z] = args.map(val => Number(val)) as [any, number, number, number];
90
+ const success = client.openBlock(x, y, z);
91
+ if (success) client.chat("opening");
92
+ else client.chat("failed");
64
93
  break;
65
94
  }
66
95
 
@@ -76,5 +105,11 @@ client.on("message", (message) => {
76
105
  case "exit":
77
106
  client.disconnect();
78
107
  break;
108
+
109
+ case "pos": {
110
+ const { x, y, z } = client.getPosition();
111
+ client.chat(`XYZ: ${x} ${y} ${z}`);
112
+ break;
113
+ }
79
114
  }
80
115
  });