teeworlds 2.4.3 → 2.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +0 -1
- package/index.ts +1 -2
- package/lib/MsgUnpacker.js +9 -11
- package/lib/MsgUnpacker.ts +13 -13
- package/lib/client.js +59 -108
- package/lib/client.ts +80 -133
- package/lib/components/game.js +11 -11
- package/lib/components/game.ts +33 -21
- package/lib/{movement.js → components/movement.js} +0 -0
- package/lib/{movement.ts → components/movement.ts} +0 -0
- package/lib/components/snapshot.js +200 -0
- package/lib/components/snapshot.ts +174 -0
- package/lib/snapshot.js +129 -56
- package/lib/snapshot.ts +134 -50
- package/lib/snapshots.d.ts +26 -22
- package/package.json +1 -1
- package/test.js +0 -32
package/lib/client.ts
CHANGED
|
@@ -5,12 +5,14 @@ import { EventEmitter } from 'stream';
|
|
|
5
5
|
|
|
6
6
|
import { unpackString, MsgUnpacker } from "./MsgUnpacker";
|
|
7
7
|
|
|
8
|
-
import Movement from './movement';
|
|
8
|
+
import Movement from './components/movement';
|
|
9
|
+
import { PlayerInput, PlayerInfo, Projectile, Laser, Pickup, Flag, GameInfo, GameData, CharacterCore, Character, ClientInfo, SpectatorInfo, Common, Explosion, Spawn, HammerHit, Death, SoundGlobal, SoundWorld, DamageInd } from "./snapshots";
|
|
9
10
|
|
|
10
11
|
import { MsgPacker } from './MsgPacker';
|
|
11
|
-
import { Snapshot } from './snapshot';
|
|
12
|
+
import { Item, Snapshot } from './snapshot';
|
|
12
13
|
import Huffman from "./huffman";
|
|
13
14
|
import { Game } from "./components/game";
|
|
15
|
+
import { SnapshotWrapper } from "./components/snapshot";
|
|
14
16
|
|
|
15
17
|
const huff = new Huffman();
|
|
16
18
|
|
|
@@ -118,9 +120,7 @@ interface chunk {
|
|
|
118
120
|
raw: Buffer,
|
|
119
121
|
extended_msgid?: Buffer;
|
|
120
122
|
}
|
|
121
|
-
|
|
122
|
-
return buff.toJSON().data.map(a => ('0' + (a & 0xff).toString(16)).slice(-2)).join("");
|
|
123
|
-
}
|
|
123
|
+
|
|
124
124
|
interface _packet {
|
|
125
125
|
twprotocol: { flags: number, ack: number, chunkAmount: number, size: number },
|
|
126
126
|
chunks: chunk[]
|
|
@@ -141,32 +141,6 @@ var messageUUIDs = {
|
|
|
141
141
|
"CAPABILITIES": Buffer.from([0xf6, 0x21, 0xa5, 0xa1, 0xf5, 0x85, 0x37, 0x75, 0x8e, 0x73, 0x41, 0xbe, 0xee, 0x79, 0xf2, 0xb2]),
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
-
function arrStartsWith(arr: number[], arrStart: number[], start = 0) {
|
|
145
|
-
arr.splice(0, start)
|
|
146
|
-
for (let i = 0; i < arrStart.length; i++) {
|
|
147
|
-
if (arr[i] == arrStart[i])
|
|
148
|
-
continue;
|
|
149
|
-
else return false;
|
|
150
|
-
}
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
declare interface PlayerInfo {
|
|
154
|
-
local: number,
|
|
155
|
-
client_id: number,
|
|
156
|
-
team: number,
|
|
157
|
-
score: number,
|
|
158
|
-
latency: number,
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
declare interface ClientInfo {
|
|
162
|
-
name: string,
|
|
163
|
-
clan: string,
|
|
164
|
-
country: number,
|
|
165
|
-
skin: string,
|
|
166
|
-
use_custom_color: number,
|
|
167
|
-
color_body: number,
|
|
168
|
-
color_feet: number,
|
|
169
|
-
}
|
|
170
144
|
declare interface iMessage {
|
|
171
145
|
team: number,
|
|
172
146
|
client_id: number,
|
|
@@ -210,6 +184,7 @@ export declare interface Client {
|
|
|
210
184
|
on(event: 'kill', listener: (kill: iKillMsg) => void): this;
|
|
211
185
|
on(event: 'motd', listener: (message: string) => void): this;
|
|
212
186
|
|
|
187
|
+
on(event: 'snapshot', listener: (items: Item[]) => void): this;
|
|
213
188
|
}
|
|
214
189
|
|
|
215
190
|
export class Client extends EventEmitter {
|
|
@@ -226,6 +201,8 @@ export class Client extends EventEmitter {
|
|
|
226
201
|
private time: number;
|
|
227
202
|
private SnapUnpacker: Snapshot;
|
|
228
203
|
|
|
204
|
+
public SnapshotUnpacker: SnapshotWrapper;
|
|
205
|
+
|
|
229
206
|
private PredGameTick: number;
|
|
230
207
|
private AckGameTick: number;
|
|
231
208
|
|
|
@@ -265,7 +242,7 @@ export class Client extends EventEmitter {
|
|
|
265
242
|
|
|
266
243
|
this.SnapshotParts = 0;
|
|
267
244
|
|
|
268
|
-
this.SnapUnpacker = new Snapshot();
|
|
245
|
+
this.SnapUnpacker = new Snapshot(this);
|
|
269
246
|
// this.eSnapHolder = [];
|
|
270
247
|
this.requestResend = false;
|
|
271
248
|
|
|
@@ -296,6 +273,7 @@ export class Client extends EventEmitter {
|
|
|
296
273
|
this.movement = new Movement();
|
|
297
274
|
|
|
298
275
|
this.game = new Game(this);
|
|
276
|
+
this.SnapshotUnpacker = new SnapshotWrapper(this);
|
|
299
277
|
|
|
300
278
|
|
|
301
279
|
}
|
|
@@ -348,7 +326,7 @@ export class Client extends EventEmitter {
|
|
|
348
326
|
chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
|
|
349
327
|
chunk.raw = packet.slice(1, chunk.bytes)
|
|
350
328
|
Object.values(messageUUIDs).forEach((a, i) => {
|
|
351
|
-
if (a.compare(packet.slice(0, 16)) == 0) {
|
|
329
|
+
if (a.byteLength >= 16 && a.compare(packet.slice(0, 16)) == 0) {
|
|
352
330
|
chunk.extended_msgid = a;
|
|
353
331
|
chunk.msg = Object.keys(messageUUIDs)[i];
|
|
354
332
|
}
|
|
@@ -360,8 +338,9 @@ export class Client extends EventEmitter {
|
|
|
360
338
|
return unpacked
|
|
361
339
|
}
|
|
362
340
|
|
|
363
|
-
|
|
364
|
-
|
|
341
|
+
|
|
342
|
+
/** Send a Control Msg to the server. (used for disconnect)*/
|
|
343
|
+
SendControlMsg(msg: number, ExtraMsg: string = "") {
|
|
365
344
|
this.lastSendTime = new Date().getTime();
|
|
366
345
|
return new Promise((resolve, reject) => {
|
|
367
346
|
if (this.socket) {
|
|
@@ -380,8 +359,9 @@ export class Client extends EventEmitter {
|
|
|
380
359
|
})
|
|
381
360
|
}
|
|
382
361
|
|
|
383
|
-
|
|
384
|
-
|
|
362
|
+
|
|
363
|
+
/** Send a Msg (or Msg[]) to the server.*/
|
|
364
|
+
SendMsgEx(Msgs: MsgPacker[] | MsgPacker) {
|
|
385
365
|
if (this.State == States.STATE_OFFLINE)
|
|
386
366
|
return;
|
|
387
367
|
if (!this.socket)
|
|
@@ -439,12 +419,14 @@ export class Client extends EventEmitter {
|
|
|
439
419
|
return;
|
|
440
420
|
this.socket.send(packet, 0, packet.length, this.port, this.host)
|
|
441
421
|
}
|
|
442
|
-
|
|
422
|
+
|
|
423
|
+
/** Queue a chunk (It will get sent in the next packet). */
|
|
443
424
|
QueueChunkEx(Msg: MsgPacker) {
|
|
444
425
|
this.queueChunkEx.push(Msg);
|
|
445
426
|
}
|
|
446
|
-
|
|
447
|
-
|
|
427
|
+
|
|
428
|
+
/** Send a Raw Buffer (as chunk) to the server. */
|
|
429
|
+
SendMsgRaw(chunks: Buffer[]) {
|
|
448
430
|
if (this.State == States.STATE_OFFLINE)
|
|
449
431
|
return;
|
|
450
432
|
if (!this.socket)
|
|
@@ -477,7 +459,7 @@ export class Client extends EventEmitter {
|
|
|
477
459
|
chunk.msg = messageTypes[packet[0]&1][chunk.msgid];
|
|
478
460
|
chunk.raw = packet.slice(1, chunk.bytes)
|
|
479
461
|
Object.values(messageUUIDs).forEach((a, i) => {
|
|
480
|
-
if (a.compare(packet.slice(0, 16)) === 0) {
|
|
462
|
+
if (a.byteLength >= 16 && a.compare(packet.slice(0, 16)) === 0) {
|
|
481
463
|
chunk.extended_msgid = a;
|
|
482
464
|
chunk.msg = Object.keys(messageUUIDs)[i];
|
|
483
465
|
}
|
|
@@ -485,8 +467,9 @@ export class Client extends EventEmitter {
|
|
|
485
467
|
return chunk;
|
|
486
468
|
}
|
|
487
469
|
|
|
488
|
-
|
|
489
|
-
|
|
470
|
+
|
|
471
|
+
/** Connect the client to the server. */
|
|
472
|
+
connect() {
|
|
490
473
|
this.State = States.STATE_CONNECTING;
|
|
491
474
|
|
|
492
475
|
let predTimer = setInterval(() => {
|
|
@@ -543,10 +526,10 @@ export class Client extends EventEmitter {
|
|
|
543
526
|
return;
|
|
544
527
|
clearInterval(connectInterval)
|
|
545
528
|
|
|
546
|
-
if (packet
|
|
547
|
-
if (packet.toString().includes("TKEN") || packet
|
|
529
|
+
if (packet[0] == 0x10) {
|
|
530
|
+
if (packet.toString().includes("TKEN") || packet[3] == 0x2) {
|
|
548
531
|
clearInterval(connectInterval);
|
|
549
|
-
this.TKEN =
|
|
532
|
+
this.TKEN = packet.slice(-4)
|
|
550
533
|
this.SendControlMsg(3);
|
|
551
534
|
this.State = States.STATE_LOADING; // loading state
|
|
552
535
|
this.receivedSnaps = 0;
|
|
@@ -557,7 +540,7 @@ export class Client extends EventEmitter {
|
|
|
557
540
|
|
|
558
541
|
var client_version = new MsgPacker(0, true, 1);
|
|
559
542
|
client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
|
|
560
|
-
let randomUuid = Buffer.
|
|
543
|
+
let randomUuid = Buffer.allocUnsafe(16);
|
|
561
544
|
|
|
562
545
|
randomBytes(16).copy(randomUuid);
|
|
563
546
|
|
|
@@ -571,13 +554,13 @@ export class Client extends EventEmitter {
|
|
|
571
554
|
}
|
|
572
555
|
|
|
573
556
|
this.SendMsgEx([client_version, info])
|
|
574
|
-
} else if (packet
|
|
557
|
+
} else if (packet[3] == 0x4) {
|
|
575
558
|
// disconnected
|
|
576
559
|
this.State = States.STATE_OFFLINE;
|
|
577
|
-
let reason: string = (unpackString(packet.
|
|
560
|
+
let reason: string = (unpackString(packet.slice(4)).result);
|
|
578
561
|
this.emit("disconnect", reason);
|
|
579
562
|
}
|
|
580
|
-
if (packet
|
|
563
|
+
if (packet[3] !== 0x0) { // keepalive
|
|
581
564
|
this.lastRecvTime = new Date().getTime();
|
|
582
565
|
}
|
|
583
566
|
} else {
|
|
@@ -611,8 +594,9 @@ export class Client extends EventEmitter {
|
|
|
611
594
|
|
|
612
595
|
})
|
|
613
596
|
this.sentChunkQueue.forEach((buff, i) => {
|
|
614
|
-
let
|
|
615
|
-
if (
|
|
597
|
+
let chunkFlags = (buff[0] >> 6) & 3;
|
|
598
|
+
if (chunkFlags & 1) {
|
|
599
|
+
let chunk = this.MsgToChunk(buff);
|
|
616
600
|
if (chunk.seq && chunk.seq >= this.ack)
|
|
617
601
|
this.sentChunkQueue.splice(i, 1);
|
|
618
602
|
}
|
|
@@ -672,7 +656,7 @@ export class Client extends EventEmitter {
|
|
|
672
656
|
this.PredGameTick = this.AckGameTick + 1;
|
|
673
657
|
|
|
674
658
|
// snapChunks.forEach(chunk => {
|
|
675
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
659
|
+
let unpacker = new MsgUnpacker(chunk.raw);
|
|
676
660
|
|
|
677
661
|
let NumParts = 1;
|
|
678
662
|
let Part = 0;
|
|
@@ -682,12 +666,12 @@ export class Client extends EventEmitter {
|
|
|
682
666
|
let Crc = 0;
|
|
683
667
|
let CompleteSize = 0;
|
|
684
668
|
|
|
685
|
-
if (chunk.
|
|
669
|
+
if (chunk.msgid == NETMSG_Sys.NETMSG_SNAP) {
|
|
686
670
|
NumParts = unpacker.unpackInt();
|
|
687
671
|
Part = unpacker.unpackInt();
|
|
688
672
|
}
|
|
689
673
|
|
|
690
|
-
if (chunk.
|
|
674
|
+
if (chunk.msgid != NETMSG_Sys.NETMSG_SNAPEMPTY) {
|
|
691
675
|
Crc = unpacker.unpackInt();
|
|
692
676
|
PartSize = unpacker.unpackInt();
|
|
693
677
|
}
|
|
@@ -703,7 +687,7 @@ export class Client extends EventEmitter {
|
|
|
703
687
|
}
|
|
704
688
|
|
|
705
689
|
// chunk.raw = Buffer.from(unpacker.remaining);
|
|
706
|
-
this.snaps[Part] =
|
|
690
|
+
this.snaps[Part] = unpacker.remaining;
|
|
707
691
|
|
|
708
692
|
this.SnapshotParts |= 1 << Part;
|
|
709
693
|
|
|
@@ -711,9 +695,9 @@ export class Client extends EventEmitter {
|
|
|
711
695
|
let mergedSnaps = Buffer.concat(this.snaps);
|
|
712
696
|
this.SnapshotParts = 0;
|
|
713
697
|
|
|
714
|
-
let snapUnpacked = this.SnapUnpacker.unpackSnapshot(mergedSnaps
|
|
698
|
+
let snapUnpacked = this.SnapUnpacker.unpackSnapshot(mergedSnaps, DeltaTick, GameTick, Crc);
|
|
715
699
|
|
|
716
|
-
this.emit("snapshot");
|
|
700
|
+
this.emit("snapshot", snapUnpacked.items);
|
|
717
701
|
this.AckGameTick = snapUnpacked.recvTick;
|
|
718
702
|
if (Math.abs(this.PredGameTick - this.AckGameTick) > 10)
|
|
719
703
|
this.PredGameTick = this.AckGameTick + 1;
|
|
@@ -736,7 +720,7 @@ export class Client extends EventEmitter {
|
|
|
736
720
|
if (chunk.msgid == NETMSG_Game.SV_VOTECLEAROPTIONS) {
|
|
737
721
|
this.VoteList = [];
|
|
738
722
|
} else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONLISTADD) {
|
|
739
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
723
|
+
let unpacker = new MsgUnpacker(chunk.raw)
|
|
740
724
|
let NumOptions = unpacker.unpackInt()
|
|
741
725
|
let list: string[] = [];
|
|
742
726
|
for (let i = 0; i < 15; i++) {
|
|
@@ -746,11 +730,11 @@ export class Client extends EventEmitter {
|
|
|
746
730
|
|
|
747
731
|
this.VoteList.push(...list);
|
|
748
732
|
} else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONADD) {
|
|
749
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
733
|
+
let unpacker = new MsgUnpacker(chunk.raw)
|
|
750
734
|
|
|
751
735
|
this.VoteList.push(unpacker.unpackString());
|
|
752
736
|
} else if (chunk.msgid == NETMSG_Game.SV_VOTEOPTIONREMOVE) {
|
|
753
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
737
|
+
let unpacker = new MsgUnpacker(chunk.raw)
|
|
754
738
|
|
|
755
739
|
let index = this.VoteList.indexOf(unpacker.unpackString());
|
|
756
740
|
|
|
@@ -761,7 +745,7 @@ export class Client extends EventEmitter {
|
|
|
761
745
|
|
|
762
746
|
// events
|
|
763
747
|
if (chunk.msgid == NETMSG_Game.SV_EMOTICON) {
|
|
764
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
748
|
+
let unpacker = new MsgUnpacker(chunk.raw);
|
|
765
749
|
let unpacked = {
|
|
766
750
|
client_id: unpacker.unpackInt(),
|
|
767
751
|
emoticon: unpacker.unpackInt()
|
|
@@ -769,8 +753,8 @@ export class Client extends EventEmitter {
|
|
|
769
753
|
|
|
770
754
|
if (unpacked.client_id != -1) {
|
|
771
755
|
unpacked.author = {
|
|
772
|
-
ClientInfo: this.
|
|
773
|
-
PlayerInfo: this.
|
|
756
|
+
ClientInfo: this.SnapshotUnpacker.getObjClientInfo(unpacked.client_id),
|
|
757
|
+
PlayerInfo: this.SnapshotUnpacker.getObjPlayerInfo(unpacked.client_id)
|
|
774
758
|
}
|
|
775
759
|
}
|
|
776
760
|
this.emit("emote", unpacked)
|
|
@@ -778,11 +762,11 @@ export class Client extends EventEmitter {
|
|
|
778
762
|
|
|
779
763
|
|
|
780
764
|
} else if (chunk.msgid == NETMSG_Game.SV_BROADCAST) {
|
|
781
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
765
|
+
let unpacker = new MsgUnpacker(chunk.raw);
|
|
782
766
|
|
|
783
767
|
this.emit("broadcast", unpacker.unpackString());
|
|
784
768
|
} if (chunk.msgid == NETMSG_Game.SV_CHAT) {
|
|
785
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
769
|
+
let unpacker = new MsgUnpacker(chunk.raw);
|
|
786
770
|
let unpacked: iMessage = {
|
|
787
771
|
team: unpacker.unpackInt(),
|
|
788
772
|
client_id: unpacker.unpackInt(),
|
|
@@ -791,27 +775,27 @@ export class Client extends EventEmitter {
|
|
|
791
775
|
|
|
792
776
|
if (unpacked.client_id != -1) {
|
|
793
777
|
unpacked.author = {
|
|
794
|
-
ClientInfo: this.
|
|
795
|
-
PlayerInfo: this.
|
|
778
|
+
ClientInfo: this.SnapshotUnpacker.getObjClientInfo(unpacked.client_id),
|
|
779
|
+
PlayerInfo: this.SnapshotUnpacker.getObjPlayerInfo(unpacked.client_id)
|
|
796
780
|
}
|
|
797
781
|
}
|
|
798
782
|
this.emit("message", unpacked)
|
|
799
783
|
} else if (chunk.msgid == NETMSG_Game.SV_KILLMSG) {
|
|
800
784
|
let unpacked: iKillMsg = {} as iKillMsg;
|
|
801
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
785
|
+
let unpacker = new MsgUnpacker(chunk.raw);
|
|
802
786
|
unpacked.killer_id = unpacker.unpackInt();
|
|
803
787
|
unpacked.victim_id = unpacker.unpackInt();
|
|
804
788
|
unpacked.weapon = unpacker.unpackInt();
|
|
805
789
|
unpacked.special_mode = unpacker.unpackInt();
|
|
806
790
|
if (unpacked.victim_id != -1 && unpacked.victim_id < 64) {
|
|
807
|
-
unpacked.victim = { ClientInfo: this.
|
|
791
|
+
unpacked.victim = { ClientInfo: this.SnapshotUnpacker.getObjClientInfo(unpacked.victim_id), PlayerInfo: this.SnapshotUnpacker.getObjPlayerInfo(unpacked.victim_id) }
|
|
808
792
|
|
|
809
793
|
}
|
|
810
794
|
if (unpacked.killer_id != -1 && unpacked.killer_id < 64)
|
|
811
|
-
unpacked.killer = { ClientInfo: this.
|
|
795
|
+
unpacked.killer = { ClientInfo: this.SnapshotUnpacker.getObjClientInfo(unpacked.killer_id), PlayerInfo: this.SnapshotUnpacker.getObjPlayerInfo(unpacked.killer_id) }
|
|
812
796
|
this.emit("kill", unpacked)
|
|
813
797
|
} else if (chunk.msgid == NETMSG_Game.SV_MOTD) {
|
|
814
|
-
let unpacker = new MsgUnpacker(chunk.raw
|
|
798
|
+
let unpacker = new MsgUnpacker(chunk.raw);
|
|
815
799
|
let message = unpacker.unpackString();
|
|
816
800
|
this.emit("motd", message);
|
|
817
801
|
}
|
|
@@ -833,8 +817,9 @@ export class Client extends EventEmitter {
|
|
|
833
817
|
})
|
|
834
818
|
}
|
|
835
819
|
|
|
836
|
-
|
|
837
|
-
|
|
820
|
+
|
|
821
|
+
/** Sending the input. (automatically done unless options.lightweight is on) */
|
|
822
|
+
sendInput(input = this.movement.input) {
|
|
838
823
|
if (this.State != States.STATE_ONLINE)
|
|
839
824
|
return;
|
|
840
825
|
|
|
@@ -843,30 +828,27 @@ export class Client extends EventEmitter {
|
|
|
843
828
|
inputMsg.AddInt(this.PredGameTick);
|
|
844
829
|
inputMsg.AddInt(40);
|
|
845
830
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
input.m_PrevWeapon
|
|
858
|
-
]
|
|
859
|
-
input_data.forEach(a => {
|
|
860
|
-
inputMsg.AddInt(a);
|
|
861
|
-
});
|
|
831
|
+
inputMsg.AddInt(input.m_Direction)
|
|
832
|
+
inputMsg.AddInt(input.m_TargetX)
|
|
833
|
+
inputMsg.AddInt(input.m_TargetY)
|
|
834
|
+
inputMsg.AddInt(input.m_Jump)
|
|
835
|
+
inputMsg.AddInt(input.m_Fire)
|
|
836
|
+
inputMsg.AddInt(input.m_Hook)
|
|
837
|
+
inputMsg.AddInt(input.m_PlayerFlags)
|
|
838
|
+
inputMsg.AddInt(input.m_WantedWeapon)
|
|
839
|
+
inputMsg.AddInt(input.m_NextWeapon)
|
|
840
|
+
inputMsg.AddInt(input.m_PrevWeapon)
|
|
841
|
+
|
|
862
842
|
this.SendMsgEx(inputMsg);
|
|
863
843
|
}
|
|
864
|
-
|
|
844
|
+
/** returns the movement object of the client */
|
|
845
|
+
get input() {
|
|
865
846
|
return this.movement.input;
|
|
866
847
|
}
|
|
867
848
|
|
|
868
|
-
|
|
869
|
-
Disconnect
|
|
849
|
+
|
|
850
|
+
/** Disconnect the client. */
|
|
851
|
+
Disconnect() {
|
|
870
852
|
return new Promise((resolve) => {
|
|
871
853
|
this.SendControlMsg(4).then(() => {
|
|
872
854
|
resolve(true);
|
|
@@ -878,46 +860,11 @@ export class Client extends EventEmitter {
|
|
|
878
860
|
})
|
|
879
861
|
}
|
|
880
862
|
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
let delta = this.SnapUnpacker.deltas.filter(_delta =>
|
|
884
|
-
_delta.type_id == 11
|
|
885
|
-
&& _delta.id == id
|
|
886
|
-
);
|
|
887
|
-
|
|
888
|
-
if (delta.length == 0)
|
|
889
|
-
return undefined;
|
|
890
|
-
return delta[0].parsed as ClientInfo;
|
|
891
|
-
// .sort((a, b) => a.id - b.id)
|
|
892
|
-
// .map(a => a.parsed as ClientInfo);
|
|
893
|
-
}
|
|
894
|
-
|
|
895
|
-
/* Get all client infos. */
|
|
896
|
-
get client_infos(): ClientInfo[] {
|
|
897
|
-
|
|
898
|
-
return this.SnapUnpacker.deltas.filter(_delta => _delta.type_id == 11)
|
|
899
|
-
.sort((a, b) => a.id - b.id)
|
|
900
|
-
.map(a => a.parsed as ClientInfo);
|
|
901
|
-
}
|
|
902
|
-
/* Get the player info from a specific player id. */
|
|
903
|
-
player_info(id: number) {
|
|
904
|
-
let delta = this.SnapUnpacker.deltas.filter(_delta =>
|
|
905
|
-
_delta.type_id == 10
|
|
906
|
-
&& _delta.id == id
|
|
907
|
-
);
|
|
908
|
-
|
|
909
|
-
if (delta.length == 0)
|
|
910
|
-
return undefined;
|
|
911
|
-
return delta[0].parsed as PlayerInfo;
|
|
912
|
-
}
|
|
913
|
-
/* Get all player infos. */
|
|
914
|
-
get player_infos(): PlayerInfo[] {
|
|
915
|
-
return this.SnapUnpacker.deltas.filter(_delta => _delta.type_id == 10)
|
|
916
|
-
.sort((a, b) => a.id - b.id)
|
|
917
|
-
.map(player => player.parsed as PlayerInfo);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
get VoteOptionList(): string[] {
|
|
863
|
+
/** Get all available vote options (for example for map voting) */
|
|
864
|
+
get VoteOptionList(): string[] {
|
|
921
865
|
return this.VoteList;
|
|
922
866
|
}
|
|
867
|
+
get rawSnapUnpacker(): Snapshot {
|
|
868
|
+
return this.SnapUnpacker;
|
|
869
|
+
}
|
|
923
870
|
}
|
package/lib/components/game.js
CHANGED
|
@@ -59,19 +59,19 @@ var Game = /** @class */ (function () {
|
|
|
59
59
|
packer.AddString(message);
|
|
60
60
|
this.send(packer);
|
|
61
61
|
};
|
|
62
|
-
|
|
62
|
+
/** Set the team of an bot. (-1 spectator team, 0 team red/normal team, 1 team blue) */
|
|
63
63
|
Game.prototype.SetTeam = function (team) {
|
|
64
64
|
var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SETTEAM, false, 1);
|
|
65
65
|
packer.AddInt(team);
|
|
66
66
|
this.send(packer);
|
|
67
67
|
};
|
|
68
|
-
|
|
68
|
+
/** Spectate an player, taking their id as parameter. pretty useless */
|
|
69
69
|
Game.prototype.SpectatorMode = function (SpectatorID) {
|
|
70
70
|
var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SETSPECTATORMODE, false, 1);
|
|
71
71
|
packer.AddInt(SpectatorID);
|
|
72
72
|
this.send(packer);
|
|
73
73
|
};
|
|
74
|
-
|
|
74
|
+
/** Change the player info */
|
|
75
75
|
Game.prototype.ChangePlayerInfo = function (playerInfo) {
|
|
76
76
|
var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false, 1);
|
|
77
77
|
packer.AddString(playerInfo.name);
|
|
@@ -83,18 +83,18 @@ var Game = /** @class */ (function () {
|
|
|
83
83
|
packer.AddInt(playerInfo.color_feet);
|
|
84
84
|
this.send(packer);
|
|
85
85
|
};
|
|
86
|
-
|
|
86
|
+
/** Kill */
|
|
87
87
|
Game.prototype.Kill = function () {
|
|
88
88
|
var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_KILL, false, 1);
|
|
89
89
|
this.send(packer);
|
|
90
90
|
};
|
|
91
|
-
|
|
91
|
+
/** Send emote */
|
|
92
92
|
Game.prototype.Emote = function (emote) {
|
|
93
93
|
var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_EMOTICON, false, 1);
|
|
94
94
|
packer.AddInt(emote);
|
|
95
95
|
this.send(packer);
|
|
96
96
|
};
|
|
97
|
-
|
|
97
|
+
/** Vote for an already running vote (true = f3 / false = f4) */
|
|
98
98
|
Game.prototype.Vote = function (vote) {
|
|
99
99
|
var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_VOTE, false, 1);
|
|
100
100
|
packer.AddInt(vote ? 1 : -1);
|
|
@@ -107,24 +107,24 @@ var Game = /** @class */ (function () {
|
|
|
107
107
|
packer.AddString(Reason);
|
|
108
108
|
this.send(packer);
|
|
109
109
|
};
|
|
110
|
-
|
|
110
|
+
/** Call a vote for an server option (for example ddnet maps) */
|
|
111
111
|
Game.prototype.CallVoteOption = function (Value, Reason) {
|
|
112
112
|
this.CallVote("option", Value, Reason);
|
|
113
113
|
};
|
|
114
|
-
|
|
114
|
+
/** Call a vote to kick a player. Requires the player id */
|
|
115
115
|
Game.prototype.CallVoteKick = function (PlayerID, Reason) {
|
|
116
116
|
this.CallVote("kick", PlayerID, Reason);
|
|
117
117
|
};
|
|
118
|
-
|
|
118
|
+
/** Call a vote to set a player in spectator mode. Requires the player id */
|
|
119
119
|
Game.prototype.CallVoteSpectate = function (PlayerID, Reason) {
|
|
120
120
|
this.CallVote("spectate", PlayerID, Reason);
|
|
121
121
|
};
|
|
122
|
-
/** probably some verification of using ddnet client
|
|
122
|
+
/** probably some verification of using ddnet client. */
|
|
123
123
|
Game.prototype.IsDDNetLegacy = function () {
|
|
124
124
|
var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_ISDDNETLEGACY, false, 1);
|
|
125
125
|
this.send(packer);
|
|
126
126
|
};
|
|
127
|
-
|
|
127
|
+
/** returns the ping in ms (as a promise) */
|
|
128
128
|
Game.prototype.Ping = function () {
|
|
129
129
|
var _this = this;
|
|
130
130
|
return new Promise(function (resolve, reject) {
|
package/lib/components/game.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import { MsgPacker } from "../MsgPacker";
|
|
3
|
+
import { PlayerInput, PlayerInfo, Projectile, Laser, Pickup, Flag, GameInfo, GameData, CharacterCore, Character, ClientInfo, SpectatorInfo, Common, Explosion, Spawn, HammerHit, Death, SoundGlobal, SoundWorld, DamageInd } from "../snapshots";
|
|
3
4
|
|
|
4
5
|
import { Client } from "../client";
|
|
5
6
|
enum NETMSGTYPE { EX, SV_MOTD, SV_BROADCAST, SV_CHAT, SV_KILLMSG, SV_SOUNDGLOBAL, SV_TUNEPARAMS, SV_EXTRAPROJECTILE, SV_READYTOENTER, SV_WEAPONPICKUP, SV_EMOTICON, SV_VOTECLEAROPTIONS, SV_VOTEOPTIONLISTADD, SV_VOTEOPTIONADD, SV_VOTEOPTIONREMOVE, SV_VOTESET, SV_VOTESTATUS, CL_SAY, CL_SETTEAM, CL_SETSPECTATORMODE, CL_STARTINFO, CL_CHANGEINFO, CL_KILL, CL_EMOTICON, CL_VOTE, CL_CALLVOTE, CL_ISDDNETLEGACY, SV_DDRACETIMELEGACY, SV_RECORDLEGACY, UNUSED, SV_TEAMSSTATELEGACY, CL_SHOWOTHERSLEGACY, NUM };
|
|
@@ -29,23 +30,26 @@ export class Game {
|
|
|
29
30
|
this.send(packer);
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
/** Set the team of an bot. (-1 spectator team, 0 team red/normal team, 1 team blue) */
|
|
35
|
+
SetTeam(team: number) {
|
|
34
36
|
var packer = new MsgPacker(NETMSGTYPE.CL_SETTEAM, false, 1);
|
|
35
37
|
packer.AddInt(team);
|
|
36
38
|
this.send(packer);
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
|
|
42
|
+
/** Spectate an player, taking their id as parameter. pretty useless */
|
|
43
|
+
SpectatorMode(SpectatorID: number) {
|
|
41
44
|
var packer = new MsgPacker(NETMSGTYPE.CL_SETSPECTATORMODE, false, 1);
|
|
42
45
|
packer.AddInt(SpectatorID);
|
|
43
46
|
this.send(packer);
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
|
|
51
|
+
/** Change the player info */
|
|
52
|
+
ChangePlayerInfo(playerInfo: ClientInfo) {
|
|
49
53
|
var packer = new MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false, 1);
|
|
50
54
|
packer.AddString(playerInfo.name);
|
|
51
55
|
packer.AddString(playerInfo.clan);
|
|
@@ -57,21 +61,24 @@ export class Game {
|
|
|
57
61
|
this.send(packer);
|
|
58
62
|
}
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
Kill
|
|
64
|
+
|
|
65
|
+
/** Kill */
|
|
66
|
+
Kill() {
|
|
62
67
|
var packer = new MsgPacker(NETMSGTYPE.CL_KILL, false, 1);
|
|
63
68
|
this.send(packer);
|
|
64
69
|
}
|
|
65
70
|
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
|
|
72
|
+
/** Send emote */
|
|
73
|
+
Emote(emote: number) {
|
|
68
74
|
var packer = new MsgPacker(NETMSGTYPE.CL_EMOTICON, false, 1);
|
|
69
75
|
packer.AddInt(emote);
|
|
70
76
|
this.send(packer);
|
|
71
77
|
}
|
|
72
78
|
|
|
73
|
-
|
|
74
|
-
Vote
|
|
79
|
+
|
|
80
|
+
/** Vote for an already running vote (true = f3 / false = f4) */
|
|
81
|
+
Vote(vote: boolean) {
|
|
75
82
|
var packer = new MsgPacker(NETMSGTYPE.CL_VOTE, false, 1);
|
|
76
83
|
packer.AddInt(vote ? 1 : -1);
|
|
77
84
|
this.send(packer);
|
|
@@ -84,27 +91,32 @@ export class Game {
|
|
|
84
91
|
packer.AddString(Reason);
|
|
85
92
|
this.send(packer);
|
|
86
93
|
}
|
|
87
|
-
|
|
88
|
-
|
|
94
|
+
|
|
95
|
+
/** Call a vote for an server option (for example ddnet maps) */
|
|
96
|
+
CallVoteOption(Value: string, Reason: string) {
|
|
89
97
|
this.CallVote("option", Value, Reason)
|
|
90
98
|
}
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
|
|
100
|
+
/** Call a vote to kick a player. Requires the player id */
|
|
101
|
+
CallVoteKick(PlayerID: string|number, Reason: string) {
|
|
93
102
|
this.CallVote("kick", PlayerID, Reason)
|
|
94
103
|
}
|
|
95
|
-
|
|
96
|
-
|
|
104
|
+
|
|
105
|
+
/** Call a vote to set a player in spectator mode. Requires the player id */
|
|
106
|
+
CallVoteSpectate(PlayerID: string|number, Reason: string) {
|
|
97
107
|
this.CallVote("spectate", PlayerID, Reason)
|
|
98
108
|
}
|
|
99
109
|
|
|
100
110
|
|
|
101
|
-
|
|
111
|
+
|
|
112
|
+
/** probably some verification of using ddnet client. */
|
|
102
113
|
IsDDNetLegacy() {
|
|
103
114
|
var packer = new MsgPacker(NETMSGTYPE.CL_ISDDNETLEGACY, false, 1);
|
|
104
115
|
this.send(packer);
|
|
105
116
|
}
|
|
106
|
-
|
|
107
|
-
|
|
117
|
+
|
|
118
|
+
/** returns the ping in ms (as a promise) */
|
|
119
|
+
Ping(): Promise<number> {
|
|
108
120
|
return new Promise((resolve, reject) => {
|
|
109
121
|
var packer = new MsgPacker(22, true, 0);
|
|
110
122
|
let startTime = new Date().getTime();
|
|
File without changes
|
|
File without changes
|