sonic-ws 1.3.1 → 1.3.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/index.js CHANGED
@@ -1,9 +1,19 @@
1
- /**
1
+ "use strict";
2
+ /*
2
3
  * Copyright 2026 Lily (liwybloc)
3
- * Licensed under the Apache License, Version 2.0.
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
- "use strict";
6
-
7
17
  Object.defineProperty(exports, "__esModule", { value: true });
8
18
  exports.WrapEnum = exports.DefineEnum = exports.UnFlattenData = exports.FlattenData = exports.CreateEnumPacket = exports.CreateObjPacket = exports.CreatePacket = exports.PacketType = exports.SonicWSServer = exports.SonicWSConnection = exports.SonicWS = void 0;
9
19
  var ClientNode_1 = require("./ws/client/node/ClientNode");
package/dist/version.js CHANGED
@@ -2,14 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.SERVER_SUFFIX_NUMS = exports.SERVER_SUFFIX = exports.VERSION = void 0;
9
- const StringUtil_1 = require("./ws/util/StringUtil");
10
-
11
- exports.VERSION = 20;
12
-
13
- exports.SERVER_SUFFIX = "SWS";
14
-
15
- exports.SERVER_SUFFIX_NUMS = (0, StringUtil_1.processCharCodes)(exports.SERVER_SUFFIX);
6
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.SERVER_SUFFIX_NUMS=exports.SERVER_SUFFIX=exports.VERSION=void 0;const e=require("./ws/util/StringUtil");exports.VERSION=20,exports.SERVER_SUFFIX="SWS",exports.SERVER_SUFFIX_NUMS=(0,e.processCharCodes)(exports.SERVER_SUFFIX);
@@ -2,8 +2,71 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- import { ConnectionMiddleware, MiddlewareHolder } from "./PacketProcessor";
5
+ import { ConnectionMiddleware, IMiddlewareHolder, MiddlewareHolder } from "./PacketProcessor";
6
6
  import { BatchHelper } from "./util/packets/BatchHelper";
7
+ /**
8
+ * Holds shared connection values. Lets helper functions work on client and server.
9
+ */
10
+ export interface IConnection<T> extends IMiddlewareHolder<ConnectionMiddleware> {
11
+ /**
12
+ * List of timers.
13
+ * For internal use only.
14
+ */
15
+ _timers: Record<number, [number, (closed: boolean) => void, boolean]>;
16
+ /**
17
+ * Sets a timeout that will automatically end when the socket closes
18
+ * @param call The function to call
19
+ * @param time The time between now and the call (ms)
20
+ * @param callOnClose If the callback should be fired anyways when the socket closes
21
+ * @returns The timeout id to be used with socket.clearInterval(id)
22
+ */
23
+ setTimeout(call: () => void, time: number, callOnClose: boolean): number;
24
+ /**
25
+ * Sets an interval that will automatically end when the socket closes
26
+ * @param call The function to call
27
+ * @param time The time between calls (ms)
28
+ * @returns The interval id to be used with socket.clearInterval(id)
29
+ */
30
+ setInterval(call: () => void, time: number): number;
31
+ /**
32
+ * Clears a timeout/interval
33
+ * @param id The timeout id
34
+ */
35
+ clearTimeout(index: number): void;
36
+ /**
37
+ * Clears an interval
38
+ *
39
+ * Delegates to `clearTimeout`
40
+ * @param id The interval id
41
+ */
42
+ clearInterval(index: number): void;
43
+ /**
44
+ * Sends raw uint8array data through the connection
45
+ */
46
+ raw_send(data: Uint8Array): void;
47
+ /**
48
+ * Listens for all messages rawly
49
+ * @param listener Callback for when data is received
50
+ */
51
+ raw_onmessage(listener: (data: T) => void): void;
52
+ /**
53
+ * Closes the connection
54
+ */
55
+ close(code?: number, reason?: string): void;
56
+ /**
57
+ * Checks if the connection is closed
58
+ * @returns If it's closed or not
59
+ */
60
+ isClosed(): boolean;
61
+ /**
62
+ * Sets the name of this connection for the debug menu; good for setting e.g. usernames on games
63
+ */
64
+ setName(name: string): Promise<void>;
65
+ /**
66
+ * @returns Name of the socket, defaults to Socket [ID] or LocalSocket unless set with setName()
67
+ */
68
+ getName(): string;
69
+ }
7
70
  export declare abstract class Connection<T extends {
8
71
  readyState: number;
9
72
  send: (u: Uint8Array) => void;
@@ -2,115 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.CloseCodes = exports.Connection = void 0;
9
- exports.getClosureCause = getClosureCause;
10
- const PacketProcessor_1 = require("./PacketProcessor");
11
- const BatchHelper_1 = require("./util/packets/BatchHelper");
12
- class Connection extends PacketProcessor_1.MiddlewareHolder {
13
- listeners;
14
- name;
15
- closed = false;
16
- socket;
17
- _timers = {};
18
- batcher;
19
- _on;
20
- _off;
21
-
22
- id;
23
- constructor(socket, id, name, addListener, removeListener) {
24
- super();
25
- this.id = id;
26
- this.listeners = {};
27
- this.name = name;
28
- this.socket = socket;
29
- this.batcher = new BatchHelper_1.BatchHelper();
30
- this._on = addListener;
31
- this._off = removeListener;
32
- this._on("close", () => {
33
- this.callMiddleware('onStatusChange', WebSocket.CLOSED);
34
- this.closed = true;
35
- for (const [id, callback, shouldCall] of Object.values(this._timers)) {
36
- this.clearTimeout(id);
37
- if (shouldCall)
38
- callback(true);
39
- }
40
- });
41
- this._on('open', () => this.callMiddleware('onStatusChange', WebSocket.OPEN));
42
- }
43
- setTimeout(call, time, callOnClose = false) {
44
- const timeout = setTimeout(() => {
45
- call();
46
- this.clearTimeout(timeout);
47
- }, time);
48
- this._timers[timeout] = [timeout, call, callOnClose];
49
- return timeout;
50
- }
51
- setInterval(call, time, callOnClose = false) {
52
- const interval = setInterval(call, time);
53
- this._timers[interval] = [interval, call, callOnClose];
54
- return interval;
55
- }
56
- clearTimeout(id) {
57
- clearTimeout(id);
58
- delete this._timers[id];
59
- }
60
- clearInterval(id) {
61
- this.clearTimeout(id);
62
- }
63
- raw_send(data) {
64
- this.socket.send(data);
65
- }
66
- raw_onmessage(listener) {
67
- this._on("message", listener);
68
- }
69
- close(code = 1000, reason) {
70
- this.closed = true;
71
- this.socket.close(code, reason?.toString());
72
- }
73
- isClosed() {
74
- return this.closed || this.socket.readyState == WebSocket.CLOSED;
75
- }
76
- async setName(name) {
77
- if (await this.callMiddleware("onNameChange", name))
78
- return;
79
- this.name = name;
80
- }
81
- getName() {
82
- return this.name;
83
- }
84
- }
85
- exports.Connection = Connection;
86
- var CloseCodes;
87
- (function (CloseCodes) {
88
- CloseCodes[CloseCodes["RATELIMIT"] = 4000] = "RATELIMIT";
89
- CloseCodes[CloseCodes["SMALL"] = 4001] = "SMALL";
90
- CloseCodes[CloseCodes["INVALID_KEY"] = 4002] = "INVALID_KEY";
91
- CloseCodes[CloseCodes["INVALID_PACKET"] = 4003] = "INVALID_PACKET";
92
- CloseCodes[CloseCodes["INVALID_DATA"] = 4004] = "INVALID_DATA";
93
- CloseCodes[CloseCodes["REPEATED_HANDSHAKE"] = 4005] = "REPEATED_HANDSHAKE";
94
- CloseCodes[CloseCodes["DISABLED_PACKET"] = 4006] = "DISABLED_PACKET";
95
- CloseCodes[CloseCodes["MIDDLEWARE"] = 4007] = "MIDDLEWARE";
96
- CloseCodes[CloseCodes["MANUAL_SHUTDOWN"] = 4008] = "MANUAL_SHUTDOWN";
97
- })(CloseCodes || (exports.CloseCodes = CloseCodes = {}));
98
- function getClosureCause(id) {
99
- if (id >= 4000) {
100
- return CloseCodes[id] ?? 'UNKNOWN';
101
- }
102
- switch (id) {
103
- case 1000:
104
- return 'NORMAL_CLOSURE';
105
- case 1001:
106
- return 'GOING_AWAY';
107
- case 1002:
108
- return 'PROTOCOL_ERROR';
109
- case 1003:
110
- return 'UNSUPPORTED_DATA';
111
- case 1006:
112
- return 'ABNORMAL_CLOSURE';
113
- default:
114
- return 'UNKNOWN';
115
- }
116
- }
6
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.CloseCodes=exports.Connection=void 0,exports.getClosureCause=function(e){if(e>=4e3)return r[e]??"UNKNOWN";switch(e){case 1e3:return"NORMAL_CLOSURE";case 1001:return"GOING_AWAY";case 1002:return"PROTOCOL_ERROR";case 1003:return"UNSUPPORTED_DATA";case 1006:return"ABNORMAL_CLOSURE";default:return"UNKNOWN"}};const e=require("./PacketProcessor"),t=require("./util/packets/BatchHelper");class s extends e.MiddlewareHolder{listeners;name;closed=!1;socket;_timers={};batcher;_on;_off;id;constructor(e,s,r,o,i){super(),this.id=s,this.listeners={},this.name=r,this.socket=e,this.batcher=new t.BatchHelper,this._on=o,this._off=i,this._on("close",()=>{this.callMiddleware("onStatusChange",WebSocket.CLOSED),this.closed=!0;for(const[e,t,s]of Object.values(this._timers))this.clearTimeout(e),s&&t(!0)}),this._on("open",()=>this.callMiddleware("onStatusChange",WebSocket.OPEN))}setTimeout(e,t,s=!1){const r=setTimeout(()=>{e(),this.clearTimeout(r)},t);return this._timers[r]=[r,e,s],r}setInterval(e,t,s=!1){const r=setInterval(e,t);return this._timers[r]=[r,e,s],r}clearTimeout(e){clearTimeout(e),delete this._timers[e]}clearInterval(e){this.clearTimeout(e)}raw_send(e){this.socket.send(e)}raw_onmessage(e){this._on("message",e)}close(e=1e3,t){this.closed=!0,this.socket.close(e,t?.toString())}isClosed(){return this.closed||this.socket.readyState==WebSocket.CLOSED}async setName(e){await this.callMiddleware("onNameChange",e)||(this.name=e)}getName(){return this.name}}var r;exports.Connection=s,function(e){e[e.RATELIMIT=4e3]="RATELIMIT",e[e.SMALL=4001]="SMALL",e[e.INVALID_KEY=4002]="INVALID_KEY",e[e.INVALID_PACKET=4003]="INVALID_PACKET",e[e.INVALID_DATA=4004]="INVALID_DATA",e[e.REPEATED_HANDSHAKE=4005]="REPEATED_HANDSHAKE",e[e.DISABLED_PACKET=4006]="DISABLED_PACKET",e[e.MIDDLEWARE=4007]="MIDDLEWARE",e[e.MANUAL_SHUTDOWN=4008]="MANUAL_SHUTDOWN"}(r||(exports.CloseCodes=r={}));
@@ -2,41 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.MiddlewareHolder = void 0;
9
- class MiddlewareHolder {
10
- middlewares = [];
11
- addMiddleware(middleware) {
12
- this.middlewares.push(middleware);
13
- const m = middleware;
14
- try {
15
- if (typeof m.init === 'function')
16
- m.init(this);
17
- }
18
- catch (e) {
19
- console.warn('Middleware init threw an error:', e);
20
- }
21
- }
22
- async callMiddleware(method, ...values) {
23
- let cancelled = false;
24
- for (const middleware of this.middlewares) {
25
- const fn = middleware[method];
26
- if (!fn)
27
- continue;
28
- try {
29
- if (await fn(...values)) {
30
- cancelled = true;
31
- }
32
- }
33
- catch (e) {
34
- console.warn(`Middleware ${String(method)} threw an error:`, e);
35
- }
36
- }
37
- return cancelled;
38
- }
39
- }
40
- exports.MiddlewareHolder = MiddlewareHolder;
41
- ;
42
- ;
6
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.MiddlewareHolder=void 0;exports.MiddlewareHolder=class{middlewares=[];addMiddleware(e){this.middlewares.push(e);const r=e;try{"function"==typeof r.init&&r.init(this)}catch(e){console.warn("Middleware init threw an error:",e)}}async callMiddleware(e,...r){let t=!1;for(const d of this.middlewares){const i=d[e];if(i)try{await i(...r)&&(t=!0)}catch(r){console.warn(`Middleware ${String(e)} threw an error:`,r)}}return t}};
@@ -2,223 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.SonicWSCore = void 0;
9
- const PacketHolder_1 = require("../../util/packets/PacketHolder");
10
- const CompressionUtil_1 = require("../../util/packets/CompressionUtil");
11
- const PacketUtils_1 = require("../../util/packets/PacketUtils");
12
- const version_1 = require("../../../version");
13
- const Packets_1 = require("../../packets/Packets");
14
- const BatchHelper_1 = require("../../util/packets/BatchHelper");
15
- const BufferUtil_1 = require("../../util/BufferUtil");
16
- const Connection_1 = require("../../Connection");
17
- const StringUtil_1 = require("../../util/StringUtil");
18
- class SonicWSCore extends Connection_1.Connection {
19
- preListen;
20
- clientPackets = new PacketHolder_1.PacketHolder();
21
- serverPackets = new PacketHolder_1.PacketHolder();
22
- pastKeys = false;
23
- readyListeners = [];
24
- bufferHandler;
25
- _timers = {};
26
- asyncData = {};
27
- asyncMap = {};
28
- constructor(ws, bufferHandler, on, off) {
29
- super(ws, -1, "LocalSocket", on, off);
30
- this.socket = ws;
31
- this.preListen = {};
32
- this.invalidPacket = this.invalidPacket.bind(this);
33
- this.serverKeyHandler = this.serverKeyHandler.bind(this);
34
- this.messageHandler = this.messageHandler.bind(this);
35
- this._on('message', this.serverKeyHandler);
36
- this._on('close', () => {
37
- this.callMiddleware('onStatusChange', WebSocket.CLOSED);
38
- for (const [id, callback, shouldCall] of Object.values(this._timers)) {
39
- this.clearTimeout(id);
40
- if (shouldCall)
41
- callback(true);
42
- }
43
- for (const packet of this.clientPackets.getPackets()) {
44
- delete packet.lastSent[0];
45
- }
46
- for (const packet of this.serverPackets.getPackets()) {
47
- delete packet.lastReceived[0];
48
- }
49
- });
50
- this.bufferHandler = bufferHandler;
51
- }
52
- reading = false;
53
- readQueue = [];
54
- async serverKeyHandler(event) {
55
- if (this.reading)
56
- return this.readQueue.push(event);
57
- this.reading = true;
58
- const cdata = await this.bufferHandler(event);
59
- if (cdata.length < 3 || (0, StringUtil_1.as8String)(cdata.slice(0, 3)) != version_1.SERVER_SUFFIX) {
60
- this.close(1000);
61
- throw new Error("The server requested is not a Sonic WS server.");
62
- }
63
- const version = cdata[3];
64
- if (version != version_1.VERSION) {
65
- this.close(1000);
66
- throw new Error(`Version mismatch: ${version > version_1.VERSION ? "client" : "server"} is outdated (server: ${version}, client: ${version_1.VERSION})`);
67
- }
68
- const data = await (0, CompressionUtil_1.decompressGzip)(cdata.subarray(4, cdata.length));
69
- const [ckOff, id] = (0, CompressionUtil_1.readVarInt)(data, 0);
70
- this.id = id;
71
- const [valuesOff, ckLength] = (0, CompressionUtil_1.readVarInt)(data, ckOff);
72
- const ckData = data.subarray(valuesOff, valuesOff + ckLength);
73
- this.clientPackets.holdPackets(Packets_1.Packet.deserializeAll(ckData, true));
74
- const skData = data.subarray(valuesOff + ckLength, data.length);
75
- this.serverPackets.holdPackets(Packets_1.Packet.deserializeAll(skData, true));
76
- this.batcher.registerSendPackets(this.clientPackets, this);
77
- for (const p of this.serverPackets.getPackets()) {
78
- const key = this.serverPackets.getKey(p.tag);
79
- this.asyncMap[key] = p.async;
80
- if (p.async) {
81
- this.asyncData[key] = [false, []];
82
- }
83
- }
84
- Object.keys(this.preListen).forEach(tag => this.preListen[tag].forEach(listener => {
85
-
86
- if (!this.serverPackets.hasTag(tag))
87
- return console.error(new Error(`The server does not send the packet with tag "${tag}"!`));
88
- this.listen(tag, listener);
89
- }));
90
- this.preListen = null;
91
- this.pastKeys = true;
92
- this.readyListeners.forEach(l => l());
93
- this.readyListeners = null;
94
- this._off('message', this.serverKeyHandler);
95
- this._on('message', this.messageHandler);
96
- this.readQueue.forEach(e => this.messageHandler(e));
97
- this.readQueue = [];
98
- }
99
- invalidPacket(listened) {
100
- console.error(listened);
101
- throw new Error("An error occured with data from the server!! This is probably my fault.. make an issue at https://github.com/liwybloc/sonic-ws");
102
- }
103
- listenLock = false;
104
- packetQueue = [];
105
- async listenPacket(data, tag, packetQueue, isAsync, asyncData) {
106
- const listeners = this.listeners[tag];
107
- if (!listeners)
108
- return console.warn("Warn: No listener for packet " + tag);
109
- await this.enqueuePacket(data, listeners, packetQueue, isAsync, asyncData);
110
- await this.callMiddleware('onReceive_post', tag, typeof data == 'string' ? [data] : data[0]);
111
- }
112
- isAsync(code) {
113
- return this.asyncMap[code];
114
- }
115
- async enqueuePacket(data, listeners, packetQueue, isAsync, asyncData) {
116
- await (0, PacketUtils_1.listenPacket)(data, listeners, this.invalidPacket);
117
- await this.triggerNextPacket(packetQueue, isAsync, asyncData);
118
- }
119
- async triggerNextPacket(packetQueue, isAsync, asyncData) {
120
- if (isAsync)
121
- asyncData[0] = false;
122
- else
123
- this.listenLock = false;
124
- if (packetQueue.length > 0) {
125
- this.dataHandler(packetQueue.shift());
126
- return;
127
- }
128
- }
129
- async dataHandler(data) {
130
- const key = data[0];
131
- const value = data.slice(1);
132
- const isAsync = this.isAsync(key);
133
- let locked;
134
- let packetQueue;
135
- let asyncData;
136
- if (isAsync) {
137
- asyncData = this.asyncData[key];
138
- locked = asyncData[0];
139
- packetQueue = asyncData[1];
140
- }
141
- else {
142
- locked = this.listenLock;
143
- packetQueue = this.packetQueue;
144
- }
145
- if (locked) {
146
- packetQueue.push(data);
147
- return;
148
- }
149
- if (isAsync)
150
- asyncData[0] = true;
151
- else
152
- this.listenLock = true;
153
- const tag = this.serverPackets.getTag(key);
154
- const packet = this.serverPackets.getPacket(tag);
155
- if (await this.callMiddleware('onReceive_pre', packet.tag, data, data.length))
156
- return;
157
- if (packet.rereference && value.length == 0) {
158
- if (packet.lastReceived[0] === undefined)
159
- return this.invalidPacket("No previous value to rereference");
160
- this.listenPacket(packet.lastReceived[0], tag, packetQueue, isAsync, asyncData);
161
- return;
162
- }
163
- if (packet.dataBatching == 0) {
164
- const res = packet.lastReceived[0] = await packet.listen(value, null);
165
- this.listenPacket(res, tag, packetQueue, isAsync, asyncData);
166
- return;
167
- }
168
- const batchData = await BatchHelper_1.BatchHelper.unravelBatch(packet, value, null);
169
- if (typeof batchData == 'string')
170
- return this.invalidPacket(batchData);
171
- batchData.forEach(data => this.listenPacket(data, tag, packetQueue, isAsync, asyncData));
172
- }
173
- async messageHandler(event) {
174
- const data = await this.bufferHandler(event);
175
- if (data.length < 1)
176
- return;
177
- await this.dataHandler(data);
178
- }
179
- listen(tag, listener) {
180
- if (!this.serverPackets.hasTag(tag)) {
181
- console.log("Tag is not available on server: " + tag);
182
- return;
183
- }
184
- (this.listeners[tag] ??= []).push(listener);
185
- }
186
-
187
- raw_onsend(listener) {
188
- this.listeners.send.push(listener);
189
- }
190
- sendQueue = [false, [], undefined];
191
-
192
- async send(tag, ...values) {
193
- if (await this.callMiddleware('onSend_pre', tag, values, Date.now(), performance.now()))
194
- return;
195
- const [code, data, packet] = await (0, PacketUtils_1.processPacket)(this.clientPackets, tag, values, this.sendQueue, 0);
196
- if (packet.dataBatching == 0)
197
- this.raw_send((0, BufferUtil_1.toPacketBuffer)(code, data));
198
- else
199
- this.batcher.batchPacket(code, data);
200
- await this.callMiddleware('onSend_post', tag, data, data.length);
201
- }
202
-
203
- on_ready(listener) {
204
- if (this.pastKeys)
205
- listener();
206
- else
207
- this.readyListeners.push(listener);
208
- }
209
-
210
- on_close(listener) {
211
- this._on("close", listener);
212
- }
213
-
214
- on(tag, listener) {
215
- if (this.socket.readyState !== WebSocket.OPEN) {
216
- if (!this.preListen[tag])
217
- this.preListen[tag] = [];
218
- this.preListen[tag].push(listener);
219
- return;
220
- }
221
- this.listen(tag, listener);
222
- }
223
- }
224
- exports.SonicWSCore = SonicWSCore;
6
+ Object.defineProperty(exports,"__esModule",{value:!0}),exports.SonicWSCore=void 0;const e=require("../../util/packets/PacketHolder"),t=require("../../util/packets/CompressionUtil"),s=require("../../util/packets/PacketUtils"),i=require("../../../version"),a=require("../../packets/Packets"),r=require("../../util/packets/BatchHelper"),n=require("../../util/BufferUtil"),c=require("../../Connection"),o=require("../../util/StringUtil");class h extends c.Connection{preListen;clientPackets=new e.PacketHolder;serverPackets=new e.PacketHolder;pastKeys=!1;readyListeners=[];bufferHandler;_timers={};asyncData={};asyncMap={};constructor(e,t,s,i){super(e,-1,"LocalSocket",s,i),this.socket=e,this.preListen={},this.invalidPacket=this.invalidPacket.bind(this),this.serverKeyHandler=this.serverKeyHandler.bind(this),this.messageHandler=this.messageHandler.bind(this),this._on("message",this.serverKeyHandler),this._on("close",()=>{this.callMiddleware("onStatusChange",WebSocket.CLOSED);for(const[e,t,s]of Object.values(this._timers))this.clearTimeout(e),s&&t(!0);for(const e of this.clientPackets.getPackets())delete e.lastSent[0];for(const e of this.serverPackets.getPackets())delete e.lastReceived[0]}),this.bufferHandler=t}reading=!1;readQueue=[];async serverKeyHandler(e){if(this.reading)return this.readQueue.push(e);this.reading=!0;const s=await this.bufferHandler(e);if(s.length<3||(0,o.as8String)(s.slice(0,3))!=i.SERVER_SUFFIX)throw this.close(1e3),new Error("The server requested is not a Sonic WS server.");const r=s[3];if(r!=i.VERSION)throw this.close(1e3),new Error(`Version mismatch: ${r>i.VERSION?"client":"server"} is outdated (server: ${r}, client: ${i.VERSION})`);const n=await(0,t.decompressGzip)(s.subarray(4,s.length)),[c,h]=(0,t.readVarInt)(n,0);this.id=h;const[l,d]=(0,t.readVarInt)(n,c),u=n.subarray(l,l+d);this.clientPackets.holdPackets(a.Packet.deserializeAll(u,!0));const k=n.subarray(l+d,n.length);this.serverPackets.holdPackets(a.Packet.deserializeAll(k,!0)),this.batcher.registerSendPackets(this.clientPackets,this);for(const e of this.serverPackets.getPackets()){const t=this.serverPackets.getKey(e.tag);this.asyncMap[t]=e.async,e.async&&(this.asyncData[t]=[!1,[]])}Object.keys(this.preListen).forEach(e=>this.preListen[e].forEach(t=>{if(!this.serverPackets.hasTag(e))return console.error(new Error(`The server does not send the packet with tag "${e}"!`));this.listen(e,t)})),this.preListen=null,this.pastKeys=!0,this.readyListeners.forEach(e=>e()),this.readyListeners=null,this._off("message",this.serverKeyHandler),this._on("message",this.messageHandler),this.readQueue.forEach(e=>this.messageHandler(e)),this.readQueue=[]}invalidPacket(e){throw console.error(e),new Error("An error occured with data from the server!! This is probably my fault.. make an issue at https://github.com/liwybloc/sonic-ws")}listenLock=!1;packetQueue=[];async listenPacket(e,t,s,i,a){const r=this.listeners[t];if(!r)return console.warn("Warn: No listener for packet "+t);await this.enqueuePacket(e,r,s,i,a),await this.callMiddleware("onReceive_post",t,"string"==typeof e?[e]:e[0])}isAsync(e){return this.asyncMap[e]}async enqueuePacket(e,t,i,a,r){await(0,s.listenPacket)(e,t,this.invalidPacket),await this.triggerNextPacket(i,a,r)}async triggerNextPacket(e,t,s){t?s[0]=!1:this.listenLock=!1,e.length>0&&this.dataHandler(e.shift())}async dataHandler(e){const t=e[0],s=e.slice(1),i=this.isAsync(t);let a,n,c;if(i?(c=this.asyncData[t],a=c[0],n=c[1]):(a=this.listenLock,n=this.packetQueue),a)return void n.push(e);i?c[0]=!0:this.listenLock=!0;const o=this.serverPackets.getTag(t),h=this.serverPackets.getPacket(o);if(await this.callMiddleware("onReceive_pre",h.tag,e,e.length))return;if(h.rereference&&0==s.length)return void 0===h.lastReceived[0]?this.invalidPacket("No previous value to rereference"):void this.listenPacket(h.lastReceived[0],o,n,i,c);if(0==h.dataBatching){const e=h.lastReceived[0]=await h.listen(s,null);return void this.listenPacket(e,o,n,i,c)}const l=await r.BatchHelper.unravelBatch(h,s,null);if("string"==typeof l)return this.invalidPacket(l);l.forEach(e=>this.listenPacket(e,o,n,i,c))}async messageHandler(e){const t=await this.bufferHandler(e);t.length<1||await this.dataHandler(t)}listen(e,t){this.serverPackets.hasTag(e)?(this.listeners[e]??=[]).push(t):console.log("Tag is not available on server: "+e)}raw_onsend(e){this.listeners.send.push(e)}sendQueue=[!1,[],void 0];async send(e,...t){if(await this.callMiddleware("onSend_pre",e,t,Date.now(),performance.now()))return;const[i,a,r]=await(0,s.processPacket)(this.clientPackets,e,t,this.sendQueue,0);0==r.dataBatching?this.raw_send((0,n.toPacketBuffer)(i,a)):this.batcher.batchPacket(i,a),await this.callMiddleware("onSend_post",e,a,a.length)}on_ready(e){this.pastKeys?e():this.readyListeners.push(e)}on_close(e){this._on("close",e)}on(e,t){if(this.socket.readyState!==WebSocket.OPEN)return this.preListen[e]||(this.preListen[e]=[]),void this.preListen[e].push(t);this.listen(e,t)}}exports.SonicWSCore=h;
@@ -2,21 +2,5 @@
2
2
  * Copyright 2026 Lily (liwybloc)
3
3
  * Licensed under the Apache License, Version 2.0.
4
4
  */
5
- "use strict";
6
5
 
7
- var __importDefault = (this && this.__importDefault) || function (mod) {
8
- return (mod && mod.__esModule) ? mod : { "default": mod };
9
- };
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.SonicWS = void 0;
12
- const ws_1 = __importDefault(require("ws"));
13
- const ClientCore_1 = require("../core/ClientCore");
14
-
15
- class SonicWS extends ClientCore_1.SonicWSCore {
16
-
17
- constructor(url, options) {
18
- const ws = new ws_1.default.WebSocket(url, options);
19
- super(ws, (val) => Promise.resolve(new Uint8Array(val)), ws.on.bind(ws), ws.removeEventListener.bind(ws));
20
- }
21
- }
22
- exports.SonicWS = SonicWS;
6
+ var e=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(exports,"__esModule",{value:!0}),exports.SonicWS=void 0;const r=e(require("ws")),o=require("../core/ClientCore");class t extends o.SonicWSCore{constructor(e,o){const t=new r.default.WebSocket(e,o);super(t,e=>Promise.resolve(new Uint8Array(e)),t.on.bind(t),t.removeEventListener.bind(t))}}exports.SonicWS=t;