isaacscript-common 20.2.0 → 20.3.1

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 (103) hide show
  1. package/dist/index.d.ts +54 -21
  2. package/dist/isaacscript-common.lua +10293 -10005
  3. package/dist/src/callbackClasses.d.ts +1 -0
  4. package/dist/src/callbackClasses.d.ts.map +1 -1
  5. package/dist/src/callbackClasses.lua +5 -0
  6. package/dist/src/callbacks.d.ts +1 -0
  7. package/dist/src/callbacks.d.ts.map +1 -1
  8. package/dist/src/callbacks.lua +2 -1
  9. package/dist/src/classes/ModUpgradedBase.d.ts +1 -1
  10. package/dist/src/classes/callbacks/PreRoomEntitySpawnFilter.d.ts +11 -0
  11. package/dist/src/classes/callbacks/PreRoomEntitySpawnFilter.d.ts.map +1 -0
  12. package/dist/src/classes/callbacks/PreRoomEntitySpawnFilter.lua +29 -0
  13. package/dist/src/classes/features/callbackLogic/CustomGridEntities.lua +3 -3
  14. package/dist/src/classes/features/callbackLogic/GridEntityCollisionDetection.lua +1 -1
  15. package/dist/src/classes/features/callbackLogic/GridEntityUpdateDetection.d.ts.map +1 -1
  16. package/dist/src/classes/features/callbackLogic/GridEntityUpdateDetection.lua +3 -3
  17. package/dist/src/classes/features/callbackLogic/PlayerCollectibleDetection.lua +1 -1
  18. package/dist/src/classes/features/other/CustomHotkeys.d.ts.map +1 -1
  19. package/dist/src/classes/features/other/CustomHotkeys.lua +2 -2
  20. package/dist/src/classes/features/other/DeployJSONRoom.lua +1 -1
  21. package/dist/src/classes/features/other/ItemPoolDetection.d.ts.map +1 -1
  22. package/dist/src/classes/features/other/ModdedElementSets.lua +3 -3
  23. package/dist/src/classes/features/other/PersistentEntities.d.ts.map +1 -1
  24. package/dist/src/classes/features/other/PersistentEntities.lua +1 -1
  25. package/dist/src/classes/features/other/PickupIndexCreation.lua +1 -1
  26. package/dist/src/classes/features/other/customStages/streakText.d.ts.map +1 -1
  27. package/dist/src/classes/features/other/extraConsoleCommands/commands.lua +0 -1
  28. package/dist/src/core/constants.d.ts +1 -1
  29. package/dist/src/core/constants.d.ts.map +1 -1
  30. package/dist/src/enums/ModCallbackCustom.d.ts +32 -7
  31. package/dist/src/enums/ModCallbackCustom.d.ts.map +1 -1
  32. package/dist/src/enums/ModCallbackCustom.lua +2 -0
  33. package/dist/src/functions/cards.lua +0 -2
  34. package/dist/src/functions/entities.lua +1 -1
  35. package/dist/src/functions/hex.d.ts +4 -3
  36. package/dist/src/functions/hex.d.ts.map +1 -1
  37. package/dist/src/functions/hex.lua +8 -0
  38. package/dist/src/functions/isaacAPIClass.d.ts +1 -1
  39. package/dist/src/functions/isaacAPIClass.d.ts.map +1 -1
  40. package/dist/src/functions/levelGrid.d.ts.map +1 -1
  41. package/dist/src/functions/levelGrid.lua +2 -2
  42. package/dist/src/functions/map.d.ts +2 -2
  43. package/dist/src/functions/map.lua +1 -1
  44. package/dist/src/functions/minimap.lua +1 -1
  45. package/dist/src/functions/table.d.ts +1 -1
  46. package/dist/src/functions/table.d.ts.map +1 -1
  47. package/dist/src/functions/utils.d.ts +5 -5
  48. package/dist/src/functions/utils.d.ts.map +1 -1
  49. package/dist/src/functions/utils.lua +9 -18
  50. package/dist/src/interfaces/private/AddCallbackParametersCustom.d.ts +7 -1
  51. package/dist/src/interfaces/private/AddCallbackParametersCustom.d.ts.map +1 -1
  52. package/dist/src/maps/characterNameToTypeMap.d.ts +1 -1
  53. package/dist/src/maps/characterNameToTypeMap.d.ts.map +1 -1
  54. package/dist/src/objects/roomShapeToDoorSlotCoordinates.d.ts +1 -1
  55. package/dist/src/objects/roomShapeToDoorSlotCoordinates.d.ts.map +1 -1
  56. package/dist/src/sets/bossSets.lua +5 -5
  57. package/dist/src/sets/entitiesWithArmorSet.d.ts +1 -1
  58. package/dist/src/sets/entitiesWithArmorSet.d.ts.map +1 -1
  59. package/package.json +2 -2
  60. package/src/callbackClasses.ts +1 -0
  61. package/src/callbacks.ts +1 -0
  62. package/src/classes/ModUpgradedBase.ts +1 -1
  63. package/src/classes/callbacks/PostTrinketBreak.ts +2 -2
  64. package/src/classes/callbacks/PreRoomEntitySpawnFilter.ts +55 -0
  65. package/src/classes/features/callbackLogic/CustomGridEntities.ts +3 -3
  66. package/src/classes/features/callbackLogic/GridEntityCollisionDetection.ts +1 -1
  67. package/src/classes/features/callbackLogic/GridEntityUpdateDetection.ts +4 -6
  68. package/src/classes/features/callbackLogic/PlayerCollectibleDetection.ts +1 -1
  69. package/src/classes/features/other/CustomHotkeys.ts +2 -8
  70. package/src/classes/features/other/DeployJSONRoom.ts +1 -1
  71. package/src/classes/features/other/FlyingDetection.ts +2 -2
  72. package/src/classes/features/other/ItemPoolDetection.ts +3 -5
  73. package/src/classes/features/other/ModdedElementSets.ts +4 -4
  74. package/src/classes/features/other/PersistentEntities.ts +1 -4
  75. package/src/classes/features/other/PickupIndexCreation.ts +1 -1
  76. package/src/classes/features/other/PonyDetection.ts +2 -2
  77. package/src/classes/features/other/customStages/backdrop.ts +2 -2
  78. package/src/classes/features/other/customStages/streakText.ts +6 -4
  79. package/src/classes/features/other/saveDataManager/glowingHourGlass.ts +2 -2
  80. package/src/core/constants.ts +7 -6
  81. package/src/enums/ModCallbackCustom.ts +32 -6
  82. package/src/functions/bitSet128.ts +1 -1
  83. package/src/functions/color.ts +1 -1
  84. package/src/functions/hex.ts +4 -2
  85. package/src/functions/input.ts +6 -6
  86. package/src/functions/isaacAPIClass.ts +1 -1
  87. package/src/functions/kColor.ts +1 -1
  88. package/src/functions/levelGrid.ts +3 -9
  89. package/src/functions/map.ts +2 -2
  90. package/src/functions/merge.ts +1 -1
  91. package/src/functions/minimap.ts +1 -1
  92. package/src/functions/rng.ts +1 -1
  93. package/src/functions/table.ts +1 -1
  94. package/src/functions/utils.ts +9 -15
  95. package/src/functions/vector.ts +1 -1
  96. package/src/interfaces/private/AddCallbackParametersCustom.ts +14 -0
  97. package/src/maps/characterNameToTypeMap.ts +86 -85
  98. package/src/objects/roomShapeBounds.ts +2 -2
  99. package/src/objects/roomShapeLayoutSizes.ts +4 -4
  100. package/src/objects/roomShapeToDoorSlotCoordinates.ts +1 -1
  101. package/src/patchErrorFunctions.ts +2 -2
  102. package/src/sets/bossSets.ts +5 -5
  103. package/src/sets/entitiesWithArmorSet.ts +1 -1
@@ -275,7 +275,7 @@ function getStoredPickupIndex(
275
275
  pickup: Entity,
276
276
  pickupDescriptions: Map<PickupIndex, PickupDescription>,
277
277
  ): PickupIndex | undefined {
278
- for (const [pickupIndex, pickupDescription] of pickupDescriptions.entries()) {
278
+ for (const [pickupIndex, pickupDescription] of pickupDescriptions) {
279
279
  if (
280
280
  vectorEquals(pickupDescription.position, pickup.Position) &&
281
281
  pickupDescription.initSeed === pickup.InitSeed
@@ -11,11 +11,11 @@ import { getPlayers } from "../../../functions/playerIndex";
11
11
  import { PlayerIndex } from "../../../types/PlayerIndex";
12
12
  import { Feature } from "../../private/Feature";
13
13
 
14
- const FLAGS_WHEN_PONY_IS_ACTIVE: readonly EntityFlag[] = [
14
+ const FLAGS_WHEN_PONY_IS_ACTIVE = [
15
15
  EntityFlag.NO_KNOCKBACK, // 1 << 26
16
16
  EntityFlag.NO_PHYSICS_KNOCKBACK, // 1 << 30
17
17
  EntityFlag.NO_DAMAGE_BLINK, // 1 << 36
18
- ];
18
+ ] as const;
19
19
 
20
20
  export class PonyDetection extends Feature {
21
21
  /** @internal */
@@ -72,10 +72,10 @@ const ROOM_SHAPE_WALL_EXTRA_ANM2_LAYERS: {
72
72
  const WALL_OFFSET = Vector(-80, -80);
73
73
 
74
74
  /** Corresponds to "floor-backdrop.anm2". */
75
- const L_FLOOR_ANM2_LAYERS: readonly int[] = [16, 17];
75
+ const L_FLOOR_ANM2_LAYERS = [16, 17] as const;
76
76
 
77
77
  /** Corresponds to "floor-backdrop.anm2". */
78
- const N_FLOOR_ANM2_LAYERS: readonly int[] = [18, 19];
78
+ const N_FLOOR_ANM2_LAYERS = [18, 19] as const;
79
79
 
80
80
  /**
81
81
  * Normally, we would make a custom entity to represent a backdrop effect, but we don't want to
@@ -49,10 +49,12 @@ const STREAK_TEXT_BOTTOM_Y_OFFSET = -9;
49
49
  const NUM_RENDER_FRAMES_MAP_HELD_BEFORE_STREAK_TEXT = 11;
50
50
 
51
51
  /** Taken from StageAPI. */
52
- const TEXT_IN_ADJUSTMENTS = [-800, -639, -450, -250, -70, 10, 6, 3];
52
+ const TEXT_IN_ADJUSTMENTS = [-800, -639, -450, -250, -70, 10, 6, 3] as const;
53
53
 
54
54
  /** Taken from StageAPI. */
55
- const TEXT_OUT_ADJUSTMENTS = [0, -5, -10, -15, -20, 144, 308, 472, 636, 800];
55
+ const TEXT_OUT_ADJUSTMENTS = [
56
+ 0, -5, -10, -15, -20, 144, 308, 472, 636, 800,
57
+ ] as const;
56
58
 
57
59
  /** Taken from StageAPI. */
58
60
  const TEXT_IN_SCALES = [
@@ -64,7 +66,7 @@ const TEXT_IN_SCALES = [
64
66
  Vector(0.95, 1.05),
65
67
  Vector(0.97, 1.03),
66
68
  Vector(0.98, 1.02),
67
- ];
69
+ ] as const;
68
70
 
69
71
  /** Taken from StageAPI. */
70
72
  const TEXT_OUT_SCALES = [
@@ -78,7 +80,7 @@ const TEXT_OUT_SCALES = [
78
80
  Vector(2.18, 0.56),
79
81
  Vector(2.59, 0.38),
80
82
  Vector(3, 0.2),
81
- ];
83
+ ] as const;
82
84
 
83
85
  interface StreakTextVars {
84
86
  run: {
@@ -14,10 +14,10 @@ import { SAVE_DATA_MANAGER_DEBUG } from "./constants";
14
14
  * When the Glowing Hourglass is used, certain save data keys will automatically be restored to a
15
15
  * backup.
16
16
  */
17
- const GLOWING_HOUR_GLASS_BACKUP_KEYS: readonly SaveDataKey[] = [
17
+ const GLOWING_HOUR_GLASS_BACKUP_KEYS = [
18
18
  SaveDataKey.RUN,
19
19
  SaveDataKey.LEVEL,
20
- ];
20
+ ] as const;
21
21
 
22
22
  const IGNORE_GLOWING_HOUR_GLASS_KEY = "__ignoreGlowingHourGlass";
23
23
 
@@ -79,12 +79,13 @@ export const GAME_FRAMES_PER_SECOND = 30;
79
79
  export const GAME_FRAMES_PER_MINUTE = GAME_FRAMES_PER_SECOND * 60;
80
80
 
81
81
  /** The set of all `ItemConfigCardType` values that are not a rune or special object. */
82
- export const ITEM_CONFIG_CARD_TYPES_FOR_CARDS = new Set([
83
- ItemConfigCardType.TAROT,
84
- ItemConfigCardType.SUIT,
85
- ItemConfigCardType.SPECIAL,
86
- ItemConfigCardType.TAROT_REVERSE,
87
- ]);
82
+ export const ITEM_CONFIG_CARD_TYPES_FOR_CARDS: ReadonlySet<ItemConfigCardType> =
83
+ new Set([
84
+ ItemConfigCardType.TAROT,
85
+ ItemConfigCardType.SUIT,
86
+ ItemConfigCardType.SPECIAL,
87
+ ItemConfigCardType.TAROT_REVERSE,
88
+ ]);
88
89
 
89
90
  /** Render frames are what is returned by the `Isaac.GetFrameCount` method. */
90
91
  export const RENDER_FRAMES_PER_SECOND = 60;
@@ -1873,12 +1873,14 @@ export enum ModCallbackCustom {
1873
1873
  *
1874
1874
  * ```ts
1875
1875
  * function preEntitySpawnFilter(
1876
- * entity: Entity,
1877
- * amount: float,
1878
- * damageFlags: BitFlags<DamageFlag>,
1879
- * source: EntityRef,
1880
- * countdownFrames: int,
1881
- * ): boolean | undefined {}
1876
+ * entityType: EntityType,
1877
+ * variant: int,
1878
+ * subType: int,
1879
+ * position: Vector,
1880
+ * velocity: Vector,
1881
+ * spawner: Entity | undefined,
1882
+ * initSeed: Seed,
1883
+ * ): [EntityType, int, int, int] | undefined {}
1882
1884
  * ```
1883
1885
  */
1884
1886
  PRE_ENTITY_SPAWN_FILTER,
@@ -1979,4 +1981,28 @@ export enum ModCallbackCustom {
1979
1981
  * ```
1980
1982
  */
1981
1983
  PRE_NPC_UPDATE_FILTER,
1984
+
1985
+ /**
1986
+ * The exact same thing as the vanilla `PRE_ROOM_ENTITY_SPAWN` callback, except this callback
1987
+ * allows you to specify extra arguments for additional filtration.
1988
+ *
1989
+ * When registering the callback with the `ModUpgraded.AddCallbackCustom` method:
1990
+ * - You can provide an optional third argument that will make the callback only fire if it
1991
+ * matches the `EntityType` or `GridEntityXMLType` provided.
1992
+ * - You can provide an optional fourth argument that will make the callback only fire if it
1993
+ * matches the variant provided.
1994
+ * - You can provide an optional fifth argument that will make the callback only fire if it
1995
+ * matches the sub-type provided.
1996
+ *
1997
+ * ```ts
1998
+ * function preRoomEntitySpawnFilter(
1999
+ * entityTypeOrGridEntityXMLType: EntityType | GridEntityXMLType,
2000
+ * variant: int,
2001
+ * subType: int,
2002
+ * gridIndex: int,
2003
+ * seed: Seed,
2004
+ * ): [EntityType | GridEntityXMLType, int, int] | undefined {}
2005
+ * ```
2006
+ */
2007
+ PRE_ROOM_ENTITY_SPAWN_FILTER,
1982
2008
  }
@@ -14,7 +14,7 @@ export type SerializedBitSet128 = LuaMap<string, unknown> & {
14
14
  };
15
15
 
16
16
  const OBJECT_NAME = "BitSet128";
17
- const KEYS = ["l", "h"];
17
+ const KEYS = ["l", "h"] as const;
18
18
 
19
19
  /** Helper function to copy a `BitSet128` Isaac API class. */
20
20
  export function copyBitSet128(bitSet128: BitSet128): BitSet128 {
@@ -16,7 +16,7 @@ export type SerializedColor = LuaMap<string, unknown> & {
16
16
  };
17
17
 
18
18
  const OBJECT_NAME = "Color";
19
- const KEYS = ["R", "G", "B", "A", "RO", "GO", "BO"];
19
+ const KEYS = ["R", "G", "B", "A", "RO", "GO", "BO"] as const;
20
20
 
21
21
  export function colorEquals(color1: Color, color2: Color): boolean {
22
22
  return isaacAPIClassEquals(color1, color2, KEYS);
@@ -6,8 +6,9 @@ const HEX_STRING_LENGTH = 6;
6
6
  * Converts a hex string like "#33aa33" to a KColor object.
7
7
  *
8
8
  * @param hexString A hex string like "#ffffff" or "ffffff". (The "#" character is optional.)
9
+ * @param alpha Optional. Range is from 0 to 1. Default is 1. (The same as the `Color` constructor.)
9
10
  */
10
- export function hexToColor(hexString: string, alpha: float): Color {
11
+ export function hexToColor(hexString: string, alpha = 1.0): Color {
11
12
  const [r, g, b] = hexToRGB(hexString);
12
13
 
13
14
  // Color values should be between 0 and 1.
@@ -19,8 +20,9 @@ export function hexToColor(hexString: string, alpha: float): Color {
19
20
  * Converts a hex string like "#33aa33" to a Color object.
20
21
  *
21
22
  * @param hexString A hex string like "#ffffff" or "ffffff". (The "#" character is optional.)
23
+ * @param alpha Range is from 0 to 1. Default is 1.
22
24
  */
23
- export function hexToKColor(hexString: string, alpha: float): KColor {
25
+ export function hexToKColor(hexString: string, alpha = 1.0): KColor {
24
26
  const [r, g, b] = hexToRGB(hexString);
25
27
 
26
28
  // KColor values should be between 0 and 1.
@@ -8,7 +8,7 @@ import { KEYBOARD_TO_STRING } from "../maps/keyboardToString";
8
8
  import { getEnumValues } from "./enums";
9
9
  import { trimPrefix } from "./string";
10
10
 
11
- const MODIFIER_KEYS: readonly Keyboard[] = [
11
+ const MODIFIER_KEYS = [
12
12
  Keyboard.LEFT_SHIFT, // 340
13
13
  Keyboard.LEFT_CONTROL, // 341
14
14
  Keyboard.LEFT_ALT, // 342
@@ -17,25 +17,25 @@ const MODIFIER_KEYS: readonly Keyboard[] = [
17
17
  Keyboard.RIGHT_CONTROL, // 345
18
18
  Keyboard.RIGHT_ALT, // 346
19
19
  Keyboard.RIGHT_SUPER, // 347
20
- ];
20
+ ] as const;
21
21
 
22
- const MOVEMENT_ACTIONS: readonly ButtonAction[] = [
22
+ const MOVEMENT_ACTIONS = [
23
23
  ButtonAction.LEFT, // 0
24
24
  ButtonAction.RIGHT, // 1
25
25
  ButtonAction.UP, // 2
26
26
  ButtonAction.DOWN, // 3
27
- ];
27
+ ] as const;
28
28
 
29
29
  export const MOVEMENT_ACTIONS_SET: ReadonlySet<ButtonAction> = new Set(
30
30
  MOVEMENT_ACTIONS,
31
31
  );
32
32
 
33
- const SHOOTING_ACTIONS: readonly ButtonAction[] = [
33
+ const SHOOTING_ACTIONS = [
34
34
  ButtonAction.SHOOT_LEFT, // 4
35
35
  ButtonAction.SHOOT_RIGHT, // 5
36
36
  ButtonAction.SHOOT_UP, // 6
37
37
  ButtonAction.SHOOT_DOWN, // 7
38
- ];
38
+ ] as const;
39
39
 
40
40
  export const SHOOTING_ACTIONS_SET: ReadonlySet<ButtonAction> = new Set(
41
41
  SHOOTING_ACTIONS,
@@ -162,7 +162,7 @@ export function isTear(variable: unknown): variable is EntityTear {
162
162
  export function isaacAPIClassEquals(
163
163
  object1: unknown,
164
164
  object2: unknown,
165
- keys: string[],
165
+ keys: string[] | readonly string[],
166
166
  ): boolean {
167
167
  const table1 = object1 as LuaMap<AnyNotNil, unknown>;
168
168
  const table2 = object2 as LuaMap<AnyNotNil, unknown>;
@@ -16,7 +16,7 @@ export type SerializedKColor = LuaMap<string, unknown> & {
16
16
  };
17
17
 
18
18
  const OBJECT_NAME = "KColor";
19
- const KEYS = ["Red", "Green", "Blue", "Alpha"];
19
+ const KEYS = ["Red", "Green", "Blue", "Alpha"] as const;
20
20
 
21
21
  /** Helper function to copy a `KColor` Isaac API class. */
22
22
  export function copyKColor(kColor: KColor): KColor {
@@ -45,7 +45,7 @@ const UP = -LEVEL_GRID_ROW_WIDTH;
45
45
  const RIGHT = 1;
46
46
  const DOWN = LEVEL_GRID_ROW_WIDTH;
47
47
 
48
- const ADJACENT_ROOM_GRID_INDEX_DELTAS: readonly int[] = [LEFT, UP, RIGHT, DOWN];
48
+ const ADJACENT_ROOM_GRID_INDEX_DELTAS = [LEFT, UP, RIGHT, DOWN] as const;
49
49
 
50
50
  /**
51
51
  * Helper function to get only the adjacent room grid indexes that exist (i.e. have room data).
@@ -300,10 +300,7 @@ export function getRoomShapeAdjacentExistingGridIndexes(
300
300
  getRoomShapeAdjacentGridIndexes(safeRoomGridIndex, roomShape),
301
301
  );
302
302
 
303
- for (const [
304
- doorSlot,
305
- roomGridIndex,
306
- ] of roomShapeAdjacentGridIndexes.entries()) {
303
+ for (const [doorSlot, roomGridIndex] of roomShapeAdjacentGridIndexes) {
307
304
  const roomData = getRoomData(roomGridIndex);
308
305
  if (roomData === undefined) {
309
306
  roomShapeAdjacentGridIndexes.delete(doorSlot);
@@ -369,10 +366,7 @@ export function getRoomShapeAdjacentNonExistingGridIndexes(
369
366
  getRoomShapeAdjacentGridIndexes(safeRoomGridIndex, roomShape),
370
367
  );
371
368
 
372
- for (const [
373
- doorSlot,
374
- roomGridIndex,
375
- ] of roomShapeAdjacentGridIndexes.entries()) {
369
+ for (const [doorSlot, roomGridIndex] of roomShapeAdjacentGridIndexes) {
376
370
  const roomData = getRoomData(roomGridIndex);
377
371
  if (roomData !== undefined) {
378
372
  roomShapeAdjacentGridIndexes.delete(doorSlot);
@@ -56,10 +56,10 @@ export function defaultMapSetHash<V>(
56
56
  * ]);
57
57
  * const searchText = "f";
58
58
  * const match = getMapPartialMatch(map, searchText); // match is now equal to ["foo", 123]
59
+ * ```
59
60
  *
60
61
  * @returns If a match was found, returns a tuple of the map key and value. If a match was not
61
- * found, returns undefined.
62
- * ```
62
+ * found, returns undefined.
63
63
  */
64
64
  export function getMapPartialMatch<T>(
65
65
  searchText: string,
@@ -219,7 +219,7 @@ function mergeSerializedTable(
219
219
  if (!isTable(oldValue)) {
220
220
  // The child table does not exist on the old table. However, we still need to copy over
221
221
  // the new table, because we need to handle data types like "Foo | null". Thus, set up a
222
- // blank sub-table on the old table, and continue to recursively merge..
222
+ // blank sub-table on the old table, and continue to recursively merge.
223
223
  oldValue = new LuaMap();
224
224
  oldTable.set(key, oldValue);
225
225
  }
@@ -108,7 +108,7 @@ export function setDisplayFlags(
108
108
  ): void {
109
109
  const level = game.GetLevel();
110
110
 
111
- for (const [roomGridIndex, displayFlags] of displayFlagsMap.entries()) {
111
+ for (const [roomGridIndex, displayFlags] of displayFlagsMap) {
112
112
  if (MinimapAPI === undefined) {
113
113
  // We pass false to the `updateVisibility` argument as a small optimization.
114
114
  setRoomDisplayFlags(roomGridIndex, displayFlags, false);
@@ -18,7 +18,7 @@ export type SerializedRNG = LuaMap<string, unknown> & {
18
18
  const RECOMMENDED_SHIFT_IDX = 35;
19
19
 
20
20
  const OBJECT_NAME = "RNG";
21
- const KEYS = ["seed"];
21
+ const KEYS = ["seed"] as const;
22
22
 
23
23
  /** Helper function to copy an `RNG` Isaac API class. */
24
24
  export function copyRNG(rng: RNG): RNG {
@@ -13,7 +13,7 @@ export function clearTable(luaMap: LuaMap<AnyNotNil, unknown>): void {
13
13
  /** Helper function to copy specific values from a userdata object (e.g. `Vector`) to a table. */
14
14
  export function copyUserdataValuesToTable(
15
15
  object: unknown,
16
- keys: string[],
16
+ keys: string[] | readonly string[],
17
17
  luaMap: LuaMap<string, unknown>,
18
18
  ): void {
19
19
  if (!isUserdata(object)) {
@@ -9,15 +9,14 @@ import { CONSOLE_COMMANDS_SET } from "../sets/consoleCommandsSet";
9
9
  * - For example, `eRange(1, 3)` will return `[1, 2]`.
10
10
  * - For example, `eRange(2)` will return `[0, 1]`.
11
11
  *
12
- * @param start The number to start at.
13
- * @param end Optional. The number to end at. If not specified, then the start will be 0 and the
12
+ * @param start The integer to start at.
13
+ * @param end Optional. The integer to end at. If not specified, then the start will be 0 and the
14
14
  * first argument will be the end.
15
15
  * @param increment Optional. The increment to use. Default is 1.
16
16
  */
17
17
  export function eRange(start: int, end?: int, increment = 1): int[] {
18
18
  if (end === undefined) {
19
- end = start;
20
- start = 0;
19
+ return eRange(0, start);
21
20
  }
22
21
 
23
22
  const array: int[] = [];
@@ -52,23 +51,18 @@ export function getTraversalDescription(
52
51
  * - For example, `iRange(1, 3)` will return `[1, 2, 3]`.
53
52
  * - For example, `iRange(2)` will return `[0, 1, 2]`.
54
53
  *
55
- * @param start The number to start at.
56
- * @param end Optional. The number to end at. If not specified, then the start will be 0 and the
54
+ * @param start The integer to start at.
55
+ * @param end Optional. The integer to end at. If not specified, then the start will be 0 and the
57
56
  * first argument will be the end.
58
57
  * @param increment Optional. The increment to use. Default is 1.
59
58
  */
60
59
  export function iRange(start: int, end?: int, increment = 1): int[] {
61
60
  if (end === undefined) {
62
- end = start;
63
- start = 0;
61
+ return iRange(0, start);
64
62
  }
65
63
 
66
- const array: int[] = [];
67
- for (let i = start; i <= end; i += increment) {
68
- array.push(i);
69
- }
70
-
71
- return array;
64
+ const exclusiveEnd = end + 1;
65
+ return eRange(start, exclusiveEnd, increment);
72
66
  }
73
67
 
74
68
  /**
@@ -226,7 +220,7 @@ export function twoDimensionalSort<T>(array1: T[], array2: T[]): -1 | 0 | 1 {
226
220
  *
227
221
  * This function is only meant to be used with interfaces (i.e. types that will not exist at
228
222
  * run-time). If you are generating an object that will contain all of the keys of an enum, use the
229
- * `newObjectWithEnumKeys` helper function instead.
223
+ * `satisfies` operator with the `HasAllEnumValues` helper type instead.
230
224
  */
231
225
  export function validateInterfaceMatchesEnum<
232
226
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -20,7 +20,7 @@ export type SerializedVector = LuaMap<string, unknown> & {
20
20
  };
21
21
 
22
22
  const OBJECT_NAME = "Vector";
23
- const KEYS = ["X", "Y"];
23
+ const KEYS = ["X", "Y"] as const;
24
24
 
25
25
  /** Helper function to copy a `Vector` Isaac API class. */
26
26
  export function copyVector(vector: Vector): Vector {
@@ -10,6 +10,7 @@ import {
10
10
  EntityType,
11
11
  FamiliarVariant,
12
12
  GridEntityType,
13
+ GridEntityXMLType,
13
14
  InputHook,
14
15
  ItemType,
15
16
  KnifeVariant,
@@ -793,6 +794,19 @@ export interface AddCallbackParametersCustom {
793
794
  variant?: int,
794
795
  subType?: int,
795
796
  ];
797
+
798
+ [ModCallbackCustom.PRE_ROOM_ENTITY_SPAWN_FILTER]: [
799
+ callback: (
800
+ entityTypeOrGridEntityXMLType: EntityType | GridEntityXMLType,
801
+ variant: int,
802
+ subType: int,
803
+ gridIndex: int,
804
+ seed: Seed,
805
+ ) => [EntityType | GridEntityXMLType, int, int] | undefined,
806
+ entityTypeOrGridEntityXMLType?: EntityType | GridEntityXMLType,
807
+ variant?: int,
808
+ subType?: int,
809
+ ];
796
810
  }
797
811
 
798
812
  validateInterfaceMatchesEnum<AddCallbackParametersCustom, ModCallbackCustom>();
@@ -1,88 +1,89 @@
1
1
  import { PlayerType } from "isaac-typescript-definitions";
2
2
 
3
3
  /** Maps character names to the values of the `PlayerType` enum. */
4
- export const CHARACTER_NAME_TO_TYPE_MAP = new Map<string, PlayerType>([
5
- ["isaac", PlayerType.ISAAC], // 0
6
- ["magdalene", PlayerType.MAGDALENE], // 1
7
- ["maggy", PlayerType.MAGDALENE], // 1
8
- ["cain", PlayerType.CAIN], // 2
9
- ["judas", PlayerType.JUDAS], // 3
10
- ["blueBaby", PlayerType.BLUE_BABY], // 4
11
- ["bb", PlayerType.BLUE_BABY], // 4
12
- ["eve", PlayerType.EVE], // 5
13
- ["samson", PlayerType.SAMSON], // 6
14
- ["azazel", PlayerType.AZAZEL], // 7
15
- ["lazarus", PlayerType.LAZARUS], // 8
16
- // Needed so that "laz2" does not take precedence over "lazarus".
17
- ["laz", PlayerType.LAZARUS], // 8
18
- ["eden", PlayerType.EDEN], // 9
19
- ["theLost", PlayerType.LOST], // 10
20
- ["lost", PlayerType.LOST], // 10
21
- ["lazarus2", PlayerType.LAZARUS_2], // 11
22
- ["laz2", PlayerType.LAZARUS_2], // 11
23
- ["darkJudas", PlayerType.DARK_JUDAS], // 12
24
- ["dJudas", PlayerType.DARK_JUDAS], // 12
25
- ["blackJudas", PlayerType.DARK_JUDAS], // 12
26
- ["bJudas", PlayerType.DARK_JUDAS], // 12
27
- ["lilith", PlayerType.LILITH], // 13
28
- ["keeper", PlayerType.KEEPER], // 14
29
- ["apollyon", PlayerType.APOLLYON], // 15
30
- ["theForgotten", PlayerType.FORGOTTEN], // 16
31
- ["forgotten", PlayerType.FORGOTTEN], // 16
32
- ["theSoul", PlayerType.SOUL], // 17
33
- ["soul", PlayerType.SOUL], // 17
34
- ["bethany", PlayerType.BETHANY], // 18
35
- ["jacob", PlayerType.JACOB], // 19
36
- ["esau", PlayerType.ESAU], // 20
37
- ["taintedIsaac", PlayerType.ISAAC_B], // 21
38
- ["tIsaac", PlayerType.ISAAC_B], // 21
39
- ["taintedMagdalene", PlayerType.MAGDALENE_B], // 22
40
- ["tMagdalene", PlayerType.MAGDALENE_B], // 22
41
- ["taintedMaggy", PlayerType.MAGDALENE_B], // 22
42
- ["tMaggy", PlayerType.MAGDALENE_B], // 22
43
- ["taintedCain", PlayerType.CAIN_B], // 23
44
- ["tCain", PlayerType.CAIN_B], // 23
45
- ["taintedJudas", PlayerType.JUDAS_B], // 24
46
- ["tJudas", PlayerType.JUDAS_B], // 24
47
- ["taintedBlueBaby", PlayerType.BLUE_BABY_B], // 25
48
- ["tBlueBaby", PlayerType.BLUE_BABY_B], // 25
49
- ["tbb", PlayerType.BLUE_BABY_B], // 25
50
- ["taintedEve", PlayerType.EVE_B], // 26
51
- ["tEve", PlayerType.EVE_B], // 26
52
- ["taintedSamson", PlayerType.SAMSON_B], // 27
53
- ["tSamson", PlayerType.SAMSON_B], // 27
54
- ["taintedAzazel", PlayerType.AZAZEL_B], // 28
55
- ["tAzazel", PlayerType.AZAZEL_B], // 28
56
- ["taintedLazarus", PlayerType.LAZARUS_B], // 29
57
- ["tLazarus", PlayerType.LAZARUS_B], // 29
58
- ["taintedLaz", PlayerType.LAZARUS_B], // 29
59
- ["tLaz", PlayerType.LAZARUS_B], // 29
60
- ["taintedEden", PlayerType.EDEN_B], // 30
61
- ["tEden", PlayerType.EDEN_B], // 30
62
- ["taintedLost", PlayerType.LOST_B], // 31
63
- ["tLost", PlayerType.LOST_B], // 31
64
- ["taintedLilith", PlayerType.LILITH_B], // 32
65
- ["tLilith", PlayerType.LILITH_B], // 32
66
- ["taintedKeeper", PlayerType.KEEPER_B], // 33
67
- ["tKeeper", PlayerType.KEEPER_B], // 33
68
- ["taintedApollyon", PlayerType.APOLLYON_B], // 34
69
- ["tApollyon", PlayerType.APOLLYON_B], // 34
70
- ["taintedForgotten", PlayerType.FORGOTTEN_B], // 35
71
- ["tForgotten", PlayerType.FORGOTTEN_B], // 35
72
- ["taintedBethany", PlayerType.BETHANY_B], // 36
73
- ["tBethany", PlayerType.BETHANY_B], // 36
74
- ["taintedJacob", PlayerType.JACOB_B], // 37
75
- ["tJacob", PlayerType.JACOB_B], // 37
76
- ["taintedLazarusDead", PlayerType.LAZARUS_2_B], // 38
77
- ["tLazarusDead", PlayerType.LAZARUS_2_B], // 38
78
- ["taintedLazDead", PlayerType.LAZARUS_2_B], // 38
79
- ["tLazDead", PlayerType.LAZARUS_2_B], // 38
80
- ["deadTaintedLazarus", PlayerType.LAZARUS_2_B], // 38
81
- ["deadTLazarus", PlayerType.LAZARUS_2_B], // 38
82
- ["deadTaintedLaz", PlayerType.LAZARUS_2_B], // 38
83
- ["deadTLaz", PlayerType.LAZARUS_2_B], // 38
84
- ["taintedJacobGhost", PlayerType.JACOB_2_B], // 39
85
- ["tJacobGhost", PlayerType.JACOB_2_B], // 39
86
- ["taintedSoul", PlayerType.SOUL_B], // 40
87
- ["tSoul", PlayerType.SOUL_B], // 40
88
- ]);
4
+ export const CHARACTER_NAME_TO_TYPE_MAP: ReadonlyMap<string, PlayerType> =
5
+ new Map([
6
+ ["isaac", PlayerType.ISAAC], // 0
7
+ ["magdalene", PlayerType.MAGDALENE], // 1
8
+ ["maggy", PlayerType.MAGDALENE], // 1
9
+ ["cain", PlayerType.CAIN], // 2
10
+ ["judas", PlayerType.JUDAS], // 3
11
+ ["blueBaby", PlayerType.BLUE_BABY], // 4
12
+ ["bb", PlayerType.BLUE_BABY], // 4
13
+ ["eve", PlayerType.EVE], // 5
14
+ ["samson", PlayerType.SAMSON], // 6
15
+ ["azazel", PlayerType.AZAZEL], // 7
16
+ ["lazarus", PlayerType.LAZARUS], // 8
17
+ // Needed so that "laz2" does not take precedence over "lazarus".
18
+ ["laz", PlayerType.LAZARUS], // 8
19
+ ["eden", PlayerType.EDEN], // 9
20
+ ["theLost", PlayerType.LOST], // 10
21
+ ["lost", PlayerType.LOST], // 10
22
+ ["lazarus2", PlayerType.LAZARUS_2], // 11
23
+ ["laz2", PlayerType.LAZARUS_2], // 11
24
+ ["darkJudas", PlayerType.DARK_JUDAS], // 12
25
+ ["dJudas", PlayerType.DARK_JUDAS], // 12
26
+ ["blackJudas", PlayerType.DARK_JUDAS], // 12
27
+ ["bJudas", PlayerType.DARK_JUDAS], // 12
28
+ ["lilith", PlayerType.LILITH], // 13
29
+ ["keeper", PlayerType.KEEPER], // 14
30
+ ["apollyon", PlayerType.APOLLYON], // 15
31
+ ["theForgotten", PlayerType.FORGOTTEN], // 16
32
+ ["forgotten", PlayerType.FORGOTTEN], // 16
33
+ ["theSoul", PlayerType.SOUL], // 17
34
+ ["soul", PlayerType.SOUL], // 17
35
+ ["bethany", PlayerType.BETHANY], // 18
36
+ ["jacob", PlayerType.JACOB], // 19
37
+ ["esau", PlayerType.ESAU], // 20
38
+ ["taintedIsaac", PlayerType.ISAAC_B], // 21
39
+ ["tIsaac", PlayerType.ISAAC_B], // 21
40
+ ["taintedMagdalene", PlayerType.MAGDALENE_B], // 22
41
+ ["tMagdalene", PlayerType.MAGDALENE_B], // 22
42
+ ["taintedMaggy", PlayerType.MAGDALENE_B], // 22
43
+ ["tMaggy", PlayerType.MAGDALENE_B], // 22
44
+ ["taintedCain", PlayerType.CAIN_B], // 23
45
+ ["tCain", PlayerType.CAIN_B], // 23
46
+ ["taintedJudas", PlayerType.JUDAS_B], // 24
47
+ ["tJudas", PlayerType.JUDAS_B], // 24
48
+ ["taintedBlueBaby", PlayerType.BLUE_BABY_B], // 25
49
+ ["tBlueBaby", PlayerType.BLUE_BABY_B], // 25
50
+ ["tbb", PlayerType.BLUE_BABY_B], // 25
51
+ ["taintedEve", PlayerType.EVE_B], // 26
52
+ ["tEve", PlayerType.EVE_B], // 26
53
+ ["taintedSamson", PlayerType.SAMSON_B], // 27
54
+ ["tSamson", PlayerType.SAMSON_B], // 27
55
+ ["taintedAzazel", PlayerType.AZAZEL_B], // 28
56
+ ["tAzazel", PlayerType.AZAZEL_B], // 28
57
+ ["taintedLazarus", PlayerType.LAZARUS_B], // 29
58
+ ["tLazarus", PlayerType.LAZARUS_B], // 29
59
+ ["taintedLaz", PlayerType.LAZARUS_B], // 29
60
+ ["tLaz", PlayerType.LAZARUS_B], // 29
61
+ ["taintedEden", PlayerType.EDEN_B], // 30
62
+ ["tEden", PlayerType.EDEN_B], // 30
63
+ ["taintedLost", PlayerType.LOST_B], // 31
64
+ ["tLost", PlayerType.LOST_B], // 31
65
+ ["taintedLilith", PlayerType.LILITH_B], // 32
66
+ ["tLilith", PlayerType.LILITH_B], // 32
67
+ ["taintedKeeper", PlayerType.KEEPER_B], // 33
68
+ ["tKeeper", PlayerType.KEEPER_B], // 33
69
+ ["taintedApollyon", PlayerType.APOLLYON_B], // 34
70
+ ["tApollyon", PlayerType.APOLLYON_B], // 34
71
+ ["taintedForgotten", PlayerType.FORGOTTEN_B], // 35
72
+ ["tForgotten", PlayerType.FORGOTTEN_B], // 35
73
+ ["taintedBethany", PlayerType.BETHANY_B], // 36
74
+ ["tBethany", PlayerType.BETHANY_B], // 36
75
+ ["taintedJacob", PlayerType.JACOB_B], // 37
76
+ ["tJacob", PlayerType.JACOB_B], // 37
77
+ ["taintedLazarusDead", PlayerType.LAZARUS_2_B], // 38
78
+ ["tLazarusDead", PlayerType.LAZARUS_2_B], // 38
79
+ ["taintedLazDead", PlayerType.LAZARUS_2_B], // 38
80
+ ["tLazDead", PlayerType.LAZARUS_2_B], // 38
81
+ ["deadTaintedLazarus", PlayerType.LAZARUS_2_B], // 38
82
+ ["deadTLazarus", PlayerType.LAZARUS_2_B], // 38
83
+ ["deadTaintedLaz", PlayerType.LAZARUS_2_B], // 38
84
+ ["deadTLaz", PlayerType.LAZARUS_2_B], // 38
85
+ ["taintedJacobGhost", PlayerType.JACOB_2_B], // 39
86
+ ["tJacobGhost", PlayerType.JACOB_2_B], // 39
87
+ ["taintedSoul", PlayerType.SOUL_B], // 40
88
+ ["tSoul", PlayerType.SOUL_B], // 40
89
+ ]);
@@ -6,10 +6,10 @@ import {
6
6
  ONE_BY_ONE_CONTENTS_WIDTH,
7
7
  } from "./roomShapeVolumes";
8
8
 
9
- const TWO_BY_TWO_BOUNDS: [width: int, height: int] = [
9
+ const TWO_BY_TWO_BOUNDS: readonly [width: int, height: int] = [
10
10
  ONE_BY_ONE_CONTENTS_WIDTH * 2,
11
11
  ONE_BY_ONE_CONTENTS_HEIGHT * 2,
12
- ];
12
+ ] as const;
13
13
 
14
14
  /**
15
15
  * The size of a room shape's contents. This does not include the tiles that the walls are on. L