@vaitosoi/minejs 0.2.0 → 0.2.2
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/dist/base/aabb.d.ts +197 -0
- package/dist/base/aabb.d.ts.map +1 -0
- package/dist/base/aabb.js +576 -0
- package/dist/base/aabb.js.map +1 -0
- package/dist/base/bitset.d.ts +9 -0
- package/dist/base/bitset.d.ts.map +1 -0
- package/dist/base/bitset.js +46 -0
- package/dist/base/bitset.js.map +1 -0
- package/dist/base/block.d.ts +86 -0
- package/dist/base/block.d.ts.map +1 -0
- package/dist/base/block.js +232 -0
- package/dist/base/block.js.map +1 -0
- package/dist/base/direction.d.ts +153 -0
- package/dist/base/direction.d.ts.map +1 -0
- package/dist/base/direction.js +288 -0
- package/dist/base/direction.js.map +1 -0
- package/dist/base/entity.d.ts +43 -0
- package/dist/base/entity.d.ts.map +1 -0
- package/dist/base/entity.js +97 -0
- package/dist/base/entity.js.map +1 -0
- package/dist/base/error.d.ts +76 -0
- package/dist/base/error.d.ts.map +1 -0
- package/dist/base/error.js +141 -0
- package/dist/base/error.js.map +1 -0
- package/dist/base/event.d.ts +7 -0
- package/dist/base/event.d.ts.map +1 -0
- package/dist/base/event.js +3 -0
- package/dist/base/event.js.map +1 -0
- package/dist/base/math.d.ts +25 -0
- package/dist/base/math.d.ts.map +1 -0
- package/dist/base/math.js +69 -0
- package/dist/base/math.js.map +1 -0
- package/dist/base/player.d.ts +107 -0
- package/dist/base/player.d.ts.map +1 -0
- package/dist/base/player.js +543 -0
- package/dist/base/player.js.map +1 -0
- package/dist/base/registry.d.ts +50 -0
- package/dist/base/registry.d.ts.map +1 -0
- package/dist/base/registry.js +89 -0
- package/dist/base/registry.js.map +1 -0
- package/dist/base/tick.d.ts +19 -0
- package/dist/base/tick.d.ts.map +1 -0
- package/dist/base/tick.js +49 -0
- package/dist/base/tick.js.map +1 -0
- package/dist/base/typing.d.ts +3 -0
- package/dist/base/typing.d.ts.map +1 -0
- package/dist/base/typing.js +3 -0
- package/dist/base/typing.js.map +1 -0
- package/dist/client/auth.d.ts +39 -0
- package/dist/client/auth.d.ts.map +1 -0
- package/dist/client/auth.js +307 -0
- package/dist/client/auth.js.map +1 -0
- package/dist/client/client.d.ts +62 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +98 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/static.d.ts +28 -0
- package/dist/client/static.d.ts.map +1 -0
- package/dist/client/static.js +43 -0
- package/dist/client/static.js.map +1 -0
- package/dist/client/tcp.d.ts +269 -0
- package/dist/client/tcp.d.ts.map +1 -0
- package/dist/client/tcp.js +838 -0
- package/dist/client/tcp.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -0
- package/dist/translator/decoder.d.ts +293 -0
- package/dist/translator/decoder.d.ts.map +1 -0
- package/dist/translator/decoder.js +668 -0
- package/dist/translator/decoder.js.map +1 -0
- package/dist/translator/encoder.d.ts +162 -0
- package/dist/translator/encoder.d.ts.map +1 -0
- package/dist/translator/encoder.js +430 -0
- package/dist/translator/encoder.js.map +1 -0
- package/dist/translator/static.d.ts +33 -0
- package/dist/translator/static.d.ts.map +1 -0
- package/dist/translator/static.js +42 -0
- package/dist/translator/static.js.map +1 -0
- package/package.json +10 -10
- package/src/base/aabb.ts +2 -0
- package/src/base/block.ts +4 -0
- package/src/base/direction.ts +5 -0
- package/src/base/error.ts +16 -0
- package/src/base/event.ts +1 -1
- package/src/base/math.ts +10 -0
- package/src/base/typing.ts +1 -0
- package/src/client/static.ts +4 -0
- package/src/translator/encoder.ts +2 -2
- package/src/translator/static.ts +9 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SNBTDecoder = exports.NBTDecoder = exports.BinaryDecoder = void 0;
|
|
4
|
+
exports.getTextFromTextComponent = getTextFromTextComponent;
|
|
5
|
+
const direction_1 = require("../base/direction");
|
|
6
|
+
const static_1 = require("./static");
|
|
7
|
+
const error_1 = require("../base/error");
|
|
8
|
+
const static_2 = require("./static");
|
|
9
|
+
const zlib_1 = require("zlib");
|
|
10
|
+
const math_1 = require("../base/math");
|
|
11
|
+
function getTextFromTextComponent(component) {
|
|
12
|
+
if (component === null || component === undefined)
|
|
13
|
+
return "null";
|
|
14
|
+
switch (typeof component) {
|
|
15
|
+
case "string":
|
|
16
|
+
return component;
|
|
17
|
+
case "object": {
|
|
18
|
+
if (Array.isArray(component))
|
|
19
|
+
return component.map(val => getTextFromTextComponent(val)).join();
|
|
20
|
+
else if ("text" in component) {
|
|
21
|
+
if ("extra" in component && Array.isArray(component["extra"]))
|
|
22
|
+
return component["text"] + component["extra"].map(val => getTextFromTextComponent(val)).join("");
|
|
23
|
+
else
|
|
24
|
+
return component["text"];
|
|
25
|
+
}
|
|
26
|
+
if ("translate" in component) {
|
|
27
|
+
if ("fallback" in component)
|
|
28
|
+
return component["fallback"];
|
|
29
|
+
else
|
|
30
|
+
return component["translate"];
|
|
31
|
+
}
|
|
32
|
+
else if ("keybind" in component)
|
|
33
|
+
return component["keybind"];
|
|
34
|
+
else
|
|
35
|
+
throw new error_1.UnexpectedValue("type of component", "string or object", typeof component);
|
|
36
|
+
}
|
|
37
|
+
default:
|
|
38
|
+
throw new error_1.UnexpectedValue("type of component", "string or object", typeof component);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
class BinaryDecoder {
|
|
42
|
+
buffer = Buffer.alloc(0);
|
|
43
|
+
offset = 0;
|
|
44
|
+
constructor(buffer, needDecompress = false) {
|
|
45
|
+
if (!needDecompress)
|
|
46
|
+
this.buffer = buffer;
|
|
47
|
+
else
|
|
48
|
+
this.buffer = (0, zlib_1.unzipSync)(buffer);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Read shortcut
|
|
52
|
+
*
|
|
53
|
+
* Read `size` bytes, use readFunc, then add `size` to internal offset
|
|
54
|
+
*/
|
|
55
|
+
read(size, readFunc) {
|
|
56
|
+
const val = readFunc(this.buffer).bind(this.buffer)(this.offset);
|
|
57
|
+
this.offset += size;
|
|
58
|
+
return val;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Read 1 byte
|
|
62
|
+
* @returns signed 1-byte integer
|
|
63
|
+
*/
|
|
64
|
+
readByte() { return this.read(1, (buffer) => buffer.readInt8); }
|
|
65
|
+
/**
|
|
66
|
+
* Read 1 byte
|
|
67
|
+
* @returns unsigned 1-byte integer
|
|
68
|
+
*/
|
|
69
|
+
readUByte() { return this.read(1, (buffer) => buffer.readUint8); }
|
|
70
|
+
/**
|
|
71
|
+
* Read 2 bytes
|
|
72
|
+
* @returns signed 2-byte integer
|
|
73
|
+
*/
|
|
74
|
+
readShort() { return this.read(2, (buffer) => buffer.readInt16BE); }
|
|
75
|
+
/**
|
|
76
|
+
* Read 2 bytes
|
|
77
|
+
* @returns unsigned 2-byte integer
|
|
78
|
+
*/
|
|
79
|
+
readUShort() { return this.read(2, (buffer) => buffer.readUint16BE); }
|
|
80
|
+
/**
|
|
81
|
+
* Read 4 bytes
|
|
82
|
+
* @returns signed 4-byte integer
|
|
83
|
+
*/
|
|
84
|
+
readInt() { return this.read(4, (buffer) => buffer.readInt32BE); }
|
|
85
|
+
/**
|
|
86
|
+
* Read 8 bytes
|
|
87
|
+
* @returns signed 8-byte integer
|
|
88
|
+
*/
|
|
89
|
+
readLong() { return this.read(8, (buffer) => buffer.readBigInt64BE); }
|
|
90
|
+
/**
|
|
91
|
+
* Read 4 bytes
|
|
92
|
+
* @returns signed 4-bytes decimal
|
|
93
|
+
*/
|
|
94
|
+
readFloat() { return this.read(4, (buffer) => buffer.readFloatBE); }
|
|
95
|
+
/**
|
|
96
|
+
* Read 8 bytes
|
|
97
|
+
* @returns signed 8-byte decimal
|
|
98
|
+
*/
|
|
99
|
+
readDouble() { return this.read(8, (buffer) => buffer.readDoubleBE); }
|
|
100
|
+
/**
|
|
101
|
+
* Read 1 byte
|
|
102
|
+
* @returns a boolean
|
|
103
|
+
*/
|
|
104
|
+
readBoolean() {
|
|
105
|
+
const value = this.readByte();
|
|
106
|
+
switch (value) {
|
|
107
|
+
case 0x01: return true;
|
|
108
|
+
case 0x00: return false;
|
|
109
|
+
default: throw new Error(`unexpect value of boolean type: ${value}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// Source: https://minecraft.wiki/w/Java_Edition_protocol/Packets#VarInt_and_VarLong
|
|
113
|
+
/**
|
|
114
|
+
* Read n bytes of integer
|
|
115
|
+
*
|
|
116
|
+
* A VarInt packet would look like this:
|
|
117
|
+
*
|
|
118
|
+
* `[7 bits of data][1 bit indicate if the VarInt ended here]`
|
|
119
|
+
*
|
|
120
|
+
* @returns signed n-bit integer
|
|
121
|
+
*/
|
|
122
|
+
readVarInt() {
|
|
123
|
+
let value = 0;
|
|
124
|
+
let position = 0;
|
|
125
|
+
let currentByte;
|
|
126
|
+
while (true) {
|
|
127
|
+
currentByte = this.readUByte();
|
|
128
|
+
value |= (currentByte & static_1.SEGMENT_BITS) << position;
|
|
129
|
+
if ((currentByte & static_1.CONTINUE_BIT) == 0)
|
|
130
|
+
break;
|
|
131
|
+
position += 7;
|
|
132
|
+
if (position >= 32)
|
|
133
|
+
throw new Error("VarInt is too big");
|
|
134
|
+
}
|
|
135
|
+
return value;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Read n bytes of integer
|
|
139
|
+
*
|
|
140
|
+
* Similar to VarInt, A VarLong packet would look like this:
|
|
141
|
+
*
|
|
142
|
+
* `[7 bits of data][1 bit indicate if the VarLong ended here]`
|
|
143
|
+
*
|
|
144
|
+
* @returns signed n-bit integer
|
|
145
|
+
*/
|
|
146
|
+
readVarLong() {
|
|
147
|
+
let value = BigInt(0);
|
|
148
|
+
let position = 0;
|
|
149
|
+
let currentByte;
|
|
150
|
+
while (true) {
|
|
151
|
+
currentByte = this.readUByte();
|
|
152
|
+
value |= BigInt((currentByte & static_1.SEGMENT_BITS) << position);
|
|
153
|
+
if ((currentByte & static_1.CONTINUE_BIT) == 0)
|
|
154
|
+
break;
|
|
155
|
+
position += 7;
|
|
156
|
+
if (position >= 64)
|
|
157
|
+
throw new Error("VarLong is too big");
|
|
158
|
+
}
|
|
159
|
+
return value;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Read a string
|
|
163
|
+
*
|
|
164
|
+
* A string packet would look like this:
|
|
165
|
+
*
|
|
166
|
+
* `[VarInt as length, if not provided][N bits of data]`
|
|
167
|
+
*
|
|
168
|
+
* @returns a string
|
|
169
|
+
*/
|
|
170
|
+
readString(length) {
|
|
171
|
+
length ||= this.readVarInt();
|
|
172
|
+
if (length == 0)
|
|
173
|
+
return "";
|
|
174
|
+
if (this.offset + length > this.buffer.length)
|
|
175
|
+
throw new error_1.StringSizeExceedLimit();
|
|
176
|
+
const string = this.buffer.subarray(this.offset, this.offset + length);
|
|
177
|
+
this.offset += length;
|
|
178
|
+
return string.toString("utf-8");
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Read a 16-byte UUID
|
|
182
|
+
*/
|
|
183
|
+
readUUID() {
|
|
184
|
+
const buffer = this.buffer.subarray(this.offset, this.offset + 16);
|
|
185
|
+
this.offset += 16;
|
|
186
|
+
return buffer.toString('hex');
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Read a Position
|
|
190
|
+
*
|
|
191
|
+
* A position packet is a 64-bit value, split into three signed integer parts:
|
|
192
|
+
* ```
|
|
193
|
+
* x: 26 MSBs
|
|
194
|
+
* z: 26 middle bits
|
|
195
|
+
* y: 12 LSBs
|
|
196
|
+
* ```
|
|
197
|
+
*
|
|
198
|
+
* @returns a Position
|
|
199
|
+
*/
|
|
200
|
+
readPosition() {
|
|
201
|
+
const val = this.readLong(), x = val >> BigInt(38), y = val << BigInt(52) >> BigInt(52), z = val << BigInt(26) >> BigInt(38);
|
|
202
|
+
return {
|
|
203
|
+
x: Number(x),
|
|
204
|
+
y: Number(y),
|
|
205
|
+
z: Number(z),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Read an array with known length
|
|
210
|
+
*
|
|
211
|
+
* @returns an array
|
|
212
|
+
*/
|
|
213
|
+
readArray(length, readFunc) {
|
|
214
|
+
return Array.from({ length }).map((_, ind) => readFunc(this, ind));
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Read a length-prefixed array
|
|
218
|
+
*
|
|
219
|
+
* An array packet would look like this:
|
|
220
|
+
* `[VarInt as length][N bytes of data]`
|
|
221
|
+
*
|
|
222
|
+
* @returns a length-prefixed array
|
|
223
|
+
*/
|
|
224
|
+
readPrefixedArray(readFunc) {
|
|
225
|
+
const length = this.readVarInt();
|
|
226
|
+
return this.readArray(length, readFunc);
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Read an array with known length and return Buffer
|
|
230
|
+
*
|
|
231
|
+
* @param size size of the item, in byte
|
|
232
|
+
* @returns an array
|
|
233
|
+
*/
|
|
234
|
+
readRawArray(length, size) {
|
|
235
|
+
const buffer = this.buffer.subarray(this.offset, this.offset + size * length);
|
|
236
|
+
this.offset += size * length;
|
|
237
|
+
return buffer;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Read a length-prefixed array and return the raw buffer
|
|
241
|
+
*
|
|
242
|
+
* An array packet would look like this:
|
|
243
|
+
* `[VarInt as length][N bytes of data]`
|
|
244
|
+
*
|
|
245
|
+
* @param size size of the item, in byte
|
|
246
|
+
* @returns a length-prefixed array
|
|
247
|
+
*/
|
|
248
|
+
readRawPrefixedArray(size) {
|
|
249
|
+
const length = this.readVarInt();
|
|
250
|
+
return this.readRawArray(length, size);
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Read a Teleport Flag packet
|
|
254
|
+
*
|
|
255
|
+
* A Teleport Flag packet, which is bit mask represented as an int, would look like this:
|
|
256
|
+
* | Hex Mask | Field |
|
|
257
|
+
* |----------|------------------------|
|
|
258
|
+
* | 0x0001 | Is X relative |
|
|
259
|
+
* | 0x0002 | Is Y relative |
|
|
260
|
+
* | 0x0004 | Is Z relative |
|
|
261
|
+
* | 0x0008 | Is Yaw relative |
|
|
262
|
+
* | 0x0010 | Is Pitch relative |
|
|
263
|
+
* | 0x0020 | Is Velocity X relative |
|
|
264
|
+
* | 0x0040 | Is Velocity Y relative |
|
|
265
|
+
* | 0x0080 | Is Velocity Z relative |
|
|
266
|
+
* | 0x0100 | Rotate velocity |
|
|
267
|
+
*/
|
|
268
|
+
readTeleportFlag() {
|
|
269
|
+
const flags = this.readInt();
|
|
270
|
+
const x = (flags & 0x0001) === 1, y = (flags & 0x0002) === 1, z = (flags & 0x0004) === 1, yaw = (flags & 0x0008) === 1, pitch = (flags & 0x0010) === 1, velX = (flags & 0x0020) === 1, velY = (flags & 0x0040) === 1, velZ = (flags & 0x0080) === 1, rotateVelocity = (flags & 0x0100) === 1;
|
|
271
|
+
return {
|
|
272
|
+
x,
|
|
273
|
+
y,
|
|
274
|
+
z,
|
|
275
|
+
yaw,
|
|
276
|
+
pitch,
|
|
277
|
+
velX,
|
|
278
|
+
velY,
|
|
279
|
+
velZ,
|
|
280
|
+
rotateVelocity,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Read a Prefixed Optional field
|
|
285
|
+
*
|
|
286
|
+
* A Prefixed Optional would look like this:
|
|
287
|
+
* `[Boolean to indicate whenether the following field is presented][N bytes of data if the boolean before is true, or else empty]`
|
|
288
|
+
*
|
|
289
|
+
* @returns
|
|
290
|
+
*/
|
|
291
|
+
readPrefixedOptional(readFunc) {
|
|
292
|
+
const isPresent = this.readBoolean();
|
|
293
|
+
if (!isPresent)
|
|
294
|
+
return null;
|
|
295
|
+
return readFunc(this);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Read a NBT
|
|
299
|
+
*/
|
|
300
|
+
readNBT() {
|
|
301
|
+
const remainData = this.buffer.subarray(this.offset);
|
|
302
|
+
const nbtDecoder = new NBTDecoder(remainData);
|
|
303
|
+
const val = nbtDecoder.decode();
|
|
304
|
+
this.offset += nbtDecoder.offset;
|
|
305
|
+
return val;
|
|
306
|
+
}
|
|
307
|
+
// For reading LpVec3
|
|
308
|
+
unpack(value) {
|
|
309
|
+
return (0, math_1.minBigInt)(BigInt(BigInt(value) & 32767n), BigInt(static_1.MAX_QUANTIZED_VALUE)) * BigInt(2.0) / BigInt(static_1.MAX_QUANTIZED_VALUE) - 1n;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Read LpVec3
|
|
313
|
+
*
|
|
314
|
+
* Read this article for more information: https://minecraft.wiki/w/Java_Edition_protocol/Data_types#LpVec3
|
|
315
|
+
*/
|
|
316
|
+
readLpVec3() {
|
|
317
|
+
const byte1 = this.readUByte();
|
|
318
|
+
if (byte1 === 0) {
|
|
319
|
+
return direction_1.Vec3.Zero;
|
|
320
|
+
}
|
|
321
|
+
const byte2 = this.readUByte();
|
|
322
|
+
const bytes3To6 = this.readInt(); // Should be UInt
|
|
323
|
+
const packed = BigInt(bytes3To6 << 16) | BigInt(byte2 << 8) | BigInt(byte1);
|
|
324
|
+
let scaleFactor = BigInt(byte1) & static_1.SCALE_BITS;
|
|
325
|
+
if ((BigInt(byte1) & static_1.CONTINUATION_FLAG) != 0n)
|
|
326
|
+
scaleFactor |= BigInt(this.readVarInt()) << 2n;
|
|
327
|
+
const scaleFactorD = BigInt(scaleFactor);
|
|
328
|
+
return new direction_1.Vec3(Number(this.unpack(packed >> 3n) * scaleFactorD), Number(this.unpack(packed >> 18n) * scaleFactorD), Number(this.unpack(packed >> 33n) * scaleFactorD));
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Resolve a fixed point to a double
|
|
332
|
+
*
|
|
333
|
+
* A fixed point is a certain number of bits represent the signed integer part (number to the left of the decimal point)
|
|
334
|
+
* and the rest represent the fractional part (to the right).
|
|
335
|
+
*
|
|
336
|
+
* @param x number to resole
|
|
337
|
+
* @param n n fraction bits
|
|
338
|
+
*/
|
|
339
|
+
readFixedPoint(x, n) {
|
|
340
|
+
return x / (1 << n);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Read an angle.
|
|
344
|
+
*
|
|
345
|
+
* An angle is a rotation angle in steps of 1/256 of a full turn
|
|
346
|
+
*/
|
|
347
|
+
readAngle() {
|
|
348
|
+
return this.readByte();
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Represents a data record of type X, either inline, or by reference to a registry implied by context
|
|
352
|
+
*/
|
|
353
|
+
readIdOrX(readX) {
|
|
354
|
+
const id = this.readVarInt();
|
|
355
|
+
if (id !== 0)
|
|
356
|
+
return id;
|
|
357
|
+
return readX(this);
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Read Chat Type Decoration
|
|
361
|
+
*
|
|
362
|
+
* The chat type decorations look like:
|
|
363
|
+
* | Name | Type | Description |
|
|
364
|
+
* |-----------------|-------------------------------|----------------------------------|
|
|
365
|
+
* | Translation Key | String | |
|
|
366
|
+
* | Parameters | Prefixed Array of VarInt Enum | 0: sender, 1: target, 2: content |
|
|
367
|
+
* | Style | NBT | |
|
|
368
|
+
*/
|
|
369
|
+
readChatTypeDecoration() {
|
|
370
|
+
const translationKey = this.readString(), parameters = this.readPrefixedArray(decoder => decoder.readVarInt()), style = this.readNBT();
|
|
371
|
+
return { translationKey, parameters, style };
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Read Chat Type
|
|
375
|
+
*/
|
|
376
|
+
readChatType() {
|
|
377
|
+
return {
|
|
378
|
+
chat: this.readChatTypeDecoration(),
|
|
379
|
+
narration: this.readChatTypeDecoration()
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
exports.BinaryDecoder = BinaryDecoder;
|
|
384
|
+
class NBTDecoder extends BinaryDecoder {
|
|
385
|
+
/**
|
|
386
|
+
* Read a Compound string
|
|
387
|
+
*
|
|
388
|
+
* A string packet would look like this:
|
|
389
|
+
*
|
|
390
|
+
* `[2 bytes as length][N bits of data]`
|
|
391
|
+
*
|
|
392
|
+
* @returns a string
|
|
393
|
+
*/
|
|
394
|
+
readCompoundString() {
|
|
395
|
+
const length = this.readUShort();
|
|
396
|
+
if (length == 0)
|
|
397
|
+
return "";
|
|
398
|
+
return this.readString(length);
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Read a list / array of tag
|
|
402
|
+
*
|
|
403
|
+
* A list / array packet should look like this:
|
|
404
|
+
* [1 byte of type, if not provided][4 bytes of length][N bits of data]
|
|
405
|
+
*
|
|
406
|
+
* @returns
|
|
407
|
+
*/
|
|
408
|
+
readCompoundList(type) {
|
|
409
|
+
type ||= this.readByte();
|
|
410
|
+
const length = this.readInt();
|
|
411
|
+
const array = Array.from({ length })
|
|
412
|
+
.map(() => this.readCompoundValue(type));
|
|
413
|
+
return array;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Read compound value base on provided tag
|
|
417
|
+
*/
|
|
418
|
+
readCompoundValue(tag) {
|
|
419
|
+
switch (tag) {
|
|
420
|
+
case static_2.Tag.Byte: return this.readByte();
|
|
421
|
+
case static_2.Tag.Short: return this.readShort();
|
|
422
|
+
case static_2.Tag.Int: return this.readInt();
|
|
423
|
+
case static_2.Tag.Long: return this.readLong();
|
|
424
|
+
case static_2.Tag.Float: return this.readFloat();
|
|
425
|
+
case static_2.Tag.Double: return this.readDouble();
|
|
426
|
+
case static_2.Tag.ByteArray: return this.readCompoundList(static_2.Tag.Byte);
|
|
427
|
+
case static_2.Tag.String: return this.readCompoundString();
|
|
428
|
+
case static_2.Tag.List: return this.readCompoundList();
|
|
429
|
+
case static_2.Tag.Compound: return this.readCompound();
|
|
430
|
+
case static_2.Tag.IntArray: return this.readCompoundList(static_2.Tag.Int);
|
|
431
|
+
case static_2.Tag.LongArray: return this.readCompoundList(static_2.Tag.Long);
|
|
432
|
+
default: throw new error_1.UnexpectedValue("compound tag", tag.toString());
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Read n bits
|
|
437
|
+
*
|
|
438
|
+
* A Compound entry would look like this:
|
|
439
|
+
*
|
|
440
|
+
* [1 byte of Type][2 byte of field name length][N bits of field length][N bits of data]
|
|
441
|
+
*
|
|
442
|
+
* @returns signed n-bit integer
|
|
443
|
+
*/
|
|
444
|
+
readCompound() {
|
|
445
|
+
const obj = {};
|
|
446
|
+
while (true) {
|
|
447
|
+
const type = this.readByte();
|
|
448
|
+
if (type === static_2.Tag.End)
|
|
449
|
+
return obj;
|
|
450
|
+
const name = this.readCompoundString();
|
|
451
|
+
const value = this.readCompoundValue(type);
|
|
452
|
+
obj[name] = value;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Read an NBT
|
|
457
|
+
*
|
|
458
|
+
* Note that Network NBT slice some root data so I have to specified it through `isNetwork` param
|
|
459
|
+
*
|
|
460
|
+
* @param isNetwork
|
|
461
|
+
* @returns
|
|
462
|
+
*/
|
|
463
|
+
decode(isNetwork = true) {
|
|
464
|
+
const type = this.readByte();
|
|
465
|
+
if (type === static_2.Tag.Compound || type === static_2.Tag.List) {
|
|
466
|
+
if (!isNetwork)
|
|
467
|
+
this.readCompoundString();
|
|
468
|
+
const value = this.readCompoundValue(type);
|
|
469
|
+
return value;
|
|
470
|
+
}
|
|
471
|
+
else if (type === static_2.Tag.End)
|
|
472
|
+
return {};
|
|
473
|
+
else {
|
|
474
|
+
if (!isNetwork)
|
|
475
|
+
this.readCompoundString();
|
|
476
|
+
const value = this.readCompoundValue(type);
|
|
477
|
+
return value;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
exports.NBTDecoder = NBTDecoder;
|
|
482
|
+
class SNBTDecoder {
|
|
483
|
+
source;
|
|
484
|
+
offset = 0;
|
|
485
|
+
constructor(source) {
|
|
486
|
+
this.source = source;
|
|
487
|
+
}
|
|
488
|
+
skipWhiteSpace() {
|
|
489
|
+
while (this.offset < this.source.length) {
|
|
490
|
+
// console.log({
|
|
491
|
+
// off: this.offset,
|
|
492
|
+
// ch: this.source[this.offset],
|
|
493
|
+
// a: this.source[this.offset] !== " ",
|
|
494
|
+
// b: this.source[this.offset] !== "\n"
|
|
495
|
+
// });
|
|
496
|
+
if (this.source[this.offset] !== " " &&
|
|
497
|
+
this.source[this.offset] !== "," &&
|
|
498
|
+
this.source[this.offset] !== "\n")
|
|
499
|
+
return;
|
|
500
|
+
this.offset += 1;
|
|
501
|
+
}
|
|
502
|
+
throw new error_1.UnexpectedValue("end of SNBT", "white space");
|
|
503
|
+
}
|
|
504
|
+
convertValue(val) {
|
|
505
|
+
if ((!isNaN(Number(val))) ||
|
|
506
|
+
val.endsWith("b") || val.endsWith("B") ||
|
|
507
|
+
val.endsWith("s") || val.endsWith("S") ||
|
|
508
|
+
val.endsWith("i") || val.endsWith("I") ||
|
|
509
|
+
val.endsWith("F") || val.endsWith("F"))
|
|
510
|
+
return Number(val);
|
|
511
|
+
if (val.endsWith("l") || val.endsWith("L") ||
|
|
512
|
+
val.endsWith("d") || val.endsWith("D") ||
|
|
513
|
+
BigInt(val) % BigInt(1) !== BigInt(0))
|
|
514
|
+
return BigInt(val);
|
|
515
|
+
if (val === "true")
|
|
516
|
+
return true;
|
|
517
|
+
if (val === "false")
|
|
518
|
+
return false;
|
|
519
|
+
if ((val.startsWith("'") && val.endsWith("'")) ||
|
|
520
|
+
(val.startsWith('"') && val.endsWith("'")))
|
|
521
|
+
return String(val.slice(1, -1));
|
|
522
|
+
return val;
|
|
523
|
+
}
|
|
524
|
+
// eoc = End Of Compound
|
|
525
|
+
seek() {
|
|
526
|
+
this.skipWhiteSpace();
|
|
527
|
+
if (this.source[this.offset] == "}")
|
|
528
|
+
return undefined;
|
|
529
|
+
let fieldName = "";
|
|
530
|
+
let sliceQuote = undefined;
|
|
531
|
+
let ch;
|
|
532
|
+
if (this.source[this.offset] === "'" || this.source[this.offset] === '"') {
|
|
533
|
+
sliceQuote = this.source[this.offset];
|
|
534
|
+
this.offset++;
|
|
535
|
+
}
|
|
536
|
+
while (true) {
|
|
537
|
+
ch = this.source[this.offset];
|
|
538
|
+
if (((sliceQuote == undefined && ch === ":") ||
|
|
539
|
+
(sliceQuote && ch === sliceQuote)) ||
|
|
540
|
+
this.offset >= this.source.length) {
|
|
541
|
+
this.offset++;
|
|
542
|
+
break;
|
|
543
|
+
}
|
|
544
|
+
fieldName += ch;
|
|
545
|
+
this.offset++;
|
|
546
|
+
}
|
|
547
|
+
if (sliceQuote)
|
|
548
|
+
this.offset++;
|
|
549
|
+
this.skipWhiteSpace();
|
|
550
|
+
let stringtifiedVal = "", convertedVal = undefined, type = "number";
|
|
551
|
+
outer: while (true) {
|
|
552
|
+
ch = this.source[this.offset];
|
|
553
|
+
console.dir({ ch, type });
|
|
554
|
+
switch (ch) {
|
|
555
|
+
case "[":
|
|
556
|
+
type = "list";
|
|
557
|
+
break;
|
|
558
|
+
// End of Array or Line
|
|
559
|
+
case "]":
|
|
560
|
+
if (type === "array" || type === "list") {
|
|
561
|
+
this.offset++;
|
|
562
|
+
break outer;
|
|
563
|
+
}
|
|
564
|
+
stringtifiedVal += ch;
|
|
565
|
+
break;
|
|
566
|
+
case ",":
|
|
567
|
+
if (type !== "array" && type !== "list") {
|
|
568
|
+
this.offset++;
|
|
569
|
+
break outer;
|
|
570
|
+
}
|
|
571
|
+
stringtifiedVal += ch;
|
|
572
|
+
break;
|
|
573
|
+
// String indicator, if found repeated mean it is the end of the string
|
|
574
|
+
case "'":
|
|
575
|
+
if (stringtifiedVal.endsWith("\\") || type == "list") {
|
|
576
|
+
stringtifiedVal += ch;
|
|
577
|
+
break;
|
|
578
|
+
}
|
|
579
|
+
if (type == "string_1") {
|
|
580
|
+
this.offset++;
|
|
581
|
+
break outer;
|
|
582
|
+
}
|
|
583
|
+
type = "string_1";
|
|
584
|
+
break;
|
|
585
|
+
case '"':
|
|
586
|
+
if (stringtifiedVal.endsWith("\\") || type == "list") {
|
|
587
|
+
stringtifiedVal += ch;
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
590
|
+
if (type == "string_2") {
|
|
591
|
+
this.offset++;
|
|
592
|
+
break outer;
|
|
593
|
+
}
|
|
594
|
+
type = "string_2";
|
|
595
|
+
break;
|
|
596
|
+
// Array type indicator
|
|
597
|
+
case "B":
|
|
598
|
+
case "I":
|
|
599
|
+
case "L":
|
|
600
|
+
type = "array";
|
|
601
|
+
this.offset++;
|
|
602
|
+
break;
|
|
603
|
+
case "{":
|
|
604
|
+
if (type != "list") {
|
|
605
|
+
convertedVal = this.obj();
|
|
606
|
+
break outer;
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
stringtifiedVal += ch;
|
|
610
|
+
break;
|
|
611
|
+
}
|
|
612
|
+
default:
|
|
613
|
+
if (ch === " " && type == "number")
|
|
614
|
+
break outer;
|
|
615
|
+
stringtifiedVal += ch;
|
|
616
|
+
break;
|
|
617
|
+
}
|
|
618
|
+
this.offset++;
|
|
619
|
+
}
|
|
620
|
+
if (stringtifiedVal !== "" && !convertedVal) {
|
|
621
|
+
if (type == "array")
|
|
622
|
+
convertedVal = stringtifiedVal.split(",")
|
|
623
|
+
.map(val => this.convertValue(val.trim()));
|
|
624
|
+
else if (type == "list") {
|
|
625
|
+
convertedVal = stringtifiedVal.split(",")
|
|
626
|
+
.map(val => {
|
|
627
|
+
val = val.trim();
|
|
628
|
+
if (val.startsWith("{") && val.endsWith("}")) {
|
|
629
|
+
const decoder = new SNBTDecoder(val);
|
|
630
|
+
const obj = decoder.decode();
|
|
631
|
+
if (Object.keys(obj).length != 1 ||
|
|
632
|
+
!("" in obj))
|
|
633
|
+
return obj;
|
|
634
|
+
return obj[""];
|
|
635
|
+
}
|
|
636
|
+
else
|
|
637
|
+
return this.convertValue(val);
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
if (type == "string_1" || type == "string_2")
|
|
642
|
+
convertedVal = stringtifiedVal;
|
|
643
|
+
else
|
|
644
|
+
convertedVal = this.convertValue(stringtifiedVal);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return [fieldName, convertedVal];
|
|
648
|
+
}
|
|
649
|
+
obj() {
|
|
650
|
+
if (this.source[this.offset] !== "{")
|
|
651
|
+
throw new error_1.UnexpectedValue("start of compound", "{", this.source[this.offset]);
|
|
652
|
+
this.offset++;
|
|
653
|
+
const obj = {};
|
|
654
|
+
while (this.offset < this.source.length) {
|
|
655
|
+
const val = this.seek();
|
|
656
|
+
if (!val)
|
|
657
|
+
break;
|
|
658
|
+
const [fieldName, fieldVal] = val;
|
|
659
|
+
obj[fieldName] = fieldVal;
|
|
660
|
+
}
|
|
661
|
+
return obj;
|
|
662
|
+
}
|
|
663
|
+
decode() {
|
|
664
|
+
return this.obj();
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
exports.SNBTDecoder = SNBTDecoder;
|
|
668
|
+
//# sourceMappingURL=decoder.js.map
|