quake2ts 0.0.214 → 0.0.216
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 +51 -1
- package/packages/server/dist/index.d.cts +2 -0
- package/packages/server/dist/index.d.ts +2 -0
- package/packages/server/dist/index.js +52 -2
|
@@ -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() {
|
|
@@ -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) {
|
|
@@ -796,10 +815,33 @@ var DedicatedServer = class {
|
|
|
796
815
|
});
|
|
797
816
|
this.game.init(0);
|
|
798
817
|
this.game.spawnWorld();
|
|
818
|
+
this.populateBaselines();
|
|
799
819
|
this.sv.state = 2 /* Game */;
|
|
800
820
|
this.frameInterval = setInterval(() => this.runFrame(), FRAME_TIME_MS);
|
|
801
821
|
console.log("Server started.");
|
|
802
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
|
+
}
|
|
803
845
|
stop() {
|
|
804
846
|
if (this.frameInterval) clearInterval(this.frameInterval);
|
|
805
847
|
if (this.wss) this.wss.close();
|
|
@@ -1019,12 +1061,20 @@ var DedicatedServer = class {
|
|
|
1019
1061
|
writePlayerState(writer, ps);
|
|
1020
1062
|
writer.writeByte(import_shared4.ServerCommand.packetentities);
|
|
1021
1063
|
const entities = snapshot.packetEntities || [];
|
|
1064
|
+
const currentEntityIds = [];
|
|
1022
1065
|
for (const entity of entities) {
|
|
1066
|
+
currentEntityIds.push(entity.number);
|
|
1023
1067
|
writeDeltaEntity({}, entity, writer, false, true);
|
|
1024
1068
|
}
|
|
1069
|
+
for (const oldId of client.lastPacketEntities) {
|
|
1070
|
+
if (!currentEntityIds.includes(oldId)) {
|
|
1071
|
+
writeRemoveEntity(oldId, writer);
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1025
1074
|
writer.writeShort(0);
|
|
1026
1075
|
client.net.send(writer.getData());
|
|
1027
1076
|
client.lastFrame = this.sv.frame;
|
|
1077
|
+
client.lastPacketEntities = currentEntityIds;
|
|
1028
1078
|
}
|
|
1029
1079
|
// GameEngine Implementation
|
|
1030
1080
|
trace(start, end) {
|
|
@@ -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
|
|
|
@@ -112,7 +112,7 @@ var WebSocketNetDriver = class {
|
|
|
112
112
|
|
|
113
113
|
// src/dedicated.ts
|
|
114
114
|
import { WebSocketServer } from "ws";
|
|
115
|
-
import { createGame, MulticastType } from "@quake2ts/game";
|
|
115
|
+
import { createGame, MulticastType, Solid } from "@quake2ts/game";
|
|
116
116
|
|
|
117
117
|
// src/client.ts
|
|
118
118
|
import { UPDATE_BACKUP } from "@quake2ts/shared";
|
|
@@ -161,7 +161,8 @@ function createClient(index, net) {
|
|
|
161
161
|
lastMessage: 0,
|
|
162
162
|
lastConnect: Date.now(),
|
|
163
163
|
challenge: 0,
|
|
164
|
-
messageQueue: []
|
|
164
|
+
messageQueue: [],
|
|
165
|
+
lastPacketEntities: []
|
|
165
166
|
};
|
|
166
167
|
}
|
|
167
168
|
function createEmptyUserCommand() {
|
|
@@ -305,6 +306,24 @@ var NULL_STATE = {
|
|
|
305
306
|
sound: 0,
|
|
306
307
|
event: 0
|
|
307
308
|
};
|
|
309
|
+
function writeRemoveEntity(number, writer) {
|
|
310
|
+
let bits = U_REMOVE;
|
|
311
|
+
if (number >= 256) {
|
|
312
|
+
bits |= U_NUMBER16;
|
|
313
|
+
}
|
|
314
|
+
if (bits & 65280) {
|
|
315
|
+
bits |= U_MOREBITS1;
|
|
316
|
+
}
|
|
317
|
+
writer.writeByte(bits & 255);
|
|
318
|
+
if (bits & U_MOREBITS1) {
|
|
319
|
+
writer.writeByte(bits >> 8 & 255);
|
|
320
|
+
}
|
|
321
|
+
if (bits & U_NUMBER16) {
|
|
322
|
+
writer.writeShort(number);
|
|
323
|
+
} else {
|
|
324
|
+
writer.writeByte(number);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
308
327
|
function writeDeltaEntity(from, to, writer, force, newEntity) {
|
|
309
328
|
let bits = 0;
|
|
310
329
|
if (newEntity) {
|
|
@@ -756,10 +775,33 @@ var DedicatedServer = class {
|
|
|
756
775
|
});
|
|
757
776
|
this.game.init(0);
|
|
758
777
|
this.game.spawnWorld();
|
|
778
|
+
this.populateBaselines();
|
|
759
779
|
this.sv.state = 2 /* Game */;
|
|
760
780
|
this.frameInterval = setInterval(() => this.runFrame(), FRAME_TIME_MS);
|
|
761
781
|
console.log("Server started.");
|
|
762
782
|
}
|
|
783
|
+
populateBaselines() {
|
|
784
|
+
if (!this.game) return;
|
|
785
|
+
this.game.entities.forEachEntity((ent) => {
|
|
786
|
+
if (ent.index >= MAX_EDICTS) return;
|
|
787
|
+
if (ent.modelindex > 0 || ent.solid !== Solid.Not) {
|
|
788
|
+
this.sv.baselines[ent.index] = {
|
|
789
|
+
number: ent.index,
|
|
790
|
+
origin: { ...ent.origin },
|
|
791
|
+
angles: { ...ent.angles },
|
|
792
|
+
modelIndex: ent.modelindex,
|
|
793
|
+
frame: ent.frame,
|
|
794
|
+
skinNum: ent.skin,
|
|
795
|
+
effects: ent.effects,
|
|
796
|
+
renderfx: ent.renderfx,
|
|
797
|
+
solid: ent.solid,
|
|
798
|
+
sound: ent.sounds,
|
|
799
|
+
// Assuming ent.sounds maps to 'sound' field in EntityState
|
|
800
|
+
event: 0
|
|
801
|
+
};
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
}
|
|
763
805
|
stop() {
|
|
764
806
|
if (this.frameInterval) clearInterval(this.frameInterval);
|
|
765
807
|
if (this.wss) this.wss.close();
|
|
@@ -979,12 +1021,20 @@ var DedicatedServer = class {
|
|
|
979
1021
|
writePlayerState(writer, ps);
|
|
980
1022
|
writer.writeByte(ServerCommand2.packetentities);
|
|
981
1023
|
const entities = snapshot.packetEntities || [];
|
|
1024
|
+
const currentEntityIds = [];
|
|
982
1025
|
for (const entity of entities) {
|
|
1026
|
+
currentEntityIds.push(entity.number);
|
|
983
1027
|
writeDeltaEntity({}, entity, writer, false, true);
|
|
984
1028
|
}
|
|
1029
|
+
for (const oldId of client.lastPacketEntities) {
|
|
1030
|
+
if (!currentEntityIds.includes(oldId)) {
|
|
1031
|
+
writeRemoveEntity(oldId, writer);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
985
1034
|
writer.writeShort(0);
|
|
986
1035
|
client.net.send(writer.getData());
|
|
987
1036
|
client.lastFrame = this.sv.frame;
|
|
1037
|
+
client.lastPacketEntities = currentEntityIds;
|
|
988
1038
|
}
|
|
989
1039
|
// GameEngine Implementation
|
|
990
1040
|
trace(start, end) {
|