@vaitosoi/minejs 0.2.2 → 0.3.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.
- package/assets/minecraft/26.2/packets.json +4741 -0
- package/dist/base/error.d.ts +29 -0
- package/dist/base/error.d.ts.map +1 -1
- package/dist/base/error.js +54 -1
- package/dist/base/error.js.map +1 -1
- package/dist/base/typing.d.ts +7 -1
- package/dist/base/typing.d.ts.map +1 -1
- package/dist/client/client.d.ts +25 -14
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +73 -35
- package/dist/client/client.js.map +1 -1
- package/dist/client/tcp.d.ts +16 -201
- package/dist/client/tcp.d.ts.map +1 -1
- package/dist/client/tcp.js +41 -706
- package/dist/client/tcp.js.map +1 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/{translator → packet}/decoder.d.ts +1 -1
- package/dist/packet/decoder.d.ts.map +1 -0
- package/dist/{translator → packet}/decoder.js +3 -3
- package/dist/packet/decoder.js.map +1 -0
- package/dist/packet/dispatcher.d.ts +46 -0
- package/dist/packet/dispatcher.d.ts.map +1 -0
- package/dist/packet/dispatcher.js +626 -0
- package/dist/packet/dispatcher.js.map +1 -0
- package/dist/{translator → packet}/encoder.d.ts +4 -3
- package/dist/packet/encoder.d.ts.map +1 -0
- package/dist/{translator → packet}/encoder.js +18 -7
- package/dist/packet/encoder.js.map +1 -0
- package/dist/packet/static.d.ts.map +1 -0
- package/dist/packet/static.js.map +1 -0
- package/dist/{base → physics}/aabb.d.ts +2 -2
- package/dist/physics/aabb.d.ts.map +1 -0
- package/dist/{base → physics}/aabb.js +5 -5
- package/dist/physics/aabb.js.map +1 -0
- package/dist/physics/direction.d.ts.map +1 -0
- package/dist/physics/direction.js.map +1 -0
- package/dist/{base → physics}/player.d.ts +8 -5
- package/dist/physics/player.d.ts.map +1 -0
- package/dist/{base → physics}/player.js +40 -25
- package/dist/physics/player.js.map +1 -0
- package/dist/version/codec.d.ts +18 -0
- package/dist/version/codec.d.ts.map +1 -0
- package/dist/version/codec.js +214 -0
- package/dist/version/codec.js.map +1 -0
- package/dist/version/registry.d.ts +236 -0
- package/dist/version/registry.d.ts.map +1 -0
- package/dist/version/registry.js +289 -0
- package/dist/version/registry.js.map +1 -0
- package/dist/{base → world}/block.d.ts +5 -5
- package/dist/world/block.d.ts.map +1 -0
- package/dist/{base → world}/block.js +13 -13
- package/dist/world/block.js.map +1 -0
- package/dist/{base → world}/entity.d.ts +4 -4
- package/dist/world/entity.d.ts.map +1 -0
- package/dist/{base → world}/entity.js +6 -6
- package/dist/world/entity.js.map +1 -0
- package/dist/world/state.d.ts +151 -0
- package/dist/world/state.d.ts.map +1 -0
- package/dist/world/state.js +108 -0
- package/dist/world/state.js.map +1 -0
- package/dist/world/tick.d.ts.map +1 -0
- package/dist/world/tick.js.map +1 -0
- package/package.json +7 -2
- package/src/base/error.ts +36 -0
- package/src/base/typing.ts +9 -1
- package/src/client/client.ts +99 -42
- package/src/client/tcp.ts +49 -954
- package/src/index.ts +12 -12
- package/src/{translator → packet}/decoder.ts +3 -3
- package/src/packet/dispatcher.ts +785 -0
- package/src/{translator → packet}/encoder.ts +20 -9
- package/src/{base → physics}/aabb.ts +5 -5
- package/src/{base → physics}/player.ts +41 -25
- package/src/version/codec.ts +227 -0
- package/src/version/registry.ts +333 -0
- package/src/{base → world}/block.ts +12 -11
- package/src/{base → world}/entity.ts +5 -5
- package/src/world/state.ts +232 -0
- package/test/adapter/index.ts +14 -0
- package/test/client/index.ts +1 -1
- package/test/json/index.ts +3 -0
- package/dist/base/aabb.d.ts.map +0 -1
- package/dist/base/aabb.js.map +0 -1
- package/dist/base/block.d.ts.map +0 -1
- package/dist/base/block.js.map +0 -1
- package/dist/base/direction.d.ts.map +0 -1
- package/dist/base/direction.js.map +0 -1
- package/dist/base/entity.d.ts.map +0 -1
- package/dist/base/entity.js.map +0 -1
- package/dist/base/player.d.ts.map +0 -1
- package/dist/base/player.js.map +0 -1
- package/dist/base/registry.d.ts +0 -50
- package/dist/base/registry.d.ts.map +0 -1
- package/dist/base/registry.js +0 -89
- package/dist/base/registry.js.map +0 -1
- package/dist/base/tick.d.ts.map +0 -1
- package/dist/base/tick.js.map +0 -1
- package/dist/translator/decoder.d.ts.map +0 -1
- package/dist/translator/decoder.js.map +0 -1
- package/dist/translator/encoder.d.ts.map +0 -1
- package/dist/translator/encoder.js.map +0 -1
- package/dist/translator/static.d.ts.map +0 -1
- package/dist/translator/static.js.map +0 -1
- package/src/base/registry.ts +0 -87
- /package/assets/minecraft/{blocks.json → 26.2/blocks.json} +0 -0
- /package/assets/minecraft/{entities.json → 26.2/entities.json} +0 -0
- /package/dist/{translator → packet}/static.d.ts +0 -0
- /package/dist/{translator → packet}/static.js +0 -0
- /package/dist/{base → physics}/direction.d.ts +0 -0
- /package/dist/{base → physics}/direction.js +0 -0
- /package/dist/{base → world}/tick.d.ts +0 -0
- /package/dist/{base → world}/tick.js +0 -0
- /package/src/{translator → packet}/static.ts +0 -0
- /package/src/{base → physics}/direction.ts +0 -0
- /package/src/{base → world}/tick.ts +0 -0
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import { Vec3 } from "../
|
|
1
|
+
import { Vec3 } 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";
|
|
5
5
|
|
|
6
|
+
export function makeMovementFlag(onGround: boolean, pushingWall: boolean) {
|
|
7
|
+
let flag = 0;
|
|
8
|
+
if (onGround)
|
|
9
|
+
flag &= 1;
|
|
10
|
+
if (pushingWall)
|
|
11
|
+
flag |= 1 << 2;
|
|
12
|
+
return flag;
|
|
13
|
+
}
|
|
14
|
+
|
|
6
15
|
export class BinaryEncoder {
|
|
7
16
|
private buffer = Buffer.alloc(0);
|
|
8
17
|
|
|
@@ -14,8 +23,9 @@ export class BinaryEncoder {
|
|
|
14
23
|
this.buffer = Buffer.alloc(0);
|
|
15
24
|
}
|
|
16
25
|
|
|
17
|
-
public
|
|
26
|
+
public writeRaw(buf: Buffer) {
|
|
18
27
|
this.buffer = Buffer.concat([this.buffer, buf]);
|
|
28
|
+
return this;
|
|
19
29
|
}
|
|
20
30
|
|
|
21
31
|
|
|
@@ -27,7 +37,7 @@ export class BinaryEncoder {
|
|
|
27
37
|
public write(size: number, val: any, writeFunc: (buf: Buffer) => ((val: any) => void)) {
|
|
28
38
|
const buf = Buffer.alloc(size);
|
|
29
39
|
writeFunc(buf).bind(buf)(val);
|
|
30
|
-
this.
|
|
40
|
+
this.writeRaw(buf);
|
|
31
41
|
return this;
|
|
32
42
|
}
|
|
33
43
|
|
|
@@ -129,7 +139,7 @@ export class BinaryEncoder {
|
|
|
129
139
|
*/
|
|
130
140
|
public writeString(str: string) {
|
|
131
141
|
this.writeVarInt(str.length);
|
|
132
|
-
this.
|
|
142
|
+
this.writeRaw(Buffer.from(str));
|
|
133
143
|
return this;
|
|
134
144
|
}
|
|
135
145
|
|
|
@@ -171,7 +181,7 @@ export class BinaryEncoder {
|
|
|
171
181
|
else return val;
|
|
172
182
|
});
|
|
173
183
|
this.writeVarInt(length);
|
|
174
|
-
this.
|
|
184
|
+
this.writeRaw(Buffer.concat(array));
|
|
175
185
|
return this;
|
|
176
186
|
}
|
|
177
187
|
|
|
@@ -187,7 +197,7 @@ export class BinaryEncoder {
|
|
|
187
197
|
public writeRawPrefixedArray(data: Buffer, size: number) {
|
|
188
198
|
const length = Math.ceil(data.length / size);
|
|
189
199
|
this.writeVarInt(length);
|
|
190
|
-
this.
|
|
200
|
+
this.writeRaw(data);
|
|
191
201
|
return this;
|
|
192
202
|
}
|
|
193
203
|
|
|
@@ -224,8 +234,9 @@ export class BinaryEncoder {
|
|
|
224
234
|
this.writeVarInt(Number(scaleFactor >> 2n));
|
|
225
235
|
}
|
|
226
236
|
}
|
|
227
|
-
}
|
|
228
237
|
|
|
238
|
+
return this;
|
|
239
|
+
}
|
|
229
240
|
}
|
|
230
241
|
|
|
231
242
|
type CompoundField = any | {
|
|
@@ -306,7 +317,7 @@ export class NBTEncoder extends BinaryEncoder {
|
|
|
306
317
|
public writeString(str: string) {
|
|
307
318
|
this.writeUShort(str.length);
|
|
308
319
|
if (str.length === 0) return this;
|
|
309
|
-
this.
|
|
320
|
+
this.writeRaw(Buffer.from(str));
|
|
310
321
|
return this;
|
|
311
322
|
}
|
|
312
323
|
|
|
@@ -322,7 +333,7 @@ export class NBTEncoder extends BinaryEncoder {
|
|
|
322
333
|
for (const item of arr)
|
|
323
334
|
this.writeString(item);
|
|
324
335
|
else
|
|
325
|
-
this.
|
|
336
|
+
this.writeRaw(Buffer.from(arr));
|
|
326
337
|
return this;
|
|
327
338
|
}
|
|
328
339
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { BitSet } from "
|
|
1
|
+
import { BitSet } from "../base/bitset";
|
|
2
2
|
import { Axis, AxisCycle, BaseAxis, BaseVec3, Direction, Vec3 } from "./direction";
|
|
3
|
-
import { RegistryItemNotFound } from "
|
|
4
|
-
import { EntityRegistry } from "
|
|
5
|
-
import { Epsilon, lowerBoundBinarySearch } from "
|
|
6
|
-
import { BlockHitResult } from "
|
|
3
|
+
import { RegistryItemNotFound } from "../base/error";
|
|
4
|
+
import { EntityRegistry } from "../version/registry";
|
|
5
|
+
import { Epsilon, lowerBoundBinarySearch } from "../base/math";
|
|
6
|
+
import { BlockHitResult } from "../world/block";
|
|
7
7
|
|
|
8
8
|
export interface BaseAABB {
|
|
9
9
|
minX: number;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { EntitiesManager } from "
|
|
1
|
+
import { EntitiesManager } from "../world/entity";
|
|
2
2
|
import { Angle, Axis, BaseAxis, BaseVec3, Vec3 } from "./direction";
|
|
3
3
|
import { AABB, Shapes, VoxelShape } from "./aabb";
|
|
4
|
-
import { BlockGetter, BlockManager, BlockState } from "
|
|
5
|
-
import { clamp, Epsilon, equal, lerp } from "
|
|
6
|
-
import {
|
|
7
|
-
import { ClientNotReady } from "./error";
|
|
4
|
+
import { BlockGetter, BlockManager, BlockState } from "../world/block";
|
|
5
|
+
import { clamp, Epsilon, equal, lerp } from "../base/math";
|
|
6
|
+
import { ClientNotReady } from "../base/error";
|
|
8
7
|
import { LevelHeightLimit } from "../client/static";
|
|
8
|
+
import { SharedState } from "../world/state";
|
|
9
|
+
import { TypedEmmiter } from "../base/event";
|
|
10
|
+
import { ClientEvents } from "../client/client";
|
|
11
|
+
import { makeMovementFlag } from "../packet/encoder";
|
|
9
12
|
|
|
10
13
|
export enum MoveDirection {
|
|
11
14
|
Forward = "W",
|
|
@@ -54,15 +57,16 @@ export class Player {
|
|
|
54
57
|
private lastOnGround: boolean = true;
|
|
55
58
|
|
|
56
59
|
constructor(
|
|
60
|
+
private state: SharedState,
|
|
61
|
+
private on: TypedEmmiter<ClientEvents>["on"],
|
|
57
62
|
private entities: EntitiesManager,
|
|
58
63
|
private blocks: BlockManager,
|
|
59
|
-
private tcp: TCPClient
|
|
60
64
|
) {
|
|
61
|
-
this.
|
|
65
|
+
this.on("playerPosition", () => {
|
|
62
66
|
this.onGround = true;
|
|
63
67
|
this.horizontalCollision = false;
|
|
64
68
|
this.fallDistance = 0;
|
|
65
|
-
this.deltaMovement = new Vec3(this.
|
|
69
|
+
this.deltaMovement = new Vec3(this.state.player!.velocity);
|
|
66
70
|
});
|
|
67
71
|
}
|
|
68
72
|
|
|
@@ -132,20 +136,20 @@ export class Player {
|
|
|
132
136
|
|
|
133
137
|
/* Getting helper, from TCP client */
|
|
134
138
|
private getPos() {
|
|
135
|
-
this.
|
|
136
|
-
return new Vec3(this.
|
|
139
|
+
this.state.checkReady();
|
|
140
|
+
return new Vec3(this.state.player!.position);
|
|
137
141
|
}
|
|
138
142
|
private setPos(pos: Vec3) {
|
|
139
|
-
this.
|
|
140
|
-
this.
|
|
143
|
+
this.state.checkReady();
|
|
144
|
+
this.state.player!.position = pos.copyBase();
|
|
141
145
|
}
|
|
142
146
|
private getAngle() {
|
|
143
|
-
this.
|
|
144
|
-
return this.
|
|
147
|
+
this.state.checkReady();
|
|
148
|
+
return this.state.player!.angle;
|
|
145
149
|
}
|
|
146
150
|
private getDimension() {
|
|
147
|
-
this.
|
|
148
|
-
return this.
|
|
151
|
+
this.state.checkReady();
|
|
152
|
+
return this.state.player!.dimension;
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
private setDeltaMovement(x: number, y: number, z: number): void;
|
|
@@ -217,7 +221,7 @@ export class Player {
|
|
|
217
221
|
* Ticking
|
|
218
222
|
*/
|
|
219
223
|
public tick() {
|
|
220
|
-
if (!this.
|
|
224
|
+
if (!this.state.isReady()) return;
|
|
221
225
|
if (!this.lastPos || !this.lastAngle) throw new ClientNotReady();
|
|
222
226
|
|
|
223
227
|
// console.log("tick");
|
|
@@ -226,7 +230,7 @@ export class Player {
|
|
|
226
230
|
this.aiStep();
|
|
227
231
|
const { x, y, z } = this.getPos(),
|
|
228
232
|
{ x: xLast, y: yLast, z: zLast } = this.lastPos,
|
|
229
|
-
{ yaw: xRot, pitch: yRot } = this.getAngle(),
|
|
233
|
+
{ yaw, yaw: xRot, pitch, pitch: yRot } = this.getAngle(),
|
|
230
234
|
{ yaw: xRotLast, pitch: yRotLast } = this.lastAngle;
|
|
231
235
|
const deltaX = x - xLast,
|
|
232
236
|
deltaY = y - yLast,
|
|
@@ -237,16 +241,28 @@ export class Player {
|
|
|
237
241
|
const move = new Vec3(deltaX, deltaY, deltaZ).lengthSqr() > (2e-4 * 2e-4) || this.positionReminder > 20,
|
|
238
242
|
rot = deltaXRot !== 0 || deltaYRot !== 0;
|
|
239
243
|
if (move && rot)
|
|
240
|
-
this.
|
|
244
|
+
this.state.enqueuePacket("move_player_pos_rot", {
|
|
245
|
+
x, feet_y: y, z,
|
|
246
|
+
yaw, pitch,
|
|
247
|
+
flags: makeMovementFlag(this.onGround, this.horizontalCollision)
|
|
248
|
+
});
|
|
241
249
|
else if (move)
|
|
242
|
-
this.
|
|
250
|
+
this.state.enqueuePacket("move_player_pos", {
|
|
251
|
+
x, feet_y: y, z,
|
|
252
|
+
flags: makeMovementFlag(this.onGround, this.horizontalCollision)
|
|
253
|
+
});
|
|
243
254
|
else if (rot)
|
|
244
|
-
this.
|
|
255
|
+
this.state.enqueuePacket("move_player_rot", {
|
|
256
|
+
yaw, pitch,
|
|
257
|
+
flags: makeMovementFlag(this.onGround, this.horizontalCollision)
|
|
258
|
+
});
|
|
245
259
|
else if (
|
|
246
260
|
this.onGround !== this.lastOnGround ||
|
|
247
261
|
this.horizontalCollision !== this.lastHorizontalCollision
|
|
248
262
|
)
|
|
249
|
-
this.
|
|
263
|
+
this.state.enqueuePacket("move_player_status_only", {
|
|
264
|
+
flags: makeMovementFlag(this.onGround, this.horizontalCollision)
|
|
265
|
+
});
|
|
250
266
|
|
|
251
267
|
if (move) {
|
|
252
268
|
this.lastPos = this.getPos();
|
|
@@ -503,7 +519,7 @@ export class Player {
|
|
|
503
519
|
|
|
504
520
|
private collide(movement: Vec3): Vec3 {
|
|
505
521
|
// Get player's bounding box
|
|
506
|
-
const { x: playerX, y: playerY, z: playerZ } = this.
|
|
522
|
+
const { x: playerX, y: playerY, z: playerZ } = this.state.player!.position;
|
|
507
523
|
const playerBB = AABB.fromEntityType("minecraft:player")
|
|
508
524
|
.move(playerX, playerY, playerZ);
|
|
509
525
|
const expandedBB = playerBB.expandTowards(movement);
|
|
@@ -515,7 +531,7 @@ export class Player {
|
|
|
515
531
|
// });
|
|
516
532
|
|
|
517
533
|
// Collect all colliders
|
|
518
|
-
const colliders = this.collectColliders(expandedBB, [this.
|
|
534
|
+
const colliders = this.collectColliders(expandedBB, [this.state.player!.entityId]);
|
|
519
535
|
// // console.log('nonEmptyColliders', colliders.filter(c => !c.isEmpty()).length);
|
|
520
536
|
|
|
521
537
|
// Get the farest distance can move
|
|
@@ -535,7 +551,7 @@ export class Player {
|
|
|
535
551
|
if (!onGroundAfterCollision)
|
|
536
552
|
stepUpAABB = stepUpAABB.expandTowards(0, -1e-5, 0);
|
|
537
553
|
|
|
538
|
-
const colliders = this.collectColliders(stepUpAABB, [this.
|
|
554
|
+
const colliders = this.collectColliders(stepUpAABB, [this.state.player!.entityId]);
|
|
539
555
|
const stepHeightToSkip = movementStep.y;
|
|
540
556
|
const stepUpCandidateSet: Set<number> = new Set();
|
|
541
557
|
for (const collider of colliders) {
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import z, { file } from "zod";
|
|
2
|
+
import { MissingField, MissingPacketField, UnexpectedValue } from "../base/error";
|
|
3
|
+
import { BinaryDecoder } from "../packet/decoder";
|
|
4
|
+
import { ConnectionState, SharedState } from "../world/state";
|
|
5
|
+
import { FieldNode, PacketObject, PacketRegistry, VersionDefinitions } from "./registry";
|
|
6
|
+
import { Dispatcher } from "../packet/dispatcher";
|
|
7
|
+
import { BinaryEncoder } from "../packet/encoder";
|
|
8
|
+
|
|
9
|
+
const TCPStateMapping: Record<ConnectionState, keyof z.infer<typeof VersionDefinitions> | null> = {
|
|
10
|
+
[ConnectionState.Disconnected]: null,
|
|
11
|
+
[ConnectionState.Handshake]: "handshaking",
|
|
12
|
+
[ConnectionState.Login]: "login",
|
|
13
|
+
[ConnectionState.Configure]: "configuration",
|
|
14
|
+
[ConnectionState.Play]: "play",
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export interface EncodeResult {
|
|
18
|
+
buffer: Buffer,
|
|
19
|
+
packet: z.infer<typeof PacketObject>,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class VersionCodec {
|
|
23
|
+
constructor(private readonly state: SharedState) { }
|
|
24
|
+
|
|
25
|
+
public consumePacket: (packetId: string, data: object) => void = (...args) => { throw new Error("method not implemented"); };
|
|
26
|
+
|
|
27
|
+
public handlePacket(packetId: number, decoder: BinaryDecoder) {
|
|
28
|
+
const mappedState = TCPStateMapping[this.state.state];
|
|
29
|
+
if (!mappedState) return; // console.log("no state");
|
|
30
|
+
const packet = PacketRegistry.getPacket(mappedState, "clientbound", packetId);
|
|
31
|
+
if (!packet) return; // console.log("no packet");
|
|
32
|
+
|
|
33
|
+
const { name, structure, skipForNow } = packet;
|
|
34
|
+
if (skipForNow) return;
|
|
35
|
+
// console.log(`> packet ${name}`);
|
|
36
|
+
const resolvedObject: Record<string, any> = {};
|
|
37
|
+
for (const [name, field] of Object.entries(structure)) {
|
|
38
|
+
// console.log({ name, resolvedObject });
|
|
39
|
+
resolvedObject[name] = this.readField(packetId, resolvedObject, name, field, decoder);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.consumePacket(`${TCPStateMapping[this.state.state]}:${name}`, resolvedObject);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public encodePacket(packetId: number | string, data: Record<string, any>): EncodeResult {
|
|
46
|
+
const mappedState = TCPStateMapping[this.state.state];
|
|
47
|
+
if (!mappedState) throw new UnexpectedValue("map-able state", this.state.state.toString());
|
|
48
|
+
const packet = PacketRegistry.getPacket(mappedState, "serverbound", packetId);
|
|
49
|
+
if (!packet) throw new UnexpectedValue("valid serverbound packet id", packetId.toString());
|
|
50
|
+
|
|
51
|
+
const { name: packetName, structure } = packet;
|
|
52
|
+
let encoder = new BinaryEncoder();
|
|
53
|
+
for (const [name, field] of Object.entries(structure)) {
|
|
54
|
+
if (!(name in data))
|
|
55
|
+
throw new MissingField(name, `packet ${packetName}`);
|
|
56
|
+
if (typeof data[name] === "object")
|
|
57
|
+
if ("value" in data[name])
|
|
58
|
+
if ("metadata" in data[name])
|
|
59
|
+
encoder = this.writeField(field, encoder, data[name]["value"], data[name]["metadata"]);
|
|
60
|
+
else if ("length" in data[name])
|
|
61
|
+
encoder = this.writeField(field, encoder, data[name]["value"], { length: data[name]["length"] });
|
|
62
|
+
else
|
|
63
|
+
encoder = this.writeField(field, encoder, data[name]["value"]);
|
|
64
|
+
else
|
|
65
|
+
encoder = this.writeField(field, encoder, data[name]);
|
|
66
|
+
else
|
|
67
|
+
encoder = this.writeField(field, encoder, data[name]);
|
|
68
|
+
}
|
|
69
|
+
return { buffer: encoder.getBuffer(), packet };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
private readField(
|
|
73
|
+
// Current reading state
|
|
74
|
+
packetId: number,
|
|
75
|
+
readObject: Record<string, any>,
|
|
76
|
+
|
|
77
|
+
// Current field
|
|
78
|
+
fieldName: string,
|
|
79
|
+
field: FieldNode,
|
|
80
|
+
decoder: BinaryDecoder
|
|
81
|
+
): any {
|
|
82
|
+
switch (field.type) {
|
|
83
|
+
case "string": return decoder.readString();
|
|
84
|
+
case "boolean": return decoder.readBoolean();
|
|
85
|
+
case "byte": return decoder.readByte();
|
|
86
|
+
case "unsigned_byte": return decoder.readUByte();
|
|
87
|
+
case "short": return decoder.readShort();
|
|
88
|
+
case "unsigned_short": return decoder.readUShort();
|
|
89
|
+
case "int": return decoder.readInt();
|
|
90
|
+
case "long": return decoder.readLong();
|
|
91
|
+
case "float": return decoder.readFloat();
|
|
92
|
+
case "double": return decoder.readDouble();
|
|
93
|
+
case "var_int": return decoder.readVarInt();
|
|
94
|
+
case "var_long": return decoder.readVarLong();
|
|
95
|
+
case "uuid": return decoder.readUUID();
|
|
96
|
+
case "position": return decoder.readPosition();
|
|
97
|
+
case "array": {
|
|
98
|
+
let length;
|
|
99
|
+
if (!isNaN(Number(field.length)))
|
|
100
|
+
length = Number(field.length);
|
|
101
|
+
else
|
|
102
|
+
length = readObject[field.length];
|
|
103
|
+
if (length === undefined) throw new MissingPacketField(packetId, fieldName, field.length.toString());
|
|
104
|
+
return decoder.readArray(length, (decoder) => this.readField(packetId, readObject, fieldName, field.subType, decoder));
|
|
105
|
+
}
|
|
106
|
+
case "prefixed_array": return decoder.readPrefixedArray((decoder) => this.readField(packetId, readObject, fieldName, field.subType, decoder));
|
|
107
|
+
case "teleport_flag": return decoder.readTeleportFlag();
|
|
108
|
+
case "prefixed_optional": return decoder.readPrefixedOptional((decoder) => this.readField(packetId, readObject, fieldName, field.subType, decoder));
|
|
109
|
+
case "nbt": return decoder.readNBT();
|
|
110
|
+
case "lpvec3": return decoder.readLpVec3();
|
|
111
|
+
case "fixed_point": {
|
|
112
|
+
const value = this.readField(packetId, readObject, fieldName, field.subType, decoder);
|
|
113
|
+
return decoder.readFixedPoint(value, field.fractionBits);
|
|
114
|
+
}
|
|
115
|
+
case "angle": return decoder.readAngle();
|
|
116
|
+
case "id_or_x": return decoder.readIdOrX((decoder) => this.readField(packetId, readObject, fieldName, field.subType, decoder));
|
|
117
|
+
case "chat_type_decoration": return decoder.readChatTypeDecoration();
|
|
118
|
+
case "chat_type": return decoder.readChatType();
|
|
119
|
+
case "enum": return this.readField(packetId, readObject, fieldName, field.subType, decoder);
|
|
120
|
+
case "json_text": return JSON.parse(decoder.readString());
|
|
121
|
+
case "object": {
|
|
122
|
+
const obj: Record<string, any> = {};
|
|
123
|
+
for (const [key, type] of Object.entries(field.fields))
|
|
124
|
+
obj[key] = this.readField(packetId, readObject, key, type, decoder);
|
|
125
|
+
return obj;
|
|
126
|
+
}
|
|
127
|
+
case "game_profile": {
|
|
128
|
+
return {
|
|
129
|
+
uuid: decoder.readUUID(),
|
|
130
|
+
username: decoder.readString(),
|
|
131
|
+
pproperties: decoder.readPrefixedArray((decoder) => ({
|
|
132
|
+
name: decoder.readString(),
|
|
133
|
+
value: decoder.readString(),
|
|
134
|
+
signature: decoder.readPrefixedOptional((decoder) => decoder.readString())
|
|
135
|
+
}))
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
case "heightmap": {
|
|
139
|
+
return {
|
|
140
|
+
type: decoder.readVarInt(),
|
|
141
|
+
data: decoder.readPrefixedArray((decoder) => decoder.readLong())
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
case "bitset": return decoder.readPrefixedArray((decoder) => decoder.readLong());
|
|
145
|
+
case "teleport_flags": return decoder.readTeleportFlag();
|
|
146
|
+
case "null": return null;
|
|
147
|
+
case "switch": {
|
|
148
|
+
if (!(field.dependsOn in readObject)) throw new MissingPacketField(packetId, fieldName, field.dependsOn);
|
|
149
|
+
const dependencyValue = readObject[field.dependsOn];
|
|
150
|
+
for (const [value, type] of field.cases)
|
|
151
|
+
if (dependencyValue === value)
|
|
152
|
+
return this.readField(packetId, readObject, fieldName, type, decoder);
|
|
153
|
+
if (field.default)
|
|
154
|
+
return this.readField(packetId, readObject, fieldName, field.default, decoder);
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
private writeField(
|
|
162
|
+
field: FieldNode,
|
|
163
|
+
encoder: BinaryEncoder,
|
|
164
|
+
value: any,
|
|
165
|
+
metadata: Record<string, any> = {}
|
|
166
|
+
): BinaryEncoder {
|
|
167
|
+
switch (field.type) {
|
|
168
|
+
case "string": return encoder.writeString(value);
|
|
169
|
+
case "boolean": return encoder.writeBoolean(value);
|
|
170
|
+
case "byte": return encoder.writeByte(value);
|
|
171
|
+
case "unsigned_byte": return encoder.writeUByte(value);
|
|
172
|
+
case "short": return encoder.writeShort(value);
|
|
173
|
+
case "unsigned_short": return encoder.writeUShort(value);
|
|
174
|
+
case "int": return encoder.writeInt(value);
|
|
175
|
+
case "long": return encoder.writeLong(value);
|
|
176
|
+
case "float": return encoder.writeFloat(value);
|
|
177
|
+
case "double": return encoder.writeDouble(value);
|
|
178
|
+
case "var_int": return encoder.writeVarInt(value);
|
|
179
|
+
case "var_long": return encoder.writeVarLong(value);
|
|
180
|
+
case "uuid": return encoder.writeRaw(value);
|
|
181
|
+
case "position": return encoder.writePosition(value);
|
|
182
|
+
// case "array": {
|
|
183
|
+
// const length = metadata["length"];
|
|
184
|
+
// // if (!length) throw new MissingField(packetId, fieldName, field.length);
|
|
185
|
+
// return encoder.writeArray(length, (decoder) => this.readField(packetId, readObject, fieldName, field.subType, decoder));
|
|
186
|
+
// }
|
|
187
|
+
case "prefixed_array": {
|
|
188
|
+
const length = metadata["length"];
|
|
189
|
+
if (!length) throw new MissingField("length", "prefixed array metadata object");
|
|
190
|
+
if (!Array.isArray(value))
|
|
191
|
+
throw new UnexpectedValue("an array for prefixed array", typeof value);
|
|
192
|
+
return encoder.writePrefixedArray(length, (encoder, index) => this.writeField(field.subType, encoder, value[index], metadata));
|
|
193
|
+
}
|
|
194
|
+
// case "teleport_flag": return encoder.writeTeleportFlag();
|
|
195
|
+
// case "prefixed_optional": return encoder.writePrefixedOptional((decoder) => this.readField(packetId, readObject, fieldName, field.subType, decoder));
|
|
196
|
+
// case "nbt": return encoder.writeNBT(value);
|
|
197
|
+
case "lpvec3": return encoder.writeLpVec3(value);
|
|
198
|
+
// case "fixed_point": {
|
|
199
|
+
// const value = this.readField(packetId, readObject, fieldName, field.subType, encoder);
|
|
200
|
+
// return encoder.writeFixedPoint(value, field.fractionBits);
|
|
201
|
+
// }
|
|
202
|
+
// case "angle": return encoder.writeAngle();
|
|
203
|
+
// case "id_or_x": return encoder.writeIdOrX((decoder) => this.readField(packetId, readObject, fieldName, field.subType, decoder));
|
|
204
|
+
// case "chat_type_decoration": return encoder.writeChatTypeDecoration();
|
|
205
|
+
// case "chat_type": return encoder.writeChatType();
|
|
206
|
+
case "enum": return this.writeField(field.subType, encoder, value, metadata);
|
|
207
|
+
case "json_text": return encoder.writeString(JSON.parse(value));
|
|
208
|
+
case "object": {
|
|
209
|
+
for (const [name, subField] of Object.entries(field.fields))
|
|
210
|
+
encoder = this.writeField(subField, encoder, value[name], metadata);
|
|
211
|
+
return encoder;
|
|
212
|
+
}
|
|
213
|
+
// case "switch": {
|
|
214
|
+
// const dependencyValue = readObject[field.dependsOn];
|
|
215
|
+
// if (!dependencyValue) throw new MissingField(packetId, fieldName, field.dependsOn);
|
|
216
|
+
// for (const [value, type] of field.cases)
|
|
217
|
+
// if (dependencyValue === value)
|
|
218
|
+
// return this.readField(packetId, readObject, fieldName, type, encoder);
|
|
219
|
+
// if (field.default)
|
|
220
|
+
// return this.readField(packetId, readObject, fieldName, field.default, encoder);
|
|
221
|
+
// break;
|
|
222
|
+
// }
|
|
223
|
+
default:
|
|
224
|
+
throw new UnexpectedValue("encoding type", field.type);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|