teeworlds 2.3.2 → 2.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/MsgPacker.js CHANGED
@@ -2,9 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MsgPacker = void 0;
4
4
  var MsgPacker = /** @class */ (function () {
5
- function MsgPacker(msg, sys) {
5
+ function MsgPacker(msg, sys, flag) {
6
6
  this.result = Buffer.from([2 * msg + (sys ? 1 : 0)]);
7
7
  this.sys = sys;
8
+ this.flag = flag;
8
9
  }
9
10
  MsgPacker.prototype.AddString = function (str) {
10
11
  this.result = Buffer.concat([this.result, Buffer.from(str), Buffer.from([0x00])]);
package/lib/MsgPacker.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export class MsgPacker {
2
2
  result: Buffer;
3
3
  sys: boolean;
4
- constructor(msg: number, sys: boolean) {
4
+ flag: number;
5
+ constructor(msg: number, sys: boolean, flag: number) {
5
6
  this.result = Buffer.from([2*msg + (sys ? 1 : 0)]);
6
7
  this.sys = sys;
8
+ this.flag = flag;
7
9
  }
8
10
  AddString(str: string) {
9
11
  this.result = Buffer.concat([this.result, Buffer.from(str), Buffer.from([0x00])])
package/lib/client.js CHANGED
@@ -139,11 +139,12 @@ var Client = /** @class */ (function (_super) {
139
139
  if (msg.ack > lastAck)
140
140
  toResend.push(msg.msg);
141
141
  });
142
- this.SendMsgEx(toResend, 1 | 2);
142
+ toResend.forEach(function (a) { return a.flag = 1 | 2; });
143
+ this.SendMsgEx(toResend);
143
144
  };
144
145
  Client.prototype.Unpack = function (packet) {
145
146
  var unpacked = { twprotocol: { flags: packet[0] >> 4, ack: ((packet[0] & 0xf) << 8) | packet[1], chunkAmount: packet[2], size: packet.byteLength - 3 }, chunks: [] };
146
- 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)
147
+ 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)
147
148
  return unpacked;
148
149
  if (unpacked.twprotocol.flags & 4) { // resend flag
149
150
  this.ResendAfter(unpacked.twprotocol.ack);
@@ -199,7 +200,7 @@ var Client = /** @class */ (function (_super) {
199
200
  */
200
201
  });
201
202
  };
202
- Client.prototype.SendMsgEx = function (Msgs, Flags) {
203
+ Client.prototype.SendMsgEx = function (Msgs) {
203
204
  var _this = this;
204
205
  if (this.State == States.STATE_OFFLINE)
205
206
  return;
@@ -219,20 +220,20 @@ var Client = /** @class */ (function (_super) {
219
220
  if (this.clientAck == 0)
220
221
  this.lastSentMessages = [];
221
222
  _Msgs.forEach(function (Msg, index) {
222
- header[index] = Buffer.alloc((Flags & 1 ? 3 : 2));
223
- header[index][0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
223
+ header[index] = Buffer.alloc((Msg.flag & 1 ? 3 : 2));
224
+ header[index][0] = ((Msg.flag & 3) << 6) | ((Msg.size >> 4) & 0x3f);
224
225
  header[index][1] = (Msg.size & 0xf);
225
- if (Flags & 1) {
226
+ if (Msg.flag & 1) {
226
227
  _this.clientAck = (_this.clientAck + 1) % (1 << 10);
227
228
  if (_this.clientAck == 0)
228
229
  _this.lastSentMessages = [];
229
230
  header[index][1] |= (_this.clientAck >> 2) & 0xf0;
230
231
  header[index][2] = _this.clientAck & 0xff;
231
- header[index][0] = (((Flags | 2) & 3) << 6) | ((Msg.size >> 4) & 0x3f); // 2 is resend flag (ugly hack for queue)
232
- if ((Flags & 2) == 0)
232
+ header[index][0] = (((Msg.flag | 2) & 3) << 6) | ((Msg.size >> 4) & 0x3f); // 2 is resend flag (ugly hack for queue)
233
+ if ((Msg.flag & 2) == 0)
233
234
  _this.sentChunkQueue.push(Buffer.concat([header[index], Msg.buffer]));
234
- header[index][0] = (((Flags) & 3) << 6) | ((Msg.size >> 4) & 0x3f);
235
- if ((Flags & 2) == 0)
235
+ header[index][0] = (((Msg.flag) & 3) << 6) | ((Msg.size >> 4) & 0x3f);
236
+ if ((Msg.flag & 2) == 0)
236
237
  _this.lastSentMessages.push({ msg: Msg, ack: _this.clientAck });
237
238
  }
238
239
  });
@@ -249,11 +250,12 @@ var Client = /** @class */ (function (_super) {
249
250
  chunks = Buffer.concat([chunks, Buffer.from(header[index]), Msg.buffer]);
250
251
  else {
251
252
  skip = true;
252
- _this.SendMsgEx(_Msgs.slice(index), Flags);
253
+ _this.SendMsgEx(_Msgs.slice(index));
253
254
  }
254
255
  });
255
256
  var packet = Buffer.concat([(packetHeader), chunks, this.TKEN]);
256
- // packet[0] |= 4;
257
+ if (chunks.length < 0)
258
+ return;
257
259
  this.socket.send(packet, 0, packet.length, this.port, this.host);
258
260
  };
259
261
  Client.prototype.QueueChunkEx = function (Msg) {
@@ -267,6 +269,8 @@ var Client = /** @class */ (function (_super) {
267
269
  this.lastSendTime = new Date().getTime();
268
270
  var packetHeader = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff, chunks.length]);
269
271
  var packet = Buffer.concat([(packetHeader), Buffer.concat(chunks), this.TKEN]);
272
+ if (chunks.length < 0)
273
+ return;
270
274
  this.socket.send(packet, 0, packet.length, this.port, this.host);
271
275
  };
272
276
  Client.prototype.MsgToChunk = function (packet) {
@@ -351,10 +355,10 @@ var Client = /** @class */ (function (_super) {
351
355
  _this.SendControlMsg(3);
352
356
  _this.State = States.STATE_LOADING; // loading state
353
357
  _this.receivedSnaps = 0;
354
- var info = new MsgPacker_1.MsgPacker(1, true);
358
+ var info = new MsgPacker_1.MsgPacker(1, true, 1);
355
359
  info.AddString(((_a = _this.options) === null || _a === void 0 ? void 0 : _a.NET_VERSION) ? _this.options.NET_VERSION : "0.6 626fce9a778df4d4");
356
360
  info.AddString(((_b = _this.options) === null || _b === void 0 ? void 0 : _b.password) === undefined ? "" : (_c = _this.options) === null || _c === void 0 ? void 0 : _c.password); // password
357
- var client_version = new MsgPacker_1.MsgPacker(0, true);
361
+ var client_version = new MsgPacker_1.MsgPacker(0, true, 1);
358
362
  client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
359
363
  var randomUuid = Buffer.alloc(16);
360
364
  crypto_1.randomBytes(16).copy(randomUuid);
@@ -367,7 +371,7 @@ var Client = /** @class */ (function (_super) {
367
371
  client_version.AddInt(16003);
368
372
  client_version.AddString("DDNet 16.0.3");
369
373
  }
370
- _this.SendMsgEx([client_version, info], 1);
374
+ _this.SendMsgEx([client_version, info]);
371
375
  }
372
376
  else if (a.toJSON().data[3] == 0x4) {
373
377
  // disconnected
@@ -379,12 +383,13 @@ var Client = /** @class */ (function (_super) {
379
383
  _this.lastRecvTime = new Date().getTime();
380
384
  }
381
385
  }
382
- else
386
+ else {
383
387
  _this.lastRecvTime = new Date().getTime();
388
+ }
384
389
  var unpacked = _this.Unpack(a);
385
390
  unpacked.chunks.forEach(function (a) {
386
- if (a.flags & 1) { // vital
387
- if (a.seq === (_this.ack + 1) % (1 << 10)) {
391
+ if (a.flags & 1 && (a.flags !== 15)) { // vital and not connless
392
+ if (a.seq === (_this.ack + 1) % (1 << 10)) { // https://github.com/nobody-mb/twchatonly/blob/master/chatonly.cpp#L237
388
393
  _this.ack = a.seq;
389
394
  _this.requestResend = false;
390
395
  }
@@ -399,8 +404,6 @@ var Client = /** @class */ (function (_super) {
399
404
  return;
400
405
  }
401
406
  _this.requestResend = true;
402
- // c_flags |= 4; /* resend flag */
403
- // continue; // take the next chunk in the packet
404
407
  }
405
408
  }
406
409
  });
@@ -436,9 +439,7 @@ var Client = /** @class */ (function (_super) {
436
439
  var num_parts_1 = 1;
437
440
  var part_1 = 0;
438
441
  if (chunk.msg === "SNAP") {
439
- // chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // delta tick
440
442
  num_parts_1 = unpacker.unpackInt();
441
- // chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // num parts
442
443
  part_1 = unpacker.unpackInt();
443
444
  }
444
445
  var crc = 0;
@@ -456,6 +457,7 @@ var Client = /** @class */ (function (_super) {
456
457
  var mergedSnaps = Buffer.concat(_this.snaps);
457
458
  var snapUnpacked = _this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, AckGameTick);
458
459
  _this.AckGameTick = snapUnpacked.recvTick;
460
+ _this.emit("snapshot");
459
461
  _this.sendInput();
460
462
  }
461
463
  }
@@ -482,36 +484,39 @@ var Client = /** @class */ (function (_super) {
482
484
  }
483
485
  });
484
486
  }
485
- if (chunkMessages.includes("SV_KILL_MSG")) {
486
- var chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_KILL_MSG"; });
487
- chat.forEach(function (a) {
488
- if (a.msg == "SV_KILL_MSG") {
489
- var unpacked = {};
490
- var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
491
- unpacked.killer_id = unpacker.unpackInt();
492
- unpacked.victim_id = unpacker.unpackInt();
493
- unpacked.weapon = unpacker.unpackInt();
494
- unpacked.special_mode = unpacker.unpackInt();
495
- if (unpacked.victim_id != -1 && unpacked.victim_id < 64) {
496
- unpacked.victim = { ClientInfo: _this.client_info(unpacked.victim_id), PlayerInfo: _this.player_info(unpacked.victim_id) };
497
- }
498
- if (unpacked.killer_id != -1 && unpacked.killer_id < 64)
499
- unpacked.killer = { ClientInfo: _this.client_info(unpacked.killer_id), PlayerInfo: _this.player_info(unpacked.killer_id) };
500
- _this.emit("kill", unpacked);
487
+ var chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_KILL_MSG" || a.msg == "SV_MOTD"; });
488
+ chat.forEach(function (a) {
489
+ if (a.msg == "SV_KILL_MSG") {
490
+ var unpacked = {};
491
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
492
+ unpacked.killer_id = unpacker.unpackInt();
493
+ unpacked.victim_id = unpacker.unpackInt();
494
+ unpacked.weapon = unpacker.unpackInt();
495
+ unpacked.special_mode = unpacker.unpackInt();
496
+ if (unpacked.victim_id != -1 && unpacked.victim_id < 64) {
497
+ unpacked.victim = { ClientInfo: _this.client_info(unpacked.victim_id), PlayerInfo: _this.player_info(unpacked.victim_id) };
501
498
  }
502
- });
503
- }
499
+ if (unpacked.killer_id != -1 && unpacked.killer_id < 64)
500
+ unpacked.killer = { ClientInfo: _this.client_info(unpacked.killer_id), PlayerInfo: _this.player_info(unpacked.killer_id) };
501
+ _this.emit("kill", unpacked);
502
+ }
503
+ else if (a.msg == "SV_MOTD") {
504
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
505
+ var message = unpacker.unpackString();
506
+ _this.emit("motd", message);
507
+ }
508
+ });
504
509
  if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
505
- var Msg = new MsgPacker_1.MsgPacker(15, true); /* entergame */
506
- _this.SendMsgEx(Msg, 1);
510
+ var Msg = new MsgPacker_1.MsgPacker(15, true, 1); /* entergame */
511
+ _this.SendMsgEx(Msg);
507
512
  }
508
513
  else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
509
514
  // send ready
510
- var Msg = new MsgPacker_1.MsgPacker(14, true); /* ready */
511
- _this.SendMsgEx(Msg, 1);
515
+ var Msg = new MsgPacker_1.MsgPacker(14, true, 1); /* ready */
516
+ _this.SendMsgEx(Msg);
512
517
  }
513
- else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY") || unpacked.chunks[0] && chunkMessages.includes("SV_MOTD"))) {
514
- var info = new MsgPacker_1.MsgPacker(20, false);
518
+ else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY"))) {
519
+ var info = new MsgPacker_1.MsgPacker(20, false, 1);
515
520
  if ((_g = _this.options) === null || _g === void 0 ? void 0 : _g.identity) {
516
521
  info.AddString(_this.options.identity.name);
517
522
  info.AddString(_this.options.identity.clan);
@@ -530,13 +535,13 @@ var Client = /** @class */ (function (_super) {
530
535
  info.AddInt(10346103); /* color body */
531
536
  info.AddInt(65535); /* color feet */
532
537
  }
533
- var crashmeplx = new MsgPacker_1.MsgPacker(17, true); // rcon
538
+ var crashmeplx = new MsgPacker_1.MsgPacker(17, true, 1); // rcon
534
539
  crashmeplx.AddString("crashmeplx"); // 64 player support message
535
- _this.SendMsgEx([info, crashmeplx], 1);
540
+ _this.SendMsgEx([info, crashmeplx]);
536
541
  }
537
542
  else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
538
- var info = new MsgPacker_1.MsgPacker(23, true);
539
- _this.SendMsgEx(info, 1);
543
+ var info = new MsgPacker_1.MsgPacker(23, true, 1);
544
+ _this.SendMsgEx(info);
540
545
  }
541
546
  if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
542
547
  _this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
@@ -556,7 +561,7 @@ var Client = /** @class */ (function (_super) {
556
561
  if (input === void 0) { input = this.movement.input; }
557
562
  if (this.State != States.STATE_ONLINE)
558
563
  return;
559
- var inputMsg = new MsgPacker_1.MsgPacker(16, true);
564
+ var inputMsg = new MsgPacker_1.MsgPacker(16, true, 0);
560
565
  inputMsg.AddInt(this.AckGameTick);
561
566
  inputMsg.AddInt(this.PredGameTick);
562
567
  inputMsg.AddInt(40);
@@ -575,7 +580,7 @@ var Client = /** @class */ (function (_super) {
575
580
  input_data.forEach(function (a) {
576
581
  inputMsg.AddInt(a);
577
582
  });
578
- this.SendMsgEx(inputMsg, 0);
583
+ this.SendMsgEx(inputMsg);
579
584
  };
580
585
  Object.defineProperty(Client.prototype, "input", {
581
586
  get: function () {
@@ -598,18 +603,18 @@ var Client = /** @class */ (function (_super) {
598
603
  };
599
604
  Client.prototype.Say = function (message, team) {
600
605
  if (team === void 0) { team = false; }
601
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SAY, false);
606
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SAY, false, 1);
602
607
  packer.AddInt(team ? 1 : 0); // team
603
608
  packer.AddString(message);
604
- this.SendMsgEx(packer, 1);
609
+ this.QueueChunkEx(packer);
605
610
  };
606
611
  Client.prototype.Vote = function (vote) {
607
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_VOTE, false);
608
- packer.AddInt(vote ? 1 : 0);
609
- this.SendMsgEx(packer, 1);
612
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_VOTE, false, 1);
613
+ packer.AddInt(vote ? 1 : -1);
614
+ this.QueueChunkEx(packer);
610
615
  };
611
616
  Client.prototype.ChangePlayerInfo = function (playerInfo) {
612
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false);
617
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false, 1);
613
618
  packer.AddString(playerInfo.name); //m_pName);
614
619
  packer.AddString(playerInfo.clan); //m_pClan);
615
620
  packer.AddInt(playerInfo.country); //m_Country);
@@ -617,21 +622,21 @@ var Client = /** @class */ (function (_super) {
617
622
  packer.AddInt(playerInfo.use_custom_color ? 1 : 0); //m_UseCustomColor);
618
623
  packer.AddInt(playerInfo.color_body); //m_ColorBody);
619
624
  packer.AddInt(playerInfo.color_feet); //m_ColorFeet);
620
- this.SendMsgEx(packer, 1);
625
+ this.QueueChunkEx(packer);
621
626
  };
622
627
  Client.prototype.Kill = function () {
623
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_KILL, false);
624
- this.SendMsgEx(packer, 1);
628
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_KILL, false, 1);
629
+ this.QueueChunkEx(packer);
625
630
  };
626
631
  Client.prototype.ChangeTeam = function (team) {
627
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SETTEAM, false);
632
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SETTEAM, false, 1);
628
633
  packer.AddInt(team);
629
- this.SendMsgEx(packer, 1);
634
+ this.QueueChunkEx(packer);
630
635
  };
631
636
  Client.prototype.Emote = function (emote) {
632
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_EMOTICON, false);
637
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_EMOTICON, false, 1);
633
638
  packer.AddInt(emote);
634
- this.SendMsgEx(packer, 1);
639
+ this.QueueChunkEx(packer);
635
640
  };
636
641
  Client.prototype.client_info = function (id) {
637
642
  var delta = this.SnapUnpacker.deltas.filter(function (a) {
@@ -655,7 +660,7 @@ var Client = /** @class */ (function (_super) {
655
660
  });
656
661
  Client.prototype.player_info = function (id) {
657
662
  var delta = this.SnapUnpacker.deltas.filter(function (a) {
658
- return a.type_id == 11
663
+ return a.type_id == 10
659
664
  && a.id == id;
660
665
  });
661
666
  if (delta.length == 0)
@@ -664,7 +669,7 @@ var Client = /** @class */ (function (_super) {
664
669
  };
665
670
  Object.defineProperty(Client.prototype, "player_infos", {
666
671
  get: function () {
667
- return this.SnapUnpacker.deltas.filter(function (a) { return a.type_id == 11; })
672
+ return this.SnapUnpacker.deltas.filter(function (a) { return a.type_id == 10; })
668
673
  .sort(function (a, b) { return a.id - b.id; })
669
674
  .map(function (a) { return a.parsed; });
670
675
  },
package/lib/client.ts CHANGED
@@ -184,6 +184,8 @@ export declare interface Client {
184
184
  on(event: 'message', listener: (message: iMessage) => void): this;
185
185
  on(event: 'broadcast', listener: (message: string) => void): this;
186
186
  on(event: 'kill', listener: (kill: iKillMsg) => void): this;
187
+ on(event: 'motd', listener: (message: string) => void): this;
188
+
187
189
  requestResend: boolean;
188
190
  }
189
191
 
@@ -235,19 +237,22 @@ export class Client extends EventEmitter {
235
237
 
236
238
  ResendAfter(lastAck: number) {
237
239
  this.clientAck = lastAck;
240
+
241
+
238
242
  let toResend: MsgPacker[] = [];
239
243
  this.lastSentMessages.forEach(msg => {
240
244
  if (msg.ack > lastAck)
241
245
  toResend.push(msg.msg);
242
246
  });
243
- this.SendMsgEx(toResend, 1|2);
247
+ toResend.forEach(a => a.flag = 1|2);
248
+ this.SendMsgEx(toResend);
244
249
  }
245
250
 
246
251
  Unpack(packet: Buffer): _packet {
247
252
  var unpacked: _packet = { twprotocol: { flags: packet[0] >> 4, ack: ((packet[0]&0xf)<<8) | packet[1], chunkAmount: packet[2], size: packet.byteLength - 3 }, chunks: [] }
248
253
 
249
254
 
250
- 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)
255
+ 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)
251
256
  return unpacked;
252
257
  if (unpacked.twprotocol.flags & 4) { // resend flag
253
258
  this.ResendAfter(unpacked.twprotocol.ack);
@@ -307,7 +312,7 @@ export class Client extends EventEmitter {
307
312
  })
308
313
  }
309
314
 
310
- SendMsgEx(Msgs: MsgPacker[] | MsgPacker, Flags: number) {
315
+ SendMsgEx(Msgs: MsgPacker[] | MsgPacker) {
311
316
  if (this.State == States.STATE_OFFLINE)
312
317
  return;
313
318
  if (!this.socket)
@@ -326,20 +331,20 @@ export class Client extends EventEmitter {
326
331
  if (this.clientAck == 0)
327
332
  this.lastSentMessages = [];
328
333
  _Msgs.forEach((Msg: MsgPacker, index) => {
329
- header[index] = Buffer.alloc((Flags & 1 ? 3 : 2));
330
- header[index][0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
334
+ header[index] = Buffer.alloc((Msg.flag & 1 ? 3 : 2));
335
+ header[index][0] = ((Msg.flag & 3) << 6) | ((Msg.size >> 4) & 0x3f);
331
336
  header[index][1] = (Msg.size & 0xf);
332
- if (Flags & 1) {
337
+ if (Msg.flag & 1) {
333
338
  this.clientAck = (this.clientAck + 1) % (1 << 10);
334
339
  if (this.clientAck == 0)
335
340
  this.lastSentMessages = [];
336
341
  header[index][1] |= (this.clientAck >> 2) & 0xf0;
337
342
  header[index][2] = this.clientAck & 0xff;
338
- header[index][0] = (((Flags | 2)&3)<<6)|((Msg.size>>4)&0x3f); // 2 is resend flag (ugly hack for queue)
339
- if ((Flags & 2) == 0)
343
+ header[index][0] = (((Msg.flag | 2)&3)<<6)|((Msg.size>>4)&0x3f); // 2 is resend flag (ugly hack for queue)
344
+ if ((Msg.flag & 2) == 0)
340
345
  this.sentChunkQueue.push(Buffer.concat([header[index], Msg.buffer]));
341
- header[index][0] = (((Flags)&3)<<6)|((Msg.size>>4)&0x3f);
342
- if ((Flags & 2) == 0)
346
+ header[index][0] = (((Msg.flag)&3)<<6)|((Msg.size>>4)&0x3f);
347
+ if ((Msg.flag & 2) == 0)
343
348
  this.lastSentMessages.push({msg: Msg, ack: this.clientAck})
344
349
  }
345
350
  })
@@ -357,11 +362,12 @@ export class Client extends EventEmitter {
357
362
  chunks = Buffer.concat([chunks, Buffer.from(header[index]), Msg.buffer]);
358
363
  else {
359
364
  skip = true;
360
- this.SendMsgEx(_Msgs.slice(index), Flags);
365
+ this.SendMsgEx(_Msgs.slice(index));
361
366
  }
362
367
  })
363
368
  var packet = Buffer.concat([(packetHeader), chunks, this.TKEN]);
364
- // packet[0] |= 4;
369
+ if (chunks.length < 0)
370
+ return;
365
371
  this.socket.send(packet, 0, packet.length, this.port, this.host)
366
372
  }
367
373
 
@@ -380,7 +386,8 @@ export class Client extends EventEmitter {
380
386
  var packetHeader = Buffer.from([0x0+(((16<<4)&0xf0)|((this.ack>>8)&0xf)), this.ack&0xff, chunks.length]);
381
387
 
382
388
  var packet = Buffer.concat([(packetHeader), Buffer.concat(chunks), this.TKEN]);
383
-
389
+ if (chunks.length < 0)
390
+ return;
384
391
  this.socket.send(packet, 0, packet.length, this.port, this.host)
385
392
  }
386
393
 
@@ -471,11 +478,11 @@ export class Client extends EventEmitter {
471
478
  this.State = States.STATE_LOADING; // loading state
472
479
  this.receivedSnaps = 0;
473
480
 
474
- var info = new MsgPacker(1, true);
481
+ var info = new MsgPacker(1, true, 1);
475
482
  info.AddString(this.options?.NET_VERSION ? this.options.NET_VERSION : "0.6 626fce9a778df4d4");
476
483
  info.AddString(this.options?.password === undefined ? "" : this.options?.password); // password
477
484
 
478
- var client_version = new MsgPacker(0, true);
485
+ var client_version = new MsgPacker(0, true, 1);
479
486
  client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
480
487
  let randomUuid = Buffer.alloc(16);
481
488
 
@@ -490,7 +497,7 @@ export class Client extends EventEmitter {
490
497
  client_version.AddString("DDNet 16.0.3");
491
498
  }
492
499
 
493
- this.SendMsgEx([client_version, info], 1)
500
+ this.SendMsgEx([client_version, info])
494
501
  } else if (a.toJSON().data[3] == 0x4) {
495
502
  // disconnected
496
503
  this.State = States.STATE_OFFLINE;
@@ -500,15 +507,18 @@ export class Client extends EventEmitter {
500
507
  if (a.toJSON().data[3] !== 0x0) { // keepalive
501
508
  this.lastRecvTime = new Date().getTime();
502
509
  }
503
- } else
510
+ } else {
504
511
  this.lastRecvTime = new Date().getTime();
505
512
 
513
+ }
514
+
506
515
 
507
- var unpacked: _packet = this.Unpack(a)
516
+ var unpacked: _packet = this.Unpack(a);
508
517
  unpacked.chunks.forEach(a => {
509
- if (a.flags & 1) { // vital
510
- if (a.seq === (this.ack+1)%(1<<10)) {
511
- this.ack = a.seq;
518
+ if (a.flags & 1 && (a.flags !== 15)) { // vital and not connless
519
+ if (a.seq === (this.ack+1)%(1<<10)) { // https://github.com/nobody-mb/twchatonly/blob/master/chatonly.cpp#L237
520
+ this.ack = a.seq!;
521
+
512
522
  this.requestResend = false;
513
523
  }
514
524
  else { //IsSeqInBackroom (old packet that we already got)
@@ -522,11 +532,10 @@ export class Client extends EventEmitter {
522
532
  return;
523
533
  }
524
534
  this.requestResend = true;
525
- // c_flags |= 4; /* resend flag */
526
- // continue; // take the next chunk in the packet
527
535
 
528
536
  }
529
537
  }
538
+
530
539
  })
531
540
  unpacked.chunks.filter(a => a.msgid == NETMSGTYPE.SV_BROADCAST && a.type == 'game').forEach(a => {
532
541
  let unpacker = new MsgUnpacker(a.raw.toJSON().data);
@@ -564,9 +573,7 @@ export class Client extends EventEmitter {
564
573
  let part = 0;
565
574
 
566
575
  if (chunk.msg === "SNAP") {
567
- // chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // delta tick
568
576
  num_parts = unpacker.unpackInt();
569
- // chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // num parts
570
577
  part = unpacker.unpackInt();
571
578
  }
572
579
 
@@ -588,7 +595,9 @@ export class Client extends EventEmitter {
588
595
 
589
596
  let snapUnpacked = this.SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, DeltaTick, AckGameTick);
590
597
  this.AckGameTick = snapUnpacked.recvTick;
591
-
598
+
599
+ this.emit("snapshot");
600
+
592
601
  this.sendInput();
593
602
  }
594
603
 
@@ -617,8 +626,7 @@ export class Client extends EventEmitter {
617
626
  }
618
627
  })
619
628
  }
620
- if (chunkMessages.includes("SV_KILL_MSG")) {
621
- var chat = unpacked.chunks.filter(a => a.msg == "SV_KILL_MSG");
629
+ var chat = unpacked.chunks.filter(a => a.msg == "SV_KILL_MSG" || a.msg == "SV_MOTD");
622
630
  chat.forEach(a => {
623
631
  if (a.msg == "SV_KILL_MSG") {
624
632
  var unpacked: iKillMsg = {} as iKillMsg;
@@ -634,19 +642,22 @@ export class Client extends EventEmitter {
634
642
  if (unpacked.killer_id != -1 && unpacked.killer_id < 64)
635
643
  unpacked.killer = { ClientInfo: this.client_info(unpacked.killer_id), PlayerInfo: this.player_info(unpacked.killer_id) }
636
644
  this.emit("kill", unpacked)
645
+ } else if (a.msg == "SV_MOTD") {
646
+ let unpacker = new MsgUnpacker(a.raw.toJSON().data);
647
+ let message = unpacker.unpackString();
648
+ this.emit("motd", message);
637
649
  }
638
650
  })
639
- }
640
651
 
641
652
  if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
642
- var Msg = new MsgPacker(15, true); /* entergame */
643
- this.SendMsgEx(Msg, 1);
653
+ var Msg = new MsgPacker(15, true, 1); /* entergame */
654
+ this.SendMsgEx(Msg);
644
655
  } else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
645
656
  // send ready
646
- var Msg = new MsgPacker(14, true); /* ready */
647
- this.SendMsgEx(Msg, 1);
648
- } else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY") || unpacked.chunks[0] && chunkMessages.includes("SV_MOTD"))) {
649
- var info = new MsgPacker(20, false);
657
+ var Msg = new MsgPacker(14, true, 1); /* ready */
658
+ this.SendMsgEx(Msg);
659
+ } else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY"))) {
660
+ var info = new MsgPacker(20, false, 1);
650
661
  if (this.options?.identity) {
651
662
  info.AddString(this.options.identity.name);
652
663
  info.AddString(this.options.identity.clan);
@@ -665,15 +676,15 @@ export class Client extends EventEmitter {
665
676
  info.AddInt(65535); /* color feet */
666
677
 
667
678
  }
668
- var crashmeplx = new MsgPacker(17, true); // rcon
679
+ var crashmeplx = new MsgPacker(17, true, 1); // rcon
669
680
  crashmeplx.AddString("crashmeplx"); // 64 player support message
670
- this.SendMsgEx([info, crashmeplx], 1);
681
+ this.SendMsgEx([info, crashmeplx]);
671
682
 
672
683
 
673
684
 
674
685
  } else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
675
- var info = new MsgPacker(23, true);
676
- this.SendMsgEx(info, 1)
686
+ var info = new MsgPacker(23, true, 1);
687
+ this.SendMsgEx(info)
677
688
  }
678
689
  if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
679
690
  this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
@@ -695,7 +706,7 @@ export class Client extends EventEmitter {
695
706
  if (this.State != States.STATE_ONLINE)
696
707
  return;
697
708
 
698
- let inputMsg = new MsgPacker(16, true);
709
+ let inputMsg = new MsgPacker(16, true, 0);
699
710
  inputMsg.AddInt(this.AckGameTick);
700
711
  inputMsg.AddInt(this.PredGameTick);
701
712
  inputMsg.AddInt(40);
@@ -716,7 +727,7 @@ export class Client extends EventEmitter {
716
727
  input_data.forEach(a => {
717
728
  inputMsg.AddInt(a);
718
729
  });
719
- this.SendMsgEx(inputMsg, 0);
730
+ this.SendMsgEx(inputMsg);
720
731
  }
721
732
  get input() {
722
733
  return this.movement.input;
@@ -735,18 +746,18 @@ export class Client extends EventEmitter {
735
746
  }
736
747
 
737
748
  Say(message: string, team = false) {
738
- var packer = new MsgPacker(NETMSGTYPE.CL_SAY, false);
749
+ var packer = new MsgPacker(NETMSGTYPE.CL_SAY, false, 1);
739
750
  packer.AddInt(team ? 1 : 0); // team
740
751
  packer.AddString(message);
741
- this.SendMsgEx(packer, 1);
752
+ this.QueueChunkEx(packer);
742
753
  }
743
754
  Vote(vote: boolean) {
744
- var packer = new MsgPacker(NETMSGTYPE.CL_VOTE, false);
745
- packer.AddInt(vote ? 1 : 0);
746
- this.SendMsgEx(packer, 1);
755
+ var packer = new MsgPacker(NETMSGTYPE.CL_VOTE, false, 1);
756
+ packer.AddInt(vote ? 1 : -1);
757
+ this.QueueChunkEx(packer);
747
758
  }
748
759
  ChangePlayerInfo(playerInfo: ClientInfo) {
749
- var packer = new MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false);
760
+ var packer = new MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false, 1);
750
761
  packer.AddString(playerInfo.name); //m_pName);
751
762
  packer.AddString(playerInfo.clan); //m_pClan);
752
763
  packer.AddInt(playerInfo.country); //m_Country);
@@ -754,21 +765,21 @@ export class Client extends EventEmitter {
754
765
  packer.AddInt(playerInfo.use_custom_color ? 1 : 0); //m_UseCustomColor);
755
766
  packer.AddInt(playerInfo.color_body); //m_ColorBody);
756
767
  packer.AddInt(playerInfo.color_feet); //m_ColorFeet);
757
- this.SendMsgEx(packer, 1);
768
+ this.QueueChunkEx(packer);
758
769
  }
759
770
  Kill() {
760
- var packer = new MsgPacker(NETMSGTYPE.CL_KILL, false);
761
- this.SendMsgEx(packer, 1);
771
+ var packer = new MsgPacker(NETMSGTYPE.CL_KILL, false, 1);
772
+ this.QueueChunkEx(packer);
762
773
  }
763
774
  ChangeTeam(team: number) {
764
- var packer = new MsgPacker(NETMSGTYPE.CL_SETTEAM, false);
775
+ var packer = new MsgPacker(NETMSGTYPE.CL_SETTEAM, false, 1);
765
776
  packer.AddInt(team);
766
- this.SendMsgEx(packer, 1);
777
+ this.QueueChunkEx(packer);
767
778
  }
768
779
  Emote(emote: number) {
769
- var packer = new MsgPacker(NETMSGTYPE.CL_EMOTICON, false);
780
+ var packer = new MsgPacker(NETMSGTYPE.CL_EMOTICON, false, 1);
770
781
  packer.AddInt(emote);
771
- this.SendMsgEx(packer, 1);
782
+ this.QueueChunkEx(packer);
772
783
  }
773
784
  client_info(id: number) {
774
785
  let delta = this.SnapUnpacker.deltas.filter(a =>
@@ -790,7 +801,7 @@ export class Client extends EventEmitter {
790
801
  }
791
802
  player_info(id: number) {
792
803
  let delta = this.SnapUnpacker.deltas.filter(a =>
793
- a.type_id == 11
804
+ a.type_id == 10
794
805
  && a.id == id
795
806
  );
796
807
 
@@ -799,7 +810,7 @@ export class Client extends EventEmitter {
799
810
  return delta[0].parsed as PlayerInfo;
800
811
  }
801
812
  get player_infos(): PlayerInfo[] {
802
- return this.SnapUnpacker.deltas.filter(a => a.type_id == 11)
813
+ return this.SnapUnpacker.deltas.filter(a => a.type_id == 10)
803
814
  .sort((a, b) => a.id - b.id)
804
815
  .map(a => a.parsed as PlayerInfo);
805
816
  }
package/lib/snapshot.js CHANGED
@@ -382,13 +382,13 @@ var Snapshot = /** @class */ (function () {
382
382
  var _loop_2 = function (newSnap) {
383
383
  if (this_2.eSnapHolder.filter(function (a) { return a.ack == newSnap.ack && a.Snapshot.Key == newSnap.Snapshot.Key; }).length === 0) { // ugly copy new snap to eSnapHolder (if it isnt pushed already)
384
384
  this_2.eSnapHolder.push({ Snapshot: { Data: newSnap.Snapshot.Data, Key: newSnap.Snapshot.Key }, ack: recvTick });
385
- var ____index = this_2.deltas.map(function (delta) { return delta.key; }).indexOf(newSnap.Snapshot.Key);
386
- if (____index > -1 && deltatick > -1) {
387
- this_2.deltas[____index] = { data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this_2.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff)) };
388
- }
389
- else
390
- this_2.deltas.push({ data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this_2.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff)) });
391
385
  }
386
+ var ____index = this_2.deltas.map(function (delta) { return delta.key; }).indexOf(newSnap.Snapshot.Key);
387
+ if (____index > -1 && deltatick > -1) {
388
+ this_2.deltas[____index] = { data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this_2.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff)) };
389
+ }
390
+ else
391
+ this_2.deltas.push({ data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this_2.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff)) });
392
392
  };
393
393
  var this_2 = this;
394
394
  for (var _i = 0, newSnaps_1 = newSnaps; _i < newSnaps_1.length; _i++) {
package/lib/snapshot.ts CHANGED
@@ -397,13 +397,13 @@ export class Snapshot {
397
397
  for (let newSnap of newSnaps) {
398
398
  if (this.eSnapHolder.filter(a => a.ack == newSnap.ack && a.Snapshot.Key == newSnap.Snapshot.Key).length === 0) { // ugly copy new snap to eSnapHolder (if it isnt pushed already)
399
399
  this.eSnapHolder.push({Snapshot: {Data: newSnap.Snapshot.Data, Key: newSnap.Snapshot.Key}, ack: recvTick});
400
- let ____index = this.deltas.map(delta => delta.key).indexOf(newSnap.Snapshot.Key);
401
-
402
- if (____index > -1 && deltatick > -1) {
403
- this.deltas[____index] = {data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff))};
404
- } else
405
- this.deltas.push({data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff))});
406
400
  }
401
+ let ____index = this.deltas.map(delta => delta.key).indexOf(newSnap.Snapshot.Key);
402
+
403
+ if (____index > -1 && deltatick > -1) {
404
+ this.deltas[____index] = {data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff))};
405
+ } else
406
+ this.deltas.push({data: newSnap.Snapshot.Data, key: newSnap.Snapshot.Key, id: newSnap.Snapshot.Key & 0xffff, type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff), parsed: this.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff))});
407
407
  }
408
408
 
409
409
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teeworlds",
3
- "version": "2.3.2",
3
+ "version": "2.3.7",
4
4
  "description": "Library for (ingame) teeworlds bots.",
5
5
  "license": "MIT",
6
6
  "main": "index.js",