quake2ts 0.0.83 → 0.0.84

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.
@@ -80,6 +80,7 @@ __export(index_exports, {
80
80
  applyRegularArmor: () => applyRegularArmor,
81
81
  applySaveFile: () => applySaveFile,
82
82
  calculateFallingDamage: () => calculateFallingDamage,
83
+ calculateSaveChecksum: () => calculateSaveChecksum,
83
84
  canPickupHealth: () => canPickupHealth,
84
85
  changeYaw: () => changeYaw,
85
86
  clampAmmoCounts: () => clampAmmoCounts,
@@ -5181,6 +5182,55 @@ function cloneRngState(state) {
5181
5182
  }
5182
5183
  };
5183
5184
  }
5185
+ function hashValue(hash, value) {
5186
+ if (value === null || value === void 0) {
5187
+ return hash;
5188
+ }
5189
+ if (typeof value === "number") {
5190
+ return hashNumber(hash, value);
5191
+ }
5192
+ if (typeof value === "string") {
5193
+ return hashString(hash, value);
5194
+ }
5195
+ if (typeof value === "boolean") {
5196
+ return hashNumber(hash, value ? 1 : 0);
5197
+ }
5198
+ if (Array.isArray(value)) {
5199
+ let h = hash;
5200
+ for (const item of value) {
5201
+ h = hashValue(h, item);
5202
+ }
5203
+ return h;
5204
+ }
5205
+ if (typeof value === "object") {
5206
+ let h = hash;
5207
+ const keys = Object.keys(value).sort();
5208
+ for (const key of keys) {
5209
+ h = hashString(h, key);
5210
+ h = hashValue(h, value[key]);
5211
+ }
5212
+ return h;
5213
+ }
5214
+ return hash;
5215
+ }
5216
+ function calculateSaveChecksum(save) {
5217
+ let hash = FNV_OFFSET_BASIS;
5218
+ hash = hashNumber(hash, save.version);
5219
+ hash = hashNumber(hash, save.timestamp);
5220
+ hash = hashString(hash, save.map);
5221
+ hash = hashNumber(hash, save.difficulty);
5222
+ hash = hashNumber(hash, save.playtimeSeconds);
5223
+ hash = hashValue(hash, save.gameState);
5224
+ hash = hashValue(hash, save.level);
5225
+ hash = hashValue(hash, save.rng);
5226
+ hash = hashValue(hash, save.entities);
5227
+ hash = hashValue(hash, save.cvars);
5228
+ hash = hashValue(hash, save.configstrings);
5229
+ if (save.player) {
5230
+ hash = hashValue(hash, save.player);
5231
+ }
5232
+ return hash >>> 0;
5233
+ }
5184
5234
  function createSaveFile(options) {
5185
5235
  const {
5186
5236
  map,
@@ -5195,7 +5245,7 @@ function createSaveFile(options) {
5195
5245
  timestamp = Date.now(),
5196
5246
  player
5197
5247
  } = options;
5198
- return {
5248
+ const saveWithoutChecksum = {
5199
5249
  version: SAVE_FORMAT_VERSION,
5200
5250
  timestamp,
5201
5251
  map,
@@ -5209,6 +5259,10 @@ function createSaveFile(options) {
5209
5259
  configstrings: [...configstrings],
5210
5260
  player: player ? serializePlayerInventory(player) : void 0
5211
5261
  };
5262
+ return {
5263
+ ...saveWithoutChecksum,
5264
+ checksum: calculateSaveChecksum(saveWithoutChecksum)
5265
+ };
5212
5266
  }
5213
5267
  function parseSaveFile(serialized, options = {}) {
5214
5268
  const { allowNewerVersion = true } = options;
@@ -5222,7 +5276,7 @@ function parseSaveFile(serialized, options = {}) {
5222
5276
  if (version > SAVE_FORMAT_VERSION && !allowNewerVersion) {
5223
5277
  throw new Error(`Save version ${version} is newer than supported ${SAVE_FORMAT_VERSION}`);
5224
5278
  }
5225
- return {
5279
+ const parsedSave = {
5226
5280
  version,
5227
5281
  timestamp: ensureNumber(save.timestamp, "timestamp"),
5228
5282
  map: ensureString(save.map, "map"),
@@ -5234,8 +5288,16 @@ function parseSaveFile(serialized, options = {}) {
5234
5288
  entities: parseEntitySnapshot(save.entities),
5235
5289
  cvars: parseCvars(save.cvars),
5236
5290
  configstrings: parseConfigstrings(save.configstrings),
5237
- player: save.player ? save.player : void 0
5291
+ player: save.player ? save.player : void 0,
5292
+ checksum: save.checksum !== void 0 ? ensureNumber(save.checksum, "checksum") : void 0
5238
5293
  };
5294
+ if (parsedSave.checksum !== void 0) {
5295
+ const calculated = calculateSaveChecksum(parsedSave);
5296
+ if (calculated !== parsedSave.checksum) {
5297
+ throw new Error(`Save file checksum mismatch: expected ${parsedSave.checksum}, calculated ${calculated}`);
5298
+ }
5299
+ }
5300
+ return parsedSave;
5239
5301
  }
5240
5302
  function applySaveFile(save, targets) {
5241
5303
  targets.levelClock.restore(save.level);
@@ -6106,6 +6168,7 @@ function createGame({ trace, pointcontents }, engine, options) {
6106
6168
  applyRegularArmor,
6107
6169
  applySaveFile,
6108
6170
  calculateFallingDamage,
6171
+ calculateSaveChecksum,
6109
6172
  canPickupHealth,
6110
6173
  changeYaw,
6111
6174
  clampAmmoCounts,