teeworlds 2.4.4 → 2.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/docs/events.md +367 -0
- package/docs/examples/chat_bot.js +25 -0
- package/docs/examples/kill_on_freeze.js +20 -0
- package/index.js +0 -1
- package/index.ts +1 -2
- package/lib/MsgUnpacker.js +6 -0
- package/lib/MsgUnpacker.ts +7 -0
- package/lib/UUIDManager.js +50 -0
- package/lib/UUIDManager.ts +45 -0
- package/lib/client.js +149 -99
- package/lib/client.ts +197 -126
- package/lib/components/game.js +11 -11
- package/lib/components/game.ts +33 -21
- package/lib/{movement.js → components/movement.js} +28 -0
- package/lib/{movement.ts → components/movement.ts} +25 -0
- package/lib/components/snapshot.js +258 -0
- package/lib/components/snapshot.ts +219 -0
- package/lib/snapshot.js +143 -90
- package/lib/snapshot.ts +166 -106
- package/lib/snapshots.d.ts +81 -29
- package/package.json +1 -1
- package/test.js +57 -0
package/lib/snapshot.ts
CHANGED
|
@@ -1,29 +1,32 @@
|
|
|
1
|
+
import { UUIDManager, createTwMD5Hash } from "./UUIDManager";
|
|
2
|
+
import { Client } from "./client";
|
|
1
3
|
import { MsgUnpacker } from "./MsgUnpacker";
|
|
4
|
+
import { PlayerInput, PlayerInfo, Projectile, Laser, Pickup, Flag, GameInfo, GameData, CharacterCore, Character, ClientInfo, SpectatorInfo, Common, Explosion, Spawn, HammerHit, Death, SoundGlobal, SoundWorld, DamageInd, MyOwnObject, DDNetCharacter, DDNetPlayer, GameInfoEx, DDNetProjectile, DDNetLaser } from "./snapshots";
|
|
2
5
|
var decoder = new TextDecoder('utf-8');
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
7
|
+
const ___itemAppendix: {"type_id": number, "size": number, "name": string}[] = [ // only used for the events underneath. the actual itemAppendix below this is only used for size
|
|
8
|
+
{"type_id": 0, "size": 0, "name": "obj_ex"},
|
|
9
|
+
{"type_id": 1, "size": 10, "name": "obj_player_input"},
|
|
10
|
+
{"type_id": 2, "size": 6, "name": "obj_projectile"},
|
|
11
|
+
{"type_id": 3, "size": 5, "name": "obj_laser"},
|
|
12
|
+
{"type_id": 4, "size": 4, "name": "obj_pickup"},
|
|
13
|
+
{"type_id": 5, "size": 3, "name": "obj_flag"},
|
|
14
|
+
{"type_id": 6, "size": 8, "name": "obj_game_info"},
|
|
15
|
+
{"type_id": 7, "size": 4, "name": "obj_game_data"},
|
|
16
|
+
{"type_id": 8, "size": 15, "name": "obj_character_core"},
|
|
17
|
+
{"type_id": 9, "size": 22, "name": "obj_character"},
|
|
18
|
+
{"type_id": 10, "size": 5, "name": "obj_player_info"},
|
|
19
|
+
{"type_id": 11, "size": 17, "name": "obj_client_info"},
|
|
20
|
+
{"type_id": 12, "size": 3, "name": "obj_spectator_info"},
|
|
21
|
+
{"type_id": 13, "size": 2, "name": "common"}, // event_common
|
|
22
|
+
{"type_id": 14, "size": 2, "name": "explosion"}, // event_explosion
|
|
23
|
+
{"type_id": 15, "size": 2, "name": "spawn"}, // event_spawn
|
|
24
|
+
{"type_id": 16, "size": 2, "name": "hammerhit"}, // event_hammerhit
|
|
25
|
+
{"type_id": 17, "size": 3, "name": "death"}, // event_death
|
|
26
|
+
{"type_id": 18, "size": 3, "name": "sound_global"}, // event_sound_global
|
|
27
|
+
{"type_id": 19, "size": 3, "name": "sound_world"}, // event_sound_world
|
|
28
|
+
{"type_id": 20, "size": 3, "name": "damage_indicator"} // event_damage_indicator
|
|
29
|
+
]
|
|
27
30
|
const itemAppendix: number[] = [
|
|
28
31
|
0,
|
|
29
32
|
10,
|
|
@@ -72,16 +75,34 @@ export enum items {
|
|
|
72
75
|
EVENT_DAMAGE_INDICATOR
|
|
73
76
|
}
|
|
74
77
|
|
|
75
|
-
export type Item = PlayerInput | PlayerInfo | Projectile | Laser | Pickup | Flag | GameInfo | GameData | CharacterCore | Character | PlayerInfo | ClientInfo | SpectatorInfo | Common | Explosion | Spawn |HammerHit | Death | SoundGlobal | SoundWorld | DamageInd
|
|
78
|
+
export declare type Item = PlayerInput | PlayerInfo | Projectile | Laser | Pickup | Flag | GameInfo | GameData | CharacterCore | Character | PlayerInfo | ClientInfo | SpectatorInfo | Common | Explosion | Spawn |HammerHit | Death | SoundGlobal | SoundWorld | DamageInd;
|
|
79
|
+
export declare type DDNetItem = MyOwnObject | DDNetCharacter | DDNetPlayer | GameInfoEx | DDNetProjectile | DDNetLaser;
|
|
76
80
|
interface eSnap {
|
|
77
81
|
Snapshot: {Key: number, Data: number[]},
|
|
78
82
|
ack: number,
|
|
79
83
|
}
|
|
84
|
+
|
|
85
|
+
// https://github.com/ddnet/ddnet/blob/571b0b36de83d18f2524ee371fc3223d04b94135/datasrc/network.py#L236
|
|
86
|
+
let supported_uuids = [
|
|
87
|
+
"my-own-object@heinrich5991.de",
|
|
88
|
+
"character@netobj.ddnet.tw", // validate_size=False
|
|
89
|
+
"player@netobj.ddnet.tw",
|
|
90
|
+
"gameinfo@netobj.ddnet.tw", // validate_size=False
|
|
91
|
+
"projectile@netobj.ddnet.tw",
|
|
92
|
+
"laser@netobj.ddnet.tw",
|
|
93
|
+
]
|
|
94
|
+
|
|
80
95
|
export class Snapshot {
|
|
81
|
-
deltas: {'data': number[], 'parsed': Item, 'type_id': number, 'id': number, 'key': number}[] = [];
|
|
96
|
+
deltas: {'data': number[], 'parsed': Item | DDNetItem, 'type_id': number, 'id': number, 'key': number}[] = [];
|
|
82
97
|
eSnapHolder: eSnap[] = [];
|
|
83
98
|
crc_errors: number = 0;
|
|
99
|
+
client: Client;
|
|
100
|
+
uuid_manager: UUIDManager = new UUIDManager(32767, true); // snapshot max_type
|
|
84
101
|
|
|
102
|
+
constructor(_client: Client) {
|
|
103
|
+
this.client = _client;
|
|
104
|
+
}
|
|
105
|
+
|
|
85
106
|
private IntsToStr(pInts: number[]): string {
|
|
86
107
|
var pIntz: number[] = [];
|
|
87
108
|
// var pStr = ''
|
|
@@ -101,8 +122,69 @@ export class Snapshot {
|
|
|
101
122
|
pStr = pStr.replace(/\0.*/g, ''); // Remove content from first null char to end.
|
|
102
123
|
return pStr;
|
|
103
124
|
}
|
|
104
|
-
private parseItem(data: number[], Type: number, id: number): Item {
|
|
105
|
-
var _item = {} as Item;
|
|
125
|
+
private parseItem(data: number[], Type: number, id: number): Item | DDNetItem {
|
|
126
|
+
var _item = {} as Item | DDNetItem;
|
|
127
|
+
if (Type >= 0x4000) { // offset uuid type
|
|
128
|
+
if (this.uuid_manager.LookupType(Type)?.name == "my-own-object@heinrich5991.de") {
|
|
129
|
+
_item = {
|
|
130
|
+
m_Test: data[0]
|
|
131
|
+
} as MyOwnObject;
|
|
132
|
+
} else if (this.uuid_manager.LookupType(Type)?.name == "character@netobj.ddnet.tw") {
|
|
133
|
+
_item = {
|
|
134
|
+
m_Flags: data[0],
|
|
135
|
+
m_FreezeEnd: data[1],
|
|
136
|
+
m_Jumps: data[2],
|
|
137
|
+
m_TeleCheckpoint: data[3],
|
|
138
|
+
m_StrongWeakID: data[4],
|
|
139
|
+
|
|
140
|
+
// # New data fields for jump display, freeze bar and ninja bar
|
|
141
|
+
// # Default values indicate that these values should not be used
|
|
142
|
+
m_JumpedTotal: data[5] ?? null,
|
|
143
|
+
m_NinjaActivationTick: data[6] ?? null,
|
|
144
|
+
m_FreezeStart: data[7] ?? null,
|
|
145
|
+
// # New data fields for improved target accuracy
|
|
146
|
+
m_TargetX: data[8] ?? null,
|
|
147
|
+
m_TargetY: data[9] ?? null,
|
|
148
|
+
id: id
|
|
149
|
+
|
|
150
|
+
} as DDNetCharacter;
|
|
151
|
+
}
|
|
152
|
+
else if (this.uuid_manager.LookupType(Type)?.name == "player@netobj.ddnet.tw") {
|
|
153
|
+
_item = {
|
|
154
|
+
m_Flags: data[0],
|
|
155
|
+
m_AuthLevel: data[1],
|
|
156
|
+
id: id
|
|
157
|
+
} as DDNetPlayer
|
|
158
|
+
}
|
|
159
|
+
else if (this.uuid_manager.LookupType(Type)?.name == "gameinfo@netobj.ddnet.tw") {
|
|
160
|
+
_item = {
|
|
161
|
+
m_Flags: data[0],
|
|
162
|
+
m_Version: data[1],
|
|
163
|
+
m_Flags2: data[2]
|
|
164
|
+
} as GameInfoEx
|
|
165
|
+
}
|
|
166
|
+
else if (this.uuid_manager.LookupType(Type)?.name == "projectile@netobj.ddnet.tw") {
|
|
167
|
+
_item = {
|
|
168
|
+
m_X: data[0],
|
|
169
|
+
m_Y: data[1],
|
|
170
|
+
m_Angle: data[2],
|
|
171
|
+
m_Data: data[3],
|
|
172
|
+
m_Type: data[3],
|
|
173
|
+
m_StartTick: data[3]
|
|
174
|
+
} as DDNetProjectile
|
|
175
|
+
}
|
|
176
|
+
else if (this.uuid_manager.LookupType(Type)?.name == "laser@netobj.ddnet.tw") {
|
|
177
|
+
_item = {
|
|
178
|
+
m_ToX: data[0],
|
|
179
|
+
m_ToY: data[1],
|
|
180
|
+
m_FromX: data[2],
|
|
181
|
+
m_FromY: data[3],
|
|
182
|
+
m_Owner: data[3],
|
|
183
|
+
m_Type: data[3]
|
|
184
|
+
} as DDNetLaser
|
|
185
|
+
}
|
|
186
|
+
return _item;
|
|
187
|
+
}
|
|
106
188
|
switch (Type) {
|
|
107
189
|
case items.OBJ_EX:
|
|
108
190
|
break;
|
|
@@ -220,6 +302,8 @@ export class Snapshot {
|
|
|
220
302
|
weapon: data[19],
|
|
221
303
|
emote: data[20],
|
|
222
304
|
attack_tick: data[21],
|
|
305
|
+
|
|
306
|
+
client_id: id
|
|
223
307
|
} as Character
|
|
224
308
|
break;
|
|
225
309
|
case items.OBJ_PLAYER_INFO:
|
|
@@ -347,10 +431,6 @@ export class Snapshot {
|
|
|
347
431
|
deltaSnaps.push(a);
|
|
348
432
|
return a.ack >= deltatick
|
|
349
433
|
})
|
|
350
|
-
// if (deltatick != -1 && this.eSnapHolder.length == 0) {
|
|
351
|
-
// console.log("no deltatick stored")
|
|
352
|
-
// return {items: [], recvTick: -1}
|
|
353
|
-
// }
|
|
354
434
|
}
|
|
355
435
|
if (snap.length == 0) {
|
|
356
436
|
// empty snap, copy old one into new ack
|
|
@@ -369,7 +449,8 @@ export class Snapshot {
|
|
|
369
449
|
* https://github.com/heinrich5991/libtw2/blob/master/snapshot/src/
|
|
370
450
|
* https://github.com/heinrich5991/libtw2/blob/master/doc/snapshot.md
|
|
371
451
|
*/
|
|
372
|
-
|
|
452
|
+
var _events: {type_id: number, parsed: Item | DDNetItem}[] = [];
|
|
453
|
+
|
|
373
454
|
let num_removed_items = unpacker.unpackInt();
|
|
374
455
|
let num_item_deltas = unpacker.unpackInt();
|
|
375
456
|
unpacker.unpackInt(); // _zero padding
|
|
@@ -384,11 +465,6 @@ export class Snapshot {
|
|
|
384
465
|
var deleted: number[] = [];
|
|
385
466
|
for (let i = 0; i < num_removed_items; i++) {
|
|
386
467
|
let deleted_key = unpacker.unpackInt(); // removed_item_keys
|
|
387
|
-
// let index = this.deltas.map(delta => delta.key).indexOf(deleted_key);
|
|
388
|
-
// let index = this.deltas.findIndex(delta => delta.key === deleted_key);
|
|
389
|
-
// if (index > -1)
|
|
390
|
-
// this.deltas.splice(index, 1);
|
|
391
|
-
// console.log(deleted_key)
|
|
392
468
|
deleted.push(deleted_key)
|
|
393
469
|
}
|
|
394
470
|
/*item_delta:
|
|
@@ -433,67 +509,70 @@ export class Snapshot {
|
|
|
433
509
|
changed = true;
|
|
434
510
|
} // else no previous, use new data
|
|
435
511
|
}
|
|
436
|
-
let parsed: Item;
|
|
437
|
-
if (
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
512
|
+
let parsed: Item | DDNetItem;
|
|
513
|
+
if (type_id !== 0) {
|
|
514
|
+
if (!changed) {
|
|
515
|
+
let oldDelta = oldDeltas.find(delta => delta.key == key);
|
|
516
|
+
if (oldDelta !== undefined && compareArrays(data, oldDelta.data)) {
|
|
517
|
+
parsed = oldDelta.parsed;
|
|
518
|
+
|
|
519
|
+
} else
|
|
520
|
+
parsed = this.parseItem(data, type_id, id)
|
|
521
|
+
|
|
442
522
|
} else
|
|
443
523
|
parsed = this.parseItem(data, type_id, id)
|
|
444
524
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
525
|
+
this.eSnapHolder.push({Snapshot: {Data: data, Key: key}, ack: recvTick});
|
|
526
|
+
|
|
527
|
+
this.deltas.push({
|
|
528
|
+
data,
|
|
529
|
+
key,
|
|
530
|
+
id,
|
|
531
|
+
type_id,
|
|
532
|
+
parsed
|
|
533
|
+
});
|
|
534
|
+
if (type_id >= items.EVENT_COMMON && type_id <= items.EVENT_DAMAGE_INDICATOR) {
|
|
535
|
+
// this.client.SnapshotUnpacker.
|
|
536
|
+
|
|
537
|
+
_events.push({type_id, parsed});
|
|
538
|
+
// this.client.SnapshotUnpacker.emit(___itemAppendix[type_id].name, parsed);
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
461
541
|
|
|
542
|
+
this.eSnapHolder.push({Snapshot: {Data: data, Key: key}, ack: recvTick});
|
|
543
|
+
|
|
544
|
+
this.deltas.push({
|
|
545
|
+
data,
|
|
546
|
+
key,
|
|
547
|
+
id,
|
|
548
|
+
type_id,
|
|
549
|
+
parsed: {} as Item
|
|
550
|
+
});
|
|
462
551
|
|
|
552
|
+
let test = (int: number) => [(int >> 24) & 0xff, (int >> 16) & 0xff, (int >> 8) & 0xff, (int) & 0xff ];
|
|
553
|
+
let test2 = (ints: number[]) => ints.map(a => test(a)).flat();
|
|
554
|
+
|
|
555
|
+
let targetUUID = Buffer.from(test2(data));
|
|
556
|
+
if (!this.uuid_manager.LookupType(id)) {
|
|
557
|
+
|
|
558
|
+
supported_uuids.forEach((a, i) => {
|
|
559
|
+
let uuid = createTwMD5Hash(a);
|
|
560
|
+
if (targetUUID.compare(uuid) == 0) {
|
|
561
|
+
this.uuid_manager.RegisterName(a, id);
|
|
562
|
+
supported_uuids.splice(i, 1);
|
|
563
|
+
}
|
|
564
|
+
})
|
|
565
|
+
}
|
|
566
|
+
}
|
|
463
567
|
}
|
|
464
|
-
|
|
465
|
-
// let _beforeLength = this.eSnapHolder.length;
|
|
466
|
-
// this.eSnapHolder = this.eSnapHolder.filter(snap => !deleted.includes(snap.Snapshot.Key));
|
|
467
|
-
// let _beforeLength = this.eSnapHolder.length;
|
|
468
|
-
// if ((_beforeLength - this.eSnapHolder.length) !== num_removed_items) {
|
|
469
|
-
// console.log("remove!", (_beforeLength - this.eSnapHolder.length) == num_removed_items, (_beforeLength - this.eSnapHolder.length), num_removed_items, WantedCrc)
|
|
470
|
-
|
|
471
|
-
// }
|
|
472
|
-
// }
|
|
568
|
+
|
|
473
569
|
|
|
474
570
|
for (let newSnap of deltaSnaps) {
|
|
475
571
|
if (deleted.includes(newSnap.Snapshot.Key)) {
|
|
476
|
-
// if ()
|
|
477
|
-
// this.deltas = this.deltas.filter(a => !deleted.includes(a.key))
|
|
478
572
|
continue;
|
|
479
573
|
}
|
|
480
574
|
if (this.eSnapHolder.findIndex(a => a.ack == recvTick && a.Snapshot.Key == newSnap.Snapshot.Key) === -1) { // ugly copy new snap to eSnapHolder (if it isnt pushed already)
|
|
481
575
|
this.eSnapHolder.push({Snapshot: {Data: newSnap.Snapshot.Data, Key: newSnap.Snapshot.Key}, ack: recvTick});
|
|
482
|
-
// this.deltas.push({})
|
|
483
|
-
// if (deltatick > -1) {
|
|
484
|
-
// let ____index = this.deltas.findIndex(delta => delta.key == newSnap.Snapshot.Key)
|
|
485
|
-
|
|
486
|
-
// if (____index > -1) {
|
|
487
|
-
// this.deltas[____index] = {
|
|
488
|
-
// data: newSnap.Snapshot.Data,
|
|
489
|
-
// key: newSnap.Snapshot.Key,
|
|
490
|
-
// id: newSnap.Snapshot.Key & 0xffff,
|
|
491
|
-
// type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff),
|
|
492
|
-
// parsed: this.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff), ((newSnap.Snapshot.Key) & 0xffff))
|
|
493
|
-
// };
|
|
494
|
-
// continue;
|
|
495
|
-
// }
|
|
496
|
-
// // }
|
|
497
576
|
let oldDelta = oldDeltas.find(delta => delta.key == newSnap.Snapshot.Key);
|
|
498
577
|
if (oldDelta !== undefined && compareArrays(newSnap.Snapshot.Data, oldDelta.data)) {
|
|
499
578
|
this.deltas.push(oldDelta);
|
|
@@ -510,24 +589,11 @@ export class Snapshot {
|
|
|
510
589
|
}
|
|
511
590
|
}
|
|
512
591
|
}
|
|
513
|
-
|
|
514
|
-
// console.log("length", items.items.length, num_item_deltas, items.items.length - num_item_deltas, WantedCrc)
|
|
515
|
-
/* this.deltas = [];
|
|
516
|
-
for (let newSnap of this.eSnapHolder) {
|
|
517
|
-
if (newSnap.ack == recvTick)
|
|
518
|
-
this.deltas.push({
|
|
519
|
-
data: newSnap.Snapshot.Data,
|
|
520
|
-
key: newSnap.Snapshot.Key,
|
|
521
|
-
id: newSnap.Snapshot.Key & 0xffff,
|
|
522
|
-
type_id: ((newSnap.Snapshot.Key >> 16) & 0xffff),
|
|
523
|
-
parsed: this.parseItem(newSnap.Snapshot.Data, ((newSnap.Snapshot.Key >> 16) & 0xffff), ((newSnap.Snapshot.Key) & 0xffff))
|
|
524
|
-
});
|
|
525
|
-
}*/
|
|
592
|
+
|
|
526
593
|
let _crc = this.crc();
|
|
527
594
|
if (_crc !== WantedCrc) {
|
|
528
595
|
this.deltas = oldDeltas;
|
|
529
596
|
this.crc_errors++;
|
|
530
|
-
console.log("crc error", _crc, WantedCrc, this.crc_errors)
|
|
531
597
|
if (this.crc_errors > 5) {
|
|
532
598
|
recvTick = -1;
|
|
533
599
|
this.crc_errors = 0;
|
|
@@ -539,12 +605,7 @@ export class Snapshot {
|
|
|
539
605
|
}
|
|
540
606
|
} else if (this.crc_errors > 0)
|
|
541
607
|
this.crc_errors--;
|
|
542
|
-
|
|
543
|
-
// if (this.deltas.length !== filterLength) {
|
|
544
|
-
// this.deltas = this.deltas.filter(a => !deleted.includes(a.key))
|
|
545
|
-
// console.log(this.deltas.length, filterLength, this.deltas.length - filterLength, num_item_deltas )
|
|
546
|
-
// }
|
|
547
|
-
|
|
608
|
+
_events.forEach(a => this.client.SnapshotUnpacker.emit(___itemAppendix[a.type_id].name, a.parsed))
|
|
548
609
|
return {items: this.deltas, recvTick};
|
|
549
610
|
}
|
|
550
611
|
}
|
|
@@ -566,7 +627,6 @@ function UndiffItem(oldItem: number[], newItem: number[]): number[] {
|
|
|
566
627
|
if (a !== undefined && out[i] !== undefined) {
|
|
567
628
|
out[i] += a;
|
|
568
629
|
} else {
|
|
569
|
-
console.log("UNDEFINED UNDEFINED UNDEFINED")
|
|
570
630
|
out[i] = 0;
|
|
571
631
|
}
|
|
572
632
|
})
|
package/lib/snapshots.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare interface PlayerInput {
|
|
1
|
+
export declare interface PlayerInput {
|
|
2
2
|
direction: number,
|
|
3
3
|
target_x: number,
|
|
4
4
|
target_y: number,
|
|
@@ -11,7 +11,7 @@ declare interface PlayerInput {
|
|
|
11
11
|
prev_weapon: number,
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
declare interface Projectile {
|
|
14
|
+
export declare interface Projectile {
|
|
15
15
|
x: number,
|
|
16
16
|
y: number,
|
|
17
17
|
vel_x: number,
|
|
@@ -20,7 +20,7 @@ declare interface Projectile {
|
|
|
20
20
|
start_tick: number,
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
declare interface Laser {
|
|
23
|
+
export declare interface Laser {
|
|
24
24
|
x: number,
|
|
25
25
|
y: number,
|
|
26
26
|
from_x: number,
|
|
@@ -28,20 +28,20 @@ declare interface Laser {
|
|
|
28
28
|
start_tick: number,
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
declare interface Pickup {
|
|
31
|
+
export declare interface Pickup {
|
|
32
32
|
x: number,
|
|
33
33
|
y: number,
|
|
34
34
|
type_: number,
|
|
35
35
|
subtype: number,
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
declare interface Flag {
|
|
38
|
+
export declare interface Flag {
|
|
39
39
|
x: number,
|
|
40
40
|
y: number,
|
|
41
41
|
team: number,
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
declare interface GameInfo {
|
|
44
|
+
export declare interface GameInfo {
|
|
45
45
|
game_flags: number,
|
|
46
46
|
game_state_flags: number,
|
|
47
47
|
round_start_tick: number,
|
|
@@ -52,14 +52,14 @@ declare interface GameInfo {
|
|
|
52
52
|
round_current: number,
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
declare interface GameData {
|
|
55
|
+
export declare interface GameData {
|
|
56
56
|
teamscore_red: number,
|
|
57
57
|
teamscore_blue: number,
|
|
58
58
|
flag_carrier_red: number,
|
|
59
59
|
flag_carrier_blue: number,
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
declare interface CharacterCore {
|
|
62
|
+
export declare interface CharacterCore {
|
|
63
63
|
tick: number,
|
|
64
64
|
x: number,
|
|
65
65
|
y: number,
|
|
@@ -77,7 +77,7 @@ declare interface CharacterCore {
|
|
|
77
77
|
hook_dy: number,
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
declare interface Character {
|
|
80
|
+
export declare interface Character {
|
|
81
81
|
character_core: CharacterCore,
|
|
82
82
|
player_flags: number,
|
|
83
83
|
health: number,
|
|
@@ -86,9 +86,11 @@ declare interface Character {
|
|
|
86
86
|
weapon: number,
|
|
87
87
|
emote: number,
|
|
88
88
|
attack_tick: number,
|
|
89
|
+
|
|
90
|
+
client_id: number
|
|
89
91
|
}
|
|
90
92
|
|
|
91
|
-
declare interface PlayerInfo {
|
|
93
|
+
export declare interface PlayerInfo {
|
|
92
94
|
local: number,
|
|
93
95
|
client_id: number,
|
|
94
96
|
team: number,
|
|
@@ -96,7 +98,7 @@ declare interface PlayerInfo {
|
|
|
96
98
|
latency: number,
|
|
97
99
|
}
|
|
98
100
|
|
|
99
|
-
declare interface ClientInfo {
|
|
101
|
+
export declare interface ClientInfo {
|
|
100
102
|
name: string,
|
|
101
103
|
clan: string,
|
|
102
104
|
country: number,
|
|
@@ -104,59 +106,53 @@ declare interface ClientInfo {
|
|
|
104
106
|
use_custom_color: number,
|
|
105
107
|
color_body: number,
|
|
106
108
|
color_feet: number,
|
|
107
|
-
}
|
|
108
109
|
|
|
109
|
-
|
|
110
|
-
flags: number,
|
|
111
|
-
freeze_end: number,
|
|
112
|
-
jumps: number,
|
|
113
|
-
tele_checkpoint: number,
|
|
114
|
-
strong_weak_id: number,
|
|
110
|
+
id: number
|
|
115
111
|
}
|
|
116
112
|
|
|
117
|
-
declare interface SpectatorInfo {
|
|
113
|
+
export declare interface SpectatorInfo {
|
|
118
114
|
spectator_id: number,
|
|
119
115
|
x: number,
|
|
120
116
|
y: number,
|
|
121
117
|
}
|
|
122
118
|
|
|
123
|
-
declare interface Common {
|
|
119
|
+
export declare interface Common {
|
|
124
120
|
x: number,
|
|
125
121
|
y: number,
|
|
126
122
|
}
|
|
127
123
|
|
|
128
|
-
declare interface Explosion {
|
|
124
|
+
export declare interface Explosion {
|
|
129
125
|
common: Common,
|
|
130
126
|
}
|
|
131
127
|
|
|
132
|
-
declare interface Spawn {
|
|
128
|
+
export declare interface Spawn {
|
|
133
129
|
common: Common,
|
|
134
130
|
}
|
|
135
131
|
|
|
136
|
-
declare interface HammerHit {
|
|
132
|
+
export declare interface HammerHit {
|
|
137
133
|
common: Common,
|
|
138
134
|
}
|
|
139
135
|
|
|
140
|
-
declare interface Death {
|
|
136
|
+
export declare interface Death {
|
|
141
137
|
common: Common,
|
|
142
138
|
client_id: number,
|
|
143
139
|
}
|
|
144
140
|
|
|
145
|
-
declare interface SoundGlobal {
|
|
141
|
+
export declare interface SoundGlobal {
|
|
146
142
|
common: Common,
|
|
147
143
|
sound_id: number,
|
|
148
144
|
}
|
|
149
145
|
|
|
150
|
-
declare interface SoundWorld {
|
|
146
|
+
export declare interface SoundWorld {
|
|
151
147
|
common: Common,
|
|
152
148
|
sound_id: number,
|
|
153
149
|
}
|
|
154
150
|
|
|
155
|
-
declare interface DamageInd {
|
|
151
|
+
export declare interface DamageInd {
|
|
156
152
|
common: Common,
|
|
157
153
|
angle: number,
|
|
158
154
|
}
|
|
159
|
-
declare enum items {
|
|
155
|
+
export declare enum items {
|
|
160
156
|
OBJ_EX,
|
|
161
157
|
OBJ_PLAYER_INPUT,
|
|
162
158
|
OBJ_PROJECTILE,
|
|
@@ -178,4 +174,60 @@ declare enum items {
|
|
|
178
174
|
EVENT_SOUND_GLOBAL,
|
|
179
175
|
EVENT_SOUND_WORLD,
|
|
180
176
|
EVENT_DAMAGE_INDICATOR
|
|
181
|
-
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export declare interface MyOwnObject {
|
|
180
|
+
m_Test: number
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export declare interface DDNetCharacter {
|
|
184
|
+
m_Flags: number,
|
|
185
|
+
m_FreezeEnd: number,
|
|
186
|
+
m_Jumps: number,
|
|
187
|
+
m_TeleCheckpoint: number,
|
|
188
|
+
m_StrongWeakID: number,
|
|
189
|
+
|
|
190
|
+
// # New data fields for jump display, freeze bar and ninja bar
|
|
191
|
+
// # Default values indicate that these values should not be used
|
|
192
|
+
m_JumpedTotal?: number,
|
|
193
|
+
m_NinjaActivationTick?: number,
|
|
194
|
+
m_FreezeStart?: number,
|
|
195
|
+
// # New data fields for improved target accuracy
|
|
196
|
+
m_TargetX?: number,
|
|
197
|
+
m_TargetY?: number,
|
|
198
|
+
id: number
|
|
199
|
+
} //, validate_size=False),
|
|
200
|
+
/** m_AuthLevel "AUTHED_NO", "AUTHED_ADMIN" */
|
|
201
|
+
export declare interface DDNetPlayer {
|
|
202
|
+
m_Flags: number,
|
|
203
|
+
m_AuthLevel: number,
|
|
204
|
+
id: number
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export declare interface GameInfoEx {
|
|
208
|
+
|
|
209
|
+
m_Flags: number,
|
|
210
|
+
m_Version: number,
|
|
211
|
+
m_Flags2: number,
|
|
212
|
+
}//, validate_size=False),
|
|
213
|
+
|
|
214
|
+
// # The code assumes that this has the same in-memory representation as
|
|
215
|
+
// # the Projectile net object.
|
|
216
|
+
export declare interface DDNetProjectile {
|
|
217
|
+
m_X: number,
|
|
218
|
+
m_Y: number,
|
|
219
|
+
m_Angle: number,
|
|
220
|
+
m_Data: number,
|
|
221
|
+
m_Type: number,
|
|
222
|
+
m_StartTick: number,
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export declare interface DDNetLaser {
|
|
226
|
+
m_ToX: number,
|
|
227
|
+
m_ToY: number,
|
|
228
|
+
m_FromX: number,
|
|
229
|
+
m_FromY: number,
|
|
230
|
+
m_StartTick: number,
|
|
231
|
+
m_Owner: number,
|
|
232
|
+
m_Type: number,
|
|
233
|
+
}
|
package/package.json
CHANGED
package/test.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
let crypto = require('crypto');
|
|
2
|
+
let list = {
|
|
3
|
+
"WHAT_IS": Buffer.from([0x24, 0x5e, 0x50, 0x97, 0x9f, 0xe0, 0x39, 0xd6, 0xbf, 0x7d, 0x9a, 0x29, 0xe1, 0x69, 0x1e, 0x4c]),
|
|
4
|
+
"IT_IS": Buffer.from([0x69, 0x54, 0x84, 0x7e, 0x2e, 0x87, 0x36, 0x03, 0xb5, 0x62, 0x36, 0xda, 0x29, 0xed, 0x1a, 0xca]),
|
|
5
|
+
"I_DONT_KNOW": Buffer.from([0x41, 0x69, 0x11, 0xb5, 0x79, 0x73, 0x33, 0xbf, 0x8d, 0x52, 0x7b, 0xf0, 0x1e, 0x51, 0x9c, 0xf0]),
|
|
6
|
+
"RCON_TYPE": Buffer.from([0x12, 0x81, 0x0e, 0x1f, 0xa1, 0xdb, 0x33, 0x78, 0xb4, 0xfb, 0x16, 0x4e, 0xd6, 0x50, 0x59, 0x26]),
|
|
7
|
+
"MAP_DETAILS": Buffer.from([0xf9, 0x11, 0x7b, 0x3c, 0x80, 0x39, 0x34, 0x16, 0x9f, 0xc0, 0xae, 0xf2, 0xbc, 0xb7, 0x5c, 0x03]),
|
|
8
|
+
"CAPABILITIES": Buffer.from([0xf6, 0x21, 0xa5, 0xa1, 0xf5, 0x85, 0x37, 0x75, 0x8e, 0x73, 0x41, 0xbe, 0xee, 0x79, 0xf2, 0xb2]),
|
|
9
|
+
"CLIENT_VERSION": Buffer.from([0x8c, 0x00, 0x13, 0x04, 0x84, 0x61, 0x3e, 0x47, 0x87, 0x87, 0xf6, 0x72, 0xb3, 0x83, 0x5b, 0xd4]),
|
|
10
|
+
// "PING_EX": Buffer.from([]),
|
|
11
|
+
// "PONG_EX": Buffer.from([]),
|
|
12
|
+
// "CHECKSUM_REQUEST": Buffer.from([]),
|
|
13
|
+
// "CHECKSUM_RESPONSE": Buffer.from([]),
|
|
14
|
+
// "CHECKSUM_ERROR": Buffer.from([])
|
|
15
|
+
}
|
|
16
|
+
let newList = {
|
|
17
|
+
"what_is": ("what-is@ddnet.tw"),
|
|
18
|
+
"it_is": ("it-is@ddnet.tw"),
|
|
19
|
+
"i_dont_know": ("i-dont-know@ddnet.tw"),
|
|
20
|
+
"rcon_type": ("rcon-type@ddnet.tw"),
|
|
21
|
+
"map_details": ("map-details@ddnet.tw"),
|
|
22
|
+
"capabilities": ("capabilities@ddnet.tw"),
|
|
23
|
+
"client_version": ("clientver@ddnet.tw"),
|
|
24
|
+
"ping": ("ping@ddnet.tw"),
|
|
25
|
+
"pong": ("pong@ddnet.tw"),
|
|
26
|
+
"checksum_request": ("checksum-request@ddnet.tw"),
|
|
27
|
+
"checksum_response": ("checksum-response@ddnet.tw"),
|
|
28
|
+
"checksum_error": ("checksum-error@ddnet.tw")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const createTwMD5Hash = (name) => { // https://github.com/ddnet/ddnet/blob/6d9284adc1e0be4b5348447d857eae575e06e654/src/engine/shared/uuid_manager.cpp#L26
|
|
32
|
+
let hash = crypto.createHash("md5")
|
|
33
|
+
.update(Buffer.from([0xe0, 0x5d, 0xda, 0xaa, 0xc4, 0xe6, 0x4c, 0xfb, 0xb6, 0x42, 0x5d, 0x48, 0xe8, 0x0c, 0x00, 0x29]))
|
|
34
|
+
.update(name)
|
|
35
|
+
.digest()
|
|
36
|
+
hash[6] &= 0x0f;
|
|
37
|
+
hash[6] |= 0x30;
|
|
38
|
+
hash[8] &= 0x3f;
|
|
39
|
+
hash[8] |= 0x80;
|
|
40
|
+
return hash;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
Object.keys(newList).forEach(name => {
|
|
44
|
+
let el = newList[name];
|
|
45
|
+
let el_old = list[name.toUpperCase()];
|
|
46
|
+
if (el_old == undefined)
|
|
47
|
+
return;
|
|
48
|
+
// let hash = crypto.createHash("md5")
|
|
49
|
+
// .update(Buffer.from([0xe0, 0x5d, 0xda, 0xaa, 0xc4, 0xe6, 0x4c, 0xfb, 0xb6, 0x42, 0x5d, 0x48, 0xe8, 0x0c, 0x00, 0x29]))
|
|
50
|
+
// .update(name).digest()
|
|
51
|
+
|
|
52
|
+
let hash = createTwMD5Hash(el);
|
|
53
|
+
console.log(hash.compare(el_old), name)
|
|
54
|
+
if (hash.compare(el_old) !== 0)
|
|
55
|
+
console.log(name, hash, el_old)
|
|
56
|
+
// it_is <Buffer 69 54 84 7e 2e 87 c6 03 75 62 36 da 29 ed 1a ca> <Buffer 69 54 84 7e 2e 87 36 03 b5 62 36 da 29 ed 1a ca>
|
|
57
|
+
});
|