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.
- package/dist/index.rollup.d.ts +26 -4
- package/dist/isaacscript-common.lua +626 -645
- package/dist/src/classes/ModFeature.d.ts.map +1 -1
- package/dist/src/classes/ModFeature.lua +5 -9
- package/dist/src/classes/ModUpgraded.d.ts.map +1 -1
- package/dist/src/classes/ModUpgraded.lua +8 -14
- package/dist/src/classes/callbacks/PostNewRoomEarly.lua +2 -2
- package/dist/src/classes/features/callbackLogic/CustomGridEntities.d.ts.map +1 -1
- package/dist/src/classes/features/callbackLogic/CustomGridEntities.lua +3 -3
- package/dist/src/classes/features/other/CharacterHealthConversion.lua +1 -1
- package/dist/src/classes/features/other/CustomItemPools.d.ts.map +1 -1
- package/dist/src/classes/features/other/CustomItemPools.lua +12 -6
- package/dist/src/classes/features/other/CustomStages.d.ts.map +1 -1
- package/dist/src/classes/features/other/CustomStages.lua +12 -14
- package/dist/src/classes/features/other/CustomTrapdoors.d.ts.map +1 -1
- package/dist/src/classes/features/other/CustomTrapdoors.lua +6 -8
- package/dist/src/classes/features/other/DeployJSONRoom.d.ts.map +1 -1
- package/dist/src/classes/features/other/DeployJSONRoom.lua +15 -15
- package/dist/src/classes/features/other/ModdedElementSets.d.ts.map +1 -1
- package/dist/src/classes/features/other/ModdedElementSets.lua +21 -12
- package/dist/src/classes/features/other/Pause.d.ts.map +1 -1
- package/dist/src/classes/features/other/Pause.lua +4 -6
- package/dist/src/classes/features/other/SaveDataManager.d.ts.map +1 -1
- package/dist/src/classes/features/other/SaveDataManager.lua +5 -9
- package/dist/src/classes/features/other/customStages/backdrop.lua +9 -10
- package/dist/src/classes/features/other/saveDataManager/restoreDefaults.lua +1 -1
- package/dist/src/functions/array.d.ts +3 -0
- package/dist/src/functions/array.d.ts.map +1 -1
- package/dist/src/functions/array.lua +9 -3
- package/dist/src/functions/bitSet128.d.ts.map +1 -1
- package/dist/src/functions/bitSet128.lua +4 -6
- package/dist/src/functions/bitwise.d.ts.map +1 -1
- package/dist/src/functions/bitwise.lua +7 -3
- package/dist/src/functions/color.d.ts.map +1 -1
- package/dist/src/functions/color.lua +5 -9
- package/dist/src/functions/deepCopy.lua +23 -31
- package/dist/src/functions/entities.d.ts.map +1 -1
- package/dist/src/functions/entities.lua +20 -18
- package/dist/src/functions/entitiesSpecific.d.ts.map +1 -1
- package/dist/src/functions/entitiesSpecific.lua +11 -27
- package/dist/src/functions/enums.d.ts +6 -4
- package/dist/src/functions/enums.d.ts.map +1 -1
- package/dist/src/functions/enums.lua +13 -9
- package/dist/src/functions/gridEntities.d.ts.map +1 -1
- package/dist/src/functions/gridEntities.lua +18 -11
- package/dist/src/functions/gridEntitiesSpecific.d.ts.map +1 -1
- package/dist/src/functions/gridEntitiesSpecific.lua +16 -28
- package/dist/src/functions/input.d.ts +3 -0
- package/dist/src/functions/input.d.ts.map +1 -1
- package/dist/src/functions/input.lua +14 -14
- package/dist/src/functions/jsonRoom.d.ts.map +1 -1
- package/dist/src/functions/jsonRoom.lua +35 -23
- package/dist/src/functions/kColor.d.ts.map +1 -1
- package/dist/src/functions/kColor.lua +6 -12
- package/dist/src/functions/map.d.ts.map +1 -1
- package/dist/src/functions/map.lua +3 -3
- package/dist/src/functions/minimap.d.ts.map +1 -1
- package/dist/src/functions/minimap.lua +17 -9
- package/dist/src/functions/players.d.ts.map +1 -1
- package/dist/src/functions/players.lua +17 -22
- package/dist/src/functions/rng.d.ts.map +1 -1
- package/dist/src/functions/rng.lua +3 -3
- package/dist/src/functions/roomShapeWalls.d.ts.map +1 -1
- package/dist/src/functions/roomShapeWalls.lua +7 -3
- package/dist/src/functions/roomTransition.d.ts.map +1 -1
- package/dist/src/functions/roomTransition.lua +7 -3
- package/dist/src/functions/rooms.d.ts.map +1 -1
- package/dist/src/functions/rooms.lua +8 -5
- package/dist/src/functions/serialization.d.ts.map +1 -1
- package/dist/src/functions/serialization.lua +8 -18
- package/dist/src/functions/table.d.ts.map +1 -1
- package/dist/src/functions/table.lua +6 -12
- package/dist/src/functions/tstlClass.d.ts.map +1 -1
- package/dist/src/functions/tstlClass.lua +3 -3
- package/dist/src/functions/utils.d.ts +9 -0
- package/dist/src/functions/utils.d.ts.map +1 -1
- package/dist/src/functions/utils.lua +14 -6
- package/dist/src/functions/vector.d.ts.map +1 -1
- package/dist/src/functions/vector.lua +4 -6
- package/dist/src/functions/weighted.d.ts.map +1 -1
- package/dist/src/functions/weighted.lua +7 -3
- package/dist/src/sets/bossSets.d.ts.map +1 -1
- package/dist/src/sets/bossSets.lua +3 -3
- package/package.json +2 -2
- package/src/classes/ModFeature.ts +16 -12
- package/src/classes/ModUpgraded.ts +18 -16
- package/src/classes/callbacks/PostNewRoomEarly.ts +2 -2
- package/src/classes/features/callbackLogic/CustomGridEntities.ts +2 -3
- package/src/classes/features/other/CharacterHealthConversion.ts +1 -1
- package/src/classes/features/other/CustomItemPools.ts +9 -8
- package/src/classes/features/other/CustomStages.ts +9 -10
- package/src/classes/features/other/CustomTrapdoors.ts +9 -10
- package/src/classes/features/other/DeployJSONRoom.ts +21 -21
- package/src/classes/features/other/ModdedElementSets.ts +18 -21
- package/src/classes/features/other/Pause.ts +9 -6
- package/src/classes/features/other/SaveDataManager.ts +14 -16
- package/src/classes/features/other/customStages/backdrop.ts +5 -6
- package/src/classes/features/other/saveDataManager/restoreDefaults.ts +1 -1
- package/src/functions/array.ts +8 -6
- package/src/functions/bitSet128.ts +9 -10
- package/src/functions/bitwise.ts +6 -3
- package/src/functions/color.ts +13 -15
- package/src/functions/deepCopy.ts +18 -24
- package/src/functions/deepCopyTests.ts +5 -6
- package/src/functions/entities.ts +22 -20
- package/src/functions/entitiesSpecific.ts +10 -27
- package/src/functions/enums.ts +29 -17
- package/src/functions/gridEntities.ts +14 -16
- package/src/functions/gridEntitiesSpecific.ts +15 -28
- package/src/functions/input.ts +3 -3
- package/src/functions/jsonRoom.ts +39 -27
- package/src/functions/kColor.ts +17 -20
- package/src/functions/map.ts +5 -5
- package/src/functions/minimap.ts +16 -15
- package/src/functions/players.ts +7 -10
- package/src/functions/rng.ts +5 -5
- package/src/functions/roomShapeWalls.ts +3 -4
- package/src/functions/roomTransition.ts +5 -5
- package/src/functions/rooms.ts +5 -6
- package/src/functions/serialization.ts +25 -30
- package/src/functions/table.ts +18 -20
- package/src/functions/tstlClass.ts +5 -5
- package/src/functions/utils.ts +27 -6
- package/src/functions/vector.ts +9 -10
- package/src/functions/weighted.ts +5 -5
- package/src/sets/bossSets.ts +5 -5
package/src/functions/array.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { ReadonlySet } from "../types/ReadonlySet";
|
|
|
2
2
|
import { getRandomInt } from "./random";
|
|
3
3
|
import { getRandomSeed, isRNG, newRNG } from "./rng";
|
|
4
4
|
import { isNumber, isTable } from "./types";
|
|
5
|
-
import { eRange } from "./utils";
|
|
5
|
+
import { assertDefined, eRange } from "./utils";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Helper function for determining if two arrays contain the exact same elements. Note that this
|
|
@@ -344,6 +344,9 @@ export function getArrayIndexes<T>(array: T[] | readonly T[]): int[] {
|
|
|
344
344
|
* Helper function to return the last element of an array.
|
|
345
345
|
*
|
|
346
346
|
* If the array is empty, this will return undefined.
|
|
347
|
+
*
|
|
348
|
+
* (Note that TSTL does not support `Array.at(-1)`, which would make this helper function largely
|
|
349
|
+
* unnecessary.)
|
|
347
350
|
*/
|
|
348
351
|
export function getLastElement<T>(array: T[]): T | undefined {
|
|
349
352
|
return array[array.length - 1];
|
|
@@ -372,11 +375,10 @@ export function getRandomArrayElement<T>(
|
|
|
372
375
|
exceptions.length > 0 ? arrayRemove(array, ...exceptions) : array;
|
|
373
376
|
const randomIndex = getRandomArrayIndex(arrayToUse, seedOrRNG);
|
|
374
377
|
const randomElement = arrayToUse[randomIndex];
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}
|
|
378
|
+
assertDefined(
|
|
379
|
+
randomElement,
|
|
380
|
+
`Failed to get a random array element since the random index of ${randomIndex} was not valid.`,
|
|
381
|
+
);
|
|
380
382
|
|
|
381
383
|
return randomElement;
|
|
382
384
|
}
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
tableHasKeys,
|
|
8
8
|
} from "./table";
|
|
9
9
|
import { isTable } from "./types";
|
|
10
|
+
import { assertDefined } from "./utils";
|
|
10
11
|
|
|
11
12
|
export type SerializedBitSet128 = LuaMap<string, unknown> & {
|
|
12
13
|
readonly __serializedBitSet128Brand: symbol;
|
|
@@ -45,16 +46,14 @@ export function deserializeBitSet128(
|
|
|
45
46
|
|
|
46
47
|
const [l, h] = getNumbersFromTable(bitSet128, OBJECT_NAME, ...KEYS);
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
);
|
|
57
|
-
}
|
|
49
|
+
assertDefined(
|
|
50
|
+
l,
|
|
51
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: l`,
|
|
52
|
+
);
|
|
53
|
+
assertDefined(
|
|
54
|
+
h,
|
|
55
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: h`,
|
|
56
|
+
);
|
|
58
57
|
|
|
59
58
|
return BitSet128(l, h);
|
|
60
59
|
}
|
package/src/functions/bitwise.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { addFlag } from "./flag";
|
|
2
|
+
import { assertDefined } from "./utils";
|
|
2
3
|
|
|
3
4
|
/** Helper function to convert a set of flags to a single `BitFlags` object. */
|
|
4
5
|
export function arrayToBitFlags<T extends BitFlag | BitFlag128>(
|
|
@@ -33,9 +34,11 @@ export function convertDecimalToBinary(number: number, minLength?: int): int[] {
|
|
|
33
34
|
const bitsString = number.toString(2);
|
|
34
35
|
for (const bitString of bitsString) {
|
|
35
36
|
const bit = tonumber(bitString);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
assertDefined(
|
|
38
|
+
bit,
|
|
39
|
+
`Failed to convert the following number to binary: ${number}`,
|
|
40
|
+
);
|
|
41
|
+
|
|
39
42
|
bits.push(bit);
|
|
40
43
|
}
|
|
41
44
|
|
package/src/functions/color.ts
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
tableHasKeys,
|
|
10
10
|
} from "./table";
|
|
11
11
|
import { isTable } from "./types";
|
|
12
|
+
import { assertDefined } from "./utils";
|
|
12
13
|
|
|
13
14
|
export type SerializedColor = LuaMap<string, unknown> & {
|
|
14
15
|
readonly __serializedColorBrand: symbol;
|
|
@@ -58,21 +59,18 @@ export function deserializeColor(color: SerializedColor): Color {
|
|
|
58
59
|
...KEYS,
|
|
59
60
|
);
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: B`,
|
|
74
|
-
);
|
|
75
|
-
}
|
|
62
|
+
assertDefined(
|
|
63
|
+
r,
|
|
64
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: R`,
|
|
65
|
+
);
|
|
66
|
+
assertDefined(
|
|
67
|
+
g,
|
|
68
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: G`,
|
|
69
|
+
);
|
|
70
|
+
assertDefined(
|
|
71
|
+
b,
|
|
72
|
+
`Failed to deserialize a ${OBJECT_NAME} object since the provided object did not have a value for: B`,
|
|
73
|
+
);
|
|
76
74
|
|
|
77
75
|
return Color(r, g, b, a, ro, go, bo);
|
|
78
76
|
}
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
newTSTLClass,
|
|
25
25
|
} from "./tstlClass";
|
|
26
26
|
import { asString, isNumber, isPrimitive } from "./types";
|
|
27
|
-
import { getTraversalDescription } from "./utils";
|
|
27
|
+
import { assertDefined, getTraversalDescription } from "./utils";
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* `deepCopy` is a semi-generic deep cloner. It will recursively copy all of the values so that none
|
|
@@ -361,11 +361,10 @@ function getNewDefaultMap(
|
|
|
361
361
|
const defaultMapValue = defaultMap.get(
|
|
362
362
|
SerializationBrand.DEFAULT_MAP_VALUE,
|
|
363
363
|
);
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
364
|
+
assertDefined(
|
|
365
|
+
defaultMapValue,
|
|
366
|
+
`Failed to deserialize a default map of "${traversalDescription}", since there was no serialization brand of: ${SerializationBrand.DEFAULT_MAP_VALUE}`,
|
|
367
|
+
);
|
|
369
368
|
|
|
370
369
|
// eslint-disable-next-line isaacscript/no-invalid-default-map
|
|
371
370
|
return new DefaultMap(defaultMapValue);
|
|
@@ -518,21 +517,21 @@ function deepCopyTSTLClass(
|
|
|
518
517
|
const tstlClassName = tstlClass.get(SerializationBrand.TSTL_CLASS) as
|
|
519
518
|
| string
|
|
520
519
|
| undefined;
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
}
|
|
520
|
+
assertDefined(
|
|
521
|
+
tstlClassName,
|
|
522
|
+
"Failed to deserialize a TSTL class since the brand did not contain the class name.",
|
|
523
|
+
);
|
|
526
524
|
|
|
527
525
|
const classConstructor = classConstructors.get(tstlClassName);
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
}
|
|
526
|
+
assertDefined(
|
|
527
|
+
classConstructor,
|
|
528
|
+
`Failed to deserialize a TSTL class since there was no constructor registered for a class name of "${tstlClassName}". If this mod is using the save data manager, it must register the class constructor with the "saveDataManagerRegisterClass" method.`,
|
|
529
|
+
);
|
|
533
530
|
|
|
534
531
|
// eslint-disable-next-line new-cap
|
|
535
532
|
newClass = new classConstructor() as TSTLClass;
|
|
533
|
+
|
|
534
|
+
break;
|
|
536
535
|
}
|
|
537
536
|
}
|
|
538
537
|
|
|
@@ -725,16 +724,10 @@ function deepCopyUserdata(
|
|
|
725
724
|
serializationType: SerializationType,
|
|
726
725
|
traversalDescription: string,
|
|
727
726
|
) {
|
|
728
|
-
const classType = getIsaacAPIClassName(value);
|
|
729
|
-
if (classType === undefined) {
|
|
730
|
-
error(
|
|
731
|
-
`The deep copy function was not able to derive the Isaac API class type for: ${traversalDescription}`,
|
|
732
|
-
);
|
|
733
|
-
}
|
|
734
|
-
|
|
735
727
|
if (!isCopyableIsaacAPIClass(value)) {
|
|
728
|
+
const className = getIsaacAPIClassName(value) ?? "Unknown";
|
|
736
729
|
error(
|
|
737
|
-
`The deep copy function does not support serializing "${traversalDescription}", since it is an Isaac API class of type: ${
|
|
730
|
+
`The deep copy function does not support serializing "${traversalDescription}", since it is an Isaac API class of type: ${className}`,
|
|
738
731
|
);
|
|
739
732
|
}
|
|
740
733
|
|
|
@@ -747,6 +740,7 @@ function deepCopyUserdata(
|
|
|
747
740
|
return serializeIsaacAPIClass(value);
|
|
748
741
|
}
|
|
749
742
|
|
|
743
|
+
// eslint-disable-next-line isaacscript/require-break
|
|
750
744
|
case SerializationType.DESERIALIZE: {
|
|
751
745
|
error(
|
|
752
746
|
`The deep copy function can not deserialize "${traversalDescription}", since it is userdata.`,
|
|
@@ -69,8 +69,7 @@ function copiedObjectHasKeyAndValueString() {
|
|
|
69
69
|
"copiedObjectHasKeyAndValueString",
|
|
70
70
|
);
|
|
71
71
|
|
|
72
|
-
const value = newObject[keyToLookFor];
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
72
|
+
const value = newObject[keyToLookFor] as string | undefined;
|
|
74
73
|
if (value === undefined) {
|
|
75
74
|
error(`The copied object did not have a key of: ${keyToLookFor}`);
|
|
76
75
|
}
|
|
@@ -236,8 +235,9 @@ function copiedObjectHasChildObject() {
|
|
|
236
235
|
"copiedObjectHasChildObject",
|
|
237
236
|
);
|
|
238
237
|
|
|
239
|
-
const childObject = newObject[childObjectIndex]
|
|
240
|
-
|
|
238
|
+
const childObject = newObject[childObjectIndex] as
|
|
239
|
+
| (typeof oldObject)["abc"]
|
|
240
|
+
| undefined;
|
|
241
241
|
if (childObject === undefined) {
|
|
242
242
|
error(`Failed to find the child object at index: ${childObjectIndex}`);
|
|
243
243
|
}
|
|
@@ -246,8 +246,7 @@ function copiedObjectHasChildObject() {
|
|
|
246
246
|
error(`The copied child object had a type of: ${typeof childObject}`);
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
-
const value = childObject[keyToLookFor];
|
|
250
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
249
|
+
const value = childObject[keyToLookFor] as string | undefined;
|
|
251
250
|
if (value === undefined) {
|
|
252
251
|
error(`The child object did not have a key of: ${keyToLookFor}`);
|
|
253
252
|
}
|
|
@@ -13,6 +13,7 @@ import { isRNG, newRNG } from "./rng";
|
|
|
13
13
|
import { setSpriteOpacity } from "./sprites";
|
|
14
14
|
import { isTSTLSet } from "./tstlClass";
|
|
15
15
|
import { isPrimitive } from "./types";
|
|
16
|
+
import { assertDefined } from "./utils";
|
|
16
17
|
import { doesVectorHaveLength, isVector, vectorToString } from "./vector";
|
|
17
18
|
|
|
18
19
|
/** From DeadInfinity. */
|
|
@@ -167,21 +168,22 @@ export function getConstituentsFromEntityID(
|
|
|
167
168
|
const [entityTypeString, variantString, subTypeString] = parts;
|
|
168
169
|
|
|
169
170
|
const entityType = tonumber(entityTypeString);
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
assertDefined(
|
|
172
|
+
entityType,
|
|
173
|
+
`Failed to convert the entity type to a number: ${entityTypeString}`,
|
|
174
|
+
);
|
|
173
175
|
|
|
174
176
|
const variant = tonumber(variantString);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
177
|
+
assertDefined(
|
|
178
|
+
variant,
|
|
179
|
+
`Failed to convert the entity variant to a number: ${variantString}`,
|
|
180
|
+
);
|
|
178
181
|
|
|
179
182
|
const subType = tonumber(subTypeString);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
183
|
+
assertDefined(
|
|
184
|
+
subType,
|
|
185
|
+
`Failed to convert the entity sub-type to a number: ${subTypeString}`,
|
|
186
|
+
);
|
|
185
187
|
|
|
186
188
|
return [entityType, variant, subType];
|
|
187
189
|
}
|
|
@@ -241,9 +243,7 @@ export function getEntityFields(
|
|
|
241
243
|
const metatable = getmetatable(entity) as
|
|
242
244
|
| LuaMap<AnyNotNil, unknown>
|
|
243
245
|
| undefined;
|
|
244
|
-
|
|
245
|
-
error("Failed to get the metatable for an entity.");
|
|
246
|
-
}
|
|
246
|
+
assertDefined(metatable, "Failed to get the metatable for an entity.");
|
|
247
247
|
|
|
248
248
|
setPrimitiveEntityFields(entity, metatable, entityFields);
|
|
249
249
|
|
|
@@ -258,9 +258,10 @@ export function getEntityFields(
|
|
|
258
258
|
const parentTable = metatable.get("__parent") as
|
|
259
259
|
| LuaMap<AnyNotNil, unknown>
|
|
260
260
|
| undefined;
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
261
|
+
assertDefined(
|
|
262
|
+
parentTable,
|
|
263
|
+
'Failed to get the "__parent" table for an entity.',
|
|
264
|
+
);
|
|
264
265
|
|
|
265
266
|
setPrimitiveEntityFields(entity, parentTable, entityFields);
|
|
266
267
|
|
|
@@ -275,9 +276,10 @@ function setPrimitiveEntityFields(
|
|
|
275
276
|
const propGetTable = metatable.get("__propget") as
|
|
276
277
|
| LuaMap<AnyNotNil, unknown>
|
|
277
278
|
| undefined;
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
279
|
+
assertDefined(
|
|
280
|
+
propGetTable,
|
|
281
|
+
'Failed to get the "__propget" table for an entity.',
|
|
282
|
+
);
|
|
281
283
|
|
|
282
284
|
for (const [key] of propGetTable) {
|
|
283
285
|
// The values of this table are functions. Thus, we use the key to index the original entity.
|
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
import { EntityType } from "isaac-typescript-definitions";
|
|
13
13
|
import { VectorZero } from "../core/constants";
|
|
14
14
|
import { getEntities, removeEntities, spawn } from "./entities";
|
|
15
|
+
import { assertDefined } from "./utils";
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Helper function to get all of the bombs in the room. (Specifically, this refers to the
|
|
@@ -562,9 +563,7 @@ export function spawnBomb(
|
|
|
562
563
|
);
|
|
563
564
|
|
|
564
565
|
const bomb = entity.ToBomb();
|
|
565
|
-
|
|
566
|
-
error("Failed to spawn a bomb.");
|
|
567
|
-
}
|
|
566
|
+
assertDefined(bomb, "Failed to spawn a bomb.");
|
|
568
567
|
|
|
569
568
|
return bomb;
|
|
570
569
|
}
|
|
@@ -608,9 +607,7 @@ export function spawnEffect(
|
|
|
608
607
|
);
|
|
609
608
|
|
|
610
609
|
const effect = entity.ToEffect();
|
|
611
|
-
|
|
612
|
-
error("Failed to spawn an effect.");
|
|
613
|
-
}
|
|
610
|
+
assertDefined(effect, "Failed to spawn an effect.");
|
|
614
611
|
|
|
615
612
|
return effect;
|
|
616
613
|
}
|
|
@@ -659,9 +656,7 @@ export function spawnFamiliar(
|
|
|
659
656
|
);
|
|
660
657
|
|
|
661
658
|
const familiar = entity.ToFamiliar();
|
|
662
|
-
|
|
663
|
-
error("Failed to spawn a familiar.");
|
|
664
|
-
}
|
|
659
|
+
assertDefined(familiar, "Failed to spawn a familiar.");
|
|
665
660
|
|
|
666
661
|
return familiar;
|
|
667
662
|
}
|
|
@@ -705,9 +700,7 @@ export function spawnKnife(
|
|
|
705
700
|
);
|
|
706
701
|
|
|
707
702
|
const knife = entity.ToKnife();
|
|
708
|
-
|
|
709
|
-
error("Failed to spawn a knife.");
|
|
710
|
-
}
|
|
703
|
+
assertDefined(knife, "Failed to spawn a knife.");
|
|
711
704
|
|
|
712
705
|
return knife;
|
|
713
706
|
}
|
|
@@ -751,9 +744,7 @@ export function spawnLaser(
|
|
|
751
744
|
);
|
|
752
745
|
|
|
753
746
|
const laser = entity.ToLaser();
|
|
754
|
-
|
|
755
|
-
error("Failed to spawn a laser.");
|
|
756
|
-
}
|
|
747
|
+
assertDefined(laser, "Failed to spawn a laser.");
|
|
757
748
|
|
|
758
749
|
return laser;
|
|
759
750
|
}
|
|
@@ -803,9 +794,7 @@ export function spawnNPC(
|
|
|
803
794
|
);
|
|
804
795
|
|
|
805
796
|
const npc = entity.ToNPC();
|
|
806
|
-
|
|
807
|
-
error("Failed to spawn an NPC.");
|
|
808
|
-
}
|
|
797
|
+
assertDefined(npc, "Failed to spawn an NPC.");
|
|
809
798
|
|
|
810
799
|
return npc;
|
|
811
800
|
}
|
|
@@ -856,9 +845,7 @@ export function spawnPickup(
|
|
|
856
845
|
);
|
|
857
846
|
|
|
858
847
|
const pickup = entity.ToPickup();
|
|
859
|
-
|
|
860
|
-
error("Failed to spawn a pickup.");
|
|
861
|
-
}
|
|
848
|
+
assertDefined(pickup, "Failed to spawn a pickup.");
|
|
862
849
|
|
|
863
850
|
return pickup;
|
|
864
851
|
}
|
|
@@ -902,9 +889,7 @@ export function spawnProjectile(
|
|
|
902
889
|
);
|
|
903
890
|
|
|
904
891
|
const projectile = entity.ToProjectile();
|
|
905
|
-
|
|
906
|
-
error("Failed to spawn a projectile.");
|
|
907
|
-
}
|
|
892
|
+
assertDefined(projectile, "Failed to spawn a projectile.");
|
|
908
893
|
|
|
909
894
|
return projectile;
|
|
910
895
|
}
|
|
@@ -987,9 +972,7 @@ export function spawnTear(
|
|
|
987
972
|
);
|
|
988
973
|
|
|
989
974
|
const tear = entity.ToTear();
|
|
990
|
-
|
|
991
|
-
error("Failed to spawn a tear.");
|
|
992
|
-
}
|
|
975
|
+
assertDefined(tear, "Failed to spawn a tear.");
|
|
993
976
|
|
|
994
977
|
return tear;
|
|
995
978
|
}
|
package/src/functions/enums.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ReadonlySet } from "../types/ReadonlySet";
|
|
2
2
|
import { getRandomArrayElement } from "./array";
|
|
3
3
|
import { getRandomSeed } from "./rng";
|
|
4
|
-
import { isString } from "./types";
|
|
5
|
-
import { iRange } from "./utils";
|
|
4
|
+
import { isNumber, isString } from "./types";
|
|
5
|
+
import { assertDefined, iRange } from "./utils";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* TypeScriptToLua will transpile TypeScript enums to Lua tables that have a double mapping. Thus,
|
|
@@ -60,13 +60,17 @@ export function getEnumEntries<T>(
|
|
|
60
60
|
* For a more in depth explanation, see:
|
|
61
61
|
* https://isaacscript.github.io/main/gotchas#iterating-over-enums
|
|
62
62
|
*/
|
|
63
|
-
export function getEnumKeys
|
|
63
|
+
export function getEnumKeys(
|
|
64
|
+
transpiledEnum: Record<string | number, string | number>,
|
|
65
|
+
): string[] {
|
|
64
66
|
const enumEntries = getEnumEntries(transpiledEnum);
|
|
65
67
|
return enumEntries.map(([key, _value]) => key);
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
/** Helper function to get the amount of entries inside of an enum. */
|
|
69
|
-
export function getEnumLength
|
|
71
|
+
export function getEnumLength(
|
|
72
|
+
transpiledEnum: Record<string | number, string | number>,
|
|
73
|
+
): int {
|
|
70
74
|
const enumEntries = getEnumEntries(transpiledEnum);
|
|
71
75
|
return enumEntries.length;
|
|
72
76
|
}
|
|
@@ -95,18 +99,17 @@ export function getEnumValues<T>(transpiledEnum: T): Array<T[keyof T]> {
|
|
|
95
99
|
/**
|
|
96
100
|
* Helper function to get the enum value with the highest value.
|
|
97
101
|
*
|
|
98
|
-
* Note that this is not necessarily the enum value that is declared last, since there
|
|
99
|
-
* infer that at run-time.
|
|
102
|
+
* Note that this is not necessarily the enum value that is declared last in the code, since there
|
|
103
|
+
* is no way to infer that at run-time.
|
|
100
104
|
*/
|
|
101
105
|
export function getHighestEnumValue<T>(transpiledEnum: T): T[keyof T] {
|
|
102
106
|
const enumValues = getEnumValues(transpiledEnum);
|
|
103
107
|
|
|
104
108
|
const lastElement = enumValues[enumValues.length - 1];
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
109
|
+
assertDefined(
|
|
110
|
+
lastElement,
|
|
111
|
+
"Failed to get the last value from an enum since the enum was empty.",
|
|
112
|
+
);
|
|
110
113
|
|
|
111
114
|
return lastElement;
|
|
112
115
|
}
|
|
@@ -128,6 +131,15 @@ export function getRandomEnumValue<T>(
|
|
|
128
131
|
return getRandomArrayElement(enumValues, seedOrRNG, exceptions);
|
|
129
132
|
}
|
|
130
133
|
|
|
134
|
+
/** Helper function to validate that a particular value exists inside of an enum. */
|
|
135
|
+
export function isEnumValue(
|
|
136
|
+
value: number | string,
|
|
137
|
+
transpiledEnum: Record<string | number, string | number>,
|
|
138
|
+
): boolean {
|
|
139
|
+
const enumValues = getEnumValues(transpiledEnum);
|
|
140
|
+
return enumValues.includes(value);
|
|
141
|
+
}
|
|
142
|
+
|
|
131
143
|
/**
|
|
132
144
|
* Helper function to check every value of a custom enum for -1. Will throw an run-time error if any
|
|
133
145
|
* -1 values are found. This is helpful because many methods of the Isaac class return -1 if they
|
|
@@ -167,12 +179,12 @@ export function validateEnumContiguous<T>(
|
|
|
167
179
|
): void {
|
|
168
180
|
const values = getEnumValues(transpiledEnum);
|
|
169
181
|
const lastValue = values[values.length - 1];
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
if (
|
|
182
|
+
assertDefined(
|
|
183
|
+
lastValue,
|
|
184
|
+
"Failed to validate that an enum was contiguous, since the last value was undefined.",
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
if (!isNumber(lastValue)) {
|
|
176
188
|
error(
|
|
177
189
|
"Failed to validate that an enum was contiguous, since the last value was not a number.",
|
|
178
190
|
);
|
|
@@ -23,7 +23,7 @@ import { getEffects } from "./entitiesSpecific";
|
|
|
23
23
|
import { isCircleIntersectingRectangle } from "./math";
|
|
24
24
|
import { roomUpdateSafe } from "./rooms";
|
|
25
25
|
import { asNumber, isNumber } from "./types";
|
|
26
|
-
import { eRange, iRange } from "./utils";
|
|
26
|
+
import { assertDefined, eRange, iRange } from "./utils";
|
|
27
27
|
import { isVector, vectorEquals } from "./vector";
|
|
28
28
|
|
|
29
29
|
const BREAKABLE_GRID_ENTITY_TYPES_BY_EXPLOSIONS =
|
|
@@ -58,11 +58,11 @@ export function convertXMLGridEntityType(
|
|
|
58
58
|
gridEntityXMLVariant: int,
|
|
59
59
|
): [GridEntityType, int] | undefined {
|
|
60
60
|
const gridEntityArray = GRID_ENTITY_XML_MAP.get(gridEntityXMLType);
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
assertDefined(
|
|
62
|
+
gridEntityArray,
|
|
63
|
+
`Failed to find an entry in the grid entity map for XML entity type: ${gridEntityXMLType}`,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
66
|
const gridEntityType = gridEntityArray[0];
|
|
67
67
|
let variant = gridEntityArray[1];
|
|
68
68
|
|
|
@@ -165,18 +165,16 @@ export function getConstituentsFromGridEntityID(
|
|
|
165
165
|
const [gridEntityTypeString, variantString] = parts;
|
|
166
166
|
|
|
167
167
|
const gridEntityType = tonumber(gridEntityTypeString);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
168
|
+
assertDefined(
|
|
169
|
+
gridEntityType,
|
|
170
|
+
`Failed to convert the grid entity type to a number: ${gridEntityTypeString}`,
|
|
171
|
+
);
|
|
173
172
|
|
|
174
173
|
const variant = tonumber(variantString);
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
174
|
+
assertDefined(
|
|
175
|
+
variant,
|
|
176
|
+
`Failed to convert the grid entity variant to a number: ${variantString}`,
|
|
177
|
+
);
|
|
180
178
|
|
|
181
179
|
return [gridEntityType, variant];
|
|
182
180
|
}
|