sonic-ws 1.3.2 → 1.3.3
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/index.d.ts +0 -4
- package/dist/version.d.ts +1 -5
- package/dist/version.js +23 -4
- package/dist/ws/Connection.d.ts +0 -4
- package/dist/ws/Connection.js +124 -4
- package/dist/ws/PacketProcessor.d.ts +0 -4
- package/dist/ws/PacketProcessor.js +50 -4
- package/dist/ws/client/core/ClientCore.d.ts +0 -4
- package/dist/ws/client/core/ClientCore.js +249 -4
- package/dist/ws/client/node/ClientNode.d.ts +0 -4
- package/dist/ws/client/node/ClientNode.js +34 -4
- package/dist/ws/debug/DebugServer.d.ts +0 -4
- package/dist/ws/debug/DebugServer.js +605 -4
- package/dist/ws/packets/PacketProcessors.d.ts +0 -4
- package/dist/ws/packets/PacketProcessors.js +315 -4
- package/dist/ws/packets/PacketType.d.ts +0 -4
- package/dist/ws/packets/PacketType.js +59 -4
- package/dist/ws/packets/Packets.d.ts +0 -4
- package/dist/ws/packets/Packets.js +275 -4
- package/dist/ws/server/SonicWSConnection.d.ts +0 -4
- package/dist/ws/server/SonicWSConnection.js +296 -4
- package/dist/ws/server/SonicWSServer.d.ts +1 -5
- package/dist/ws/server/SonicWSServer.js +305 -4
- package/dist/ws/util/BufferUtil.d.ts +0 -4
- package/dist/ws/util/BufferUtil.js +40 -4
- package/dist/ws/util/StringUtil.d.ts +0 -4
- package/dist/ws/util/StringUtil.js +49 -4
- package/dist/ws/util/enums/EnumHandler.d.ts +0 -4
- package/dist/ws/util/enums/EnumHandler.js +58 -4
- package/dist/ws/util/enums/EnumType.d.ts +0 -4
- package/dist/ws/util/enums/EnumType.js +70 -4
- package/dist/ws/util/packets/BatchHelper.d.ts +0 -4
- package/dist/ws/util/packets/BatchHelper.js +83 -4
- package/dist/ws/util/packets/CompressionUtil.d.ts +5 -9
- package/dist/ws/util/packets/CompressionUtil.js +275 -4
- package/dist/ws/util/packets/HashUtil.d.ts +0 -4
- package/dist/ws/util/packets/HashUtil.js +120 -4
- package/dist/ws/util/packets/JSONUtil.d.ts +0 -4
- package/dist/ws/util/packets/JSONUtil.js +177 -4
- package/dist/ws/util/packets/PacketHolder.d.ts +0 -4
- package/dist/ws/util/packets/PacketHolder.js +124 -4
- package/dist/ws/util/packets/PacketUtils.d.ts +0 -4
- package/dist/ws/util/packets/PacketUtils.js +281 -4
- package/dist/ws/util/packets/RateHandler.d.ts +0 -4
- package/dist/ws/util/packets/RateHandler.js +64 -4
- package/package.json +3 -3
|
@@ -1,6 +1,307 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
2
3
|
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
4
16
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.SonicWSServer = void 0;
|
|
52
|
+
const WS = __importStar(require("ws"));
|
|
53
|
+
const SonicWSConnection_1 = require("./SonicWSConnection");
|
|
54
|
+
const PacketHolder_1 = require("../util/packets/PacketHolder");
|
|
55
|
+
const CompressionUtil_1 = require("../util/packets/CompressionUtil");
|
|
56
|
+
const version_1 = require("../../version");
|
|
57
|
+
const PacketUtils_1 = require("../util/packets/PacketUtils");
|
|
58
|
+
const PacketProcessor_1 = require("../PacketProcessor");
|
|
59
|
+
const HashUtil_1 = require("../util/packets/HashUtil");
|
|
60
|
+
const Connection_1 = require("../Connection");
|
|
61
|
+
const DebugServer_1 = require("../debug/DebugServer");
|
|
62
|
+
class SonicWSServer extends PacketProcessor_1.MiddlewareHolder {
|
|
63
|
+
wss;
|
|
64
|
+
availableIds = [];
|
|
65
|
+
lastId = 0;
|
|
66
|
+
connectListeners = [];
|
|
67
|
+
clientPackets;
|
|
68
|
+
serverPackets;
|
|
69
|
+
connections = [];
|
|
70
|
+
connectionMap = {};
|
|
71
|
+
clientRateLimit = 500;
|
|
72
|
+
serverRateLimit = 500;
|
|
73
|
+
handshakePacket = null;
|
|
74
|
+
tags = new Map();
|
|
75
|
+
tagsInv = new Map();
|
|
76
|
+
serverwideSendQueue = [false, [], undefined];
|
|
77
|
+
/**
|
|
78
|
+
* Initializes and hosts a websocket with sonic protocol
|
|
79
|
+
* Rate limits can be set with wss.setClientRateLimit(x) and wss.setServerRateLimit(x); it is defaulted at 500/second per both
|
|
80
|
+
* @param settings Sonic Server Options such as schema data for client and server packets, alongside websocket options
|
|
81
|
+
*/
|
|
82
|
+
constructor(settings) {
|
|
83
|
+
super();
|
|
84
|
+
const { clientPackets = [], serverPackets = [], websocketOptions = {} } = settings;
|
|
85
|
+
this.wss = new WS.WebSocketServer(websocketOptions);
|
|
86
|
+
this.clientPackets = new PacketHolder_1.PacketHolder(clientPackets);
|
|
87
|
+
this.serverPackets = new PacketHolder_1.PacketHolder(serverPackets);
|
|
88
|
+
const s_clientPackets = this.clientPackets.serialize();
|
|
89
|
+
const s_serverPackets = this.serverPackets.serialize();
|
|
90
|
+
const serverData = [...version_1.SERVER_SUFFIX_NUMS, version_1.VERSION];
|
|
91
|
+
const keyData = [...(0, CompressionUtil_1.convertVarInt)(s_clientPackets.length), ...s_clientPackets, ...s_serverPackets];
|
|
92
|
+
(0, HashUtil_1.setHashFunc)(settings.sonicServerSettings?.bit64Hash ?? true);
|
|
93
|
+
this.wss.on('connection', async (socket) => {
|
|
94
|
+
const sonicConnection = new SonicWSConnection_1.SonicWSConnection(socket, this, this.generateSocketID(), this.handshakePacket, this.clientRateLimit, this.serverRateLimit);
|
|
95
|
+
if (await this.callMiddleware("onClientConnect", sonicConnection)) {
|
|
96
|
+
sonicConnection.close(Connection_1.CloseCodes.MIDDLEWARE, "Connection blocked by middleware.");
|
|
97
|
+
this.callMiddleware("onClientDisconnect", sonicConnection, Connection_1.CloseCodes.MIDDLEWARE, Buffer.from("Connection blocked by middleware."));
|
|
98
|
+
this.availableIds.push(sonicConnection.id);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
// send tags to the client so it doesn't have to hard code them in
|
|
102
|
+
const data = new Uint8Array([...(0, CompressionUtil_1.convertVarInt)(sonicConnection.id), ...keyData]);
|
|
103
|
+
socket.send([...serverData, ...await (0, CompressionUtil_1.compressGzip)(data)]);
|
|
104
|
+
this.connections.push(sonicConnection);
|
|
105
|
+
this.connectionMap[sonicConnection.id] = sonicConnection;
|
|
106
|
+
this.connectListeners.forEach(l => l(sonicConnection));
|
|
107
|
+
socket.on('close', (code, reason) => {
|
|
108
|
+
this.connections.splice(this.connections.indexOf(sonicConnection), 1);
|
|
109
|
+
delete this.connectionMap[sonicConnection.id];
|
|
110
|
+
this.availableIds.push(sonicConnection.id);
|
|
111
|
+
if (this.tags.has(sonicConnection)) {
|
|
112
|
+
for (const tag of this.tags.get(sonicConnection))
|
|
113
|
+
this.tagsInv.get(tag)?.delete(sonicConnection);
|
|
114
|
+
this.tags.delete(sonicConnection);
|
|
115
|
+
}
|
|
116
|
+
this.callMiddleware("onClientDisconnect", sonicConnection, code, reason);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
if (settings.sonicServerSettings?.checkForUpdates ?? true) {
|
|
120
|
+
fetch('https://raw.githubusercontent.com/liwybloc/sonic-ws/refs/heads/main/release/version')
|
|
121
|
+
.then((res) => res.text())
|
|
122
|
+
.then((ver) => {
|
|
123
|
+
if (parseInt(ver) > version_1.VERSION) {
|
|
124
|
+
console.warn(`SonicWS is currently running outdated! (current: ${version_1.VERSION}, latest: ${ver}) Update with "npm update sonic-ws"`);
|
|
125
|
+
}
|
|
126
|
+
})
|
|
127
|
+
.catch((err) => {
|
|
128
|
+
console.error(err);
|
|
129
|
+
console.warn(`Could not check SonicWS version.`);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
generateSocketID() {
|
|
134
|
+
if (this.availableIds.length == 0)
|
|
135
|
+
this.availableIds.push(this.lastId + 1);
|
|
136
|
+
this.lastId = this.availableIds.shift();
|
|
137
|
+
return this.lastId;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Requires each client to send this packet upon initialization
|
|
141
|
+
*
|
|
142
|
+
* Recreates this:
|
|
143
|
+
* ```js
|
|
144
|
+
* let initiated = false;
|
|
145
|
+
* socket.on('init', () => {
|
|
146
|
+
* if(initiated) return socket.close();
|
|
147
|
+
* initiated = true;
|
|
148
|
+
* // process
|
|
149
|
+
* });
|
|
150
|
+
*
|
|
151
|
+
* socket.on('otherPacket', () => {
|
|
152
|
+
* if(!initiated) return socket.close();
|
|
153
|
+
* // process
|
|
154
|
+
* })
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @param packet The tag of the packet to require as a handshake
|
|
158
|
+
*/
|
|
159
|
+
requireHandshake(packet) {
|
|
160
|
+
if (!this.clientPackets.hasTag(packet))
|
|
161
|
+
throw new Error(`The client does not send "${packet}" and so it cannot use it as a handshake!`);
|
|
162
|
+
if (this.clientPackets.getPacket(packet).dataBatching != 0)
|
|
163
|
+
throw new Error(`The packet "${packet}" is a batched packet, and cannot be used as a handshake!`);
|
|
164
|
+
this.handshakePacket = packet;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Sets the rate limit for all client-side packets
|
|
168
|
+
* @param limit Amount of packets the sockets can send every second, or 0 for infinite
|
|
169
|
+
*/
|
|
170
|
+
setClientRateLimit(limit) {
|
|
171
|
+
// so that i can store limits in 1 packet
|
|
172
|
+
if (limit > CompressionUtil_1.MAX_BYTE) {
|
|
173
|
+
limit = 0;
|
|
174
|
+
console.warn(`A rate limit above ${CompressionUtil_1.MAX_BYTE} is considered infinite.`);
|
|
175
|
+
}
|
|
176
|
+
this.clientRateLimit = limit;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Sets the rate limit for server-side packets per-socket
|
|
180
|
+
* @param limit Amount of packets the server can send every second, or 0 for infinite
|
|
181
|
+
*/
|
|
182
|
+
setServerRateLimit(limit) {
|
|
183
|
+
// so that i can store limits in 1 packet
|
|
184
|
+
if (limit > CompressionUtil_1.MAX_BYTE) {
|
|
185
|
+
limit = 0;
|
|
186
|
+
console.warn(`A rate limit above ${CompressionUtil_1.MAX_BYTE} is considered infinite.`);
|
|
187
|
+
}
|
|
188
|
+
this.serverRateLimit = limit;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Enables a packet for all current & new clients.
|
|
192
|
+
* @param tag The tag of the packet
|
|
193
|
+
*/
|
|
194
|
+
enablePacket(tag) {
|
|
195
|
+
this.clientPackets.getPacket(tag).defaultEnabled = true;
|
|
196
|
+
this.connections.forEach(socket => socket.enablePacket(tag));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Disables a packet for all current & new clients.
|
|
200
|
+
* @param tag The tag of the packet
|
|
201
|
+
*/
|
|
202
|
+
disablePacket(tag) {
|
|
203
|
+
this.clientPackets.getPacket(tag).defaultEnabled = false;
|
|
204
|
+
this.connections.forEach(socket => socket.disablePacket(tag));
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Listens for whenever a client connects
|
|
208
|
+
* @param runner Called when ready
|
|
209
|
+
*/
|
|
210
|
+
on_connect(runner) {
|
|
211
|
+
this.connectListeners.push(runner);
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Listens for whenever the server is ready
|
|
215
|
+
* @param runner Called when ready
|
|
216
|
+
*/
|
|
217
|
+
on_ready(runner) {
|
|
218
|
+
this.wss.on('listening', runner);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Closes the server
|
|
222
|
+
* @param callback Called when server closes
|
|
223
|
+
*/
|
|
224
|
+
shutdown(callback) {
|
|
225
|
+
this.wss.close(callback);
|
|
226
|
+
}
|
|
227
|
+
async broadcastInternal(packetTag, target, values) {
|
|
228
|
+
let recipients;
|
|
229
|
+
if (target.type === "all") {
|
|
230
|
+
recipients = this.connections;
|
|
231
|
+
}
|
|
232
|
+
else if (target.type === "tagged") {
|
|
233
|
+
if (!this.tagsInv.has(target.tag))
|
|
234
|
+
return;
|
|
235
|
+
recipients = Array.from(this.tagsInv.get(target.tag));
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
recipients = this.connections.filter(target.filter);
|
|
239
|
+
}
|
|
240
|
+
if (await this.callMiddleware("onPacketBroadcast_pre", packetTag, { recipients, ...target }, values))
|
|
241
|
+
return;
|
|
242
|
+
if (recipients.length === 0)
|
|
243
|
+
return;
|
|
244
|
+
const [code, data, packet] = await (0, PacketUtils_1.processPacket)(this.serverPackets, packetTag, values, this.serverwideSendQueue, -1);
|
|
245
|
+
if (await this.callMiddleware("onPacketBroadcast_post", packetTag, { recipients, ...target }, data, data.length))
|
|
246
|
+
return;
|
|
247
|
+
recipients.forEach(conn => conn.send_processed(code, data, packet));
|
|
248
|
+
}
|
|
249
|
+
async broadcastTagged(tag, packetTag, ...values) {
|
|
250
|
+
await this.broadcastInternal(packetTag, { type: "tagged", tag }, values);
|
|
251
|
+
}
|
|
252
|
+
async broadcastFiltered(tag, filter, ...values) {
|
|
253
|
+
await this.broadcastInternal(tag, { type: "filter", filter }, values);
|
|
254
|
+
}
|
|
255
|
+
async broadcast(tag, ...values) {
|
|
256
|
+
await this.broadcastInternal(tag, { type: "all" }, values);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* @returns All users connected to the socket
|
|
260
|
+
*/
|
|
261
|
+
getConnected() {
|
|
262
|
+
return this.connections;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* @param id The socket id
|
|
266
|
+
* @returns The socket
|
|
267
|
+
*/
|
|
268
|
+
getSocket(id) {
|
|
269
|
+
return this.connectionMap[id];
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Closes a socket by id
|
|
273
|
+
* @param id The socket id
|
|
274
|
+
*/
|
|
275
|
+
closeSocket(id, code = 1000, reason) {
|
|
276
|
+
this.getSocket(id).close(code, reason);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Tags the socket with a key
|
|
280
|
+
* @param socket The socket to tag
|
|
281
|
+
* @param tag The tag to add
|
|
282
|
+
* @param replace If it should replace a previous tag; defaults to true. If using false, you can add multiple tags.
|
|
283
|
+
*/
|
|
284
|
+
tag(socket, tag, replace = true) {
|
|
285
|
+
if (!this.tags.get(socket))
|
|
286
|
+
this.tags.set(socket, new Set());
|
|
287
|
+
if (!this.tagsInv.get(tag))
|
|
288
|
+
this.tagsInv.set(tag, new Set());
|
|
289
|
+
if (replace) {
|
|
290
|
+
this.tags.get(socket).forEach(v => this.tagsInv.get(v)?.delete(socket));
|
|
291
|
+
}
|
|
292
|
+
this.tags.get(socket).add(tag);
|
|
293
|
+
this.tagsInv.get(tag).add(socket);
|
|
294
|
+
}
|
|
295
|
+
debugServer = null;
|
|
296
|
+
/**
|
|
297
|
+
* Opens a debug menu; this launches the browser and starts a subserver
|
|
298
|
+
* @param port Port of the server/http, defaults to 0 which finds an open port
|
|
299
|
+
* @param password Toggles the requirement of a password to access the server. Defaults to empty, which doesn't ask for a password.
|
|
300
|
+
*/
|
|
301
|
+
OpenDebug(data = {}) {
|
|
302
|
+
if (this.debugServer != null)
|
|
303
|
+
throw new Error("Attempted to open a debug server when one has already been opened.");
|
|
304
|
+
this.debugServer = new DebugServer_1.DebugServer(this, data);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
exports.SonicWSServer = SonicWSServer;
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
* Licensed under the Apache License, Version 2.0.
|
|
4
|
-
*/
|
|
5
1
|
type BuildTuple<T, L extends number, R extends unknown[] = []> = R['length'] extends L ? R : BuildTuple<T, L, [T, ...R]>;
|
|
6
2
|
export declare function splitArray<T, N extends number>(arr: T[], size: N): Array<BuildTuple<T, N>>;
|
|
7
3
|
export declare function toPacketBuffer(code: number, data: Uint8Array): Uint8Array;
|
|
@@ -1,6 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
2
3
|
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
4
16
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.splitArray = splitArray;
|
|
19
|
+
exports.toPacketBuffer = toPacketBuffer;
|
|
20
|
+
exports.splitBuffer = splitBuffer;
|
|
21
|
+
exports.stringifyBuffer = stringifyBuffer;
|
|
22
|
+
function splitArray(arr, size) {
|
|
23
|
+
const result = [];
|
|
24
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
25
|
+
const chunk = arr.slice(i, i + size);
|
|
26
|
+
result.push(chunk);
|
|
27
|
+
}
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
function toPacketBuffer(code, data) {
|
|
31
|
+
const buffer = new Uint8Array(1 + data.length);
|
|
32
|
+
buffer[0] = code;
|
|
33
|
+
buffer.set(data, 1);
|
|
34
|
+
return buffer;
|
|
35
|
+
}
|
|
36
|
+
function splitBuffer(arr, x) {
|
|
37
|
+
return splitArray(Array.from(arr), x);
|
|
38
|
+
}
|
|
39
|
+
function stringifyBuffer(data) {
|
|
40
|
+
const contents = Array.from(data).map(n => n.toString(16).padStart(2, "0")).join(" ");
|
|
41
|
+
return `<Buffer ${contents}>`;
|
|
42
|
+
}
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
* Licensed under the Apache License, Version 2.0.
|
|
4
|
-
*/
|
|
5
1
|
export declare function processCharCodes(text: string): number[];
|
|
6
2
|
export declare function convertCharCodes(codes: number[]): string;
|
|
7
3
|
export declare function encodeHuffman(text: string): Uint8Array;
|
|
@@ -1,6 +1,51 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
2
3
|
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
4
16
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.processCharCodes = processCharCodes;
|
|
19
|
+
exports.convertCharCodes = convertCharCodes;
|
|
20
|
+
exports.encodeHuffman = encodeHuffman;
|
|
21
|
+
exports.decodeHuffman = decodeHuffman;
|
|
22
|
+
exports.as8String = as8String;
|
|
23
|
+
const CompressionUtil_1 = require("./packets/CompressionUtil");
|
|
24
|
+
function processCharCodes(text) {
|
|
25
|
+
return Array.from(text, char => char.codePointAt(0));
|
|
26
|
+
}
|
|
27
|
+
function convertCharCodes(codes) {
|
|
28
|
+
return String.fromCodePoint(...codes);
|
|
29
|
+
}
|
|
30
|
+
const codeToChar = { "1000001": "w", "1000010": "m", "1000100": "u", "1000101": "c", "1000110": "l", "1000111": "d", "1001001": "r", "1001010": "h", "1001100": "s", "1001101": "n", "1001110": "i", "1001111": "o", "1010001": "a", "1010010": "t", "1010100": "e", "1010101": "", "10000000": "", "10000001": "", "10000111": "", "10010000": "
", "10010001": "", "10010111": "", "10100000": "", "10100001": "", "10100111": "", "10101100": "", "10101101": "~", "10101111": "}", "10110000": "|", "10110001": "{", "10110011": "`", "10110100": "_", "10110101": "^", "10110111": "]", "10111000": "", "10111001": "[", "10111011": "@", "10111100": "?", "10111101": ">", "10111111": "=", "11000000": "<", "11000001": ";", "11000011": ":", "11000100": "9", "11000101": "8", "11000111": "7", "11001000": "6", "11001001": "5", "11001011": "4", "11001100": "3", "11001101": "2", "11001111": "1", "11010000": "0", "11010001": "/", "11010011": ".", "11010100": "-", "11010101": ",", "11010111": "+", "11011000": "*", "11011001": ")", "11011011": "(", "11011100": "'", "11011101": "&", "11011111": "$", "11100001": "#", "11100010": "\"", "11100100": "!", "11100101": "\u001f", "11100110": "\u001e", "11100111": "\u001d", "11101001": "\u001c", "11101010": "\u001b", "11101100": "\u001a", "11101101": "\u0019", "11101110": "\u0018", "11101111": "\u0017", "11110001": "\u0016", "11110010": "\u0015", "11110100": "\u0014", "11110101": "\u0013", "11110110": "\u0012", "11110111": "\u0011", "11111001": "\u0010", "11111010": "\u000f", "11111100": "\u000e", "11111101": "", "11111110": "", "11111111": "", "100001100": "Ã", "100101100": "Â", "100101101": "Á", "101001100": "À", "101011100": "¿", "101011101": "¾", "101100100": "½", "101101100": "¼", "101101101": "»", "101110100": "º", "101111100": "¹", "101111101": "¸", "110000100": "·", "110001100": "¶", "110001101": "µ", "110010100": "´", "110011100": "³", "110011101": "²", "110100100": "±", "110101100": "°", "110101101": "¯", "110110100": "®", "110111100": "", "110111101": "%", "111000000": "¬", "111000001": "«", "111000111": "ª", "111010000": "©", "111010001": "¨", "111010111": "§", "111100000": "¦", "111100001": "¥", "111100111": "¤", "111110000": "£", "111110001": "¢", "111110111": "¡", "1000011010": "á", "1010011010": "à", "1010011011": "ß", "1011001010": "Þ", "1011101010": "Ý", "1011101011": "Ü", "1100001010": "Û", "1100101010": "Ú", "1100101011": "Ù", "1101001010": "Ø", "1101101010": "×", "1101101011": "Ö", "1110001100": "Õ", "1110101100": "Ô", "1110101101": "Ó", "1111001100": "Ò", "1111101100": "Ñ", "1111101101": "Ð", "00000000": " ", "00000001": "", "0000001": "\n", "0000010": "", "000001100": "Ï", "0000011010": "ç", "00000110110": "ó", "000001101110": "ù", "0000011011110": "ü", "00000110111110": "þ", "00000110111111": "ý", "00000111": "", "0000100": "\b", "0000101": "\u0007", "0000110": "\u0006", "0000111": "\u0005", "00010000": "", "00010001": "", "0001001": "\u0004", "0001010": "\u0003", "000101100": "Î", "000101101": "Í", "00010111": "", "0001100": "\u0002", "0001101": "\u0001", "0001110": "", "0001111": "Z", "00100000": "", "00100001": "", "0010001": "Q", "0010010": "X", "001001100": "Ì", "0010011010": "æ", "0010011011": "å", "00100111": "", "0010100": "J", "0010101": "K", "0010110": "V", "0010111": "B", "00110000": "", "00110001": "", "0011001": "P", "0011010": "Y", "001101100": "Ë", "001101101": "Ê", "00110111": "", "0011100": "G", "0011101": "F", "0011110": "W", "0011111": "M", "01000000": "", "01000001": "", "0100001": "U", "0100010": "C", "010001100": "É", "0100011010": "ä", "01000110110": "ò", "01000110111": "ñ", "01000111": "", "0100100": "L", "0100101": "D", "0100110": "R", "0100111": "H", "01010000": "", "01010001": "", "0101001": "S", "0101010": "N", "010101100": "È", "010101101": "Ç", "01010111": "", "0101100": "I", "0101101": "O", "0101110": "A", "0101111": "T", "01100000": "", "01100001": "", "0110001": "E", "0110010": "z", "011001100": "Æ", "0110011010": "ã", "0110011011": "â", "01100111": "", "0110100": "q", "0110101": "x", "0110110": "j", "0110111": "k", "01110000": "", "01110001": "", "0111001": "v", "0111010": "b", "011101100": "Å", "011101101": "Ä", "01110111": "", "0111100": "p", "0111101": "y", "0111110": "g", "0111111": "f", "10000110110": "ð", "100001101110": "ø", "100001101111": "÷", "10110010110": "ï", "10110010111": "î", "11000010110": "í", "110000101110": "ö", "1100001011110": "û", "1100001011111": "ú", "11010010110": "ì", "11010010111": "ë", "11100011010": "ê", "111000110110": "õ", "111000110111": "ô", "11110011010": "é", "11110011011": "è" };
|
|
31
|
+
const charToCode = Object.fromEntries(Object.entries(codeToChar).map(([code, char]) => [char, code]));
|
|
32
|
+
function encodeHuffman(text) {
|
|
33
|
+
return (0, CompressionUtil_1.bitsToBytes)(Array.from(text).map(char => charToCode[char]).join(""));
|
|
34
|
+
}
|
|
35
|
+
;
|
|
36
|
+
function decodeHuffman(bits) {
|
|
37
|
+
let result = '';
|
|
38
|
+
let buffer = '';
|
|
39
|
+
for (const bit of bits) {
|
|
40
|
+
buffer += bit;
|
|
41
|
+
if (codeToChar[buffer]) {
|
|
42
|
+
result += codeToChar[buffer];
|
|
43
|
+
buffer = '';
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
;
|
|
49
|
+
function as8String(data) {
|
|
50
|
+
return convertCharCodes(Array.from(data));
|
|
51
|
+
}
|
|
@@ -1,6 +1,60 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
2
3
|
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.SET_PACKAGES = exports.ENUM_KEY_TO_TAG = exports.ENUM_TAG_TO_KEY = exports.MAX_ENUM_SIZE = void 0;
|
|
19
|
+
exports.DefineEnum = DefineEnum;
|
|
20
|
+
exports.WrapEnum = WrapEnum;
|
|
21
|
+
exports.DeWrapEnum = DeWrapEnum;
|
|
22
|
+
const CompressionUtil_1 = require("../packets/CompressionUtil");
|
|
23
|
+
const EnumType_1 = require("./EnumType");
|
|
24
|
+
exports.MAX_ENUM_SIZE = CompressionUtil_1.MAX_BYTE;
|
|
25
|
+
exports.ENUM_TAG_TO_KEY = {};
|
|
26
|
+
exports.ENUM_KEY_TO_TAG = {};
|
|
27
|
+
exports.SET_PACKAGES = {};
|
|
28
|
+
/**
|
|
29
|
+
* Defines an enum with its tag and values
|
|
30
|
+
* @param tag The tag of the enum; used for WrapEnum(tag, ...)
|
|
31
|
+
* @param values The possible values of the enum
|
|
32
|
+
* @returns A packaged enum
|
|
33
|
+
*/
|
|
34
|
+
function DefineEnum(tag, values) {
|
|
35
|
+
const setPkg = exports.SET_PACKAGES[tag];
|
|
36
|
+
if (setPkg) {
|
|
37
|
+
if (setPkg.values.find((n, i) => values[i] != n))
|
|
38
|
+
throw new Error(`Pre-existing enum package of tag '${tag}' is set and different!`);
|
|
39
|
+
return setPkg;
|
|
40
|
+
}
|
|
41
|
+
if (values.length > exports.MAX_ENUM_SIZE)
|
|
42
|
+
throw new Error(`An enum can only hold ${exports.MAX_ENUM_SIZE} possible values.`);
|
|
43
|
+
exports.ENUM_TAG_TO_KEY[tag] = Object.fromEntries(values.map((v, i) => [v, i]));
|
|
44
|
+
exports.ENUM_KEY_TO_TAG[tag] = Object.fromEntries(values.map((v, i) => [i, v]));
|
|
45
|
+
return exports.SET_PACKAGES[tag] = new EnumType_1.EnumPackage(tag, values);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Wraps an enum into a transmittable format
|
|
49
|
+
* @param tag The tag of the enum
|
|
50
|
+
* @param value The value to send
|
|
51
|
+
* @returns A transmittable enum value
|
|
4
52
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
53
|
+
function WrapEnum(tag, value) {
|
|
54
|
+
if (!(value in exports.ENUM_TAG_TO_KEY[tag]))
|
|
55
|
+
throw new Error(`Value "${value}" does not exist in enum "${tag}"`);
|
|
56
|
+
return exports.ENUM_TAG_TO_KEY[tag][value];
|
|
57
|
+
}
|
|
58
|
+
function DeWrapEnum(tag, value) {
|
|
59
|
+
return exports.ENUM_KEY_TO_TAG[tag][value];
|
|
60
|
+
}
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
* Licensed under the Apache License, Version 2.0.
|
|
4
|
-
*/
|
|
5
1
|
export declare const TYPE_CONVERSION_MAP: Record<number, (data: string) => string | number | boolean | undefined | null>;
|
|
6
2
|
export type EnumValue = string | number | boolean | undefined | null;
|
|
@@ -1,6 +1,72 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
2
3
|
* Copyright 2026 Lily (liwybloc)
|
|
3
|
-
*
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
4
16
|
*/
|
|
5
|
-
|
|
6
|
-
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.EnumPackage = exports.TYPE_CONVERSION_MAP = void 0;
|
|
19
|
+
const StringUtil_1 = require("../StringUtil");
|
|
20
|
+
const EnumHandler_1 = require("./EnumHandler");
|
|
21
|
+
const TYPE_INDEX_MAP = {
|
|
22
|
+
'string': 0,
|
|
23
|
+
'number': 1,
|
|
24
|
+
'boolean': 2,
|
|
25
|
+
'undefined': 3,
|
|
26
|
+
'object': 4, // to handle null bug
|
|
27
|
+
};
|
|
28
|
+
exports.TYPE_CONVERSION_MAP = {
|
|
29
|
+
0: (d) => d,
|
|
30
|
+
1: (d) => parseFloat(d),
|
|
31
|
+
2: (d) => d == 'true',
|
|
32
|
+
3: () => undefined,
|
|
33
|
+
4: () => null,
|
|
34
|
+
};
|
|
35
|
+
function getTypedIndex(data) {
|
|
36
|
+
const type = typeof data;
|
|
37
|
+
if (!(type in TYPE_INDEX_MAP) && data != null)
|
|
38
|
+
throw new Error(`Cannot serialize type "${type}" in an enum!`);
|
|
39
|
+
return TYPE_INDEX_MAP[type];
|
|
40
|
+
}
|
|
41
|
+
/** @internal */
|
|
42
|
+
class EnumPackage {
|
|
43
|
+
tag;
|
|
44
|
+
values;
|
|
45
|
+
constructor(tag, values) {
|
|
46
|
+
this.tag = tag;
|
|
47
|
+
this.values = values;
|
|
48
|
+
this.wrap = this.wrap.bind(this);
|
|
49
|
+
}
|
|
50
|
+
serialize() {
|
|
51
|
+
const tag = (0, StringUtil_1.processCharCodes)(this.tag);
|
|
52
|
+
return [
|
|
53
|
+
this.tag.length, // tag length
|
|
54
|
+
...tag, // tag
|
|
55
|
+
this.values.length, // value count
|
|
56
|
+
...this.values.map(v => [
|
|
57
|
+
String(v).length, // value length
|
|
58
|
+
getTypedIndex(v), // value type
|
|
59
|
+
...(0, StringUtil_1.processCharCodes)(String(v)) // value
|
|
60
|
+
]).flat(),
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Wraps a value with this enum package
|
|
65
|
+
* @param value Value to wrap
|
|
66
|
+
* @returns Network encoded value
|
|
67
|
+
*/
|
|
68
|
+
wrap(value) {
|
|
69
|
+
return (0, EnumHandler_1.WrapEnum)(this.tag, value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.EnumPackage = EnumPackage;
|