teeworlds 2.0.2 → 2.0.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/lib/client.js +212 -228
- package/lib/client.ts +19 -26
- package/lib/huffman.js +236 -0
- package/lib/huffman.ts +342 -0
- package/package.json +1 -1
- package/lib/huffman.py +0 -224
package/lib/client.js
CHANGED
|
@@ -54,10 +54,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
54
54
|
var crypto_1 = require("crypto");
|
|
55
55
|
var dgram_1 = __importDefault(require("dgram"));
|
|
56
56
|
var stream_1 = require("stream");
|
|
57
|
-
var child_process_1 = require("child_process");
|
|
58
57
|
var MsgUnpacker_1 = __importDefault(require("./MsgUnpacker"));
|
|
59
58
|
var MsgPacker_1 = __importDefault(require("./MsgPacker"));
|
|
60
59
|
var snapshot_1 = require("./snapshot");
|
|
60
|
+
var huffman_1 = __importDefault(require("./huffman"));
|
|
61
|
+
var huff = new huffman_1.default();
|
|
61
62
|
var SnapUnpacker = new snapshot_1.Snapshot();
|
|
62
63
|
var NETMSGTYPE;
|
|
63
64
|
(function (NETMSGTYPE) {
|
|
@@ -122,26 +123,6 @@ var items;
|
|
|
122
123
|
function toHexStream(buff) {
|
|
123
124
|
return buff.toJSON().data.map(function (a) { return ('0' + (a & 0xff).toString(16)).slice(-2); }).join("");
|
|
124
125
|
}
|
|
125
|
-
function decompress(buff) {
|
|
126
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
127
|
-
return __generator(this, function (_a) {
|
|
128
|
-
return [2 /*return*/, new Promise(function (resolve) {
|
|
129
|
-
// get hex stream
|
|
130
|
-
var hexStream = toHexStream(buff);
|
|
131
|
-
var ls = child_process_1.spawn('python', [__dirname + '\\huffman.py', hexStream, "-decompress"]);
|
|
132
|
-
ls.stdout.on('data', function (data) {
|
|
133
|
-
resolve(Buffer.from(eval(data.toString()))); // convert stdout array to actual array, then convert the array to Buffer & return it
|
|
134
|
-
});
|
|
135
|
-
setTimeout(function () {
|
|
136
|
-
ls.stdin.end();
|
|
137
|
-
ls.stdout.destroy();
|
|
138
|
-
ls.stderr.destroy();
|
|
139
|
-
resolve(Buffer.from([]));
|
|
140
|
-
}, 750);
|
|
141
|
-
})];
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
}
|
|
145
126
|
var messageTypes = [
|
|
146
127
|
["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"],
|
|
147
128
|
["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"]
|
|
@@ -193,48 +174,42 @@ var Client = /** @class */ (function (_super) {
|
|
|
193
174
|
return __awaiter(this, void 0, void 0, function () {
|
|
194
175
|
var unpacked, i, chunk;
|
|
195
176
|
return __generator(this, function (_a) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
return [4 /*yield*/, decompress(packet)];
|
|
204
|
-
case 1:
|
|
205
|
-
packet = _a.sent();
|
|
206
|
-
if (packet.length == 1 && packet[0] == -1)
|
|
207
|
-
return [2 /*return*/, unpacked];
|
|
208
|
-
_a.label = 2;
|
|
209
|
-
case 2:
|
|
210
|
-
// return unpacked;
|
|
211
|
-
for (i = 0; i < unpacked.twprotocol.chunkAmount; i++) {
|
|
212
|
-
chunk = {};
|
|
213
|
-
chunk.bytes = ((packet[0] & 0x3f) << 4) | (packet[1] & ((1 << 4) - 1)); // idk what this shit is but it works
|
|
214
|
-
chunk.flags = (packet[0] >> 6) & 3;
|
|
215
|
-
chunk.sequence = -1;
|
|
216
|
-
if (chunk.flags & 1) {
|
|
217
|
-
chunk.seq = ((packet[1] & 0xf0) << 2) | packet[2];
|
|
218
|
-
packet = packet.slice(3); // remove flags & size
|
|
219
|
-
}
|
|
220
|
-
else
|
|
221
|
-
packet = packet.slice(2);
|
|
222
|
-
chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
|
|
223
|
-
chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
|
|
224
|
-
chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
|
|
225
|
-
chunk.raw = packet.slice(1, chunk.bytes);
|
|
226
|
-
Object.values(messageUUIDs).forEach(function (a, i) {
|
|
227
|
-
if (a.compare(packet.slice(0, 16)) == 0) {
|
|
228
|
-
chunk.extended_msgid = a;
|
|
229
|
-
// chunk.type = 'sys';
|
|
230
|
-
chunk.msg = Object.keys(messageUUIDs)[i];
|
|
231
|
-
}
|
|
232
|
-
});
|
|
233
|
-
packet = packet.slice(chunk.bytes); // +1 cuz it adds an extra \x00 for easier parsing i guess
|
|
234
|
-
unpacked.chunks.push(chunk);
|
|
235
|
-
}
|
|
177
|
+
unpacked = { twprotocol: { flags: packet[0], ack: packet[1], chunkAmount: packet[2], size: packet.byteLength - 3 }, chunks: [] };
|
|
178
|
+
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)
|
|
179
|
+
return [2 /*return*/, unpacked];
|
|
180
|
+
packet = packet.slice(3);
|
|
181
|
+
if (unpacked.twprotocol.flags & 128) {
|
|
182
|
+
packet = huff.decompress(packet);
|
|
183
|
+
if (packet.length == 1 && packet[0] == -1)
|
|
236
184
|
return [2 /*return*/, unpacked];
|
|
237
185
|
}
|
|
186
|
+
// return unpacked;
|
|
187
|
+
for (i = 0; i < unpacked.twprotocol.chunkAmount; i++) {
|
|
188
|
+
chunk = {};
|
|
189
|
+
chunk.bytes = ((packet[0] & 0x3f) << 4) | (packet[1] & ((1 << 4) - 1)); // idk what this shit is but it works
|
|
190
|
+
chunk.flags = (packet[0] >> 6) & 3;
|
|
191
|
+
chunk.sequence = -1;
|
|
192
|
+
if (chunk.flags & 1) {
|
|
193
|
+
chunk.seq = ((packet[1] & 0xf0) << 2) | packet[2];
|
|
194
|
+
packet = packet.slice(3); // remove flags & size
|
|
195
|
+
}
|
|
196
|
+
else
|
|
197
|
+
packet = packet.slice(2);
|
|
198
|
+
chunk.type = packet[0] & 1 ? "sys" : "game"; // & 1 = binary, ****_***1. e.g 0001_0111 sys, 0001_0110 game
|
|
199
|
+
chunk.msgid = (packet[0] - (packet[0] & 1)) / 2;
|
|
200
|
+
chunk.msg = messageTypes[packet[0] & 1][chunk.msgid];
|
|
201
|
+
chunk.raw = packet.slice(1, chunk.bytes);
|
|
202
|
+
Object.values(messageUUIDs).forEach(function (a, i) {
|
|
203
|
+
if (a.compare(packet.slice(0, 16)) == 0) {
|
|
204
|
+
chunk.extended_msgid = a;
|
|
205
|
+
// chunk.type = 'sys';
|
|
206
|
+
chunk.msg = Object.keys(messageUUIDs)[i];
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
packet = packet.slice(chunk.bytes); // +1 cuz it adds an extra \x00 for easier parsing i guess
|
|
210
|
+
unpacked.chunks.push(chunk);
|
|
211
|
+
}
|
|
212
|
+
return [2 /*return*/, unpacked];
|
|
238
213
|
});
|
|
239
214
|
});
|
|
240
215
|
};
|
|
@@ -242,11 +217,13 @@ var Client = /** @class */ (function (_super) {
|
|
|
242
217
|
var _this = this;
|
|
243
218
|
if (ExtraMsg === void 0) { ExtraMsg = ""; }
|
|
244
219
|
return new Promise(function (resolve, reject) {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
220
|
+
if (_this.socket) {
|
|
221
|
+
var latestBuf = Buffer.from([0x10 + (((16 << 4) & 0xf0) | ((_this.ack >> 8) & 0xf)), _this.ack & 0xff, 0x00, msg]);
|
|
222
|
+
latestBuf = Buffer.concat([latestBuf, Buffer.from(ExtraMsg), _this.TKEN]); // move header (latestBuf), optional extraMsg & TKEN into 1 buffer
|
|
223
|
+
_this.socket.send(latestBuf, 0, latestBuf.length, _this.port, _this.host, function (err, bytes) {
|
|
224
|
+
resolve(bytes);
|
|
225
|
+
});
|
|
226
|
+
}
|
|
250
227
|
setTimeout(function () { resolve("failed, rip"); }, 2000);
|
|
251
228
|
/* after 2 seconds it was probably not able to send,
|
|
252
229
|
so when sending a quit message the user doesnt
|
|
@@ -257,6 +234,8 @@ var Client = /** @class */ (function (_super) {
|
|
|
257
234
|
Client.prototype.SendMsgEx = function (Msg, Flags) {
|
|
258
235
|
if (this.State == -1)
|
|
259
236
|
throw new Error("Client is not connected");
|
|
237
|
+
if (!this.socket)
|
|
238
|
+
return;
|
|
260
239
|
var header = [];
|
|
261
240
|
header[0] = ((Flags & 3) << 6) | ((Msg.size >> 4) & 0x3f);
|
|
262
241
|
header[1] = (Msg.size & 0xf);
|
|
@@ -273,6 +252,8 @@ var Client = /** @class */ (function (_super) {
|
|
|
273
252
|
var _this = this;
|
|
274
253
|
if (this.State == -1)
|
|
275
254
|
throw new Error("Client is not connected");
|
|
255
|
+
if (!this.socket)
|
|
256
|
+
return;
|
|
276
257
|
var header = [];
|
|
277
258
|
Msgs.forEach(function (Msg, index) {
|
|
278
259
|
header[index] = new Array(2);
|
|
@@ -302,184 +283,187 @@ var Client = /** @class */ (function (_super) {
|
|
|
302
283
|
clearInterval(connectInterval);
|
|
303
284
|
}, 500);
|
|
304
285
|
this.time = new Date().getTime() + 2000; // start sending keepalives after 2s
|
|
305
|
-
this.socket
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
unpacked.
|
|
315
|
-
|
|
316
|
-
if (a.
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
286
|
+
if (this.socket)
|
|
287
|
+
this.socket.on("message", function (a) { return __awaiter(_this, void 0, void 0, function () {
|
|
288
|
+
var unpacked, chunkMessages, chat, chat, info, client_version, randomUuid, reason, Msg, Msg, info, info, chunks, part_1, num_parts_1;
|
|
289
|
+
var _this = this;
|
|
290
|
+
return __generator(this, function (_a) {
|
|
291
|
+
switch (_a.label) {
|
|
292
|
+
case 0: return [4 /*yield*/, this.Unpack(a)];
|
|
293
|
+
case 1:
|
|
294
|
+
unpacked = _a.sent();
|
|
295
|
+
if (unpacked.twprotocol.flags != 128 && unpacked.twprotocol.ack) {
|
|
296
|
+
unpacked.chunks.forEach(function (a) {
|
|
297
|
+
if (a.msg && !a.msg.startsWith("SNAP")) {
|
|
298
|
+
if (a.seq != undefined && a.seq != -1)
|
|
299
|
+
_this.ack = a.seq;
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
chunkMessages = unpacked.chunks.map(function (a) { return a.msg; });
|
|
304
|
+
if (chunkMessages.includes("SV_CHAT")) {
|
|
305
|
+
chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_CHAT"; });
|
|
306
|
+
chat.forEach(function (a) {
|
|
307
|
+
if (a.msg == "SV_CHAT") {
|
|
308
|
+
var unpacked = {};
|
|
309
|
+
unpacked.team = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).result;
|
|
310
|
+
var remaining = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).remaining;
|
|
311
|
+
unpacked.client_id = MsgUnpacker_1.default.unpackInt(remaining).result;
|
|
312
|
+
remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
|
|
313
|
+
unpacked.message = MsgUnpacker_1.default.unpackString(remaining).result;
|
|
314
|
+
if (unpacked.client_id != -1)
|
|
315
|
+
unpacked.author = { ClientInfo: _this.client_infos[unpacked.client_id], PlayerInfo: _this.player_infos[unpacked.client_id] };
|
|
316
|
+
// console.log(unpacked)
|
|
317
|
+
_this.emit("message", unpacked);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
if (chunkMessages.includes("SV_KILL_MSG")) {
|
|
322
|
+
chat = unpacked.chunks.filter(function (a) { return a.msg == "SV_KILL_MSG"; });
|
|
323
|
+
chat.forEach(function (a) {
|
|
324
|
+
if (a.msg == "SV_KILL_MSG") {
|
|
325
|
+
var unpacked = {};
|
|
326
|
+
unpacked.killer_id = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).result;
|
|
327
|
+
var remaining = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).remaining;
|
|
328
|
+
unpacked.victim_id = MsgUnpacker_1.default.unpackInt(remaining).result;
|
|
329
|
+
remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
|
|
330
|
+
unpacked.weapon = MsgUnpacker_1.default.unpackInt(remaining).result;
|
|
331
|
+
remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
|
|
332
|
+
unpacked.special_mode = MsgUnpacker_1.default.unpackInt(remaining).result;
|
|
333
|
+
if (unpacked.victim_id != -1)
|
|
334
|
+
unpacked.victim = { ClientInfo: _this.client_infos[unpacked.victim_id], PlayerInfo: _this.player_infos[unpacked.victim_id] };
|
|
335
|
+
if (unpacked.killer_id != -1)
|
|
336
|
+
unpacked.killer = { ClientInfo: _this.client_infos[unpacked.killer_id], PlayerInfo: _this.player_infos[unpacked.killer_id] };
|
|
337
|
+
// console.log(unpacked)
|
|
338
|
+
_this.emit("kill", unpacked);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
if (a.toJSON().data[0] == 0x10) {
|
|
343
|
+
if (a.toString().includes("TKEN") || arrStartsWith(a.toJSON().data, [0x10, 0x0, 0x0, 0x0])) {
|
|
344
|
+
clearInterval(connectInterval);
|
|
345
|
+
this.TKEN = Buffer.from(a.toJSON().data.slice(a.toJSON().data.length - 4, a.toJSON().data.length));
|
|
346
|
+
this.SendControlMsg(3);
|
|
347
|
+
this.State = 2; // loading state
|
|
348
|
+
info = new MsgPacker_1.default(1, true);
|
|
349
|
+
info.AddString("0.6 626fce9a778df4d4");
|
|
350
|
+
info.AddString(""); // password
|
|
351
|
+
client_version = new MsgPacker_1.default(0, true);
|
|
352
|
+
client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
|
|
353
|
+
randomUuid = new Uint8Array(16);
|
|
354
|
+
crypto_1.randomBytes(16).copy(randomUuid);
|
|
355
|
+
client_version.AddBuffer(Buffer.from(randomUuid));
|
|
356
|
+
client_version.AddInt(15091);
|
|
357
|
+
client_version.AddString("DDNet 15.9.1");
|
|
358
|
+
this.SendMsgExWithChunks([client_version, info], 1);
|
|
336
359
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
var unpacked = {};
|
|
344
|
-
unpacked.killer_id = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).result;
|
|
345
|
-
var remaining = MsgUnpacker_1.default.unpackInt(a.raw.toJSON().data).remaining;
|
|
346
|
-
unpacked.victim_id = MsgUnpacker_1.default.unpackInt(remaining).result;
|
|
347
|
-
remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
|
|
348
|
-
unpacked.weapon = MsgUnpacker_1.default.unpackInt(remaining).result;
|
|
349
|
-
remaining = MsgUnpacker_1.default.unpackInt(remaining).remaining;
|
|
350
|
-
unpacked.special_mode = MsgUnpacker_1.default.unpackInt(remaining).result;
|
|
351
|
-
if (unpacked.victim_id != -1)
|
|
352
|
-
unpacked.victim = { ClientInfo: _this.client_infos[unpacked.victim_id], PlayerInfo: _this.player_infos[unpacked.victim_id] };
|
|
353
|
-
if (unpacked.killer_id != -1)
|
|
354
|
-
unpacked.killer = { ClientInfo: _this.client_infos[unpacked.killer_id], PlayerInfo: _this.player_infos[unpacked.killer_id] };
|
|
355
|
-
// console.log(unpacked)
|
|
356
|
-
_this.emit("kill", unpacked);
|
|
360
|
+
else if (a.toJSON().data[3] == 0x4) {
|
|
361
|
+
// disconnected
|
|
362
|
+
this.State = 0;
|
|
363
|
+
reason = (MsgUnpacker_1.default.unpackString(a.toJSON().data.slice(4)).result);
|
|
364
|
+
this.State = -1;
|
|
365
|
+
this.emit("disconnect", reason);
|
|
357
366
|
}
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
if (a.toJSON().data[0] == 0x10) {
|
|
361
|
-
if (a.toString().includes("TKEN") || arrStartsWith(a.toJSON().data, [0x10, 0x0, 0x0, 0x0])) {
|
|
362
|
-
clearInterval(connectInterval);
|
|
363
|
-
this.TKEN = Buffer.from(a.toJSON().data.slice(a.toJSON().data.length - 4, a.toJSON().data.length));
|
|
364
|
-
this.SendControlMsg(3);
|
|
365
|
-
this.State = 2; // loading state
|
|
366
|
-
info = new MsgPacker_1.default(1, true);
|
|
367
|
-
info.AddString("0.6 626fce9a778df4d4");
|
|
368
|
-
info.AddString(""); // password
|
|
369
|
-
client_version = new MsgPacker_1.default(0, true);
|
|
370
|
-
client_version.AddBuffer(Buffer.from("8c00130484613e478787f672b3835bd4", 'hex'));
|
|
371
|
-
randomUuid = new Uint8Array(16);
|
|
372
|
-
crypto_1.randomBytes(16).copy(randomUuid);
|
|
373
|
-
client_version.AddBuffer(Buffer.from(randomUuid));
|
|
374
|
-
client_version.AddInt(15091);
|
|
375
|
-
client_version.AddString("DDNet 15.9.1");
|
|
376
|
-
this.SendMsgExWithChunks([client_version, info], 1);
|
|
377
367
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
this.
|
|
381
|
-
reason = (MsgUnpacker_1.default.unpackString(a.toJSON().data.slice(4)).result);
|
|
382
|
-
this.State = -1;
|
|
383
|
-
this.emit("disconnect", reason);
|
|
368
|
+
if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
|
|
369
|
+
Msg = new MsgPacker_1.default(15, true);
|
|
370
|
+
this.SendMsgEx(Msg, 1);
|
|
384
371
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
this.SendMsgEx(Msg, 1);
|
|
389
|
-
}
|
|
390
|
-
else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
|
|
391
|
-
Msg = new MsgPacker_1.default(14, true);
|
|
392
|
-
this.SendMsgEx(Msg, 1);
|
|
393
|
-
}
|
|
394
|
-
else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY") || unpacked.chunks[0] && chunkMessages.includes("SV_MOTD"))) {
|
|
395
|
-
info = new MsgPacker_1.default(20, false);
|
|
396
|
-
info.AddString(this.name); /* name */
|
|
397
|
-
info.AddString(""); /* clan */
|
|
398
|
-
info.AddInt(-1); /* country */
|
|
399
|
-
info.AddString("greyfox"); /* skin */
|
|
400
|
-
info.AddInt(1); /* use custom color */
|
|
401
|
-
info.AddInt(10346103); /* color body */
|
|
402
|
-
info.AddInt(65535); /* color feet */
|
|
403
|
-
this.SendMsgEx(info, 1);
|
|
404
|
-
}
|
|
405
|
-
else if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
|
|
406
|
-
if (this.State != 3) {
|
|
407
|
-
this.emit('connected');
|
|
372
|
+
else if ((unpacked.chunks[0] && chunkMessages.includes("CAPABILITIES") || unpacked.chunks[0] && chunkMessages.includes("MAP_CHANGE"))) {
|
|
373
|
+
Msg = new MsgPacker_1.default(14, true);
|
|
374
|
+
this.SendMsgEx(Msg, 1);
|
|
408
375
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
376
|
+
else if ((unpacked.chunks[0] && chunkMessages.includes("CON_READY") || unpacked.chunks[0] && chunkMessages.includes("SV_MOTD"))) {
|
|
377
|
+
info = new MsgPacker_1.default(20, false);
|
|
378
|
+
info.AddString(this.name); /* name */
|
|
379
|
+
info.AddString(""); /* clan */
|
|
380
|
+
info.AddInt(-1); /* country */
|
|
381
|
+
info.AddString("greyfox"); /* skin */
|
|
382
|
+
info.AddInt(1); /* use custom color */
|
|
383
|
+
info.AddInt(10346103); /* color body */
|
|
384
|
+
info.AddInt(65535); /* color feet */
|
|
385
|
+
this.SendMsgEx(info, 1);
|
|
386
|
+
}
|
|
387
|
+
else if (unpacked.chunks[0] && chunkMessages.includes("SV_READY_TO_ENTER")) {
|
|
388
|
+
if (this.State != 3) {
|
|
419
389
|
this.emit('connected');
|
|
390
|
+
}
|
|
420
391
|
this.State = 3;
|
|
421
392
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
393
|
+
else if (unpacked.chunks[0] && chunkMessages.includes("PING")) {
|
|
394
|
+
info = new MsgPacker_1.default(23, true);
|
|
395
|
+
this.SendMsgEx(info, 1);
|
|
396
|
+
}
|
|
397
|
+
if (chunkMessages.includes("SNAP") || chunkMessages.includes("SNAP_EMPTY") || chunkMessages.includes("SNAP_SINGLE")) {
|
|
398
|
+
this.receivedSnaps++; /* wait for 2 ss before seeing self as connected */
|
|
399
|
+
if (this.receivedSnaps >= 2) {
|
|
400
|
+
if (this.State != 3)
|
|
401
|
+
this.emit('connected');
|
|
402
|
+
this.State = 3;
|
|
403
|
+
}
|
|
404
|
+
chunks = unpacked.chunks.filter(function (a) { return a.msg == "SNAP" || a.msg == "SNAP_SINGLE" || a.msg == "SNAP_EMPTY"; });
|
|
405
|
+
if (chunks.length > 0) {
|
|
406
|
+
part_1 = 0;
|
|
407
|
+
num_parts_1 = 1;
|
|
408
|
+
chunks.forEach(function (chunk) {
|
|
409
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
410
|
+
var AckGameTick = (MsgUnpacker_1.default.unpackInt(chunk.raw.toJSON().data).result);
|
|
411
|
+
chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_a = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _a === void 0 ? void 0 : _a.toJSON().data).remaining);
|
|
412
|
+
var DeltaTick = MsgUnpacker_1.default.unpackInt((_b = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _b === void 0 ? void 0 : _b.toJSON().data).result;
|
|
413
|
+
if (chunk.msg == "SNAP") {
|
|
414
|
+
chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_c = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _c === void 0 ? void 0 : _c.toJSON().data).remaining); // delta tick
|
|
415
|
+
num_parts_1 = (MsgUnpacker_1.default.unpackInt((_d = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _d === void 0 ? void 0 : _d.toJSON().data).result);
|
|
416
|
+
chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_e = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _e === void 0 ? void 0 : _e.toJSON().data).remaining); // num parts
|
|
417
|
+
part_1 = (MsgUnpacker_1.default.unpackInt((_f = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _f === void 0 ? void 0 : _f.toJSON().data).result);
|
|
418
|
+
}
|
|
419
|
+
chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_g = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _g === void 0 ? void 0 : _g.toJSON().data).remaining); // part
|
|
420
|
+
if (chunk.msg != "SNAP_EMPTY")
|
|
421
|
+
chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_h = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _h === void 0 ? void 0 : _h.toJSON().data).remaining); // crc
|
|
422
|
+
chunk.raw = Buffer.from(MsgUnpacker_1.default.unpackInt((_j = chunk === null || chunk === void 0 ? void 0 : chunk.raw) === null || _j === void 0 ? void 0 : _j.toJSON().data).remaining); // crc
|
|
423
|
+
if (part_1 == 0 || _this.snaps.length > 30) {
|
|
424
|
+
_this.snaps = [];
|
|
425
|
+
}
|
|
426
|
+
_this.snaps.push(chunk.raw);
|
|
427
|
+
if ((num_parts_1 - 1) == part_1 && _this.snaps.length == num_parts_1) {
|
|
428
|
+
var mergedSnaps = Buffer.concat(_this.snaps);
|
|
429
|
+
var snapUnpacked = SnapUnpacker.unpackSnapshot(mergedSnaps.toJSON().data, 1);
|
|
430
|
+
snapUnpacked.items.forEach(function (a, i) {
|
|
431
|
+
if (a.type_id == items.OBJ_CLIENT_INFO) {
|
|
432
|
+
_this.client_infos[a.id] = a.parsed;
|
|
433
|
+
// console.log(a.parsed, i)
|
|
434
|
+
// console.log(this.client_infos[a.id])
|
|
461
435
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
436
|
+
else if (a.type_id == items.OBJ_PLAYER_INFO) {
|
|
437
|
+
_this.player_infos[i] = a.parsed;
|
|
438
|
+
}
|
|
439
|
+
else if (a.type_id == items.OBJ_EX || a.type_id > 0x4000) {
|
|
440
|
+
if (a.data.length == 5 && (a.parsed.freeze_end > 0 || a.parsed.freeze_end == -1)) {
|
|
441
|
+
// var packer = new MsgPacker(22, false)
|
|
442
|
+
// this.SendMsgEx(packer, 1)
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
});
|
|
448
|
+
}
|
|
466
449
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
}
|
|
474
|
-
});
|
|
475
|
-
}); });
|
|
450
|
+
if (new Date().getTime() - this.time >= 1000) {
|
|
451
|
+
this.time = new Date().getTime();
|
|
452
|
+
this.SendControlMsg(0);
|
|
453
|
+
}
|
|
454
|
+
return [2 /*return*/];
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}); });
|
|
476
458
|
};
|
|
477
459
|
Client.prototype.Disconnect = function () {
|
|
478
460
|
var _this = this;
|
|
479
461
|
return new Promise(function (resolve) {
|
|
480
462
|
_this.SendControlMsg(4).then(function () {
|
|
481
463
|
resolve(true);
|
|
482
|
-
_this.socket
|
|
464
|
+
if (_this.socket)
|
|
465
|
+
_this.socket.close();
|
|
466
|
+
_this.socket = undefined;
|
|
483
467
|
_this.State = -1;
|
|
484
468
|
});
|
|
485
469
|
});
|