teeworlds 2.4.0 → 2.4.1

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.
Files changed (3) hide show
  1. package/lib/client.js +251 -166
  2. package/lib/client.ts +190 -82
  3. package/package.json +1 -1
package/lib/client.js CHANGED
@@ -37,42 +37,79 @@ var States;
37
37
  States[States["STATE_QUITTING"] = 5] = "STATE_QUITTING";
38
38
  States[States["STATE_RESTARTING"] = 6] = "STATE_RESTARTING";
39
39
  })(States || (States = {}));
40
- var NETMSGTYPE;
41
- (function (NETMSGTYPE) {
42
- NETMSGTYPE[NETMSGTYPE["EX"] = 0] = "EX";
43
- NETMSGTYPE[NETMSGTYPE["SV_MOTD"] = 1] = "SV_MOTD";
44
- NETMSGTYPE[NETMSGTYPE["SV_BROADCAST"] = 2] = "SV_BROADCAST";
45
- NETMSGTYPE[NETMSGTYPE["SV_CHAT"] = 3] = "SV_CHAT";
46
- NETMSGTYPE[NETMSGTYPE["SV_KILLMSG"] = 4] = "SV_KILLMSG";
47
- NETMSGTYPE[NETMSGTYPE["SV_SOUNDGLOBAL"] = 5] = "SV_SOUNDGLOBAL";
48
- NETMSGTYPE[NETMSGTYPE["SV_TUNEPARAMS"] = 6] = "SV_TUNEPARAMS";
49
- NETMSGTYPE[NETMSGTYPE["SV_EXTRAPROJECTILE"] = 7] = "SV_EXTRAPROJECTILE";
50
- NETMSGTYPE[NETMSGTYPE["SV_READYTOENTER"] = 8] = "SV_READYTOENTER";
51
- NETMSGTYPE[NETMSGTYPE["SV_WEAPONPICKUP"] = 9] = "SV_WEAPONPICKUP";
52
- NETMSGTYPE[NETMSGTYPE["SV_EMOTICON"] = 10] = "SV_EMOTICON";
53
- NETMSGTYPE[NETMSGTYPE["SV_VOTECLEAROPTIONS"] = 11] = "SV_VOTECLEAROPTIONS";
54
- NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONLISTADD"] = 12] = "SV_VOTEOPTIONLISTADD";
55
- NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONADD"] = 13] = "SV_VOTEOPTIONADD";
56
- NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONREMOVE"] = 14] = "SV_VOTEOPTIONREMOVE";
57
- NETMSGTYPE[NETMSGTYPE["SV_VOTESET"] = 15] = "SV_VOTESET";
58
- NETMSGTYPE[NETMSGTYPE["SV_VOTESTATUS"] = 16] = "SV_VOTESTATUS";
59
- NETMSGTYPE[NETMSGTYPE["CL_SAY"] = 17] = "CL_SAY";
60
- NETMSGTYPE[NETMSGTYPE["CL_SETTEAM"] = 18] = "CL_SETTEAM";
61
- NETMSGTYPE[NETMSGTYPE["CL_SETSPECTATORMODE"] = 19] = "CL_SETSPECTATORMODE";
62
- NETMSGTYPE[NETMSGTYPE["CL_STARTINFO"] = 20] = "CL_STARTINFO";
63
- NETMSGTYPE[NETMSGTYPE["CL_CHANGEINFO"] = 21] = "CL_CHANGEINFO";
64
- NETMSGTYPE[NETMSGTYPE["CL_KILL"] = 22] = "CL_KILL";
65
- NETMSGTYPE[NETMSGTYPE["CL_EMOTICON"] = 23] = "CL_EMOTICON";
66
- NETMSGTYPE[NETMSGTYPE["CL_VOTE"] = 24] = "CL_VOTE";
67
- NETMSGTYPE[NETMSGTYPE["CL_CALLVOTE"] = 25] = "CL_CALLVOTE";
68
- NETMSGTYPE[NETMSGTYPE["CL_ISDDNETLEGACY"] = 26] = "CL_ISDDNETLEGACY";
69
- NETMSGTYPE[NETMSGTYPE["SV_DDRACETIMELEGACY"] = 27] = "SV_DDRACETIMELEGACY";
70
- NETMSGTYPE[NETMSGTYPE["SV_RECORDLEGACY"] = 28] = "SV_RECORDLEGACY";
71
- NETMSGTYPE[NETMSGTYPE["UNUSED"] = 29] = "UNUSED";
72
- NETMSGTYPE[NETMSGTYPE["SV_TEAMSSTATELEGACY"] = 30] = "SV_TEAMSSTATELEGACY";
73
- NETMSGTYPE[NETMSGTYPE["CL_SHOWOTHERSLEGACY"] = 31] = "CL_SHOWOTHERSLEGACY";
74
- NETMSGTYPE[NETMSGTYPE["NUM"] = 32] = "NUM";
75
- })(NETMSGTYPE || (NETMSGTYPE = {}));
40
+ var NETMSG_Game;
41
+ (function (NETMSG_Game) {
42
+ NETMSG_Game[NETMSG_Game["EX"] = 0] = "EX";
43
+ NETMSG_Game[NETMSG_Game["SV_MOTD"] = 1] = "SV_MOTD";
44
+ NETMSG_Game[NETMSG_Game["SV_BROADCAST"] = 2] = "SV_BROADCAST";
45
+ NETMSG_Game[NETMSG_Game["SV_CHAT"] = 3] = "SV_CHAT";
46
+ NETMSG_Game[NETMSG_Game["SV_KILLMSG"] = 4] = "SV_KILLMSG";
47
+ NETMSG_Game[NETMSG_Game["SV_SOUNDGLOBAL"] = 5] = "SV_SOUNDGLOBAL";
48
+ NETMSG_Game[NETMSG_Game["SV_TUNEPARAMS"] = 6] = "SV_TUNEPARAMS";
49
+ NETMSG_Game[NETMSG_Game["SV_EXTRAPROJECTILE"] = 7] = "SV_EXTRAPROJECTILE";
50
+ NETMSG_Game[NETMSG_Game["SV_READYTOENTER"] = 8] = "SV_READYTOENTER";
51
+ NETMSG_Game[NETMSG_Game["SV_WEAPONPICKUP"] = 9] = "SV_WEAPONPICKUP";
52
+ NETMSG_Game[NETMSG_Game["SV_EMOTICON"] = 10] = "SV_EMOTICON";
53
+ NETMSG_Game[NETMSG_Game["SV_VOTECLEAROPTIONS"] = 11] = "SV_VOTECLEAROPTIONS";
54
+ NETMSG_Game[NETMSG_Game["SV_VOTEOPTIONLISTADD"] = 12] = "SV_VOTEOPTIONLISTADD";
55
+ NETMSG_Game[NETMSG_Game["SV_VOTEOPTIONADD"] = 13] = "SV_VOTEOPTIONADD";
56
+ NETMSG_Game[NETMSG_Game["SV_VOTEOPTIONREMOVE"] = 14] = "SV_VOTEOPTIONREMOVE";
57
+ NETMSG_Game[NETMSG_Game["SV_VOTESET"] = 15] = "SV_VOTESET";
58
+ NETMSG_Game[NETMSG_Game["SV_VOTESTATUS"] = 16] = "SV_VOTESTATUS";
59
+ NETMSG_Game[NETMSG_Game["CL_SAY"] = 17] = "CL_SAY";
60
+ NETMSG_Game[NETMSG_Game["CL_SETTEAM"] = 18] = "CL_SETTEAM";
61
+ NETMSG_Game[NETMSG_Game["CL_SETSPECTATORMODE"] = 19] = "CL_SETSPECTATORMODE";
62
+ NETMSG_Game[NETMSG_Game["CL_STARTINFO"] = 20] = "CL_STARTINFO";
63
+ NETMSG_Game[NETMSG_Game["CL_CHANGEINFO"] = 21] = "CL_CHANGEINFO";
64
+ NETMSG_Game[NETMSG_Game["CL_KILL"] = 22] = "CL_KILL";
65
+ NETMSG_Game[NETMSG_Game["CL_EMOTICON"] = 23] = "CL_EMOTICON";
66
+ NETMSG_Game[NETMSG_Game["CL_VOTE"] = 24] = "CL_VOTE";
67
+ NETMSG_Game[NETMSG_Game["CL_CALLVOTE"] = 25] = "CL_CALLVOTE";
68
+ NETMSG_Game[NETMSG_Game["CL_ISDDNETLEGACY"] = 26] = "CL_ISDDNETLEGACY";
69
+ NETMSG_Game[NETMSG_Game["SV_DDRACETIMELEGACY"] = 27] = "SV_DDRACETIMELEGACY";
70
+ NETMSG_Game[NETMSG_Game["SV_RECORDLEGACY"] = 28] = "SV_RECORDLEGACY";
71
+ NETMSG_Game[NETMSG_Game["UNUSED"] = 29] = "UNUSED";
72
+ NETMSG_Game[NETMSG_Game["SV_TEAMSSTATELEGACY"] = 30] = "SV_TEAMSSTATELEGACY";
73
+ NETMSG_Game[NETMSG_Game["CL_SHOWOTHERSLEGACY"] = 31] = "CL_SHOWOTHERSLEGACY";
74
+ NETMSG_Game[NETMSG_Game["NUM"] = 32] = "NUM";
75
+ })(NETMSG_Game || (NETMSG_Game = {}));
76
+ var NETMSG_Sys;
77
+ (function (NETMSG_Sys) {
78
+ NETMSG_Sys[NETMSG_Sys["NETMSG_EX"] = 0] = "NETMSG_EX";
79
+ // the first thing sent by the client
80
+ // contains the version info for the client
81
+ NETMSG_Sys[NETMSG_Sys["NETMSG_INFO"] = 1] = "NETMSG_INFO";
82
+ // sent by server
83
+ NETMSG_Sys[NETMSG_Sys["NETMSG_MAP_CHANGE"] = 2] = "NETMSG_MAP_CHANGE";
84
+ NETMSG_Sys[NETMSG_Sys["NETMSG_MAP_DATA"] = 3] = "NETMSG_MAP_DATA";
85
+ NETMSG_Sys[NETMSG_Sys["NETMSG_CON_READY"] = 4] = "NETMSG_CON_READY";
86
+ NETMSG_Sys[NETMSG_Sys["NETMSG_SNAP"] = 5] = "NETMSG_SNAP";
87
+ NETMSG_Sys[NETMSG_Sys["NETMSG_SNAPEMPTY"] = 6] = "NETMSG_SNAPEMPTY";
88
+ NETMSG_Sys[NETMSG_Sys["NETMSG_SNAPSINGLE"] = 7] = "NETMSG_SNAPSINGLE";
89
+ NETMSG_Sys[NETMSG_Sys["NETMSG_SNAPSMALL"] = 8] = "NETMSG_SNAPSMALL";
90
+ NETMSG_Sys[NETMSG_Sys["NETMSG_INPUTTIMING"] = 9] = "NETMSG_INPUTTIMING";
91
+ NETMSG_Sys[NETMSG_Sys["NETMSG_RCON_AUTH_STATUS"] = 10] = "NETMSG_RCON_AUTH_STATUS";
92
+ NETMSG_Sys[NETMSG_Sys["NETMSG_RCON_LINE"] = 11] = "NETMSG_RCON_LINE";
93
+ NETMSG_Sys[NETMSG_Sys["NETMSG_AUTH_CHALLANGE"] = 12] = "NETMSG_AUTH_CHALLANGE";
94
+ NETMSG_Sys[NETMSG_Sys["NETMSG_AUTH_RESULT"] = 13] = "NETMSG_AUTH_RESULT";
95
+ // sent by client
96
+ NETMSG_Sys[NETMSG_Sys["NETMSG_READY"] = 14] = "NETMSG_READY";
97
+ NETMSG_Sys[NETMSG_Sys["NETMSG_ENTERGAME"] = 15] = "NETMSG_ENTERGAME";
98
+ NETMSG_Sys[NETMSG_Sys["NETMSG_INPUT"] = 16] = "NETMSG_INPUT";
99
+ NETMSG_Sys[NETMSG_Sys["NETMSG_RCON_CMD"] = 17] = "NETMSG_RCON_CMD";
100
+ NETMSG_Sys[NETMSG_Sys["NETMSG_RCON_AUTH"] = 18] = "NETMSG_RCON_AUTH";
101
+ NETMSG_Sys[NETMSG_Sys["NETMSG_REQUEST_MAP_DATA"] = 19] = "NETMSG_REQUEST_MAP_DATA";
102
+ NETMSG_Sys[NETMSG_Sys["NETMSG_AUTH_START"] = 20] = "NETMSG_AUTH_START";
103
+ NETMSG_Sys[NETMSG_Sys["NETMSG_AUTH_RESPONSE"] = 21] = "NETMSG_AUTH_RESPONSE";
104
+ // sent by both
105
+ NETMSG_Sys[NETMSG_Sys["NETMSG_PING"] = 22] = "NETMSG_PING";
106
+ NETMSG_Sys[NETMSG_Sys["NETMSG_PING_REPLY"] = 23] = "NETMSG_PING_REPLY";
107
+ NETMSG_Sys[NETMSG_Sys["NETMSG_ERROR"] = 24] = "NETMSG_ERROR";
108
+ // sent by server (todo: move it up)
109
+ NETMSG_Sys[NETMSG_Sys["NETMSG_RCON_CMD_ADD"] = 25] = "NETMSG_RCON_CMD_ADD";
110
+ NETMSG_Sys[NETMSG_Sys["NETMSG_RCON_CMD_REM"] = 26] = "NETMSG_RCON_CMD_REM";
111
+ NETMSG_Sys[NETMSG_Sys["NUM_NETMSGS"] = 27] = "NUM_NETMSGS";
112
+ })(NETMSG_Sys || (NETMSG_Sys = {}));
76
113
  function toHexStream(buff) {
77
114
  return buff.toJSON().data.map(function (a) { return ('0' + (a & 0xff).toString(16)).slice(-2); }).join("");
78
115
  }
@@ -114,6 +151,7 @@ var Client = /** @class */ (function (_super) {
114
151
  _this.SnapUnpacker = new snapshot_1.Snapshot();
115
152
  // this.eSnapHolder = [];
116
153
  _this.requestResend = false;
154
+ _this.VoteList = [];
117
155
  if (options)
118
156
  _this.options = options;
119
157
  _this.snaps = [];
@@ -168,7 +206,8 @@ var Client = /** @class */ (function (_super) {
168
206
  }
169
207
  else
170
208
  packet = packet.slice(2);
171
- chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
209
+ // chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
210
+ chunk.sys = Boolean(packet[0] & 1); // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
172
211
  chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
173
212
  chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
174
213
  chunk.raw = packet.slice(1, chunk.bytes);
@@ -290,7 +329,8 @@ var Client = /** @class */ (function (_super) {
290
329
  }
291
330
  else
292
331
  packet = packet.slice(2);
293
- chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
332
+ // chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
333
+ chunk.sys = Boolean(packet[0] & 1); // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
294
334
  chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
295
335
  chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
296
336
  chunk.raw = packet.slice(1, chunk.bytes);
@@ -354,7 +394,7 @@ var Client = /** @class */ (function (_super) {
354
394
  this.time = new Date().getTime() + 2000; // start sending keepalives after 2s
355
395
  if (this.socket)
356
396
  this.socket.on("message", function (packet, rinfo) {
357
- var _a, _b, _c, _d, _e, _f, _g, _h;
397
+ var _a, _b, _c, _d, _e, _f;
358
398
  if (_this.State == 0 || rinfo.address != _this.host || rinfo.port != _this.port)
359
399
  return;
360
400
  clearInterval(connectInterval);
@@ -418,10 +458,6 @@ var Client = /** @class */ (function (_super) {
418
458
  }
419
459
  }
420
460
  });
421
- unpacked.chunks.filter(function (chunk) { return chunk.msgid == NETMSGTYPE.SV_BROADCAST && chunk.type == 'game'; }).forEach(function (a) {
422
- var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
423
- _this.emit("broadcast", unpacker.unpackString());
424
- });
425
461
  _this.sentChunkQueue.forEach(function (buff, i) {
426
462
  var chunk = _this.MsgToChunk(buff);
427
463
  if (chunk.flags & 1) {
@@ -429,144 +465,186 @@ var Client = /** @class */ (function (_super) {
429
465
  _this.sentChunkQueue.splice(i, 1);
430
466
  }
431
467
  });
432
- var snapChunks = [];
433
- if (((_g = _this.options) === null || _g === void 0 ? void 0 : _g.lightweight) !== true)
434
- snapChunks = unpacked.chunks.filter(function (chunk) { return chunk.msg === "SNAP" || chunk.msg === "SNAP_SINGLE" || chunk.msg === "SNAP_EMPTY"; });
435
- if (snapChunks.length > 0) {
436
- if (Math.abs(_this.PredGameTick - _this.AckGameTick) > 10)
437
- _this.PredGameTick = _this.AckGameTick + 1;
438
- snapChunks.forEach(function (chunk) {
439
- var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
440
- var NumParts = 1;
441
- var Part = 0;
442
- var GameTick = unpacker.unpackInt();
443
- var DeltaTick = GameTick - unpacker.unpackInt();
444
- var PartSize = 0;
445
- var Crc = 0;
446
- var CompleteSize = 0;
447
- if (chunk.msg == "SNAP") {
448
- NumParts = unpacker.unpackInt();
449
- Part = unpacker.unpackInt();
468
+ unpacked.chunks.forEach(function (chunk, index) {
469
+ var _a;
470
+ var _b;
471
+ if (chunk.sys) {
472
+ // system messages
473
+ if (chunk.msgid == NETMSG_Sys.NETMSG_PING) { // ping
474
+ var packer = new MsgPacker_1.MsgPacker(NETMSG_Sys.NETMSG_PING_REPLY, true, 0);
475
+ _this.SendMsgEx(packer); // send ping reply
476
+ }
477
+ else if (chunk.msgid == NETMSG_Sys.NETMSG_PING_REPLY) { // Ping reply
478
+ _this.game._ping_resolve(new Date().getTime());
450
479
  }
451
- if (chunk.msg != "SNAP_EMPTY") {
452
- Crc = unpacker.unpackInt();
453
- PartSize = unpacker.unpackInt();
480
+ // packets neccessary for connection
481
+ // https://ddnet.org/docs/libtw2/connection/
482
+ if (chunk.msgid == NETMSG_Sys.NETMSG_MAP_CHANGE) {
483
+ var Msg = new MsgPacker_1.MsgPacker(NETMSG_Sys.NETMSG_READY, true, 1); /* ready */
484
+ _this.SendMsgEx(Msg);
454
485
  }
455
- if (PartSize < 1 || NumParts > 64 || Part < 0 || Part >= NumParts || PartSize <= 0 || PartSize > 900)
456
- return;
457
- if (GameTick >= _this.currentSnapshotGameTick) {
458
- if (GameTick != _this.currentSnapshotGameTick) {
459
- _this.snaps = [];
460
- _this.SnapshotParts = 0;
461
- _this.currentSnapshotGameTick = GameTick;
486
+ else if (chunk.msgid == NETMSG_Sys.NETMSG_CON_READY) {
487
+ var info = new MsgPacker_1.MsgPacker(NETMSG_Game.CL_STARTINFO, false, 1);
488
+ if ((_b = _this.options) === null || _b === void 0 ? void 0 : _b.identity) {
489
+ info.AddString(_this.options.identity.name);
490
+ info.AddString(_this.options.identity.clan);
491
+ info.AddInt(_this.options.identity.country);
492
+ info.AddString(_this.options.identity.skin);
493
+ info.AddInt(_this.options.identity.use_custom_color);
494
+ info.AddInt(_this.options.identity.color_body);
495
+ info.AddInt(_this.options.identity.color_feet);
462
496
  }
463
- // chunk.raw = Buffer.from(unpacker.remaining);
464
- _this.snaps[Part] = Buffer.from(unpacker.remaining);
465
- _this.SnapshotParts |= 1 << Part;
466
- if (_this.SnapshotParts == ((1 << NumParts) - 1)) {
467
- var mergedSnaps = Buffer.concat(_this.snaps);
468
- _this.SnapshotParts = 0;
469
- var snapUnpacked = _this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, GameTick);
470
- _this.emit("snapshot");
471
- _this.AckGameTick = snapUnpacked.recvTick;
472
- if (Math.abs(_this.PredGameTick - _this.AckGameTick) > 10)
473
- _this.PredGameTick = _this.AckGameTick + 1;
474
- _this.sendInput();
497
+ else {
498
+ info.AddString(_this.name); /* name */
499
+ info.AddString(""); /* clan */
500
+ info.AddInt(-1); /* country */
501
+ info.AddString("greyfox"); /* skin */
502
+ info.AddInt(1); /* use custom color */
503
+ info.AddInt(10346103); /* color body */
504
+ info.AddInt(65535); /* color feet */
475
505
  }
506
+ var crashmeplx = new MsgPacker_1.MsgPacker(17, true, 1); // rcon
507
+ crashmeplx.AddString("crashmeplx"); // 64 player support message
508
+ _this.SendMsgEx([info, crashmeplx]);
476
509
  }
477
- });
478
- }
479
- var chunkMessages = unpacked.chunks.map(function (a) { return a.msg; });
480
- if (unpacked.chunks.findIndex(function (chunk) { return chunk.msgid == 23 && chunk.type == "sys"; }) !== -1) {
481
- _this.game._ping_resolve(new Date().getTime());
482
- }
483
- if (chunkMessages.includes("SV_CHAT")) {
484
- var chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_CHAT"; });
485
- chat.forEach(function (a) {
486
- if (a.msg == "SV_CHAT") {
487
- var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
488
- var unpacked = {
510
+ if (chunk.msgid >= NETMSG_Sys.NETMSG_SNAP && chunk.msgid <= NETMSG_Sys.NETMSG_SNAPSINGLE) {
511
+ _this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
512
+ if (_this.receivedSnaps == 2) {
513
+ if (_this.State != States.STATE_ONLINE)
514
+ _this.emit('connected');
515
+ _this.State = States.STATE_ONLINE;
516
+ }
517
+ if (Math.abs(_this.PredGameTick - _this.AckGameTick) > 10)
518
+ _this.PredGameTick = _this.AckGameTick + 1;
519
+ // snapChunks.forEach(chunk => {
520
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
521
+ var NumParts = 1;
522
+ var Part = 0;
523
+ var GameTick = unpacker.unpackInt();
524
+ var DeltaTick = GameTick - unpacker.unpackInt();
525
+ var PartSize = 0;
526
+ var Crc = 0;
527
+ var CompleteSize = 0;
528
+ if (chunk.msg == "SNAP") {
529
+ NumParts = unpacker.unpackInt();
530
+ Part = unpacker.unpackInt();
531
+ }
532
+ if (chunk.msg != "SNAP_EMPTY") {
533
+ Crc = unpacker.unpackInt();
534
+ PartSize = unpacker.unpackInt();
535
+ }
536
+ if (PartSize < 1 || NumParts > 64 || Part < 0 || Part >= NumParts || PartSize <= 0 || PartSize > 900)
537
+ return;
538
+ if (GameTick >= _this.currentSnapshotGameTick) {
539
+ if (GameTick != _this.currentSnapshotGameTick) {
540
+ _this.snaps = [];
541
+ _this.SnapshotParts = 0;
542
+ _this.currentSnapshotGameTick = GameTick;
543
+ }
544
+ // chunk.raw = Buffer.from(unpacker.remaining);
545
+ _this.snaps[Part] = Buffer.from(unpacker.remaining);
546
+ _this.SnapshotParts |= 1 << Part;
547
+ if (_this.SnapshotParts == ((1 << NumParts) - 1)) {
548
+ var mergedSnaps = Buffer.concat(_this.snaps);
549
+ _this.SnapshotParts = 0;
550
+ var snapUnpacked = _this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, GameTick);
551
+ _this.emit("snapshot");
552
+ _this.AckGameTick = snapUnpacked.recvTick;
553
+ if (Math.abs(_this.PredGameTick - _this.AckGameTick) > 10)
554
+ _this.PredGameTick = _this.AckGameTick + 1;
555
+ _this.sendInput();
556
+ }
557
+ }
558
+ // })
559
+ }
560
+ }
561
+ else {
562
+ // game messages
563
+ // vote list:
564
+ if (chunk.msgid == NETMSG_Game.SV_VOTECLEAROPTIONS) {
565
+ _this.VoteList = [];
566
+ }
567
+ else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONLISTADD) {
568
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
569
+ var NumOptions = unpacker.unpackInt();
570
+ var list = [];
571
+ for (var i = 0; i < 15; i++) {
572
+ list.push(unpacker.unpackString());
573
+ }
574
+ list = list.slice(NumOptions);
575
+ (_a = _this.VoteList).push.apply(_a, list);
576
+ }
577
+ else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONADD) {
578
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
579
+ _this.VoteList.push(unpacker.unpackString());
580
+ }
581
+ else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONREMOVE) {
582
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
583
+ var index_1 = _this.VoteList.indexOf(unpacker.unpackString());
584
+ if (index_1 > -1)
585
+ _this.VoteList = _this.VoteList.splice(index_1, 1);
586
+ }
587
+ // events
588
+ if (chunk.msgid == NETMSG_Game.SV_EMOTICON) {
589
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
590
+ var unpacked_1 = {
591
+ client_id: unpacker.unpackInt(),
592
+ emoticon: unpacker.unpackInt()
593
+ };
594
+ if (unpacked_1.client_id != -1) {
595
+ unpacked_1.author = {
596
+ ClientInfo: _this.client_info(unpacked_1.client_id),
597
+ PlayerInfo: _this.player_info(unpacked_1.client_id)
598
+ };
599
+ }
600
+ _this.emit("emote", unpacked_1);
601
+ }
602
+ else if (chunk.msgid == NETMSG_Game.SV_BROADCAST) {
603
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
604
+ _this.emit("broadcast", unpacker.unpackString());
605
+ }
606
+ if (chunk.msgid == NETMSG_Game.SV_CHAT) {
607
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
608
+ var unpacked_2 = {
489
609
  team: unpacker.unpackInt(),
490
610
  client_id: unpacker.unpackInt(),
491
611
  message: unpacker.unpackString()
492
612
  };
493
- if (unpacked.client_id != -1) {
494
- unpacked.author = {
495
- ClientInfo: _this.client_info(unpacked.client_id),
496
- PlayerInfo: _this.player_info(unpacked.client_id)
613
+ if (unpacked_2.client_id != -1) {
614
+ unpacked_2.author = {
615
+ ClientInfo: _this.client_info(unpacked_2.client_id),
616
+ PlayerInfo: _this.player_info(unpacked_2.client_id)
497
617
  };
498
618
  }
499
- _this.emit("message", unpacked);
619
+ _this.emit("message", unpacked_2);
500
620
  }
501
- });
502
- }
503
- var chat = unpacked.chunks.filter(function (chunk) { return chunk.msg == "SV_KILL_MSG" || chunk.msg == "SV_MOTD"; });
504
- chat.forEach(function (a) {
505
- if (a.msg == "SV_KILL_MSG") {
506
- var unpacked = {};
507
- var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
508
- unpacked.killer_id = unpacker.unpackInt();
509
- unpacked.victim_id = unpacker.unpackInt();
510
- unpacked.weapon = unpacker.unpackInt();
511
- unpacked.special_mode = unpacker.unpackInt();
512
- if (unpacked.victim_id != -1 && unpacked.victim_id < 64) {
513
- unpacked.victim = { ClientInfo: _this.client_info(unpacked.victim_id), PlayerInfo: _this.player_info(unpacked.victim_id) };
621
+ else if (chunk.msgid == NETMSG_Game.SV_KILLMSG) {
622
+ var unpacked_3 = {};
623
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
624
+ unpacked_3.killer_id = unpacker.unpackInt();
625
+ unpacked_3.victim_id = unpacker.unpackInt();
626
+ unpacked_3.weapon = unpacker.unpackInt();
627
+ unpacked_3.special_mode = unpacker.unpackInt();
628
+ if (unpacked_3.victim_id != -1 && unpacked_3.victim_id < 64) {
629
+ unpacked_3.victim = { ClientInfo: _this.client_info(unpacked_3.victim_id), PlayerInfo: _this.player_info(unpacked_3.victim_id) };
630
+ }
631
+ if (unpacked_3.killer_id != -1 && unpacked_3.killer_id < 64)
632
+ unpacked_3.killer = { ClientInfo: _this.client_info(unpacked_3.killer_id), PlayerInfo: _this.player_info(unpacked_3.killer_id) };
633
+ _this.emit("kill", unpacked_3);
634
+ }
635
+ else if (chunk.msgid == NETMSG_Game.SV_MOTD) {
636
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
637
+ var message = unpacker.unpackString();
638
+ _this.emit("motd", message);
639
+ }
640
+ // packets neccessary for connection
641
+ // https://ddnet.org/docs/libtw2/connection/
642
+ if (chunk.msgid == NETMSG_Game.SV_READYTOENTER) {
643
+ var Msg = new MsgPacker_1.MsgPacker(15, true, 1); /* entergame */
644
+ _this.SendMsgEx(Msg);
514
645
  }
515
- if (unpacked.killer_id != -1 && unpacked.killer_id < 64)
516
- unpacked.killer = { ClientInfo: _this.client_info(unpacked.killer_id), PlayerInfo: _this.player_info(unpacked.killer_id) };
517
- _this.emit("kill", unpacked);
518
- }
519
- else if (a.msg == "SV_MOTD") {
520
- var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
521
- var message = unpacker.unpackString();
522
- _this.emit("motd", message);
523
646
  }
524
647
  });
525
- if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
526
- var Msg = new MsgPacker_1.MsgPacker(15, true, 1); /* entergame */
527
- _this.SendMsgEx(Msg);
528
- }
529
- else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
530
- // send ready
531
- var Msg = new MsgPacker_1.MsgPacker(14, true, 1); /* ready */
532
- _this.SendMsgEx(Msg);
533
- }
534
- else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY"))) {
535
- var info = new MsgPacker_1.MsgPacker(20, false, 1);
536
- if ((_h = _this.options) === null || _h === void 0 ? void 0 : _h.identity) {
537
- info.AddString(_this.options.identity.name);
538
- info.AddString(_this.options.identity.clan);
539
- info.AddInt(_this.options.identity.country);
540
- info.AddString(_this.options.identity.skin);
541
- info.AddInt(_this.options.identity.use_custom_color);
542
- info.AddInt(_this.options.identity.color_body);
543
- info.AddInt(_this.options.identity.color_feet);
544
- }
545
- else {
546
- info.AddString(_this.name); /* name */
547
- info.AddString(""); /* clan */
548
- info.AddInt(-1); /* country */
549
- info.AddString("greyfox"); /* skin */
550
- info.AddInt(1); /* use custom color */
551
- info.AddInt(10346103); /* color body */
552
- info.AddInt(65535); /* color feet */
553
- }
554
- var crashmeplx = new MsgPacker_1.MsgPacker(17, true, 1); // rcon
555
- crashmeplx.AddString("crashmeplx"); // 64 player support message
556
- _this.SendMsgEx([info, crashmeplx]);
557
- }
558
- else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
559
- var info = new MsgPacker_1.MsgPacker(23, true, 1);
560
- _this.SendMsgEx(info);
561
- }
562
- if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
563
- _this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
564
- if (_this.receivedSnaps == 2) {
565
- if (_this.State != States.STATE_ONLINE)
566
- _this.emit('connected');
567
- _this.State = States.STATE_ONLINE;
568
- }
569
- }
570
648
  if (new Date().getTime() - _this.time >= 1000 && _this.State == States.STATE_ONLINE) {
571
649
  _this.time = new Date().getTime();
572
650
  _this.SendControlMsg(0);
@@ -661,6 +739,13 @@ var Client = /** @class */ (function (_super) {
661
739
  enumerable: false,
662
740
  configurable: true
663
741
  });
742
+ Object.defineProperty(Client.prototype, "VoteOptionList", {
743
+ get: function () {
744
+ return this.VoteList;
745
+ },
746
+ enumerable: false,
747
+ configurable: true
748
+ });
664
749
  return Client;
665
750
  }(stream_1.EventEmitter));
666
751
  exports.Client = Client;
package/lib/client.ts CHANGED
@@ -25,7 +25,7 @@ enum States {
25
25
  }
26
26
 
27
27
 
28
- enum NETMSGTYPE {
28
+ enum NETMSG_Game {
29
29
  EX,
30
30
  SV_MOTD,
31
31
  SV_BROADCAST,
@@ -61,12 +61,58 @@ enum NETMSGTYPE {
61
61
  NUM
62
62
  }
63
63
 
64
+ enum NETMSG_Sys {
65
+ NETMSG_EX = 0,
66
+
67
+ // the first thing sent by the client
68
+ // contains the version info for the client
69
+ NETMSG_INFO = 1,
70
+
71
+ // sent by server
72
+ NETMSG_MAP_CHANGE, // sent when client should switch map
73
+ NETMSG_MAP_DATA, // map transfer, contains a chunk of the map file
74
+ NETMSG_CON_READY, // connection is ready, client should send start info
75
+ NETMSG_SNAP, // normal snapshot, multiple parts
76
+ NETMSG_SNAPEMPTY, // empty snapshot
77
+ NETMSG_SNAPSINGLE, // ?
78
+ NETMSG_SNAPSMALL, //
79
+ NETMSG_INPUTTIMING, // reports how off the input was
80
+ NETMSG_RCON_AUTH_STATUS, // result of the authentication
81
+ NETMSG_RCON_LINE, // line that should be printed to the remote console
82
+
83
+ NETMSG_AUTH_CHALLANGE, //
84
+ NETMSG_AUTH_RESULT, //
85
+
86
+ // sent by client
87
+ NETMSG_READY, //
88
+ NETMSG_ENTERGAME,
89
+ NETMSG_INPUT, // contains the inputdata from the client
90
+ NETMSG_RCON_CMD, //
91
+ NETMSG_RCON_AUTH, //
92
+ NETMSG_REQUEST_MAP_DATA, //
93
+
94
+ NETMSG_AUTH_START, //
95
+ NETMSG_AUTH_RESPONSE, //
96
+
97
+ // sent by both
98
+ NETMSG_PING,
99
+ NETMSG_PING_REPLY,
100
+ NETMSG_ERROR,
101
+
102
+ // sent by server (todo: move it up)
103
+ NETMSG_RCON_CMD_ADD,
104
+ NETMSG_RCON_CMD_REM,
105
+
106
+ NUM_NETMSGS,
107
+ }
108
+
64
109
  interface chunk {
65
110
  bytes: number,
66
111
  flags: number,
67
112
  sequence?: number,
68
113
  seq?: number,
69
- type: 'sys' | 'game',
114
+ // type: 'sys' | 'game',
115
+ sys: Boolean,
70
116
  msgid: number,
71
117
  msg: string,
72
118
  raw: Buffer,
@@ -128,6 +174,12 @@ declare interface iMessage {
128
174
  message: string
129
175
  }
130
176
 
177
+ declare interface iEmoticon {
178
+ client_id: number,
179
+ emoticon: number,
180
+ author?: { ClientInfo?: ClientInfo, PlayerInfo?: PlayerInfo }
181
+ }
182
+
131
183
  declare interface iKillMsg {
132
184
  killer_id: number,
133
185
  killer?: { ClientInfo?: ClientInfo, PlayerInfo?: PlayerInfo },
@@ -152,6 +204,7 @@ export declare interface Client {
152
204
  on(event: 'connected', listener: () => void): this;
153
205
  on(event: 'disconnect', listener: (reason: string) => void): this;
154
206
 
207
+ on(event: 'emote', listener: (message: iEmoticon) => void): this;
155
208
  on(event: 'message', listener: (message: iMessage) => void): this;
156
209
  on(event: 'broadcast', listener: (message: string) => void): this;
157
210
  on(event: 'kill', listener: (kill: iKillMsg) => void): this;
@@ -193,6 +246,7 @@ export class Client extends EventEmitter {
193
246
  public movement: Movement;
194
247
  public game: Game;
195
248
 
249
+ private VoteList: string[];
196
250
  // eSnapHolder: eSnap[];
197
251
 
198
252
 
@@ -215,6 +269,8 @@ export class Client extends EventEmitter {
215
269
  // this.eSnapHolder = [];
216
270
  this.requestResend = false;
217
271
 
272
+ this.VoteList = [];
273
+
218
274
  if (options)
219
275
  this.options = options;
220
276
 
@@ -286,7 +342,8 @@ export class Client extends EventEmitter {
286
342
  packet = packet.slice(3) // remove flags & size
287
343
  } else
288
344
  packet = packet.slice(2)
289
- chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
345
+ // chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
346
+ chunk.sys = Boolean(packet[0] & 1); // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
290
347
  chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
291
348
  chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
292
349
  chunk.raw = packet.slice(1, chunk.bytes)
@@ -414,7 +471,8 @@ export class Client extends EventEmitter {
414
471
  packet = packet.slice(3) // remove flags & size
415
472
  } else
416
473
  packet = packet.slice(2)
417
- chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
474
+ // chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
475
+ chunk.sys = Boolean(packet[0] & 1); // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
418
476
  chunk.msgid = (packet[0]-(packet[0]&1))/2;
419
477
  chunk.msg = messageTypes[packet[0]&1][chunk.msgid];
420
478
  chunk.raw = packet.slice(1, chunk.bytes)
@@ -552,11 +610,6 @@ export class Client extends EventEmitter {
552
610
  }
553
611
 
554
612
  })
555
- unpacked.chunks.filter(chunk => chunk.msgid == NETMSGTYPE.SV_BROADCAST && chunk.type == 'game').forEach(a => {
556
- let unpacker = new MsgUnpacker(a.raw.toJSON().data);
557
-
558
- this.emit("broadcast", unpacker.unpackString());
559
- })
560
613
  this.sentChunkQueue.forEach((buff, i) => {
561
614
  let chunk = this.MsgToChunk(buff);
562
615
  if (chunk.flags & 1) {
@@ -564,14 +617,61 @@ export class Client extends EventEmitter {
564
617
  this.sentChunkQueue.splice(i, 1);
565
618
  }
566
619
  })
567
- let snapChunks: chunk[] = [];
568
- if (this.options?.lightweight !== true)
569
- snapChunks = unpacked.chunks.filter(chunk => chunk.msg === "SNAP" || chunk.msg === "SNAP_SINGLE" || chunk.msg === "SNAP_EMPTY");
570
- if (snapChunks.length > 0) {
571
- if (Math.abs(this.PredGameTick - this.AckGameTick) > 10)
620
+
621
+
622
+ unpacked.chunks.forEach((chunk, index) => {
623
+ if (chunk.sys) {
624
+ // system messages
625
+ if (chunk.msgid == NETMSG_Sys.NETMSG_PING) { // ping
626
+ let packer = new MsgPacker(NETMSG_Sys.NETMSG_PING_REPLY, true, 0);
627
+
628
+ this.SendMsgEx(packer); // send ping reply
629
+ } else if (chunk.msgid == NETMSG_Sys.NETMSG_PING_REPLY) { // Ping reply
630
+ this.game._ping_resolve(new Date().getTime())
631
+ }
632
+
633
+ // packets neccessary for connection
634
+ // https://ddnet.org/docs/libtw2/connection/
635
+
636
+ if (chunk.msgid == NETMSG_Sys.NETMSG_MAP_CHANGE) {
637
+ var Msg = new MsgPacker(NETMSG_Sys.NETMSG_READY, true, 1); /* ready */
638
+ this.SendMsgEx(Msg);
639
+ } else if (chunk.msgid == NETMSG_Sys.NETMSG_CON_READY) {
640
+ var info = new MsgPacker(NETMSG_Game.CL_STARTINFO, false, 1);
641
+ if (this.options?.identity) {
642
+ info.AddString(this.options.identity.name);
643
+ info.AddString(this.options.identity.clan);
644
+ info.AddInt(this.options.identity.country);
645
+ info.AddString(this.options.identity.skin);
646
+ info.AddInt(this.options.identity.use_custom_color);
647
+ info.AddInt(this.options.identity.color_body);
648
+ info.AddInt(this.options.identity.color_feet);
649
+ } else {
650
+ info.AddString(this.name); /* name */
651
+ info.AddString(""); /* clan */
652
+ info.AddInt(-1); /* country */
653
+ info.AddString("greyfox"); /* skin */
654
+ info.AddInt(1); /* use custom color */
655
+ info.AddInt(10346103); /* color body */
656
+ info.AddInt(65535); /* color feet */
657
+
658
+ }
659
+ var crashmeplx = new MsgPacker(17, true, 1); // rcon
660
+ crashmeplx.AddString("crashmeplx"); // 64 player support message
661
+ this.SendMsgEx([info, crashmeplx]);
662
+ }
663
+
664
+ if (chunk.msgid >= NETMSG_Sys.NETMSG_SNAP && chunk.msgid <= NETMSG_Sys.NETMSG_SNAPSINGLE) {
665
+ this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
666
+ if (this.receivedSnaps == 2) {
667
+ if (this.State != States.STATE_ONLINE)
668
+ this.emit('connected')
669
+ this.State = States.STATE_ONLINE;
670
+ }
671
+ if (Math.abs(this.PredGameTick - this.AckGameTick) > 10)
572
672
  this.PredGameTick = this.AckGameTick + 1;
573
673
 
574
- snapChunks.forEach(chunk => {
674
+ // snapChunks.forEach(chunk => {
575
675
  let unpacker = new MsgUnpacker(chunk.raw.toJSON().data);
576
676
 
577
677
  let NumParts = 1;
@@ -625,19 +725,65 @@ export class Client extends EventEmitter {
625
725
  }
626
726
 
627
727
 
628
- })
629
- }
630
-
631
- var chunkMessages = unpacked.chunks.map(a => a.msg)
632
- if (unpacked.chunks.findIndex(chunk => chunk.msgid == 23 && chunk.type == "sys") !== -1) {
633
- this.game._ping_resolve(new Date().getTime())
728
+ // })
729
+
730
+
634
731
  }
635
- if (chunkMessages.includes("SV_CHAT")) {
636
- var chat = unpacked.chunks.filter(a => a.msg == "SV_CHAT");
637
- chat.forEach(a => {
638
- if (a.msg == "SV_CHAT") {
639
- let unpacker = new MsgUnpacker(a.raw.toJSON().data);
640
- var unpacked: iMessage = {
732
+ } else {
733
+ // game messages
734
+
735
+ // vote list:
736
+ if (chunk.msgid == NETMSG_Game.SV_VOTECLEAROPTIONS) {
737
+ this.VoteList = [];
738
+ } else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONLISTADD) {
739
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data)
740
+ let NumOptions = unpacker.unpackInt()
741
+ let list: string[] = [];
742
+ for (let i = 0; i < 15; i++) {
743
+ list.push(unpacker.unpackString());
744
+ }
745
+ list = list.slice(NumOptions);
746
+
747
+ this.VoteList.push(...list);
748
+ } else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONADD) {
749
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data)
750
+
751
+ this.VoteList.push(unpacker.unpackString());
752
+ } else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONREMOVE) {
753
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data)
754
+
755
+ let index = this.VoteList.indexOf(unpacker.unpackString());
756
+
757
+ if (index > -1)
758
+ this.VoteList = this.VoteList.splice(index, 1);
759
+
760
+ }
761
+
762
+ // events
763
+ if (chunk.msgid == NETMSG_Game.SV_EMOTICON) {
764
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data);
765
+ let unpacked = {
766
+ client_id: unpacker.unpackInt(),
767
+ emoticon: unpacker.unpackInt()
768
+ } as iEmoticon;
769
+
770
+ if (unpacked.client_id != -1) {
771
+ unpacked.author = {
772
+ ClientInfo: this.client_info(unpacked.client_id),
773
+ PlayerInfo: this.player_info(unpacked.client_id)
774
+ }
775
+ }
776
+ this.emit("emote", unpacked)
777
+
778
+
779
+
780
+ } else if (chunk.msgid == NETMSG_Game.SV_BROADCAST) {
781
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data);
782
+
783
+ this.emit("broadcast", unpacker.unpackString());
784
+ } if (chunk.msgid == NETMSG_Game.SV_CHAT) {
785
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data);
786
+ let unpacked: iMessage = {
641
787
  team: unpacker.unpackInt(),
642
788
  client_id: unpacker.unpackInt(),
643
789
  message: unpacker.unpackString()
@@ -650,14 +796,9 @@ export class Client extends EventEmitter {
650
796
  }
651
797
  }
652
798
  this.emit("message", unpacked)
653
- }
654
- })
655
- }
656
- var chat = unpacked.chunks.filter(chunk => chunk.msg == "SV_KILL_MSG" || chunk.msg == "SV_MOTD");
657
- chat.forEach(a => {
658
- if (a.msg == "SV_KILL_MSG") {
659
- var unpacked: iKillMsg = {} as iKillMsg;
660
- let unpacker = new MsgUnpacker(a.raw.toJSON().data);
799
+ } else if (chunk.msgid == NETMSG_Game.SV_KILLMSG) {
800
+ let unpacked: iKillMsg = {} as iKillMsg;
801
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data);
661
802
  unpacked.killer_id = unpacker.unpackInt();
662
803
  unpacked.victim_id = unpacker.unpackInt();
663
804
  unpacked.weapon = unpacker.unpackInt();
@@ -669,59 +810,22 @@ export class Client extends EventEmitter {
669
810
  if (unpacked.killer_id != -1 && unpacked.killer_id < 64)
670
811
  unpacked.killer = { ClientInfo: this.client_info(unpacked.killer_id), PlayerInfo: this.player_info(unpacked.killer_id) }
671
812
  this.emit("kill", unpacked)
672
- } else if (a.msg == "SV_MOTD") {
673
- let unpacker = new MsgUnpacker(a.raw.toJSON().data);
813
+ } else if (chunk.msgid == NETMSG_Game.SV_MOTD) {
814
+ let unpacker = new MsgUnpacker(chunk.raw.toJSON().data);
674
815
  let message = unpacker.unpackString();
675
816
  this.emit("motd", message);
676
817
  }
677
- })
678
-
679
- if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
680
- var Msg = new MsgPacker(15, true, 1); /* entergame */
681
- this.SendMsgEx(Msg);
682
- } else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
683
- // send ready
684
- var Msg = new MsgPacker(14, true, 1); /* ready */
685
- this.SendMsgEx(Msg);
686
- } else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY"))) {
687
- var info = new MsgPacker(20, false, 1);
688
- if (this.options?.identity) {
689
- info.AddString(this.options.identity.name);
690
- info.AddString(this.options.identity.clan);
691
- info.AddInt(this.options.identity.country);
692
- info.AddString(this.options.identity.skin);
693
- info.AddInt(this.options.identity.use_custom_color);
694
- info.AddInt(this.options.identity.color_body);
695
- info.AddInt(this.options.identity.color_feet);
696
- } else {
697
- info.AddString(this.name); /* name */
698
- info.AddString(""); /* clan */
699
- info.AddInt(-1); /* country */
700
- info.AddString("greyfox"); /* skin */
701
- info.AddInt(1); /* use custom color */
702
- info.AddInt(10346103); /* color body */
703
- info.AddInt(65535); /* color feet */
704
-
705
- }
706
- var crashmeplx = new MsgPacker(17, true, 1); // rcon
707
- crashmeplx.AddString("crashmeplx"); // 64 player support message
708
- this.SendMsgEx([info, crashmeplx]);
709
818
 
710
-
711
-
712
- } else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
713
- var info = new MsgPacker(23, true, 1);
714
- this.SendMsgEx(info)
715
- }
716
- if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
717
- this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
718
- if (this.receivedSnaps == 2) {
719
- if (this.State != States.STATE_ONLINE)
720
- this.emit('connected')
721
- this.State = States.STATE_ONLINE;
819
+ // packets neccessary for connection
820
+ // https://ddnet.org/docs/libtw2/connection/
821
+ if (chunk.msgid == NETMSG_Game.SV_READYTOENTER) {
822
+ var Msg = new MsgPacker(15, true, 1); /* entergame */
823
+ this.SendMsgEx(Msg);
824
+ }
722
825
  }
826
+ })
723
827
 
724
- }
828
+
725
829
  if (new Date().getTime() - this.time >= 1000 && this.State == States.STATE_ONLINE) {
726
830
  this.time = new Date().getTime();
727
831
  this.SendControlMsg(0);
@@ -812,4 +916,8 @@ export class Client extends EventEmitter {
812
916
  .sort((a, b) => a.id - b.id)
813
917
  .map(player => player.parsed as PlayerInfo);
814
918
  }
919
+
920
+ get VoteOptionList(): string[] {
921
+ return this.VoteList;
922
+ }
815
923
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teeworlds",
3
- "version": "2.4.0",
3
+ "version": "2.4.1",
4
4
  "description": "Library for (ingame) teeworlds bots.",
5
5
  "license": "MIT",
6
6
  "main": "index.js",