teeworlds 2.0.9 → 2.1.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.
@@ -1,44 +1,60 @@
1
1
  var decoder = new TextDecoder('utf-8');
2
- function unpackInt(pSrc: number[]): {result: number, remaining: number[]} {
2
+ export function unpackInt(pSrc: number[]): {result: number, remaining: number[]} {
3
3
  var result = 0;
4
4
  var len = 1;
5
5
 
6
6
  var iter = pSrc[Symbol.iterator]()
7
7
  var src: any = iter.next()
8
- // if (src.done)
9
- // console.warn("Unexpected end", src)
10
8
  src = src.value
11
9
  var sign = ((src >> 6) & 1)
12
10
 
13
11
  result |= (src & 0b0011_1111)
14
12
  for (let i = 0; i < 4; i++) {
15
13
 
16
- if ((src & 0b1000_0000) == 0)
14
+ if ((src & 0b1000_0000) === 0)
17
15
  break;
18
16
  src = iter.next()
19
17
 
20
- // console.log(src & 0b1000_0000)
21
- // if (src.done)
22
- // console.warn("Unexpected end", src);
23
- src = src.value
24
- len += 1;
25
- if (i == 3 && (src & 0b1111_0000) != 0)
26
- console.warn("NonZeroIntPadding")
18
+ src = src.value;
19
+ len++;
27
20
  result |= ((src & 0b0111_1111)) << (6+7*i)
28
21
 
29
22
  }
30
- if (len > 1 && src == 0b0000_0000) {
31
- console.warn("OverlongIntEncoding")
32
- }
33
23
  result ^= -sign;
34
24
 
35
25
  return {result, remaining: Array.from(iter)};
36
26
  }
37
- function unpackString(pSrc: number[]): {result: string, remaining: number[]} {
27
+ export function unpackString(pSrc: number[]): {result: string, remaining: number[]} {
38
28
  var result = pSrc.slice(0, pSrc.indexOf(0))
39
29
  pSrc = pSrc.slice(pSrc.indexOf(0), pSrc.length)
40
30
  return {result: decoder.decode(new Uint8Array(result)), remaining: pSrc}
41
31
  }
42
32
 
33
+ export class MsgUnpacker {
34
+ remaining: number[];
35
+ constructor(pSrc: number[]) {
36
+ this.remaining = pSrc;
37
+ }
38
+
39
+ unpackInt(_unpacked = false): number {
40
+ let unpacked;
41
+ if (!_unpacked) {
42
+ unpacked = unpackInt(this.remaining);
43
+ this.remaining = unpacked.remaining;
44
+ } else {
45
+ unpacked = {result: this.remaining[0]};
46
+ this.remaining = this.remaining.slice(1);
47
+
48
+ }
49
+ return unpacked.result;
50
+ }
51
+
52
+ unpackString(): string {
53
+ let unpacked = unpackString(this.remaining);
54
+ this.remaining = unpacked.remaining;
55
+ return unpacked.result;
56
+ }
57
+ }
58
+
43
59
 
44
- export = {unpackInt, unpackString};
60
+ // export = {MsgUnpacker, unpackInt, unpackString}
package/lib/client.ts CHANGED
@@ -4,7 +4,10 @@ import net from 'dgram';
4
4
  import fs from 'fs';
5
5
  import { EventEmitter } from 'stream';
6
6
  import { spawn } from 'child_process';
7
- import MsgUnpacker from './MsgUnpacker';
7
+
8
+ import { unpackInt, unpackString, MsgUnpacker } from "./MsgUnpacker";
9
+
10
+
8
11
  import MsgPacker from './MsgPacker';
9
12
  import { Snapshot } from './snapshot';
10
13
  import Huffman from "./huffman";
@@ -312,11 +315,11 @@ class Client extends EventEmitter {
312
315
  chat.forEach(a => {
313
316
  if (a.msg == "SV_CHAT") {
314
317
  var unpacked: iMessage = {} as iMessage;
315
- unpacked.team = MsgUnpacker.unpackInt(a.raw.toJSON().data).result;
316
- var remaining: number[] = MsgUnpacker.unpackInt(a.raw.toJSON().data).remaining;
317
- unpacked.client_id = MsgUnpacker.unpackInt(remaining).result;
318
- remaining = MsgUnpacker.unpackInt(remaining).remaining;
319
- unpacked.message = MsgUnpacker.unpackString(remaining).result;
318
+ unpacked.team = unpackInt(a.raw.toJSON().data).result;
319
+ var remaining: number[] = unpackInt(a.raw.toJSON().data).remaining;
320
+ unpacked.client_id = unpackInt(remaining).result;
321
+ remaining = unpackInt(remaining).remaining;
322
+ unpacked.message = unpackString(remaining).result;
320
323
  if (unpacked.client_id != -1)
321
324
  unpacked.author = { ClientInfo: this.client_infos[unpacked.client_id], PlayerInfo: this.player_infos[unpacked.client_id] }
322
325
  // console.log(unpacked)
@@ -329,13 +332,11 @@ class Client extends EventEmitter {
329
332
  chat.forEach(a => {
330
333
  if (a.msg == "SV_KILL_MSG") {
331
334
  var unpacked: iKillMsg = {} as iKillMsg;
332
- unpacked.killer_id = MsgUnpacker.unpackInt(a.raw.toJSON().data).result;
333
- var remaining: number[] = MsgUnpacker.unpackInt(a.raw.toJSON().data).remaining;
334
- unpacked.victim_id = MsgUnpacker.unpackInt(remaining).result;
335
- remaining = MsgUnpacker.unpackInt(remaining).remaining;
336
- unpacked.weapon = MsgUnpacker.unpackInt(remaining).result;
337
- remaining = MsgUnpacker.unpackInt(remaining).remaining;
338
- unpacked.special_mode = MsgUnpacker.unpackInt(remaining).result;
335
+ let unpacker = new MsgUnpacker(a.raw.toJSON().data);
336
+ unpacked.killer_id = unpacker.unpackInt();
337
+ unpacked.victim_id = unpacker.unpackInt();
338
+ unpacked.weapon = unpacker.unpackInt();
339
+ unpacked.special_mode = unpacker.unpackInt();
339
340
  if (unpacked.victim_id != -1)
340
341
  unpacked.victim = { ClientInfo: this.client_infos[unpacked.victim_id], PlayerInfo: this.player_infos[unpacked.victim_id] }
341
342
  if (unpacked.killer_id != -1)
@@ -369,7 +370,7 @@ class Client extends EventEmitter {
369
370
  } else if (a.toJSON().data[3] == 0x4) {
370
371
  // disconnected
371
372
  this.State = 0;
372
- let reason: string = (MsgUnpacker.unpackString(a.toJSON().data.slice(4)).result);
373
+ let reason: string = (unpackString(a.toJSON().data.slice(4)).result);
373
374
  this.State = -1;
374
375
  this.emit("disconnect", reason);
375
376
  }
@@ -417,19 +418,19 @@ class Client extends EventEmitter {
417
418
  let part = 0;
418
419
  let num_parts = 1;
419
420
  chunks.forEach(chunk => {
420
- let AckGameTick = (MsgUnpacker.unpackInt(chunk.raw.toJSON().data).result);
421
- chunk.raw = Buffer.from(MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).remaining);
422
- let DeltaTick = MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).result
421
+ let AckGameTick = (unpackInt(chunk.raw.toJSON().data).result);
422
+ chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining);
423
+ let DeltaTick = unpackInt(chunk?.raw?.toJSON().data).result
423
424
  if (chunk.msg == "SNAP") {
424
- chunk.raw = Buffer.from(MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).remaining); // delta tick
425
- num_parts = (MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).result)
426
- chunk.raw = Buffer.from(MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).remaining); // num parts
427
- part = (MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).result)
425
+ chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // delta tick
426
+ num_parts = (unpackInt(chunk?.raw?.toJSON().data).result)
427
+ chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // num parts
428
+ part = (unpackInt(chunk?.raw?.toJSON().data).result)
428
429
  }
429
- chunk.raw = Buffer.from(MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).remaining); // part
430
+ chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // part
430
431
  if (chunk.msg != "SNAP_EMPTY")
431
- chunk.raw = Buffer.from(MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).remaining); // crc
432
- chunk.raw = Buffer.from(MsgUnpacker.unpackInt(chunk?.raw?.toJSON().data).remaining); // crc
432
+ chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // crc
433
+ chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // crc
433
434
  if (part == 0 || this.snaps.length > 30) {
434
435
  this.snaps = [];
435
436
  }
package/lib/snapshot.ts CHANGED
@@ -1,4 +1,4 @@
1
- var MsgUnpacker = require('./MsgUnpacker');
1
+ import { MsgUnpacker } from "./MsgUnpacker";
2
2
  var decoder = new TextDecoder('utf-8');
3
3
 
4
4
  const itemAppendix: {"type_id": number, "size": number, "name": string}[] = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teeworlds",
3
- "version": "2.0.9",
3
+ "version": "2.1.0",
4
4
  "description": "Library for (ingame) teeworlds bots.",
5
5
  "license": "MIT",
6
6
  "main": "index.js",
package/lib/MsgPacker.js DELETED
@@ -1,53 +0,0 @@
1
- "use strict";
2
- var MsgPacker = /** @class */ (function () {
3
- function MsgPacker(msg, sys) {
4
- this.result = Buffer.from([2 * msg + (sys ? 1 : 0)]); // booleans turn into int automatically.
5
- this.sys = sys;
6
- }
7
- MsgPacker.prototype.AddString = function (str) {
8
- this.result = Buffer.concat([this.result, Buffer.from(str), Buffer.from([0x00])]);
9
- };
10
- MsgPacker.prototype.AddBuffer = function (buffer) {
11
- this.result = Buffer.concat([this.result, buffer]);
12
- };
13
- MsgPacker.prototype.AddInt = function (i) {
14
- var result = [];
15
- var pDst = (i >> 25) & 0x40;
16
- var i = i ^ (i >> 31);
17
- pDst |= i & 0x3f;
18
- i >>= 6;
19
- if (i) {
20
- pDst |= 0x80;
21
- result.push(pDst);
22
- while (true) {
23
- pDst++;
24
- pDst = i & (0x7f);
25
- i >>= 7;
26
- pDst |= (Number(i != 0)) << 7;
27
- result.push(pDst);
28
- if (!i)
29
- break;
30
- }
31
- }
32
- else
33
- result.push(pDst);
34
- // ... i'll just stop trying to understand.
35
- this.result = Buffer.concat([this.result, Buffer.from(result)]);
36
- };
37
- Object.defineProperty(MsgPacker.prototype, "size", {
38
- get: function () {
39
- return this.result.byteLength;
40
- },
41
- enumerable: false,
42
- configurable: true
43
- });
44
- Object.defineProperty(MsgPacker.prototype, "buffer", {
45
- get: function () {
46
- return this.result;
47
- },
48
- enumerable: false,
49
- configurable: true
50
- });
51
- return MsgPacker;
52
- }());
53
- module.exports = MsgPacker;
@@ -1,37 +0,0 @@
1
- "use strict";
2
- var decoder = new TextDecoder('utf-8');
3
- function unpackInt(pSrc) {
4
- var result = 0;
5
- var len = 1;
6
- var iter = pSrc[Symbol.iterator]();
7
- var src = iter.next();
8
- // if (src.done)
9
- // console.warn("Unexpected end", src)
10
- src = src.value;
11
- var sign = ((src >> 6) & 1);
12
- result |= (src & 63);
13
- for (var i = 0; i < 4; i++) {
14
- if ((src & 128) == 0)
15
- break;
16
- src = iter.next();
17
- // console.log(src & 0b1000_0000)
18
- // if (src.done)
19
- // console.warn("Unexpected end", src);
20
- src = src.value;
21
- len += 1;
22
- if (i == 3 && (src & 240) != 0)
23
- console.warn("NonZeroIntPadding");
24
- result |= ((src & 127)) << (6 + 7 * i);
25
- }
26
- if (len > 1 && src == 0) {
27
- console.warn("OverlongIntEncoding");
28
- }
29
- result ^= -sign;
30
- return { result: result, remaining: Array.from(iter) };
31
- }
32
- function unpackString(pSrc) {
33
- var result = pSrc.slice(0, pSrc.indexOf(0));
34
- pSrc = pSrc.slice(pSrc.indexOf(0), pSrc.length);
35
- return { result: decoder.decode(new Uint8Array(result)), remaining: pSrc };
36
- }
37
- module.exports = { unpackInt: unpackInt, unpackString: unpackString };
package/lib/client.js DELETED
@@ -1,511 +0,0 @@
1
- "use strict";
2
- var __extends = (this && this.__extends) || (function () {
3
- var extendStatics = function (d, b) {
4
- extendStatics = Object.setPrototypeOf ||
5
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
- function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
- return extendStatics(d, b);
8
- };
9
- return function (d, b) {
10
- extendStatics(d, b);
11
- function __() { this.constructor = d; }
12
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
- };
14
- })();
15
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
16
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
17
- return new (P || (P = Promise))(function (resolve, reject) {
18
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
19
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
20
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
21
- step((generator = generator.apply(thisArg, _arguments || [])).next());
22
- });
23
- };
24
- var __generator = (this && this.__generator) || function (thisArg, body) {
25
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
26
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
27
- function verb(n) { return function (v) { return step([n, v]); }; }
28
- function step(op) {
29
- if (f) throw new TypeError("Generator is already executing.");
30
- while (_) try {
31
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
32
- if (y = 0, t) op = [op[0] & 2, t.value];
33
- switch (op[0]) {
34
- case 0: case 1: t = op; break;
35
- case 4: _.label++; return { value: op[1], done: false };
36
- case 5: _.label++; y = op[1]; op = [0]; continue;
37
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
38
- default:
39
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
40
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
41
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
42
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
43
- if (t[2]) _.ops.pop();
44
- _.trys.pop(); continue;
45
- }
46
- op = body.call(thisArg, _);
47
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
48
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
49
- }
50
- };
51
- var __importDefault = (this && this.__importDefault) || function (mod) {
52
- return (mod && mod.__esModule) ? mod : { "default": mod };
53
- };
54
- var crypto_1 = require("crypto");
55
- var dgram_1 = __importDefault(require("dgram"));
56
- var stream_1 = require("stream");
57
- var MsgUnpacker_1 = __importDefault(require("./MsgUnpacker"));
58
- var MsgPacker_1 = __importDefault(require("./MsgPacker"));
59
- var snapshot_1 = require("./snapshot");
60
- var huffman_1 = __importDefault(require("./huffman"));
61
- var huff = new huffman_1.default();
62
- var SnapUnpacker = new snapshot_1.Snapshot();
63
- var NETMSGTYPE;
64
- (function (NETMSGTYPE) {
65
- NETMSGTYPE[NETMSGTYPE["EX"] = 0] = "EX";
66
- NETMSGTYPE[NETMSGTYPE["SV_MOTD"] = 1] = "SV_MOTD";
67
- NETMSGTYPE[NETMSGTYPE["SV_BROADCAST"] = 2] = "SV_BROADCAST";
68
- NETMSGTYPE[NETMSGTYPE["SV_CHAT"] = 3] = "SV_CHAT";
69
- NETMSGTYPE[NETMSGTYPE["SV_KILLMSG"] = 4] = "SV_KILLMSG";
70
- NETMSGTYPE[NETMSGTYPE["SV_SOUNDGLOBAL"] = 5] = "SV_SOUNDGLOBAL";
71
- NETMSGTYPE[NETMSGTYPE["SV_TUNEPARAMS"] = 6] = "SV_TUNEPARAMS";
72
- NETMSGTYPE[NETMSGTYPE["SV_EXTRAPROJECTILE"] = 7] = "SV_EXTRAPROJECTILE";
73
- NETMSGTYPE[NETMSGTYPE["SV_READYTOENTER"] = 8] = "SV_READYTOENTER";
74
- NETMSGTYPE[NETMSGTYPE["SV_WEAPONPICKUP"] = 9] = "SV_WEAPONPICKUP";
75
- NETMSGTYPE[NETMSGTYPE["SV_EMOTICON"] = 10] = "SV_EMOTICON";
76
- NETMSGTYPE[NETMSGTYPE["SV_VOTECLEAROPTIONS"] = 11] = "SV_VOTECLEAROPTIONS";
77
- NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONLISTADD"] = 12] = "SV_VOTEOPTIONLISTADD";
78
- NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONADD"] = 13] = "SV_VOTEOPTIONADD";
79
- NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONREMOVE"] = 14] = "SV_VOTEOPTIONREMOVE";
80
- NETMSGTYPE[NETMSGTYPE["SV_VOTESET"] = 15] = "SV_VOTESET";
81
- NETMSGTYPE[NETMSGTYPE["SV_VOTESTATUS"] = 16] = "SV_VOTESTATUS";
82
- NETMSGTYPE[NETMSGTYPE["CL_SAY"] = 17] = "CL_SAY";
83
- NETMSGTYPE[NETMSGTYPE["CL_SETTEAM"] = 18] = "CL_SETTEAM";
84
- NETMSGTYPE[NETMSGTYPE["CL_SETSPECTATORMODE"] = 19] = "CL_SETSPECTATORMODE";
85
- NETMSGTYPE[NETMSGTYPE["CL_STARTINFO"] = 20] = "CL_STARTINFO";
86
- NETMSGTYPE[NETMSGTYPE["CL_CHANGEINFO"] = 21] = "CL_CHANGEINFO";
87
- NETMSGTYPE[NETMSGTYPE["CL_KILL"] = 22] = "CL_KILL";
88
- NETMSGTYPE[NETMSGTYPE["CL_EMOTICON"] = 23] = "CL_EMOTICON";
89
- NETMSGTYPE[NETMSGTYPE["CL_VOTE"] = 24] = "CL_VOTE";
90
- NETMSGTYPE[NETMSGTYPE["CL_CALLVOTE"] = 25] = "CL_CALLVOTE";
91
- NETMSGTYPE[NETMSGTYPE["CL_ISDDNETLEGACY"] = 26] = "CL_ISDDNETLEGACY";
92
- NETMSGTYPE[NETMSGTYPE["SV_DDRACETIMELEGACY"] = 27] = "SV_DDRACETIMELEGACY";
93
- NETMSGTYPE[NETMSGTYPE["SV_RECORDLEGACY"] = 28] = "SV_RECORDLEGACY";
94
- NETMSGTYPE[NETMSGTYPE["UNUSED"] = 29] = "UNUSED";
95
- NETMSGTYPE[NETMSGTYPE["SV_TEAMSSTATELEGACY"] = 30] = "SV_TEAMSSTATELEGACY";
96
- NETMSGTYPE[NETMSGTYPE["CL_SHOWOTHERSLEGACY"] = 31] = "CL_SHOWOTHERSLEGACY";
97
- NETMSGTYPE[NETMSGTYPE["NUM"] = 32] = "NUM";
98
- })(NETMSGTYPE || (NETMSGTYPE = {}));
99
- var items;
100
- (function (items) {
101
- items[items["OBJ_EX"] = 0] = "OBJ_EX";
102
- items[items["OBJ_PLAYER_INPUT"] = 1] = "OBJ_PLAYER_INPUT";
103
- items[items["OBJ_PROJECTILE"] = 2] = "OBJ_PROJECTILE";
104
- items[items["OBJ_LASER"] = 3] = "OBJ_LASER";
105
- items[items["OBJ_PICKUP"] = 4] = "OBJ_PICKUP";
106
- items[items["OBJ_FLAG"] = 5] = "OBJ_FLAG";
107
- items[items["OBJ_GAME_INFO"] = 6] = "OBJ_GAME_INFO";
108
- items[items["OBJ_GAME_DATA"] = 7] = "OBJ_GAME_DATA";
109
- items[items["OBJ_CHARACTER_CORE"] = 8] = "OBJ_CHARACTER_CORE";
110
- items[items["OBJ_CHARACTER"] = 9] = "OBJ_CHARACTER";
111
- items[items["OBJ_PLAYER_INFO"] = 10] = "OBJ_PLAYER_INFO";
112
- items[items["OBJ_CLIENT_INFO"] = 11] = "OBJ_CLIENT_INFO";
113
- items[items["OBJ_SPECTATOR_INFO"] = 12] = "OBJ_SPECTATOR_INFO";
114
- items[items["EVENT_COMMON"] = 13] = "EVENT_COMMON";
115
- items[items["EVENT_EXPLOSION"] = 14] = "EVENT_EXPLOSION";
116
- items[items["EVENT_SPAWN"] = 15] = "EVENT_SPAWN";
117
- items[items["EVENT_HAMMERHIT"] = 16] = "EVENT_HAMMERHIT";
118
- items[items["EVENT_DEATH"] = 17] = "EVENT_DEATH";
119
- items[items["EVENT_SOUND_GLOBAL"] = 18] = "EVENT_SOUND_GLOBAL";
120
- items[items["EVENT_SOUND_WORLD"] = 19] = "EVENT_SOUND_WORLD";
121
- items[items["EVENT_DAMAGE_INDICATOR"] = 20] = "EVENT_DAMAGE_INDICATOR";
122
- })(items || (items = {}));
123
- function toHexStream(buff) {
124
- return buff.toJSON().data.map(function (a) { return ('0' + (a & 0xff).toString(16)).slice(-2); }).join("");
125
- }
126
- var messageTypes = [
127
- ["none, starts at 1", "SV_MOTD", "SV_BROADCAST", "SV_CHAT", "SV_KILL_MSG", "SV_SOUND_GLOBAL", "SV_TUNE_PARAMS", "SV_EXTRA_PROJECTILE", "SV_READY_TO_ENTER", "SV_WEAPON_PICKUP", "SV_EMOTICON", "SV_VOTE_CLEAR_OPTIONS", "SV_VOTE_OPTION_LIST_ADD", "SV_VOTE_OPTION_ADD", "SV_VOTE_OPTION_REMOVE", "SV_VOTE_SET", "SV_VOTE_STATUS", "CL_SAY", "CL_SET_TEAM", "CL_SET_SPECTATOR_MODE", "CL_START_INFO", "CL_CHANGE_INFO", "CL_KILL", "CL_EMOTICON", "CL_VOTE", "CL_CALL_VOTE", "CL_IS_DDNET", "SV_DDRACE_TIME", "SV_RECORD", "UNUSED", "SV_TEAMS_STATE", "CL_SHOW_OTHERS_LEGACY"],
128
- ["none, starts at 1", "INFO", "MAP_CHANGE", "MAP_DATA", "CON_READY", "SNAP", "SNAP_EMPTY", "SNAP_SINGLE", "INPUT_TIMING", "RCON_AUTH_STATUS", "RCON_LINE", "READY", "ENTER_GAME", "INPUT", "RCON_CMD", "RCON_AUTH", "REQUEST_MAP_DATA", "PING", "PING_REPLY", "RCON_CMD_ADD", "RCON_CMD_REMOVE"]
129
- ];
130
- var messageUUIDs = {
131
- "WHAT_IS": Buffer.from([0x24, 0x5e, 0x50, 0x97, 0x9f, 0xe0, 0x39, 0xd6, 0xbf, 0x7d, 0x9a, 0x29, 0xe1, 0x69, 0x1e, 0x4c]),
132
- "IT_IS": Buffer.from([0x69, 0x54, 0x84, 0x7e, 0x2e, 0x87, 0x36, 0x03, 0xb5, 0x62, 0x36, 0xda, 0x29, 0xed, 0x1a, 0xca]),
133
- "I_DONT_KNOW": Buffer.from([0x41, 0x69, 0x11, 0xb5, 0x79, 0x73, 0x33, 0xbf, 0x8d, 0x52, 0x7b, 0xf0, 0x1e, 0x51, 0x9c, 0xf0]),
134
- "RCON_TYPE": Buffer.from([0x12, 0x81, 0x0e, 0x1f, 0xa1, 0xdb, 0x33, 0x78, 0xb4, 0xfb, 0x16, 0x4e, 0xd6, 0x50, 0x59, 0x26]),
135
- "MAP_DETAILS": Buffer.from([0xf9, 0x11, 0x7b, 0x3c, 0x80, 0x39, 0x34, 0x16, 0x9f, 0xc0, 0xae, 0xf2, 0xbc, 0xb7, 0x5c, 0x03]),
136
- "CLIENT_VERSION": Buffer.from([0x8c, 0x00, 0x13, 0x04, 0x84, 0x61, 0x3e, 0x47, 0x87, 0x87, 0xf6, 0x72, 0xb3, 0x83, 0x5b, 0xd4]),
137
- "CAPABILITIES": Buffer.from([0xf6, 0x21, 0xa5, 0xa1, 0xf5, 0x85, 0x37, 0x75, 0x8e, 0x73, 0x41, 0xbe, 0xee, 0x79, 0xf2, 0xb2]),
138
- };
139
- function arrStartsWith(arr, arrStart, start) {
140
- if (start === void 0) { start = 0; }
141
- arr.splice(0, start);
142
- for (var i = 0; i < arrStart.length; i++) {
143
- if (arr[i] == arrStart[i])
144
- continue;
145
- else
146
- return false;
147
- }
148
- return true;
149
- }
150
- var Client = /** @class */ (function (_super) {
151
- __extends(Client, _super);
152
- function Client(ip, port, nickname) {
153
- var _this = _super.call(this) || this;
154
- _this.host = ip;
155
- _this.port = port;
156
- _this.name = nickname;
157
- _this.snaps = [];
158
- _this.client_infos = [];
159
- _this.player_infos = [];
160
- _this.State = 0; // 0 = offline; 1 = STATE_CONNECTING = 1, STATE_LOADING = 2, STATE_ONLINE = 3
161
- _this.ack = 0; // ack of messages the client has received
162
- _this.clientAck = 0; // ack of messages the client has sent
163
- _this.receivedSnaps = 0; /* wait for 2 snaps before seeing self as connected */
164
- _this.lastMsg = "";
165
- _this._port = Math.floor(Math.random() * 65535);
166
- _this.socket = dgram_1.default.createSocket("udp4");
167
- _this.socket.bind();
168
- _this.TKEN = Buffer.from([255, 255, 255, 255]);
169
- _this.time = new Date().getTime() + 2000; // time (used for keepalives, start to send keepalives after 2 seconds)
170
- _this.State = 0;
171
- return _this;
172
- }
173
- Client.prototype.Unpack = function (packet) {
174
- return __awaiter(this, void 0, void 0, function () {
175
- var unpacked, i, chunk;
176
- return __generator(this, function (_a) {
177
- unpacked = { twprotocol: { flags: packet[0], ack: packet[1], chunkAmount: packet[2], size: packet.byteLength - 3 }, chunks: [] };
178
- if (packet.indexOf(Buffer.from([0xff, 0xff, 0xff, 0xff])) == 0 && !(unpacked.twprotocol.flags & 8) || unpacked.twprotocol.flags == 255) // flags == 255 is connectionless (used for sending usernames)
179
- return [2 /*return*/, unpacked];
180
- packet = packet.slice(3);
181
- if (unpacked.twprotocol.flags & 128) {
182
- packet = huff.decompress(packet);
183
- if (packet.length == 1 && packet[0] == -1)
184
- return [2 /*return*/, unpacked];
185
- }
186
- // return unpacked;
187
- for (i = 0; i < unpacked.twprotocol.chunkAmount; i++) {
188
- chunk = {};
189
- chunk.bytes = ((packet[0] & 0x3f) << 4) | (packet[1] & ((1 << 4) - 1)); // idk what this shit is but it works
190
- chunk.flags = (packet[0] >> 6) & 3;
191
- chunk.sequence = -1;
192
- if (chunk.flags & 1) {
193
- chunk.seq = ((packet[1] & 0xf0) << 2) | packet[2];
194
- packet = packet.slice(3); // remove flags & size
195
- }
196
- else
197
- packet = packet.slice(2);
198
- chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
199
- chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
200
- chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
201
- chunk.raw = packet.slice(1, chunk.bytes);
202
- Object.values(messageUUIDs).forEach(function (a, i) {
203
- if (a.compare(packet.slice(0, 16)) == 0) {
204
- chunk.extended_msgid = a;
205
- // chunk.type = 'sys';
206
- chunk.msg = Object.keys(messageUUIDs)[i];
207
- }
208
- });
209
- packet = packet.slice(chunk.bytes); // +1 cuz it adds an extra \x00 for easier parsing i guess
210
- unpacked.chunks.push(chunk);
211
- }
212
- return [2 /*return*/, unpacked];
213
- });
214
- });
215
- };
216
- Client.prototype.SendControlMsg = function (msg, ExtraMsg) {
217
- var _this = this;
218
- if (ExtraMsg === void 0) { ExtraMsg = ""; }
219
- return new Promise(function (resolve, reject) {
220
- if (_this.socket) {
221
- var latestBuf = Buffer.from([0x10 + (((16 << 4) & 0xf0) | ((_this.ack >> 8) & 0xf)), _this.ack & 0xff, 0x00, msg]);
222
- latestBuf = Buffer.concat([latestBuf, Buffer.from(ExtraMsg), _this.TKEN]); // move header (latestBuf), optional extraMsg & TKEN into 1 buffer
223
- _this.socket.send(latestBuf, 0, latestBuf.length, _this.port, _this.host, function (err, bytes) {
224
- resolve(bytes);
225
- });
226
- }
227
- setTimeout(function () { resolve("failed, rip"); }, 2000);
228
- /* after 2 seconds it was probably not able to send,
229
- so when sending a quit message the user doesnt
230
- stay stuck not being able to ctrl + c
231
- */
232
- });
233
- };
234
- Client.prototype.SendMsgEx = function (Msg, Flags) {
235
- if (this.State == -1)
236
- throw new Error("Client is not connected");
237
- if (!this.socket)
238
- return;
239
- var header = [];
240
- header[0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
241
- header[1] = (Msg.size & 0xf);
242
- if (Flags & 1) {
243
- this.clientAck = (this.clientAck + 1) % (1 << 10);
244
- header[1] |= (this.clientAck >> 2) & 0xf0;
245
- header[2] = this.clientAck & 0xff;
246
- }
247
- var latestBuf = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff, 0x1, header[0], header[1], this.clientAck]);
248
- var latestBuf = Buffer.concat([latestBuf, Msg.buffer, this.TKEN]);
249
- this.socket.send(latestBuf, 0, latestBuf.length, this.port, this.host);
250
- };
251
- Client.prototype.SendMsgExWithChunks = function (Msgs, Flags) {
252
- var _this = this;
253
- if (this.State == -1)
254
- throw new Error("Client is not connected");
255
- if (!this.socket)
256
- return;
257
- var header = [];
258
- Msgs.forEach(function (Msg, index) {
259
- header[index] = new Array(2);
260
- header[index][0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
261
- header[index][1] = (Msg.size & 0xf);
262
- if (Flags & 1) {
263
- _this.clientAck = (_this.clientAck + 1) % (1 << 10);
264
- header[index][1] |= (_this.clientAck >> 2) & 0xf0;
265
- header[index][2] = _this.clientAck & 0xff;
266
- }
267
- });
268
- var packetHeader = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff, Msgs.length]);
269
- var chunks = Buffer.from([]);
270
- Msgs.forEach(function (Msg, index) {
271
- chunks = Buffer.concat([chunks, Buffer.from(header[index]), Msg.buffer]);
272
- });
273
- var packet = Buffer.concat([(packetHeader), chunks, this.TKEN]);
274
- this.socket.send(packet, 0, packet.length, this.port, this.host);
275
- };
276
- Client.prototype.connect = function () {
277
- var _this = this;
278
- this.SendControlMsg(1, "TKEN");
279
- var connectInterval = setInterval(function () {
280
- if (_this.State == 0)
281
- _this.SendControlMsg(1, "TKEN");
282
- else
283
- clearInterval(connectInterval);
284
- }, 500);
285
- this.time = new Date().getTime() + 2000; // start sending keepalives after 2s
286
- if (this.socket)
287
- this.socket.on("message", function (a) { return __awaiter(_this, void 0, void 0, function () {
288
- var unpacked, chunkMessages, chat, chat, info, client_version, randomUuid, reason, Msg, Msg, info, info, chunks, part_1, num_parts_1;
289
- var _this = this;
290
- return __generator(this, function (_a) {
291
- switch (_a.label) {
292
- case 0: return [4 /*yield*/, this.Unpack(a)];
293
- case 1:
294
- unpacked = _a.sent();
295
- if (unpacked.twprotocol.flags != 128 && unpacked.twprotocol.ack) {
296
- unpacked.chunks.forEach(function (a) {
297
- if (a.msg && !a.msg.startsWith("SNAP")) {
298
- if (a.seq != undefined && a.seq != -1)
299
- _this.ack = a.seq;
300
- }
301
- });
302
- }
303
- chunkMessages = unpacked.chunks.map(function (a) { return a.msg; });
304
- if (chunkMessages.includes("SV_CHAT")) {
305
- chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_CHAT"; });
306
- chat.forEach(function (a) {
307
- if (a.msg == "SV_CHAT") {
308
- var unpacked = {};
309
- unpacked.team = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).result;
310
- var remaining = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).remaining;
311
- unpacked.client_id = MsgUnpacker_1.default.unpackInt(remaining).result;
312
- remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
313
- unpacked.message = MsgUnpacker_1.default.unpackString(remaining).result;
314
- if (unpacked.client_id != -1)
315
- unpacked.author = { ClientInfo: _this.client_infos[unpacked.client_id], PlayerInfo: _this.player_infos[unpacked.client_id] };
316
- // console.log(unpacked)
317
- _this.emit("message", unpacked);
318
- }
319
- });
320
- }
321
- if (chunkMessages.includes("SV_KILL_MSG")) {
322
- chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_KILL_MSG"; });
323
- chat.forEach(function (a) {
324
- if (a.msg == "SV_KILL_MSG") {
325
- var unpacked = {};
326
- unpacked.killer_id = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).result;
327
- var remaining = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).remaining;
328
- unpacked.victim_id = MsgUnpacker_1.default.unpackInt(remaining).result;
329
- remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
330
- unpacked.weapon = MsgUnpacker_1.default.unpackInt(remaining).result;
331
- remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
332
- unpacked.special_mode = MsgUnpacker_1.default.unpackInt(remaining).result;
333
- if (unpacked.victim_id != -1)
334
- unpacked.victim = { ClientInfo: _this.client_infos[unpacked.victim_id], PlayerInfo: _this.player_infos[unpacked.victim_id] };
335
- if (unpacked.killer_id != -1)
336
- unpacked.killer = { ClientInfo: _this.client_infos[unpacked.killer_id], PlayerInfo: _this.player_infos[unpacked.killer_id] };
337
- // console.log(unpacked)
338
- _this.emit("kill", unpacked);
339
- }
340
- });
341
- }
342
- if (a.toJSON().data[0] == 0x10) {
343
- if (a.toString().includes("TKEN") || arrStartsWith(a.toJSON().data, [0x10, 0x0, 0x0, 0x0])) {
344
- clearInterval(connectInterval);
345
- this.TKEN = Buffer.from(a.toJSON().data.slice(a.toJSON().data.length - 4, a.toJSON().data.length));
346
- this.SendControlMsg(3);
347
- this.State = 2; // loading state
348
- info = new MsgPacker_1.default(1, true);
349
- info.AddString("0.6 626fce9a778df4d4");
350
- info.AddString(""); // password
351
- client_version = new MsgPacker_1.default(0, true);
352
- client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
353
- randomUuid = new Uint8Array(16);
354
- crypto_1.randomBytes(16).copy(randomUuid);
355
- client_version.AddBuffer(Buffer.from(randomUuid));
356
- client_version.AddInt(15091);
357
- client_version.AddString("DDNet 15.9.1");
358
- this.SendMsgExWithChunks([client_version, info], 1);
359
- }
360
- else if (a.toJSON().data[3] == 0x4) {
361
- // disconnected
362
- this.State = 0;
363
- reason = (MsgUnpacker_1.default.unpackString(a.toJSON().data.slice(4)).result);
364
- this.State = -1;
365
- this.emit("disconnect", reason);
366
- }
367
- }
368
- if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
369
- Msg = new MsgPacker_1.default(15, true);
370
- this.SendMsgEx(Msg, 1);
371
- }
372
- else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
373
- Msg = new MsgPacker_1.default(14, true);
374
- this.SendMsgEx(Msg, 1);
375
- }
376
- else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY") || unpacked.chunks[0] && chunkMessages.includes("SV_MOTD"))) {
377
- info = new MsgPacker_1.default(20, false);
378
- info.AddString(this.name); /* name */
379
- info.AddString(""); /* clan */
380
- info.AddInt(-1); /* country */
381
- info.AddString("greyfox"); /* skin */
382
- info.AddInt(1); /* use custom color */
383
- info.AddInt(10346103); /* color body */
384
- info.AddInt(65535); /* color feet */
385
- this.SendMsgEx(info, 1);
386
- }
387
- else if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
388
- if (this.State != 3) {
389
- this.emit('connected');
390
- }
391
- this.State = 3;
392
- }
393
- else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
394
- info = new MsgPacker_1.default(23, true);
395
- this.SendMsgEx(info, 1);
396
- }
397
- if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
398
- this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
399
- if (this.receivedSnaps >= 2) {
400
- if (this.State != 3)
401
- this.emit('connected');
402
- this.State = 3;
403
- }
404
- chunks = unpacked.chunks.filter(function (a) { return a.msg == "SNAP" || a.msg == "SNAP_SINGLE" || a.msg == "SNAP_EMPTY"; });
405
- if (chunks.length > 0) {
406
- part_1 = 0;
407
- num_parts_1 = 1;
408
- chunks.forEach(function (chunk) {
409
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
410
- var AckGameTick = (MsgUnpacker_1.default.unpackInt(chunk.raw.toJSON().data).result);
411
- chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_a = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _a === void 0 ? void 0 : _a.toJSON().data).remaining);
412
- var DeltaTick = MsgUnpacker_1.default.unpackInt((_b = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _b === void 0 ? void 0 : _b.toJSON().data).result;
413
- if (chunk.msg == "SNAP") {
414
- chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_c = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _c === void 0 ? void 0 : _c.toJSON().data).remaining); // delta tick
415
- num_parts_1 = (MsgUnpacker_1.default.unpackInt((_d = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _d === void 0 ? void 0 : _d.toJSON().data).result);
416
- chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_e = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _e === void 0 ? void 0 : _e.toJSON().data).remaining); // num parts
417
- part_1 = (MsgUnpacker_1.default.unpackInt((_f = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _f === void 0 ? void 0 : _f.toJSON().data).result);
418
- }
419
- chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_g = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _g === void 0 ? void 0 : _g.toJSON().data).remaining); // part
420
- if (chunk.msg != "SNAP_EMPTY")
421
- chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_h = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _h === void 0 ? void 0 : _h.toJSON().data).remaining); // crc
422
- chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_j = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _j === void 0 ? void 0 : _j.toJSON().data).remaining); // crc
423
- if (part_1 == 0 || _this.snaps.length > 30) {
424
- _this.snaps = [];
425
- }
426
- _this.snaps.push(chunk.raw);
427
- if ((num_parts_1 - 1) == part_1 && _this.snaps.length == num_parts_1) {
428
- var mergedSnaps = Buffer.concat(_this.snaps);
429
- var snapUnpacked = SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, 1);
430
- snapUnpacked.items.forEach(function (a, i) {
431
- if (a.type_id == items.OBJ_CLIENT_INFO) {
432
- _this.client_infos[a.id] = a.parsed;
433
- // console.log(a.parsed, i)
434
- // console.log(this.client_infos[a.id])
435
- }
436
- else if (a.type_id == items.OBJ_PLAYER_INFO) {
437
- _this.player_infos[i] = a.parsed;
438
- }
439
- else if (a.type_id == items.OBJ_EX || a.type_id > 0x4000) {
440
- if (a.data.length == 5 && (a.parsed.freeze_end > 0 || a.parsed.freeze_end == -1)) {
441
- // var packer = new MsgPacker(22, false)
442
- // this.SendMsgEx(packer, 1)
443
- }
444
- }
445
- });
446
- }
447
- });
448
- }
449
- }
450
- if (new Date().getTime() - this.time >= 1000) {
451
- this.time = new Date().getTime();
452
- this.SendControlMsg(0);
453
- }
454
- return [2 /*return*/];
455
- }
456
- });
457
- }); });
458
- };
459
- Client.prototype.Disconnect = function () {
460
- var _this = this;
461
- return new Promise(function (resolve) {
462
- _this.SendControlMsg(4).then(function () {
463
- resolve(true);
464
- if (_this.socket)
465
- _this.socket.close();
466
- _this.socket = undefined;
467
- _this.State = -1;
468
- });
469
- });
470
- };
471
- Client.prototype.Say = function (message, team) {
472
- if (team === void 0) { team = false; }
473
- var packer = new MsgPacker_1.default(NETMSGTYPE.CL_SAY, false);
474
- packer.AddInt(team ? 1 : 0); // team
475
- packer.AddString(message);
476
- this.SendMsgEx(packer, 1);
477
- };
478
- Client.prototype.Vote = function (vote) {
479
- var packer = new MsgPacker_1.default(NETMSGTYPE.CL_VOTE, false);
480
- packer.AddInt(vote ? 1 : 0);
481
- this.SendMsgEx(packer, 1);
482
- };
483
- Client.prototype.ChangePlayerInfo = function (playerInfo) {
484
- var packer = new MsgPacker_1.default(NETMSGTYPE.CL_CHANGEINFO, false);
485
- packer.AddString(playerInfo.name); //m_pName);
486
- packer.AddString(playerInfo.clan); //m_pClan);
487
- packer.AddInt(playerInfo.country); //m_Country);
488
- packer.AddString(playerInfo.skin); //m_pSkin);
489
- packer.AddInt(playerInfo.use_custom_color ? 1 : 0); //m_UseCustomColor);
490
- packer.AddInt(playerInfo.color_body); //m_ColorBody);
491
- packer.AddInt(playerInfo.color_feet); //m_ColorFeet);
492
- this.SendMsgEx(packer, 1);
493
- };
494
- Client.prototype.Kill = function () {
495
- var packer = new MsgPacker_1.default(NETMSGTYPE.CL_KILL, false);
496
- this.SendMsgEx(packer, 1);
497
- };
498
- Client.prototype.ChangeTeam = function (team) {
499
- var packer = new MsgPacker_1.default(NETMSGTYPE.CL_SETTEAM, false);
500
- packer.AddInt(team);
501
- this.SendMsgEx(packer, 1);
502
- };
503
- Client.prototype.Emote = function (emote) {
504
- var packer = new MsgPacker_1.default(NETMSGTYPE.CL_EMOTICON, false);
505
- packer.AddInt(emote);
506
- this.SendMsgEx(packer, 1);
507
- };
508
- return Client;
509
- }(stream_1.EventEmitter));
510
- module.exports = Client;
511
- // module.exports = Client;
package/lib/huffman.js DELETED
@@ -1,190 +0,0 @@
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/snapshot.js DELETED
@@ -1,349 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Snapshot = void 0;
4
- var MsgUnpacker = require('./MsgUnpacker');
5
- var decoder = new TextDecoder('utf-8');
6
- var itemAppendix = [
7
- { "type_id": 0, "size": 0, "name": "obj_ex" },
8
- { "type_id": 1, "size": 10, "name": "obj_player_input" },
9
- { "type_id": 2, "size": 6, "name": "obj_projectile" },
10
- { "type_id": 3, "size": 5, "name": "obj_laser" },
11
- { "type_id": 4, "size": 4, "name": "obj_pickup" },
12
- { "type_id": 5, "size": 3, "name": "obj_flag" },
13
- { "type_id": 6, "size": 8, "name": "obj_game_info" },
14
- { "type_id": 7, "size": 4, "name": "obj_game_data" },
15
- { "type_id": 8, "size": 15, "name": "obj_character_core" },
16
- { "type_id": 9, "size": 22, "name": "obj_character" },
17
- { "type_id": 10, "size": 5, "name": "obj_player_info" },
18
- { "type_id": 11, "size": 17, "name": "obj_client_info" },
19
- { "type_id": 12, "size": 3, "name": "obj_spectator_info" },
20
- { "type_id": 13, "size": 2, "name": "event_common" },
21
- { "type_id": 14, "size": 2, "name": "event_explosion" },
22
- { "type_id": 15, "size": 2, "name": "event_spawn" },
23
- { "type_id": 16, "size": 2, "name": "event_hammerhit" },
24
- { "type_id": 17, "size": 3, "name": "event_death" },
25
- { "type_id": 18, "size": 3, "name": "event_sound_global" },
26
- { "type_id": 19, "size": 3, "name": "event_sound_world" },
27
- { "type_id": 20, "size": 3, "name": "event_damage_indicator" }
28
- ];
29
- var items;
30
- (function (items) {
31
- items[items["OBJ_EX"] = 0] = "OBJ_EX";
32
- items[items["OBJ_PLAYER_INPUT"] = 1] = "OBJ_PLAYER_INPUT";
33
- items[items["OBJ_PROJECTILE"] = 2] = "OBJ_PROJECTILE";
34
- items[items["OBJ_LASER"] = 3] = "OBJ_LASER";
35
- items[items["OBJ_PICKUP"] = 4] = "OBJ_PICKUP";
36
- items[items["OBJ_FLAG"] = 5] = "OBJ_FLAG";
37
- items[items["OBJ_GAME_INFO"] = 6] = "OBJ_GAME_INFO";
38
- items[items["OBJ_GAME_DATA"] = 7] = "OBJ_GAME_DATA";
39
- items[items["OBJ_CHARACTER_CORE"] = 8] = "OBJ_CHARACTER_CORE";
40
- items[items["OBJ_CHARACTER"] = 9] = "OBJ_CHARACTER";
41
- items[items["OBJ_PLAYER_INFO"] = 10] = "OBJ_PLAYER_INFO";
42
- items[items["OBJ_CLIENT_INFO"] = 11] = "OBJ_CLIENT_INFO";
43
- items[items["OBJ_SPECTATOR_INFO"] = 12] = "OBJ_SPECTATOR_INFO";
44
- items[items["EVENT_COMMON"] = 13] = "EVENT_COMMON";
45
- items[items["EVENT_EXPLOSION"] = 14] = "EVENT_EXPLOSION";
46
- items[items["EVENT_SPAWN"] = 15] = "EVENT_SPAWN";
47
- items[items["EVENT_HAMMERHIT"] = 16] = "EVENT_HAMMERHIT";
48
- items[items["EVENT_DEATH"] = 17] = "EVENT_DEATH";
49
- items[items["EVENT_SOUND_GLOBAL"] = 18] = "EVENT_SOUND_GLOBAL";
50
- items[items["EVENT_SOUND_WORLD"] = 19] = "EVENT_SOUND_WORLD";
51
- items[items["EVENT_DAMAGE_INDICATOR"] = 20] = "EVENT_DAMAGE_INDICATOR";
52
- })(items || (items = {}));
53
- var Snapshot = /** @class */ (function () {
54
- function Snapshot() {
55
- }
56
- Snapshot.prototype.IntsToStr = function (pInts) {
57
- var pIntz = [];
58
- var pStr = '';
59
- for (var _i = 0, pInts_1 = pInts; _i < pInts_1.length; _i++) {
60
- var x = pInts_1[_i];
61
- pStr += String.fromCharCode((((x) >> 24) & 0xff) - 128);
62
- pIntz.push((((x) >> 24) & 0xff) - 128);
63
- pStr += String.fromCharCode((((x) >> 16) & 0xff) - 128);
64
- pIntz.push((((x) >> 16) & 0xff) - 128);
65
- pStr += String.fromCharCode((((x) >> 8) & 0xff) - 128);
66
- pIntz.push((((x) >> 8) & 0xff) - 128);
67
- pStr += String.fromCharCode(((x) & 0xff) - 128);
68
- pIntz.push(((x) & 0xff) - 128);
69
- }
70
- pIntz.splice(-1, 1);
71
- pStr = decoder.decode(new Uint8Array(pIntz));
72
- pStr = pStr.replace(/\x00|\u0000/g, ""); //.replace(/タ/g, "")
73
- return pStr;
74
- };
75
- Snapshot.prototype.parseItem = function (data, Type) {
76
- var _item = {};
77
- switch (Type) {
78
- case items.OBJ_EX:
79
- break;
80
- case items.OBJ_PLAYER_INPUT:
81
- _item = {
82
- direction: data[0],
83
- target_x: data[1],
84
- target_y: data[2],
85
- jump: data[3],
86
- fire: data[4],
87
- hook: data[5],
88
- player_flags: data[6],
89
- wanted_weapon: data[7],
90
- next_weapon: data[8],
91
- prev_weapon: data[9],
92
- };
93
- break;
94
- case items.OBJ_PROJECTILE:
95
- _item = {
96
- x: data[0],
97
- y: data[1],
98
- vel_x: data[2],
99
- vel_y: data[3],
100
- type_: data[4],
101
- start_tick: data[5],
102
- };
103
- break;
104
- case items.OBJ_LASER:
105
- _item = {
106
- x: data[0],
107
- y: data[1],
108
- from_x: data[2],
109
- from_y: data[3],
110
- start_tick: data[4],
111
- };
112
- break;
113
- case items.OBJ_PICKUP:
114
- _item = {
115
- x: data[0],
116
- y: data[1],
117
- type_: data[2],
118
- subtype: data[3],
119
- };
120
- break;
121
- case items.OBJ_FLAG:
122
- _item = {
123
- x: data[0],
124
- y: data[1],
125
- team: data[2],
126
- };
127
- break;
128
- case items.OBJ_GAME_INFO:
129
- _item = {
130
- game_flags: data[0],
131
- game_state_flags: data[1],
132
- round_start_tick: data[2],
133
- warmup_timer: data[3],
134
- score_limit: data[4],
135
- time_limit: data[5],
136
- round_num: data[6],
137
- round_current: data[7],
138
- };
139
- break;
140
- case items.OBJ_GAME_DATA:
141
- _item = {
142
- teamscore_red: data[0],
143
- teamscore_blue: data[1],
144
- flag_carrier_red: data[2],
145
- flag_carrier_blue: data[3],
146
- };
147
- break;
148
- case items.OBJ_CHARACTER_CORE:
149
- _item = {
150
- tick: data[0],
151
- x: data[1],
152
- y: data[2],
153
- vel_x: data[3],
154
- vel_y: data[4],
155
- angle: data[5],
156
- direction: data[6],
157
- jumped: data[7],
158
- hooked_player: data[8],
159
- hook_state: data[9],
160
- hook_tick: data[10],
161
- hook_x: data[11],
162
- hook_y: data[12],
163
- hook_dx: data[13],
164
- hook_dy: data[14],
165
- };
166
- break;
167
- case items.OBJ_CHARACTER:
168
- _item = {
169
- character_core: {
170
- tick: data[0],
171
- x: data[1],
172
- y: data[2],
173
- vel_x: data[3],
174
- vel_y: data[4],
175
- angle: data[5],
176
- direction: data[6],
177
- jumped: data[7],
178
- hooked_player: data[8],
179
- hook_state: data[9],
180
- hook_tick: data[10],
181
- hook_x: data[11],
182
- hook_y: data[12],
183
- hook_dx: data[13],
184
- hook_dy: data[14],
185
- },
186
- player_flags: data[15],
187
- health: data[16],
188
- armor: data[17],
189
- ammo_count: data[18],
190
- weapon: data[19],
191
- emote: data[20],
192
- attack_tick: data[21],
193
- };
194
- break;
195
- case items.OBJ_PLAYER_INFO:
196
- _item = {
197
- local: data[0],
198
- client_id: data[1],
199
- team: data[2],
200
- score: data[3],
201
- latency: data[4],
202
- };
203
- break;
204
- case items.OBJ_CLIENT_INFO:
205
- _item = {
206
- name: this.IntsToStr([data[0], data[1], data[2], data[3]]),
207
- clan: this.IntsToStr([data[4], data[5], data[6]]),
208
- country: data[7],
209
- skin: this.IntsToStr([data[8], data[9], data[10], data[11], data[12], data[13]]),
210
- use_custom_color: Number(data.slice(14, 15)),
211
- color_body: Number(data.slice(15, 16)),
212
- color_feet: Number(data.slice(16, 17)),
213
- };
214
- break;
215
- case items.OBJ_SPECTATOR_INFO:
216
- _item = {
217
- spectator_id: data[0],
218
- x: data[1],
219
- y: data[2],
220
- };
221
- break;
222
- case items.EVENT_COMMON:
223
- _item = {
224
- x: data[0],
225
- y: data[1],
226
- };
227
- break;
228
- case items.EVENT_EXPLOSION:
229
- _item = {
230
- common: {
231
- x: data[0],
232
- y: data[1]
233
- }
234
- };
235
- break;
236
- case items.EVENT_SPAWN:
237
- _item = {
238
- common: {
239
- x: data[0],
240
- y: data[1]
241
- }
242
- };
243
- break;
244
- case items.EVENT_HAMMERHIT:
245
- _item = {
246
- common: {
247
- x: data[0],
248
- y: data[1]
249
- }
250
- };
251
- break;
252
- case items.EVENT_DEATH:
253
- _item = {
254
- client_id: data[0],
255
- common: {
256
- x: data[1],
257
- y: data[2]
258
- }
259
- };
260
- break;
261
- case items.EVENT_SOUND_GLOBAL:
262
- _item = {
263
- common: {
264
- x: data[0],
265
- y: data[1]
266
- },
267
- sound_id: data[2]
268
- };
269
- break;
270
- case items.EVENT_SOUND_WORLD:
271
- _item = {
272
- common: {
273
- x: data[0],
274
- y: data[1]
275
- },
276
- sound_id: data[2]
277
- };
278
- break;
279
- case items.EVENT_DAMAGE_INDICATOR:
280
- _item = {
281
- angle: data[0],
282
- common: {
283
- x: data[0],
284
- y: data[1]
285
- },
286
- };
287
- break;
288
- }
289
- return _item;
290
- };
291
- Snapshot.prototype.unpackSnapshot = function (snap, lost) {
292
- if (lost === void 0) { lost = 0; }
293
- // var size = unpackInt(snap).result;
294
- var unpacker = new MsgUnpacker(snap);
295
- // snap = unpackInt(snap).remaining; // size
296
- /* key = (((type_id) << 16) | (id))
297
- * key_to_id = ((key) & 0xffff)
298
- * key_to_type_id = ((key >> 16) & 0xffff)
299
- * https://github.com/heinrich5991/libtw2/blob/master/snapshot/src/
300
- * https://github.com/heinrich5991/libtw2/blob/master/doc/snapshot.md
301
- */
302
- // snap = unpackInt(snap).remaining;
303
- // console.log(unpackInt(snap).result, "tick?") // key?
304
- // snap = unpackInt(snap).remaining;
305
- var num_removed_items = unpacker.unpackInt();
306
- var num_item_deltas = unpacker.unpackInt();
307
- unpacker.unpackInt(); // _zero padding
308
- /*snapshot_delta:
309
- [ 4] num_removed_items
310
- [ 4] num_item_deltas
311
- [ 4] _zero
312
- [*4] removed_item_keys
313
- [ ] item_deltas
314
- */
315
- for (var i = 0; i < num_removed_items; i++) {
316
- unpacker.unpackInt(); // removed_item_keys
317
- }
318
- /*item_delta:
319
- [ 4] type_id
320
- [ 4] id
321
- [ 4] _size
322
- [*4] data_delta*/
323
- var items = { items: [], /* client_infos: client_infos, player_infos: player_infos,*/ lost: 0 };
324
- for (var i = 0; i < num_item_deltas; i++) {
325
- var type_id = unpacker.unpackInt();
326
- var id = unpacker.unpackInt();
327
- var key = (((type_id) << 16) | (id));
328
- var _size = void 0;
329
- if (type_id > 0 && type_id < itemAppendix.length) {
330
- _size = itemAppendix[type_id].size;
331
- }
332
- else
333
- _size = unpacker.unpackInt();
334
- var data = [];
335
- for (var j = 0; j < _size; j++) {
336
- if (unpacker.remaining.length > 0)
337
- data.push(unpacker.unpackInt());
338
- }
339
- // console.log(type_id, id, _size, data);
340
- var parsed = this.parseItem(data, type_id);
341
- // console.log(data)
342
- // console.log('')
343
- items.items.push({ data: data, parsed: parsed, type_id: type_id, id: id, key: key });
344
- }
345
- return items;
346
- };
347
- return Snapshot;
348
- }());
349
- exports.Snapshot = Snapshot;