quake2ts 0.0.299 → 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.
@@ -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() {
@@ -11880,6 +11887,89 @@ var MultiplayerConnection = class {
11880
11887
  }
11881
11888
  };
11882
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
+
11883
11973
  // src/input/bindings.ts
11884
11974
  var DEFAULT_BINDINGS = [
11885
11975
  { code: "KeyW", command: "+forward" },
@@ -12392,6 +12482,7 @@ function createClient(imports) {
12392
12482
  const prediction = new import_cgame3.ClientPrediction(imports.engine.trace, pointContents);
12393
12483
  const view = new import_cgame4.ViewEffects();
12394
12484
  const demoPlayback = new DemoPlaybackController();
12485
+ const demoControls = new DemoControls(demoPlayback);
12395
12486
  const demoHandler = new ClientNetworkHandler(imports);
12396
12487
  demoHandler.setView(view);
12397
12488
  let isDemoPlaying = false;
@@ -12586,6 +12677,11 @@ function createClient(imports) {
12586
12677
  return prediction.enqueueCommand(command);
12587
12678
  },
12588
12679
  handleInput(key, down) {
12680
+ if (isDemoPlaying) {
12681
+ if (demoControls.handleInput(key, down)) {
12682
+ return true;
12683
+ }
12684
+ }
12589
12685
  if (!menuSystem.isActive()) return false;
12590
12686
  if (!down) return true;
12591
12687
  const lowerKey = key.toLowerCase();
@@ -12805,6 +12901,9 @@ function createClient(imports) {
12805
12901
  if (menuSystem.isActive()) {
12806
12902
  Draw_Menu(imports.engine.renderer, menuSystem.getState(), imports.engine.renderer.width, imports.engine.renderer.height);
12807
12903
  }
12904
+ if (isDemoPlaying) {
12905
+ demoControls.render(imports.engine.renderer, imports.engine.renderer.width, imports.engine.renderer.height);
12906
+ }
12808
12907
  if (lastRendered && lastRendered.client) {
12809
12908
  wheelMenuSystem.render(imports.engine.renderer, imports.engine.renderer.width, imports.engine.renderer.height, lastRendered.client);
12810
12909
  }