@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaitosoi/minejs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "A Minecraft client package",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -28,19 +28,17 @@
|
|
|
28
28
|
"@clean-jsdoc-theme/typedoc": "5.0.5",
|
|
29
29
|
"@eslint/js": "^10.0.1",
|
|
30
30
|
"@stylistic/eslint-plugin": "^5.10.0",
|
|
31
|
-
"@types/
|
|
32
|
-
"@types/node": "^26.1.1",
|
|
31
|
+
"@types/node": "^26.4.0",
|
|
33
32
|
"@typescript/native": "npm:typescript@^7.0.2",
|
|
34
|
-
"eslint": "^10.
|
|
35
|
-
"globals": "^17.
|
|
36
|
-
"tsx": "^4.
|
|
33
|
+
"eslint": "^10.9.1",
|
|
34
|
+
"globals": "^17.11.0",
|
|
35
|
+
"tsx": "^4.23.12",
|
|
37
36
|
"typedoc": "^0.28.20",
|
|
38
37
|
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
39
|
-
"typescript-eslint": "^8.
|
|
38
|
+
"typescript-eslint": "^8.68.0"
|
|
40
39
|
},
|
|
41
40
|
"dependencies": {
|
|
42
|
-
"
|
|
43
|
-
"zod": "^4.4.3"
|
|
41
|
+
"zod": "^4.5.2"
|
|
44
42
|
},
|
|
45
|
-
"packageManager": "pnpm@11.
|
|
43
|
+
"packageManager": "pnpm@11.24.0"
|
|
46
44
|
}
|
package/src/base/bitset.ts
CHANGED
|
@@ -1,42 +1,323 @@
|
|
|
1
|
-
import
|
|
1
|
+
import assert from "node:assert";
|
|
2
|
+
import { UnexpectedValue } from "./error";
|
|
3
|
+
import { numberOfLeadingZeros, numberOfTrailingZeros } from "./math";
|
|
4
|
+
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
|
-
*
|
|
7
|
+
* Simplified implementation of the Java's BitSet class
|
|
8
|
+
*
|
|
9
|
+
* @see https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/BitSet.java
|
|
10
|
+
* @hidden
|
|
5
11
|
*/
|
|
6
|
-
export class BitSet
|
|
7
|
-
public
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
12
|
+
export class BitSet {
|
|
13
|
+
public static readonly ADDRESS_BITS_PER_WORD = 6;
|
|
14
|
+
public static readonly BITS_PER_WORD = 1 << this.ADDRESS_BITS_PER_WORD;
|
|
15
|
+
public static readonly WORD_MASK = 0xffffffffffffffffn;
|
|
16
|
+
|
|
17
|
+
public words: BigUint64Array;
|
|
18
|
+
public wordsInUse: number = 0;
|
|
19
|
+
|
|
20
|
+
private static wordIndex(bitIndex: number) {
|
|
21
|
+
return bitIndex >> this.ADDRESS_BITS_PER_WORD;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private static bitIndexInWord(bitIndex: number) {
|
|
25
|
+
return bitIndex & (this.BITS_PER_WORD - 1); // should be bitIndex & 63
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a mask with lowest `n` bits set to 1
|
|
30
|
+
*
|
|
31
|
+
* For example:
|
|
32
|
+
* * n = 0 -> `0b0n`
|
|
33
|
+
* * n = 3 -> `0b111n`
|
|
34
|
+
* * n = 5 -> `0b11111n`
|
|
35
|
+
*
|
|
36
|
+
* @param nBits
|
|
37
|
+
* @returns
|
|
38
|
+
*/
|
|
39
|
+
private static lowBits(nBits: number) {
|
|
40
|
+
return (1n << BigInt(nBits)) - 1n;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private initWords(nBits: number) {
|
|
44
|
+
return new BigUint64Array(BitSet.wordIndex(nBits - 1) + 1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private static checkRange(fromIndex: number, toIndex: number) {
|
|
48
|
+
if (fromIndex < 0)
|
|
49
|
+
throw new UnexpectedValue("value of fromIndex", fromIndex.toString(), "non-negative number");
|
|
50
|
+
if (toIndex < 0)
|
|
51
|
+
throw new UnexpectedValue("value of toIndex", toIndex.toString(), "non-negative number");
|
|
52
|
+
if (fromIndex > toIndex)
|
|
53
|
+
throw new UnexpectedValue("fromIndex and toIndex", `fromIndex ${fromIndex}; toIndex ${toIndex}`, "fromIndex has to be smaller than toIndex");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
constructor(nBits?: number) {
|
|
58
|
+
if (nBits && nBits < 0)
|
|
59
|
+
throw new UnexpectedValue("length of bitset", nBits.toString(), "non-negative number");
|
|
60
|
+
this.words = this.initWords(nBits ?? BitSet.BITS_PER_WORD);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public clone() {
|
|
64
|
+
const bitset = new BitSet(0);
|
|
65
|
+
bitset.words = structuredClone(this.words);
|
|
66
|
+
bitset.wordsInUse = this.wordsInUse;
|
|
67
|
+
bitset.checkInvariants();
|
|
68
|
+
return bitset;
|
|
69
|
+
}
|
|
11
70
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
71
|
+
private expandTo(wordIndex: number) {
|
|
72
|
+
const wordsRequired = wordIndex + 1;
|
|
73
|
+
if (this.wordsInUse < wordsRequired) {
|
|
74
|
+
this.ensureCapacity(wordsRequired);
|
|
75
|
+
this.wordsInUse = wordsRequired;
|
|
15
76
|
}
|
|
77
|
+
}
|
|
16
78
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
79
|
+
private ensureCapacity(wordsRequired: number) {
|
|
80
|
+
if (wordsRequired > this.words.length) {
|
|
81
|
+
// Allocate larger of doubled size or required size
|
|
82
|
+
const request = Math.max(2 * this.words.length, wordsRequired);
|
|
83
|
+
const newWords = new BigUint64Array(request);
|
|
84
|
+
newWords.set(this.words);
|
|
85
|
+
this.words = newWords;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
21
88
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
89
|
+
private recalculateWordsInUse() {
|
|
90
|
+
let i = this.wordsInUse - 1;
|
|
91
|
+
while (i >= 0 && this.words[i] === 0n) i--;
|
|
92
|
+
this.wordsInUse = i + 1; // The new logical size
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
private checkInvariants() {
|
|
96
|
+
assert(this.wordsInUse === 0 || this.words[this.wordsInUse - 1] !== 0n);
|
|
97
|
+
assert(this.wordsInUse >= 0 && this.wordsInUse <= this.words.length);
|
|
98
|
+
assert(this.wordsInUse === this.words.length || this.words[this.wordsInUse] === 0n);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
public toByteArray() {
|
|
103
|
+
const n = this.wordsInUse;
|
|
104
|
+
if (n == 0)
|
|
105
|
+
return [];
|
|
106
|
+
|
|
107
|
+
const bytes: number[] = [];
|
|
108
|
+
for (const word of this.words) {
|
|
109
|
+
let coppiedWord = structuredClone(word);
|
|
110
|
+
// Slice a 64-bit (or 8-byte word) into 8 8-bit (or 1-byte) slices
|
|
111
|
+
for (let i = 0; i < 8; i++) {
|
|
112
|
+
bytes.push(Number(coppiedWord & 0xffn));
|
|
113
|
+
coppiedWord >>= 8n;
|
|
34
114
|
}
|
|
35
|
-
word = ~data[wordIndex];
|
|
36
115
|
}
|
|
37
|
-
};
|
|
38
116
|
|
|
39
|
-
|
|
40
|
-
return
|
|
117
|
+
while (bytes.length > 0 && bytes.at(-1) === 0) bytes.pop();
|
|
118
|
+
return bytes;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public flip(bitIndex: number) {
|
|
122
|
+
if (bitIndex < 0)
|
|
123
|
+
throw new UnexpectedValue("value of bitIndex", bitIndex.toString(), "non-negative number");
|
|
124
|
+
|
|
125
|
+
const wordIndex = BitSet.wordIndex(bitIndex);
|
|
126
|
+
this.expandTo(wordIndex);
|
|
127
|
+
|
|
128
|
+
this.words[wordIndex]! ^= BigInt(BitSet.bitIndexInWord(bitIndex));
|
|
129
|
+
|
|
130
|
+
this.recalculateWordsInUse();
|
|
131
|
+
this.checkInvariants();
|
|
41
132
|
}
|
|
42
|
-
|
|
133
|
+
|
|
134
|
+
public set(bitIndex: number) {
|
|
135
|
+
if (bitIndex < 0)
|
|
136
|
+
throw new UnexpectedValue("value of bitIndex", bitIndex.toString(), "non-negative number");
|
|
137
|
+
|
|
138
|
+
const wordIndex = BitSet.wordIndex(bitIndex);
|
|
139
|
+
this.expandTo(wordIndex);
|
|
140
|
+
|
|
141
|
+
this.words[wordIndex]! |= 1n << BigInt(BitSet.bitIndexInWord(bitIndex)); // Restores invariants
|
|
142
|
+
|
|
143
|
+
this.checkInvariants();
|
|
144
|
+
}
|
|
145
|
+
public setRange(fromIndex: number, toIndex: number) {
|
|
146
|
+
BitSet.checkRange(fromIndex, toIndex);
|
|
147
|
+
|
|
148
|
+
if (fromIndex == toIndex)
|
|
149
|
+
return;
|
|
150
|
+
|
|
151
|
+
// Increase capacity if necessary
|
|
152
|
+
const startWordIndex = BitSet.wordIndex(fromIndex);
|
|
153
|
+
const endWordIndex = BitSet.wordIndex(toIndex - 1);
|
|
154
|
+
this.expandTo(endWordIndex);
|
|
155
|
+
|
|
156
|
+
const fromBit = BitSet.bitIndexInWord(fromIndex),
|
|
157
|
+
toBitInclusive = BitSet.bitIndexInWord(toIndex - 1) + 1,
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The NOT (~) bitwise meaning:
|
|
161
|
+
*
|
|
162
|
+
* Let say we want to set 2 to 6:
|
|
163
|
+
* ```
|
|
164
|
+
* 110010100
|
|
165
|
+
* ^ ^
|
|
166
|
+
* | +-- this is the 2nd bit
|
|
167
|
+
* and this is the 6th bit
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* So we call lowBits(2) and it return `...0011`
|
|
171
|
+
*
|
|
172
|
+
* Then we have to flip it to `...1100` to access the '2nd bit and the bits after it'
|
|
173
|
+
*/
|
|
174
|
+
firstWordMask = ~BitSet.lowBits(fromBit),
|
|
175
|
+
lastWordMask = BitSet.lowBits(toBitInclusive);
|
|
176
|
+
if (startWordIndex == endWordIndex) {
|
|
177
|
+
// Case 1: One word
|
|
178
|
+
this.words[startWordIndex]! |= (firstWordMask & lastWordMask);
|
|
179
|
+
} else {
|
|
180
|
+
// Case 2: Multiple words
|
|
181
|
+
// Handle first word
|
|
182
|
+
this.words[startWordIndex]! |= firstWordMask;
|
|
183
|
+
|
|
184
|
+
// Handle intermediate words, if any
|
|
185
|
+
for (let i = startWordIndex + 1; i < endWordIndex; i++)
|
|
186
|
+
this.words[i] = BitSet.WORD_MASK;
|
|
187
|
+
|
|
188
|
+
// Handle last word (restores invariants)
|
|
189
|
+
this.words[endWordIndex]! |= lastWordMask;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
this.checkInvariants();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
public clear(bitIndex: number) {
|
|
197
|
+
if (bitIndex < 0)
|
|
198
|
+
throw new UnexpectedValue("value of bitIndex", bitIndex.toString(), "non-negative number");
|
|
199
|
+
|
|
200
|
+
const wordIndex = BitSet.wordIndex(bitIndex);
|
|
201
|
+
if (wordIndex >= this.wordsInUse)
|
|
202
|
+
return;
|
|
203
|
+
|
|
204
|
+
this.words[wordIndex]! &= ~(1n << BigInt(bitIndex));
|
|
205
|
+
|
|
206
|
+
this.recalculateWordsInUse();
|
|
207
|
+
this.checkInvariants();
|
|
208
|
+
}
|
|
209
|
+
public clearRange(fromIndex: number, toIndex: number) {
|
|
210
|
+
BitSet.checkRange(fromIndex, toIndex);
|
|
211
|
+
|
|
212
|
+
if (fromIndex == toIndex)
|
|
213
|
+
return;
|
|
214
|
+
|
|
215
|
+
const startWordIndex = BitSet.wordIndex(fromIndex);
|
|
216
|
+
if (startWordIndex >= this.wordsInUse)
|
|
217
|
+
return;
|
|
218
|
+
|
|
219
|
+
let endWordIndex = BitSet.wordIndex(toIndex - 1);
|
|
220
|
+
if (endWordIndex >= this.wordsInUse) {
|
|
221
|
+
toIndex = this.length();
|
|
222
|
+
endWordIndex = this.wordsInUse - 1;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const fromBit = BitSet.bitIndexInWord(fromIndex),
|
|
226
|
+
toBitInclusive = BitSet.bitIndexInWord(toIndex - 1) + 1,
|
|
227
|
+
/**
|
|
228
|
+
* See the explaination in the setRange function
|
|
229
|
+
*/
|
|
230
|
+
firstWordMask = ~BitSet.lowBits(fromBit),
|
|
231
|
+
lastWordMask = BitSet.lowBits(toBitInclusive);
|
|
232
|
+
if (startWordIndex == endWordIndex) {
|
|
233
|
+
// Case 1: One word
|
|
234
|
+
this.words[startWordIndex]! &= ~(firstWordMask & lastWordMask);
|
|
235
|
+
} else {
|
|
236
|
+
// Case 2: Multiple words
|
|
237
|
+
// Handle first word
|
|
238
|
+
this.words[startWordIndex]! &= ~firstWordMask;
|
|
239
|
+
|
|
240
|
+
// Handle intermediate words, if any
|
|
241
|
+
for (let i = startWordIndex + 1; i < endWordIndex; i++)
|
|
242
|
+
this.words[i]! = 0n;
|
|
243
|
+
|
|
244
|
+
// Handle last word
|
|
245
|
+
this.words[endWordIndex]! &= ~lastWordMask;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.recalculateWordsInUse();
|
|
249
|
+
this.checkInvariants();
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
public get(bitIndex: number) {
|
|
254
|
+
if (bitIndex < 0)
|
|
255
|
+
throw new UnexpectedValue("value of bitIndex", bitIndex.toString(), "non-negative number");
|
|
256
|
+
|
|
257
|
+
this.checkInvariants();
|
|
258
|
+
|
|
259
|
+
const wordIndex = BitSet.wordIndex(bitIndex);
|
|
260
|
+
if (wordIndex >= this.wordsInUse) return false;
|
|
261
|
+
|
|
262
|
+
const bit = 1n << BigInt(BitSet.bitIndexInWord(bitIndex));
|
|
263
|
+
return (Number(this.words[wordIndex]! & bit) != 0);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
public nextSetBit(fromIndex: number) {
|
|
267
|
+
if (fromIndex < 0)
|
|
268
|
+
throw new UnexpectedValue("value of fromIndex", fromIndex.toString(), "non-negative number");
|
|
269
|
+
|
|
270
|
+
this.checkInvariants();
|
|
271
|
+
|
|
272
|
+
let u = BitSet.wordIndex(fromIndex);
|
|
273
|
+
if (u >= this.wordsInUse)
|
|
274
|
+
return -1;
|
|
275
|
+
|
|
276
|
+
let word = this.words[u]! & (~0n << BigInt(BitSet.bitIndexInWord(fromIndex)));
|
|
277
|
+
|
|
278
|
+
while (true) {
|
|
279
|
+
if (word != 0n)
|
|
280
|
+
return (u * BitSet.BITS_PER_WORD) + numberOfTrailingZeros(word);
|
|
281
|
+
if (++u == this.wordsInUse)
|
|
282
|
+
return -1;
|
|
283
|
+
word = this.words[u]!;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
public nextClearBit(fromIndex: number) {
|
|
288
|
+
// Neither spec nor implementation handle bitsets of maximal length.
|
|
289
|
+
// See 4816253.
|
|
290
|
+
if (fromIndex < 0)
|
|
291
|
+
throw new UnexpectedValue("value of fromIndex", fromIndex.toString(), "non-negative number");
|
|
292
|
+
|
|
293
|
+
this.checkInvariants();
|
|
294
|
+
|
|
295
|
+
let u = BitSet.wordIndex(fromIndex);
|
|
296
|
+
if (u >= this.wordsInUse)
|
|
297
|
+
return fromIndex;
|
|
298
|
+
|
|
299
|
+
let word = ~this.words[u]! & (BitSet.WORD_MASK << BigInt(fromIndex));
|
|
300
|
+
|
|
301
|
+
while (true) {
|
|
302
|
+
if (word != 0n)
|
|
303
|
+
return (u * BitSet.BITS_PER_WORD) + numberOfTrailingZeros(word);
|
|
304
|
+
if (++u == this.wordsInUse)
|
|
305
|
+
return this.wordsInUse * BitSet.BITS_PER_WORD;
|
|
306
|
+
word = ~this.words[u]!;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
public length() {
|
|
311
|
+
if (this.wordsInUse == 0)
|
|
312
|
+
return 0;
|
|
313
|
+
|
|
314
|
+
return BitSet.BITS_PER_WORD * (this.wordsInUse - 1) +
|
|
315
|
+
(BitSet.BITS_PER_WORD - numberOfLeadingZeros(this.words[this.wordsInUse - 1]!));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
public isEmpty() {
|
|
319
|
+
return this.wordsInUse == 0;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export default BitSet;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The base implementation for the Cache class
|
|
3
|
+
*/
|
|
4
|
+
export abstract class CacheImplementation<T = any> {
|
|
5
|
+
public abstract put(key: string, item: T): void;
|
|
6
|
+
public abstract get(key: string): T | undefined;
|
|
7
|
+
public abstract del(key: string): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* The LRU cache implementation.
|
|
12
|
+
*
|
|
13
|
+
* @see https://en.wikipedia.org/wiki/Cache_replacement_policies#Time-Aware,_Least_Recently_Used_(TLRU)
|
|
14
|
+
*/
|
|
15
|
+
export class LRUCache<T> extends CacheImplementation<T> {
|
|
16
|
+
private hash: Map<string, T> = new Map();
|
|
17
|
+
private list: string[] = [];
|
|
18
|
+
|
|
19
|
+
constructor(private capacity: number) {
|
|
20
|
+
super();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public put(key: string, item: T): void {
|
|
24
|
+
if (this.hash.has(key)) {
|
|
25
|
+
const oldIndex = this.list.indexOf(key);
|
|
26
|
+
if (oldIndex > -1)
|
|
27
|
+
this.list.splice(oldIndex, 1);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.hash.set(key, item);
|
|
31
|
+
this.list.push(key);
|
|
32
|
+
|
|
33
|
+
this.truncateHash();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
public get(key: string) {
|
|
37
|
+
if (!this.hash.has(key)) return undefined;
|
|
38
|
+
|
|
39
|
+
const item = this.hash.get(key);
|
|
40
|
+
const oldIndex = this.list.indexOf(key);
|
|
41
|
+
if (oldIndex > -1)
|
|
42
|
+
this.list.splice(oldIndex, 1);
|
|
43
|
+
this.list.push(key);
|
|
44
|
+
|
|
45
|
+
return item;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
public del(key: string): void {
|
|
49
|
+
const oldIndex = this.list.indexOf(key);
|
|
50
|
+
if (oldIndex > -1)
|
|
51
|
+
this.list.splice(oldIndex, 1);
|
|
52
|
+
this.hash.delete(key);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private truncateHash() {
|
|
56
|
+
while (this.list.length > this.capacity) {
|
|
57
|
+
const popping = this.list.pop();
|
|
58
|
+
if (popping)
|
|
59
|
+
this.hash.delete(popping);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
package/src/base/error.ts
CHANGED
|
@@ -131,6 +131,7 @@ export class MissingAuthOption extends Error {
|
|
|
131
131
|
}
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
/** @hidden */
|
|
134
135
|
export class AuthRelatedNotFound extends Error {
|
|
135
136
|
constructor(public component: string) {
|
|
136
137
|
super(`auth option is enabled, but the auth related component (${component}) is not found`);
|
|
@@ -190,18 +191,33 @@ export class NotImplemented extends Error {
|
|
|
190
191
|
}
|
|
191
192
|
}
|
|
192
193
|
|
|
194
|
+
|
|
195
|
+
/** @hidden */
|
|
196
|
+
export class SkippableNotImplemented extends Error {}
|
|
197
|
+
|
|
193
198
|
/*
|
|
194
199
|
* Messages
|
|
195
200
|
*/
|
|
196
201
|
|
|
202
|
+
/** @hidden */
|
|
197
203
|
export class MessageLinkNotFound extends Error {
|
|
198
204
|
constructor(public senderUUID: string) {
|
|
199
205
|
super(`message link of sender ${senderUUID} not found, maybe because server has sent out of order packet`);
|
|
200
206
|
}
|
|
201
207
|
}
|
|
202
208
|
|
|
209
|
+
/** @hidden */
|
|
203
210
|
export class HaveSignatureButNotIndex extends Error {
|
|
204
211
|
constructor() {
|
|
205
212
|
super (`expecting both shouldVerifyMessageOrder set to true when shouldVerifyMessageSignature set to true`);
|
|
206
213
|
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @hidden
|
|
218
|
+
*/
|
|
219
|
+
export class MessageTooLong extends Error {
|
|
220
|
+
constructor(public message: string) {
|
|
221
|
+
super(`your message is exceeding the 256 characters long limit, got ${message.length} characters`);
|
|
222
|
+
}
|
|
207
223
|
}
|
package/src/base/math.ts
CHANGED
|
@@ -112,4 +112,46 @@ export function minecraftSha1(
|
|
|
112
112
|
function mcHexDigest(digest: Buffer | Uint8Array): string {
|
|
113
113
|
const bigint = BigInt(`0x${digest.toString('hex')}`);
|
|
114
114
|
return BigInt.asIntN(digest.length * 8, bigint).toString(16);
|
|
115
|
-
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Simplified implementation of Java's Long.numberOfTrailingZeros
|
|
119
|
+
* @param n
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
export function numberOfTrailingZeros(n: bigint): number {
|
|
123
|
+
if (n === 0n) {
|
|
124
|
+
return 64;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
let count = 0;
|
|
128
|
+
while ((n & 1n) === 0n) {
|
|
129
|
+
count++;
|
|
130
|
+
n >>= 1n;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return count;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Simplified implementation of Java's Long.numberOfLeadingZeros
|
|
138
|
+
* @param n
|
|
139
|
+
* @returns
|
|
140
|
+
*/
|
|
141
|
+
export function numberOfLeadingZeros(n: bigint): number {
|
|
142
|
+
if (n === 0n) {
|
|
143
|
+
return 64;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let count = 0;
|
|
147
|
+
// Start checking from bit 63 (the most significant bit)
|
|
148
|
+
for (let i = 63; i >= 0; i--) {
|
|
149
|
+
if ((n & (1n << BigInt(i))) === 0n) {
|
|
150
|
+
count++;
|
|
151
|
+
} else {
|
|
152
|
+
break; // Stop at the first 1 bit
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return count;
|
|
157
|
+
}
|
package/src/base/typing.ts
CHANGED
|
@@ -8,3 +8,8 @@ export type If<Condition extends boolean, True, False = null> = Condition extend
|
|
|
8
8
|
* @see https://minecraft.wiki/w/Text_component_format
|
|
9
9
|
*/
|
|
10
10
|
export type TextComponent = Record<string, any>;
|
|
11
|
+
|
|
12
|
+
export interface RegistryData {
|
|
13
|
+
registry_id: string,
|
|
14
|
+
entries: { entry_id: string, data: Record<string, any> | null }[]
|
|
15
|
+
}
|
|
@@ -62,9 +62,13 @@ export class BinaryEncoder {
|
|
|
62
62
|
*/
|
|
63
63
|
public writeInt(val: number) { return this.write(4, val, (buf) => buf.writeInt32BE); }
|
|
64
64
|
/**
|
|
65
|
-
* Write
|
|
65
|
+
* Write 8 bytes singed integer
|
|
66
66
|
*/
|
|
67
|
-
public writeLong(val: bigint
|
|
67
|
+
public writeLong(val: bigint | number) {
|
|
68
|
+
// Cast to BigInt
|
|
69
|
+
const v = typeof val === "bigint" ? val : BigInt(val);
|
|
70
|
+
return this.write(8, v, (buf) => buf.writeBigInt64BE);
|
|
71
|
+
}
|
|
68
72
|
/**
|
|
69
73
|
* Write 4 bytes float
|
|
70
74
|
*/
|