teeworlds 2.3.3 → 2.3.4

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;
@@ -482,36 +483,39 @@ var Client = /** @class */ (function (_super) {
482
483
  }
483
484
  });
484
485
  }
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);
486
+ var chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_KILL_MSG" || a.msg == "SV_MOTD"; });
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) };
501
497
  }
502
- });
503
- }
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);
501
+ }
502
+ else if (a.msg == "SV_MOTD") {
503
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
504
+ var message = unpacker.unpackString();
505
+ _this.emit("motd", message);
506
+ }
507
+ });
504
508
  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);
509
+ var Msg = new MsgPacker_1.MsgPacker(15, true, 1); /* entergame */
510
+ _this.SendMsgEx(Msg);
507
511
  }
508
512
  else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
509
513
  // send ready
510
- var Msg = new MsgPacker_1.MsgPacker(14, true); /* ready */
511
- _this.SendMsgEx(Msg, 1);
514
+ var Msg = new MsgPacker_1.MsgPacker(14, true, 1); /* ready */
515
+ _this.SendMsgEx(Msg);
512
516
  }
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);
517
+ else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY"))) {
518
+ var info = new MsgPacker_1.MsgPacker(20, false, 1);
515
519
  if ((_g = _this.options) === null || _g === void 0 ? void 0 : _g.identity) {
516
520
  info.AddString(_this.options.identity.name);
517
521
  info.AddString(_this.options.identity.clan);
@@ -530,13 +534,13 @@ var Client = /** @class */ (function (_super) {
530
534
  info.AddInt(10346103); /* color body */
531
535
  info.AddInt(65535); /* color feet */
532
536
  }
533
- var crashmeplx = new MsgPacker_1.MsgPacker(17, true); // rcon
537
+ var crashmeplx = new MsgPacker_1.MsgPacker(17, true, 1); // rcon
534
538
  crashmeplx.AddString("crashmeplx"); // 64 player support message
535
- _this.SendMsgEx([info, crashmeplx], 1);
539
+ _this.SendMsgEx([info, crashmeplx]);
536
540
  }
537
541
  else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
538
- var info = new MsgPacker_1.MsgPacker(23, true);
539
- _this.SendMsgEx(info, 1);
542
+ var info = new MsgPacker_1.MsgPacker(23, true, 1);
543
+ _this.SendMsgEx(info);
540
544
  }
541
545
  if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
542
546
  _this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
@@ -556,7 +560,7 @@ var Client = /** @class */ (function (_super) {
556
560
  if (input === void 0) { input = this.movement.input; }
557
561
  if (this.State != States.STATE_ONLINE)
558
562
  return;
559
- var inputMsg = new MsgPacker_1.MsgPacker(16, true);
563
+ var inputMsg = new MsgPacker_1.MsgPacker(16, true, 0);
560
564
  inputMsg.AddInt(this.AckGameTick);
561
565
  inputMsg.AddInt(this.PredGameTick);
562
566
  inputMsg.AddInt(40);
@@ -575,7 +579,7 @@ var Client = /** @class */ (function (_super) {
575
579
  input_data.forEach(function (a) {
576
580
  inputMsg.AddInt(a);
577
581
  });
578
- this.SendMsgEx(inputMsg, 0);
582
+ this.SendMsgEx(inputMsg);
579
583
  };
580
584
  Object.defineProperty(Client.prototype, "input", {
581
585
  get: function () {
@@ -598,18 +602,18 @@ var Client = /** @class */ (function (_super) {
598
602
  };
599
603
  Client.prototype.Say = function (message, team) {
600
604
  if (team === void 0) { team = false; }
601
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SAY, false);
605
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SAY, false, 1);
602
606
  packer.AddInt(team ? 1 : 0); // team
603
607
  packer.AddString(message);
604
- this.SendMsgEx(packer, 1);
608
+ this.QueueChunkEx(packer);
605
609
  };
606
610
  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);
611
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_VOTE, false, 1);
612
+ packer.AddInt(vote ? 1 : -1);
613
+ this.QueueChunkEx(packer);
610
614
  };
611
615
  Client.prototype.ChangePlayerInfo = function (playerInfo) {
612
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false);
616
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false, 1);
613
617
  packer.AddString(playerInfo.name); //m_pName);
614
618
  packer.AddString(playerInfo.clan); //m_pClan);
615
619
  packer.AddInt(playerInfo.country); //m_Country);
@@ -617,21 +621,21 @@ var Client = /** @class */ (function (_super) {
617
621
  packer.AddInt(playerInfo.use_custom_color ? 1 : 0); //m_UseCustomColor);
618
622
  packer.AddInt(playerInfo.color_body); //m_ColorBody);
619
623
  packer.AddInt(playerInfo.color_feet); //m_ColorFeet);
620
- this.SendMsgEx(packer, 1);
624
+ this.QueueChunkEx(packer);
621
625
  };
622
626
  Client.prototype.Kill = function () {
623
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_KILL, false);
624
- this.SendMsgEx(packer, 1);
627
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_KILL, false, 1);
628
+ this.QueueChunkEx(packer);
625
629
  };
626
630
  Client.prototype.ChangeTeam = function (team) {
627
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SETTEAM, false);
631
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SETTEAM, false, 1);
628
632
  packer.AddInt(team);
629
- this.SendMsgEx(packer, 1);
633
+ this.QueueChunkEx(packer);
630
634
  };
631
635
  Client.prototype.Emote = function (emote) {
632
- var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_EMOTICON, false);
636
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_EMOTICON, false, 1);
633
637
  packer.AddInt(emote);
634
- this.SendMsgEx(packer, 1);
638
+ this.QueueChunkEx(packer);
635
639
  };
636
640
  Client.prototype.client_info = function (id) {
637
641
  var delta = this.SnapUnpacker.deltas.filter(function (a) {
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
 
@@ -617,8 +624,7 @@ export class Client extends EventEmitter {
617
624
  }
618
625
  })
619
626
  }
620
- if (chunkMessages.includes("SV_KILL_MSG")) {
621
- var chat = unpacked.chunks.filter(a => a.msg == "SV_KILL_MSG");
627
+ var chat = unpacked.chunks.filter(a => a.msg == "SV_KILL_MSG" || a.msg == "SV_MOTD");
622
628
  chat.forEach(a => {
623
629
  if (a.msg == "SV_KILL_MSG") {
624
630
  var unpacked: iKillMsg = {} as iKillMsg;
@@ -634,19 +640,22 @@ export class Client extends EventEmitter {
634
640
  if (unpacked.killer_id != -1 && unpacked.killer_id < 64)
635
641
  unpacked.killer = { ClientInfo: this.client_info(unpacked.killer_id), PlayerInfo: this.player_info(unpacked.killer_id) }
636
642
  this.emit("kill", unpacked)
643
+ } else if (a.msg == "SV_MOTD") {
644
+ let unpacker = new MsgUnpacker(a.raw.toJSON().data);
645
+ let message = unpacker.unpackString();
646
+ this.emit("motd", message);
637
647
  }
638
648
  })
639
- }
640
649
 
641
650
  if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
642
- var Msg = new MsgPacker(15, true); /* entergame */
643
- this.SendMsgEx(Msg, 1);
651
+ var Msg = new MsgPacker(15, true, 1); /* entergame */
652
+ this.SendMsgEx(Msg);
644
653
  } else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
645
654
  // 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);
655
+ var Msg = new MsgPacker(14, true, 1); /* ready */
656
+ this.SendMsgEx(Msg);
657
+ } else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY"))) {
658
+ var info = new MsgPacker(20, false, 1);
650
659
  if (this.options?.identity) {
651
660
  info.AddString(this.options.identity.name);
652
661
  info.AddString(this.options.identity.clan);
@@ -665,15 +674,15 @@ export class Client extends EventEmitter {
665
674
  info.AddInt(65535); /* color feet */
666
675
 
667
676
  }
668
- var crashmeplx = new MsgPacker(17, true); // rcon
677
+ var crashmeplx = new MsgPacker(17, true, 1); // rcon
669
678
  crashmeplx.AddString("crashmeplx"); // 64 player support message
670
- this.SendMsgEx([info, crashmeplx], 1);
679
+ this.SendMsgEx([info, crashmeplx]);
671
680
 
672
681
 
673
682
 
674
683
  } else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
675
- var info = new MsgPacker(23, true);
676
- this.SendMsgEx(info, 1)
684
+ var info = new MsgPacker(23, true, 1);
685
+ this.SendMsgEx(info)
677
686
  }
678
687
  if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
679
688
  this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
@@ -695,7 +704,7 @@ export class Client extends EventEmitter {
695
704
  if (this.State != States.STATE_ONLINE)
696
705
  return;
697
706
 
698
- let inputMsg = new MsgPacker(16, true);
707
+ let inputMsg = new MsgPacker(16, true, 0);
699
708
  inputMsg.AddInt(this.AckGameTick);
700
709
  inputMsg.AddInt(this.PredGameTick);
701
710
  inputMsg.AddInt(40);
@@ -716,7 +725,7 @@ export class Client extends EventEmitter {
716
725
  input_data.forEach(a => {
717
726
  inputMsg.AddInt(a);
718
727
  });
719
- this.SendMsgEx(inputMsg, 0);
728
+ this.SendMsgEx(inputMsg);
720
729
  }
721
730
  get input() {
722
731
  return this.movement.input;
@@ -735,18 +744,18 @@ export class Client extends EventEmitter {
735
744
  }
736
745
 
737
746
  Say(message: string, team = false) {
738
- var packer = new MsgPacker(NETMSGTYPE.CL_SAY, false);
747
+ var packer = new MsgPacker(NETMSGTYPE.CL_SAY, false, 1);
739
748
  packer.AddInt(team ? 1 : 0); // team
740
749
  packer.AddString(message);
741
- this.SendMsgEx(packer, 1);
750
+ this.QueueChunkEx(packer);
742
751
  }
743
752
  Vote(vote: boolean) {
744
- var packer = new MsgPacker(NETMSGTYPE.CL_VOTE, false);
745
- packer.AddInt(vote ? 1 : 0);
746
- this.SendMsgEx(packer, 1);
753
+ var packer = new MsgPacker(NETMSGTYPE.CL_VOTE, false, 1);
754
+ packer.AddInt(vote ? 1 : -1);
755
+ this.QueueChunkEx(packer);
747
756
  }
748
757
  ChangePlayerInfo(playerInfo: ClientInfo) {
749
- var packer = new MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false);
758
+ var packer = new MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false, 1);
750
759
  packer.AddString(playerInfo.name); //m_pName);
751
760
  packer.AddString(playerInfo.clan); //m_pClan);
752
761
  packer.AddInt(playerInfo.country); //m_Country);
@@ -754,21 +763,21 @@ export class Client extends EventEmitter {
754
763
  packer.AddInt(playerInfo.use_custom_color ? 1 : 0); //m_UseCustomColor);
755
764
  packer.AddInt(playerInfo.color_body); //m_ColorBody);
756
765
  packer.AddInt(playerInfo.color_feet); //m_ColorFeet);
757
- this.SendMsgEx(packer, 1);
766
+ this.QueueChunkEx(packer);
758
767
  }
759
768
  Kill() {
760
- var packer = new MsgPacker(NETMSGTYPE.CL_KILL, false);
761
- this.SendMsgEx(packer, 1);
769
+ var packer = new MsgPacker(NETMSGTYPE.CL_KILL, false, 1);
770
+ this.QueueChunkEx(packer);
762
771
  }
763
772
  ChangeTeam(team: number) {
764
- var packer = new MsgPacker(NETMSGTYPE.CL_SETTEAM, false);
773
+ var packer = new MsgPacker(NETMSGTYPE.CL_SETTEAM, false, 1);
765
774
  packer.AddInt(team);
766
- this.SendMsgEx(packer, 1);
775
+ this.QueueChunkEx(packer);
767
776
  }
768
777
  Emote(emote: number) {
769
- var packer = new MsgPacker(NETMSGTYPE.CL_EMOTICON, false);
778
+ var packer = new MsgPacker(NETMSGTYPE.CL_EMOTICON, false, 1);
770
779
  packer.AddInt(emote);
771
- this.SendMsgEx(packer, 1);
780
+ this.QueueChunkEx(packer);
772
781
  }
773
782
  client_info(id: number) {
774
783
  let delta = this.SnapUnpacker.deltas.filter(a =>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teeworlds",
3
- "version": "2.3.3",
3
+ "version": "2.3.4",
4
4
  "description": "Library for (ingame) teeworlds bots.",
5
5
  "license": "MIT",
6
6
  "main": "index.js",