teeworlds 2.1.5 → 2.1.9

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/client.js ADDED
@@ -0,0 +1,588 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ extendStatics(d, b);
11
+ function __() { this.constructor = d; }
12
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
13
+ };
14
+ })();
15
+ var __importDefault = (this && this.__importDefault) || function (mod) {
16
+ return (mod && mod.__esModule) ? mod : { "default": mod };
17
+ };
18
+ Object.defineProperty(exports, "__esModule", { value: true });
19
+ exports.Client = void 0;
20
+ var crypto_1 = require("crypto");
21
+ var dgram_1 = __importDefault(require("dgram"));
22
+ var stream_1 = require("stream");
23
+ var MsgUnpacker_1 = require("./MsgUnpacker");
24
+ var movement_1 = __importDefault(require("./movement"));
25
+ var MsgPacker_1 = require("./MsgPacker");
26
+ var snapshot_1 = require("./snapshot");
27
+ var huffman_1 = __importDefault(require("./huffman"));
28
+ var huff = new huffman_1.default();
29
+ var SnapUnpacker = new snapshot_1.Snapshot();
30
+ var States;
31
+ (function (States) {
32
+ States[States["STATE_OFFLINE"] = 0] = "STATE_OFFLINE";
33
+ States[States["STATE_CONNECTING"] = 1] = "STATE_CONNECTING";
34
+ States[States["STATE_LOADING"] = 2] = "STATE_LOADING";
35
+ States[States["STATE_ONLINE"] = 3] = "STATE_ONLINE";
36
+ States[States["STATE_DEMOPLAYBACK"] = 4] = "STATE_DEMOPLAYBACK";
37
+ States[States["STATE_QUITTING"] = 5] = "STATE_QUITTING";
38
+ States[States["STATE_RESTARTING"] = 6] = "STATE_RESTARTING";
39
+ })(States || (States = {}));
40
+ ;
41
+ var NETMSGTYPE;
42
+ (function (NETMSGTYPE) {
43
+ NETMSGTYPE[NETMSGTYPE["EX"] = 0] = "EX";
44
+ NETMSGTYPE[NETMSGTYPE["SV_MOTD"] = 1] = "SV_MOTD";
45
+ NETMSGTYPE[NETMSGTYPE["SV_BROADCAST"] = 2] = "SV_BROADCAST";
46
+ NETMSGTYPE[NETMSGTYPE["SV_CHAT"] = 3] = "SV_CHAT";
47
+ NETMSGTYPE[NETMSGTYPE["SV_KILLMSG"] = 4] = "SV_KILLMSG";
48
+ NETMSGTYPE[NETMSGTYPE["SV_SOUNDGLOBAL"] = 5] = "SV_SOUNDGLOBAL";
49
+ NETMSGTYPE[NETMSGTYPE["SV_TUNEPARAMS"] = 6] = "SV_TUNEPARAMS";
50
+ NETMSGTYPE[NETMSGTYPE["SV_EXTRAPROJECTILE"] = 7] = "SV_EXTRAPROJECTILE";
51
+ NETMSGTYPE[NETMSGTYPE["SV_READYTOENTER"] = 8] = "SV_READYTOENTER";
52
+ NETMSGTYPE[NETMSGTYPE["SV_WEAPONPICKUP"] = 9] = "SV_WEAPONPICKUP";
53
+ NETMSGTYPE[NETMSGTYPE["SV_EMOTICON"] = 10] = "SV_EMOTICON";
54
+ NETMSGTYPE[NETMSGTYPE["SV_VOTECLEAROPTIONS"] = 11] = "SV_VOTECLEAROPTIONS";
55
+ NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONLISTADD"] = 12] = "SV_VOTEOPTIONLISTADD";
56
+ NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONADD"] = 13] = "SV_VOTEOPTIONADD";
57
+ NETMSGTYPE[NETMSGTYPE["SV_VOTEOPTIONREMOVE"] = 14] = "SV_VOTEOPTIONREMOVE";
58
+ NETMSGTYPE[NETMSGTYPE["SV_VOTESET"] = 15] = "SV_VOTESET";
59
+ NETMSGTYPE[NETMSGTYPE["SV_VOTESTATUS"] = 16] = "SV_VOTESTATUS";
60
+ NETMSGTYPE[NETMSGTYPE["CL_SAY"] = 17] = "CL_SAY";
61
+ NETMSGTYPE[NETMSGTYPE["CL_SETTEAM"] = 18] = "CL_SETTEAM";
62
+ NETMSGTYPE[NETMSGTYPE["CL_SETSPECTATORMODE"] = 19] = "CL_SETSPECTATORMODE";
63
+ NETMSGTYPE[NETMSGTYPE["CL_STARTINFO"] = 20] = "CL_STARTINFO";
64
+ NETMSGTYPE[NETMSGTYPE["CL_CHANGEINFO"] = 21] = "CL_CHANGEINFO";
65
+ NETMSGTYPE[NETMSGTYPE["CL_KILL"] = 22] = "CL_KILL";
66
+ NETMSGTYPE[NETMSGTYPE["CL_EMOTICON"] = 23] = "CL_EMOTICON";
67
+ NETMSGTYPE[NETMSGTYPE["CL_VOTE"] = 24] = "CL_VOTE";
68
+ NETMSGTYPE[NETMSGTYPE["CL_CALLVOTE"] = 25] = "CL_CALLVOTE";
69
+ NETMSGTYPE[NETMSGTYPE["CL_ISDDNETLEGACY"] = 26] = "CL_ISDDNETLEGACY";
70
+ NETMSGTYPE[NETMSGTYPE["SV_DDRACETIMELEGACY"] = 27] = "SV_DDRACETIMELEGACY";
71
+ NETMSGTYPE[NETMSGTYPE["SV_RECORDLEGACY"] = 28] = "SV_RECORDLEGACY";
72
+ NETMSGTYPE[NETMSGTYPE["UNUSED"] = 29] = "UNUSED";
73
+ NETMSGTYPE[NETMSGTYPE["SV_TEAMSSTATELEGACY"] = 30] = "SV_TEAMSSTATELEGACY";
74
+ NETMSGTYPE[NETMSGTYPE["CL_SHOWOTHERSLEGACY"] = 31] = "CL_SHOWOTHERSLEGACY";
75
+ NETMSGTYPE[NETMSGTYPE["NUM"] = 32] = "NUM";
76
+ })(NETMSGTYPE || (NETMSGTYPE = {}));
77
+ var items;
78
+ (function (items) {
79
+ items[items["OBJ_EX"] = 0] = "OBJ_EX";
80
+ items[items["OBJ_PLAYER_INPUT"] = 1] = "OBJ_PLAYER_INPUT";
81
+ items[items["OBJ_PROJECTILE"] = 2] = "OBJ_PROJECTILE";
82
+ items[items["OBJ_LASER"] = 3] = "OBJ_LASER";
83
+ items[items["OBJ_PICKUP"] = 4] = "OBJ_PICKUP";
84
+ items[items["OBJ_FLAG"] = 5] = "OBJ_FLAG";
85
+ items[items["OBJ_GAME_INFO"] = 6] = "OBJ_GAME_INFO";
86
+ items[items["OBJ_GAME_DATA"] = 7] = "OBJ_GAME_DATA";
87
+ items[items["OBJ_CHARACTER_CORE"] = 8] = "OBJ_CHARACTER_CORE";
88
+ items[items["OBJ_CHARACTER"] = 9] = "OBJ_CHARACTER";
89
+ items[items["OBJ_PLAYER_INFO"] = 10] = "OBJ_PLAYER_INFO";
90
+ items[items["OBJ_CLIENT_INFO"] = 11] = "OBJ_CLIENT_INFO";
91
+ items[items["OBJ_SPECTATOR_INFO"] = 12] = "OBJ_SPECTATOR_INFO";
92
+ items[items["EVENT_COMMON"] = 13] = "EVENT_COMMON";
93
+ items[items["EVENT_EXPLOSION"] = 14] = "EVENT_EXPLOSION";
94
+ items[items["EVENT_SPAWN"] = 15] = "EVENT_SPAWN";
95
+ items[items["EVENT_HAMMERHIT"] = 16] = "EVENT_HAMMERHIT";
96
+ items[items["EVENT_DEATH"] = 17] = "EVENT_DEATH";
97
+ items[items["EVENT_SOUND_GLOBAL"] = 18] = "EVENT_SOUND_GLOBAL";
98
+ items[items["EVENT_SOUND_WORLD"] = 19] = "EVENT_SOUND_WORLD";
99
+ items[items["EVENT_DAMAGE_INDICATOR"] = 20] = "EVENT_DAMAGE_INDICATOR";
100
+ })(items || (items = {}));
101
+ function toHexStream(buff) {
102
+ return buff.toJSON().data.map(function (a) { return ('0' + (a & 0xff).toString(16)).slice(-2); }).join("");
103
+ }
104
+ var messageTypes = [
105
+ ["none, starts at 1", "SV_MOTD", "SV_BROADCAST", "SV_CHAT", "SV_KILL_MSG", "SV_SOUND_GLOBAL", "SV_TUNE_PARAMS", "SV_EXTRA_PROJECTILE", "SV_READY_TO_ENTER", "SV_WEAPON_PICKUP", "SV_EMOTICON", "SV_VOTE_CLEAR_OPTIONS", "SV_VOTE_OPTION_LIST_ADD", "SV_VOTE_OPTION_ADD", "SV_VOTE_OPTION_REMOVE", "SV_VOTE_SET", "SV_VOTE_STATUS", "CL_SAY", "CL_SET_TEAM", "CL_SET_SPECTATOR_MODE", "CL_START_INFO", "CL_CHANGE_INFO", "CL_KILL", "CL_EMOTICON", "CL_VOTE", "CL_CALL_VOTE", "CL_IS_DDNET", "SV_DDRACE_TIME", "SV_RECORD", "UNUSED", "SV_TEAMS_STATE", "CL_SHOW_OTHERS_LEGACY"],
106
+ ["none, starts at 1", "INFO", "MAP_CHANGE", "MAP_DATA", "CON_READY", "SNAP", "SNAP_EMPTY", "SNAP_SINGLE", "INPUT_TIMING", "RCON_AUTH_STATUS", "RCON_LINE", "READY", "ENTER_GAME", "INPUT", "RCON_CMD", "RCON_AUTH", "REQUEST_MAP_DATA", "PING", "PING_REPLY", "RCON_CMD_ADD", "RCON_CMD_REMOVE"]
107
+ ];
108
+ var messageUUIDs = {
109
+ "WHAT_IS": Buffer.from([0x24, 0x5e, 0x50, 0x97, 0x9f, 0xe0, 0x39, 0xd6, 0xbf, 0x7d, 0x9a, 0x29, 0xe1, 0x69, 0x1e, 0x4c]),
110
+ "IT_IS": Buffer.from([0x69, 0x54, 0x84, 0x7e, 0x2e, 0x87, 0x36, 0x03, 0xb5, 0x62, 0x36, 0xda, 0x29, 0xed, 0x1a, 0xca]),
111
+ "I_DONT_KNOW": Buffer.from([0x41, 0x69, 0x11, 0xb5, 0x79, 0x73, 0x33, 0xbf, 0x8d, 0x52, 0x7b, 0xf0, 0x1e, 0x51, 0x9c, 0xf0]),
112
+ "RCON_TYPE": Buffer.from([0x12, 0x81, 0x0e, 0x1f, 0xa1, 0xdb, 0x33, 0x78, 0xb4, 0xfb, 0x16, 0x4e, 0xd6, 0x50, 0x59, 0x26]),
113
+ "MAP_DETAILS": Buffer.from([0xf9, 0x11, 0x7b, 0x3c, 0x80, 0x39, 0x34, 0x16, 0x9f, 0xc0, 0xae, 0xf2, 0xbc, 0xb7, 0x5c, 0x03]),
114
+ "CLIENT_VERSION": Buffer.from([0x8c, 0x00, 0x13, 0x04, 0x84, 0x61, 0x3e, 0x47, 0x87, 0x87, 0xf6, 0x72, 0xb3, 0x83, 0x5b, 0xd4]),
115
+ "CAPABILITIES": Buffer.from([0xf6, 0x21, 0xa5, 0xa1, 0xf5, 0x85, 0x37, 0x75, 0x8e, 0x73, 0x41, 0xbe, 0xee, 0x79, 0xf2, 0xb2]),
116
+ };
117
+ function arrStartsWith(arr, arrStart, start) {
118
+ if (start === void 0) { start = 0; }
119
+ arr.splice(0, start);
120
+ for (var i = 0; i < arrStart.length; i++) {
121
+ if (arr[i] == arrStart[i])
122
+ continue;
123
+ else
124
+ return false;
125
+ }
126
+ return true;
127
+ }
128
+ var Client = /** @class */ (function (_super) {
129
+ __extends(Client, _super);
130
+ function Client(ip, port, nickname, options) {
131
+ var _this = _super.call(this) || this;
132
+ _this.host = ip;
133
+ _this.port = port;
134
+ _this.name = nickname;
135
+ _this.AckGameTick = 0;
136
+ _this.PredGameTick = 0;
137
+ if (options)
138
+ _this.options = options;
139
+ _this.timer = 0;
140
+ _this.movement = new movement_1.default();
141
+ _this.snaps = [];
142
+ _this.client_infos = [];
143
+ _this.player_infos = [];
144
+ _this.sentChunkQueue = [];
145
+ _this.State = States.STATE_OFFLINE; // 0 = offline; 1 = STATE_CONNECTING = 1, STATE_LOADING = 2, STATE_ONLINE = 3
146
+ _this.ack = 0; // ack of messages the client has received
147
+ _this.clientAck = 0; // ack of messages the client has sent
148
+ _this.receivedSnaps = 0; /* wait for 2 snaps before seeing self as connected */
149
+ _this.lastMsg = "";
150
+ _this.socket = dgram_1.default.createSocket("udp4");
151
+ _this.socket.bind();
152
+ _this.TKEN = Buffer.from([255, 255, 255, 255]);
153
+ _this.time = new Date().getTime() + 2000; // time (used for keepalives, start to send keepalives after 2 seconds)
154
+ _this.lastSendTime = new Date().getTime();
155
+ return _this;
156
+ }
157
+ Client.prototype.Unpack = function (packet) {
158
+ var unpacked = { twprotocol: { flags: packet[0], ack: packet[1], chunkAmount: packet[2], size: packet.byteLength - 3 }, chunks: [] };
159
+ 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)
160
+ return unpacked;
161
+ packet = packet.slice(3);
162
+ if (unpacked.twprotocol.flags & 128) {
163
+ packet = huff.decompress(packet);
164
+ if (packet.length == 1 && packet[0] == -1)
165
+ return unpacked;
166
+ }
167
+ for (var i = 0; i < unpacked.twprotocol.chunkAmount; i++) {
168
+ var chunk = {};
169
+ chunk.bytes = ((packet[0] & 0x3f) << 4) | (packet[1] & ((1 << 4) - 1));
170
+ chunk.flags = (packet[0] >> 6) & 3;
171
+ chunk.sequence = -1;
172
+ if (chunk.flags & 1) {
173
+ chunk.seq = ((packet[1] & 0xf0) << 2) | packet[2];
174
+ packet = packet.slice(3); // remove flags & size
175
+ }
176
+ else
177
+ packet = packet.slice(2);
178
+ chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
179
+ chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
180
+ chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
181
+ chunk.raw = packet.slice(1, chunk.bytes);
182
+ Object.values(messageUUIDs).forEach(function (a, i) {
183
+ if (a.compare(packet.slice(0, 16)) == 0) {
184
+ chunk.extended_msgid = a;
185
+ chunk.msg = Object.keys(messageUUIDs)[i];
186
+ }
187
+ });
188
+ packet = packet.slice(chunk.bytes);
189
+ unpacked.chunks.push(chunk);
190
+ }
191
+ return unpacked;
192
+ };
193
+ Client.prototype.SendControlMsg = function (msg, ExtraMsg) {
194
+ var _this = this;
195
+ if (ExtraMsg === void 0) { ExtraMsg = ""; }
196
+ this.lastSendTime = new Date().getTime();
197
+ return new Promise(function (resolve, reject) {
198
+ if (_this.socket) {
199
+ var latestBuf = Buffer.from([0x10 + (((16 << 4) & 0xf0) | ((_this.ack >> 8) & 0xf)), _this.ack & 0xff, 0x00, msg]);
200
+ latestBuf = Buffer.concat([latestBuf, Buffer.from(ExtraMsg), _this.TKEN]); // move header (latestBuf), optional extraMsg & TKEN into 1 buffer
201
+ _this.socket.send(latestBuf, 0, latestBuf.length, _this.port, _this.host, function (err, bytes) {
202
+ resolve(bytes);
203
+ });
204
+ }
205
+ setTimeout(function () { resolve("failed, rip"); }, 2000);
206
+ /* after 2 seconds it was probably not able to send,
207
+ so when sending a quit message the user doesnt
208
+ stay stuck not being able to ctrl + c
209
+ */
210
+ });
211
+ };
212
+ Client.prototype.SendMsgEx = function (Msgs, Flags) {
213
+ var _this = this;
214
+ if (this.State == States.STATE_OFFLINE)
215
+ return;
216
+ if (!this.socket)
217
+ return;
218
+ var _Msgs;
219
+ if (Msgs instanceof Array)
220
+ _Msgs = Msgs;
221
+ else
222
+ _Msgs = [Msgs];
223
+ this.lastSendTime = new Date().getTime();
224
+ var header = [];
225
+ _Msgs.forEach(function (Msg, index) {
226
+ header[index] = Buffer.alloc((Flags & 1 ? 3 : 2));
227
+ header[index][0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
228
+ header[index][1] = (Msg.size & 0xf);
229
+ if (Flags & 1) {
230
+ _this.clientAck = (_this.clientAck + 1) % (1 << 10);
231
+ header[index][1] |= (_this.clientAck >> 2) & 0xf0;
232
+ header[index][2] = _this.clientAck & 0xff;
233
+ header[index][0] = (((Flags | 2) & 3) << 6) | ((Msg.size >> 4) & 0x3f); // 2 is resend flag (ugly hack for queue)
234
+ _this.sentChunkQueue.push(Buffer.concat([header[index], Msg.buffer]));
235
+ header[index][0] = (((Flags) & 3) << 6) | ((Msg.size >> 4) & 0x3f);
236
+ }
237
+ });
238
+ var packetHeader = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff, _Msgs.length]);
239
+ var chunks = Buffer.from([]);
240
+ _Msgs.forEach(function (Msg, index) {
241
+ chunks = Buffer.concat([chunks, Buffer.from(header[index]), Msg.buffer]);
242
+ });
243
+ var packet = Buffer.concat([(packetHeader), chunks, this.TKEN]);
244
+ this.socket.send(packet, 0, packet.length, this.port, this.host);
245
+ };
246
+ Client.prototype.SendMsgRaw = function (chunks) {
247
+ if (this.State == States.STATE_OFFLINE)
248
+ return;
249
+ if (!this.socket)
250
+ return;
251
+ this.lastSendTime = new Date().getTime();
252
+ var packetHeader = Buffer.from([0x0 + (((16 << 4) & 0xf0) | ((this.ack >> 8) & 0xf)), this.ack & 0xff, chunks.length]);
253
+ var packet = Buffer.concat([(packetHeader), Buffer.concat(chunks), this.TKEN]);
254
+ this.socket.send(packet, 0, packet.length, this.port, this.host);
255
+ };
256
+ Client.prototype.MsgToChunk = function (packet) {
257
+ var chunk = {};
258
+ chunk.bytes = ((packet[0] & 0x3f) << 4) | (packet[1] & ((1 << 4) - 1));
259
+ chunk.flags = (packet[0] >> 6) & 3;
260
+ chunk.sequence = -1;
261
+ if (chunk.flags & 1) {
262
+ chunk.seq = ((packet[1] & 0xf0) << 2) | packet[2];
263
+ packet = packet.slice(3); // remove flags & size
264
+ }
265
+ else
266
+ packet = packet.slice(2);
267
+ chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
268
+ chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
269
+ chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
270
+ chunk.raw = packet.slice(1, chunk.bytes);
271
+ Object.values(messageUUIDs).forEach(function (a, i) {
272
+ if (a.compare(packet.slice(0, 16)) === 0) {
273
+ chunk.extended_msgid = a;
274
+ chunk.msg = Object.keys(messageUUIDs)[i];
275
+ }
276
+ });
277
+ return chunk;
278
+ };
279
+ Client.prototype.connect = function () {
280
+ var _this = this;
281
+ this.State = States.STATE_CONNECTING;
282
+ var predTimer = setInterval(function () {
283
+ if (_this.State == States.STATE_ONLINE) {
284
+ if (_this.AckGameTick > 0)
285
+ _this.PredGameTick++;
286
+ }
287
+ else if (_this.State == States.STATE_OFFLINE)
288
+ clearInterval(predTimer);
289
+ }, 20);
290
+ this.SendControlMsg(1, "TKEN");
291
+ var connectInterval = setInterval(function () {
292
+ if (_this.State == States.STATE_CONNECTING)
293
+ _this.SendControlMsg(1, "TKEN");
294
+ else
295
+ clearInterval(connectInterval);
296
+ }, 500);
297
+ var inputInterval = setInterval(function () {
298
+ if (_this.State == States.STATE_OFFLINE)
299
+ clearInterval(inputInterval);
300
+ if (_this.State != States.STATE_ONLINE)
301
+ return;
302
+ _this.time = new Date().getTime();
303
+ _this.sendInput();
304
+ }, 500);
305
+ var resendTimeout = setInterval(function () {
306
+ if (_this.State != States.STATE_OFFLINE) {
307
+ if (((new Date().getTime()) - _this.lastSendTime) > 900 && _this.sentChunkQueue.length > 0) {
308
+ _this.SendMsgRaw([_this.sentChunkQueue[0]]);
309
+ }
310
+ }
311
+ else
312
+ clearInterval(resendTimeout);
313
+ }, 1000);
314
+ this.time = new Date().getTime() + 2000; // start sending keepalives after 2s
315
+ if (this.socket)
316
+ this.socket.on("message", function (a, rinfo) {
317
+ var _a, _b, _c, _d, _e, _f;
318
+ if (_this.State == 0 || rinfo.address != _this.host || rinfo.port != _this.port)
319
+ return;
320
+ clearInterval(connectInterval);
321
+ if (a.toJSON().data[0] == 0x10) {
322
+ if (a.toString().includes("TKEN") || a.toJSON().data[3] == 0x2) {
323
+ clearInterval(connectInterval);
324
+ _this.TKEN = Buffer.from(a.toJSON().data.slice(a.toJSON().data.length - 4, a.toJSON().data.length));
325
+ _this.SendControlMsg(3);
326
+ _this.State = States.STATE_LOADING; // loading state
327
+ _this.receivedSnaps = 0;
328
+ var info = new MsgPacker_1.MsgPacker(1, true);
329
+ info.AddString("0.6 626fce9a778df4d4");
330
+ info.AddString(((_a = _this.options) === null || _a === void 0 ? void 0 : _a.password) === undefined ? "" : (_b = _this.options) === null || _b === void 0 ? void 0 : _b.password); // password
331
+ var client_version = new MsgPacker_1.MsgPacker(0, true);
332
+ client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
333
+ var randomUuid = Buffer.alloc(16);
334
+ crypto_1.randomBytes(16).copy(randomUuid);
335
+ client_version.AddBuffer(randomUuid);
336
+ if (((_c = _this.options) === null || _c === void 0 ? void 0 : _c.ddnet_version) !== undefined) {
337
+ client_version.AddInt((_d = _this.options) === null || _d === void 0 ? void 0 : _d.ddnet_version.version);
338
+ client_version.AddString("DDNet " + ((_e = _this.options) === null || _e === void 0 ? void 0 : _e.ddnet_version.release_version));
339
+ }
340
+ else {
341
+ client_version.AddInt(16003);
342
+ client_version.AddString("DDNet 16.0.3");
343
+ }
344
+ _this.SendMsgEx([client_version, info], 1);
345
+ }
346
+ else if (a.toJSON().data[3] == 0x4) {
347
+ // disconnected
348
+ _this.State = States.STATE_OFFLINE;
349
+ var reason = (MsgUnpacker_1.unpackString(a.toJSON().data.slice(4)).result);
350
+ _this.emit("disconnect", reason);
351
+ }
352
+ }
353
+ var unpacked = _this.Unpack(a);
354
+ unpacked.chunks.forEach(function (a) {
355
+ if (a.flags & 1) { // vital
356
+ if (a.seq != undefined && a.seq != -1)
357
+ _this.ack = a.seq;
358
+ }
359
+ });
360
+ _this.sentChunkQueue.forEach(function (buff, i) {
361
+ var chunk = _this.MsgToChunk(buff);
362
+ if (chunk.flags & 1) {
363
+ if (chunk.seq && chunk.seq < _this.ack) {
364
+ _this.sentChunkQueue.splice(i, 1);
365
+ }
366
+ }
367
+ });
368
+ var snapChunks = unpacked.chunks.filter(function (a) { return a.msg === "SNAP" || a.msg === "SNAP_SINGLE" || a.msg === "SNAP_EMPTY"; });
369
+ if (snapChunks.length > 0) {
370
+ var part = 0;
371
+ var num_parts = 1;
372
+ snapChunks.forEach(function (chunk) {
373
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(chunk.raw.toJSON().data);
374
+ var AckGameTick = unpacker.unpackInt();
375
+ if (AckGameTick > _this.AckGameTick) {
376
+ _this.AckGameTick = AckGameTick;
377
+ if (Math.abs(_this.PredGameTick - _this.AckGameTick) > 10)
378
+ _this.PredGameTick = AckGameTick + 1;
379
+ }
380
+ // chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining);
381
+ var DeltaTick = AckGameTick - unpacker.unpackInt();
382
+ var num_parts = 1;
383
+ var part = 0;
384
+ if (chunk.msg === "SNAP") {
385
+ // chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // delta tick
386
+ num_parts = unpacker.unpackInt();
387
+ // chunk.raw = Buffer.from(unpackInt(chunk?.raw?.toJSON().data).remaining); // num parts
388
+ part = unpacker.unpackInt();
389
+ }
390
+ var crc = 0;
391
+ var part_size = 0;
392
+ if (chunk.msg != "SNAP_EMPTY") {
393
+ crc = unpacker.unpackInt(); // crc
394
+ part_size = unpacker.unpackInt();
395
+ }
396
+ if (part === 0 || _this.snaps.length > 30) {
397
+ _this.snaps = [];
398
+ }
399
+ chunk.raw = Buffer.from(unpacker.remaining);
400
+ _this.snaps.push(chunk.raw);
401
+ if ((num_parts - 1) === part && _this.snaps.length === num_parts) {
402
+ var mergedSnaps = Buffer.concat(_this.snaps);
403
+ // mergedSnaps = Buffer.from(unpackInt(mergedSnaps.toJSON().data).remaining);
404
+ var snapUnpacked = SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, 1);
405
+ // console.log(snapUnpacked.items, toHexStream(mergedSnaps));
406
+ snapUnpacked.items.forEach(function (a, i) {
407
+ if (a.type_id === items.OBJ_CLIENT_INFO) {
408
+ _this.client_infos[a.id] = a.parsed;
409
+ // if (this.client_infos[a.id].name.includes("�") || this.client_infos[a.id].clan.includes("�")) {
410
+ // console.log("bad name", this.client_infos[a.id], toHexStream(mergedSnaps), chunk, AckGameTick, DeltaTick, crc, part_size);
411
+ // }
412
+ // console.log(this.client_infos[a.id])
413
+ }
414
+ });
415
+ }
416
+ });
417
+ }
418
+ var chunkMessages = unpacked.chunks.map(function (a) { return a.msg; });
419
+ if (chunkMessages.includes("SV_CHAT")) {
420
+ var chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_CHAT"; });
421
+ chat.forEach(function (a) {
422
+ if (a.msg == "SV_CHAT") {
423
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
424
+ var unpacked = {
425
+ team: unpacker.unpackInt(),
426
+ client_id: unpacker.unpackInt(),
427
+ message: unpacker.unpackString()
428
+ };
429
+ if (unpacked.client_id != -1)
430
+ unpacked.author = {
431
+ ClientInfo: _this.client_infos[unpacked.client_id],
432
+ PlayerInfo: _this.player_infos[unpacked.client_id]
433
+ };
434
+ _this.emit("message", unpacked);
435
+ }
436
+ });
437
+ }
438
+ if (chunkMessages.includes("SV_KILL_MSG")) {
439
+ var chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_KILL_MSG"; });
440
+ chat.forEach(function (a) {
441
+ if (a.msg == "SV_KILL_MSG") {
442
+ var unpacked = {};
443
+ var unpacker = new MsgUnpacker_1.MsgUnpacker(a.raw.toJSON().data);
444
+ unpacked.killer_id = unpacker.unpackInt();
445
+ unpacked.victim_id = unpacker.unpackInt();
446
+ unpacked.weapon = unpacker.unpackInt();
447
+ unpacked.special_mode = unpacker.unpackInt();
448
+ if (unpacked.victim_id != -1)
449
+ unpacked.victim = { ClientInfo: _this.client_infos[unpacked.victim_id], PlayerInfo: _this.player_infos[unpacked.victim_id] };
450
+ if (unpacked.killer_id != -1)
451
+ unpacked.killer = { ClientInfo: _this.client_infos[unpacked.killer_id], PlayerInfo: _this.player_infos[unpacked.killer_id] };
452
+ _this.emit("kill", unpacked);
453
+ }
454
+ });
455
+ }
456
+ if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
457
+ var Msg = new MsgPacker_1.MsgPacker(15, true); /* entergame */
458
+ _this.SendMsgEx(Msg, 1);
459
+ }
460
+ else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
461
+ // send ready
462
+ var Msg = new MsgPacker_1.MsgPacker(14, true); /* ready */
463
+ _this.SendMsgEx(Msg, 1);
464
+ }
465
+ else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY") || unpacked.chunks[0] && chunkMessages.includes("SV_MOTD"))) {
466
+ var info = new MsgPacker_1.MsgPacker(20, false);
467
+ if ((_f = _this.options) === null || _f === void 0 ? void 0 : _f.identity) {
468
+ info.AddString(_this.options.identity.name);
469
+ info.AddString(_this.options.identity.clan);
470
+ info.AddInt(_this.options.identity.country);
471
+ info.AddString(_this.options.identity.skin);
472
+ info.AddInt(_this.options.identity.use_custom_color);
473
+ info.AddInt(_this.options.identity.color_body);
474
+ info.AddInt(_this.options.identity.color_feet);
475
+ }
476
+ else {
477
+ info.AddString(_this.name); /* name */
478
+ info.AddString(""); /* clan */
479
+ info.AddInt(-1); /* country */
480
+ info.AddString("greyfox"); /* skin */
481
+ info.AddInt(1); /* use custom color */
482
+ info.AddInt(10346103); /* color body */
483
+ info.AddInt(65535); /* color feet */
484
+ }
485
+ _this.SendMsgEx(info, 1);
486
+ }
487
+ else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
488
+ var info = new MsgPacker_1.MsgPacker(23, true);
489
+ _this.SendMsgEx(info, 1);
490
+ }
491
+ if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
492
+ _this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
493
+ if (_this.receivedSnaps == 2) {
494
+ if (_this.State != States.STATE_ONLINE)
495
+ _this.emit('connected');
496
+ _this.State = States.STATE_ONLINE;
497
+ }
498
+ }
499
+ if (new Date().getTime() - _this.time >= 1000 && _this.State == States.STATE_ONLINE) {
500
+ _this.time = new Date().getTime();
501
+ _this.SendControlMsg(0);
502
+ }
503
+ });
504
+ };
505
+ Client.prototype.sendInput = function (input) {
506
+ if (input === void 0) { input = this.movement.input; }
507
+ if (this.State != States.STATE_ONLINE)
508
+ return;
509
+ var inputMsg = new MsgPacker_1.MsgPacker(16, true);
510
+ inputMsg.AddInt(this.AckGameTick);
511
+ inputMsg.AddInt(this.PredGameTick);
512
+ inputMsg.AddInt(40);
513
+ var input_data = [
514
+ input.m_Direction,
515
+ input.m_TargetX,
516
+ input.m_TargetY,
517
+ input.m_Jump,
518
+ input.m_Fire,
519
+ input.m_Hook,
520
+ input.m_PlayerFlags,
521
+ input.m_WantedWeapon,
522
+ input.m_NextWeapon,
523
+ input.m_PrevWeapon
524
+ ];
525
+ input_data.forEach(function (a) {
526
+ inputMsg.AddInt(a);
527
+ });
528
+ this.SendMsgEx(inputMsg, 0);
529
+ };
530
+ Object.defineProperty(Client.prototype, "input", {
531
+ get: function () {
532
+ return this.movement.input;
533
+ },
534
+ enumerable: false,
535
+ configurable: true
536
+ });
537
+ Client.prototype.Disconnect = function () {
538
+ var _this = this;
539
+ return new Promise(function (resolve) {
540
+ _this.SendControlMsg(4).then(function () {
541
+ resolve(true);
542
+ if (_this.socket)
543
+ _this.socket.close();
544
+ _this.socket = undefined;
545
+ _this.State = States.STATE_OFFLINE;
546
+ });
547
+ });
548
+ };
549
+ Client.prototype.Say = function (message, team) {
550
+ if (team === void 0) { team = false; }
551
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SAY, false);
552
+ packer.AddInt(team ? 1 : 0); // team
553
+ packer.AddString(message);
554
+ this.SendMsgEx(packer, 1);
555
+ };
556
+ Client.prototype.Vote = function (vote) {
557
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_VOTE, false);
558
+ packer.AddInt(vote ? 1 : 0);
559
+ this.SendMsgEx(packer, 1);
560
+ };
561
+ Client.prototype.ChangePlayerInfo = function (playerInfo) {
562
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_CHANGEINFO, false);
563
+ packer.AddString(playerInfo.name); //m_pName);
564
+ packer.AddString(playerInfo.clan); //m_pClan);
565
+ packer.AddInt(playerInfo.country); //m_Country);
566
+ packer.AddString(playerInfo.skin); //m_pSkin);
567
+ packer.AddInt(playerInfo.use_custom_color ? 1 : 0); //m_UseCustomColor);
568
+ packer.AddInt(playerInfo.color_body); //m_ColorBody);
569
+ packer.AddInt(playerInfo.color_feet); //m_ColorFeet);
570
+ this.SendMsgEx(packer, 1);
571
+ };
572
+ Client.prototype.Kill = function () {
573
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_KILL, false);
574
+ this.SendMsgEx(packer, 1);
575
+ };
576
+ Client.prototype.ChangeTeam = function (team) {
577
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_SETTEAM, false);
578
+ packer.AddInt(team);
579
+ this.SendMsgEx(packer, 1);
580
+ };
581
+ Client.prototype.Emote = function (emote) {
582
+ var packer = new MsgPacker_1.MsgPacker(NETMSGTYPE.CL_EMOTICON, false);
583
+ packer.AddInt(emote);
584
+ this.SendMsgEx(packer, 1);
585
+ };
586
+ return Client;
587
+ }(stream_1.EventEmitter));
588
+ exports.Client = Client;