quake2ts 0.0.213 → 0.0.215
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/package.json +1 -1
- package/packages/client/dist/browser/index.global.js +10 -10
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/game/dist/browser/index.global.js +2 -2
- package/packages/game/dist/browser/index.global.js.map +1 -1
- package/packages/game/dist/cjs/index.cjs +26 -22
- package/packages/game/dist/cjs/index.cjs.map +1 -1
- package/packages/game/dist/esm/index.js +26 -22
- package/packages/game/dist/esm/index.js.map +1 -1
- package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/types/entities/monsters/berserk.d.ts.map +1 -1
- package/packages/server/dist/index.cjs +216 -24
- package/packages/server/dist/index.d.cts +2 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.js +209 -17
|
@@ -201,7 +201,8 @@ function createClient(index, net) {
|
|
|
201
201
|
lastMessage: 0,
|
|
202
202
|
lastConnect: Date.now(),
|
|
203
203
|
challenge: 0,
|
|
204
|
-
messageQueue: []
|
|
204
|
+
messageQueue: [],
|
|
205
|
+
lastPacketEntities: []
|
|
205
206
|
};
|
|
206
207
|
}
|
|
207
208
|
function createEmptyUserCommand() {
|
|
@@ -302,7 +303,7 @@ var ClientMessageParser = class {
|
|
|
302
303
|
};
|
|
303
304
|
|
|
304
305
|
// src/dedicated.ts
|
|
305
|
-
var
|
|
306
|
+
var import_shared4 = require("@quake2ts/shared");
|
|
306
307
|
var import_engine = require("@quake2ts/engine");
|
|
307
308
|
var import_promises = __toESM(require("fs/promises"), 1);
|
|
308
309
|
var import_game2 = require("@quake2ts/game");
|
|
@@ -345,6 +346,24 @@ var NULL_STATE = {
|
|
|
345
346
|
sound: 0,
|
|
346
347
|
event: 0
|
|
347
348
|
};
|
|
349
|
+
function writeRemoveEntity(number, writer) {
|
|
350
|
+
let bits = U_REMOVE;
|
|
351
|
+
if (number >= 256) {
|
|
352
|
+
bits |= U_NUMBER16;
|
|
353
|
+
}
|
|
354
|
+
if (bits & 65280) {
|
|
355
|
+
bits |= U_MOREBITS1;
|
|
356
|
+
}
|
|
357
|
+
writer.writeByte(bits & 255);
|
|
358
|
+
if (bits & U_MOREBITS1) {
|
|
359
|
+
writer.writeByte(bits >> 8 & 255);
|
|
360
|
+
}
|
|
361
|
+
if (bits & U_NUMBER16) {
|
|
362
|
+
writer.writeShort(number);
|
|
363
|
+
} else {
|
|
364
|
+
writer.writeByte(number);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
348
367
|
function writeDeltaEntity(from, to, writer, force, newEntity) {
|
|
349
368
|
let bits = 0;
|
|
350
369
|
if (newEntity) {
|
|
@@ -549,6 +568,113 @@ function writePlayerState(writer, ps) {
|
|
|
549
568
|
}
|
|
550
569
|
}
|
|
551
570
|
|
|
571
|
+
// src/protocol/write.ts
|
|
572
|
+
var import_shared3 = require("@quake2ts/shared");
|
|
573
|
+
function writeServerCommand(writer, event, ...args) {
|
|
574
|
+
writer.writeByte(event);
|
|
575
|
+
switch (event) {
|
|
576
|
+
case import_shared3.ServerCommand.print: {
|
|
577
|
+
const level = args[0];
|
|
578
|
+
const text = args[1];
|
|
579
|
+
writer.writeByte(level);
|
|
580
|
+
writer.writeString(text);
|
|
581
|
+
break;
|
|
582
|
+
}
|
|
583
|
+
case import_shared3.ServerCommand.muzzleflash: {
|
|
584
|
+
const entIndex = args[0];
|
|
585
|
+
const flashType = args[1];
|
|
586
|
+
writer.writeShort(entIndex);
|
|
587
|
+
writer.writeByte(flashType);
|
|
588
|
+
break;
|
|
589
|
+
}
|
|
590
|
+
case import_shared3.ServerCommand.temp_entity: {
|
|
591
|
+
const type = args[0];
|
|
592
|
+
writer.writeByte(type);
|
|
593
|
+
writeTempEntity(writer, type, args.slice(1));
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
default:
|
|
597
|
+
console.warn(`writeServerCommand: Unhandled command ${event}`);
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
function writeTempEntity(writer, type, args) {
|
|
602
|
+
switch (type) {
|
|
603
|
+
case import_shared3.TempEntity.ROCKET_EXPLOSION:
|
|
604
|
+
case import_shared3.TempEntity.GRENADE_EXPLOSION:
|
|
605
|
+
case import_shared3.TempEntity.EXPLOSION1:
|
|
606
|
+
case import_shared3.TempEntity.EXPLOSION2:
|
|
607
|
+
case import_shared3.TempEntity.ROCKET_EXPLOSION_WATER:
|
|
608
|
+
case import_shared3.TempEntity.GRENADE_EXPLOSION_WATER:
|
|
609
|
+
case import_shared3.TempEntity.BFG_EXPLOSION:
|
|
610
|
+
case import_shared3.TempEntity.BFG_BIGEXPLOSION:
|
|
611
|
+
case import_shared3.TempEntity.PLASMA_EXPLOSION:
|
|
612
|
+
case import_shared3.TempEntity.PLAIN_EXPLOSION:
|
|
613
|
+
case import_shared3.TempEntity.TRACKER_EXPLOSION:
|
|
614
|
+
case import_shared3.TempEntity.EXPLOSION1_BIG:
|
|
615
|
+
case import_shared3.TempEntity.EXPLOSION1_NP:
|
|
616
|
+
case import_shared3.TempEntity.EXPLOSION1_NL:
|
|
617
|
+
case import_shared3.TempEntity.EXPLOSION2_NL:
|
|
618
|
+
case import_shared3.TempEntity.BERSERK_SLAM:
|
|
619
|
+
writer.writePos(args[0]);
|
|
620
|
+
break;
|
|
621
|
+
case import_shared3.TempEntity.BLASTER:
|
|
622
|
+
case import_shared3.TempEntity.FLECHETTE:
|
|
623
|
+
writer.writePos(args[0]);
|
|
624
|
+
writer.writeDir(args[1]);
|
|
625
|
+
break;
|
|
626
|
+
case import_shared3.TempEntity.RAILTRAIL:
|
|
627
|
+
case import_shared3.TempEntity.DEBUGTRAIL:
|
|
628
|
+
case import_shared3.TempEntity.BUBBLETRAIL:
|
|
629
|
+
case import_shared3.TempEntity.BUBBLETRAIL2:
|
|
630
|
+
case import_shared3.TempEntity.BFG_LASER:
|
|
631
|
+
case import_shared3.TempEntity.LIGHTNING_BEAM:
|
|
632
|
+
case import_shared3.TempEntity.LIGHTNING:
|
|
633
|
+
writer.writePos(args[0]);
|
|
634
|
+
writer.writePos(args[1]);
|
|
635
|
+
break;
|
|
636
|
+
case import_shared3.TempEntity.LASER_SPARKS:
|
|
637
|
+
case import_shared3.TempEntity.WELDING_SPARKS:
|
|
638
|
+
case import_shared3.TempEntity.TUNNEL_SPARKS:
|
|
639
|
+
case import_shared3.TempEntity.ELECTRIC_SPARKS:
|
|
640
|
+
case import_shared3.TempEntity.HEATBEAM_SPARKS:
|
|
641
|
+
case import_shared3.TempEntity.HEATBEAM_STEAM:
|
|
642
|
+
case import_shared3.TempEntity.STEAM:
|
|
643
|
+
writer.writeByte(args[0]);
|
|
644
|
+
writer.writePos(args[1]);
|
|
645
|
+
writer.writeDir(args[2]);
|
|
646
|
+
writer.writeByte(args[3] || 0);
|
|
647
|
+
break;
|
|
648
|
+
case import_shared3.TempEntity.PARASITE_ATTACK:
|
|
649
|
+
case import_shared3.TempEntity.MEDIC_CABLE_ATTACK:
|
|
650
|
+
const ent = args[0];
|
|
651
|
+
writer.writeShort(ent ? ent.index : 0);
|
|
652
|
+
writer.writePos(args[1]);
|
|
653
|
+
writer.writePos(args[2]);
|
|
654
|
+
break;
|
|
655
|
+
case import_shared3.TempEntity.GUNSHOT:
|
|
656
|
+
case import_shared3.TempEntity.BLOOD:
|
|
657
|
+
case import_shared3.TempEntity.SPARKS:
|
|
658
|
+
case import_shared3.TempEntity.BULLET_SPARKS:
|
|
659
|
+
case import_shared3.TempEntity.SCREEN_SPARKS:
|
|
660
|
+
case import_shared3.TempEntity.SHIELD_SPARKS:
|
|
661
|
+
writer.writePos(args[0]);
|
|
662
|
+
writer.writeDir(args[1]);
|
|
663
|
+
break;
|
|
664
|
+
case import_shared3.TempEntity.SPLASH:
|
|
665
|
+
case import_shared3.TempEntity.POWER_SPLASH:
|
|
666
|
+
case import_shared3.TempEntity.WIDOWSPLASH:
|
|
667
|
+
writer.writeByte(args[0]);
|
|
668
|
+
writer.writePos(args[1]);
|
|
669
|
+
writer.writeDir(args[2]);
|
|
670
|
+
writer.writeByte(args[3] || 0);
|
|
671
|
+
break;
|
|
672
|
+
default:
|
|
673
|
+
console.warn(`writeTempEntity: Unhandled TempEntity ${type}`);
|
|
674
|
+
break;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
552
678
|
// src/dedicated.ts
|
|
553
679
|
var MAX_CLIENTS = 16;
|
|
554
680
|
var FRAME_RATE = 10;
|
|
@@ -579,11 +705,11 @@ var DedicatedServer = class {
|
|
|
579
705
|
frame: 0,
|
|
580
706
|
name: "",
|
|
581
707
|
collisionModel: null,
|
|
582
|
-
configStrings: new Array(
|
|
583
|
-
baselines: new Array(
|
|
708
|
+
configStrings: new Array(import_shared4.MAX_CONFIGSTRINGS).fill(""),
|
|
709
|
+
baselines: new Array(import_shared4.MAX_EDICTS).fill(null),
|
|
584
710
|
multicastBuf: new Uint8Array(0)
|
|
585
711
|
};
|
|
586
|
-
this.entityIndex = new
|
|
712
|
+
this.entityIndex = new import_shared4.CollisionEntityIndex();
|
|
587
713
|
}
|
|
588
714
|
async start(mapName) {
|
|
589
715
|
console.log(`Starting Dedicated Server on port ${this.port}...`);
|
|
@@ -634,7 +760,7 @@ var DedicatedServer = class {
|
|
|
634
760
|
ent: hitEntity
|
|
635
761
|
};
|
|
636
762
|
}
|
|
637
|
-
const worldResult = this.sv.collisionModel ? (0,
|
|
763
|
+
const worldResult = this.sv.collisionModel ? (0, import_shared4.traceBox)({
|
|
638
764
|
start,
|
|
639
765
|
end,
|
|
640
766
|
mins: mins || void 0,
|
|
@@ -689,10 +815,33 @@ var DedicatedServer = class {
|
|
|
689
815
|
});
|
|
690
816
|
this.game.init(0);
|
|
691
817
|
this.game.spawnWorld();
|
|
818
|
+
this.populateBaselines();
|
|
692
819
|
this.sv.state = 2 /* Game */;
|
|
693
820
|
this.frameInterval = setInterval(() => this.runFrame(), FRAME_TIME_MS);
|
|
694
821
|
console.log("Server started.");
|
|
695
822
|
}
|
|
823
|
+
populateBaselines() {
|
|
824
|
+
if (!this.game) return;
|
|
825
|
+
this.game.entities.forEachEntity((ent) => {
|
|
826
|
+
if (ent.index >= import_shared4.MAX_EDICTS) return;
|
|
827
|
+
if (ent.modelindex > 0 || ent.solid !== import_game.Solid.Not) {
|
|
828
|
+
this.sv.baselines[ent.index] = {
|
|
829
|
+
number: ent.index,
|
|
830
|
+
origin: { ...ent.origin },
|
|
831
|
+
angles: { ...ent.angles },
|
|
832
|
+
modelIndex: ent.modelindex,
|
|
833
|
+
frame: ent.frame,
|
|
834
|
+
skinNum: ent.skin,
|
|
835
|
+
effects: ent.effects,
|
|
836
|
+
renderfx: ent.renderfx,
|
|
837
|
+
solid: ent.solid,
|
|
838
|
+
sound: ent.sounds,
|
|
839
|
+
// Assuming ent.sounds maps to 'sound' field in EntityState
|
|
840
|
+
event: 0
|
|
841
|
+
};
|
|
842
|
+
}
|
|
843
|
+
});
|
|
844
|
+
}
|
|
696
845
|
stop() {
|
|
697
846
|
if (this.frameInterval) clearInterval(this.frameInterval);
|
|
698
847
|
if (this.wss) this.wss.close();
|
|
@@ -755,14 +904,14 @@ var DedicatedServer = class {
|
|
|
755
904
|
client.userInfo = userInfo;
|
|
756
905
|
console.log(`Client ${client.index} connected: ${userInfo}`);
|
|
757
906
|
this.sendServerData(client);
|
|
758
|
-
const writer = new
|
|
759
|
-
writer.writeByte(
|
|
907
|
+
const writer = new import_shared4.BinaryWriter();
|
|
908
|
+
writer.writeByte(import_shared4.ServerCommand.stufftext);
|
|
760
909
|
writer.writeString("precache\n");
|
|
761
910
|
client.net.send(writer.getData());
|
|
762
911
|
} else {
|
|
763
912
|
console.log(`Client ${client.index} rejected: ${result}`);
|
|
764
|
-
const writer = new
|
|
765
|
-
writer.writeByte(
|
|
913
|
+
const writer = new import_shared4.BinaryWriter();
|
|
914
|
+
writer.writeByte(import_shared4.ServerCommand.print);
|
|
766
915
|
writer.writeByte(2);
|
|
767
916
|
writer.writeString(`Connection rejected: ${result}
|
|
768
917
|
`);
|
|
@@ -786,31 +935,31 @@ var DedicatedServer = class {
|
|
|
786
935
|
console.log(`Client ${client.index} entered game`);
|
|
787
936
|
}
|
|
788
937
|
sendServerData(client) {
|
|
789
|
-
const writer = new
|
|
790
|
-
writer.writeByte(
|
|
938
|
+
const writer = new import_shared4.BinaryWriter();
|
|
939
|
+
writer.writeByte(import_shared4.ServerCommand.serverdata);
|
|
791
940
|
writer.writeLong(34);
|
|
792
941
|
writer.writeLong(this.sv.frame);
|
|
793
942
|
writer.writeByte(0);
|
|
794
943
|
writer.writeString("baseq2");
|
|
795
944
|
writer.writeShort(client.index);
|
|
796
945
|
writer.writeString("maps/test.bsp");
|
|
797
|
-
for (let i = 0; i <
|
|
946
|
+
for (let i = 0; i < import_shared4.MAX_CONFIGSTRINGS; i++) {
|
|
798
947
|
if (this.sv.configStrings[i]) {
|
|
799
948
|
this.SV_WriteConfigString(writer, i, this.sv.configStrings[i]);
|
|
800
949
|
}
|
|
801
950
|
}
|
|
802
|
-
for (let i = 0; i <
|
|
951
|
+
for (let i = 0; i < import_shared4.MAX_EDICTS; i++) {
|
|
803
952
|
if (this.sv.baselines[i]) {
|
|
804
|
-
writer.writeByte(
|
|
953
|
+
writer.writeByte(import_shared4.ServerCommand.spawnbaseline);
|
|
805
954
|
writeDeltaEntity({}, this.sv.baselines[i], writer, true, true);
|
|
806
955
|
}
|
|
807
956
|
}
|
|
808
957
|
client.net.send(writer.getData());
|
|
809
958
|
}
|
|
810
959
|
SV_SetConfigString(index, value) {
|
|
811
|
-
if (index < 0 || index >=
|
|
960
|
+
if (index < 0 || index >= import_shared4.MAX_CONFIGSTRINGS) return;
|
|
812
961
|
this.sv.configStrings[index] = value;
|
|
813
|
-
const writer = new
|
|
962
|
+
const writer = new import_shared4.BinaryWriter();
|
|
814
963
|
this.SV_WriteConfigString(writer, index, value);
|
|
815
964
|
const data = writer.getData();
|
|
816
965
|
for (const client of this.svs.clients) {
|
|
@@ -820,7 +969,7 @@ var DedicatedServer = class {
|
|
|
820
969
|
}
|
|
821
970
|
}
|
|
822
971
|
SV_WriteConfigString(writer, index, value) {
|
|
823
|
-
writer.writeByte(
|
|
972
|
+
writer.writeByte(import_shared4.ServerCommand.configstring);
|
|
824
973
|
writer.writeShort(index);
|
|
825
974
|
writer.writeString(value);
|
|
826
975
|
}
|
|
@@ -830,7 +979,7 @@ var DedicatedServer = class {
|
|
|
830
979
|
while (client.messageQueue.length > 0) {
|
|
831
980
|
const data = client.messageQueue.shift();
|
|
832
981
|
if (!data) continue;
|
|
833
|
-
const reader = new
|
|
982
|
+
const reader = new import_shared4.BinaryStream(data.buffer);
|
|
834
983
|
const parser = new ClientMessageParser(reader, {
|
|
835
984
|
onMove: (checksum, lastFrame, cmd) => this.handleMove(client, cmd),
|
|
836
985
|
onUserInfo: (info) => this.handleUserInfo(client, info),
|
|
@@ -876,13 +1025,13 @@ var DedicatedServer = class {
|
|
|
876
1025
|
}
|
|
877
1026
|
}
|
|
878
1027
|
SV_SendClientFrame(client, snapshot) {
|
|
879
|
-
const writer = new
|
|
880
|
-
writer.writeByte(
|
|
1028
|
+
const writer = new import_shared4.BinaryWriter();
|
|
1029
|
+
writer.writeByte(import_shared4.ServerCommand.frame);
|
|
881
1030
|
writer.writeLong(this.sv.frame);
|
|
882
1031
|
writer.writeLong(0);
|
|
883
1032
|
writer.writeByte(0);
|
|
884
1033
|
writer.writeByte(0);
|
|
885
|
-
writer.writeByte(
|
|
1034
|
+
writer.writeByte(import_shared4.ServerCommand.playerinfo);
|
|
886
1035
|
const ps = {
|
|
887
1036
|
pm_type: snapshot.pmType,
|
|
888
1037
|
origin: snapshot.origin,
|
|
@@ -910,24 +1059,67 @@ var DedicatedServer = class {
|
|
|
910
1059
|
stats: snapshot.stats
|
|
911
1060
|
};
|
|
912
1061
|
writePlayerState(writer, ps);
|
|
913
|
-
writer.writeByte(
|
|
1062
|
+
writer.writeByte(import_shared4.ServerCommand.packetentities);
|
|
914
1063
|
const entities = snapshot.packetEntities || [];
|
|
1064
|
+
const currentEntityIds = [];
|
|
915
1065
|
for (const entity of entities) {
|
|
1066
|
+
currentEntityIds.push(entity.number);
|
|
916
1067
|
writeDeltaEntity({}, entity, writer, false, true);
|
|
917
1068
|
}
|
|
1069
|
+
for (const oldId of client.lastPacketEntities) {
|
|
1070
|
+
if (!currentEntityIds.includes(oldId)) {
|
|
1071
|
+
writeRemoveEntity(oldId, writer);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
918
1074
|
writer.writeShort(0);
|
|
919
1075
|
client.net.send(writer.getData());
|
|
920
1076
|
client.lastFrame = this.sv.frame;
|
|
1077
|
+
client.lastPacketEntities = currentEntityIds;
|
|
921
1078
|
}
|
|
922
1079
|
// GameEngine Implementation
|
|
923
1080
|
trace(start, end) {
|
|
924
1081
|
return { fraction: 1 };
|
|
925
1082
|
}
|
|
926
1083
|
multicast(origin, type, event, ...args) {
|
|
1084
|
+
const writer = new import_shared4.BinaryWriter();
|
|
1085
|
+
writeServerCommand(writer, event, ...args);
|
|
1086
|
+
const data = writer.getData();
|
|
1087
|
+
const reliable = event === import_shared4.ServerCommand.print || event === import_shared4.ServerCommand.configstring;
|
|
1088
|
+
for (const client of this.svs.clients) {
|
|
1089
|
+
if (!client || client.state < 4 /* Active */ || !client.edict) {
|
|
1090
|
+
continue;
|
|
1091
|
+
}
|
|
1092
|
+
let send = false;
|
|
1093
|
+
switch (type) {
|
|
1094
|
+
case import_game.MulticastType.All:
|
|
1095
|
+
send = true;
|
|
1096
|
+
break;
|
|
1097
|
+
case import_game.MulticastType.Pvs:
|
|
1098
|
+
if (this.sv.collisionModel) {
|
|
1099
|
+
send = (0, import_shared4.inPVS)(origin, client.edict.origin, this.sv.collisionModel);
|
|
1100
|
+
} else {
|
|
1101
|
+
send = true;
|
|
1102
|
+
}
|
|
1103
|
+
break;
|
|
1104
|
+
case import_game.MulticastType.Phs:
|
|
1105
|
+
if (this.sv.collisionModel) {
|
|
1106
|
+
send = (0, import_shared4.inPHS)(origin, client.edict.origin, this.sv.collisionModel);
|
|
1107
|
+
} else {
|
|
1108
|
+
send = true;
|
|
1109
|
+
}
|
|
1110
|
+
break;
|
|
1111
|
+
}
|
|
1112
|
+
if (send) {
|
|
1113
|
+
client.net.send(data);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
927
1116
|
}
|
|
928
1117
|
unicast(ent, reliable, event, ...args) {
|
|
929
1118
|
const client = this.svs.clients.find((c) => c?.edict === ent);
|
|
930
|
-
if (client) {
|
|
1119
|
+
if (client && client.state >= 2 /* Connected */) {
|
|
1120
|
+
const writer = new import_shared4.BinaryWriter();
|
|
1121
|
+
writeServerCommand(writer, event, ...args);
|
|
1122
|
+
client.net.send(writer.getData());
|
|
931
1123
|
}
|
|
932
1124
|
}
|
|
933
1125
|
configstring(index, value) {
|
|
@@ -27,6 +27,7 @@ declare class DedicatedServer implements GameEngine {
|
|
|
27
27
|
private entityIndex;
|
|
28
28
|
constructor(port?: number);
|
|
29
29
|
start(mapName: string): Promise<void>;
|
|
30
|
+
private populateBaselines;
|
|
30
31
|
stop(): void;
|
|
31
32
|
private handleConnection;
|
|
32
33
|
private onClientMessage;
|
|
@@ -90,6 +91,7 @@ interface Client {
|
|
|
90
91
|
lastConnect: number;
|
|
91
92
|
challenge: number;
|
|
92
93
|
messageQueue: Uint8Array[];
|
|
94
|
+
lastPacketEntities: number[];
|
|
93
95
|
}
|
|
94
96
|
declare function createClient(index: number, net: NetDriver): Client;
|
|
95
97
|
|
|
@@ -27,6 +27,7 @@ declare class DedicatedServer implements GameEngine {
|
|
|
27
27
|
private entityIndex;
|
|
28
28
|
constructor(port?: number);
|
|
29
29
|
start(mapName: string): Promise<void>;
|
|
30
|
+
private populateBaselines;
|
|
30
31
|
stop(): void;
|
|
31
32
|
private handleConnection;
|
|
32
33
|
private onClientMessage;
|
|
@@ -90,6 +91,7 @@ interface Client {
|
|
|
90
91
|
lastConnect: number;
|
|
91
92
|
challenge: number;
|
|
92
93
|
messageQueue: Uint8Array[];
|
|
94
|
+
lastPacketEntities: number[];
|
|
93
95
|
}
|
|
94
96
|
declare function createClient(index: number, net: NetDriver): Client;
|
|
95
97
|
|