@vaitosoi/minejs 0.6.0 → 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.
- package/README.md +23 -11
- package/assets/minecraft/26.2/packets.json +0 -12
- package/assets/minecraft/26.3/packets.json +228 -38
- package/dist/binary/encoder.d.ts.map +1 -1
- package/dist/binary/encoder.js +4 -4
- package/dist/binary/encoder.js.map +1 -1
- package/dist/client/client.d.ts +127 -28
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +108 -27
- package/dist/client/client.js.map +1 -1
- package/dist/net/tcp.d.ts +0 -7
- package/dist/net/tcp.d.ts.map +1 -1
- package/dist/net/tcp.js +12 -18
- package/dist/net/tcp.js.map +1 -1
- package/dist/packet/listener.d.ts +1 -1
- package/dist/packet/listener.d.ts.map +1 -1
- package/dist/packet/listener.js +142 -55
- package/dist/packet/listener.js.map +1 -1
- package/dist/packet/sender.d.ts +2 -1
- package/dist/packet/sender.d.ts.map +1 -1
- package/dist/packet/sender.js +17 -6
- package/dist/packet/sender.js.map +1 -1
- package/dist/physics/aabb.d.ts.map +1 -1
- package/dist/physics/aabb.js +10 -2
- package/dist/physics/aabb.js.map +1 -1
- package/dist/physics/direction.js +2 -2
- package/dist/physics/direction.js.map +1 -1
- package/dist/version/codec.d.ts.map +1 -1
- package/dist/version/codec.js +38 -0
- package/dist/version/codec.js.map +1 -1
- package/dist/version/registry.d.ts +6 -1
- package/dist/version/registry.d.ts.map +1 -1
- package/dist/version/registry.js +26 -3
- package/dist/version/registry.js.map +1 -1
- package/dist/world/block.d.ts +44 -2
- package/dist/world/block.d.ts.map +1 -1
- package/dist/world/block.js +61 -21
- package/dist/world/block.js.map +1 -1
- package/dist/world/entity.d.ts +3 -0
- package/dist/world/entity.d.ts.map +1 -1
- package/dist/world/entity.js +3 -0
- package/dist/world/entity.js.map +1 -1
- package/dist/world/state.d.ts +3 -0
- package/dist/world/state.d.ts.map +1 -1
- package/dist/world/state.js +9 -0
- package/dist/world/state.js.map +1 -1
- package/package.json +2 -2
- package/src/binary/encoder.ts +5 -6
- package/src/client/client.ts +174 -51
- package/src/net/tcp.ts +12 -18
- package/src/packet/listener.ts +172 -70
- package/src/packet/sender.ts +18 -7
- package/src/physics/aabb.ts +11 -2
- package/src/physics/direction.ts +2 -2
- package/src/version/codec.ts +32 -0
- package/src/version/registry.ts +35 -5
- package/src/world/block.ts +64 -22
- package/src/world/entity.ts +3 -0
- package/src/world/state.ts +10 -0
- package/test/client/index.ts +13 -6
package/src/packet/listener.ts
CHANGED
|
@@ -56,7 +56,7 @@ export class Listener {
|
|
|
56
56
|
"play:add_entity": this.handleSpawnEntity,
|
|
57
57
|
"play:move_entity_pos": this.handleUpdateEntityPosition,
|
|
58
58
|
"play:move_entity_pos_rot": this.handleUpdateEntityPositionRotation,
|
|
59
|
-
"play:entity_position_sync": this.
|
|
59
|
+
"play:entity_position_sync": this.handleEntityPositionSync,
|
|
60
60
|
"play:player_position": this.handleSynchronizePlayerPosition,
|
|
61
61
|
"play:update_mob_effect": this.handleUpdateMobEffect,
|
|
62
62
|
"play:remove_entities": this.handleRemoveEntity,
|
|
@@ -315,8 +315,8 @@ export class Listener {
|
|
|
315
315
|
angle: newAngle,
|
|
316
316
|
} satisfies ClientPlayer as any
|
|
317
317
|
);
|
|
318
|
-
this.state.enqueueEvent("playerPosition",
|
|
319
|
-
this.sender.sendConfirmTeleportation(teleport_id);
|
|
318
|
+
this.state.enqueueEvent("playerPosition", newPosition);
|
|
319
|
+
this.sender.sendConfirmTeleportation(teleport_id, newPosition, newAngle);
|
|
320
320
|
this.sender.sendPacket("move_player_pos_rot", {
|
|
321
321
|
x: newPosition.x,
|
|
322
322
|
feet_y: newPosition.y,
|
|
@@ -523,89 +523,191 @@ export class Listener {
|
|
|
523
523
|
this.state.enqueueEvent("spawnEntity", entity);
|
|
524
524
|
}
|
|
525
525
|
|
|
526
|
-
private
|
|
527
|
-
|
|
528
|
-
entity_id,
|
|
529
|
-
x,
|
|
530
|
-
y,
|
|
531
|
-
z,
|
|
532
|
-
velocity_x,
|
|
533
|
-
velocity_y,
|
|
534
|
-
velocity_z,
|
|
535
|
-
pitch,
|
|
536
|
-
yaw
|
|
537
|
-
} = zodParse(data, zod.object({
|
|
538
|
-
entity_id: zod.int(),
|
|
539
|
-
x: zod.number(),
|
|
540
|
-
y: zod.number(),
|
|
541
|
-
z: zod.number(),
|
|
542
|
-
velocity_x: zod.number(),
|
|
543
|
-
velocity_y: zod.number(),
|
|
544
|
-
velocity_z: zod.number(),
|
|
545
|
-
pitch: zod.number(),
|
|
546
|
-
yaw: zod.number(),
|
|
547
|
-
}));
|
|
526
|
+
private handleEntityPositionSync(data: object) {
|
|
527
|
+
if (this.state.getProtocolId() > 776) {
|
|
548
528
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
529
|
+
const {
|
|
530
|
+
entity_id,
|
|
531
|
+
linear,
|
|
532
|
+
stepped,
|
|
533
|
+
pitch,
|
|
534
|
+
yaw
|
|
535
|
+
} = zodParse(data, zod.object({
|
|
536
|
+
entity_id: zod.int(),
|
|
537
|
+
linear: zod.object({
|
|
538
|
+
x: zod.number(),
|
|
539
|
+
y: zod.number(),
|
|
540
|
+
z: zod.number(),
|
|
541
|
+
}).nullable(),
|
|
542
|
+
stepped: zod.object({
|
|
543
|
+
x: zod.number(),
|
|
544
|
+
y: zod.number(),
|
|
545
|
+
z: zod.number(),
|
|
546
|
+
tick_offset: zod.number()
|
|
547
|
+
}).array().nullable(),
|
|
548
|
+
pitch: zod.number(),
|
|
549
|
+
yaw: zod.number(),
|
|
550
|
+
}));
|
|
551
|
+
const { x, y, z } = linear ? linear : stepped![stepped!.length - 1]!;
|
|
552
|
+
|
|
553
|
+
if (entity_id in this.state.world!.entities) this.state.enqueueMutation(state => {
|
|
554
|
+
state.world!.entities[entity_id]!.position = { x, y, z };
|
|
555
|
+
state.world!.entities[entity_id]!.angle = { pitch, yaw };
|
|
556
|
+
});
|
|
557
|
+
this.state.enqueueEvent("updateEntity", entity_id);
|
|
558
|
+
} else {
|
|
559
|
+
const {
|
|
560
|
+
entity_id,
|
|
561
|
+
x,
|
|
562
|
+
y,
|
|
563
|
+
z,
|
|
564
|
+
velocity_x,
|
|
565
|
+
velocity_y,
|
|
566
|
+
velocity_z,
|
|
567
|
+
pitch,
|
|
568
|
+
yaw
|
|
569
|
+
} = zodParse(data, zod.object({
|
|
570
|
+
entity_id: zod.int(),
|
|
571
|
+
x: zod.number(),
|
|
572
|
+
y: zod.number(),
|
|
573
|
+
z: zod.number(),
|
|
574
|
+
velocity_x: zod.number(),
|
|
575
|
+
velocity_y: zod.number(),
|
|
576
|
+
velocity_z: zod.number(),
|
|
577
|
+
pitch: zod.number(),
|
|
578
|
+
yaw: zod.number(),
|
|
579
|
+
}));
|
|
580
|
+
|
|
581
|
+
if (entity_id in this.state.world!.entities) this.state.enqueueMutation(state => {
|
|
582
|
+
state.world!.entities[entity_id]!.position = { x, y, z };
|
|
583
|
+
state.world!.entities[entity_id]!.velocity = { x: velocity_x, y: velocity_y, z: velocity_z };
|
|
584
|
+
state.world!.entities[entity_id]!.angle = { pitch, yaw };
|
|
585
|
+
});
|
|
586
|
+
this.state.enqueueEvent("updateEntity", entity_id);
|
|
587
|
+
}
|
|
555
588
|
}
|
|
556
589
|
|
|
557
590
|
private handleUpdateEntityPosition(data: object) {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
591
|
+
if (this.state.getProtocolId() <= 776) { // Before 26.3
|
|
592
|
+
const {
|
|
593
|
+
entity_id,
|
|
594
|
+
delta_x,
|
|
595
|
+
delta_y,
|
|
596
|
+
delta_z
|
|
597
|
+
} = zodParse(data, zod.object({
|
|
598
|
+
entity_id: zod.number(),
|
|
599
|
+
delta_x: zod.number(),
|
|
600
|
+
delta_y: zod.number(),
|
|
601
|
+
delta_z: zod.number(),
|
|
602
|
+
}));
|
|
569
603
|
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
604
|
+
if (entity_id in this.state.world!.entities) this.state.enqueueMutation(state => {
|
|
605
|
+
let { x, y, z } = state.world!.entities[entity_id]!.position;
|
|
606
|
+
x += delta_x;
|
|
607
|
+
y += delta_y;
|
|
608
|
+
z += delta_z;
|
|
609
|
+
state.world!.entities[entity_id]!.position = { x, y, z };
|
|
610
|
+
});
|
|
611
|
+
this.state.enqueueEvent("updateEntity", entity_id);
|
|
612
|
+
} else {
|
|
613
|
+
const {
|
|
614
|
+
entity_id,
|
|
615
|
+
step,
|
|
616
|
+
steps
|
|
617
|
+
} = zodParse(data, zod.object({
|
|
618
|
+
entity_id: zod.number(),
|
|
619
|
+
step: zod.object({
|
|
620
|
+
delta_x: zod.number(),
|
|
621
|
+
delta_y: zod.number(),
|
|
622
|
+
delta_z: zod.number(),
|
|
623
|
+
}).nullable(),
|
|
624
|
+
steps: zod.object({
|
|
625
|
+
tick_offset: zod.number(),
|
|
626
|
+
delta_x: zod.number(),
|
|
627
|
+
delta_y: zod.number(),
|
|
628
|
+
delta_z: zod.number(),
|
|
629
|
+
}).array().nullable()
|
|
630
|
+
}));
|
|
631
|
+
const { delta_x, delta_y, delta_z } = step ? step : steps![steps!.length - 1]!;
|
|
579
632
|
|
|
580
|
-
|
|
581
|
-
const {
|
|
582
|
-
entity_id,
|
|
583
|
-
delta_x,
|
|
584
|
-
delta_y,
|
|
585
|
-
delta_z,
|
|
586
|
-
pitch,
|
|
587
|
-
yaw
|
|
588
|
-
} = zodParse(data, zod.object({
|
|
589
|
-
entity_id: zod.number(),
|
|
590
|
-
delta_x: zod.number(),
|
|
591
|
-
delta_y: zod.number(),
|
|
592
|
-
delta_z: zod.number(),
|
|
593
|
-
pitch: zod.number(),
|
|
594
|
-
yaw: zod.number(),
|
|
595
|
-
}));
|
|
596
|
-
if (entity_id in this.state.world!.entities) {
|
|
597
|
-
this.state.enqueueMutation(state => {
|
|
633
|
+
if (entity_id in this.state.world!.entities) this.state.enqueueMutation(state => {
|
|
598
634
|
let { x, y, z } = state.world!.entities[entity_id]!.position;
|
|
599
635
|
x += delta_x;
|
|
600
636
|
y += delta_y;
|
|
601
637
|
z += delta_z;
|
|
602
638
|
state.world!.entities[entity_id]!.position = { x, y, z };
|
|
603
|
-
state.world!.entities[entity_id]!.angle = { yaw, pitch };
|
|
604
639
|
});
|
|
605
640
|
this.state.enqueueEvent("updateEntity", entity_id);
|
|
606
641
|
}
|
|
607
642
|
}
|
|
608
643
|
|
|
644
|
+
private handleUpdateEntityPositionRotation(data: object) {
|
|
645
|
+
if (this.state.getProtocolId() <= 776) { // Before 26.3
|
|
646
|
+
const {
|
|
647
|
+
entity_id,
|
|
648
|
+
delta_x,
|
|
649
|
+
delta_y,
|
|
650
|
+
delta_z,
|
|
651
|
+
pitch,
|
|
652
|
+
yaw
|
|
653
|
+
} = zodParse(data, zod.object({
|
|
654
|
+
entity_id: zod.number(),
|
|
655
|
+
delta_x: zod.number(),
|
|
656
|
+
delta_y: zod.number(),
|
|
657
|
+
delta_z: zod.number(),
|
|
658
|
+
pitch: zod.number(),
|
|
659
|
+
yaw: zod.number(),
|
|
660
|
+
}));
|
|
661
|
+
if (entity_id in this.state.world!.entities) {
|
|
662
|
+
this.state.enqueueMutation(state => {
|
|
663
|
+
let { x, y, z } = state.world!.entities[entity_id]!.position;
|
|
664
|
+
x += delta_x;
|
|
665
|
+
y += delta_y;
|
|
666
|
+
z += delta_z;
|
|
667
|
+
state.world!.entities[entity_id]!.position = { x, y, z };
|
|
668
|
+
state.world!.entities[entity_id]!.angle = { yaw, pitch };
|
|
669
|
+
});
|
|
670
|
+
this.state.enqueueEvent("updateEntity", entity_id);
|
|
671
|
+
}
|
|
672
|
+
} else {
|
|
673
|
+
const {
|
|
674
|
+
entity_id,
|
|
675
|
+
step,
|
|
676
|
+
steps,
|
|
677
|
+
pitch,
|
|
678
|
+
yaw
|
|
679
|
+
} = zodParse(data, zod.object({
|
|
680
|
+
entity_id: zod.number(),
|
|
681
|
+
step: zod.object({
|
|
682
|
+
delta_x: zod.number(),
|
|
683
|
+
delta_y: zod.number(),
|
|
684
|
+
delta_z: zod.number(),
|
|
685
|
+
}).nullable(),
|
|
686
|
+
steps: zod.object({
|
|
687
|
+
tick_offset: zod.number(),
|
|
688
|
+
delta_x: zod.number(),
|
|
689
|
+
delta_y: zod.number(),
|
|
690
|
+
delta_z: zod.number(),
|
|
691
|
+
}).array().nullable(),
|
|
692
|
+
pitch: zod.number(),
|
|
693
|
+
yaw: zod.number(),
|
|
694
|
+
}));
|
|
695
|
+
const { delta_x, delta_y, delta_z } = step ? step : steps![steps!.length - 1]!;
|
|
696
|
+
|
|
697
|
+
if (entity_id in this.state.world!.entities) {
|
|
698
|
+
this.state.enqueueMutation(state => {
|
|
699
|
+
let { x, y, z } = state.world!.entities[entity_id]!.position;
|
|
700
|
+
x += delta_x;
|
|
701
|
+
y += delta_y;
|
|
702
|
+
z += delta_z;
|
|
703
|
+
state.world!.entities[entity_id]!.position = { x, y, z };
|
|
704
|
+
state.world!.entities[entity_id]!.angle = { yaw, pitch };
|
|
705
|
+
});
|
|
706
|
+
this.state.enqueueEvent("updateEntity", entity_id);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
609
711
|
private handleSetEntityVelocity(data: object) {
|
|
610
712
|
const { entity_id, velocity } = zodParse(data, zod.object({
|
|
611
713
|
entity_id: zod.number(),
|
package/src/packet/sender.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { ClientStatus, ConnectionState, ServerKnownPack, SharedState } from "../
|
|
|
6
6
|
import { sliceBuffer } from "../base/buffer";
|
|
7
7
|
import { randomUUIDBytes } from "../base/math";
|
|
8
8
|
import { Angle, BaseVec3, Direction } from "../physics/direction";
|
|
9
|
-
import { MessageTooLong, NotImplemented } from "../base/error";
|
|
9
|
+
import { MessageTooLong, MissingField, NotImplemented } from "../base/error";
|
|
10
10
|
import BitSet from "../base/bitset";
|
|
11
11
|
import { makeMovementFlag } from "../binary/encoder";
|
|
12
12
|
import { BlockFace } from "../world/block";
|
|
@@ -98,10 +98,22 @@ export class Sender {
|
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
public sendConfirmTeleportation(teleportId: number)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
101
|
+
public sendConfirmTeleportation(teleportId: number): void;
|
|
102
|
+
public sendConfirmTeleportation(teleportId: number, newPos: BaseVec3, newAngle: Angle): void;
|
|
103
|
+
public sendConfirmTeleportation(teleportId: number, newPos?: BaseVec3, newAngle?: Angle) {
|
|
104
|
+
if (this.state.getProtocolId() > 776) {
|
|
105
|
+
if (!newPos || !newAngle) throw new MissingField("newPos or newAngle", "confirm_teleportation packet on version 26.3 or over");
|
|
106
|
+
const { x, y, z } = newPos,
|
|
107
|
+
{ yaw, pitch } = newAngle;
|
|
108
|
+
this.sendPacket("accept_teleportation", {
|
|
109
|
+
teleport_id: teleportId,
|
|
110
|
+
x, y, z,
|
|
111
|
+
yaw, pitch
|
|
112
|
+
});
|
|
113
|
+
} else
|
|
114
|
+
this.sendPacket("accept_teleportation", {
|
|
115
|
+
teleport_id: teleportId
|
|
116
|
+
});
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
public sendKeepAlive(id: bigint) {
|
|
@@ -185,7 +197,6 @@ export class Sender {
|
|
|
185
197
|
cursorPositionOnBlock: BaseVec3,
|
|
186
198
|
isInsideBlock: boolean,
|
|
187
199
|
worldBorderHit: boolean,
|
|
188
|
-
sequence: number = randomInt(1024),
|
|
189
200
|
) {
|
|
190
201
|
const face_ = (face instanceof Direction ? face.index3D : face) as number;
|
|
191
202
|
this.sendPacket("use_item_on", {
|
|
@@ -197,7 +208,7 @@ export class Sender {
|
|
|
197
208
|
cursor_position_z: cursorPositionOnBlock.z,
|
|
198
209
|
inside_block: isInsideBlock,
|
|
199
210
|
world_border_hit: worldBorderHit,
|
|
200
|
-
sequence
|
|
211
|
+
sequence: this.state.nextSequence()
|
|
201
212
|
});
|
|
202
213
|
}
|
|
203
214
|
}
|
package/src/physics/aabb.ts
CHANGED
|
@@ -585,13 +585,22 @@ export class VoxelShape {
|
|
|
585
585
|
}
|
|
586
586
|
private forAllBoxes(consumer: (bb: BaseAABB) => void, mergeNeighbor: boolean) {
|
|
587
587
|
const shape = this.copy();
|
|
588
|
+
const consumerWithRawInd = (bb: BaseAABB) =>
|
|
589
|
+
consumer({
|
|
590
|
+
minX: shape.xs[bb.minX]!,
|
|
591
|
+
maxX: shape.xs[bb.maxX]!,
|
|
592
|
+
minY: shape.ys[bb.minY]!,
|
|
593
|
+
maxY: shape.ys[bb.maxY]!,
|
|
594
|
+
minZ: shape.zs[bb.minZ]!,
|
|
595
|
+
maxZ: shape.zs[bb.maxZ]!
|
|
596
|
+
});
|
|
588
597
|
for (let y = 0; y < shape.getSize(BaseAxis.Y); y++)
|
|
589
598
|
for (let x = 0; x < shape.getSize(BaseAxis.X); x++) {
|
|
590
599
|
let lastStartZ = -1;
|
|
591
600
|
for (let z = 0; z <= shape.getSize(BaseAxis.Z); z++) {
|
|
592
601
|
if (shape.isFullWide(x, y, z)) {
|
|
593
602
|
if (!mergeNeighbor)
|
|
594
|
-
|
|
603
|
+
consumerWithRawInd({
|
|
595
604
|
minX: x,
|
|
596
605
|
maxX: x + 1,
|
|
597
606
|
minY: y,
|
|
@@ -615,7 +624,7 @@ export class VoxelShape {
|
|
|
615
624
|
}
|
|
616
625
|
endY++;
|
|
617
626
|
}
|
|
618
|
-
|
|
627
|
+
consumerWithRawInd({
|
|
619
628
|
minX: x,
|
|
620
629
|
maxX: endX + 1,
|
|
621
630
|
minY: y,
|
package/src/physics/direction.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class Vec3 implements BaseVec3 {
|
|
|
17
17
|
* Helper function for loading vec3 args
|
|
18
18
|
*/
|
|
19
19
|
static loadArgs(a: BaseVec3 | number, b?: number, c?: number): BaseVec3 {
|
|
20
|
-
let x =
|
|
20
|
+
let x = 0, y = 0, z = 0;
|
|
21
21
|
if (typeof a === "object" && "x" in a) {
|
|
22
22
|
x = a.x;
|
|
23
23
|
y = a.y;
|
|
@@ -114,7 +114,7 @@ export class Vec3 implements BaseVec3 {
|
|
|
114
114
|
public multiply(x: number, y: number, z: number): Vec3;
|
|
115
115
|
public multiply(a: BaseVec3 | number, b?: number, c?: number) {
|
|
116
116
|
let vec: BaseVec3;
|
|
117
|
-
if ((a && b && c) || (typeof a === "object" && "x" in a)) vec = Vec3.loadArgs(a, b, c);
|
|
117
|
+
if ((a !== undefined && b !== undefined && c !== undefined) || (typeof a === "object" && "x" in a)) vec = Vec3.loadArgs(a, b, c);
|
|
118
118
|
else vec = { x: a, y: a, z: a };
|
|
119
119
|
const x = this.x * vec.x;
|
|
120
120
|
const y = this.y * vec.y;
|
package/src/version/codec.ts
CHANGED
|
@@ -112,6 +112,21 @@ export class VersionCodec {
|
|
|
112
112
|
field: FieldNode,
|
|
113
113
|
decoder: BinaryDecoder
|
|
114
114
|
): any {
|
|
115
|
+
// if (
|
|
116
|
+
// this.state.clientOptions.debug &&
|
|
117
|
+
// this.state.clientOptions.debug.packetLogger &&
|
|
118
|
+
// (
|
|
119
|
+
// (Array.isArray(this.state.clientOptions.debug.ignoreTCPPacketLogs) && !this.state.clientOptions.debug.ignoreTCPPacketLogs.includes(packetId)) ||
|
|
120
|
+
// (!this.state.clientOptions.debug.ignoreTCPPacketLogs)
|
|
121
|
+
// )
|
|
122
|
+
// )
|
|
123
|
+
// console.dir({
|
|
124
|
+
// packetId,
|
|
125
|
+
// readObject,
|
|
126
|
+
// fieldName,
|
|
127
|
+
// field,
|
|
128
|
+
// decoder
|
|
129
|
+
// }, { depth: null });
|
|
115
130
|
switch (field.type) {
|
|
116
131
|
case "string": return decoder.readString();
|
|
117
132
|
case "boolean": return decoder.readBoolean();
|
|
@@ -186,6 +201,23 @@ export class VersionCodec {
|
|
|
186
201
|
throw new SkippableNotImplemented();
|
|
187
202
|
throw new NotImplemented();
|
|
188
203
|
}
|
|
204
|
+
case "infer": {
|
|
205
|
+
const args = field.args?.map(val =>
|
|
206
|
+
typeof val === "number"
|
|
207
|
+
? val
|
|
208
|
+
: val.startsWith("literal:")
|
|
209
|
+
? val.slice(8)
|
|
210
|
+
: readObject[val]
|
|
211
|
+
) || [];
|
|
212
|
+
let func: (...args: any[]) => any = () => undefined;
|
|
213
|
+
switch (field.function) {
|
|
214
|
+
case "bit_and": func = (a: number, b: number) => a & b; break;
|
|
215
|
+
case "bit_or": func = (a: number, b: number) => a | b; break;
|
|
216
|
+
case "shift_left": func = (val: number, pos: number) => val << pos; break;
|
|
217
|
+
case "shift_right": func = (val: number, pos: number) => val >>> pos; break;
|
|
218
|
+
}
|
|
219
|
+
return func(...args);
|
|
220
|
+
}
|
|
189
221
|
case "switch": {
|
|
190
222
|
if (!(field.dependsOn in readObject)) throw new MissingPacketField(packetId, fieldName, field.dependsOn);
|
|
191
223
|
const dependencyValue = readObject[field.dependsOn];
|
package/src/version/registry.ts
CHANGED
|
@@ -204,6 +204,7 @@ export const SupportTypes = z.enum([
|
|
|
204
204
|
"slot",
|
|
205
205
|
"null", // a constant
|
|
206
206
|
"special",
|
|
207
|
+
"infer",
|
|
207
208
|
|
|
208
209
|
/**
|
|
209
210
|
* This is used for handle field that its type depends on previous field type, or value
|
|
@@ -226,6 +227,7 @@ export type FieldNode = ({
|
|
|
226
227
|
| "fixed_bitset"
|
|
227
228
|
| "byte_array"
|
|
228
229
|
| "special"
|
|
230
|
+
| "infer"
|
|
229
231
|
>,
|
|
230
232
|
} | {
|
|
231
233
|
type: "not_implemented",
|
|
@@ -262,13 +264,32 @@ export type FieldNode = ({
|
|
|
262
264
|
} | {
|
|
263
265
|
type: "special",
|
|
264
266
|
comment: string,
|
|
267
|
+
} | { // Call a function
|
|
268
|
+
type: "infer",
|
|
269
|
+
args?: (string | number)[] | undefined,
|
|
270
|
+
function: string
|
|
265
271
|
}) & {
|
|
266
272
|
skip_able?: boolean | undefined
|
|
267
273
|
}
|
|
268
274
|
/** @hidden */
|
|
269
275
|
export const Field: z.ZodType<FieldNode> = z.union([
|
|
270
276
|
z.object({
|
|
271
|
-
type: SupportTypes.exclude([
|
|
277
|
+
type: SupportTypes.exclude([
|
|
278
|
+
"prefixed_array",
|
|
279
|
+
"prefixed_optional",
|
|
280
|
+
"string",
|
|
281
|
+
"id_or_x",
|
|
282
|
+
"array",
|
|
283
|
+
"switch",
|
|
284
|
+
"fixed_point",
|
|
285
|
+
"enum",
|
|
286
|
+
"not_implemented",
|
|
287
|
+
"object",
|
|
288
|
+
"fixed_bitset",
|
|
289
|
+
"byte_array",
|
|
290
|
+
"special",
|
|
291
|
+
"infer"
|
|
292
|
+
]),
|
|
272
293
|
}),
|
|
273
294
|
z.object({
|
|
274
295
|
type: z.literal(["not_implemented"]),
|
|
@@ -290,7 +311,9 @@ export const Field: z.ZodType<FieldNode> = z.union([
|
|
|
290
311
|
length: z.number().optional()
|
|
291
312
|
}),
|
|
292
313
|
z.object({
|
|
293
|
-
type: z.literal(["id_or_x",
|
|
314
|
+
type: z.literal(["id_or_x",
|
|
315
|
+
"enum",
|
|
316
|
+
"prefixed_optional"]),
|
|
294
317
|
/**
|
|
295
318
|
* For case like `Array<subType>` or `PrefixedOptional<subType>`
|
|
296
319
|
*/
|
|
@@ -344,9 +367,14 @@ export const Field: z.ZodType<FieldNode> = z.union([
|
|
|
344
367
|
length: z.int()
|
|
345
368
|
}),
|
|
346
369
|
z.object({
|
|
347
|
-
type: z.literal(
|
|
370
|
+
type: z.literal("special"),
|
|
348
371
|
comment: z.string()
|
|
349
372
|
}),
|
|
373
|
+
z.object({
|
|
374
|
+
type: z.literal("infer"),
|
|
375
|
+
args: z.string().or(z.number()).array().optional(),
|
|
376
|
+
function: z.string(),
|
|
377
|
+
})
|
|
350
378
|
])
|
|
351
379
|
.and(
|
|
352
380
|
z.object({
|
|
@@ -398,7 +426,8 @@ export class PacketRegistry {
|
|
|
398
426
|
if (this.loaded) return;
|
|
399
427
|
this.loaded = true;
|
|
400
428
|
|
|
401
|
-
const json = getFile(version,
|
|
429
|
+
const json = getFile(version,
|
|
430
|
+
"packets") as Record<string, any>;
|
|
402
431
|
|
|
403
432
|
const definition = VersionDefinitions.parse(json);
|
|
404
433
|
for (const [stateKey, state] of Object.entries(definition)) {
|
|
@@ -427,7 +456,8 @@ export class PacketRegistry {
|
|
|
427
456
|
numbericId = parseInt(id, 16);
|
|
428
457
|
else numbericId = id;
|
|
429
458
|
if (isNaN(numbericId))
|
|
430
|
-
throw new UnexpectedValue("valid packet id", id.toString(),
|
|
459
|
+
throw new UnexpectedValue("valid packet id", id.toString(),
|
|
460
|
+
"name or number or hex");
|
|
431
461
|
else
|
|
432
462
|
return this.definition[state][type]["0x" + numbericId.toString(16).toUpperCase()];
|
|
433
463
|
}
|
package/src/world/block.ts
CHANGED
|
@@ -44,6 +44,10 @@ export class BlockState {
|
|
|
44
44
|
if (defaultVal) return defaultVal;
|
|
45
45
|
return null;
|
|
46
46
|
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get the block facing
|
|
50
|
+
*/
|
|
47
51
|
public getFacing(): "north" | "south" | "west" | "east" | null { return this.get("facing"); }
|
|
48
52
|
}
|
|
49
53
|
|
|
@@ -51,6 +55,9 @@ export class BlockState {
|
|
|
51
55
|
* Represent a block
|
|
52
56
|
*/
|
|
53
57
|
export class Block {
|
|
58
|
+
/**
|
|
59
|
+
* A block will have multiple states (example: a stair will have difference facing).
|
|
60
|
+
*/
|
|
54
61
|
public states: BlockState[];
|
|
55
62
|
|
|
56
63
|
constructor(
|
|
@@ -74,16 +81,46 @@ export class Block {
|
|
|
74
81
|
if (defaultVal) return defaultVal;
|
|
75
82
|
return null;
|
|
76
83
|
}
|
|
77
|
-
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the block type.
|
|
87
|
+
*
|
|
88
|
+
* A block type will contain multiple blocks, like type `wall_sign` will have
|
|
89
|
+
* `oak_wall_sign`, `spruce_wall_sign`, `acacia_wall_sign`, etc...
|
|
90
|
+
*/
|
|
91
|
+
public getType() { return this.get<string>("type")!; }
|
|
92
|
+
/**
|
|
93
|
+
* Get the block friction.
|
|
94
|
+
*
|
|
95
|
+
* By default, block friction is 0.6, except for ice block family.
|
|
96
|
+
*/
|
|
78
97
|
public getFriction() { return this.get("friction", 0.6); }
|
|
98
|
+
/**
|
|
99
|
+
* Get the block bounciness.
|
|
100
|
+
*
|
|
101
|
+
* By default, block friction is 0, except for slime block.
|
|
102
|
+
*/
|
|
79
103
|
public getBounciness() { return this.get("bounciness", 0); }
|
|
104
|
+
/**
|
|
105
|
+
* Get the block speed factor.
|
|
106
|
+
*
|
|
107
|
+
* By default, block friction is 1, except for soul sand block.
|
|
108
|
+
*/
|
|
80
109
|
public getSpeedFactor() { return this.get("speed_factor", 1); }
|
|
110
|
+
/**
|
|
111
|
+
* Check if the block is climable.
|
|
112
|
+
*
|
|
113
|
+
* By default, block friction is false, except for ladder and vine.
|
|
114
|
+
*/
|
|
81
115
|
public getClimbable() { return this.get("climbable", false); }
|
|
116
|
+
/**
|
|
117
|
+
* Get the block jump factor.
|
|
118
|
+
*/
|
|
82
119
|
public getJumpFactor() { return this.get("jump_factor", 1); }
|
|
83
120
|
}
|
|
84
121
|
|
|
85
122
|
/**
|
|
86
|
-
*
|
|
123
|
+
* This class is for fetching blocks and chunks data.
|
|
87
124
|
*/
|
|
88
125
|
export class BlockManager {
|
|
89
126
|
constructor(private state: SharedState) { }
|
|
@@ -115,7 +152,9 @@ export class BlockManager {
|
|
|
115
152
|
this.state.checkReady();
|
|
116
153
|
let { x, y, z } = Vec3.loadArgs(a, b, c);
|
|
117
154
|
x = Math.floor(x); y = Math.floor(y); z = Math.floor(z);
|
|
155
|
+
// Chunk position
|
|
118
156
|
const sx = Math.floor(x / 16), sy = Math.floor((y + 64) / 16), sz = Math.floor(z / 16);
|
|
157
|
+
// Block position within the chunk
|
|
119
158
|
const px = ((x % 16) + 16) % 16, py = ((y % 16) + 16) % 16, pz = ((z % 16) + 16) % 16;
|
|
120
159
|
|
|
121
160
|
if (this.state.cache)
|
|
@@ -166,6 +205,13 @@ export class BlockManager {
|
|
|
166
205
|
const state = arr.at(this.getLocalPosKey(localPos))!;
|
|
167
206
|
return this.getBlock(state);
|
|
168
207
|
}
|
|
208
|
+
/**
|
|
209
|
+
* Delete the chunk cache
|
|
210
|
+
*
|
|
211
|
+
* @param sx chunk x
|
|
212
|
+
* @param sy section y
|
|
213
|
+
* @param sz chunk z
|
|
214
|
+
*/
|
|
169
215
|
public deleteChunkCache(
|
|
170
216
|
sx: number, sy: number, sz: number,
|
|
171
217
|
) {
|
|
@@ -193,7 +239,6 @@ export class BlockManager {
|
|
|
193
239
|
const stateId = bitsPerEntry <= 8 ? section.palette[localId]! : localId;
|
|
194
240
|
|
|
195
241
|
return BlockRegistry.getState(String(stateId));
|
|
196
|
-
|
|
197
242
|
}
|
|
198
243
|
private getLocalPosKey(pos: BaseVec3) {
|
|
199
244
|
return pos.x + 16 * (pos.y + 16 * pos.z);
|
|
@@ -255,8 +300,6 @@ export class BlockGetter {
|
|
|
255
300
|
consumer: (context: C, position: BaseVec3) => T,
|
|
256
301
|
missFactory: (context: C) => T
|
|
257
302
|
): T {
|
|
258
|
-
let result: T;
|
|
259
|
-
|
|
260
303
|
if (from.equal(to)) return missFactory(context);
|
|
261
304
|
const toX = lerp(-Epsilon, to.x, from.x);
|
|
262
305
|
const toY = lerp(-Epsilon, to.y, from.y);
|
|
@@ -281,29 +324,28 @@ export class BlockGetter {
|
|
|
281
324
|
let tX = signX === 0 ? Infinity : tDeltaX * (signX > 0 ? 1 - getFrac(fromX) : getFrac(fromX));
|
|
282
325
|
let tY = signY === 0 ? Infinity : tDeltaY * (signY > 0 ? 1 - getFrac(fromY) : getFrac(fromY));
|
|
283
326
|
let tZ = signZ === 0 ? Infinity : tDeltaZ * (signZ > 0 ? 1 - getFrac(fromZ) : getFrac(fromZ));
|
|
284
|
-
|
|
285
|
-
if (tX
|
|
286
|
-
if (tX <
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
tX += tDeltaX;
|
|
290
|
-
} else {
|
|
291
|
-
currentBlockZ += signZ;
|
|
292
|
-
tZ += tDeltaZ;
|
|
293
|
-
}
|
|
294
|
-
} else if (tY < tZ) {
|
|
295
|
-
currentBlockY += signY;
|
|
296
|
-
tY += tDeltaY;
|
|
327
|
+
while (tX <= 1.0 || tY <= 1.0 || tZ <= 1.0) {
|
|
328
|
+
if (tX < tY) {
|
|
329
|
+
if (tX < tZ) {
|
|
330
|
+
currentBlockX += signX;
|
|
331
|
+
tX += tDeltaX;
|
|
297
332
|
} else {
|
|
298
333
|
currentBlockZ += signZ;
|
|
299
334
|
tZ += tDeltaZ;
|
|
300
335
|
}
|
|
301
|
-
|
|
336
|
+
} else if (tY < tZ) {
|
|
337
|
+
currentBlockY += signY;
|
|
338
|
+
tY += tDeltaY;
|
|
302
339
|
} else {
|
|
303
|
-
|
|
340
|
+
currentBlockZ += signZ;
|
|
341
|
+
tZ += tDeltaZ;
|
|
304
342
|
}
|
|
305
|
-
|
|
306
|
-
|
|
343
|
+
const result = consumer(context, { x: currentBlockX, y: currentBlockY, z: currentBlockZ });
|
|
344
|
+
|
|
345
|
+
if (result !== null)
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
return missFactory(context);
|
|
307
349
|
}
|
|
308
350
|
}
|
|
309
351
|
|