teeworlds 2.1.5 → 2.1.7
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/index.js +16 -9
- package/index.ts +5 -9
- package/lib/MsgPacker.js +57 -0
- package/lib/MsgPacker.ts +2 -2
- package/lib/MsgUnpacker.js +56 -0
- package/lib/MsgUnpacker.ts +1 -1
- package/lib/client.js +684 -0
- package/lib/client.ts +100 -62
- package/lib/huffman.js +190 -0
- package/lib/movement.js +54 -0
- package/lib/snapshot.js +351 -0
- package/lib/snapshot.ts +7 -5
- package/package.json +1 -1
package/lib/client.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { randomBytes } from "crypto";
|
|
2
2
|
|
|
3
3
|
import net from 'dgram';
|
|
4
|
-
import fs, { stat } from 'fs';
|
|
5
4
|
import { EventEmitter } from 'stream';
|
|
6
|
-
import { spawn } from 'child_process';
|
|
7
5
|
|
|
8
6
|
import { unpackInt, unpackString, MsgUnpacker } from "./MsgUnpacker";
|
|
9
7
|
|
|
10
8
|
import Movement from './movement';
|
|
11
9
|
|
|
12
|
-
import MsgPacker from './MsgPacker';
|
|
10
|
+
import { MsgPacker } from './MsgPacker';
|
|
13
11
|
import { Snapshot } from './snapshot';
|
|
14
12
|
import Huffman from "./huffman";
|
|
15
13
|
|
|
@@ -174,7 +172,13 @@ declare interface iKillMsg {
|
|
|
174
172
|
special_mode: number
|
|
175
173
|
}
|
|
176
174
|
|
|
177
|
-
declare interface
|
|
175
|
+
declare interface iOptions {
|
|
176
|
+
identity?: ClientInfo,
|
|
177
|
+
password?: string,
|
|
178
|
+
ddnet_version?: {version: number, release_version: string},
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export declare interface Client {
|
|
178
182
|
host: string;
|
|
179
183
|
port: number;
|
|
180
184
|
name: string;
|
|
@@ -201,6 +205,7 @@ declare interface Client {
|
|
|
201
205
|
|
|
202
206
|
lastSendTime: number;
|
|
203
207
|
|
|
208
|
+
options?: iOptions;
|
|
204
209
|
|
|
205
210
|
on(event: 'connected', listener: () => void): this;
|
|
206
211
|
on(event: 'disconnect', listener: (reason: string) => void): this;
|
|
@@ -209,17 +214,23 @@ declare interface Client {
|
|
|
209
214
|
on(event: 'kill', listener: (kill: iKillMsg) => void): this;
|
|
210
215
|
|
|
211
216
|
}
|
|
212
|
-
class Client extends EventEmitter {
|
|
213
217
|
|
|
214
218
|
|
|
215
219
|
|
|
216
|
-
|
|
220
|
+
export class Client extends EventEmitter {
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
constructor(ip: string, port: number, nickname: string, options?: iOptions) {
|
|
217
225
|
super();
|
|
218
226
|
this.host = ip;
|
|
219
227
|
this.port = port;
|
|
220
228
|
this.name = nickname;
|
|
221
229
|
this.AckGameTick = 0;
|
|
222
230
|
this.PredGameTick = 0;
|
|
231
|
+
|
|
232
|
+
if (options)
|
|
233
|
+
this.options = options;
|
|
223
234
|
|
|
224
235
|
this.timer = 0;
|
|
225
236
|
|
|
@@ -304,39 +315,43 @@ class Client extends EventEmitter {
|
|
|
304
315
|
*/
|
|
305
316
|
})
|
|
306
317
|
}
|
|
307
|
-
SendMsgEx(Msg: MsgPacker, Flags: number) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
|
|
318
|
+
// SendMsgEx(Msg: MsgPacker, Flags: number) {
|
|
319
|
+
// if (this.State == States.STATE_OFFLINE)
|
|
320
|
+
// throw new Error("Client is not connected");
|
|
321
|
+
// if (!this.socket)
|
|
322
|
+
// return;
|
|
323
|
+
// this.lastSendTime = new Date().getTime();
|
|
324
|
+
// var header = []
|
|
325
|
+
// header[0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
|
|
326
|
+
// header[1] = (Msg.size & 0xf);
|
|
327
|
+
// if (Flags & 1) {
|
|
328
|
+
// this.clientAck = (this.clientAck + 1) % (1 << 10);
|
|
329
|
+
// header[1] |= (this.clientAck >> 2) & 0xf0;
|
|
330
|
+
// header[2] = this.clientAck & 0xff;
|
|
331
|
+
|
|
332
|
+
// this.sentChunkQueue.push(Buffer.concat([Buffer.from(header), Msg.buffer]));
|
|
333
|
+
// }
|
|
334
|
+
|
|
335
|
+
// let latestBuf = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff, 0x1, header[0], header[1]]);
|
|
336
|
+
// if (Flags & 1)
|
|
337
|
+
// latestBuf = Buffer.concat([latestBuf, Buffer.from([this.clientAck])]);
|
|
338
|
+
// latestBuf = Buffer.concat([latestBuf, Msg.buffer, this.TKEN]);
|
|
339
|
+
// this.socket.send(latestBuf, 0, latestBuf.length, this.port, this.host);
|
|
340
|
+
|
|
341
|
+
// }
|
|
342
|
+
SendMsgEx(Msgs: MsgPacker[] | MsgPacker, Flags: number) {
|
|
332
343
|
if (this.State == States.STATE_OFFLINE)
|
|
333
|
-
throw new Error("Client is not connected");
|
|
344
|
+
return; //throw new Error("Client is not connected");
|
|
334
345
|
if (!this.socket)
|
|
335
346
|
return;
|
|
347
|
+
let _Msgs: MsgPacker[];
|
|
348
|
+
if (Msgs instanceof Array)
|
|
349
|
+
_Msgs = Msgs;
|
|
350
|
+
else
|
|
351
|
+
_Msgs = [Msgs];
|
|
336
352
|
this.lastSendTime = new Date().getTime();
|
|
337
353
|
var header: Buffer[] = [];
|
|
338
|
-
|
|
339
|
-
Msgs.forEach((Msg: MsgPacker, index) => {
|
|
354
|
+
_Msgs.forEach((Msg: MsgPacker, index) => {
|
|
340
355
|
header[index] = Buffer.alloc((Flags & 1 ? 3 : 2));
|
|
341
356
|
header[index][0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
|
|
342
357
|
header[index][1] = (Msg.size & 0xf);
|
|
@@ -344,19 +359,15 @@ class Client extends EventEmitter {
|
|
|
344
359
|
this.clientAck = (this.clientAck + 1) % (1 << 10);
|
|
345
360
|
header[index][1] |= (this.clientAck >> 2) & 0xf0;
|
|
346
361
|
header[index][2] = this.clientAck & 0xff;
|
|
347
|
-
|
|
348
362
|
header[index][0] = (((Flags | 2)&3)<<6)|((Msg.size>>4)&0x3f); // 2 is resend flag (ugly hack for queue)
|
|
349
363
|
|
|
350
364
|
this.sentChunkQueue.push(Buffer.concat([header[index], Msg.buffer]));
|
|
351
|
-
|
|
352
365
|
header[index][0] = (((Flags)&3)<<6)|((Msg.size>>4)&0x3f);
|
|
353
|
-
|
|
354
|
-
|
|
355
366
|
}
|
|
356
367
|
})
|
|
357
|
-
var packetHeader = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff,
|
|
368
|
+
var packetHeader = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff, _Msgs.length]);
|
|
358
369
|
var chunks = Buffer.from([]);
|
|
359
|
-
|
|
370
|
+
_Msgs.forEach((Msg: MsgPacker, index) => {
|
|
360
371
|
chunks = Buffer.concat([chunks, Buffer.from(header[index]), Msg.buffer]);
|
|
361
372
|
})
|
|
362
373
|
var packet = Buffer.concat([(packetHeader), chunks, this.TKEN]);
|
|
@@ -365,7 +376,7 @@ class Client extends EventEmitter {
|
|
|
365
376
|
}
|
|
366
377
|
SendMsgRaw(chunks: Buffer[]) {
|
|
367
378
|
if (this.State == States.STATE_OFFLINE)
|
|
368
|
-
throw new Error("Client is not connected");
|
|
379
|
+
return console.log(chunks, "client not connected"); //throw new Error("Client is not connected");
|
|
369
380
|
if (!this.socket)
|
|
370
381
|
return;
|
|
371
382
|
|
|
@@ -411,10 +422,13 @@ class Client extends EventEmitter {
|
|
|
411
422
|
this.State = States.STATE_CONNECTING;
|
|
412
423
|
|
|
413
424
|
let predTimer = setInterval(() => {
|
|
414
|
-
if (this.State == States.STATE_ONLINE
|
|
415
|
-
this.
|
|
425
|
+
if (this.State == States.STATE_ONLINE) {
|
|
426
|
+
if (this.AckGameTick > 0)
|
|
427
|
+
this.PredGameTick++;
|
|
416
428
|
// console.log(this.PredGameTick, this.AckGameTick)
|
|
417
|
-
}
|
|
429
|
+
} else if (this.State == States.STATE_OFFLINE)
|
|
430
|
+
clearInterval(predTimer);
|
|
431
|
+
|
|
418
432
|
}, 20);
|
|
419
433
|
|
|
420
434
|
this.SendControlMsg(1, "TKEN")
|
|
@@ -425,8 +439,10 @@ class Client extends EventEmitter {
|
|
|
425
439
|
clearInterval(connectInterval)
|
|
426
440
|
}, 500);
|
|
427
441
|
|
|
428
|
-
setInterval(() => {
|
|
442
|
+
let inputInterval = setInterval(() => {
|
|
429
443
|
// if (new Date().getTime() - this.time >= 1000) {
|
|
444
|
+
if (this.State == States.STATE_OFFLINE)
|
|
445
|
+
clearInterval(inputInterval)
|
|
430
446
|
if (this.State != States.STATE_ONLINE)
|
|
431
447
|
return;
|
|
432
448
|
this.time = new Date().getTime();
|
|
@@ -440,12 +456,13 @@ class Client extends EventEmitter {
|
|
|
440
456
|
// this.sentChunkQueue.forEach((chunk) => {
|
|
441
457
|
// if (this.State == 0) // disconnected
|
|
442
458
|
// return;
|
|
443
|
-
if (this.State !=
|
|
444
|
-
if (((new Date().getTime()) - this.lastSendTime) > 900) {
|
|
459
|
+
if (this.State != States.STATE_OFFLINE) {
|
|
460
|
+
if (((new Date().getTime()) - this.lastSendTime) > 900 && this.sentChunkQueue.length > 0) {
|
|
445
461
|
this.SendMsgRaw([this.sentChunkQueue[0]]);
|
|
446
|
-
console.log(this.sentChunkQueue);
|
|
462
|
+
console.log(this.sentChunkQueue, this.State);
|
|
447
463
|
}
|
|
448
|
-
}
|
|
464
|
+
} else
|
|
465
|
+
clearInterval(resendTimeout)
|
|
449
466
|
// })
|
|
450
467
|
}, 1000)
|
|
451
468
|
|
|
@@ -453,7 +470,9 @@ class Client extends EventEmitter {
|
|
|
453
470
|
this.time = new Date().getTime() + 2000; // start sending keepalives after 2s
|
|
454
471
|
|
|
455
472
|
if (this.socket)
|
|
456
|
-
this.socket.on("message", (a) => {
|
|
473
|
+
this.socket.on("message", (a, rinfo) => {
|
|
474
|
+
if (this.State == 0 || rinfo.address != this.host || rinfo.port != this.port)
|
|
475
|
+
return;
|
|
457
476
|
clearInterval(connectInterval)
|
|
458
477
|
if (a.toJSON().data[0] == 0x10) {
|
|
459
478
|
if (a.toString().includes("TKEN") || a.toJSON().data[3] == 0x2) {
|
|
@@ -461,9 +480,11 @@ class Client extends EventEmitter {
|
|
|
461
480
|
this.TKEN = Buffer.from(a.toJSON().data.slice(a.toJSON().data.length - 4, a.toJSON().data.length))
|
|
462
481
|
this.SendControlMsg(3);
|
|
463
482
|
this.State = States.STATE_LOADING; // loading state
|
|
483
|
+
this.receivedSnaps = 0;
|
|
484
|
+
|
|
464
485
|
var info = new MsgPacker(1, true);
|
|
465
486
|
info.AddString("0.6 626fce9a778df4d4");
|
|
466
|
-
info.AddString(""); // password
|
|
487
|
+
info.AddString(this.options?.password === undefined ? "" : this.options?.password); // password
|
|
467
488
|
|
|
468
489
|
var client_version = new MsgPacker(0, true);
|
|
469
490
|
client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
|
|
@@ -472,10 +493,15 @@ class Client extends EventEmitter {
|
|
|
472
493
|
randomBytes(16).copy(randomUuid);
|
|
473
494
|
|
|
474
495
|
client_version.AddBuffer(randomUuid);
|
|
475
|
-
|
|
476
|
-
|
|
496
|
+
if (this.options?.ddnet_version !== undefined) {
|
|
497
|
+
client_version.AddInt(this.options?.ddnet_version.version);
|
|
498
|
+
client_version.AddString("DDNet " + this.options?.ddnet_version.release_version);
|
|
499
|
+
} else {
|
|
500
|
+
client_version.AddInt(16003);
|
|
501
|
+
client_version.AddString("DDNet 16.0.3");
|
|
502
|
+
}
|
|
477
503
|
|
|
478
|
-
this.
|
|
504
|
+
this.SendMsgEx([client_version, info], 1)
|
|
479
505
|
} else if (a.toJSON().data[3] == 0x4) {
|
|
480
506
|
// disconnected
|
|
481
507
|
this.State = States.STATE_OFFLINE;
|
|
@@ -610,13 +636,24 @@ class Client extends EventEmitter {
|
|
|
610
636
|
this.SendMsgEx(Msg, 1);
|
|
611
637
|
} else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY") || unpacked.chunks[0] && chunkMessages.includes("SV_MOTD"))) {
|
|
612
638
|
var info = new MsgPacker(20, false);
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
639
|
+
if (this.options?.identity) {
|
|
640
|
+
info.AddString(this.options.identity.name);
|
|
641
|
+
info.AddString(this.options.identity.clan);
|
|
642
|
+
info.AddInt(this.options.identity.country);
|
|
643
|
+
info.AddString(this.options.identity.skin);
|
|
644
|
+
info.AddInt(this.options.identity.use_custom_color);
|
|
645
|
+
info.AddInt(this.options.identity.color_body);
|
|
646
|
+
info.AddInt(this.options.identity.color_feet);
|
|
647
|
+
} else {
|
|
648
|
+
info.AddString(this.name); /* name */
|
|
649
|
+
info.AddString(""); /* clan */
|
|
650
|
+
info.AddInt(-1); /* country */
|
|
651
|
+
info.AddString("greyfox"); /* skin */
|
|
652
|
+
info.AddInt(1); /* use custom color */
|
|
653
|
+
info.AddInt(10346103); /* color body */
|
|
654
|
+
info.AddInt(65535); /* color feet */
|
|
655
|
+
|
|
656
|
+
}
|
|
620
657
|
this.SendMsgEx(info, 1);
|
|
621
658
|
|
|
622
659
|
|
|
@@ -772,5 +809,6 @@ class Client extends EventEmitter {
|
|
|
772
809
|
|
|
773
810
|
|
|
774
811
|
}
|
|
775
|
-
|
|
812
|
+
|
|
813
|
+
// export = Client;
|
|
776
814
|
// module.exports = Client;
|
package/lib/huffman.js
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var FREQ_TABLE = [
|
|
3
|
+
1 << 30, 4545, 2657, 431, 1950, 919, 444, 482, 2244, 617, 838, 542, 715, 1814, 304, 240, 754, 212, 647, 186,
|
|
4
|
+
283, 131, 146, 166, 543, 164, 167, 136, 179, 859, 363, 113, 157, 154, 204, 108, 137, 180, 202, 176,
|
|
5
|
+
872, 404, 168, 134, 151, 111, 113, 109, 120, 126, 129, 100, 41, 20, 16, 22, 18, 18, 17, 19,
|
|
6
|
+
16, 37, 13, 21, 362, 166, 99, 78, 95, 88, 81, 70, 83, 284, 91, 187, 77, 68, 52, 68,
|
|
7
|
+
59, 66, 61, 638, 71, 157, 50, 46, 69, 43, 11, 24, 13, 19, 10, 12, 12, 20, 14, 9,
|
|
8
|
+
20, 20, 10, 10, 15, 15, 12, 12, 7, 19, 15, 14, 13, 18, 35, 19, 17, 14, 8, 5,
|
|
9
|
+
15, 17, 9, 15, 14, 18, 8, 10, 2173, 134, 157, 68, 188, 60, 170, 60, 194, 62, 175, 71,
|
|
10
|
+
148, 67, 167, 78, 211, 67, 156, 69, 1674, 90, 174, 53, 147, 89, 181, 51, 174, 63, 163, 80,
|
|
11
|
+
167, 94, 128, 122, 223, 153, 218, 77, 200, 110, 190, 73, 174, 69, 145, 66, 277, 143, 141, 60,
|
|
12
|
+
136, 53, 180, 57, 142, 57, 158, 61, 166, 112, 152, 92, 26, 22, 21, 28, 20, 26, 30, 21,
|
|
13
|
+
32, 27, 20, 17, 23, 21, 30, 22, 22, 21, 27, 25, 17, 27, 23, 18, 39, 26, 15, 21,
|
|
14
|
+
12, 18, 18, 27, 20, 18, 15, 19, 11, 17, 33, 12, 18, 15, 19, 18, 16, 26, 17, 18,
|
|
15
|
+
9, 10, 25, 22, 22, 17, 20, 16, 6, 16, 15, 20, 14, 18, 24, 335, 1517
|
|
16
|
+
], HUFFMAN_EOF_SYMBOL = 256, HUFFMAN_MAX_SYMBOLS = HUFFMAN_EOF_SYMBOL + 1, HUFFMAN_MAX_NODES = HUFFMAN_MAX_SYMBOLS * 2 - 1, HUFFMAN_LUTBITS = 10, HUFFMAN_LUTSIZE = 1 << HUFFMAN_LUTBITS, HUFFMAN_LUTMASK = HUFFMAN_LUTSIZE - 1;
|
|
17
|
+
var Huffman = /** @class */ (function () {
|
|
18
|
+
function Huffman(frequencies) {
|
|
19
|
+
if (frequencies === void 0) { frequencies = FREQ_TABLE; }
|
|
20
|
+
this.nodes = new Array(HUFFMAN_MAX_NODES);
|
|
21
|
+
for (var i = 0; i < HUFFMAN_MAX_NODES; i++) {
|
|
22
|
+
this.nodes[i] = {};
|
|
23
|
+
}
|
|
24
|
+
this.decode_lut = new Array(HUFFMAN_LUTSIZE);
|
|
25
|
+
this.num_nodes = 0;
|
|
26
|
+
this.start_node_index = 0;
|
|
27
|
+
this.construct_tree(frequencies);
|
|
28
|
+
for (var i = 0; i < HUFFMAN_LUTSIZE; i++) {
|
|
29
|
+
var bits = i;
|
|
30
|
+
var broke = false;
|
|
31
|
+
var index = this.start_node_index;
|
|
32
|
+
for (var x = 0; x < HUFFMAN_LUTBITS; x++) {
|
|
33
|
+
if (bits & 1)
|
|
34
|
+
index = this.nodes[index].right;
|
|
35
|
+
else
|
|
36
|
+
index = this.nodes[index].left;
|
|
37
|
+
bits >>= 1;
|
|
38
|
+
if (this.nodes[index].numbits) {
|
|
39
|
+
this.decode_lut[i] = index;
|
|
40
|
+
broke = true;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (!broke) {
|
|
45
|
+
this.decode_lut[i] = index;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
Huffman.prototype.set_bits_r = function (node_index, bits, depth) {
|
|
50
|
+
if (this.nodes[node_index].right != 0xffff)
|
|
51
|
+
this.set_bits_r(this.nodes[node_index].right, bits | (1 << depth), depth + 1);
|
|
52
|
+
if (this.nodes[node_index].left != 0xffff)
|
|
53
|
+
this.set_bits_r(this.nodes[node_index].left, bits, depth + 1);
|
|
54
|
+
if (this.nodes[node_index].numbits) {
|
|
55
|
+
this.nodes[node_index].bits = bits;
|
|
56
|
+
this.nodes[node_index].numbits = depth;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
Huffman.prototype.bubble_sort = function (index_list, node_list, size) {
|
|
60
|
+
var changed = true;
|
|
61
|
+
while (changed) {
|
|
62
|
+
changed = false;
|
|
63
|
+
for (var i = 0; i < size - 1; i++) {
|
|
64
|
+
if (node_list[index_list[i]].frequency < node_list[index_list[i + 1]].frequency) {
|
|
65
|
+
var temp = index_list[i];
|
|
66
|
+
index_list[i] = index_list[i + 1];
|
|
67
|
+
index_list[i + 1] = temp;
|
|
68
|
+
changed = true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
size--;
|
|
72
|
+
}
|
|
73
|
+
return index_list;
|
|
74
|
+
};
|
|
75
|
+
Huffman.prototype.construct_tree = function (frequencies) {
|
|
76
|
+
if (frequencies === void 0) { frequencies = FREQ_TABLE; }
|
|
77
|
+
var nodes_left_storage = new Array(HUFFMAN_MAX_SYMBOLS);
|
|
78
|
+
for (var i = 0; i < HUFFMAN_MAX_SYMBOLS; i++) {
|
|
79
|
+
nodes_left_storage[i] = {};
|
|
80
|
+
}
|
|
81
|
+
var nodes_left = new Array(HUFFMAN_MAX_SYMBOLS);
|
|
82
|
+
var num_nodes_left = HUFFMAN_MAX_SYMBOLS;
|
|
83
|
+
for (var i = 0; i < HUFFMAN_MAX_SYMBOLS; i++) {
|
|
84
|
+
this.nodes[i].numbits = 0xFFFFFFFF;
|
|
85
|
+
this.nodes[i].symbol = i;
|
|
86
|
+
this.nodes[i].left = 0xFFFF;
|
|
87
|
+
this.nodes[i].right = 0xFFFF;
|
|
88
|
+
if (i == HUFFMAN_EOF_SYMBOL) {
|
|
89
|
+
nodes_left_storage[i].frequency = 1;
|
|
90
|
+
}
|
|
91
|
+
else
|
|
92
|
+
nodes_left_storage[i].frequency = frequencies[i];
|
|
93
|
+
nodes_left_storage[i].node_id = i;
|
|
94
|
+
nodes_left[i] = i;
|
|
95
|
+
}
|
|
96
|
+
this.num_nodes = HUFFMAN_MAX_SYMBOLS;
|
|
97
|
+
while (num_nodes_left > 1) {
|
|
98
|
+
nodes_left = this.bubble_sort(nodes_left, nodes_left_storage, num_nodes_left);
|
|
99
|
+
this.nodes[this.num_nodes].numbits = 0;
|
|
100
|
+
this.nodes[this.num_nodes].left = nodes_left_storage[nodes_left[num_nodes_left - 1]].node_id;
|
|
101
|
+
this.nodes[this.num_nodes].right = nodes_left_storage[nodes_left[num_nodes_left - 2]].node_id;
|
|
102
|
+
nodes_left_storage[nodes_left[num_nodes_left - 2]].node_id = this.num_nodes;
|
|
103
|
+
nodes_left_storage[nodes_left[num_nodes_left - 2]].frequency = nodes_left_storage[nodes_left[num_nodes_left - 1]].frequency
|
|
104
|
+
+ nodes_left_storage[nodes_left[num_nodes_left - 2]].frequency;
|
|
105
|
+
this.num_nodes++;
|
|
106
|
+
num_nodes_left--;
|
|
107
|
+
}
|
|
108
|
+
this.start_node_index = this.num_nodes - 1;
|
|
109
|
+
this.set_bits_r(this.start_node_index, 0, 0);
|
|
110
|
+
};
|
|
111
|
+
Huffman.prototype.compress = function (inp_buffer, start_index, size) {
|
|
112
|
+
if (start_index === void 0) { start_index = 0; }
|
|
113
|
+
if (size === void 0) { size = 0; }
|
|
114
|
+
var output = [];
|
|
115
|
+
var bits = 0;
|
|
116
|
+
var bitcount = 0;
|
|
117
|
+
if (size == 0)
|
|
118
|
+
size = inp_buffer.byteLength;
|
|
119
|
+
inp_buffer = inp_buffer.slice(start_index, start_index + size);
|
|
120
|
+
for (var i = 0; i < size; i++) {
|
|
121
|
+
var x = inp_buffer[i];
|
|
122
|
+
bits |= this.nodes[x].bits << bitcount;
|
|
123
|
+
bitcount += this.nodes[x].numbits;
|
|
124
|
+
while (bitcount >= 8) {
|
|
125
|
+
output.push(bits & 0xff);
|
|
126
|
+
bits >>= 8;
|
|
127
|
+
bitcount -= 8;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
bits |= this.nodes[HUFFMAN_EOF_SYMBOL].bits << bitcount;
|
|
131
|
+
bitcount += this.nodes[HUFFMAN_EOF_SYMBOL].numbits;
|
|
132
|
+
while (bitcount >= 8) {
|
|
133
|
+
output.push(bits & 0xff);
|
|
134
|
+
bits >>= 8;
|
|
135
|
+
bitcount -= 8;
|
|
136
|
+
}
|
|
137
|
+
output.push(bits);
|
|
138
|
+
return Buffer.from(output);
|
|
139
|
+
};
|
|
140
|
+
Huffman.prototype.decompress = function (inp_buffer, size) {
|
|
141
|
+
if (size === void 0) { size = 0; }
|
|
142
|
+
var bits = 0;
|
|
143
|
+
var bitcount = 0;
|
|
144
|
+
var eof = this.nodes[HUFFMAN_EOF_SYMBOL];
|
|
145
|
+
var output = [];
|
|
146
|
+
if (size == 0)
|
|
147
|
+
size = inp_buffer.byteLength;
|
|
148
|
+
inp_buffer = inp_buffer.slice(0, size);
|
|
149
|
+
var src_index = 0;
|
|
150
|
+
while (true) {
|
|
151
|
+
var node_i = -1;
|
|
152
|
+
if (bitcount >= HUFFMAN_LUTBITS)
|
|
153
|
+
node_i = this.decode_lut[bits & HUFFMAN_LUTMASK];
|
|
154
|
+
while (bitcount < 24 && src_index != size) {
|
|
155
|
+
bits |= inp_buffer[src_index] << bitcount;
|
|
156
|
+
bitcount += 8;
|
|
157
|
+
src_index++;
|
|
158
|
+
}
|
|
159
|
+
if (node_i == -1)
|
|
160
|
+
node_i = this.decode_lut[bits & HUFFMAN_LUTMASK];
|
|
161
|
+
if (this.nodes[node_i].numbits) {
|
|
162
|
+
bits >>= this.nodes[node_i].numbits;
|
|
163
|
+
bitcount -= this.nodes[node_i].numbits;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
bits >>= HUFFMAN_LUTBITS;
|
|
167
|
+
bitcount -= HUFFMAN_LUTBITS;
|
|
168
|
+
while (true) {
|
|
169
|
+
if (bits & 1) {
|
|
170
|
+
node_i = this.nodes[node_i].right;
|
|
171
|
+
}
|
|
172
|
+
else
|
|
173
|
+
node_i = this.nodes[node_i].left;
|
|
174
|
+
bitcount -= 1;
|
|
175
|
+
bits >>= 1;
|
|
176
|
+
if (this.nodes[node_i].numbits)
|
|
177
|
+
break;
|
|
178
|
+
if (bitcount == 0)
|
|
179
|
+
throw new Error("No more bits, decoding error");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
if (this.nodes[node_i] == eof)
|
|
183
|
+
break;
|
|
184
|
+
output.push(this.nodes[node_i].symbol);
|
|
185
|
+
}
|
|
186
|
+
return Buffer.from(output);
|
|
187
|
+
};
|
|
188
|
+
return Huffman;
|
|
189
|
+
}());
|
|
190
|
+
module.exports = Huffman;
|
package/lib/movement.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
;
|
|
4
|
+
var Movement = /** @class */ (function () {
|
|
5
|
+
function Movement() {
|
|
6
|
+
this.input = { m_Direction: 0, m_Fire: 0, m_Hook: 0, m_Jump: 0, m_NextWeapon: 0, m_PlayerFlags: 1, m_PrevWeapon: 0, m_TargetX: 0, m_TargetY: 0, m_WantedWeapon: 1 };
|
|
7
|
+
}
|
|
8
|
+
Movement.prototype.RunLeft = function () {
|
|
9
|
+
this.input.m_Direction = -1;
|
|
10
|
+
};
|
|
11
|
+
Movement.prototype.RunRight = function () {
|
|
12
|
+
this.input.m_Direction = 1;
|
|
13
|
+
};
|
|
14
|
+
Movement.prototype.RunStop = function () {
|
|
15
|
+
this.input.m_Direction = 0;
|
|
16
|
+
};
|
|
17
|
+
Movement.prototype.Jump = function (state) {
|
|
18
|
+
if (state === void 0) { state = true; }
|
|
19
|
+
this.input.m_Jump = state ? 1 : 0;
|
|
20
|
+
};
|
|
21
|
+
Movement.prototype.Fire = function () {
|
|
22
|
+
this.input.m_Fire = 1;
|
|
23
|
+
};
|
|
24
|
+
Movement.prototype.Hook = function (state) {
|
|
25
|
+
if (state === void 0) { state = true; }
|
|
26
|
+
this.input.m_Hook = state ? 1 : 0;
|
|
27
|
+
};
|
|
28
|
+
Movement.prototype.NextWeapon = function () {
|
|
29
|
+
this.input.m_NextWeapon = 1;
|
|
30
|
+
this.WantedWeapon(0);
|
|
31
|
+
};
|
|
32
|
+
Movement.prototype.PrevWeapon = function () {
|
|
33
|
+
this.input.m_PrevWeapon = 1;
|
|
34
|
+
this.WantedWeapon(0);
|
|
35
|
+
};
|
|
36
|
+
Movement.prototype.WantedWeapon = function (weapon) {
|
|
37
|
+
this.input.m_WantedWeapon = weapon;
|
|
38
|
+
};
|
|
39
|
+
Movement.prototype.SetAim = function (x, y) {
|
|
40
|
+
this.input.m_TargetX = x;
|
|
41
|
+
this.input.m_TargetY = y;
|
|
42
|
+
};
|
|
43
|
+
Movement.prototype.Reset = function () {
|
|
44
|
+
this.input.m_Direction = 0;
|
|
45
|
+
this.input.m_Jump = 0;
|
|
46
|
+
this.input.m_Fire = 0;
|
|
47
|
+
this.input.m_Hook = 0;
|
|
48
|
+
this.input.m_PlayerFlags = 0;
|
|
49
|
+
this.input.m_NextWeapon = 0;
|
|
50
|
+
this.input.m_PrevWeapon = 0;
|
|
51
|
+
};
|
|
52
|
+
return Movement;
|
|
53
|
+
}());
|
|
54
|
+
exports.default = Movement;
|