sonic-ws 1.1.1 → 1.2.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 +5 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/ws/client/core/ClientCore.d.ts +2 -1
- package/dist/ws/client/core/ClientCore.js +17 -15
- package/dist/ws/packets/PacketProcessors.d.ts +4 -10
- package/dist/ws/packets/PacketProcessors.js +198 -124
- package/dist/ws/packets/PacketType.d.ts +7 -1
- package/dist/ws/packets/PacketType.js +6 -0
- package/dist/ws/packets/Packets.d.ts +10 -6
- package/dist/ws/packets/Packets.js +39 -40
- package/dist/ws/server/SonicWSConnection.d.ts +1 -1
- package/dist/ws/server/SonicWSConnection.js +5 -5
- package/dist/ws/server/SonicWSServer.d.ts +4 -2
- package/dist/ws/server/SonicWSServer.js +20 -17
- package/dist/ws/util/packets/BatchHelper.d.ts +1 -1
- package/dist/ws/util/packets/BatchHelper.js +2 -2
- package/dist/ws/util/packets/CompressionUtil.d.ts +7 -0
- package/dist/ws/util/packets/CompressionUtil.js +202 -1
- package/dist/ws/util/packets/PacketHolder.d.ts +1 -1
- package/dist/ws/util/packets/PacketHolder.js +1 -1
- package/dist/ws/util/packets/PacketUtils.d.ts +10 -1
- package/dist/ws/util/packets/PacketUtils.js +26 -12
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -7,8 +7,9 @@ SonicWS is an ultra-lightweight, high-performance WebSocket library focused on m
|
|
|
7
7
|
Compression:
|
|
8
8
|
- Lossless compression up to 70% or more (for example, 38kb -> 14kb)
|
|
9
9
|
- Optimized bandwidth for many different types to fit special constraints
|
|
10
|
-
- Automatic helpers to flatten typed nested arrays for maximum wire efficiency (for example, [[1,
|
|
10
|
+
- Automatic helpers to flatten typed nested arrays for maximum wire efficiency (for example, [[1,false,"text"],[4,true,"other"]] to [[1,4],[false,true],["text,"other"]])
|
|
11
11
|
- Uses raw binary bytes to transmit data as efficiently as possible while still using high level readable code
|
|
12
|
+
- Built-in ability to use compression libraries
|
|
12
13
|
|
|
13
14
|
Developer Friendly:
|
|
14
15
|
- Predefined data types of various sized integers, single and double precision floating point numbers, strings, enums, etc. and RAW to allow for developers to do anything they want
|
|
@@ -38,8 +39,9 @@ Developer Experience:
|
|
|
38
39
|
- Debug tools for socket ids, byte size, data logging, etc. for troubleshooting
|
|
39
40
|
- Very minimal learning curve, easy to work in
|
|
40
41
|
- JSDoc's for understanding; immensely intuitive (personally, I took a break for half a year and came back and snapped right back in)
|
|
42
|
+
- Almost every case has a pre-made wire optimization and boilerplate removal.
|
|
41
43
|
|
|
42
|
-
Whether you're making a real-time game, a dashboard, a distributed system, or anything else, SonicWS gets you safe, structured packets
|
|
44
|
+
Whether you're making a real-time game, a dashboard, a distributed system, or anything else, SonicWS gets you safe, structured packets; fast.
|
|
43
45
|
|
|
44
46
|
## SAMPLES
|
|
45
47
|
|
|
@@ -117,4 +119,4 @@ Some weird error messages when invalid inputs are in like CreatePacket() and stu
|
|
|
117
119
|
|
|
118
120
|
Better error handling
|
|
119
121
|
|
|
120
|
-
|
|
122
|
+
Some middleware support
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
|
@@ -18,7 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
exports.SERVER_SUFFIX_NUMS = exports.SERVER_SUFFIX = exports.VERSION = void 0;
|
|
19
19
|
const StringUtil_1 = require("./ws/util/StringUtil");
|
|
20
20
|
/** Current protocol version */
|
|
21
|
-
exports.VERSION =
|
|
21
|
+
exports.VERSION = 16;
|
|
22
22
|
/** Server data suffix */
|
|
23
23
|
exports.SERVER_SUFFIX = "SWS";
|
|
24
24
|
/** Server data suffix in array */
|
|
@@ -26,6 +26,7 @@ export declare abstract class SonicWSCore implements Connection {
|
|
|
26
26
|
private asyncMap;
|
|
27
27
|
constructor(ws: WebSocket, bufferHandler: (val: MessageEvent) => Promise<Uint8Array>);
|
|
28
28
|
private reading;
|
|
29
|
+
private readQueue;
|
|
29
30
|
private serverKeyHandler;
|
|
30
31
|
private invalidPacket;
|
|
31
32
|
private listenLock;
|
|
@@ -50,7 +51,7 @@ export declare abstract class SonicWSCore implements Connection {
|
|
|
50
51
|
* @param tag The tag of the packet
|
|
51
52
|
* @param values The values to send
|
|
52
53
|
*/
|
|
53
|
-
send(tag: string, ...values: any[]): void
|
|
54
|
+
send(tag: string, ...values: any[]): Promise<void>;
|
|
54
55
|
/**
|
|
55
56
|
* Listens for when the client connects
|
|
56
57
|
* @param listener Callback on connection
|
|
@@ -63,27 +63,28 @@ class SonicWSCore {
|
|
|
63
63
|
this.bufferHandler = bufferHandler;
|
|
64
64
|
}
|
|
65
65
|
reading = false;
|
|
66
|
+
readQueue = [];
|
|
66
67
|
async serverKeyHandler(event) {
|
|
67
|
-
// stupid asynchronous bullshit
|
|
68
68
|
if (this.reading)
|
|
69
|
-
return this.
|
|
69
|
+
return this.readQueue.push(event);
|
|
70
70
|
this.reading = true;
|
|
71
|
-
const
|
|
72
|
-
if (
|
|
71
|
+
const cdata = await this.bufferHandler(event);
|
|
72
|
+
if (cdata.length < 3 || (0, BufferUtil_1.as8String)(cdata.slice(0, 3)) != version_1.SERVER_SUFFIX) {
|
|
73
73
|
this.socket.close(1000);
|
|
74
74
|
throw new Error("The server requested is not a Sonic WS server.");
|
|
75
75
|
}
|
|
76
|
-
const version =
|
|
76
|
+
const version = cdata[3];
|
|
77
77
|
if (version != version_1.VERSION) {
|
|
78
78
|
this.socket.close(1000);
|
|
79
79
|
throw new Error(`Version mismatch: ${version > version_1.VERSION ? "client" : "server"} is outdated (server: ${version}, client: ${version_1.VERSION})`);
|
|
80
80
|
}
|
|
81
|
-
const
|
|
81
|
+
const data = await (0, CompressionUtil_1.decompressGzip)(cdata.subarray(4, cdata.length));
|
|
82
|
+
const [ckOff, id] = (0, CompressionUtil_1.readVarInt)(data, 0);
|
|
82
83
|
this.id = id;
|
|
83
84
|
const [valuesOff, ckLength] = (0, CompressionUtil_1.readVarInt)(data, ckOff);
|
|
84
|
-
const ckData = data.
|
|
85
|
+
const ckData = data.subarray(valuesOff, valuesOff + ckLength);
|
|
85
86
|
this.clientPackets.holdPackets(Packets_1.Packet.deserializeAll(ckData, true));
|
|
86
|
-
const skData = data.
|
|
87
|
+
const skData = data.subarray(valuesOff + ckLength, data.length);
|
|
87
88
|
this.serverPackets.holdPackets(Packets_1.Packet.deserializeAll(skData, true));
|
|
88
89
|
this.batcher.registerSendPackets(this.clientPackets, this);
|
|
89
90
|
for (const p of this.serverPackets.getPackets()) {
|
|
@@ -105,6 +106,8 @@ class SonicWSCore {
|
|
|
105
106
|
this.readyListeners = null; // clear
|
|
106
107
|
this.socket.removeEventListener('message', this.serverKeyHandler);
|
|
107
108
|
this.socket.addEventListener('message', this.messageHandler);
|
|
109
|
+
this.readQueue.forEach(e => this.messageHandler(e));
|
|
110
|
+
this.readQueue = [];
|
|
108
111
|
}
|
|
109
112
|
invalidPacket(listened) {
|
|
110
113
|
console.error(listened);
|
|
@@ -136,7 +139,7 @@ class SonicWSCore {
|
|
|
136
139
|
packetQueue = this.packetQueue;
|
|
137
140
|
}
|
|
138
141
|
if (locked) {
|
|
139
|
-
packetQueue.push(
|
|
142
|
+
packetQueue.push(data);
|
|
140
143
|
return;
|
|
141
144
|
}
|
|
142
145
|
if (isAsync)
|
|
@@ -144,12 +147,11 @@ class SonicWSCore {
|
|
|
144
147
|
else
|
|
145
148
|
this.listenLock = true;
|
|
146
149
|
let currentData = data;
|
|
147
|
-
let currentCode = code;
|
|
148
150
|
while (true) {
|
|
149
151
|
await (0, PacketUtils_1.listenPacket)(currentData, listeners, this.invalidPacket);
|
|
150
152
|
if (packetQueue.length === 0)
|
|
151
153
|
break;
|
|
152
|
-
|
|
154
|
+
currentData = packetQueue.shift();
|
|
153
155
|
}
|
|
154
156
|
if (isAsync)
|
|
155
157
|
asyncData[0] = false;
|
|
@@ -165,10 +167,10 @@ class SonicWSCore {
|
|
|
165
167
|
const value = data.slice(1);
|
|
166
168
|
const packet = this.serverPackets.getPacket(this.serverPackets.getTag(key));
|
|
167
169
|
if (packet.dataBatching == 0) {
|
|
168
|
-
this.listenPacket(packet.listen(value, null), key);
|
|
170
|
+
this.listenPacket(await packet.listen(value, null), key);
|
|
169
171
|
return;
|
|
170
172
|
}
|
|
171
|
-
const batchData = BatchHelper_1.BatchHelper.unravelBatch(packet, value, null);
|
|
173
|
+
const batchData = await BatchHelper_1.BatchHelper.unravelBatch(packet, value, null);
|
|
172
174
|
if (typeof batchData == 'string')
|
|
173
175
|
return this.invalidPacket(batchData);
|
|
174
176
|
batchData.forEach(data => this.listenPacket(data, key));
|
|
@@ -202,8 +204,8 @@ class SonicWSCore {
|
|
|
202
204
|
* @param tag The tag of the packet
|
|
203
205
|
* @param values The values to send
|
|
204
206
|
*/
|
|
205
|
-
send(tag, ...values) {
|
|
206
|
-
const [code, data, packet] = (0, PacketUtils_1.processPacket)(this.clientPackets, tag, values);
|
|
207
|
+
async send(tag, ...values) {
|
|
208
|
+
const [code, data, packet] = await (0, PacketUtils_1.processPacket)(this.clientPackets, tag, values);
|
|
207
209
|
if (packet.dataBatching == 0)
|
|
208
210
|
this.raw_send((0, BufferUtil_1.toPacketBuffer)(code, data));
|
|
209
211
|
else
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
import { EnumPackage } from "../util/enums/EnumType";
|
|
2
2
|
import { Packet } from "./Packets";
|
|
3
3
|
import { PacketType } from "./PacketType";
|
|
4
|
-
export type PacketTypeValidator = (data: Uint8Array, index: number) => false | any
|
|
4
|
+
export type PacketTypeValidator = (data: Uint8Array, index: number) => Promise<[Uint8Array, false | any]>;
|
|
5
5
|
export type PacketReceiveProcessor = (data: Uint8Array, validationResult: any, index: number) => any;
|
|
6
|
-
export type PacketSendProcessor = (...data: any) =>
|
|
7
|
-
export declare function createValidator<T extends PacketType>(type: T, dataCap: number, dataMin: number, packet: Packet<T | T[]
|
|
6
|
+
export type PacketSendProcessor = (ident: string, ...data: any[]) => Promise<Uint8Array>;
|
|
7
|
+
export declare function createValidator<T extends PacketType>(type: T, dataCap: number, dataMin: number, packet: Packet<T | T[]>, gzipCompression: boolean, rereference: boolean): PacketTypeValidator;
|
|
8
8
|
export declare function createReceiveProcessor(type: PacketType, enumData: EnumPackage[], cap: number): PacketReceiveProcessor;
|
|
9
9
|
/** Creates a function that processes a packet type */
|
|
10
|
-
export declare function createSendProcessor(type: PacketType): PacketSendProcessor;
|
|
10
|
+
export declare function createSendProcessor(type: PacketType, gzipCompression: boolean, rereference: boolean): PacketSendProcessor;
|
|
11
11
|
export declare function createObjSendProcessor(packet: Packet<PacketType[]>): PacketSendProcessor;
|
|
12
12
|
export declare function createObjReceiveProcessor(packet: Packet<PacketType[]>): PacketReceiveProcessor;
|
|
13
13
|
export declare function createObjValidator(packet: Packet<PacketType[]>): PacketTypeValidator;
|
|
14
|
-
type BuildTuple<T, N extends number, R extends unknown[] = []> = R['length'] extends N ? R : BuildTuple<T, N, [T, ...R]>;
|
|
15
|
-
export type PacketResponse<T extends PacketType | readonly PacketType[], N extends number | readonly number[]> = T extends PacketType[] ? N extends number[] ? PacketResponseArray<T, N> : never : BuildTuple<T extends PacketType.NONE ? undefined : T extends PacketType.RAW ? Uint8Array : T extends PacketType.BYTES | PacketType.UBYTES ? number : T extends PacketType.SHORTS | PacketType.USHORTS ? number : T extends PacketType.VARINT | PacketType.UVARINT | PacketType.DELTAS ? number : T extends PacketType.FLOATS | PacketType.DOUBLES ? number : T extends PacketType.BOOLEANS ? boolean : T extends PacketType.STRINGS_ASCII | PacketType.STRINGS_UTF16 ? string : T extends PacketType.ENUMS ? any : never, N extends number ? N : never>;
|
|
16
|
-
type PacketResponseArray<T extends PacketType[], N extends number[]> = {
|
|
17
|
-
[K in keyof T]: K extends number ? PacketResponse<T[K], N[K] & number> : never;
|
|
18
|
-
};
|
|
19
|
-
export {};
|
|
@@ -52,91 +52,127 @@ function VARINT_VERIF(cap, min) {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
;
|
|
55
|
-
function createValidator(type, dataCap, dataMin, packet) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const pkg = packet.enumData[index];
|
|
63
|
-
for (let i = 0; i < data.length; i++) {
|
|
64
|
-
if (pkg.values.length <= data[i])
|
|
55
|
+
function createValidator(type, dataCap, dataMin, packet, gzipCompression, rereference) {
|
|
56
|
+
function genFunc() {
|
|
57
|
+
switch (type) {
|
|
58
|
+
case PacketType_1.PacketType.NONE: return (data) => data.length == 0;
|
|
59
|
+
case PacketType_1.PacketType.RAW: return () => undefined;
|
|
60
|
+
case PacketType_1.PacketType.ENUMS: return (data, index) => {
|
|
61
|
+
if (data.length < dataMin || data.length > dataCap || index >= packet.enumData.length)
|
|
65
62
|
return false;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const min = Math.ceil(dataMin * CompressionUtil_1.ONE_EIGHT);
|
|
94
|
-
const cap = Math.ceil(dataCap * CompressionUtil_1.ONE_EIGHT);
|
|
95
|
-
return (data) => data.length >= min && data.length <= cap;
|
|
96
|
-
}
|
|
97
|
-
;
|
|
98
|
-
case PacketType_1.PacketType.STRINGS_ASCII: return (data) => {
|
|
99
|
-
let index = 0;
|
|
100
|
-
const [offCount, stringCount] = (0, CompressionUtil_1.readVarInt)(data, index);
|
|
101
|
-
index = offCount;
|
|
102
|
-
if (stringCount < dataMin || stringCount > dataCap)
|
|
103
|
-
return false;
|
|
104
|
-
const lengths = [];
|
|
105
|
-
let totalLength = 0;
|
|
106
|
-
for (let i = 0; i < stringCount; i++) {
|
|
107
|
-
const [offLen, strLen] = (0, CompressionUtil_1.readVarInt)(data, index);
|
|
108
|
-
index = offLen;
|
|
109
|
-
lengths.push(strLen);
|
|
110
|
-
totalLength += strLen;
|
|
111
|
-
}
|
|
112
|
-
if (index + Math.ceil(totalLength / 8) > data.length)
|
|
113
|
-
return false;
|
|
114
|
-
return [stringCount, lengths, index];
|
|
115
|
-
};
|
|
116
|
-
case PacketType_1.PacketType.STRINGS_UTF16: return (data) => {
|
|
117
|
-
let sectors = 0, index = 0, computed = [];
|
|
118
|
-
while (index < data.length) {
|
|
119
|
-
sectors++;
|
|
120
|
-
if (sectors > dataCap)
|
|
63
|
+
const pkg = packet.enumData[index];
|
|
64
|
+
for (let i = 0; i < data.length; i++) {
|
|
65
|
+
if (pkg.values.length <= data[i])
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
case PacketType_1.PacketType.BYTES: return BYTE_LEN(dataCap, dataMin);
|
|
70
|
+
case PacketType_1.PacketType.UBYTES: return BYTE_LEN(dataCap, dataMin);
|
|
71
|
+
case PacketType_1.PacketType.HEX: return BYTE_LEN(dataCap, dataMin);
|
|
72
|
+
case PacketType_1.PacketType.SHORTS: return SHORT_LEN(dataCap, dataMin);
|
|
73
|
+
case PacketType_1.PacketType.USHORTS: return SHORT_LEN(dataCap, dataMin);
|
|
74
|
+
case PacketType_1.PacketType.VARINT: return VARINT_VERIF(dataCap, dataMin);
|
|
75
|
+
case PacketType_1.PacketType.UVARINT: return VARINT_VERIF(dataCap, dataMin);
|
|
76
|
+
case PacketType_1.PacketType.DELTAS: return VARINT_VERIF(dataCap, dataMin);
|
|
77
|
+
case PacketType_1.PacketType.FLOATS: return (data) => {
|
|
78
|
+
if (data.length % 4 !== 0)
|
|
79
|
+
return false;
|
|
80
|
+
const sectors = data.length * CompressionUtil_1.ONE_FOURTH;
|
|
81
|
+
if (sectors > dataCap || sectors < dataMin)
|
|
82
|
+
return false;
|
|
83
|
+
return undefined;
|
|
84
|
+
};
|
|
85
|
+
case PacketType_1.PacketType.DOUBLES: return (data) => {
|
|
86
|
+
if (data.length % 8 !== 0)
|
|
87
|
+
return false;
|
|
88
|
+
const sectors = data.length * CompressionUtil_1.ONE_EIGHT;
|
|
89
|
+
if (sectors > dataCap || sectors < dataMin)
|
|
121
90
|
return false;
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
91
|
+
return undefined;
|
|
92
|
+
};
|
|
93
|
+
case PacketType_1.PacketType.BOOLEANS:
|
|
94
|
+
{
|
|
95
|
+
const min = Math.ceil(dataMin * CompressionUtil_1.ONE_EIGHT);
|
|
96
|
+
const cap = Math.ceil(dataCap * CompressionUtil_1.ONE_EIGHT);
|
|
97
|
+
return (data) => data.length >= min && data.length <= cap;
|
|
98
|
+
}
|
|
99
|
+
;
|
|
100
|
+
case PacketType_1.PacketType.STRINGS_ASCII: return (data) => {
|
|
101
|
+
let index = 0;
|
|
102
|
+
const [offCount, stringCount] = (0, CompressionUtil_1.readVarInt)(data, index);
|
|
103
|
+
index = offCount;
|
|
104
|
+
if (stringCount < dataMin || stringCount > dataCap)
|
|
105
|
+
return false;
|
|
106
|
+
const lengths = [];
|
|
107
|
+
let totalLength = 0;
|
|
108
|
+
for (let i = 0; i < stringCount; i++) {
|
|
109
|
+
const [offLen, strLen] = (0, CompressionUtil_1.readVarInt)(data, index);
|
|
110
|
+
index = offLen;
|
|
111
|
+
lengths.push(strLen);
|
|
112
|
+
totalLength += strLen;
|
|
113
|
+
}
|
|
114
|
+
if (index + Math.ceil(totalLength / 8) > data.length)
|
|
115
|
+
return false;
|
|
116
|
+
return [stringCount, lengths, index];
|
|
117
|
+
};
|
|
118
|
+
case PacketType_1.PacketType.STRINGS_UTF16: return (data) => {
|
|
119
|
+
let sectors = 0, index = 0, computed = [];
|
|
120
|
+
while (index < data.length) {
|
|
121
|
+
sectors++;
|
|
122
|
+
if (sectors > dataCap)
|
|
129
123
|
return false;
|
|
130
|
-
|
|
124
|
+
const [off, strLength] = (0, CompressionUtil_1.readVarInt)(data, index);
|
|
125
|
+
index = off;
|
|
126
|
+
let string = [];
|
|
127
|
+
for (let i = 0; i < strLength; i++) {
|
|
128
|
+
const [newOff, char] = (0, CompressionUtil_1.readVarInt)(data, index);
|
|
129
|
+
index = newOff;
|
|
130
|
+
if (index > data.length)
|
|
131
|
+
return false;
|
|
132
|
+
string.push(char);
|
|
133
|
+
}
|
|
134
|
+
computed.push(string);
|
|
135
|
+
}
|
|
136
|
+
if (sectors < dataMin)
|
|
137
|
+
return false;
|
|
138
|
+
return computed;
|
|
139
|
+
};
|
|
140
|
+
case PacketType_1.PacketType.JSON: return (data) => {
|
|
141
|
+
try {
|
|
142
|
+
return (0, CompressionUtil_1.decompressJSON)(data);
|
|
131
143
|
}
|
|
132
|
-
|
|
144
|
+
catch {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
default: throw new Error("Unknown type: " + type);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const fn = genFunc();
|
|
152
|
+
let parsed = null;
|
|
153
|
+
return gzipCompression
|
|
154
|
+
? async (data, index) => {
|
|
155
|
+
if (rereference && data.length == 0) {
|
|
156
|
+
if (parsed == null)
|
|
157
|
+
return [data, false];
|
|
158
|
+
return parsed;
|
|
133
159
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
160
|
+
try {
|
|
161
|
+
const dec = await (0, CompressionUtil_1.decompressGzip)(data);
|
|
162
|
+
return parsed = [dec, fn(dec, index)];
|
|
163
|
+
}
|
|
164
|
+
catch {
|
|
165
|
+
return [data, false];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
: async (data, index) => {
|
|
169
|
+
if (rereference && data.length == 0) {
|
|
170
|
+
if (parsed == null)
|
|
171
|
+
return [data, false];
|
|
172
|
+
return parsed;
|
|
173
|
+
}
|
|
174
|
+
return parsed = [data, fn(data, index)];
|
|
137
175
|
};
|
|
138
|
-
default: throw new Error("Unknown type: " + type);
|
|
139
|
-
}
|
|
140
176
|
}
|
|
141
177
|
function createReceiveProcessor(type, enumData, cap) {
|
|
142
178
|
switch (type) {
|
|
@@ -144,6 +180,7 @@ function createReceiveProcessor(type, enumData, cap) {
|
|
|
144
180
|
case PacketType_1.PacketType.RAW: return (data) => data;
|
|
145
181
|
case PacketType_1.PacketType.BYTES: return (data) => Array.from(data).map(CompressionUtil_1.demapZigZag);
|
|
146
182
|
case PacketType_1.PacketType.UBYTES: return (data) => Array.from(data);
|
|
183
|
+
case PacketType_1.PacketType.HEX: return (data) => (0, CompressionUtil_1.bytesToHex)(data);
|
|
147
184
|
case PacketType_1.PacketType.SHORTS: return (data) => (0, BufferUtil_1.splitBuffer)(data, 2).map(v => (0, CompressionUtil_1.demapShort_ZZ)(v));
|
|
148
185
|
case PacketType_1.PacketType.USHORTS: return (data) => (0, BufferUtil_1.splitBuffer)(data, 2).map(v => (0, CompressionUtil_1.fromShort)(v));
|
|
149
186
|
case PacketType_1.PacketType.VARINT: return (_, computed) => computed.map(CompressionUtil_1.demapZigZag);
|
|
@@ -170,64 +207,101 @@ function createReceiveProcessor(type, enumData, cap) {
|
|
|
170
207
|
}
|
|
171
208
|
return strings;
|
|
172
209
|
};
|
|
173
|
-
case PacketType_1.PacketType.STRINGS_UTF16: return (
|
|
210
|
+
case PacketType_1.PacketType.STRINGS_UTF16: return (_, computed) => {
|
|
174
211
|
return computed.map(codes => String.fromCodePoint(...codes));
|
|
175
212
|
};
|
|
213
|
+
case PacketType_1.PacketType.JSON: return (_, computed) => computed;
|
|
176
214
|
default: throw new Error("Unknown type: " + type);
|
|
177
215
|
}
|
|
178
216
|
}
|
|
179
217
|
/** Creates a function that processes a packet type */
|
|
180
|
-
function createSendProcessor(type) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
return
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
];
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
218
|
+
function createSendProcessor(type, gzipCompression, rereference) {
|
|
219
|
+
function genFunc() {
|
|
220
|
+
switch (type) {
|
|
221
|
+
case PacketType_1.PacketType.NONE: return () => [];
|
|
222
|
+
case PacketType_1.PacketType.RAW: return (data) => Array.from(data);
|
|
223
|
+
case PacketType_1.PacketType.ENUMS: return (enums) => enums;
|
|
224
|
+
case PacketType_1.PacketType.BYTES: return (numbers) => numbers.map(CompressionUtil_1.mapZigZag);
|
|
225
|
+
case PacketType_1.PacketType.UBYTES: return (numbers) => numbers.map(CompressionUtil_1.toByte);
|
|
226
|
+
case PacketType_1.PacketType.HEX: return (hex) => {
|
|
227
|
+
if (typeof hex != "string") {
|
|
228
|
+
if (hex instanceof Array && hex.length == 1)
|
|
229
|
+
return (0, CompressionUtil_1.hexToBytes)(hex[0]);
|
|
230
|
+
throw new Error("Cannot send more than 1 hex string; this packet is equivalent to UBYTES: " + JSON.stringify(hex));
|
|
231
|
+
}
|
|
232
|
+
return (0, CompressionUtil_1.hexToBytes)(hex);
|
|
233
|
+
};
|
|
234
|
+
case PacketType_1.PacketType.SHORTS: return (numbers) => numbers.map(CompressionUtil_1.mapShort_ZZ).flat();
|
|
235
|
+
case PacketType_1.PacketType.USHORTS: return (numbers) => numbers.map(CompressionUtil_1.toShort).flat();
|
|
236
|
+
case PacketType_1.PacketType.VARINT: return (numbers) => numbers.map(n => (0, CompressionUtil_1.convertVarInt)((0, CompressionUtil_1.mapZigZag)(n))).flat();
|
|
237
|
+
case PacketType_1.PacketType.UVARINT: return (numbers) => numbers.map(CompressionUtil_1.convertVarInt).flat();
|
|
238
|
+
case PacketType_1.PacketType.DELTAS: return (numbers) => numbers.map((n, i) => (0, CompressionUtil_1.convertVarInt)((0, CompressionUtil_1.mapZigZag)(n - (numbers[i - 1] || 0)))).flat();
|
|
239
|
+
case PacketType_1.PacketType.FLOATS: return (singles) => singles.map(CompressionUtil_1.convertFloat).flat();
|
|
240
|
+
case PacketType_1.PacketType.DOUBLES: return (doubles) => doubles.map(CompressionUtil_1.convertDouble).flat();
|
|
241
|
+
case PacketType_1.PacketType.BOOLEANS: return (bools) => (0, ArrayUtil_1.splitArray)(bools, 8).map((bools) => (0, CompressionUtil_1.compressBools)(bools)).flat();
|
|
242
|
+
case PacketType_1.PacketType.STRINGS_ASCII: return (strings) => {
|
|
243
|
+
return [
|
|
244
|
+
...(0, CompressionUtil_1.convertVarInt)(strings.length),
|
|
245
|
+
...strings.map(str => (0, CompressionUtil_1.convertVarInt)(str.length)).flat(),
|
|
246
|
+
...(0, CompressionUtil_1.encodeHuffman)(strings.reduce((a, b) => a + String(b), "")),
|
|
247
|
+
];
|
|
248
|
+
};
|
|
249
|
+
case PacketType_1.PacketType.STRINGS_UTF16: return (strings) => {
|
|
250
|
+
const res = [];
|
|
251
|
+
for (const v of strings) {
|
|
252
|
+
const string = String(v);
|
|
253
|
+
const charCodes = (0, StringUtil_1.processCharCodes)(string);
|
|
254
|
+
// hate js man
|
|
255
|
+
const length = charCodes.length;
|
|
256
|
+
res.push(...(0, CompressionUtil_1.convertVarInt)(length));
|
|
257
|
+
res.push(...charCodes.map(CompressionUtil_1.convertVarInt).flat());
|
|
258
|
+
}
|
|
259
|
+
return res;
|
|
260
|
+
};
|
|
261
|
+
case PacketType_1.PacketType.JSON: return (value) => Array.from((0, CompressionUtil_1.compressJSON)(value));
|
|
262
|
+
default: throw new Error("Unknown type: " + type);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const fn = genFunc();
|
|
266
|
+
let lastSent;
|
|
267
|
+
if (!gzipCompression) {
|
|
268
|
+
return async (_, data) => {
|
|
269
|
+
if (rereference) {
|
|
270
|
+
const jstr = JSON.stringify(data);
|
|
271
|
+
if (jstr == lastSent) {
|
|
272
|
+
return CompressionUtil_1.EMPTY_UINT8;
|
|
273
|
+
}
|
|
274
|
+
lastSent = jstr;
|
|
211
275
|
}
|
|
212
|
-
return
|
|
276
|
+
return new Uint8Array(fn(data));
|
|
213
277
|
};
|
|
214
|
-
default: throw new Error("Unknown type: " + type);
|
|
215
278
|
}
|
|
279
|
+
return async (ident, data) => {
|
|
280
|
+
if (rereference) {
|
|
281
|
+
const jstr = JSON.stringify(data);
|
|
282
|
+
if (jstr == lastSent) {
|
|
283
|
+
return CompressionUtil_1.EMPTY_UINT8;
|
|
284
|
+
}
|
|
285
|
+
lastSent = jstr;
|
|
286
|
+
}
|
|
287
|
+
return (0, CompressionUtil_1.compressGzip)(new Uint8Array(fn(data)), ident);
|
|
288
|
+
};
|
|
216
289
|
}
|
|
217
290
|
function createObjSendProcessor(packet) {
|
|
218
291
|
const size = packet.type.length;
|
|
219
|
-
|
|
220
|
-
|
|
292
|
+
// TODO: Add compression and add rereferences[]
|
|
293
|
+
const processors = packet.type.map(t => createSendProcessor(t, false, false));
|
|
294
|
+
return async (ident, data) => {
|
|
221
295
|
let result = [];
|
|
222
296
|
for (let i = 0; i < size; i++) {
|
|
223
297
|
const sectorData = data[i];
|
|
224
|
-
const d = processors[i](Array.isArray(sectorData) ? sectorData : [sectorData]);
|
|
298
|
+
const d = await processors[i](ident, Array.isArray(sectorData) ? sectorData : [sectorData]);
|
|
225
299
|
if (d.length > CompressionUtil_1.MAX_UVARINT)
|
|
226
300
|
throw new Error(`Cannot send ${d.length}/${CompressionUtil_1.MAX_UVARINT} bytes of data!`);
|
|
227
301
|
result.push(...(0, CompressionUtil_1.convertVarInt)(d.length));
|
|
228
302
|
d.forEach(val => result.push(val));
|
|
229
303
|
}
|
|
230
|
-
return result;
|
|
304
|
+
return new Uint8Array(result);
|
|
231
305
|
};
|
|
232
306
|
}
|
|
233
307
|
function createObjReceiveProcessor(packet) {
|
|
@@ -247,22 +321,22 @@ function createObjReceiveProcessor(packet) {
|
|
|
247
321
|
};
|
|
248
322
|
}
|
|
249
323
|
function createObjValidator(packet) {
|
|
250
|
-
const validators = packet.type.map((t, i) => createValidator(t, packet.dataMax[i], packet.dataMin[i], packet));
|
|
251
|
-
return (data) => {
|
|
324
|
+
const validators = packet.type.map((t, i) => createValidator(t, packet.dataMax[i], packet.dataMin[i], packet, false, false));
|
|
325
|
+
return async (data) => {
|
|
252
326
|
let index = 0, enums = 0, computedData = [];
|
|
253
327
|
while (index < data.length) {
|
|
254
328
|
if (computedData.length > packet.type.length)
|
|
255
|
-
return false; // only types amount of values
|
|
329
|
+
return [data, false]; // only types amount of values
|
|
256
330
|
const [off, sectorLength] = (0, CompressionUtil_1.readVarInt)(data, index);
|
|
257
331
|
index = off;
|
|
258
332
|
if (sectorLength + index > data.length)
|
|
259
|
-
return false;
|
|
333
|
+
return [data, false];
|
|
260
334
|
const sector = data.subarray(index, index += sectorLength);
|
|
261
|
-
const result = validators[computedData.length](sector, packet.type[computedData.length] == PacketType_1.PacketType.ENUMS ? enums++ : 0);
|
|
335
|
+
const [, result] = await validators[computedData.length](sector, packet.type[computedData.length] == PacketType_1.PacketType.ENUMS ? enums++ : 0);
|
|
262
336
|
if (result === false)
|
|
263
|
-
return false; // chat i used === to fix a bug !!!!
|
|
337
|
+
return [data, false]; // chat i used === to fix a bug !!!!
|
|
264
338
|
computedData.push(result);
|
|
265
339
|
}
|
|
266
|
-
return computedData;
|
|
340
|
+
return [data, computedData];
|
|
267
341
|
};
|
|
268
342
|
}
|
|
@@ -31,5 +31,11 @@ export declare enum PacketType {
|
|
|
31
31
|
/** One or more double precision floating point numbers. */
|
|
32
32
|
DOUBLES = 13,
|
|
33
33
|
/** One or more true/false */
|
|
34
|
-
BOOLEANS = 14
|
|
34
|
+
BOOLEANS = 14,
|
|
35
|
+
/** Consumes multiple keys to describe the value. E.g. if you want to send a boolean, this could take up 2 keys instead of sending 2 bytes. Currently W.I.P. */
|
|
36
|
+
KEY_EFFECTIVE = 15,
|
|
37
|
+
/** A more optimized version of JSON for when it's a necessity. However, please try to avoid this; the other types are usually better. */
|
|
38
|
+
JSON = 16,
|
|
39
|
+
/** Hex bytes, e.g. 0xFFFFFF - the result will always be returned in lowercase. This can only hold 1 hex string, since it's the same as UBYTES but auto-parses. */
|
|
40
|
+
HEX = 17
|
|
35
41
|
}
|
|
@@ -52,4 +52,10 @@ var PacketType;
|
|
|
52
52
|
PacketType[PacketType["DOUBLES"] = 13] = "DOUBLES";
|
|
53
53
|
/** One or more true/false */
|
|
54
54
|
PacketType[PacketType["BOOLEANS"] = 14] = "BOOLEANS";
|
|
55
|
+
/** Consumes multiple keys to describe the value. E.g. if you want to send a boolean, this could take up 2 keys instead of sending 2 bytes. Currently W.I.P. */
|
|
56
|
+
PacketType[PacketType["KEY_EFFECTIVE"] = 15] = "KEY_EFFECTIVE";
|
|
57
|
+
/** A more optimized version of JSON for when it's a necessity. However, please try to avoid this; the other types are usually better. */
|
|
58
|
+
PacketType[PacketType["JSON"] = 16] = "JSON";
|
|
59
|
+
/** Hex bytes, e.g. 0xFFFFFF - the result will always be returned in lowercase. This can only hold 1 hex string, since it's the same as UBYTES but auto-parses. */
|
|
60
|
+
PacketType[PacketType["HEX"] = 17] = "HEX";
|
|
55
61
|
})(PacketType || (exports.PacketType = PacketType = {}));
|