quake2ts 0.0.298 → 0.0.301
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/cgame/dist/index.cjs +52 -1
- package/packages/cgame/dist/index.cjs.map +1 -1
- package/packages/cgame/dist/index.d.cts +7 -0
- package/packages/cgame/dist/index.d.ts +7 -0
- package/packages/cgame/dist/index.js +53 -2
- package/packages/cgame/dist/index.js.map +1 -1
- package/packages/client/dist/browser/index.global.js +13 -13
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/client/dist/cjs/index.cjs +166 -10
- package/packages/client/dist/cjs/index.cjs.map +1 -1
- package/packages/client/dist/esm/index.js +161 -5
- package/packages/client/dist/esm/index.js.map +1 -1
- package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/client/dist/types/cgameBridge.d.ts.map +1 -1
- package/packages/client/dist/types/index.d.ts.map +1 -1
- package/packages/client/dist/types/input/controller.d.ts +1 -0
- package/packages/client/dist/types/input/controller.d.ts.map +1 -1
- package/packages/client/dist/types/net/connection.d.ts +3 -0
- package/packages/client/dist/types/net/connection.d.ts.map +1 -1
- package/packages/client/dist/types/ui/demo-controls.d.ts +11 -0
- package/packages/client/dist/types/ui/demo-controls.d.ts.map +1 -0
- package/packages/engine/dist/browser/index.global.js.map +1 -1
- package/packages/engine/dist/cjs/index.cjs.map +1 -1
- package/packages/engine/dist/esm/index.js.map +1 -1
- package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/browser/index.global.js +4 -4
- package/packages/game/dist/browser/index.global.js.map +1 -1
- package/packages/game/dist/cjs/index.cjs +17 -10
- package/packages/game/dist/cjs/index.cjs.map +1 -1
- package/packages/game/dist/esm/index.js +17 -10
- package/packages/game/dist/esm/index.js.map +1 -1
- package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/game/dist/types/entities/gibs.d.ts +1 -1
- package/packages/game/dist/types/entities/gibs.d.ts.map +1 -1
- package/packages/server/dist/index.cjs +9 -2
- package/packages/server/dist/index.js +9 -2
- package/packages/shared/dist/browser/index.global.js.map +1 -1
- package/packages/shared/dist/cjs/index.cjs.map +1 -1
- package/packages/shared/dist/esm/index.js.map +1 -1
- package/packages/shared/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/shared/dist/types/protocol/usercmd.d.ts +3 -0
- package/packages/shared/dist/types/protocol/usercmd.d.ts.map +1 -1
- package/packages/tools/dist/tsconfig.tsbuildinfo +1 -1
|
@@ -22,15 +22,15 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
ClientConfigStrings: () => ClientConfigStrings,
|
|
24
24
|
ClientMode: () => ClientMode,
|
|
25
|
-
ClientPrediction: () =>
|
|
25
|
+
ClientPrediction: () => import_cgame5.ClientPrediction,
|
|
26
26
|
InputAction: () => InputAction,
|
|
27
27
|
InputBindings: () => InputBindings,
|
|
28
28
|
InputCommandBuffer: () => InputCommandBuffer,
|
|
29
29
|
InputController: () => InputController,
|
|
30
|
-
ViewEffects: () =>
|
|
30
|
+
ViewEffects: () => import_cgame6.ViewEffects,
|
|
31
31
|
createClient: () => createClient,
|
|
32
32
|
createDefaultBindings: () => createDefaultBindings,
|
|
33
|
-
interpolatePredictionState: () =>
|
|
33
|
+
interpolatePredictionState: () => import_cgame5.interpolatePredictionState,
|
|
34
34
|
normalizeCommand: () => normalizeCommand,
|
|
35
35
|
normalizeInputCode: () => normalizeInputCode
|
|
36
36
|
});
|
|
@@ -8341,6 +8341,13 @@ var NetworkMessageParser = class _NetworkMessageParser {
|
|
|
8341
8341
|
if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = this.stream.readShort();
|
|
8342
8342
|
}
|
|
8343
8343
|
};
|
|
8344
|
+
var PlaybackState = /* @__PURE__ */ ((PlaybackState22) => {
|
|
8345
|
+
PlaybackState22[PlaybackState22["Stopped"] = 0] = "Stopped";
|
|
8346
|
+
PlaybackState22[PlaybackState22["Playing"] = 1] = "Playing";
|
|
8347
|
+
PlaybackState22[PlaybackState22["Paused"] = 2] = "Paused";
|
|
8348
|
+
PlaybackState22[PlaybackState22["Finished"] = 3] = "Finished";
|
|
8349
|
+
return PlaybackState22;
|
|
8350
|
+
})(PlaybackState || {});
|
|
8344
8351
|
var DemoPlaybackController = class {
|
|
8345
8352
|
// ms (10Hz default)
|
|
8346
8353
|
constructor() {
|
|
@@ -9655,8 +9662,8 @@ var AmmoType2 = /* @__PURE__ */ ((AmmoType22) => {
|
|
|
9655
9662
|
var AMMO_TYPE_COUNT2 = Object.keys(AmmoType2).length / 2;
|
|
9656
9663
|
|
|
9657
9664
|
// src/index.ts
|
|
9658
|
-
var import_cgame2 = require("@quake2ts/cgame");
|
|
9659
9665
|
var import_cgame3 = require("@quake2ts/cgame");
|
|
9666
|
+
var import_cgame4 = require("@quake2ts/cgame");
|
|
9660
9667
|
|
|
9661
9668
|
// src/cgameBridge.ts
|
|
9662
9669
|
function createCGameImport(imports, state) {
|
|
@@ -9706,6 +9713,24 @@ function createCGameImport(imports, state) {
|
|
|
9706
9713
|
flags
|
|
9707
9714
|
});
|
|
9708
9715
|
},
|
|
9716
|
+
Cvar_Get: (name, value, flags) => {
|
|
9717
|
+
if (!imports.host || !imports.host.cvars) {
|
|
9718
|
+
return { value: parseInt(value) || 0 };
|
|
9719
|
+
}
|
|
9720
|
+
let existing = imports.host.cvars.get(name);
|
|
9721
|
+
if (!existing) {
|
|
9722
|
+
existing = imports.host.cvars.register({
|
|
9723
|
+
name,
|
|
9724
|
+
defaultValue: value,
|
|
9725
|
+
flags
|
|
9726
|
+
});
|
|
9727
|
+
}
|
|
9728
|
+
return {
|
|
9729
|
+
get value() {
|
|
9730
|
+
return existing.number;
|
|
9731
|
+
}
|
|
9732
|
+
};
|
|
9733
|
+
},
|
|
9709
9734
|
cvar_set: (name, value) => {
|
|
9710
9735
|
imports.host?.cvars?.setValue(name, value);
|
|
9711
9736
|
},
|
|
@@ -11643,6 +11668,7 @@ var BrowserWebSocketNetDriver = class {
|
|
|
11643
11668
|
};
|
|
11644
11669
|
|
|
11645
11670
|
// src/net/connection.ts
|
|
11671
|
+
var import_cgame2 = require("@quake2ts/cgame");
|
|
11646
11672
|
var MultiplayerConnection = class {
|
|
11647
11673
|
constructor(options) {
|
|
11648
11674
|
this.state = 0 /* Disconnected */;
|
|
@@ -11660,6 +11686,8 @@ var MultiplayerConnection = class {
|
|
|
11660
11686
|
this.connectPacketTime = 0;
|
|
11661
11687
|
this.latestServerFrame = 0;
|
|
11662
11688
|
this.commandHistory = [];
|
|
11689
|
+
// Prediction
|
|
11690
|
+
this.prediction = null;
|
|
11663
11691
|
this.driver = new BrowserWebSocketNetDriver();
|
|
11664
11692
|
this.options = options;
|
|
11665
11693
|
this.netchan = new NetChan();
|
|
@@ -11667,6 +11695,9 @@ var MultiplayerConnection = class {
|
|
|
11667
11695
|
this.driver.onClose(() => this.handleDisconnect());
|
|
11668
11696
|
this.driver.onError((err2) => console.error("Network Error:", err2));
|
|
11669
11697
|
}
|
|
11698
|
+
setPrediction(prediction) {
|
|
11699
|
+
this.prediction = prediction;
|
|
11700
|
+
}
|
|
11670
11701
|
async connect(url) {
|
|
11671
11702
|
if (this.state !== 0 /* Disconnected */) {
|
|
11672
11703
|
this.disconnect();
|
|
@@ -11704,6 +11735,9 @@ var MultiplayerConnection = class {
|
|
|
11704
11735
|
if (this.commandHistory.length > CMD_BACKUP) {
|
|
11705
11736
|
this.commandHistory.shift();
|
|
11706
11737
|
}
|
|
11738
|
+
if (this.prediction) {
|
|
11739
|
+
this.prediction.enqueueCommand(commandWithFrame);
|
|
11740
|
+
}
|
|
11707
11741
|
const writer = new BinaryWriter2();
|
|
11708
11742
|
writer.writeByte(ClientCommand.move);
|
|
11709
11743
|
writer.writeByte(0);
|
|
@@ -11801,6 +11835,31 @@ var MultiplayerConnection = class {
|
|
|
11801
11835
|
if (frame.serverFrame > this.latestServerFrame) {
|
|
11802
11836
|
this.latestServerFrame = frame.serverFrame;
|
|
11803
11837
|
}
|
|
11838
|
+
if (this.prediction && frame.playerState) {
|
|
11839
|
+
const ps = frame.playerState;
|
|
11840
|
+
const predState = {
|
|
11841
|
+
...(0, import_cgame2.defaultPredictionState)(),
|
|
11842
|
+
// Manual mapping due to type mismatch (MutableVec3 vs Vec3, and property names)
|
|
11843
|
+
origin: { x: ps.origin.x, y: ps.origin.y, z: ps.origin.z },
|
|
11844
|
+
velocity: { x: ps.velocity.x, y: ps.velocity.y, z: ps.velocity.z },
|
|
11845
|
+
viewAngles: { x: ps.viewangles.x, y: ps.viewangles.y, z: ps.viewangles.z },
|
|
11846
|
+
deltaAngles: { x: ps.delta_angles.x, y: ps.delta_angles.y, z: ps.delta_angles.z },
|
|
11847
|
+
pmFlags: ps.pm_flags,
|
|
11848
|
+
pmType: ps.pm_type,
|
|
11849
|
+
gravity: ps.gravity,
|
|
11850
|
+
// Copy other matching fields
|
|
11851
|
+
health: ps.stats[0]
|
|
11852
|
+
// Assuming stat 0 is health? Or generic copy
|
|
11853
|
+
// ...
|
|
11854
|
+
};
|
|
11855
|
+
const gameFrame = {
|
|
11856
|
+
frame: frame.serverFrame,
|
|
11857
|
+
timeMs: 0,
|
|
11858
|
+
// Should be server time, but frame doesn't always have it explicitly?
|
|
11859
|
+
state: predState
|
|
11860
|
+
};
|
|
11861
|
+
this.prediction.setAuthoritative(gameFrame);
|
|
11862
|
+
}
|
|
11804
11863
|
}
|
|
11805
11864
|
// Stubs for other handlers
|
|
11806
11865
|
onCenterPrint(msg) {
|
|
@@ -11828,6 +11887,89 @@ var MultiplayerConnection = class {
|
|
|
11828
11887
|
}
|
|
11829
11888
|
};
|
|
11830
11889
|
|
|
11890
|
+
// src/ui/demo-controls.ts
|
|
11891
|
+
var DemoControls = class {
|
|
11892
|
+
constructor(playback) {
|
|
11893
|
+
this.isVisible = true;
|
|
11894
|
+
this.playback = playback;
|
|
11895
|
+
}
|
|
11896
|
+
render(renderer, width, height) {
|
|
11897
|
+
if (!this.isVisible) return;
|
|
11898
|
+
const state = this.playback.getState();
|
|
11899
|
+
const isPlaying = state === PlaybackState.Playing;
|
|
11900
|
+
const overlayHeight = 60;
|
|
11901
|
+
const y = height - overlayHeight;
|
|
11902
|
+
renderer.drawfillRect(0, y, width, overlayHeight, [0, 0, 0, 0.5]);
|
|
11903
|
+
const iconSize = 24;
|
|
11904
|
+
const iconY = y + (overlayHeight - iconSize) / 2;
|
|
11905
|
+
const iconX = 20;
|
|
11906
|
+
const statusText = isPlaying ? "PAUSE" : "PLAY";
|
|
11907
|
+
renderer.drawString(iconX, iconY, statusText);
|
|
11908
|
+
const speed = this.playback.getSpeed();
|
|
11909
|
+
const speedText = `Speed: ${speed}x`;
|
|
11910
|
+
renderer.drawCenterString(iconY, speedText);
|
|
11911
|
+
const currentTime = this.playback.getCurrentTime();
|
|
11912
|
+
const currentFormatted = this.formatTime(currentTime);
|
|
11913
|
+
const totalFormatted = "--:--";
|
|
11914
|
+
const timeText = `${currentFormatted} / ${totalFormatted}`;
|
|
11915
|
+
const timeX = width - 150;
|
|
11916
|
+
renderer.drawString(timeX, iconY, timeText);
|
|
11917
|
+
const timelineY = y + 5;
|
|
11918
|
+
const timelineHeight = 4;
|
|
11919
|
+
const timelineWidth = width - 40;
|
|
11920
|
+
const timelineX = 20;
|
|
11921
|
+
renderer.drawfillRect(timelineX, timelineY, timelineWidth, timelineHeight, [0.3, 0.3, 0.3, 1]);
|
|
11922
|
+
const progress = 0;
|
|
11923
|
+
const progressWidth = timelineWidth * progress;
|
|
11924
|
+
renderer.drawfillRect(timelineX, timelineY, progressWidth, timelineHeight, [1, 1, 1, 1]);
|
|
11925
|
+
const markerX = timelineX + progressWidth;
|
|
11926
|
+
renderer.drawfillRect(markerX - 2, timelineY - 2, 4, timelineHeight + 4, [1, 0, 0, 1]);
|
|
11927
|
+
const helpText = "[Space] Toggle [< >] Step [ [ ] ] Speed [Esc] Stop";
|
|
11928
|
+
renderer.drawCenterString(y + 35, helpText);
|
|
11929
|
+
}
|
|
11930
|
+
handleInput(key, down) {
|
|
11931
|
+
if (!down) return false;
|
|
11932
|
+
switch (key.toLowerCase()) {
|
|
11933
|
+
case " ":
|
|
11934
|
+
if (this.playback.getState() === PlaybackState.Playing) {
|
|
11935
|
+
this.playback.pause();
|
|
11936
|
+
} else if (this.playback.getState() === PlaybackState.Paused) {
|
|
11937
|
+
this.playback.play();
|
|
11938
|
+
}
|
|
11939
|
+
return true;
|
|
11940
|
+
case "arrowright":
|
|
11941
|
+
this.playback.stepForward();
|
|
11942
|
+
return true;
|
|
11943
|
+
case "arrowleft":
|
|
11944
|
+
this.playback.stepBackward();
|
|
11945
|
+
return true;
|
|
11946
|
+
case "]":
|
|
11947
|
+
this.changeSpeed(2);
|
|
11948
|
+
return true;
|
|
11949
|
+
case "[":
|
|
11950
|
+
this.changeSpeed(0.5);
|
|
11951
|
+
return true;
|
|
11952
|
+
case "escape":
|
|
11953
|
+
this.playback.stop();
|
|
11954
|
+
return true;
|
|
11955
|
+
}
|
|
11956
|
+
return false;
|
|
11957
|
+
}
|
|
11958
|
+
changeSpeed(factor) {
|
|
11959
|
+
const current = this.playback.getSpeed();
|
|
11960
|
+
let newSpeed = current * factor;
|
|
11961
|
+
if (newSpeed < 0.1) newSpeed = 0.1;
|
|
11962
|
+
if (newSpeed > 16) newSpeed = 16;
|
|
11963
|
+
this.playback.setSpeed(newSpeed);
|
|
11964
|
+
}
|
|
11965
|
+
formatTime(ms) {
|
|
11966
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
11967
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
11968
|
+
const seconds = totalSeconds % 60;
|
|
11969
|
+
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
11970
|
+
}
|
|
11971
|
+
};
|
|
11972
|
+
|
|
11831
11973
|
// src/input/bindings.ts
|
|
11832
11974
|
var DEFAULT_BINDINGS = [
|
|
11833
11975
|
{ code: "KeyW", command: "+forward" },
|
|
@@ -11992,6 +12134,7 @@ var InputController = class {
|
|
|
11992
12134
|
this.touchButtons = /* @__PURE__ */ new Map();
|
|
11993
12135
|
this.touchMove = { x: 0, y: 0 };
|
|
11994
12136
|
this.touchLook = { x: 0, y: 0 };
|
|
12137
|
+
this.sequence = 0;
|
|
11995
12138
|
this.bindings = bindings;
|
|
11996
12139
|
this.forwardSpeed = options.forwardSpeed ?? DEFAULT_FORWARD_SPEED;
|
|
11997
12140
|
this.sideSpeed = options.sideSpeed ?? DEFAULT_SIDE_SPEED;
|
|
@@ -12130,6 +12273,7 @@ var InputController = class {
|
|
|
12130
12273
|
buttons |= PlayerButton.Any;
|
|
12131
12274
|
}
|
|
12132
12275
|
this.anyPressed = false;
|
|
12276
|
+
this.sequence++;
|
|
12133
12277
|
return {
|
|
12134
12278
|
msec,
|
|
12135
12279
|
buttons,
|
|
@@ -12137,7 +12281,10 @@ var InputController = class {
|
|
|
12137
12281
|
forwardmove,
|
|
12138
12282
|
sidemove,
|
|
12139
12283
|
upmove,
|
|
12140
|
-
serverFrame
|
|
12284
|
+
serverFrame,
|
|
12285
|
+
sequence: this.sequence,
|
|
12286
|
+
lightlevel: 0,
|
|
12287
|
+
impulse: 0
|
|
12141
12288
|
};
|
|
12142
12289
|
}
|
|
12143
12290
|
consumeConsoleCommands() {
|
|
@@ -12317,8 +12464,8 @@ var InputCommandBuffer = class {
|
|
|
12317
12464
|
};
|
|
12318
12465
|
|
|
12319
12466
|
// src/index.ts
|
|
12320
|
-
var import_cgame4 = require("@quake2ts/cgame");
|
|
12321
12467
|
var import_cgame5 = require("@quake2ts/cgame");
|
|
12468
|
+
var import_cgame6 = require("@quake2ts/cgame");
|
|
12322
12469
|
var ZERO_VEC32 = { x: 0, y: 0, z: 0 };
|
|
12323
12470
|
var ClientMode = /* @__PURE__ */ ((ClientMode2) => {
|
|
12324
12471
|
ClientMode2[ClientMode2["Normal"] = 0] = "Normal";
|
|
@@ -12332,9 +12479,10 @@ function createClient(imports) {
|
|
|
12332
12479
|
const tr = imports.engine.trace(point, point, zero3, zero3);
|
|
12333
12480
|
return tr.contents || 0;
|
|
12334
12481
|
};
|
|
12335
|
-
const prediction = new
|
|
12336
|
-
const view = new
|
|
12482
|
+
const prediction = new import_cgame3.ClientPrediction(imports.engine.trace, pointContents);
|
|
12483
|
+
const view = new import_cgame4.ViewEffects();
|
|
12337
12484
|
const demoPlayback = new DemoPlaybackController();
|
|
12485
|
+
const demoControls = new DemoControls(demoPlayback);
|
|
12338
12486
|
const demoHandler = new ClientNetworkHandler(imports);
|
|
12339
12487
|
demoHandler.setView(view);
|
|
12340
12488
|
let isDemoPlaying = false;
|
|
@@ -12375,7 +12523,7 @@ function createClient(imports) {
|
|
|
12375
12523
|
}
|
|
12376
12524
|
};
|
|
12377
12525
|
const cgameImport = createCGameImport(imports, stateProvider);
|
|
12378
|
-
const cg = (0,
|
|
12526
|
+
const cg = (0, import_cgame3.GetCGameAPI)(cgameImport);
|
|
12379
12527
|
const multiplayer = new MultiplayerConnection({
|
|
12380
12528
|
get username() {
|
|
12381
12529
|
return imports.host?.cvars?.get("name")?.string || "Player";
|
|
@@ -12529,6 +12677,11 @@ function createClient(imports) {
|
|
|
12529
12677
|
return prediction.enqueueCommand(command);
|
|
12530
12678
|
},
|
|
12531
12679
|
handleInput(key, down) {
|
|
12680
|
+
if (isDemoPlaying) {
|
|
12681
|
+
if (demoControls.handleInput(key, down)) {
|
|
12682
|
+
return true;
|
|
12683
|
+
}
|
|
12684
|
+
}
|
|
12532
12685
|
if (!menuSystem.isActive()) return false;
|
|
12533
12686
|
if (!down) return true;
|
|
12534
12687
|
const lowerKey = key.toLowerCase();
|
|
@@ -12614,7 +12767,7 @@ function createClient(imports) {
|
|
|
12614
12767
|
latestFrame = sample.latest;
|
|
12615
12768
|
}
|
|
12616
12769
|
if (sample.previous?.state && sample.latest?.state) {
|
|
12617
|
-
lastRendered = (0,
|
|
12770
|
+
lastRendered = (0, import_cgame3.interpolatePredictionState)(sample.previous.state, sample.latest.state, sample.alpha);
|
|
12618
12771
|
if (sample.latest.state.packetEntities && sample.previous.state.packetEntities) {
|
|
12619
12772
|
renderEntities = buildRenderableEntities(
|
|
12620
12773
|
sample.latest.state.packetEntities,
|
|
@@ -12748,6 +12901,9 @@ function createClient(imports) {
|
|
|
12748
12901
|
if (menuSystem.isActive()) {
|
|
12749
12902
|
Draw_Menu(imports.engine.renderer, menuSystem.getState(), imports.engine.renderer.width, imports.engine.renderer.height);
|
|
12750
12903
|
}
|
|
12904
|
+
if (isDemoPlaying) {
|
|
12905
|
+
demoControls.render(imports.engine.renderer, imports.engine.renderer.width, imports.engine.renderer.height);
|
|
12906
|
+
}
|
|
12751
12907
|
if (lastRendered && lastRendered.client) {
|
|
12752
12908
|
wheelMenuSystem.render(imports.engine.renderer, imports.engine.renderer.width, imports.engine.renderer.height, lastRendered.client);
|
|
12753
12909
|
}
|