quake2ts 0.0.403 → 0.0.407
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 +16 -16
- package/packages/client/dist/browser/index.global.js.map +1 -1
- package/packages/client/dist/cjs/index.cjs +405 -13
- package/packages/client/dist/cjs/index.cjs.map +1 -1
- package/packages/client/dist/esm/index.js +404 -13
- package/packages/client/dist/esm/index.js.map +1 -1
- package/packages/client/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/client/dist/types/demo/camera.d.ts +16 -0
- package/packages/client/dist/types/demo/camera.d.ts.map +1 -0
- package/packages/client/dist/types/index.d.ts +7 -1
- package/packages/client/dist/types/index.d.ts.map +1 -1
- package/packages/client/dist/types/ui/demo-controls.d.ts +2 -1
- package/packages/client/dist/types/ui/demo-controls.d.ts.map +1 -1
- package/packages/engine/dist/browser/index.global.js +16 -16
- package/packages/engine/dist/browser/index.global.js.map +1 -1
- package/packages/engine/dist/cjs/index.cjs +362 -4
- package/packages/engine/dist/cjs/index.cjs.map +1 -1
- package/packages/engine/dist/esm/index.js +361 -4
- package/packages/engine/dist/esm/index.js.map +1 -1
- package/packages/engine/dist/tsconfig.tsbuildinfo +1 -1
- package/packages/engine/dist/types/assets/mapStatistics.d.ts +20 -0
- package/packages/engine/dist/types/assets/mapStatistics.d.ts.map +1 -0
- package/packages/engine/dist/types/audio/api.d.ts +1 -0
- package/packages/engine/dist/types/audio/api.d.ts.map +1 -1
- package/packages/engine/dist/types/audio/context.d.ts +1 -0
- package/packages/engine/dist/types/audio/context.d.ts.map +1 -1
- package/packages/engine/dist/types/audio/system.d.ts +3 -0
- package/packages/engine/dist/types/audio/system.d.ts.map +1 -1
- package/packages/engine/dist/types/commands.d.ts +3 -0
- package/packages/engine/dist/types/commands.d.ts.map +1 -1
- package/packages/engine/dist/types/cvars.d.ts +11 -0
- package/packages/engine/dist/types/cvars.d.ts.map +1 -1
- package/packages/engine/dist/types/demo/analysis.d.ts +33 -0
- package/packages/engine/dist/types/demo/analysis.d.ts.map +1 -1
- package/packages/engine/dist/types/demo/analyzer.d.ts +28 -0
- package/packages/engine/dist/types/demo/analyzer.d.ts.map +1 -0
- package/packages/engine/dist/types/demo/playback.d.ts +16 -1
- package/packages/engine/dist/types/demo/playback.d.ts.map +1 -1
- package/packages/engine/dist/types/index.d.ts +1 -0
- package/packages/engine/dist/types/index.d.ts.map +1 -1
- package/packages/game/dist/tsconfig.tsbuildinfo +1 -1
|
@@ -1821,6 +1821,9 @@ var CommandRegistry = class {
|
|
|
1821
1821
|
this.commands.set(name, command);
|
|
1822
1822
|
return command;
|
|
1823
1823
|
}
|
|
1824
|
+
registerCommand(name, callback) {
|
|
1825
|
+
this.register(name, callback);
|
|
1826
|
+
}
|
|
1824
1827
|
get(name) {
|
|
1825
1828
|
return this.commands.get(name);
|
|
1826
1829
|
}
|
|
@@ -1836,10 +1839,33 @@ var CommandRegistry = class {
|
|
|
1836
1839
|
command.execute(args);
|
|
1837
1840
|
return true;
|
|
1838
1841
|
}
|
|
1842
|
+
this.onConsoleOutput?.(`Unknown command "${name}"`);
|
|
1839
1843
|
return false;
|
|
1840
1844
|
}
|
|
1845
|
+
executeCommand(cmd) {
|
|
1846
|
+
this.execute(cmd);
|
|
1847
|
+
}
|
|
1841
1848
|
tokenize(text) {
|
|
1842
|
-
|
|
1849
|
+
const args = [];
|
|
1850
|
+
let currentArg = "";
|
|
1851
|
+
let inQuote = false;
|
|
1852
|
+
for (let i = 0; i < text.length; i++) {
|
|
1853
|
+
const char = text[i];
|
|
1854
|
+
if (char === '"') {
|
|
1855
|
+
inQuote = !inQuote;
|
|
1856
|
+
} else if (char === " " && !inQuote) {
|
|
1857
|
+
if (currentArg.length > 0) {
|
|
1858
|
+
args.push(currentArg);
|
|
1859
|
+
currentArg = "";
|
|
1860
|
+
}
|
|
1861
|
+
} else {
|
|
1862
|
+
currentArg += char;
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
if (currentArg.length > 0) {
|
|
1866
|
+
args.push(currentArg);
|
|
1867
|
+
}
|
|
1868
|
+
return args;
|
|
1843
1869
|
}
|
|
1844
1870
|
list() {
|
|
1845
1871
|
return [...this.commands.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -2924,13 +2950,21 @@ var CvarRegistry = class {
|
|
|
2924
2950
|
if (existing) {
|
|
2925
2951
|
return existing;
|
|
2926
2952
|
}
|
|
2927
|
-
const
|
|
2953
|
+
const originalOnChange = def.onChange;
|
|
2954
|
+
const wrappedOnChange = (cvar2, prev) => {
|
|
2955
|
+
originalOnChange?.(cvar2, prev);
|
|
2956
|
+
this.onCvarChange?.(cvar2.name, cvar2.string);
|
|
2957
|
+
};
|
|
2958
|
+
const cvar = new Cvar({ ...def, onChange: wrappedOnChange });
|
|
2928
2959
|
this.cvars.set(def.name, cvar);
|
|
2929
2960
|
return cvar;
|
|
2930
2961
|
}
|
|
2931
2962
|
get(name) {
|
|
2932
2963
|
return this.cvars.get(name);
|
|
2933
2964
|
}
|
|
2965
|
+
getCvar(name) {
|
|
2966
|
+
return this.get(name);
|
|
2967
|
+
}
|
|
2934
2968
|
setValue(name, value) {
|
|
2935
2969
|
const cvar = this.get(name);
|
|
2936
2970
|
if (!cvar) {
|
|
@@ -2939,6 +2973,9 @@ var CvarRegistry = class {
|
|
|
2939
2973
|
cvar.set(value);
|
|
2940
2974
|
return cvar;
|
|
2941
2975
|
}
|
|
2976
|
+
setCvar(name, value) {
|
|
2977
|
+
this.setValue(name, value);
|
|
2978
|
+
}
|
|
2942
2979
|
resetAll() {
|
|
2943
2980
|
for (const cvar of this.cvars.values()) {
|
|
2944
2981
|
cvar.reset();
|
|
@@ -2954,6 +2991,15 @@ var CvarRegistry = class {
|
|
|
2954
2991
|
list() {
|
|
2955
2992
|
return [...this.cvars.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
2956
2993
|
}
|
|
2994
|
+
listCvars() {
|
|
2995
|
+
return this.list().map((cvar) => ({
|
|
2996
|
+
name: cvar.name,
|
|
2997
|
+
value: cvar.string,
|
|
2998
|
+
defaultValue: cvar.defaultValue,
|
|
2999
|
+
flags: cvar.flags,
|
|
3000
|
+
description: cvar.description
|
|
3001
|
+
}));
|
|
3002
|
+
}
|
|
2957
3003
|
};
|
|
2958
3004
|
var EngineHost = class {
|
|
2959
3005
|
constructor(game, client, options = {}) {
|
|
@@ -8762,6 +8808,162 @@ var NetworkMessageParser = class _NetworkMessageParser {
|
|
|
8762
8808
|
}
|
|
8763
8809
|
}
|
|
8764
8810
|
};
|
|
8811
|
+
var DemoAnalyzer = class {
|
|
8812
|
+
constructor(buffer) {
|
|
8813
|
+
this.events = [];
|
|
8814
|
+
this.summary = {
|
|
8815
|
+
totalKills: 0,
|
|
8816
|
+
totalDeaths: 0,
|
|
8817
|
+
damageDealt: 0,
|
|
8818
|
+
damageReceived: 0,
|
|
8819
|
+
weaponUsage: /* @__PURE__ */ new Map()
|
|
8820
|
+
};
|
|
8821
|
+
this.header = null;
|
|
8822
|
+
this.configStrings = /* @__PURE__ */ new Map();
|
|
8823
|
+
this.serverInfo = {};
|
|
8824
|
+
this.statistics = null;
|
|
8825
|
+
this.playerStats = /* @__PURE__ */ new Map();
|
|
8826
|
+
this.weaponStats = /* @__PURE__ */ new Map();
|
|
8827
|
+
this.buffer = buffer;
|
|
8828
|
+
}
|
|
8829
|
+
analyze() {
|
|
8830
|
+
const reader = new DemoReader(this.buffer);
|
|
8831
|
+
let currentFrameIndex = -1;
|
|
8832
|
+
let currentTime = 0;
|
|
8833
|
+
let frameDuration = 0.1;
|
|
8834
|
+
let protocolVersion = 0;
|
|
8835
|
+
const handler = {
|
|
8836
|
+
onServerData: (protocol, serverCount, attractLoop, gameDir, playerNum, levelName, tickRate, demoType) => {
|
|
8837
|
+
protocolVersion = protocol;
|
|
8838
|
+
this.header = {
|
|
8839
|
+
protocolVersion: protocol,
|
|
8840
|
+
gameDir,
|
|
8841
|
+
levelName,
|
|
8842
|
+
playerNum,
|
|
8843
|
+
serverCount,
|
|
8844
|
+
spawnCount: serverCount,
|
|
8845
|
+
// Mapping generic arg
|
|
8846
|
+
tickRate,
|
|
8847
|
+
demoType
|
|
8848
|
+
};
|
|
8849
|
+
if (tickRate && tickRate > 0) {
|
|
8850
|
+
frameDuration = 1 / tickRate;
|
|
8851
|
+
}
|
|
8852
|
+
},
|
|
8853
|
+
onConfigString: (index, str3) => {
|
|
8854
|
+
this.configStrings.set(index, str3);
|
|
8855
|
+
if (index === 0) {
|
|
8856
|
+
this.parseServerInfo(str3);
|
|
8857
|
+
}
|
|
8858
|
+
},
|
|
8859
|
+
onSpawnBaseline: (entity) => {
|
|
8860
|
+
},
|
|
8861
|
+
onFrame: (frame) => {
|
|
8862
|
+
},
|
|
8863
|
+
onPrint: (level, msg) => {
|
|
8864
|
+
if (msg.includes("died") || msg.includes("killed")) {
|
|
8865
|
+
this.summary.totalDeaths++;
|
|
8866
|
+
this.recordEvent({
|
|
8867
|
+
type: 4,
|
|
8868
|
+
frame: currentFrameIndex,
|
|
8869
|
+
time: currentTime,
|
|
8870
|
+
description: msg.trim()
|
|
8871
|
+
});
|
|
8872
|
+
}
|
|
8873
|
+
},
|
|
8874
|
+
onCenterPrint: () => {
|
|
8875
|
+
},
|
|
8876
|
+
onStuffText: () => {
|
|
8877
|
+
},
|
|
8878
|
+
onSound: () => {
|
|
8879
|
+
},
|
|
8880
|
+
onTempEntity: () => {
|
|
8881
|
+
},
|
|
8882
|
+
onLayout: () => {
|
|
8883
|
+
},
|
|
8884
|
+
onInventory: () => {
|
|
8885
|
+
},
|
|
8886
|
+
onMuzzleFlash: (ent, weapon) => {
|
|
8887
|
+
this.handleWeaponFire(ent, weapon, currentFrameIndex, currentTime);
|
|
8888
|
+
},
|
|
8889
|
+
onMuzzleFlash2: (ent, weapon) => {
|
|
8890
|
+
this.handleWeaponFire(ent, weapon, currentFrameIndex, currentTime);
|
|
8891
|
+
},
|
|
8892
|
+
onMuzzleFlash3: (ent, weapon) => {
|
|
8893
|
+
this.handleWeaponFire(ent, weapon, currentFrameIndex, currentTime);
|
|
8894
|
+
},
|
|
8895
|
+
onDisconnect: () => {
|
|
8896
|
+
},
|
|
8897
|
+
onReconnect: () => {
|
|
8898
|
+
},
|
|
8899
|
+
onDownload: () => {
|
|
8900
|
+
},
|
|
8901
|
+
// Rerelease specific
|
|
8902
|
+
onDamage: (indicators) => {
|
|
8903
|
+
for (const ind of indicators) {
|
|
8904
|
+
this.recordEvent({
|
|
8905
|
+
type: 2,
|
|
8906
|
+
frame: currentFrameIndex,
|
|
8907
|
+
time: currentTime,
|
|
8908
|
+
value: ind.damage,
|
|
8909
|
+
position: ind.dir,
|
|
8910
|
+
description: `Took ${ind.damage} damage`
|
|
8911
|
+
});
|
|
8912
|
+
this.summary.damageReceived += ind.damage;
|
|
8913
|
+
}
|
|
8914
|
+
}
|
|
8915
|
+
};
|
|
8916
|
+
while (reader.hasMore()) {
|
|
8917
|
+
const block = reader.readNextBlock();
|
|
8918
|
+
if (!block) break;
|
|
8919
|
+
currentFrameIndex++;
|
|
8920
|
+
currentTime = currentFrameIndex * frameDuration;
|
|
8921
|
+
const parser = new NetworkMessageParser(block.data, handler);
|
|
8922
|
+
parser.setProtocolVersion(protocolVersion);
|
|
8923
|
+
parser.parseMessage();
|
|
8924
|
+
protocolVersion = parser.getProtocolVersion();
|
|
8925
|
+
}
|
|
8926
|
+
this.statistics = {
|
|
8927
|
+
duration: currentTime,
|
|
8928
|
+
frameCount: currentFrameIndex + 1,
|
|
8929
|
+
averageFps: (currentFrameIndex + 1) / (currentTime || 1),
|
|
8930
|
+
mapName: this.header?.levelName || "unknown",
|
|
8931
|
+
playerCount: 1
|
|
8932
|
+
// Default to 1 for SP/client demo
|
|
8933
|
+
};
|
|
8934
|
+
return {
|
|
8935
|
+
events: this.events,
|
|
8936
|
+
summary: this.summary,
|
|
8937
|
+
header: this.header,
|
|
8938
|
+
configStrings: this.configStrings,
|
|
8939
|
+
serverInfo: this.serverInfo,
|
|
8940
|
+
statistics: this.statistics
|
|
8941
|
+
};
|
|
8942
|
+
}
|
|
8943
|
+
handleWeaponFire(ent, weapon, frame, time) {
|
|
8944
|
+
this.recordEvent({
|
|
8945
|
+
type: 0,
|
|
8946
|
+
frame,
|
|
8947
|
+
time,
|
|
8948
|
+
entityId: ent,
|
|
8949
|
+
value: weapon,
|
|
8950
|
+
description: `Weapon ${weapon} fired by ${ent}`
|
|
8951
|
+
});
|
|
8952
|
+
const count = this.summary.weaponUsage.get(weapon) || 0;
|
|
8953
|
+
this.summary.weaponUsage.set(weapon, count + 1);
|
|
8954
|
+
}
|
|
8955
|
+
recordEvent(event) {
|
|
8956
|
+
this.events.push(event);
|
|
8957
|
+
}
|
|
8958
|
+
parseServerInfo(str3) {
|
|
8959
|
+
const parts = str3.split("\\");
|
|
8960
|
+
for (let i = 1; i < parts.length; i += 2) {
|
|
8961
|
+
if (i + 1 < parts.length) {
|
|
8962
|
+
this.serverInfo[parts[i]] = parts[i + 1];
|
|
8963
|
+
}
|
|
8964
|
+
}
|
|
8965
|
+
}
|
|
8966
|
+
};
|
|
8765
8967
|
var PlaybackState = /* @__PURE__ */ ((PlaybackState22) => {
|
|
8766
8968
|
PlaybackState22[PlaybackState22["Stopped"] = 0] = "Stopped";
|
|
8767
8969
|
PlaybackState22[PlaybackState22["Playing"] = 1] = "Playing";
|
|
@@ -8772,6 +8974,7 @@ var PlaybackState = /* @__PURE__ */ ((PlaybackState22) => {
|
|
|
8772
8974
|
var DemoPlaybackController = class {
|
|
8773
8975
|
constructor() {
|
|
8774
8976
|
this.reader = null;
|
|
8977
|
+
this.buffer = null;
|
|
8775
8978
|
this.state = 0;
|
|
8776
8979
|
this.playbackSpeed = 1;
|
|
8777
8980
|
this.currentProtocolVersion = 0;
|
|
@@ -8781,6 +8984,12 @@ var DemoPlaybackController = class {
|
|
|
8781
8984
|
this.frameDuration = 100;
|
|
8782
8985
|
this.snapshotInterval = 100;
|
|
8783
8986
|
this.snapshots = /* @__PURE__ */ new Map();
|
|
8987
|
+
this.cachedEvents = null;
|
|
8988
|
+
this.cachedSummary = null;
|
|
8989
|
+
this.cachedHeader = null;
|
|
8990
|
+
this.cachedConfigStrings = null;
|
|
8991
|
+
this.cachedServerInfo = null;
|
|
8992
|
+
this.cachedStatistics = null;
|
|
8784
8993
|
}
|
|
8785
8994
|
setHandler(handler) {
|
|
8786
8995
|
this.handler = handler;
|
|
@@ -8789,6 +8998,7 @@ var DemoPlaybackController = class {
|
|
|
8789
8998
|
this.callbacks = callbacks;
|
|
8790
8999
|
}
|
|
8791
9000
|
loadDemo(buffer) {
|
|
9001
|
+
this.buffer = buffer;
|
|
8792
9002
|
this.reader = new DemoReader(buffer);
|
|
8793
9003
|
this.transitionState(
|
|
8794
9004
|
0
|
|
@@ -8799,6 +9009,12 @@ var DemoPlaybackController = class {
|
|
|
8799
9009
|
this.currentFrameIndex = -1;
|
|
8800
9010
|
this.snapshots.clear();
|
|
8801
9011
|
this.lastFrameData = null;
|
|
9012
|
+
this.cachedEvents = null;
|
|
9013
|
+
this.cachedSummary = null;
|
|
9014
|
+
this.cachedHeader = null;
|
|
9015
|
+
this.cachedConfigStrings = null;
|
|
9016
|
+
this.cachedServerInfo = null;
|
|
9017
|
+
this.cachedStatistics = null;
|
|
8802
9018
|
}
|
|
8803
9019
|
play() {
|
|
8804
9020
|
if (this.reader && this.state !== 1) {
|
|
@@ -9126,6 +9342,57 @@ var DemoPlaybackController = class {
|
|
|
9126
9342
|
this.seek(originalFrame);
|
|
9127
9343
|
return trajectory;
|
|
9128
9344
|
}
|
|
9345
|
+
// 3.2.3 Event Log Extraction & 3.3 Metadata
|
|
9346
|
+
getDemoEvents() {
|
|
9347
|
+
this.ensureAnalysis();
|
|
9348
|
+
return this.cachedEvents || [];
|
|
9349
|
+
}
|
|
9350
|
+
filterEvents(type, entityId) {
|
|
9351
|
+
const events = this.getDemoEvents();
|
|
9352
|
+
return events.filter((e) => {
|
|
9353
|
+
if (e.type !== type) return false;
|
|
9354
|
+
if (entityId !== void 0 && e.entityId !== entityId) return false;
|
|
9355
|
+
return true;
|
|
9356
|
+
});
|
|
9357
|
+
}
|
|
9358
|
+
getEventSummary() {
|
|
9359
|
+
this.ensureAnalysis();
|
|
9360
|
+
return this.cachedSummary || {
|
|
9361
|
+
totalKills: 0,
|
|
9362
|
+
totalDeaths: 0,
|
|
9363
|
+
damageDealt: 0,
|
|
9364
|
+
damageReceived: 0,
|
|
9365
|
+
weaponUsage: /* @__PURE__ */ new Map()
|
|
9366
|
+
};
|
|
9367
|
+
}
|
|
9368
|
+
getDemoHeader() {
|
|
9369
|
+
this.ensureAnalysis();
|
|
9370
|
+
return this.cachedHeader;
|
|
9371
|
+
}
|
|
9372
|
+
getDemoConfigStrings() {
|
|
9373
|
+
this.ensureAnalysis();
|
|
9374
|
+
return this.cachedConfigStrings || /* @__PURE__ */ new Map();
|
|
9375
|
+
}
|
|
9376
|
+
getDemoServerInfo() {
|
|
9377
|
+
this.ensureAnalysis();
|
|
9378
|
+
return this.cachedServerInfo || {};
|
|
9379
|
+
}
|
|
9380
|
+
getDemoStatistics() {
|
|
9381
|
+
this.ensureAnalysis();
|
|
9382
|
+
return this.cachedStatistics;
|
|
9383
|
+
}
|
|
9384
|
+
ensureAnalysis() {
|
|
9385
|
+
if (!this.cachedEvents && this.buffer) {
|
|
9386
|
+
const analyzer = new DemoAnalyzer(this.buffer);
|
|
9387
|
+
const result = analyzer.analyze();
|
|
9388
|
+
this.cachedEvents = result.events;
|
|
9389
|
+
this.cachedSummary = result.summary;
|
|
9390
|
+
this.cachedHeader = result.header;
|
|
9391
|
+
this.cachedConfigStrings = result.configStrings;
|
|
9392
|
+
this.cachedServerInfo = result.serverInfo;
|
|
9393
|
+
this.cachedStatistics = result.statistics;
|
|
9394
|
+
}
|
|
9395
|
+
}
|
|
9129
9396
|
};
|
|
9130
9397
|
var DemoRecorder = class {
|
|
9131
9398
|
// -1 means start of demo
|
|
@@ -9205,12 +9472,56 @@ var __export3 = (target, all) => {
|
|
|
9205
9472
|
};
|
|
9206
9473
|
var ZERO_VEC3 = { x: 0, y: 0, z: 0 };
|
|
9207
9474
|
var DEG_TO_RAD2 = Math.PI / 180;
|
|
9475
|
+
var PITCH = 0;
|
|
9476
|
+
var YAW = 1;
|
|
9477
|
+
var ROLL = 2;
|
|
9208
9478
|
var DEG2RAD_FACTOR2 = Math.PI / 180;
|
|
9209
9479
|
var RAD2DEG_FACTOR2 = 180 / Math.PI;
|
|
9480
|
+
function axisComponent(vec, axis) {
|
|
9481
|
+
switch (axis) {
|
|
9482
|
+
case PITCH:
|
|
9483
|
+
return vec.x;
|
|
9484
|
+
case YAW:
|
|
9485
|
+
return vec.y;
|
|
9486
|
+
case ROLL:
|
|
9487
|
+
default:
|
|
9488
|
+
return vec.z;
|
|
9489
|
+
}
|
|
9490
|
+
}
|
|
9491
|
+
function degToRad(degrees) {
|
|
9492
|
+
return degrees * DEG2RAD_FACTOR2;
|
|
9493
|
+
}
|
|
9210
9494
|
function angleMod(angle2) {
|
|
9211
9495
|
const value = angle2 % 360;
|
|
9212
9496
|
return value < 0 ? 360 + value : value;
|
|
9213
9497
|
}
|
|
9498
|
+
function angleVectors(angles) {
|
|
9499
|
+
const yaw = degToRad(axisComponent(angles, YAW));
|
|
9500
|
+
const pitch = degToRad(axisComponent(angles, PITCH));
|
|
9501
|
+
const roll = degToRad(axisComponent(angles, ROLL));
|
|
9502
|
+
const sy = Math.sin(yaw);
|
|
9503
|
+
const cy = Math.cos(yaw);
|
|
9504
|
+
const sp = Math.sin(pitch);
|
|
9505
|
+
const cp = Math.cos(pitch);
|
|
9506
|
+
const sr = Math.sin(roll);
|
|
9507
|
+
const cr = Math.cos(roll);
|
|
9508
|
+
const forward = {
|
|
9509
|
+
x: cp * cy,
|
|
9510
|
+
y: cp * sy,
|
|
9511
|
+
z: -sp
|
|
9512
|
+
};
|
|
9513
|
+
const right = {
|
|
9514
|
+
x: -sr * sp * cy - cr * -sy,
|
|
9515
|
+
y: -sr * sp * sy - cr * cy,
|
|
9516
|
+
z: -sr * cp
|
|
9517
|
+
};
|
|
9518
|
+
const up = {
|
|
9519
|
+
x: cr * sp * cy - sr * -sy,
|
|
9520
|
+
y: cr * sp * sy - sr * cy,
|
|
9521
|
+
z: cr * cp
|
|
9522
|
+
};
|
|
9523
|
+
return { forward, right, up };
|
|
9524
|
+
}
|
|
9214
9525
|
var ANORMS2 = [
|
|
9215
9526
|
[-0.525731, 0, 0.850651],
|
|
9216
9527
|
[-0.442863, 0.238856, 0.864188],
|
|
@@ -13106,10 +13417,11 @@ var MultiplayerConnection = class {
|
|
|
13106
13417
|
|
|
13107
13418
|
// src/ui/demo-controls.ts
|
|
13108
13419
|
var DemoControls = class {
|
|
13109
|
-
constructor(playback) {
|
|
13420
|
+
constructor(playback, onSpeedChange) {
|
|
13110
13421
|
this.isVisible = true;
|
|
13111
13422
|
this.demoName = null;
|
|
13112
13423
|
this.playback = playback;
|
|
13424
|
+
this.onSpeedChange = onSpeedChange;
|
|
13113
13425
|
}
|
|
13114
13426
|
setDemoName(name) {
|
|
13115
13427
|
this.demoName = name;
|
|
@@ -13187,6 +13499,9 @@ var DemoControls = class {
|
|
|
13187
13499
|
if (newSpeed < 0.1) newSpeed = 0.1;
|
|
13188
13500
|
if (newSpeed > 16) newSpeed = 16;
|
|
13189
13501
|
this.playback.setSpeed(newSpeed);
|
|
13502
|
+
if (this.onSpeedChange) {
|
|
13503
|
+
this.onSpeedChange(newSpeed);
|
|
13504
|
+
}
|
|
13190
13505
|
}
|
|
13191
13506
|
formatTime(ms) {
|
|
13192
13507
|
const totalSeconds = Math.floor(ms / 1e3);
|
|
@@ -13196,6 +13511,15 @@ var DemoControls = class {
|
|
|
13196
13511
|
}
|
|
13197
13512
|
};
|
|
13198
13513
|
|
|
13514
|
+
// src/demo/camera.ts
|
|
13515
|
+
var DemoCameraMode = /* @__PURE__ */ ((DemoCameraMode2) => {
|
|
13516
|
+
DemoCameraMode2[DemoCameraMode2["FirstPerson"] = 0] = "FirstPerson";
|
|
13517
|
+
DemoCameraMode2[DemoCameraMode2["ThirdPerson"] = 1] = "ThirdPerson";
|
|
13518
|
+
DemoCameraMode2[DemoCameraMode2["Free"] = 2] = "Free";
|
|
13519
|
+
DemoCameraMode2[DemoCameraMode2["Follow"] = 3] = "Follow";
|
|
13520
|
+
return DemoCameraMode2;
|
|
13521
|
+
})(DemoCameraMode || {});
|
|
13522
|
+
|
|
13199
13523
|
// src/effects.ts
|
|
13200
13524
|
function addDLight(dlights, origin, color, intensity, minLight = 0, die = 0) {
|
|
13201
13525
|
dlights.push({
|
|
@@ -13886,13 +14210,28 @@ function createClient(imports) {
|
|
|
13886
14210
|
const prediction = new ClientPrediction2(imports.engine.trace, pointContents);
|
|
13887
14211
|
const view = new ViewEffects2();
|
|
13888
14212
|
const demoPlayback = new DemoPlaybackController();
|
|
13889
|
-
const demoControls = new DemoControls(demoPlayback)
|
|
14213
|
+
const demoControls = new DemoControls(demoPlayback, (speed) => {
|
|
14214
|
+
if (imports.engine.audio) {
|
|
14215
|
+
const audio = imports.engine.audio;
|
|
14216
|
+
if (typeof audio.setPlaybackRate === "function") {
|
|
14217
|
+
audio.setPlaybackRate(speed);
|
|
14218
|
+
}
|
|
14219
|
+
}
|
|
14220
|
+
});
|
|
13890
14221
|
const demoHandler = new ClientNetworkHandler(imports);
|
|
13891
14222
|
const demoRecorder = new DemoRecorder();
|
|
13892
14223
|
demoHandler.setView(view);
|
|
13893
14224
|
let isDemoPlaying = false;
|
|
13894
14225
|
let currentDemoName = null;
|
|
13895
14226
|
let clientMode = 0 /* Normal */;
|
|
14227
|
+
const demoCameraState = {
|
|
14228
|
+
mode: 0 /* FirstPerson */,
|
|
14229
|
+
thirdPersonDistance: 80,
|
|
14230
|
+
thirdPersonOffset: { x: 0, y: 0, z: 0 },
|
|
14231
|
+
freeCameraOrigin: { x: 0, y: 0, z: 0 },
|
|
14232
|
+
freeCameraAngles: { x: 0, y: 0, z: 0 },
|
|
14233
|
+
followEntityId: -1
|
|
14234
|
+
};
|
|
13896
14235
|
const menuSystem = new MenuSystem();
|
|
13897
14236
|
const loadingScreen = new LoadingScreen();
|
|
13898
14237
|
const errorDialog = new ErrorDialog();
|
|
@@ -14107,6 +14446,8 @@ function createClient(imports) {
|
|
|
14107
14446
|
},
|
|
14108
14447
|
handleInput(key, down) {
|
|
14109
14448
|
if (isDemoPlaying) {
|
|
14449
|
+
if (demoCameraState.mode === 2 /* Free */) {
|
|
14450
|
+
}
|
|
14110
14451
|
if (demoControls.handleInput(key, down)) {
|
|
14111
14452
|
return true;
|
|
14112
14453
|
}
|
|
@@ -14192,18 +14533,51 @@ function createClient(imports) {
|
|
|
14192
14533
|
lastRenderTime = now;
|
|
14193
14534
|
demoPlayback.update(dt);
|
|
14194
14535
|
lastRendered = demoHandler.getPredictionState(demoPlayback.getCurrentTime());
|
|
14195
|
-
const frameDuration = 100;
|
|
14196
14536
|
renderEntities = demoHandler.getRenderableEntities(1, configStrings);
|
|
14197
14537
|
if (demoHandler.latestFrame && demoHandler.latestFrame.packetEntities) {
|
|
14198
14538
|
currentPacketEntities = demoHandler.latestFrame.packetEntities.entities;
|
|
14199
14539
|
}
|
|
14200
14540
|
if (lastRendered) {
|
|
14201
14541
|
const demoCamera = demoHandler.getDemoCamera(1);
|
|
14202
|
-
if (
|
|
14203
|
-
|
|
14204
|
-
|
|
14205
|
-
|
|
14206
|
-
|
|
14542
|
+
if (demoCameraState.mode === 0 /* FirstPerson */) {
|
|
14543
|
+
if (demoCamera) {
|
|
14544
|
+
lastRendered.origin = demoCamera.origin;
|
|
14545
|
+
lastRendered.viewAngles = demoCamera.angles;
|
|
14546
|
+
if (demoCamera.fov) {
|
|
14547
|
+
lastRendered.fov = demoCamera.fov;
|
|
14548
|
+
}
|
|
14549
|
+
}
|
|
14550
|
+
} else if (demoCameraState.mode === 1 /* ThirdPerson */) {
|
|
14551
|
+
if (demoCamera) {
|
|
14552
|
+
const vectors = angleVectors(demoCamera.angles);
|
|
14553
|
+
const forward = vectors.forward;
|
|
14554
|
+
const dist2 = demoCameraState.thirdPersonDistance;
|
|
14555
|
+
const camOrigin = { ...demoCamera.origin };
|
|
14556
|
+
camOrigin.x -= forward.x * dist2;
|
|
14557
|
+
camOrigin.y -= forward.y * dist2;
|
|
14558
|
+
camOrigin.z -= forward.z * dist2;
|
|
14559
|
+
const traceStart = demoCamera.origin;
|
|
14560
|
+
const traceEnd = camOrigin;
|
|
14561
|
+
const mins = { x: -4, y: -4, z: -4 };
|
|
14562
|
+
const maxs = { x: 4, y: 4, z: 4 };
|
|
14563
|
+
const trace = imports.engine.trace(traceStart, traceEnd, mins, maxs);
|
|
14564
|
+
if (trace.fraction < 1) {
|
|
14565
|
+
lastRendered.origin = trace.endpos;
|
|
14566
|
+
} else {
|
|
14567
|
+
lastRendered.origin = camOrigin;
|
|
14568
|
+
}
|
|
14569
|
+
lastRendered.viewAngles = demoCamera.angles;
|
|
14570
|
+
}
|
|
14571
|
+
} else if (demoCameraState.mode === 2 /* Free */) {
|
|
14572
|
+
lastRendered.origin = demoCameraState.freeCameraOrigin;
|
|
14573
|
+
lastRendered.viewAngles = demoCameraState.freeCameraAngles;
|
|
14574
|
+
} else if (demoCameraState.mode === 3 /* Follow */) {
|
|
14575
|
+
if (demoCameraState.followEntityId !== -1) {
|
|
14576
|
+
const ent = renderEntities.find((e) => e.id === demoCameraState.followEntityId);
|
|
14577
|
+
if (ent) {
|
|
14578
|
+
const mat = ent.transform;
|
|
14579
|
+
lastRendered.origin = { x: mat[12], y: mat[13], z: mat[14] };
|
|
14580
|
+
}
|
|
14207
14581
|
}
|
|
14208
14582
|
}
|
|
14209
14583
|
}
|
|
@@ -14243,8 +14617,10 @@ function createClient(imports) {
|
|
|
14243
14617
|
const { origin, viewAngles } = lastRendered;
|
|
14244
14618
|
camera = new Camera();
|
|
14245
14619
|
camera.position = vec3_exports.fromValues(origin.x, origin.y, origin.z);
|
|
14246
|
-
|
|
14247
|
-
|
|
14620
|
+
if (!isDemoPlaying || demoCameraState.mode === 0 /* FirstPerson */) {
|
|
14621
|
+
const viewOffset = lastView?.offset ?? { x: 0, y: 0, z: 0 };
|
|
14622
|
+
vec3_exports.add(camera.position, camera.position, [viewOffset.x, viewOffset.y, viewOffset.z]);
|
|
14623
|
+
}
|
|
14248
14624
|
const effectAngles = lastView?.angles ?? { x: 0, y: 0, z: 0 };
|
|
14249
14625
|
camera.angles = vec3_exports.fromValues(viewAngles.x + effectAngles.x, viewAngles.y + effectAngles.y, viewAngles.z + effectAngles.z);
|
|
14250
14626
|
if (isDemoPlaying && lastRendered.fov) {
|
|
@@ -14477,7 +14853,21 @@ function createClient(imports) {
|
|
|
14477
14853
|
},
|
|
14478
14854
|
demoHandler,
|
|
14479
14855
|
multiplayer,
|
|
14480
|
-
configStrings
|
|
14856
|
+
configStrings,
|
|
14857
|
+
// Demo Camera API
|
|
14858
|
+
setDemoCameraMode(mode) {
|
|
14859
|
+
demoCameraState.mode = mode;
|
|
14860
|
+
},
|
|
14861
|
+
setDemoThirdPersonDistance(dist2) {
|
|
14862
|
+
demoCameraState.thirdPersonDistance = dist2;
|
|
14863
|
+
},
|
|
14864
|
+
setDemoThirdPersonOffset(offset) {
|
|
14865
|
+
demoCameraState.thirdPersonOffset = offset;
|
|
14866
|
+
},
|
|
14867
|
+
setDemoFreeCamera(origin, angles) {
|
|
14868
|
+
demoCameraState.freeCameraOrigin = origin;
|
|
14869
|
+
demoCameraState.freeCameraAngles = angles;
|
|
14870
|
+
}
|
|
14481
14871
|
};
|
|
14482
14872
|
return clientExports;
|
|
14483
14873
|
}
|
|
@@ -14485,6 +14875,7 @@ export {
|
|
|
14485
14875
|
ClientConfigStrings,
|
|
14486
14876
|
ClientMode,
|
|
14487
14877
|
ClientPrediction3 as ClientPrediction,
|
|
14878
|
+
DemoCameraMode,
|
|
14488
14879
|
GameSession,
|
|
14489
14880
|
InputAction,
|
|
14490
14881
|
InputBindings,
|