@vaitosoi/minejs 0.4.2 → 0.5.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.
- package/README.md +53 -5
- package/assets/doc/rejected.png +0 -0
- package/assets/minecraft/26.2/effects.json +42 -0
- package/assets/minecraft/26.2/packets.json +3 -2
- package/dist/base/bitset.d.ts +43 -4
- package/dist/base/bitset.d.ts.map +1 -1
- package/dist/base/bitset.js +251 -30
- package/dist/base/bitset.js.map +1 -1
- package/dist/base/cache.d.ts +24 -0
- package/dist/base/cache.d.ts.map +1 -0
- package/dist/base/cache.js +58 -0
- package/dist/base/cache.js.map +1 -0
- package/dist/base/error.d.ts +13 -0
- package/dist/base/error.d.ts.map +1 -1
- package/dist/base/error.js +19 -1
- package/dist/base/error.js.map +1 -1
- package/dist/base/math.d.ts +12 -0
- package/dist/base/math.d.ts.map +1 -1
- package/dist/base/math.js +39 -0
- package/dist/base/math.js.map +1 -1
- package/dist/base/typing.d.ts +7 -0
- package/dist/base/typing.d.ts.map +1 -1
- package/dist/{packet → binary}/decoder.d.ts.map +1 -1
- package/dist/{packet → binary}/decoder.js.map +1 -1
- package/dist/{packet → binary}/encoder.d.ts +2 -2
- package/dist/binary/encoder.d.ts.map +1 -0
- package/dist/{packet → binary}/encoder.js +6 -2
- package/dist/binary/encoder.js.map +1 -0
- package/dist/{packet → binary}/static.d.ts.map +1 -1
- package/dist/{packet → binary}/static.js.map +1 -1
- package/dist/client/client.d.ts +23 -2
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +34 -19
- package/dist/client/client.js.map +1 -1
- package/dist/index.d.ts +12 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -4
- package/dist/index.js.map +1 -1
- package/dist/{client → net}/tcp.d.ts +2 -2
- package/dist/net/tcp.d.ts.map +1 -0
- package/dist/{client → net}/tcp.js +4 -2
- package/dist/net/tcp.js.map +1 -0
- package/dist/packet/{dispatcher.d.ts → listener.d.ts} +7 -18
- package/dist/packet/listener.d.ts.map +1 -0
- package/dist/packet/{dispatcher.js → listener.js} +73 -139
- package/dist/packet/listener.js.map +1 -0
- package/dist/packet/sender.d.ts +25 -0
- package/dist/packet/sender.d.ts.map +1 -0
- package/dist/packet/sender.js +144 -0
- package/dist/packet/sender.js.map +1 -0
- package/dist/physics/aabb.d.ts.map +1 -1
- package/dist/physics/aabb.js +9 -8
- package/dist/physics/aabb.js.map +1 -1
- package/dist/physics/player.d.ts +1 -0
- package/dist/physics/player.d.ts.map +1 -1
- package/dist/physics/player.js +22 -4
- package/dist/physics/player.js.map +1 -1
- package/dist/version/codec.d.ts +1 -1
- package/dist/version/codec.d.ts.map +1 -1
- package/dist/version/codec.js +28 -6
- package/dist/version/codec.js.map +1 -1
- package/dist/version/registry.d.ts +19 -2
- package/dist/version/registry.d.ts.map +1 -1
- package/dist/version/registry.js +35 -3
- package/dist/version/registry.js.map +1 -1
- package/dist/world/block.d.ts +5 -0
- package/dist/world/block.d.ts.map +1 -1
- package/dist/world/block.js +56 -0
- package/dist/world/block.js.map +1 -1
- package/dist/world/state.d.ts +22 -3
- package/dist/world/state.d.ts.map +1 -1
- package/dist/world/state.js +36 -12
- package/dist/world/state.js.map +1 -1
- package/package.json +8 -10
- package/src/base/bitset.ts +312 -31
- package/src/base/cache.ts +62 -0
- package/src/base/error.ts +16 -0
- package/src/base/math.ts +43 -1
- package/src/base/typing.ts +5 -0
- package/src/{packet → binary}/encoder.ts +6 -2
- package/src/client/client.ts +56 -23
- package/src/index.ts +12 -4
- package/src/{client → net}/tcp.ts +5 -3
- package/src/packet/{dispatcher.ts → listener.ts} +92 -177
- package/src/packet/sender.ts +176 -0
- package/src/physics/aabb.ts +9 -8
- package/src/physics/player.ts +20 -5
- package/src/version/codec.ts +29 -8
- package/src/version/registry.ts +58 -5
- package/src/world/block.ts +72 -2
- package/src/world/state.ts +59 -14
- package/test/bitset/index.ts +3 -8
- package/test/client/index.ts +23 -13
- package/test/state/index.ts +7 -0
- package/dist/client/tcp.d.ts.map +0 -1
- package/dist/client/tcp.js.map +0 -1
- package/dist/packet/dispatcher.d.ts.map +0 -1
- package/dist/packet/dispatcher.js.map +0 -1
- package/dist/packet/encoder.d.ts.map +0 -1
- package/dist/packet/encoder.js.map +0 -1
- /package/dist/{packet → binary}/decoder.d.ts +0 -0
- /package/dist/{packet → binary}/decoder.js +0 -0
- /package/dist/{packet → binary}/static.d.ts +0 -0
- /package/dist/{packet → binary}/static.js +0 -0
- /package/src/{packet → binary}/decoder.ts +0 -0
- /package/src/{packet → binary}/static.ts +0 -0
package/src/client/client.ts
CHANGED
|
@@ -3,17 +3,19 @@ import { 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";
|
|
6
|
-
import { Message, TCPClient, TCPClientOption } from "
|
|
6
|
+
import { Message, TCPClient, TCPClientOption } from "../net/tcp";
|
|
7
7
|
import { TypedEmmiter as TypedEmitter } from "../base/event";
|
|
8
|
-
import { BlockRegistry, EntityRegistry, PacketRegistry, ProtocolVersionMapping } from "../version/registry";
|
|
8
|
+
import { BlockRegistry, EffectRegistry, EntityRegistry, PacketRegistry, ProtocolVersionMapping } from "../version/registry";
|
|
9
9
|
import { BaseVec3, Vec3 } from "../physics/direction";
|
|
10
|
-
import { TextComponent } from "../base/typing";
|
|
10
|
+
import { RegistryData, TextComponent } from "../base/typing";
|
|
11
11
|
import { ClientStatus, ConnectionState, EmittedEvent as EmittedEvent, Entity, SharedState } from "../world/state";
|
|
12
|
-
import {
|
|
12
|
+
import { Listener } from "../packet/listener";
|
|
13
13
|
import { VersionCodec } from "../version/codec";
|
|
14
14
|
import { AuthClient } from "./auth";
|
|
15
15
|
import { computeUUID } from "../base/math";
|
|
16
16
|
import { HaveSignatureButNotIndex } from "../base/error";
|
|
17
|
+
import { Sender } from "../packet/sender";
|
|
18
|
+
import { CacheImplementation } from "../base/cache";
|
|
17
19
|
|
|
18
20
|
export type ClientOption = Omit<TCPClientOption, "protocolVersion"> & {
|
|
19
21
|
version: string,
|
|
@@ -23,12 +25,26 @@ export type ClientOption = Omit<TCPClientOption, "protocolVersion"> & {
|
|
|
23
25
|
*
|
|
24
26
|
* When set this option to true, you HAVE TO set `shouldVerifyMessageOrder` to true
|
|
25
27
|
*/
|
|
26
|
-
shouldVerifyMessageSignature?: boolean
|
|
28
|
+
shouldVerifyMessageSignature?: boolean,
|
|
27
29
|
|
|
28
30
|
/**
|
|
29
31
|
* Should verify the message orders to keep the sync with server.
|
|
30
32
|
*/
|
|
31
|
-
shouldVerifyMessageOrder?: boolean
|
|
33
|
+
shouldVerifyMessageOrder?: boolean,
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Whether to load the whole chunk section (16x16x16) and keep them in the cache or just load the needed block.
|
|
37
|
+
*
|
|
38
|
+
* Please consider this carefully since this can consume a lot of resource to calculate the whole chunk section and store it while you may not need that much.
|
|
39
|
+
*
|
|
40
|
+
* This option is useful when you have to constantly access to the world chunk, e.g pathfinding.
|
|
41
|
+
*/
|
|
42
|
+
loadAndCacheChunk?: boolean,
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Custom cache class. Default to `LRUCache`
|
|
46
|
+
*/
|
|
47
|
+
cacheImplementation?: new () => CacheImplementation<Uint16Array>,
|
|
32
48
|
}
|
|
33
49
|
|
|
34
50
|
export interface ClientEvents {
|
|
@@ -71,6 +87,8 @@ export interface ClientEvents {
|
|
|
71
87
|
updateEntity: [entityId: number],
|
|
72
88
|
/** When an entity go out of client view distance or despawned */
|
|
73
89
|
removeEntity: [entityId: number],
|
|
90
|
+
/** The registry_data packet */
|
|
91
|
+
registryData: [data: RegistryData],
|
|
74
92
|
|
|
75
93
|
// Chat
|
|
76
94
|
/** When a chat message got broadcasted */
|
|
@@ -101,6 +119,8 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
|
|
|
101
119
|
|
|
102
120
|
private tcp: TCPClient;
|
|
103
121
|
private state: SharedState<IsReady>;
|
|
122
|
+
private packetListener: Listener;
|
|
123
|
+
private packetSender: Sender;
|
|
104
124
|
|
|
105
125
|
constructor(private options: ClientOption) {
|
|
106
126
|
if (options.shouldVerifyMessageSignature === true && options.shouldVerifyMessageOrder !== true)
|
|
@@ -111,7 +131,8 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
|
|
|
111
131
|
// For managing shared data
|
|
112
132
|
this.state = new SharedState(options);
|
|
113
133
|
// For handling packet
|
|
114
|
-
|
|
134
|
+
this.packetSender = new Sender(this.state, this.emit.bind(this));
|
|
135
|
+
this.packetListener = new Listener(this.state, this.emit.bind(this), this.packetSender);
|
|
115
136
|
// For reading packet
|
|
116
137
|
const versionCodec = new VersionCodec(this.state);
|
|
117
138
|
// For throwing packet through internet
|
|
@@ -126,12 +147,12 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
|
|
|
126
147
|
this.tcp.forwardPacket = versionCodec.handlePacket.bind(versionCodec);
|
|
127
148
|
this.tcp.parsePacket = versionCodec.encodePacket.bind(versionCodec);
|
|
128
149
|
this.tcp.sendInitPacket = () => {
|
|
129
|
-
|
|
130
|
-
|
|
150
|
+
this.packetSender.sendHandshake();
|
|
151
|
+
this.packetSender.sendLoginStart();
|
|
131
152
|
};
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
versionCodec.consumePacket =
|
|
153
|
+
this.packetSender.sendPacket = this.tcp.sendPacket.bind(this.tcp);
|
|
154
|
+
this.packetListener.disconnect = this.disconnect.bind(this);
|
|
155
|
+
versionCodec.consumePacket = this.packetListener.handlePacket.bind(this.packetListener);
|
|
135
156
|
|
|
136
157
|
// For querying data
|
|
137
158
|
this.blocks = new BlockManager(this.state);
|
|
@@ -143,24 +164,27 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
|
|
|
143
164
|
this.entities,
|
|
144
165
|
this.blocks,
|
|
145
166
|
);
|
|
146
|
-
this.player.sendPlayerPos =
|
|
147
|
-
this.player.sendPlayerPosRot =
|
|
148
|
-
this.player.sendPlayerRot =
|
|
149
|
-
this.player.sendPlayerStatus =
|
|
167
|
+
this.player.sendPlayerPos = this.packetSender.sendPlayerPos;
|
|
168
|
+
this.player.sendPlayerPosRot = this.packetSender.sendPlayerPosRot;
|
|
169
|
+
this.player.sendPlayerRot = this.packetSender.sendPlayerRot;
|
|
170
|
+
this.player.sendPlayerStatus = this.packetSender.sendPlayerStatus;
|
|
150
171
|
|
|
151
172
|
// For tick-tock tick-tock
|
|
152
173
|
this.tickLoop = new TickLoop(() => {
|
|
153
174
|
this.state.drainMutation();
|
|
154
|
-
this.state.drainEvent()
|
|
155
|
-
|
|
156
|
-
this.state.drainPacket()
|
|
157
|
-
.forEach((packet) => this.tcp.sendPacket(packet.id, packet.data));
|
|
175
|
+
this.state.drainEvent(event => this.emitEvent(event));
|
|
176
|
+
this.state.drainPacket((packet) => this.tcp.sendPacket(packet.id, packet.data));
|
|
158
177
|
this.player.tick();
|
|
159
178
|
});
|
|
160
179
|
|
|
161
180
|
// Forward TCP events
|
|
162
181
|
this.tcp.on("connect", () => this.emit("connect"));
|
|
163
182
|
this.tcp.on("destroy", () => this.emit("destroy"));
|
|
183
|
+
this.on("loadChunk", (sx, sy, sz) => this.blocks.deleteChunkCache(sx, sy, sz));
|
|
184
|
+
this.on("unloadChunk", (sx, sz) => {
|
|
185
|
+
for (let sy = 0; sy < 16; sy++)
|
|
186
|
+
this.blocks.deleteChunkCache(sx, sy, sz);
|
|
187
|
+
});
|
|
164
188
|
}
|
|
165
189
|
|
|
166
190
|
private emitEvent(event: EmittedEvent) {
|
|
@@ -170,9 +194,11 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
|
|
|
170
194
|
private async loadRegistries() {
|
|
171
195
|
if (Client.loadRegistry) return;
|
|
172
196
|
Client.loadRegistry = true;
|
|
173
|
-
|
|
174
|
-
await
|
|
175
|
-
await
|
|
197
|
+
const { version } = this.options;
|
|
198
|
+
await BlockRegistry.load(version);
|
|
199
|
+
await EntityRegistry.load(version);
|
|
200
|
+
await PacketRegistry.load(version);
|
|
201
|
+
await EffectRegistry.load(version);
|
|
176
202
|
}
|
|
177
203
|
|
|
178
204
|
// Start / stop
|
|
@@ -241,6 +267,13 @@ export class Client<IsReady extends boolean = boolean> extends (EventEmitter as
|
|
|
241
267
|
this.player.releaseAllInputs();
|
|
242
268
|
}
|
|
243
269
|
|
|
270
|
+
/**
|
|
271
|
+
* Send a message
|
|
272
|
+
*/
|
|
273
|
+
public chat(message: string) {
|
|
274
|
+
this.packetSender.sendMessage(message);
|
|
275
|
+
}
|
|
276
|
+
|
|
244
277
|
// World
|
|
245
278
|
/**
|
|
246
279
|
* Get the block state at position
|
package/src/index.ts
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
export * from "./base/bitset";
|
|
2
|
+
export * from "./base/buffer";
|
|
3
|
+
export * from "./base/cache";
|
|
2
4
|
export * from "./base/error";
|
|
3
5
|
export * from "./base/event";
|
|
6
|
+
export * from "./base/http";
|
|
4
7
|
export * from "./base/math";
|
|
5
8
|
export * from "./base/typing";
|
|
9
|
+
export * from "./binary/decoder";
|
|
10
|
+
export * from "./binary/encoder";
|
|
11
|
+
export * from "./binary/static";
|
|
6
12
|
export * from "./client/auth";
|
|
7
13
|
export * from "./client/client";
|
|
8
|
-
export * from "./client/
|
|
9
|
-
export * from "./
|
|
10
|
-
export * from "./
|
|
11
|
-
export * from "./
|
|
14
|
+
export * from "./client/static";
|
|
15
|
+
export * from "./message/link";
|
|
16
|
+
export * from "./message/sigCache";
|
|
17
|
+
export * from "./net/tcp";
|
|
18
|
+
export * from "./packet/listener";
|
|
19
|
+
export * from "./packet/sender";
|
|
12
20
|
export * from "./physics/aabb";
|
|
13
21
|
export * from "./physics/direction";
|
|
14
22
|
export * from "./physics/player";
|
|
@@ -3,9 +3,9 @@ import { EventEmitter } from "node:events";
|
|
|
3
3
|
import { deflateSync, inflateSync } from "node:zlib";
|
|
4
4
|
|
|
5
5
|
import { TypedEmmiter } from "../base/event";
|
|
6
|
-
import { BinaryDecoder } from "../
|
|
7
|
-
import { BinaryEncoder } from "../
|
|
8
|
-
import { AuthOption } from "
|
|
6
|
+
import { BinaryDecoder } from "../binary/decoder";
|
|
7
|
+
import { BinaryEncoder } from "../binary/encoder";
|
|
8
|
+
import { AuthOption } from "../client/auth";
|
|
9
9
|
import { ClientStatus, SharedState } from "../world/state";
|
|
10
10
|
import { EncodeResult } from "../version/codec";
|
|
11
11
|
import { TextComponent } from "../base/typing";
|
|
@@ -171,6 +171,8 @@ export class TCPClient extends (EventEmitter as new () => TypedEmmiter<TCPClient
|
|
|
171
171
|
packetID = decoder.readVarInt();
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
|
+
if (this.state.clientOptions.debug?.packetLogger == true)
|
|
175
|
+
console.log("packet", packetID, "length", decoder.buffer.length);
|
|
174
176
|
this.forwardPacket(packetID, decoder);
|
|
175
177
|
|
|
176
178
|
this.bufferPool = this.bufferPool.subarray(expectedPacketEnd);
|
|
@@ -1,61 +1,67 @@
|
|
|
1
1
|
import zod from "zod";
|
|
2
|
-
import { createCipheriv, createDecipheriv,
|
|
3
|
-
import { BlockEntity, ChunkSection, ClientPlayer, ClientStatus,
|
|
4
|
-
import { BinaryDecoder, getTextFromTextComponent } from "
|
|
2
|
+
import { createCipheriv, createDecipheriv, randomBytes, createVerify } from "node:crypto";
|
|
3
|
+
import { BlockEntity, ChunkSection, ClientPlayer, ClientStatus, Entity, GameMode, ServerKnownPack, ServerWorld, SharedState } from "../world/state";
|
|
4
|
+
import { BinaryDecoder, getTextFromTextComponent } from "../binary/decoder";
|
|
5
5
|
import { packBlockPos, SectionsPerChunk } from "../client/static";
|
|
6
|
-
import {
|
|
7
|
-
import { ProtocolVersionMapping } from "../version/registry";
|
|
6
|
+
import { Vec3 } from "../physics/direction";
|
|
8
7
|
import { TypedEmmiter } from "../base/event";
|
|
9
8
|
import { ClientEvents } from "../client/client";
|
|
10
|
-
import { makeMovementFlag } from "
|
|
9
|
+
import { makeMovementFlag } from "../binary/encoder";
|
|
11
10
|
import { TextComponent } from "../base/typing";
|
|
12
|
-
import { AuthRelatedNotFound, HaveSignatureButNotIndex, MessageLinkNotFound,
|
|
13
|
-
import {
|
|
11
|
+
import { AuthRelatedNotFound, HaveSignatureButNotIndex, MessageLinkNotFound, NotImplemented, UnexpectedValue } from "../base/error";
|
|
12
|
+
import { uuidToBuffer } from "../base/math";
|
|
14
13
|
import { MessageLink } from "../message/link";
|
|
15
|
-
import {
|
|
14
|
+
import { Sender } from "./sender";
|
|
16
15
|
|
|
17
16
|
function zodParse<Type extends zod.ZodType>(data: object, zod: Type): zod.infer<Type> {
|
|
18
17
|
return zod.parse(data);
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
export class
|
|
20
|
+
export class Listener {
|
|
22
21
|
private readonly mapping: Record<string, (data: object) => void>;
|
|
23
22
|
|
|
24
23
|
constructor(
|
|
25
24
|
private state: SharedState,
|
|
26
|
-
private emit: TypedEmmiter<ClientEvents>["emit"]
|
|
25
|
+
private emit: TypedEmmiter<ClientEvents>["emit"],
|
|
26
|
+
private sender: Sender,
|
|
27
27
|
) {
|
|
28
28
|
this.mapping = {
|
|
29
29
|
"login:login_disconnect": this.handleLoginDisconnect,
|
|
30
30
|
"login:hello": this.handleEncryption,
|
|
31
31
|
"login:login_finished": this.handleLoginSucess,
|
|
32
32
|
"login:login_compression": this.handleSetCompression,
|
|
33
|
+
|
|
33
34
|
"configuration:disconnect": this.handleConfiguarionPlayDisconnect,
|
|
34
35
|
"configuration:keep_alive": this.handleKeepAlive,
|
|
35
36
|
"configuration:registry_data": this.handleRegistryData,
|
|
36
37
|
"configuration:select_known_packs": this.handleKnownPack,
|
|
37
38
|
"configuration:finish_configuration": this.handleFinishConfiguration,
|
|
38
|
-
|
|
39
|
+
|
|
40
|
+
"play:login": this.handlePlayLogin,
|
|
39
41
|
"play:disconnect": this.handleConfiguarionPlayDisconnect,
|
|
40
|
-
"play:disguised_chat": this.handleDisguisedChatMessage,
|
|
41
|
-
"play:entity_position_sync": this.handleTeleportEntity,
|
|
42
|
-
"play:forget_level_chunk": this.handleUnloadChunk,
|
|
43
42
|
"play:keep_alive": this.handleKeepAlive,
|
|
43
|
+
|
|
44
|
+
"play:player_chat": this.handlePlayerChat,
|
|
45
|
+
"play:disguised_chat": this.handleDisguisedChatMessage,
|
|
46
|
+
"play:system_chat": this.handleSystemMessage,
|
|
47
|
+
"play:set_action_bar_text": this.handleSetActionBar,
|
|
48
|
+
|
|
44
49
|
"play:level_chunk_with_light": this.handleChunkData,
|
|
45
|
-
"play:
|
|
50
|
+
"play:forget_level_chunk": this.handleUnloadChunk,
|
|
51
|
+
|
|
52
|
+
"play:add_entity": this.handleSpawnEntity,
|
|
46
53
|
"play:move_entity_pos": this.handleUpdateEntityPosition,
|
|
47
54
|
"play:move_entity_pos_rot": this.handleUpdateEntityPositionRotation,
|
|
48
|
-
"play:
|
|
55
|
+
"play:entity_position_sync": this.handleTeleportEntity,
|
|
49
56
|
"play:player_position": this.handleSynchronizePlayerPosition,
|
|
57
|
+
"play:update_mob_effect": this.handleUpdateMobEffect,
|
|
50
58
|
"play:remove_entities": this.handleRemoveEntity,
|
|
51
|
-
|
|
52
|
-
"play:
|
|
59
|
+
"play:remove_mob_effect": this.handleRemoveMobEffect,
|
|
60
|
+
// "play:rotate_head": ,
|
|
53
61
|
"play:set_entity_motion": this.handleSetEntityVelocity,
|
|
54
|
-
"play:system_chat": this.handleSystemMessage,
|
|
55
62
|
};
|
|
56
63
|
}
|
|
57
64
|
|
|
58
|
-
public sendPacket: (packetId: string, data: object) => void = () => { throw new NotImplemented(); };
|
|
59
65
|
public disconnect: (reason: string, reasonRaw?: TextComponent) => void = () => { throw new NotImplemented(); };
|
|
60
66
|
|
|
61
67
|
|
|
@@ -99,9 +105,9 @@ export class Dispatcher {
|
|
|
99
105
|
throw new AuthRelatedNotFound("auth client");
|
|
100
106
|
else
|
|
101
107
|
this.state.authClient.sendAuth(server_id, sharedSecret, publicKey)
|
|
102
|
-
.then(() => this.sendEncryptionResponse(publicKey, verifyToken));
|
|
108
|
+
.then(() => this.sender.sendEncryptionResponse(publicKey, verifyToken));
|
|
103
109
|
else
|
|
104
|
-
this.sendEncryptionResponse(publicKey, verifyToken);
|
|
110
|
+
this.sender.sendEncryptionResponse(publicKey, verifyToken);
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
private handleSetCompression(data: object) {
|
|
@@ -136,9 +142,10 @@ export class Dispatcher {
|
|
|
136
142
|
angle: {
|
|
137
143
|
yaw: 0,
|
|
138
144
|
pitch: 0,
|
|
139
|
-
}
|
|
145
|
+
},
|
|
146
|
+
effects: {}
|
|
140
147
|
} satisfies ClientPlayer as any;
|
|
141
|
-
this.sendLoginAck();
|
|
148
|
+
this.sender.sendLoginAck();
|
|
142
149
|
}
|
|
143
150
|
|
|
144
151
|
// Configure
|
|
@@ -152,8 +159,8 @@ export class Dispatcher {
|
|
|
152
159
|
}))
|
|
153
160
|
}));
|
|
154
161
|
this.state.server!.knownPacks = known_packs satisfies ServerKnownPack[] as any;
|
|
155
|
-
this.sendKnownPack(this.state.clientOptions.loadRegistry === true ? [] : known_packs);
|
|
156
|
-
// this.sendKnownPack([]);
|
|
162
|
+
this.sender.sendKnownPack(this.state.clientOptions.loadRegistry === true ? [] : known_packs);
|
|
163
|
+
// this.sender.sendKnownPack([]);
|
|
157
164
|
}
|
|
158
165
|
|
|
159
166
|
private handleRegistryData(data: object) {
|
|
@@ -171,10 +178,11 @@ export class Dispatcher {
|
|
|
171
178
|
const registry = this.state.registry as Record<string, any[]>;
|
|
172
179
|
if (!(registry_id in registry)) registry[registry_id] = [];
|
|
173
180
|
registry[registry_id]!.push(...entries);
|
|
181
|
+
this.emit("registryData", { registry_id, entries });
|
|
174
182
|
}
|
|
175
183
|
|
|
176
184
|
private handleFinishConfiguration(data: object) {
|
|
177
|
-
this.sendConfigureAck();
|
|
185
|
+
this.sender.sendConfigureAck();
|
|
178
186
|
}
|
|
179
187
|
|
|
180
188
|
private handleConfiguarionPlayDisconnect(data: object) {
|
|
@@ -225,7 +233,7 @@ export class Dispatcher {
|
|
|
225
233
|
this.state.status = ClientStatus.Ready;
|
|
226
234
|
|
|
227
235
|
if (this.state.useEncryption)
|
|
228
|
-
this.sendPlayerSession();
|
|
236
|
+
this.sender.sendPlayerSession();
|
|
229
237
|
|
|
230
238
|
this.emit("ready");
|
|
231
239
|
}
|
|
@@ -291,8 +299,8 @@ export class Dispatcher {
|
|
|
291
299
|
} satisfies ClientPlayer as any
|
|
292
300
|
);
|
|
293
301
|
this.state.enqueueEvent("playerPosition", { x: newPosX, y: newPosY, z: newPosZ });
|
|
294
|
-
this.sendConfirmTeleportation(teleport_id);
|
|
295
|
-
this.sendPacket("move_player_pos_rot", {
|
|
302
|
+
this.sender.sendConfirmTeleportation(teleport_id);
|
|
303
|
+
this.sender.sendPacket("move_player_pos_rot", {
|
|
296
304
|
x: newPosition.x,
|
|
297
305
|
feet_y: newPosition.y,
|
|
298
306
|
z: newPosition.z,
|
|
@@ -308,7 +316,7 @@ export class Dispatcher {
|
|
|
308
316
|
keep_alive_id: zod.bigint().or(zod.number())
|
|
309
317
|
})
|
|
310
318
|
);
|
|
311
|
-
this.sendKeepAlive(BigInt(keep_alive_id));
|
|
319
|
+
this.sender.sendKeepAlive(BigInt(keep_alive_id));
|
|
312
320
|
}
|
|
313
321
|
|
|
314
322
|
private handleChangeGameMode(data: object) {
|
|
@@ -337,7 +345,7 @@ export class Dispatcher {
|
|
|
337
345
|
type: zod.int(),
|
|
338
346
|
data: zod.record(zod.string(), zod.any())
|
|
339
347
|
})),
|
|
340
|
-
light: zod.any(),
|
|
348
|
+
light: zod.any().optional(),
|
|
341
349
|
})
|
|
342
350
|
);
|
|
343
351
|
|
|
@@ -602,6 +610,53 @@ export class Dispatcher {
|
|
|
602
610
|
});
|
|
603
611
|
}
|
|
604
612
|
|
|
613
|
+
private handleUpdateMobEffect(data: object) {
|
|
614
|
+
const {
|
|
615
|
+
entity_id,
|
|
616
|
+
effect_id,
|
|
617
|
+
amplifier,
|
|
618
|
+
duration,
|
|
619
|
+
flags
|
|
620
|
+
} = zodParse(data, zod.object({
|
|
621
|
+
entity_id: zod.number(),
|
|
622
|
+
effect_id: zod.number(),
|
|
623
|
+
amplifier: zod.number(),
|
|
624
|
+
duration: zod.number(),
|
|
625
|
+
flags: zod.number(),
|
|
626
|
+
}));
|
|
627
|
+
const isAmbient = (flags & 0x01) == 1,
|
|
628
|
+
showParticles = (flags & 0x02) == 1,
|
|
629
|
+
showIcon = (flags & 0x04) == 1,
|
|
630
|
+
blend = (flags & 0x08) == 1;
|
|
631
|
+
this.state.enqueueMutation((state) => {
|
|
632
|
+
if (state.player!.entityId === entity_id)
|
|
633
|
+
state.player!.effects[effect_id] = {
|
|
634
|
+
amplifier,
|
|
635
|
+
duration,
|
|
636
|
+
id: effect_id,
|
|
637
|
+
flag: {
|
|
638
|
+
blend,
|
|
639
|
+
isAmbient,
|
|
640
|
+
showIcon,
|
|
641
|
+
showParticles
|
|
642
|
+
},
|
|
643
|
+
date: Date.now()
|
|
644
|
+
};
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
private handleRemoveMobEffect(data: object) {
|
|
649
|
+
const { entity_id, effect_id } = zodParse(data, zod.object({
|
|
650
|
+
entity_id: zod.number(),
|
|
651
|
+
effect_id: zod.number(),
|
|
652
|
+
}));
|
|
653
|
+
|
|
654
|
+
this.state.enqueueMutation((state) => {
|
|
655
|
+
if (state.player!.entityId === entity_id)
|
|
656
|
+
delete state.player!.effects[effect_id];
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
|
|
605
660
|
// Chat
|
|
606
661
|
private handlePlayerChat(data: object) {
|
|
607
662
|
const {
|
|
@@ -645,7 +700,7 @@ export class Dispatcher {
|
|
|
645
700
|
const emitObject = {
|
|
646
701
|
sender: senderNameText,
|
|
647
702
|
target: targetNameText,
|
|
648
|
-
content:
|
|
703
|
+
content: message,
|
|
649
704
|
raw: {
|
|
650
705
|
sender: sender_name,
|
|
651
706
|
target: target_name || undefined,
|
|
@@ -677,6 +732,8 @@ export class Dispatcher {
|
|
|
677
732
|
}
|
|
678
733
|
}
|
|
679
734
|
|
|
735
|
+
if (message_signature_bytes !== null)
|
|
736
|
+
this.state.messageCount += 1;
|
|
680
737
|
if (this.state.clientOptions.shouldVerifyMessageSignature === true && message_signature_bytes) {
|
|
681
738
|
if (!this.state.sessionID)
|
|
682
739
|
throw new AuthRelatedNotFound("session uuid");
|
|
@@ -716,7 +773,7 @@ export class Dispatcher {
|
|
|
716
773
|
const signature = Buffer.from(message_signature_bytes);
|
|
717
774
|
|
|
718
775
|
if (!verify.verify(publicKey!, signature))
|
|
719
|
-
this.emit("failedMessage", emitObject);
|
|
776
|
+
return this.emit("failedMessage", emitObject);
|
|
720
777
|
}
|
|
721
778
|
|
|
722
779
|
this.emit("message", emitObject);
|
|
@@ -774,146 +831,4 @@ export class Dispatcher {
|
|
|
774
831
|
}
|
|
775
832
|
});
|
|
776
833
|
}
|
|
777
|
-
|
|
778
|
-
/*
|
|
779
|
-
* Send packet
|
|
780
|
-
*/
|
|
781
|
-
|
|
782
|
-
// Login
|
|
783
|
-
|
|
784
|
-
public sendHandshake() {
|
|
785
|
-
this.state.state = ConnectionState.Handshake;
|
|
786
|
-
this.sendPacket("intention",
|
|
787
|
-
{
|
|
788
|
-
protocol_version: ProtocolVersionMapping[this.state.clientOptions.version]!,
|
|
789
|
-
server_address: this.state.clientOptions.host,
|
|
790
|
-
server_port: this.state.clientOptions.port,
|
|
791
|
-
intent: 2
|
|
792
|
-
}
|
|
793
|
-
);
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
public sendLoginStart() {
|
|
797
|
-
this.state.state = ConnectionState.Login;
|
|
798
|
-
this.state.status = ClientStatus.Logining;
|
|
799
|
-
this.sendPacket("hello", {
|
|
800
|
-
name: this.state.clientOptions.playerName,
|
|
801
|
-
player_uuid: Buffer.from(this.state.playerUUID!, "hex")
|
|
802
|
-
});
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
private sendEncryptionResponse(publicKey: Buffer, verifyToken: Buffer) {
|
|
806
|
-
const encryptedSecret = publicEncrypt({
|
|
807
|
-
key: createPublicKey({ key: publicKey, format: 'der', type: 'spki' }),
|
|
808
|
-
padding: crypto_constants.RSA_PKCS1_PADDING
|
|
809
|
-
}, this.state.sharedSecret!);
|
|
810
|
-
const encryptedVerifyToken = publicEncrypt({
|
|
811
|
-
key: createPublicKey({ key: publicKey, format: 'der', type: 'spki' }),
|
|
812
|
-
padding: crypto_constants.RSA_PKCS1_PADDING
|
|
813
|
-
}, verifyToken);
|
|
814
|
-
const secretBuf = sliceBuffer(encryptedSecret, 1, (buf) => buf.readInt8());
|
|
815
|
-
const token = sliceBuffer(encryptedVerifyToken, 1, (buf) => buf.readInt8());
|
|
816
|
-
this.sendPacket("key", {
|
|
817
|
-
shared_secret: { value: secretBuf, length: secretBuf.length },
|
|
818
|
-
verify_token: { value: token, length: token.length }
|
|
819
|
-
});
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
private sendLoginAck() {
|
|
823
|
-
this.sendPacket("login_acknowledged", {});
|
|
824
|
-
this.state.state = ConnectionState.Configure;
|
|
825
|
-
this.state.server = {};
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
// Configuring
|
|
829
|
-
|
|
830
|
-
private sendKnownPack(knownPacks: ServerKnownPack[]) {
|
|
831
|
-
this.sendPacket("select_known_packs", {
|
|
832
|
-
known_packs: {
|
|
833
|
-
value: knownPacks,
|
|
834
|
-
length: knownPacks.length
|
|
835
|
-
}
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
|
|
839
|
-
private sendConfigureAck() {
|
|
840
|
-
this.sendPacket("finish_configuration", {});
|
|
841
|
-
this.state.state = ConnectionState.Play;
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
// Play
|
|
845
|
-
|
|
846
|
-
private sendPlayerSession() {
|
|
847
|
-
const sessionUUID = randomUUIDBytes();
|
|
848
|
-
const expireTime = 15 * 60 * 1000; // 15min in ms
|
|
849
|
-
const expiredAt = Date.now() + expireTime;
|
|
850
|
-
const { publicKey, signature } = this.state.getSignature();
|
|
851
|
-
this.state.sessionID = sessionUUID;
|
|
852
|
-
this.sendPacket("chat_session_update", {
|
|
853
|
-
session_id: sessionUUID,
|
|
854
|
-
expire_at: expiredAt,
|
|
855
|
-
public_key: publicKey,
|
|
856
|
-
signature
|
|
857
|
-
});
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
private sendConfirmTeleportation(teleportId: number) {
|
|
861
|
-
this.sendPacket("accept_teleportation", {
|
|
862
|
-
teleport_id: teleportId
|
|
863
|
-
});
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
private sendKeepAlive(id: bigint) {
|
|
867
|
-
this.sendPacket("keep_alive", {
|
|
868
|
-
keep_alive_id: id
|
|
869
|
-
});
|
|
870
|
-
}
|
|
871
|
-
|
|
872
|
-
public sendPlayerPos(
|
|
873
|
-
position: BaseVec3,
|
|
874
|
-
onGround: boolean,
|
|
875
|
-
horizontalCollision: boolean
|
|
876
|
-
) {
|
|
877
|
-
const { x, y, z } = position;
|
|
878
|
-
this.state.enqueuePacket("move_player_pos", {
|
|
879
|
-
x, feet_y: y, z,
|
|
880
|
-
flags: makeMovementFlag(onGround, horizontalCollision)
|
|
881
|
-
});
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
public sendPlayerPosRot(
|
|
885
|
-
position: BaseVec3,
|
|
886
|
-
angle: Angle,
|
|
887
|
-
onGround: boolean,
|
|
888
|
-
horizontalCollision: boolean
|
|
889
|
-
) {
|
|
890
|
-
const { x, y, z } = position,
|
|
891
|
-
{ yaw, pitch } = angle;
|
|
892
|
-
this.state.enqueuePacket("move_player_pos_rot", {
|
|
893
|
-
x, feet_y: y, z,
|
|
894
|
-
yaw, pitch,
|
|
895
|
-
flags: makeMovementFlag(onGround, horizontalCollision)
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
public sendPlayerRot(
|
|
900
|
-
angle: Angle,
|
|
901
|
-
onGround: boolean,
|
|
902
|
-
horizontalCollision: boolean
|
|
903
|
-
) {
|
|
904
|
-
const { yaw, pitch } = angle;
|
|
905
|
-
this.state.enqueuePacket("move_player_rot", {
|
|
906
|
-
yaw, pitch,
|
|
907
|
-
flags: makeMovementFlag(onGround, horizontalCollision)
|
|
908
|
-
});
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
public sendPlayerStatus(
|
|
912
|
-
onGround: boolean,
|
|
913
|
-
horizontalCollision: boolean
|
|
914
|
-
) {
|
|
915
|
-
this.state.enqueuePacket("move_player_status_only", {
|
|
916
|
-
flags: makeMovementFlag(onGround, horizontalCollision)
|
|
917
|
-
});
|
|
918
|
-
}
|
|
919
834
|
}
|