isaacscript-common 31.5.0 → 31.6.0

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.
Files changed (126) hide show
  1. package/dist/index.rollup.d.ts +26 -4
  2. package/dist/isaacscript-common.lua +626 -645
  3. package/dist/src/classes/ModFeature.d.ts.map +1 -1
  4. package/dist/src/classes/ModFeature.lua +5 -9
  5. package/dist/src/classes/ModUpgraded.d.ts.map +1 -1
  6. package/dist/src/classes/ModUpgraded.lua +8 -14
  7. package/dist/src/classes/callbacks/PostNewRoomEarly.lua +2 -2
  8. package/dist/src/classes/features/callbackLogic/CustomGridEntities.d.ts.map +1 -1
  9. package/dist/src/classes/features/callbackLogic/CustomGridEntities.lua +3 -3
  10. package/dist/src/classes/features/other/CharacterHealthConversion.lua +1 -1
  11. package/dist/src/classes/features/other/CustomItemPools.d.ts.map +1 -1
  12. package/dist/src/classes/features/other/CustomItemPools.lua +12 -6
  13. package/dist/src/classes/features/other/CustomStages.d.ts.map +1 -1
  14. package/dist/src/classes/features/other/CustomStages.lua +12 -14
  15. package/dist/src/classes/features/other/CustomTrapdoors.d.ts.map +1 -1
  16. package/dist/src/classes/features/other/CustomTrapdoors.lua +6 -8
  17. package/dist/src/classes/features/other/DeployJSONRoom.d.ts.map +1 -1
  18. package/dist/src/classes/features/other/DeployJSONRoom.lua +15 -15
  19. package/dist/src/classes/features/other/ModdedElementSets.d.ts.map +1 -1
  20. package/dist/src/classes/features/other/ModdedElementSets.lua +21 -12
  21. package/dist/src/classes/features/other/Pause.d.ts.map +1 -1
  22. package/dist/src/classes/features/other/Pause.lua +4 -6
  23. package/dist/src/classes/features/other/SaveDataManager.d.ts.map +1 -1
  24. package/dist/src/classes/features/other/SaveDataManager.lua +5 -9
  25. package/dist/src/classes/features/other/customStages/backdrop.lua +9 -10
  26. package/dist/src/classes/features/other/saveDataManager/restoreDefaults.lua +1 -1
  27. package/dist/src/functions/array.d.ts +3 -0
  28. package/dist/src/functions/array.d.ts.map +1 -1
  29. package/dist/src/functions/array.lua +9 -3
  30. package/dist/src/functions/bitSet128.d.ts.map +1 -1
  31. package/dist/src/functions/bitSet128.lua +4 -6
  32. package/dist/src/functions/bitwise.d.ts.map +1 -1
  33. package/dist/src/functions/bitwise.lua +7 -3
  34. package/dist/src/functions/color.d.ts.map +1 -1
  35. package/dist/src/functions/color.lua +5 -9
  36. package/dist/src/functions/deepCopy.lua +23 -31
  37. package/dist/src/functions/entities.d.ts.map +1 -1
  38. package/dist/src/functions/entities.lua +20 -18
  39. package/dist/src/functions/entitiesSpecific.d.ts.map +1 -1
  40. package/dist/src/functions/entitiesSpecific.lua +11 -27
  41. package/dist/src/functions/enums.d.ts +6 -4
  42. package/dist/src/functions/enums.d.ts.map +1 -1
  43. package/dist/src/functions/enums.lua +13 -9
  44. package/dist/src/functions/gridEntities.d.ts.map +1 -1
  45. package/dist/src/functions/gridEntities.lua +18 -11
  46. package/dist/src/functions/gridEntitiesSpecific.d.ts.map +1 -1
  47. package/dist/src/functions/gridEntitiesSpecific.lua +16 -28
  48. package/dist/src/functions/input.d.ts +3 -0
  49. package/dist/src/functions/input.d.ts.map +1 -1
  50. package/dist/src/functions/input.lua +14 -14
  51. package/dist/src/functions/jsonRoom.d.ts.map +1 -1
  52. package/dist/src/functions/jsonRoom.lua +35 -23
  53. package/dist/src/functions/kColor.d.ts.map +1 -1
  54. package/dist/src/functions/kColor.lua +6 -12
  55. package/dist/src/functions/map.d.ts.map +1 -1
  56. package/dist/src/functions/map.lua +3 -3
  57. package/dist/src/functions/minimap.d.ts.map +1 -1
  58. package/dist/src/functions/minimap.lua +17 -9
  59. package/dist/src/functions/players.d.ts.map +1 -1
  60. package/dist/src/functions/players.lua +17 -22
  61. package/dist/src/functions/rng.d.ts.map +1 -1
  62. package/dist/src/functions/rng.lua +3 -3
  63. package/dist/src/functions/roomShapeWalls.d.ts.map +1 -1
  64. package/dist/src/functions/roomShapeWalls.lua +7 -3
  65. package/dist/src/functions/roomTransition.d.ts.map +1 -1
  66. package/dist/src/functions/roomTransition.lua +7 -3
  67. package/dist/src/functions/rooms.d.ts.map +1 -1
  68. package/dist/src/functions/rooms.lua +8 -5
  69. package/dist/src/functions/serialization.d.ts.map +1 -1
  70. package/dist/src/functions/serialization.lua +8 -18
  71. package/dist/src/functions/table.d.ts.map +1 -1
  72. package/dist/src/functions/table.lua +6 -12
  73. package/dist/src/functions/tstlClass.d.ts.map +1 -1
  74. package/dist/src/functions/tstlClass.lua +3 -3
  75. package/dist/src/functions/utils.d.ts +9 -0
  76. package/dist/src/functions/utils.d.ts.map +1 -1
  77. package/dist/src/functions/utils.lua +14 -6
  78. package/dist/src/functions/vector.d.ts.map +1 -1
  79. package/dist/src/functions/vector.lua +4 -6
  80. package/dist/src/functions/weighted.d.ts.map +1 -1
  81. package/dist/src/functions/weighted.lua +7 -3
  82. package/dist/src/sets/bossSets.d.ts.map +1 -1
  83. package/dist/src/sets/bossSets.lua +3 -3
  84. package/package.json +2 -2
  85. package/src/classes/ModFeature.ts +16 -12
  86. package/src/classes/ModUpgraded.ts +18 -16
  87. package/src/classes/callbacks/PostNewRoomEarly.ts +2 -2
  88. package/src/classes/features/callbackLogic/CustomGridEntities.ts +2 -3
  89. package/src/classes/features/other/CharacterHealthConversion.ts +1 -1
  90. package/src/classes/features/other/CustomItemPools.ts +9 -8
  91. package/src/classes/features/other/CustomStages.ts +9 -10
  92. package/src/classes/features/other/CustomTrapdoors.ts +9 -10
  93. package/src/classes/features/other/DeployJSONRoom.ts +21 -21
  94. package/src/classes/features/other/ModdedElementSets.ts +18 -21
  95. package/src/classes/features/other/Pause.ts +9 -6
  96. package/src/classes/features/other/SaveDataManager.ts +14 -16
  97. package/src/classes/features/other/customStages/backdrop.ts +5 -6
  98. package/src/classes/features/other/saveDataManager/restoreDefaults.ts +1 -1
  99. package/src/functions/array.ts +8 -6
  100. package/src/functions/bitSet128.ts +9 -10
  101. package/src/functions/bitwise.ts +6 -3
  102. package/src/functions/color.ts +13 -15
  103. package/src/functions/deepCopy.ts +18 -24
  104. package/src/functions/deepCopyTests.ts +5 -6
  105. package/src/functions/entities.ts +22 -20
  106. package/src/functions/entitiesSpecific.ts +10 -27
  107. package/src/functions/enums.ts +29 -17
  108. package/src/functions/gridEntities.ts +14 -16
  109. package/src/functions/gridEntitiesSpecific.ts +15 -28
  110. package/src/functions/input.ts +3 -3
  111. package/src/functions/jsonRoom.ts +39 -27
  112. package/src/functions/kColor.ts +17 -20
  113. package/src/functions/map.ts +5 -5
  114. package/src/functions/minimap.ts +16 -15
  115. package/src/functions/players.ts +7 -10
  116. package/src/functions/rng.ts +5 -5
  117. package/src/functions/roomShapeWalls.ts +3 -4
  118. package/src/functions/roomTransition.ts +5 -5
  119. package/src/functions/rooms.ts +5 -6
  120. package/src/functions/serialization.ts +25 -30
  121. package/src/functions/table.ts +18 -20
  122. package/src/functions/tstlClass.ts +5 -5
  123. package/src/functions/utils.ts +27 -6
  124. package/src/functions/vector.ts +9 -10
  125. package/src/functions/weighted.ts +5 -5
  126. package/src/sets/bossSets.ts +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"bossSets.d.ts","sourceRoot":"","sources":["../../../src/sets/bossSets.ts"],"names":[],"mappings":"AAmbA,eAAO,MAAM,mCAAmC,+DAe9C,CAAC;AAEH,eAAO,MAAM,8BAA8B,0CAezC,CAAC;AAEH,eAAO,MAAM,cAAc,qBAQzB,CAAC;AAEH,eAAO,MAAM,qCAAqC,qBACX,CAAC"}
1
+ {"version":3,"file":"bossSets.d.ts","sourceRoot":"","sources":["../../../src/sets/bossSets.ts"],"names":[],"mappings":"AAobA,eAAO,MAAM,mCAAmC,+DAe9C,CAAC;AAEH,eAAO,MAAM,8BAA8B,0CAezC,CAAC;AAEH,eAAO,MAAM,cAAc,qBAQzB,CAAC;AAEH,eAAO,MAAM,qCAAqC,qBACX,CAAC"}
@@ -41,6 +41,8 @@ local ____entities = require("src.functions.entities")
41
41
  local parseEntityTypeVariantString = ____entities.parseEntityTypeVariantString
42
42
  local ____set = require("src.functions.set")
43
43
  local copySet = ____set.copySet
44
+ local ____utils = require("src.functions.utils")
45
+ local assertDefined = ____utils.assertDefined
44
46
  local ____ReadonlyMap = require("src.types.ReadonlyMap")
45
47
  local ReadonlyMap = ____ReadonlyMap.ReadonlyMap
46
48
  local ____ReadonlySet = require("src.types.ReadonlySet")
@@ -52,9 +54,7 @@ function getAllBossesExcludingStoryBossesSet(self)
52
54
  local allBosses = {__TS__Spread(____exports.ALL_BOSSES_SET:values())}
53
55
  for ____, entityTypeVariantString in ipairs(allBosses) do
54
56
  local tuple = parseEntityTypeVariantString(nil, entityTypeVariantString)
55
- if tuple == nil then
56
- error("Failed to parse a boss tuple when constructing the story boss set.")
57
- end
57
+ assertDefined(nil, tuple, "Failed to parse a boss tuple when constructing the story boss set.")
58
58
  local entityType, _variant = table.unpack(tuple)
59
59
  if STORY_BOSSES_SET:has(entityType) then
60
60
  allBossesExcludingStoryBossesSet:delete(entityTypeVariantString)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "31.5.0",
3
+ "version": "31.6.0",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -25,6 +25,6 @@
25
25
  "main": "dist/src/index",
26
26
  "types": "dist/index.rollup.d.ts",
27
27
  "dependencies": {
28
- "isaac-typescript-definitions": "^13.0.26"
28
+ "isaac-typescript-definitions": "^13.0.27"
29
29
  }
30
30
  }
@@ -7,6 +7,7 @@ import {
7
7
  getTSTLClassName,
8
8
  } from "../functions/tstlClass";
9
9
  import { isFunction, isNumber, isTable } from "../functions/types";
10
+ import { assertDefined } from "../functions/utils";
10
11
  import type { TSTLClassMetatable } from "../interfaces/TSTLClassMetatable";
11
12
  import type { AnyFunction } from "../types/AnyFunction";
12
13
  import type { ModUpgraded } from "./ModUpgraded";
@@ -124,14 +125,16 @@ export class ModFeature {
124
125
  this.initialized = init;
125
126
 
126
127
  const constructor = getTSTLClassConstructor(this);
127
- if (constructor === undefined) {
128
- error("Failed to get the TSTL class constructor for a mod feature.");
129
- }
128
+ assertDefined(
129
+ constructor,
130
+ "Failed to get the TSTL class constructor for a mod feature.",
131
+ );
130
132
 
131
133
  const tstlClassName = getTSTLClassName(this);
132
- if (tstlClassName === undefined) {
133
- error("Failed to get the TSTL class name for a mod feature.");
134
- }
134
+ assertDefined(
135
+ tstlClassName,
136
+ "Failed to get the TSTL class name for a mod feature.",
137
+ );
135
138
 
136
139
  initDecoratedCallbacks(this, constructor, tstlClassName, true, init);
137
140
  initDecoratedCallbacks(this, constructor, tstlClassName, false, init);
@@ -360,12 +363,13 @@ function initSaveDataManager(
360
363
  const saveDataManagerMethodName = init
361
364
  ? "saveDataManager"
362
365
  : "saveDataManagerRemove";
363
- const saveDataManagerMethod = mod[saveDataManagerMethodName];
364
- if (saveDataManagerMethod === undefined) {
365
- error(
366
- 'Failed to initialize a mod feature class due to having a "v" object and not having the save data manager initialized. You must pass "ISCFeature.SAVE_DATA_MANAGER" to the "upgradeMod" function.',
367
- );
368
- }
366
+ const saveDataManagerMethod = mod[saveDataManagerMethodName] as
367
+ | AnyFunction
368
+ | undefined;
369
+ assertDefined(
370
+ saveDataManagerMethod,
371
+ 'Failed to initialize a mod feature class due to having a "v" object and not having the save data manager initialized. You must pass "ISCFeature.SAVE_DATA_MANAGER" to the "upgradeMod" function.',
372
+ );
369
373
 
370
374
  if (typeof saveDataManagerMethod !== "function") {
371
375
  error(
@@ -11,6 +11,7 @@ import {
11
11
  getTSTLClassConstructor,
12
12
  getTSTLClassName,
13
13
  } from "../functions/tstlClass";
14
+ import { assertDefined } from "../functions/utils";
14
15
  import type { AddCallbackParametersCustom } from "../interfaces/private/AddCallbackParametersCustom";
15
16
  import type { ModUpgradedInterface } from "../interfaces/private/ModUpgradedInterface";
16
17
  import type { AnyFunction } from "../types/AnyFunction";
@@ -234,11 +235,10 @@ export class ModUpgraded implements Mod {
234
235
  }
235
236
 
236
237
  const modCallbackCustom = tonumber(modCallbackCustomString);
237
- if (modCallbackCustom === undefined) {
238
- error(
239
- "Failed to convert an index on the callbacks object to a number.",
240
- );
241
- }
238
+ assertDefined(
239
+ modCallbackCustom,
240
+ "Failed to convert an index on the callbacks object to a number.",
241
+ );
242
242
 
243
243
  log(
244
244
  `- ModCallbackCustom.${ModCallbackCustom[modCallbackCustom]} (${modCallbackCustom})`,
@@ -254,9 +254,10 @@ export class ModUpgraded implements Mod {
254
254
  }
255
255
 
256
256
  const iscFeature = tonumber(iscFeatureString);
257
- if (iscFeature === undefined) {
258
- error("Failed to convert an index on the features object to a number.");
259
- }
257
+ assertDefined(
258
+ iscFeature,
259
+ "Failed to convert an index on the features object to a number.",
260
+ );
260
261
 
261
262
  log(`- ISCFeature.${ISCFeature[iscFeature]} (${iscFeature})`);
262
263
  }
@@ -324,9 +325,8 @@ export class ModUpgraded implements Mod {
324
325
 
325
326
  if (feature.v !== undefined) {
326
327
  const className = getTSTLClassName(feature);
327
- if (className === undefined) {
328
- error("Failed to get the name of a feature.");
329
- }
328
+ assertDefined(className, "Failed to get the name of a feature.");
329
+
330
330
  const saveDataManagerClass = this.features[ISCFeature.SAVE_DATA_MANAGER];
331
331
  saveDataManagerClass.saveDataManager(
332
332
  className,
@@ -387,9 +387,8 @@ export class ModUpgraded implements Mod {
387
387
 
388
388
  if (feature.v !== undefined) {
389
389
  const className = getTSTLClassName(feature);
390
- if (className === undefined) {
391
- error("Failed to get the name of a feature.");
392
- }
390
+ assertDefined(className, "Failed to get the name of a feature.");
391
+
393
392
  const saveDataManagerClass = this.features[ISCFeature.SAVE_DATA_MANAGER];
394
393
  saveDataManagerClass.saveDataManagerRemove(className);
395
394
  }
@@ -430,6 +429,9 @@ function getExportedMethodsFromFeature(featureClass: unknown): FunctionTuple[] {
430
429
 
431
430
  return exportedMethodNames.map((name) => {
432
431
  const featureClassRecord = featureClass as Record<string, AnyFunction>;
432
+
433
+ // We cannot split out the method to a separate variable or else the "self" parameter will not
434
+ // be properly passed to the method.
433
435
  if (featureClassRecord[name] === undefined) {
434
436
  error(`Failed to find a decorated exported method: ${name}`);
435
437
  }
@@ -437,8 +439,8 @@ function getExportedMethodsFromFeature(featureClass: unknown): FunctionTuple[] {
437
439
  // In order for "this" to work properly in the method, we have to wrap the method invocation in
438
440
  // an arrow function.
439
441
  const wrappedMethod = (...args: unknown[]) =>
440
- // We cannot split out the method to a separate variable or else the "self" parameter will not
441
- // be properly passed to the method.
442
+ // We use a non-null assertion since we have already validated that the function exists. (See
443
+ // the above comment.)
442
444
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
443
445
  featureClassRecord[name]!(...args);
444
446
 
@@ -68,7 +68,7 @@ export class PostNewRoomEarly extends CustomCallback<ModCallbackCustom.POST_NEW_
68
68
  topLeftWall = spawnGridEntity(GridEntityType.WALL, topLeftWallGridIndex);
69
69
  if (topLeftWall === undefined) {
70
70
  logError(
71
- "Failed to spawn a new wall (1) for the POST_NEW_ROOM_EARLY callback.",
71
+ "Failed to spawn a new wall for the POST_NEW_ROOM_EARLY callback (on the first try).",
72
72
  );
73
73
  return false;
74
74
  }
@@ -83,7 +83,7 @@ export class PostNewRoomEarly extends CustomCallback<ModCallbackCustom.POST_NEW_
83
83
  );
84
84
  if (topLeftWall2 === undefined) {
85
85
  logError(
86
- "Failed to spawn a new wall (2) for the POST_NEW_ROOM_EARLY callback.",
86
+ "Failed to spawn a new wall for the POST_NEW_ROOM_EARLY callback (on the second try).",
87
87
  );
88
88
  return false;
89
89
  }
@@ -16,6 +16,7 @@ import {
16
16
  import { getPlayerFromPtr } from "../../../functions/players";
17
17
  import { getRoomListIndex } from "../../../functions/roomData";
18
18
  import { isNumber } from "../../../functions/types";
19
+ import { assertDefined } from "../../../functions/utils";
19
20
  import { isVector } from "../../../functions/vector";
20
21
  import type { GridEntityCustomData } from "../../../interfaces/GridEntityCustomData";
21
22
  import { DefaultMap } from "../../DefaultMap";
@@ -245,9 +246,7 @@ export class CustomGridEntities extends Feature {
245
246
  baseGridEntityVariant,
246
247
  gridIndexOrPosition,
247
248
  );
248
- if (customGridEntity === undefined) {
249
- error("Failed to spawn a custom grid entity.");
250
- }
249
+ assertDefined(customGridEntity, "Failed to spawn a custom grid entity.");
251
250
 
252
251
  if (gridCollisionClass !== undefined) {
253
252
  customGridEntity.CollisionClass = gridCollisionClass;
@@ -70,7 +70,7 @@ export class CharacterHealthConversion extends Feature {
70
70
  const conversionHeartSubType =
71
71
  this.characterHealthReplacementMap.get(character);
72
72
  if (conversionHeartSubType === undefined) {
73
- return;
73
+ return undefined;
74
74
  }
75
75
 
76
76
  convertRedHeartContainers(player, conversionHeartSubType);
@@ -5,6 +5,7 @@ import { ModCallbackCustom } from "../../../enums/ModCallbackCustom";
5
5
  import { arrayRemoveIndexInPlace } from "../../../functions/array";
6
6
  import { copyMap } from "../../../functions/map";
7
7
  import { getRandomSeed } from "../../../functions/rng";
8
+ import { assertDefined } from "../../../functions/utils";
8
9
  import { getRandomIndexFromWeightedArray } from "../../../functions/weighted";
9
10
  import type { WeightedArray } from "../../../types/WeightedArray";
10
11
  import { Feature } from "../../private/Feature";
@@ -116,9 +117,10 @@ export class CustomItemPools extends Feature {
116
117
  defaultItem = CollectibleType.NULL,
117
118
  ): CollectibleType {
118
119
  const customItemPool = v.run.customItemPools.get(itemPoolTypeCustom);
119
- if (customItemPool === undefined) {
120
- error(`Failed to find the custom item pool of: ${itemPoolTypeCustom}`);
121
- }
120
+ assertDefined(
121
+ customItemPool,
122
+ `Failed to find the custom item pool of: ${itemPoolTypeCustom}`,
123
+ );
122
124
 
123
125
  if (customItemPool.length === 0) {
124
126
  return defaultItem;
@@ -129,11 +131,10 @@ export class CustomItemPools extends Feature {
129
131
  seedOrRNG,
130
132
  );
131
133
  const tuple = customItemPool[randomIndex];
132
- if (tuple === undefined) {
133
- error(
134
- `Failed to get an element from a custom item pool using a random index of: ${randomIndex}`,
135
- );
136
- }
134
+ assertDefined(
135
+ tuple,
136
+ `Failed to get an element from a custom item pool using a random index of: ${randomIndex}`,
137
+ );
137
138
 
138
139
  if (decrease) {
139
140
  arrayRemoveIndexInPlace(customItemPool, randomIndex);
@@ -31,6 +31,7 @@ import {
31
31
  import { getMusicForStage } from "../../../functions/sound";
32
32
  import { setStage } from "../../../functions/stage";
33
33
  import { asNumber } from "../../../functions/types";
34
+ import { assertDefined } from "../../../functions/utils";
34
35
  import type {
35
36
  CustomStageLua,
36
37
  CustomStageRoomMetadata,
@@ -201,11 +202,10 @@ export class CustomStages extends Feature {
201
202
  destinationStage: LevelStage,
202
203
  _destinationStageType: StageType,
203
204
  ) => {
204
- if (destinationName === undefined) {
205
- error(
206
- "Failed to go to a custom stage since the custom trapdoors feature did not pass a destination name to the logic function.",
207
- );
208
- }
205
+ assertDefined(
206
+ destinationName,
207
+ "Failed to go to a custom stage since the custom trapdoors feature did not pass a destination name to the logic function.",
208
+ );
209
209
 
210
210
  const firstFloor = destinationStage === LevelStage.BASEMENT_1;
211
211
  this.setCustomStage(destinationName, firstFloor);
@@ -498,11 +498,10 @@ export class CustomStages extends Feature {
498
498
  verbose = false,
499
499
  ): void {
500
500
  const customStage = this.customStagesMap.get(name);
501
- if (customStage === undefined) {
502
- error(
503
- `Failed to set the custom stage of "${name}" because it was not found in the custom stages map. (Try restarting IsaacScript / recompiling the mod / restarting the game, and try again. If that does not work, you probably forgot to define it in your "tsconfig.json" file.) See the website for more details on how to set up custom stages.`,
504
- );
505
- }
501
+ assertDefined(
502
+ customStage,
503
+ `Failed to set the custom stage of "${name}" because it was not found in the custom stages map. (Try restarting IsaacScript / recompiling the mod / restarting the game, and try again. If that does not work, you probably forgot to define it in your "tsconfig.json" file.) See the website for more details on how to set up custom stages.`,
504
+ );
506
505
 
507
506
  const level = game.GetLevel();
508
507
  const stage = level.GetStage();
@@ -37,6 +37,7 @@ import {
37
37
  import { teleport } from "../../../functions/roomTransition";
38
38
  import { setStage } from "../../../functions/stage";
39
39
  import { getTSTLClassName } from "../../../functions/tstlClass";
40
+ import { assertDefined } from "../../../functions/utils";
40
41
  import { isVector } from "../../../functions/vector";
41
42
  import type { CustomTrapdoorDescription } from "../../../interfaces/private/CustomTrapdoorDescription";
42
43
  import { ReadonlySet } from "../../../types/ReadonlySet";
@@ -365,11 +366,10 @@ export class CustomTrapdoors extends Feature {
365
366
  this.logStateChanged();
366
367
 
367
368
  const tstlClassName = getTSTLClassName(this);
368
- if (tstlClassName === undefined) {
369
- error(
370
- "Failed to find get the class name for the custom trapdoor feature.",
371
- );
372
- }
369
+ assertDefined(
370
+ tstlClassName,
371
+ "Failed to find get the class name for the custom trapdoor feature.",
372
+ );
373
373
 
374
374
  this.disableInputs.enableAllInputs(tstlClassName);
375
375
  }
@@ -506,11 +506,10 @@ export class CustomTrapdoors extends Feature {
506
506
  this.logStateChanged();
507
507
 
508
508
  const tstlClassName = getTSTLClassName(this);
509
- if (tstlClassName === undefined) {
510
- error(
511
- "Failed to find get the class name for the custom trapdoor feature.",
512
- );
513
- }
509
+ assertDefined(
510
+ tstlClassName,
511
+ "Failed to find get the class name for the custom trapdoor feature.",
512
+ );
514
513
 
515
514
  // We don't want to allow pausing, since that will allow render frames to pass without advancing
516
515
  // the stage traveling logic. (We track how many render frames have passed to know when to move
@@ -28,6 +28,7 @@ import { getRandomSeed, isRNG, newRNG } from "../../../functions/rng";
28
28
  import { gridCoordinatesToWorldPosition } from "../../../functions/roomGrid";
29
29
  import { setRoomCleared, setRoomUncleared } from "../../../functions/rooms";
30
30
  import { asCollectibleType, asNumber } from "../../../functions/types";
31
+ import { assertDefined } from "../../../functions/utils";
31
32
  import type { JSONRoom } from "../../../interfaces/JSONRoomsFile";
32
33
  import { ReadonlySet } from "../../../types/ReadonlySet";
33
34
  import { Feature } from "../../private/Feature";
@@ -68,41 +69,40 @@ export class DeployJSONRoom extends Feature {
68
69
  for (const jsonSpawn of jsonRoom.spawn) {
69
70
  const xString = jsonSpawn.$.x;
70
71
  const x = tonumber(xString);
71
- if (x === undefined) {
72
- error(
73
- `Failed to convert the following x coordinate to a number (for a spawn): ${xString}`,
74
- );
75
- }
72
+ assertDefined(
73
+ x,
74
+ `Failed to convert the following x coordinate to a number (for a spawn): ${xString}`,
75
+ );
76
76
 
77
77
  const yString = jsonSpawn.$.y;
78
78
  const y = tonumber(yString);
79
- if (y === undefined) {
80
- error(
81
- `Failed to convert the following y coordinate to a number (for a spawn): ${yString}`,
82
- );
83
- }
79
+ assertDefined(
80
+ y,
81
+ `Failed to convert the following y coordinate to a number (for a spawn): ${yString}`,
82
+ );
84
83
 
85
84
  const jsonEntity = getRandomJSONEntity(jsonSpawn.entity);
86
85
 
87
86
  const entityTypeString = jsonEntity.$.type;
88
87
  const entityTypeNumber = tonumber(entityTypeString);
89
- if (entityTypeNumber === undefined) {
90
- error(
91
- `Failed to convert the entity type to a number: ${entityTypeString}`,
92
- );
93
- }
88
+ assertDefined(
89
+ entityTypeNumber,
90
+ `Failed to convert the entity type to a number: ${entityTypeString}`,
91
+ );
94
92
 
95
93
  const variantString = jsonEntity.$.variant;
96
94
  const variant = tonumber(variantString);
97
- if (variant === undefined) {
98
- error(`Failed to convert the entity variant to a number: ${variant}`);
99
- }
95
+ assertDefined(
96
+ variant,
97
+ `Failed to convert the entity variant to a number: ${variant}`,
98
+ );
100
99
 
101
100
  const subTypeString = jsonEntity.$.subtype;
102
101
  const subType = tonumber(subTypeString);
103
- if (subType === undefined) {
104
- error(`Failed to convert the entity sub-type to a number: ${subType}`);
105
- }
102
+ assertDefined(
103
+ subType,
104
+ `Failed to convert the entity sub-type to a number: ${subType}`,
105
+ );
106
106
 
107
107
  const isGridEntity = GRID_ENTITY_XML_TYPE_SET.has(
108
108
  entityTypeNumber as GridEntityXMLType,
@@ -40,7 +40,7 @@ import {
40
40
  getVanillaTrinketTypeRange,
41
41
  trinketHasCacheFlag,
42
42
  } from "../../../functions/trinkets";
43
- import { repeat } from "../../../functions/utils";
43
+ import { assertDefined, repeat } from "../../../functions/utils";
44
44
  import { ITEM_CONFIG_CARD_TYPES_FOR_CARDS_SET } from "../../../sets/itemConfigCardTypesForCardsSet";
45
45
  import { ReadonlyMap } from "../../../types/ReadonlyMap";
46
46
  import { ReadonlySet } from "../../../types/ReadonlySet";
@@ -440,11 +440,11 @@ export class ModdedElementSets extends Feature {
440
440
  if (itemConfigCardType !== undefined) {
441
441
  const cardTypeSet =
442
442
  this.itemConfigCardTypeToCardTypeMap.get(itemConfigCardType);
443
- if (cardTypeSet === undefined) {
444
- error(
445
- `Failed to get the card set for item config card type: ${itemConfigCardType}`,
446
- );
447
- }
443
+ assertDefined(
444
+ cardTypeSet,
445
+ `Failed to get the card set for item config card type: ${itemConfigCardType}`,
446
+ );
447
+
448
448
  cardTypeSet.add(cardType);
449
449
 
450
450
  if (ITEM_CONFIG_CARD_TYPES_FOR_CARDS_SET.has(itemConfigCardType)) {
@@ -515,11 +515,10 @@ export class ModdedElementSets extends Feature {
515
515
  for (const itemConfigCardType of itemConfigCardTypes) {
516
516
  const cardTypeSet =
517
517
  this.itemConfigCardTypeToCardTypeMap.get(itemConfigCardType);
518
- if (cardTypeSet === undefined) {
519
- error(
520
- `Failed to get the card type set for item config type: ${itemConfigCardType}`,
521
- );
522
- }
518
+ assertDefined(
519
+ cardTypeSet,
520
+ `Failed to get the card type set for item config type: ${itemConfigCardType}`,
521
+ );
523
522
 
524
523
  for (const cardType of cardTypeSet) {
525
524
  matchingCardTypes.add(cardType);
@@ -588,11 +587,10 @@ export class ModdedElementSets extends Feature {
588
587
  playerForm: PlayerForm,
589
588
  ): ReadonlySet<CollectibleType> {
590
589
  const itemConfigTag = TRANSFORMATION_TO_TAG_MAP.get(playerForm);
591
- if (itemConfigTag === undefined) {
592
- error(
593
- `Failed to get the collectible types for the transformation of ${playerForm} because that transformation is not based on collectibles.`,
594
- );
595
- }
590
+ assertDefined(
591
+ itemConfigTag,
592
+ `Failed to get the collectible types for the transformation of ${playerForm} because that transformation is not based on collectibles.`,
593
+ );
596
594
 
597
595
  return this.getCollectiblesWithTag(itemConfigTag);
598
596
  }
@@ -648,11 +646,10 @@ export class ModdedElementSets extends Feature {
648
646
  this.lazyInitTagToCollectibleTypesMap();
649
647
 
650
648
  const collectibleTypes = this.tagToCollectibleTypesMap.get(itemConfigTag);
651
- if (collectibleTypes === undefined) {
652
- error(
653
- `The item config tag of ${itemConfigTag} is not a valid value of the "ItemConfigTag" enum.`,
654
- );
655
- }
649
+ assertDefined(
650
+ collectibleTypes,
651
+ `The item config tag of ${itemConfigTag} is not a valid value of the "ItemConfigTag" enum.`,
652
+ );
656
653
 
657
654
  return collectibleTypes;
658
655
  }
@@ -17,6 +17,7 @@ import { logError } from "../../../functions/logMisc";
17
17
  import { getAllPlayers } from "../../../functions/playerIndex";
18
18
  import { useActiveItemTemp } from "../../../functions/players";
19
19
  import { getTSTLClassName } from "../../../functions/tstlClass";
20
+ import { assertDefined } from "../../../functions/utils";
20
21
  import { ReadonlySet } from "../../../types/ReadonlySet";
21
22
  import { Feature } from "../../private/Feature";
22
23
  import type { DisableInputs } from "./DisableInputs";
@@ -170,9 +171,10 @@ export class Pause extends Feature {
170
171
  useActiveItemTemp(firstPlayer, CollectibleType.PAUSE);
171
172
 
172
173
  const tstlClassName = getTSTLClassName(this);
173
- if (tstlClassName === undefined) {
174
- error("Failed to get the class name for the pause feature.");
175
- }
174
+ assertDefined(
175
+ tstlClassName,
176
+ "Failed to get the class name for the pause feature.",
177
+ );
176
178
 
177
179
  const whitelist = new ReadonlySet([
178
180
  ButtonAction.MENU_CONFIRM,
@@ -210,9 +212,10 @@ export class Pause extends Feature {
210
212
  v.run.shouldUnpause = true;
211
213
 
212
214
  const tstlClassName = getTSTLClassName(this);
213
- if (tstlClassName === undefined) {
214
- error("Failed to find get the class name for the pause feature.");
215
- }
215
+ assertDefined(
216
+ tstlClassName,
217
+ "Failed to find get the class name for the pause feature.",
218
+ );
216
219
 
217
220
  this.disableInputs.enableAllInputs(tstlClassName);
218
221
  for (const player of getAllPlayers()) {
@@ -10,6 +10,7 @@ import { log } from "../../../functions/log";
10
10
  import { onFirstFloor } from "../../../functions/stage";
11
11
  import { getTSTLClassName, isTSTLClass } from "../../../functions/tstlClass";
12
12
  import { isString, isTable } from "../../../functions/types";
13
+ import { assertDefined } from "../../../functions/utils";
13
14
  import type { SaveData } from "../../../interfaces/SaveData";
14
15
  import type { AnyClass } from "../../../types/AnyClass";
15
16
  import { ReadonlySet } from "../../../types/ReadonlySet";
@@ -332,11 +333,10 @@ export class SaveDataManager extends Feature {
332
333
  ): void {
333
334
  if (isTSTLClass(key)) {
334
335
  const className = getTSTLClassName(key);
335
- if (className === undefined) {
336
- error(
337
- 'Failed to get the class name for the submitted class (as part of the "key" parameter) when registering new data with the save data manager.',
338
- );
339
- }
336
+ assertDefined(
337
+ className,
338
+ 'Failed to get the class name for the submitted class (as part of the "key" parameter) when registering new data with the save data manager.',
339
+ );
340
340
 
341
341
  key = className;
342
342
  }
@@ -459,12 +459,11 @@ export class SaveDataManager extends Feature {
459
459
  public saveDataManagerRegisterClass(...tstlClasses: AnyClass[]): void {
460
460
  for (const tstlClass of tstlClasses) {
461
461
  const { name } = tstlClass;
462
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
463
- if (name === undefined) {
464
- error(
465
- "Failed to register a class with the save data manager due to not being able to derive the name of the class.",
466
- );
467
- }
462
+ assertDefined(
463
+ // Since we are accepting untrusted user input, this might nto be a real TSTL class.
464
+ name as string | undefined,
465
+ "Failed to register a class with the save data manager due to not being able to derive the name of the class.",
466
+ );
468
467
 
469
468
  this.classConstructors.set(name, tstlClass);
470
469
  }
@@ -528,11 +527,10 @@ export class SaveDataManager extends Feature {
528
527
  }
529
528
 
530
529
  const saveData = this.saveDataMap.get(key);
531
- if (saveData === undefined) {
532
- error(
533
- `The save data manager is not managing save data for a key of: ${key}`,
534
- );
535
- }
530
+ assertDefined(
531
+ saveData,
532
+ `The save data manager is not managing save data for a key of: ${key}`,
533
+ );
536
534
 
537
535
  restoreDefaultForFeatureKey(
538
536
  this.saveDataDefaultsMap,
@@ -19,7 +19,7 @@ import {
19
19
  removeCharactersBefore,
20
20
  trimPrefix,
21
21
  } from "../../../../functions/string";
22
- import { eRange, iRange } from "../../../../functions/utils";
22
+ import { assertDefined, eRange, iRange } from "../../../../functions/utils";
23
23
  import type { CustomStage } from "../../../../interfaces/private/CustomStage";
24
24
  import { ReadonlySet } from "../../../../types/ReadonlySet";
25
25
  import { ISAACSCRIPT_CUSTOM_STAGE_GFX_PATH } from "./constants";
@@ -149,11 +149,10 @@ function spawnWallEntity(
149
149
  ? ROOM_SHAPE_WALL_EXTRA_ANM2_LAYERS
150
150
  : ROOM_SHAPE_WALL_ANM2_LAYERS;
151
151
  const numWallLayers = wallLayersArray[roomShape];
152
- if (numWallLayers === undefined) {
153
- error(
154
- `Failed to get the layers when creating the backdrop for custom stage: ${customStage.name}`,
155
- );
156
- }
152
+ assertDefined(
153
+ numWallLayers,
154
+ `Failed to get the layers when creating the backdrop for custom stage: ${customStage.name}`,
155
+ );
157
156
 
158
157
  if (isLRoomShape(roomShape)) {
159
158
  const cornerPNGPath = getBackdropPNGPath(
@@ -80,7 +80,7 @@ export function restoreDefaultForFeatureKey(
80
80
  const childTableDefaults = saveDataDefaults[saveDataKey];
81
81
  if (childTableDefaults === undefined) {
82
82
  logError(
83
- `Failed to find the default copy of the child table "${saveDataKey}" for subscriber "${subscriberName}". This error usually means that your save data is out of date. You can try purging all of your save data by deleting the following directory: C:\\Program Files (x86)\\Steam\\steamapps\\common\\The Binding of Isaac Rebirth\\data`,
83
+ `Failed to find the default copy of the child table "${saveDataKey}" for subscriber "${subscriberName}". This error usually means that your mod-specific save data is out of date. You can try purging all of your mod-specific save data by deleting the following directory: C:\\Program Files (x86)\\Steam\\steamapps\\common\\The Binding of Isaac Rebirth\\data`,
84
84
  );
85
85
  return;
86
86
  }