quake2ts 0.0.220 → 0.0.221
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
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quake2ts",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.221",
|
|
4
4
|
"description": "Quake II re-release port to TypeScript with WebGL renderer - A complete game engine with physics, networking, and BSP rendering",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "pnpm@8.15.7",
|
|
@@ -174,7 +174,8 @@ function createClient(index, net) {
|
|
|
174
174
|
playerState: createEmptyPlayerState(),
|
|
175
175
|
numEntities: 0,
|
|
176
176
|
firstEntity: 0,
|
|
177
|
-
sentTime: 0
|
|
177
|
+
sentTime: 0,
|
|
178
|
+
entities: []
|
|
178
179
|
});
|
|
179
180
|
}
|
|
180
181
|
return {
|
|
@@ -825,23 +826,26 @@ var DedicatedServer = class {
|
|
|
825
826
|
this.game.entities.forEachEntity((ent) => {
|
|
826
827
|
if (ent.index >= import_shared4.MAX_EDICTS) return;
|
|
827
828
|
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
|
-
};
|
|
829
|
+
this.sv.baselines[ent.index] = this.entityToState(ent);
|
|
842
830
|
}
|
|
843
831
|
});
|
|
844
832
|
}
|
|
833
|
+
entityToState(ent) {
|
|
834
|
+
return {
|
|
835
|
+
number: ent.index,
|
|
836
|
+
origin: { ...ent.origin },
|
|
837
|
+
angles: { ...ent.angles },
|
|
838
|
+
modelIndex: ent.modelindex,
|
|
839
|
+
frame: ent.frame,
|
|
840
|
+
skinNum: ent.skin,
|
|
841
|
+
effects: ent.effects,
|
|
842
|
+
renderfx: ent.renderfx,
|
|
843
|
+
solid: ent.solid,
|
|
844
|
+
sound: ent.sounds,
|
|
845
|
+
// Assuming ent.sounds maps to 'sound' field in EntityState
|
|
846
|
+
event: 0
|
|
847
|
+
};
|
|
848
|
+
}
|
|
845
849
|
stop() {
|
|
846
850
|
if (this.frameTimeout) clearTimeout(this.frameTimeout);
|
|
847
851
|
if (this.wss) this.wss.close();
|
|
@@ -1036,7 +1040,11 @@ var DedicatedServer = class {
|
|
|
1036
1040
|
const writer = new import_shared4.BinaryWriter(MTU);
|
|
1037
1041
|
writer.writeByte(import_shared4.ServerCommand.frame);
|
|
1038
1042
|
writer.writeLong(this.sv.frame);
|
|
1039
|
-
|
|
1043
|
+
let deltaFrame = 0;
|
|
1044
|
+
if (client.lastFrame && client.lastFrame < this.sv.frame && client.lastFrame >= this.sv.frame - import_shared4.UPDATE_BACKUP) {
|
|
1045
|
+
deltaFrame = client.lastFrame;
|
|
1046
|
+
}
|
|
1047
|
+
writer.writeLong(deltaFrame);
|
|
1040
1048
|
writer.writeByte(0);
|
|
1041
1049
|
writer.writeByte(0);
|
|
1042
1050
|
writer.writeByte(import_shared4.ServerCommand.playerinfo);
|
|
@@ -1070,13 +1078,26 @@ var DedicatedServer = class {
|
|
|
1070
1078
|
writer.writeByte(import_shared4.ServerCommand.packetentities);
|
|
1071
1079
|
const entities = snapshot.packetEntities || [];
|
|
1072
1080
|
const currentEntityIds = [];
|
|
1073
|
-
|
|
1081
|
+
const frameIdx = this.sv.frame % import_shared4.UPDATE_BACKUP;
|
|
1082
|
+
const currentFrame = client.frames[frameIdx];
|
|
1083
|
+
currentFrame.entities = entities;
|
|
1084
|
+
let oldEntities = [];
|
|
1085
|
+
if (deltaFrame > 0) {
|
|
1086
|
+
const oldFrameIdx = deltaFrame % import_shared4.UPDATE_BACKUP;
|
|
1087
|
+
oldEntities = client.frames[oldFrameIdx].entities;
|
|
1088
|
+
}
|
|
1089
|
+
for (const entityState of currentFrame.entities) {
|
|
1074
1090
|
if (writer.getOffset() > MTU - 200) {
|
|
1075
1091
|
console.warn("Packet MTU limit reached, dropping remaining entities");
|
|
1076
1092
|
break;
|
|
1077
1093
|
}
|
|
1078
|
-
currentEntityIds.push(
|
|
1079
|
-
|
|
1094
|
+
currentEntityIds.push(entityState.number);
|
|
1095
|
+
const oldState = oldEntities.find((e) => e.number === entityState.number);
|
|
1096
|
+
if (oldState) {
|
|
1097
|
+
writeDeltaEntity(oldState, entityState, writer, false, false);
|
|
1098
|
+
} else {
|
|
1099
|
+
writeDeltaEntity({}, entityState, writer, false, true);
|
|
1100
|
+
}
|
|
1080
1101
|
}
|
|
1081
1102
|
for (const oldId of client.lastPacketEntities) {
|
|
1082
1103
|
if (writer.getOffset() > MTU - 10) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NetDriver, ServerCommand, PlayerState, UserCommand, BinaryStream } from '@quake2ts/shared';
|
|
1
|
+
import { NetDriver, ServerCommand, PlayerState, EntityState, UserCommand, BinaryStream } from '@quake2ts/shared';
|
|
2
2
|
import WebSocket from 'ws';
|
|
3
3
|
import { GameEngine, MulticastType, Entity } from '@quake2ts/game';
|
|
4
4
|
|
|
@@ -28,6 +28,7 @@ declare class DedicatedServer implements GameEngine {
|
|
|
28
28
|
constructor(port?: number);
|
|
29
29
|
start(mapName: string): Promise<void>;
|
|
30
30
|
private populateBaselines;
|
|
31
|
+
private entityToState;
|
|
31
32
|
stop(): void;
|
|
32
33
|
private handleConnection;
|
|
33
34
|
private onClientMessage;
|
|
@@ -65,6 +66,7 @@ interface ClientFrame {
|
|
|
65
66
|
numEntities: number;
|
|
66
67
|
firstEntity: number;
|
|
67
68
|
sentTime: number;
|
|
69
|
+
entities: EntityState[];
|
|
68
70
|
}
|
|
69
71
|
interface Client {
|
|
70
72
|
index: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NetDriver, ServerCommand, PlayerState, UserCommand, BinaryStream } from '@quake2ts/shared';
|
|
1
|
+
import { NetDriver, ServerCommand, PlayerState, EntityState, UserCommand, BinaryStream } from '@quake2ts/shared';
|
|
2
2
|
import WebSocket from 'ws';
|
|
3
3
|
import { GameEngine, MulticastType, Entity } from '@quake2ts/game';
|
|
4
4
|
|
|
@@ -28,6 +28,7 @@ declare class DedicatedServer implements GameEngine {
|
|
|
28
28
|
constructor(port?: number);
|
|
29
29
|
start(mapName: string): Promise<void>;
|
|
30
30
|
private populateBaselines;
|
|
31
|
+
private entityToState;
|
|
31
32
|
stop(): void;
|
|
32
33
|
private handleConnection;
|
|
33
34
|
private onClientMessage;
|
|
@@ -65,6 +66,7 @@ interface ClientFrame {
|
|
|
65
66
|
numEntities: number;
|
|
66
67
|
firstEntity: number;
|
|
67
68
|
sentTime: number;
|
|
69
|
+
entities: EntityState[];
|
|
68
70
|
}
|
|
69
71
|
interface Client {
|
|
70
72
|
index: number;
|
|
@@ -134,7 +134,8 @@ function createClient(index, net) {
|
|
|
134
134
|
playerState: createEmptyPlayerState(),
|
|
135
135
|
numEntities: 0,
|
|
136
136
|
firstEntity: 0,
|
|
137
|
-
sentTime: 0
|
|
137
|
+
sentTime: 0,
|
|
138
|
+
entities: []
|
|
138
139
|
});
|
|
139
140
|
}
|
|
140
141
|
return {
|
|
@@ -263,7 +264,7 @@ var ClientMessageParser = class {
|
|
|
263
264
|
};
|
|
264
265
|
|
|
265
266
|
// src/dedicated.ts
|
|
266
|
-
import { BinaryWriter as BinaryWriter2, ServerCommand as ServerCommand2, BinaryStream as BinaryStream2, traceBox, MAX_CONFIGSTRINGS as MAX_CONFIGSTRINGS2, MAX_EDICTS, CollisionEntityIndex, inPVS, inPHS } from "@quake2ts/shared";
|
|
267
|
+
import { BinaryWriter as BinaryWriter2, ServerCommand as ServerCommand2, BinaryStream as BinaryStream2, traceBox, UPDATE_BACKUP as UPDATE_BACKUP2, MAX_CONFIGSTRINGS as MAX_CONFIGSTRINGS2, MAX_EDICTS, CollisionEntityIndex, inPVS, inPHS } from "@quake2ts/shared";
|
|
267
268
|
import { parseBsp } from "@quake2ts/engine";
|
|
268
269
|
import fs from "fs/promises";
|
|
269
270
|
import { createPlayerInventory, createPlayerWeaponStates } from "@quake2ts/game";
|
|
@@ -785,23 +786,26 @@ var DedicatedServer = class {
|
|
|
785
786
|
this.game.entities.forEachEntity((ent) => {
|
|
786
787
|
if (ent.index >= MAX_EDICTS) return;
|
|
787
788
|
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
|
-
};
|
|
789
|
+
this.sv.baselines[ent.index] = this.entityToState(ent);
|
|
802
790
|
}
|
|
803
791
|
});
|
|
804
792
|
}
|
|
793
|
+
entityToState(ent) {
|
|
794
|
+
return {
|
|
795
|
+
number: ent.index,
|
|
796
|
+
origin: { ...ent.origin },
|
|
797
|
+
angles: { ...ent.angles },
|
|
798
|
+
modelIndex: ent.modelindex,
|
|
799
|
+
frame: ent.frame,
|
|
800
|
+
skinNum: ent.skin,
|
|
801
|
+
effects: ent.effects,
|
|
802
|
+
renderfx: ent.renderfx,
|
|
803
|
+
solid: ent.solid,
|
|
804
|
+
sound: ent.sounds,
|
|
805
|
+
// Assuming ent.sounds maps to 'sound' field in EntityState
|
|
806
|
+
event: 0
|
|
807
|
+
};
|
|
808
|
+
}
|
|
805
809
|
stop() {
|
|
806
810
|
if (this.frameTimeout) clearTimeout(this.frameTimeout);
|
|
807
811
|
if (this.wss) this.wss.close();
|
|
@@ -996,7 +1000,11 @@ var DedicatedServer = class {
|
|
|
996
1000
|
const writer = new BinaryWriter2(MTU);
|
|
997
1001
|
writer.writeByte(ServerCommand2.frame);
|
|
998
1002
|
writer.writeLong(this.sv.frame);
|
|
999
|
-
|
|
1003
|
+
let deltaFrame = 0;
|
|
1004
|
+
if (client.lastFrame && client.lastFrame < this.sv.frame && client.lastFrame >= this.sv.frame - UPDATE_BACKUP2) {
|
|
1005
|
+
deltaFrame = client.lastFrame;
|
|
1006
|
+
}
|
|
1007
|
+
writer.writeLong(deltaFrame);
|
|
1000
1008
|
writer.writeByte(0);
|
|
1001
1009
|
writer.writeByte(0);
|
|
1002
1010
|
writer.writeByte(ServerCommand2.playerinfo);
|
|
@@ -1030,13 +1038,26 @@ var DedicatedServer = class {
|
|
|
1030
1038
|
writer.writeByte(ServerCommand2.packetentities);
|
|
1031
1039
|
const entities = snapshot.packetEntities || [];
|
|
1032
1040
|
const currentEntityIds = [];
|
|
1033
|
-
|
|
1041
|
+
const frameIdx = this.sv.frame % UPDATE_BACKUP2;
|
|
1042
|
+
const currentFrame = client.frames[frameIdx];
|
|
1043
|
+
currentFrame.entities = entities;
|
|
1044
|
+
let oldEntities = [];
|
|
1045
|
+
if (deltaFrame > 0) {
|
|
1046
|
+
const oldFrameIdx = deltaFrame % UPDATE_BACKUP2;
|
|
1047
|
+
oldEntities = client.frames[oldFrameIdx].entities;
|
|
1048
|
+
}
|
|
1049
|
+
for (const entityState of currentFrame.entities) {
|
|
1034
1050
|
if (writer.getOffset() > MTU - 200) {
|
|
1035
1051
|
console.warn("Packet MTU limit reached, dropping remaining entities");
|
|
1036
1052
|
break;
|
|
1037
1053
|
}
|
|
1038
|
-
currentEntityIds.push(
|
|
1039
|
-
|
|
1054
|
+
currentEntityIds.push(entityState.number);
|
|
1055
|
+
const oldState = oldEntities.find((e) => e.number === entityState.number);
|
|
1056
|
+
if (oldState) {
|
|
1057
|
+
writeDeltaEntity(oldState, entityState, writer, false, false);
|
|
1058
|
+
} else {
|
|
1059
|
+
writeDeltaEntity({}, entityState, writer, false, true);
|
|
1060
|
+
}
|
|
1040
1061
|
}
|
|
1041
1062
|
for (const oldId of client.lastPacketEntities) {
|
|
1042
1063
|
if (writer.getOffset() > MTU - 10) {
|