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
|
@@ -8309,6 +8309,13 @@ var NetworkMessageParser = class _NetworkMessageParser {
|
|
|
8309
8309
|
if (bitsHigh & U_OLD_FRAME_HIGH) to.oldFrame = this.stream.readShort();
|
|
8310
8310
|
}
|
|
8311
8311
|
};
|
|
8312
|
+
var PlaybackState = /* @__PURE__ */ ((PlaybackState22) => {
|
|
8313
|
+
PlaybackState22[PlaybackState22["Stopped"] = 0] = "Stopped";
|
|
8314
|
+
PlaybackState22[PlaybackState22["Playing"] = 1] = "Playing";
|
|
8315
|
+
PlaybackState22[PlaybackState22["Paused"] = 2] = "Paused";
|
|
8316
|
+
PlaybackState22[PlaybackState22["Finished"] = 3] = "Finished";
|
|
8317
|
+
return PlaybackState22;
|
|
8318
|
+
})(PlaybackState || {});
|
|
8312
8319
|
var DemoPlaybackController = class {
|
|
8313
8320
|
// ms (10Hz default)
|
|
8314
8321
|
constructor() {
|
|
@@ -9623,7 +9630,7 @@ var AmmoType2 = /* @__PURE__ */ ((AmmoType22) => {
|
|
|
9623
9630
|
var AMMO_TYPE_COUNT2 = Object.keys(AmmoType2).length / 2;
|
|
9624
9631
|
|
|
9625
9632
|
// src/index.ts
|
|
9626
|
-
import { ClientPrediction, interpolatePredictionState as interpolatePredictionState2, GetCGameAPI } from "@quake2ts/cgame";
|
|
9633
|
+
import { ClientPrediction as ClientPrediction2, interpolatePredictionState as interpolatePredictionState2, GetCGameAPI } from "@quake2ts/cgame";
|
|
9627
9634
|
import { ViewEffects as ViewEffects2 } from "@quake2ts/cgame";
|
|
9628
9635
|
|
|
9629
9636
|
// src/cgameBridge.ts
|
|
@@ -9674,6 +9681,24 @@ function createCGameImport(imports, state) {
|
|
|
9674
9681
|
flags
|
|
9675
9682
|
});
|
|
9676
9683
|
},
|
|
9684
|
+
Cvar_Get: (name, value, flags) => {
|
|
9685
|
+
if (!imports.host || !imports.host.cvars) {
|
|
9686
|
+
return { value: parseInt(value) || 0 };
|
|
9687
|
+
}
|
|
9688
|
+
let existing = imports.host.cvars.get(name);
|
|
9689
|
+
if (!existing) {
|
|
9690
|
+
existing = imports.host.cvars.register({
|
|
9691
|
+
name,
|
|
9692
|
+
defaultValue: value,
|
|
9693
|
+
flags
|
|
9694
|
+
});
|
|
9695
|
+
}
|
|
9696
|
+
return {
|
|
9697
|
+
get value() {
|
|
9698
|
+
return existing.number;
|
|
9699
|
+
}
|
|
9700
|
+
};
|
|
9701
|
+
},
|
|
9677
9702
|
cvar_set: (name, value) => {
|
|
9678
9703
|
imports.host?.cvars?.setValue(name, value);
|
|
9679
9704
|
},
|
|
@@ -11611,6 +11636,7 @@ var BrowserWebSocketNetDriver = class {
|
|
|
11611
11636
|
};
|
|
11612
11637
|
|
|
11613
11638
|
// src/net/connection.ts
|
|
11639
|
+
import { defaultPredictionState as defaultPredictionState2 } from "@quake2ts/cgame";
|
|
11614
11640
|
var MultiplayerConnection = class {
|
|
11615
11641
|
constructor(options) {
|
|
11616
11642
|
this.state = 0 /* Disconnected */;
|
|
@@ -11628,6 +11654,8 @@ var MultiplayerConnection = class {
|
|
|
11628
11654
|
this.connectPacketTime = 0;
|
|
11629
11655
|
this.latestServerFrame = 0;
|
|
11630
11656
|
this.commandHistory = [];
|
|
11657
|
+
// Prediction
|
|
11658
|
+
this.prediction = null;
|
|
11631
11659
|
this.driver = new BrowserWebSocketNetDriver();
|
|
11632
11660
|
this.options = options;
|
|
11633
11661
|
this.netchan = new NetChan();
|
|
@@ -11635,6 +11663,9 @@ var MultiplayerConnection = class {
|
|
|
11635
11663
|
this.driver.onClose(() => this.handleDisconnect());
|
|
11636
11664
|
this.driver.onError((err2) => console.error("Network Error:", err2));
|
|
11637
11665
|
}
|
|
11666
|
+
setPrediction(prediction) {
|
|
11667
|
+
this.prediction = prediction;
|
|
11668
|
+
}
|
|
11638
11669
|
async connect(url) {
|
|
11639
11670
|
if (this.state !== 0 /* Disconnected */) {
|
|
11640
11671
|
this.disconnect();
|
|
@@ -11672,6 +11703,9 @@ var MultiplayerConnection = class {
|
|
|
11672
11703
|
if (this.commandHistory.length > CMD_BACKUP) {
|
|
11673
11704
|
this.commandHistory.shift();
|
|
11674
11705
|
}
|
|
11706
|
+
if (this.prediction) {
|
|
11707
|
+
this.prediction.enqueueCommand(commandWithFrame);
|
|
11708
|
+
}
|
|
11675
11709
|
const writer = new BinaryWriter2();
|
|
11676
11710
|
writer.writeByte(ClientCommand.move);
|
|
11677
11711
|
writer.writeByte(0);
|
|
@@ -11769,6 +11803,31 @@ var MultiplayerConnection = class {
|
|
|
11769
11803
|
if (frame.serverFrame > this.latestServerFrame) {
|
|
11770
11804
|
this.latestServerFrame = frame.serverFrame;
|
|
11771
11805
|
}
|
|
11806
|
+
if (this.prediction && frame.playerState) {
|
|
11807
|
+
const ps = frame.playerState;
|
|
11808
|
+
const predState = {
|
|
11809
|
+
...defaultPredictionState2(),
|
|
11810
|
+
// Manual mapping due to type mismatch (MutableVec3 vs Vec3, and property names)
|
|
11811
|
+
origin: { x: ps.origin.x, y: ps.origin.y, z: ps.origin.z },
|
|
11812
|
+
velocity: { x: ps.velocity.x, y: ps.velocity.y, z: ps.velocity.z },
|
|
11813
|
+
viewAngles: { x: ps.viewangles.x, y: ps.viewangles.y, z: ps.viewangles.z },
|
|
11814
|
+
deltaAngles: { x: ps.delta_angles.x, y: ps.delta_angles.y, z: ps.delta_angles.z },
|
|
11815
|
+
pmFlags: ps.pm_flags,
|
|
11816
|
+
pmType: ps.pm_type,
|
|
11817
|
+
gravity: ps.gravity,
|
|
11818
|
+
// Copy other matching fields
|
|
11819
|
+
health: ps.stats[0]
|
|
11820
|
+
// Assuming stat 0 is health? Or generic copy
|
|
11821
|
+
// ...
|
|
11822
|
+
};
|
|
11823
|
+
const gameFrame = {
|
|
11824
|
+
frame: frame.serverFrame,
|
|
11825
|
+
timeMs: 0,
|
|
11826
|
+
// Should be server time, but frame doesn't always have it explicitly?
|
|
11827
|
+
state: predState
|
|
11828
|
+
};
|
|
11829
|
+
this.prediction.setAuthoritative(gameFrame);
|
|
11830
|
+
}
|
|
11772
11831
|
}
|
|
11773
11832
|
// Stubs for other handlers
|
|
11774
11833
|
onCenterPrint(msg) {
|
|
@@ -11796,6 +11855,89 @@ var MultiplayerConnection = class {
|
|
|
11796
11855
|
}
|
|
11797
11856
|
};
|
|
11798
11857
|
|
|
11858
|
+
// src/ui/demo-controls.ts
|
|
11859
|
+
var DemoControls = class {
|
|
11860
|
+
constructor(playback) {
|
|
11861
|
+
this.isVisible = true;
|
|
11862
|
+
this.playback = playback;
|
|
11863
|
+
}
|
|
11864
|
+
render(renderer, width, height) {
|
|
11865
|
+
if (!this.isVisible) return;
|
|
11866
|
+
const state = this.playback.getState();
|
|
11867
|
+
const isPlaying = state === PlaybackState.Playing;
|
|
11868
|
+
const overlayHeight = 60;
|
|
11869
|
+
const y = height - overlayHeight;
|
|
11870
|
+
renderer.drawfillRect(0, y, width, overlayHeight, [0, 0, 0, 0.5]);
|
|
11871
|
+
const iconSize = 24;
|
|
11872
|
+
const iconY = y + (overlayHeight - iconSize) / 2;
|
|
11873
|
+
const iconX = 20;
|
|
11874
|
+
const statusText = isPlaying ? "PAUSE" : "PLAY";
|
|
11875
|
+
renderer.drawString(iconX, iconY, statusText);
|
|
11876
|
+
const speed = this.playback.getSpeed();
|
|
11877
|
+
const speedText = `Speed: ${speed}x`;
|
|
11878
|
+
renderer.drawCenterString(iconY, speedText);
|
|
11879
|
+
const currentTime = this.playback.getCurrentTime();
|
|
11880
|
+
const currentFormatted = this.formatTime(currentTime);
|
|
11881
|
+
const totalFormatted = "--:--";
|
|
11882
|
+
const timeText = `${currentFormatted} / ${totalFormatted}`;
|
|
11883
|
+
const timeX = width - 150;
|
|
11884
|
+
renderer.drawString(timeX, iconY, timeText);
|
|
11885
|
+
const timelineY = y + 5;
|
|
11886
|
+
const timelineHeight = 4;
|
|
11887
|
+
const timelineWidth = width - 40;
|
|
11888
|
+
const timelineX = 20;
|
|
11889
|
+
renderer.drawfillRect(timelineX, timelineY, timelineWidth, timelineHeight, [0.3, 0.3, 0.3, 1]);
|
|
11890
|
+
const progress = 0;
|
|
11891
|
+
const progressWidth = timelineWidth * progress;
|
|
11892
|
+
renderer.drawfillRect(timelineX, timelineY, progressWidth, timelineHeight, [1, 1, 1, 1]);
|
|
11893
|
+
const markerX = timelineX + progressWidth;
|
|
11894
|
+
renderer.drawfillRect(markerX - 2, timelineY - 2, 4, timelineHeight + 4, [1, 0, 0, 1]);
|
|
11895
|
+
const helpText = "[Space] Toggle [< >] Step [ [ ] ] Speed [Esc] Stop";
|
|
11896
|
+
renderer.drawCenterString(y + 35, helpText);
|
|
11897
|
+
}
|
|
11898
|
+
handleInput(key, down) {
|
|
11899
|
+
if (!down) return false;
|
|
11900
|
+
switch (key.toLowerCase()) {
|
|
11901
|
+
case " ":
|
|
11902
|
+
if (this.playback.getState() === PlaybackState.Playing) {
|
|
11903
|
+
this.playback.pause();
|
|
11904
|
+
} else if (this.playback.getState() === PlaybackState.Paused) {
|
|
11905
|
+
this.playback.play();
|
|
11906
|
+
}
|
|
11907
|
+
return true;
|
|
11908
|
+
case "arrowright":
|
|
11909
|
+
this.playback.stepForward();
|
|
11910
|
+
return true;
|
|
11911
|
+
case "arrowleft":
|
|
11912
|
+
this.playback.stepBackward();
|
|
11913
|
+
return true;
|
|
11914
|
+
case "]":
|
|
11915
|
+
this.changeSpeed(2);
|
|
11916
|
+
return true;
|
|
11917
|
+
case "[":
|
|
11918
|
+
this.changeSpeed(0.5);
|
|
11919
|
+
return true;
|
|
11920
|
+
case "escape":
|
|
11921
|
+
this.playback.stop();
|
|
11922
|
+
return true;
|
|
11923
|
+
}
|
|
11924
|
+
return false;
|
|
11925
|
+
}
|
|
11926
|
+
changeSpeed(factor) {
|
|
11927
|
+
const current = this.playback.getSpeed();
|
|
11928
|
+
let newSpeed = current * factor;
|
|
11929
|
+
if (newSpeed < 0.1) newSpeed = 0.1;
|
|
11930
|
+
if (newSpeed > 16) newSpeed = 16;
|
|
11931
|
+
this.playback.setSpeed(newSpeed);
|
|
11932
|
+
}
|
|
11933
|
+
formatTime(ms) {
|
|
11934
|
+
const totalSeconds = Math.floor(ms / 1e3);
|
|
11935
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
11936
|
+
const seconds = totalSeconds % 60;
|
|
11937
|
+
return `${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
|
|
11938
|
+
}
|
|
11939
|
+
};
|
|
11940
|
+
|
|
11799
11941
|
// src/input/bindings.ts
|
|
11800
11942
|
var DEFAULT_BINDINGS = [
|
|
11801
11943
|
{ code: "KeyW", command: "+forward" },
|
|
@@ -11960,6 +12102,7 @@ var InputController = class {
|
|
|
11960
12102
|
this.touchButtons = /* @__PURE__ */ new Map();
|
|
11961
12103
|
this.touchMove = { x: 0, y: 0 };
|
|
11962
12104
|
this.touchLook = { x: 0, y: 0 };
|
|
12105
|
+
this.sequence = 0;
|
|
11963
12106
|
this.bindings = bindings;
|
|
11964
12107
|
this.forwardSpeed = options.forwardSpeed ?? DEFAULT_FORWARD_SPEED;
|
|
11965
12108
|
this.sideSpeed = options.sideSpeed ?? DEFAULT_SIDE_SPEED;
|
|
@@ -12098,6 +12241,7 @@ var InputController = class {
|
|
|
12098
12241
|
buttons |= PlayerButton.Any;
|
|
12099
12242
|
}
|
|
12100
12243
|
this.anyPressed = false;
|
|
12244
|
+
this.sequence++;
|
|
12101
12245
|
return {
|
|
12102
12246
|
msec,
|
|
12103
12247
|
buttons,
|
|
@@ -12105,7 +12249,10 @@ var InputController = class {
|
|
|
12105
12249
|
forwardmove,
|
|
12106
12250
|
sidemove,
|
|
12107
12251
|
upmove,
|
|
12108
|
-
serverFrame
|
|
12252
|
+
serverFrame,
|
|
12253
|
+
sequence: this.sequence,
|
|
12254
|
+
lightlevel: 0,
|
|
12255
|
+
impulse: 0
|
|
12109
12256
|
};
|
|
12110
12257
|
}
|
|
12111
12258
|
consumeConsoleCommands() {
|
|
@@ -12286,7 +12433,7 @@ var InputCommandBuffer = class {
|
|
|
12286
12433
|
|
|
12287
12434
|
// src/index.ts
|
|
12288
12435
|
import {
|
|
12289
|
-
ClientPrediction as
|
|
12436
|
+
ClientPrediction as ClientPrediction3,
|
|
12290
12437
|
interpolatePredictionState as interpolatePredictionState3
|
|
12291
12438
|
} from "@quake2ts/cgame";
|
|
12292
12439
|
import { ViewEffects as ViewEffects3 } from "@quake2ts/cgame";
|
|
@@ -12303,9 +12450,10 @@ function createClient(imports) {
|
|
|
12303
12450
|
const tr = imports.engine.trace(point, point, zero3, zero3);
|
|
12304
12451
|
return tr.contents || 0;
|
|
12305
12452
|
};
|
|
12306
|
-
const prediction = new
|
|
12453
|
+
const prediction = new ClientPrediction2(imports.engine.trace, pointContents);
|
|
12307
12454
|
const view = new ViewEffects2();
|
|
12308
12455
|
const demoPlayback = new DemoPlaybackController();
|
|
12456
|
+
const demoControls = new DemoControls(demoPlayback);
|
|
12309
12457
|
const demoHandler = new ClientNetworkHandler(imports);
|
|
12310
12458
|
demoHandler.setView(view);
|
|
12311
12459
|
let isDemoPlaying = false;
|
|
@@ -12500,6 +12648,11 @@ function createClient(imports) {
|
|
|
12500
12648
|
return prediction.enqueueCommand(command);
|
|
12501
12649
|
},
|
|
12502
12650
|
handleInput(key, down) {
|
|
12651
|
+
if (isDemoPlaying) {
|
|
12652
|
+
if (demoControls.handleInput(key, down)) {
|
|
12653
|
+
return true;
|
|
12654
|
+
}
|
|
12655
|
+
}
|
|
12503
12656
|
if (!menuSystem.isActive()) return false;
|
|
12504
12657
|
if (!down) return true;
|
|
12505
12658
|
const lowerKey = key.toLowerCase();
|
|
@@ -12719,6 +12872,9 @@ function createClient(imports) {
|
|
|
12719
12872
|
if (menuSystem.isActive()) {
|
|
12720
12873
|
Draw_Menu(imports.engine.renderer, menuSystem.getState(), imports.engine.renderer.width, imports.engine.renderer.height);
|
|
12721
12874
|
}
|
|
12875
|
+
if (isDemoPlaying) {
|
|
12876
|
+
demoControls.render(imports.engine.renderer, imports.engine.renderer.width, imports.engine.renderer.height);
|
|
12877
|
+
}
|
|
12722
12878
|
if (lastRendered && lastRendered.client) {
|
|
12723
12879
|
wheelMenuSystem.render(imports.engine.renderer, imports.engine.renderer.width, imports.engine.renderer.height, lastRendered.client);
|
|
12724
12880
|
}
|
|
@@ -12803,7 +12959,7 @@ function createClient(imports) {
|
|
|
12803
12959
|
export {
|
|
12804
12960
|
ClientConfigStrings,
|
|
12805
12961
|
ClientMode,
|
|
12806
|
-
|
|
12962
|
+
ClientPrediction3 as ClientPrediction,
|
|
12807
12963
|
InputAction,
|
|
12808
12964
|
InputBindings,
|
|
12809
12965
|
InputCommandBuffer,
|