isaacscript-common 10.0.0 → 10.1.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.d.ts +78 -22
- package/dist/isaacscript-common.lua +203 -102
- package/dist/package.lua +2 -2
- package/dist/src/features/deployJSONRoom.d.ts +16 -6
- package/dist/src/features/deployJSONRoom.d.ts.map +1 -1
- package/dist/src/features/deployJSONRoom.lua +16 -6
- package/dist/src/features/saveDataManager/load.d.ts.map +1 -1
- package/dist/src/features/saveDataManager/merge.d.ts.map +1 -1
- package/dist/src/features/saveDataManager/saveDataManagerConstants.d.ts +1 -1
- package/dist/src/features/saveDataManager/saveDataManagerConstants.d.ts.map +1 -1
- package/dist/src/functions/bitSet128.d.ts +2 -1
- package/dist/src/functions/bitSet128.d.ts.map +1 -1
- package/dist/src/functions/bitSet128.lua +2 -2
- package/dist/src/functions/color.d.ts +2 -3
- package/dist/src/functions/color.d.ts.map +1 -1
- package/dist/src/functions/color.lua +2 -2
- package/dist/src/functions/curses.d.ts +1 -1
- package/dist/src/functions/curses.lua +1 -1
- package/dist/src/functions/deepCopy.d.ts +2 -1
- package/dist/src/functions/deepCopy.d.ts.map +1 -1
- package/dist/src/functions/deepCopy.lua +19 -25
- package/dist/src/functions/deepCopyTests.lua +13 -26
- package/dist/src/functions/doors.d.ts +9 -1
- package/dist/src/functions/doors.d.ts.map +1 -1
- package/dist/src/functions/doors.lua +8 -1
- package/dist/src/functions/kColor.d.ts +2 -3
- package/dist/src/functions/kColor.d.ts.map +1 -1
- package/dist/src/functions/kColor.lua +2 -2
- package/dist/src/functions/rng.d.ts +2 -2
- package/dist/src/functions/rng.d.ts.map +1 -1
- package/dist/src/functions/serialization.d.ts +11 -4
- package/dist/src/functions/serialization.d.ts.map +1 -1
- package/dist/src/functions/serialization.lua +15 -0
- package/dist/src/functions/table.d.ts +2 -2
- package/dist/src/functions/table.d.ts.map +1 -1
- package/dist/src/functions/table.lua +6 -5
- package/dist/src/functions/vector.d.ts +2 -1
- package/dist/src/functions/vector.d.ts.map +1 -1
- package/dist/src/functions/vector.lua +2 -2
- package/dist/src/functions/weighted.d.ts +6 -0
- package/dist/src/functions/weighted.d.ts.map +1 -0
- package/dist/src/functions/weighted.lua +35 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.lua +8 -0
- package/dist/src/interfaces/SaveData.d.ts +3 -8
- package/dist/src/interfaces/SaveData.d.ts.map +1 -1
- package/dist/src/objects/isaacAPIClassTypeToBrand.d.ts +1 -1
- package/dist/src/objects/isaacAPIClassTypeToBrand.d.ts.map +1 -1
- package/dist/src/objects/isaacAPIClassTypeToBrand.lua +2 -2
- package/dist/src/objects/isaacAPIClassTypeToFunctions.d.ts +36 -8
- package/dist/src/objects/isaacAPIClassTypeToFunctions.d.ts.map +1 -1
- package/dist/src/objects/isaacAPIClassTypeToFunctions.lua +42 -7
- package/dist/src/types/WeightedArray.d.ts +4 -0
- package/dist/src/types/WeightedArray.d.ts.map +1 -0
- package/dist/src/types/{SerializedIsaacAPIClass.lua → WeightedArray.lua} +0 -0
- package/package.json +2 -2
- package/src/callbacks/customRevive.ts +1 -2
- package/src/features/deployJSONRoom.ts +16 -6
- package/src/features/saveDataManager/exports.ts +1 -1
- package/src/features/saveDataManager/load.ts +0 -2
- package/src/features/saveDataManager/merge.ts +0 -3
- package/src/features/saveDataManager/saveDataManagerConstants.ts +1 -1
- package/src/functions/bitSet128.ts +8 -2
- package/src/functions/color.ts +8 -2
- package/src/functions/curses.ts +1 -1
- package/src/functions/deepCopy.ts +25 -23
- package/src/functions/deepCopyTests.ts +19 -41
- package/src/functions/doors.ts +13 -1
- package/src/functions/initArray.ts +1 -1
- package/src/functions/kColor.ts +8 -2
- package/src/functions/rng.ts +2 -0
- package/src/functions/serialization.ts +72 -18
- package/src/functions/table.ts +8 -5
- package/src/functions/vector.ts +11 -3
- package/src/functions/weighted.ts +36 -0
- package/src/index.ts +2 -1
- package/src/interfaces/SaveData.ts +4 -3
- package/src/objects/isaacAPIClassTypeToBrand.ts +1 -1
- package/src/objects/isaacAPIClassTypeToFunctions.ts +58 -9
- package/src/types/WeightedArray.ts +2 -0
- package/dist/src/enums/private/CopyableIsaacAPIClassType.d.ts +0 -12
- package/dist/src/enums/private/CopyableIsaacAPIClassType.d.ts.map +0 -1
- package/dist/src/enums/private/CopyableIsaacAPIClassType.lua +0 -10
- package/dist/src/types/SerializedIsaacAPIClass.d.ts +0 -11
- package/dist/src/types/SerializedIsaacAPIClass.d.ts.map +0 -1
- package/src/enums/private/CopyableIsaacAPIClassType.ts +0 -11
- package/src/types/SerializedIsaacAPIClass.ts +0 -9
|
@@ -45,7 +45,6 @@ export function merge(
|
|
|
45
45
|
newTable: LuaMap<AnyNotNil, unknown>,
|
|
46
46
|
traversalDescription: string,
|
|
47
47
|
): void {
|
|
48
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
49
48
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
50
49
|
log(`merge is traversing: ${traversalDescription}`);
|
|
51
50
|
}
|
|
@@ -148,7 +147,6 @@ function mergeTable(
|
|
|
148
147
|
iterateTableInOrder(
|
|
149
148
|
newTable,
|
|
150
149
|
(key, value) => {
|
|
151
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
152
150
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
153
151
|
const valueToPrint = value === "" ? "(empty string)" : `${value}`;
|
|
154
152
|
log(`merge is merging: ${traversalDescription} --> ${valueToPrint}`);
|
|
@@ -160,7 +158,6 @@ function mergeTable(
|
|
|
160
158
|
|
|
161
159
|
// Handle the special case of serialized Isaac API classes.
|
|
162
160
|
if (isSerializedIsaacAPIClass(value)) {
|
|
163
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
164
161
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
165
162
|
log("merge found a serialized Isaac API class.");
|
|
166
163
|
}
|
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import { CopyableIsaacAPIClassType } from "isaac-typescript-definitions";
|
|
1
2
|
import { SerializationBrand } from "../enums/private/SerializationBrand";
|
|
2
3
|
import { isIsaacAPIClassOfType } from "./isaacAPIClass";
|
|
3
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
copyUserdataValuesToTable,
|
|
6
|
+
getNumbersFromTable,
|
|
7
|
+
tableHasKeys,
|
|
8
|
+
} from "./table";
|
|
4
9
|
import { isTable } from "./types";
|
|
5
10
|
|
|
6
11
|
export type SerializedBitSet128 = LuaMap<string, unknown> & {
|
|
7
12
|
readonly __serializedBitSet128Brand: symbol;
|
|
13
|
+
readonly __kind: CopyableIsaacAPIClassType.BIT_SET_128;
|
|
8
14
|
};
|
|
9
15
|
|
|
10
16
|
const OBJECT_NAME = "BitSet128";
|
|
@@ -86,7 +92,7 @@ export function serializeBitSet128(bitSet128: BitSet128): SerializedBitSet128 {
|
|
|
86
92
|
}
|
|
87
93
|
|
|
88
94
|
const bitSet128Table = new LuaMap<string, unknown>();
|
|
89
|
-
|
|
95
|
+
copyUserdataValuesToTable(bitSet128, KEYS, bitSet128Table);
|
|
90
96
|
bitSet128Table.set(SerializationBrand.BIT_SET_128, "");
|
|
91
97
|
return bitSet128Table as SerializedBitSet128;
|
|
92
98
|
}
|
package/src/functions/color.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
+
import { CopyableIsaacAPIClassType } from "isaac-typescript-definitions";
|
|
1
2
|
import { SerializationBrand } from "../enums/private/SerializationBrand";
|
|
2
3
|
import { isaacAPIClassEquals, isIsaacAPIClassOfType } from "./isaacAPIClass";
|
|
3
4
|
import { getRandom } from "./random";
|
|
4
5
|
import { getRandomSeed, isRNG, newRNG } from "./rng";
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
copyUserdataValuesToTable,
|
|
8
|
+
getNumbersFromTable,
|
|
9
|
+
tableHasKeys,
|
|
10
|
+
} from "./table";
|
|
6
11
|
import { isTable } from "./types";
|
|
7
12
|
|
|
8
13
|
export type SerializedColor = LuaMap<string, unknown> & {
|
|
9
14
|
readonly __serializedColorBrand: symbol;
|
|
15
|
+
readonly __kind: CopyableIsaacAPIClassType.COLOR;
|
|
10
16
|
};
|
|
11
17
|
|
|
12
18
|
const OBJECT_NAME = "Color";
|
|
@@ -120,7 +126,7 @@ export function serializeColor(color: Color): SerializedColor {
|
|
|
120
126
|
}
|
|
121
127
|
|
|
122
128
|
const colorTable = new LuaMap<string, unknown>();
|
|
123
|
-
|
|
129
|
+
copyUserdataValuesToTable(color, KEYS, colorTable);
|
|
124
130
|
colorTable.set(SerializationBrand.COLOR, "");
|
|
125
131
|
return colorTable as SerializedColor;
|
|
126
132
|
}
|
package/src/functions/curses.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { hasFlag } from "./flag";
|
|
|
5
5
|
/**
|
|
6
6
|
* Helper function to get the actual bit flag for modded curses.
|
|
7
7
|
*
|
|
8
|
-
* Will throw a
|
|
8
|
+
* Will throw a run-time error if the provided curse does not exist.
|
|
9
9
|
*
|
|
10
10
|
* Use this over the `Isaac.GetCurseIdByName` method because that will return an integer instead of
|
|
11
11
|
* a bit flag.
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { DefaultMap } from "../classes/DefaultMap";
|
|
2
|
-
import { CopyableIsaacAPIClassType } from "../enums/private/CopyableIsaacAPIClassType";
|
|
3
2
|
import { SerializationBrand } from "../enums/private/SerializationBrand";
|
|
4
3
|
import { SerializationType } from "../enums/SerializationType";
|
|
5
4
|
import { SAVE_DATA_MANAGER_DEBUG } from "../features/saveDataManager/saveDataManagerConstants";
|
|
6
5
|
import { isSerializationBrand } from "../features/saveDataManager/serializationBrands";
|
|
7
6
|
import { TSTLClass } from "../types/TSTLClass";
|
|
8
7
|
import { isArray } from "./array";
|
|
9
|
-
import { getEnumValues } from "./enums";
|
|
10
8
|
import { getIsaacAPIClassName } from "./isaacAPIClass";
|
|
11
9
|
import { log } from "./log";
|
|
12
10
|
import {
|
|
13
11
|
copyIsaacAPIClass,
|
|
14
12
|
deserializeIsaacAPIClass,
|
|
13
|
+
isCopyableIsaacAPIClass,
|
|
15
14
|
isSerializedIsaacAPIClass,
|
|
16
15
|
serializeIsaacAPIClass,
|
|
17
16
|
} from "./serialization";
|
|
@@ -26,10 +25,6 @@ import {
|
|
|
26
25
|
import { asString, isNumber, isPrimitive } from "./types";
|
|
27
26
|
import { getTraversalDescription, twoDimensionalSort } from "./utils";
|
|
28
27
|
|
|
29
|
-
const COPYABLE_ISAAC_API_CLASS_TYPES_SET = new Set<string>(
|
|
30
|
-
getEnumValues(CopyableIsaacAPIClassType),
|
|
31
|
-
);
|
|
32
|
-
|
|
33
28
|
/**
|
|
34
29
|
* `deepCopy` is a semi-generic deep cloner. It will recursively copy all of the values so that none
|
|
35
30
|
* of the nested references remain.
|
|
@@ -64,13 +59,24 @@ const COPYABLE_ISAAC_API_CLASS_TYPES_SET = new Set<string>(
|
|
|
64
59
|
* @param insideMap Optional. Tracks whether or not the deep copy function is in the process of
|
|
65
60
|
* recursively copying a TSTL Map. Default is false.
|
|
66
61
|
*/
|
|
62
|
+
export function deepCopy<T>(
|
|
63
|
+
value: T,
|
|
64
|
+
serializationType?: SerializationType.NONE,
|
|
65
|
+
traversalDescription?: string,
|
|
66
|
+
insideMap?: boolean,
|
|
67
|
+
): T;
|
|
68
|
+
export function deepCopy(
|
|
69
|
+
value: unknown,
|
|
70
|
+
serializationType: SerializationType,
|
|
71
|
+
traversalDescription?: string,
|
|
72
|
+
insideMap?: boolean,
|
|
73
|
+
): unknown; // The return types for serialization/deserialization are non-trivial, so we do not type them.
|
|
67
74
|
export function deepCopy(
|
|
68
75
|
value: unknown,
|
|
69
76
|
serializationType = SerializationType.NONE,
|
|
70
77
|
traversalDescription = "",
|
|
71
78
|
insideMap = false,
|
|
72
79
|
): unknown {
|
|
73
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
74
80
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
75
81
|
let logString = `deepCopy is operating on: ${traversalDescription}`;
|
|
76
82
|
if (serializationType === SerializationType.SERIALIZE) {
|
|
@@ -101,6 +107,12 @@ export function deepCopy(
|
|
|
101
107
|
);
|
|
102
108
|
}
|
|
103
109
|
|
|
110
|
+
if (serializationType === SerializationType.DESERIALIZE) {
|
|
111
|
+
error(
|
|
112
|
+
`The deep copy function does not support deserialization of "${traversalDescription}", since it is type: ${valueType}`,
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
104
116
|
// We cannot copy this, so simply return the reference.
|
|
105
117
|
return value;
|
|
106
118
|
}
|
|
@@ -126,7 +138,7 @@ function deepCopyTable(
|
|
|
126
138
|
serializationType: SerializationType,
|
|
127
139
|
traversalDescription: string,
|
|
128
140
|
insideMap: boolean,
|
|
129
|
-
) {
|
|
141
|
+
): unknown {
|
|
130
142
|
// First, handle the cases of TSTL classes or serialized TSTL classes.
|
|
131
143
|
if (isDefaultMap(luaMap) || luaMap.has(SerializationBrand.DEFAULT_MAP)) {
|
|
132
144
|
return deepCopyDefaultMap(
|
|
@@ -214,7 +226,6 @@ function deepCopyDefaultMap(
|
|
|
214
226
|
traversalDescription: string,
|
|
215
227
|
insideMap: boolean,
|
|
216
228
|
) {
|
|
217
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
218
229
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
219
230
|
log("deepCopy is copying a DefaultMap.");
|
|
220
231
|
}
|
|
@@ -346,7 +357,6 @@ function deepCopyMap(
|
|
|
346
357
|
traversalDescription: string,
|
|
347
358
|
insideMap: boolean,
|
|
348
359
|
) {
|
|
349
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
350
360
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
351
361
|
log("deepCopy is copying a Map.");
|
|
352
362
|
}
|
|
@@ -399,7 +409,6 @@ function deepCopySet(
|
|
|
399
409
|
traversalDescription: string,
|
|
400
410
|
insideMap: boolean,
|
|
401
411
|
) {
|
|
402
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
403
412
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
404
413
|
log("deepCopy is copying a Set.");
|
|
405
414
|
}
|
|
@@ -453,7 +462,6 @@ function deepCopyTSTLClass(
|
|
|
453
462
|
traversalDescription: string,
|
|
454
463
|
insideMap: boolean,
|
|
455
464
|
) {
|
|
456
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
457
465
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
458
466
|
log("deepCopy is copying a TSTL class.");
|
|
459
467
|
}
|
|
@@ -492,7 +500,6 @@ function deepCopyArray(
|
|
|
492
500
|
traversalDescription: string,
|
|
493
501
|
insideMap: boolean,
|
|
494
502
|
) {
|
|
495
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
496
503
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
497
504
|
log("deepCopy is copying an array.");
|
|
498
505
|
}
|
|
@@ -518,7 +525,6 @@ function deepCopyNormalLuaTable(
|
|
|
518
525
|
traversalDescription: string,
|
|
519
526
|
insideMap: boolean,
|
|
520
527
|
) {
|
|
521
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
522
528
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
523
529
|
log("deepCopy is copying a normal Lua table.");
|
|
524
530
|
}
|
|
@@ -568,7 +574,6 @@ function getCopiedEntries(
|
|
|
568
574
|
}
|
|
569
575
|
}
|
|
570
576
|
|
|
571
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
572
577
|
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
573
578
|
entries.sort(twoDimensionalSort);
|
|
574
579
|
}
|
|
@@ -651,11 +656,6 @@ function deepCopyUserdata(
|
|
|
651
656
|
serializationType: SerializationType,
|
|
652
657
|
traversalDescription: string,
|
|
653
658
|
) {
|
|
654
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
655
|
-
if (SAVE_DATA_MANAGER_DEBUG) {
|
|
656
|
-
log("deepCopy is copying userdata.");
|
|
657
|
-
}
|
|
658
|
-
|
|
659
659
|
const classType = getIsaacAPIClassName(value);
|
|
660
660
|
if (classType === undefined) {
|
|
661
661
|
error(
|
|
@@ -663,9 +663,9 @@ function deepCopyUserdata(
|
|
|
663
663
|
);
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
-
if (!
|
|
666
|
+
if (!isCopyableIsaacAPIClass(value)) {
|
|
667
667
|
error(
|
|
668
|
-
`The deep copy function does not support
|
|
668
|
+
`The deep copy function does not support serializing "${traversalDescription}", since it is an Isaac API class of type: ${classType}`,
|
|
669
669
|
);
|
|
670
670
|
}
|
|
671
671
|
|
|
@@ -679,7 +679,9 @@ function deepCopyUserdata(
|
|
|
679
679
|
}
|
|
680
680
|
|
|
681
681
|
case SerializationType.DESERIALIZE: {
|
|
682
|
-
|
|
682
|
+
error(
|
|
683
|
+
`The deep copy function can not deserialize "${traversalDescription}", since it is userdata.`,
|
|
684
|
+
);
|
|
683
685
|
}
|
|
684
686
|
}
|
|
685
687
|
}
|
|
@@ -49,7 +49,7 @@ function copiedObjectIsTable() {
|
|
|
49
49
|
abc: "def",
|
|
50
50
|
};
|
|
51
51
|
const newObject = deepCopy(
|
|
52
|
-
oldObject
|
|
52
|
+
oldObject,
|
|
53
53
|
SerializationType.NONE,
|
|
54
54
|
"copiedObjectIsTable",
|
|
55
55
|
);
|
|
@@ -64,12 +64,11 @@ function copiedObjectHasKeyAndValueString() {
|
|
|
64
64
|
const oldObject = {
|
|
65
65
|
abc: valueToLookFor,
|
|
66
66
|
};
|
|
67
|
-
const
|
|
68
|
-
oldObject
|
|
67
|
+
const newObject = deepCopy(
|
|
68
|
+
oldObject,
|
|
69
69
|
SerializationType.NONE,
|
|
70
70
|
"copiedObjectHasKeyAndValueString",
|
|
71
71
|
);
|
|
72
|
-
const newObject = newTable as typeof oldObject;
|
|
73
72
|
|
|
74
73
|
const value = newObject[keyToLookFor];
|
|
75
74
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -91,12 +90,11 @@ function copiedTableHasKeyAndValueNumber() {
|
|
|
91
90
|
const oldTable = new LuaMap<AnyNotNil, unknown>();
|
|
92
91
|
oldTable.set(keyToLookFor, valueToLookFor);
|
|
93
92
|
|
|
94
|
-
const
|
|
93
|
+
const newTable = deepCopy(
|
|
95
94
|
oldTable,
|
|
96
95
|
SerializationType.NONE,
|
|
97
96
|
"copiedTableHasKeyAndValueNumber",
|
|
98
97
|
);
|
|
99
|
-
const newTable = newObject as LuaMap<AnyNotNil, unknown>;
|
|
100
98
|
|
|
101
99
|
const value = newTable.get(keyToLookFor) as number | undefined;
|
|
102
100
|
if (value === undefined) {
|
|
@@ -117,12 +115,11 @@ function copiedTableDoesNotCoerceTypes() {
|
|
|
117
115
|
const oldTable = new LuaMap<AnyNotNil, unknown>();
|
|
118
116
|
oldTable.set(keyToLookFor, valueToLookFor);
|
|
119
117
|
|
|
120
|
-
const
|
|
118
|
+
const newTable = deepCopy(
|
|
121
119
|
oldTable,
|
|
122
120
|
SerializationType.NONE,
|
|
123
121
|
"copiedTableDoesNotCoerceTypes",
|
|
124
122
|
);
|
|
125
|
-
const newTable = newObject as LuaMap<AnyNotNil, unknown>;
|
|
126
123
|
|
|
127
124
|
const keyString = tostring(keyToLookFor);
|
|
128
125
|
const valueString = tostring(valueToLookFor);
|
|
@@ -148,12 +145,11 @@ function copiedObjectHasNoReferencesForPrimitivesForward() {
|
|
|
148
145
|
abc: originalStringValue,
|
|
149
146
|
def: originalNumberValue,
|
|
150
147
|
};
|
|
151
|
-
const
|
|
152
|
-
oldObject
|
|
148
|
+
const newObject = deepCopy(
|
|
149
|
+
oldObject,
|
|
153
150
|
SerializationType.NONE,
|
|
154
151
|
"copiedObjectHasNoReferencesForPrimitivesForward",
|
|
155
152
|
);
|
|
156
|
-
const newObject = newTable as typeof oldObject;
|
|
157
153
|
|
|
158
154
|
oldObject.abc = "newValue";
|
|
159
155
|
if (oldObject.abc === newObject.abc) {
|
|
@@ -173,12 +169,11 @@ function copiedObjectHasNoReferencesForPrimitivesBackward() {
|
|
|
173
169
|
abc: originalStringValue,
|
|
174
170
|
def: originalNumberValue,
|
|
175
171
|
};
|
|
176
|
-
const
|
|
177
|
-
oldObject
|
|
172
|
+
const newObject = deepCopy(
|
|
173
|
+
oldObject,
|
|
178
174
|
SerializationType.NONE,
|
|
179
175
|
"copiedObjectHasNoReferencesForPrimitivesBackward",
|
|
180
176
|
);
|
|
181
|
-
const newObject = newTable as typeof oldObject;
|
|
182
177
|
|
|
183
178
|
newObject.abc = "newValue";
|
|
184
179
|
if (newObject.abc === oldObject.abc) {
|
|
@@ -196,12 +191,11 @@ function copiedObjectHasNoReferencesForArray() {
|
|
|
196
191
|
const oldObject = {
|
|
197
192
|
abc: [1, 2, 3],
|
|
198
193
|
};
|
|
199
|
-
const
|
|
200
|
-
oldObject
|
|
194
|
+
const newObject = deepCopy(
|
|
195
|
+
oldObject,
|
|
201
196
|
SerializationType.NONE,
|
|
202
197
|
"copiedObjectHasNoReferencesForArray",
|
|
203
198
|
);
|
|
204
|
-
const newObject = newTable as typeof oldObject;
|
|
205
199
|
|
|
206
200
|
if (oldObject.abc === newObject.abc) {
|
|
207
201
|
error("The copied object has the same point to the child array.");
|
|
@@ -237,12 +231,11 @@ function copiedObjectHasChildObject() {
|
|
|
237
231
|
def: valueToLookFor,
|
|
238
232
|
},
|
|
239
233
|
};
|
|
240
|
-
const
|
|
241
|
-
oldObject
|
|
234
|
+
const newObject = deepCopy(
|
|
235
|
+
oldObject,
|
|
242
236
|
SerializationType.NONE,
|
|
243
237
|
"copiedObjectHasChildObject",
|
|
244
238
|
);
|
|
245
|
-
const newObject = newTable as typeof oldObject;
|
|
246
239
|
|
|
247
240
|
const childObject = newObject[childObjectIndex];
|
|
248
241
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -274,8 +267,7 @@ function copiedMapIsMap() {
|
|
|
274
267
|
const oldMap = new Map<string, string>();
|
|
275
268
|
oldMap.set(keyToLookFor, valueToLookFor);
|
|
276
269
|
|
|
277
|
-
const
|
|
278
|
-
const newMap = newObject as Map<string, string>;
|
|
270
|
+
const newMap = deepCopy(oldMap, SerializationType.NONE, "copiedMapIsMap");
|
|
279
271
|
|
|
280
272
|
if (!isTSTLMap(newMap)) {
|
|
281
273
|
error(`The copied Map was not a Map and has a type of: ${typeof newMap}`);
|
|
@@ -288,13 +280,7 @@ function copiedMapHasValue() {
|
|
|
288
280
|
const oldMap = new Map<string, string>();
|
|
289
281
|
oldMap.set(keyToLookFor, valueToLookFor);
|
|
290
282
|
|
|
291
|
-
const
|
|
292
|
-
oldMap,
|
|
293
|
-
SerializationType.NONE,
|
|
294
|
-
"copiedMapHasValue",
|
|
295
|
-
);
|
|
296
|
-
|
|
297
|
-
const newMap = newTable as typeof oldMap;
|
|
283
|
+
const newMap = deepCopy(oldMap, SerializationType.NONE, "copiedMapHasValue");
|
|
298
284
|
|
|
299
285
|
if (!isTSTLMap(newMap)) {
|
|
300
286
|
error(`The copied Map was not a Map and has a type of: ${typeof newMap}`);
|
|
@@ -314,8 +300,7 @@ function copiedSetIsSet() {
|
|
|
314
300
|
const oldSet = new Set<string>();
|
|
315
301
|
oldSet.add(valueToLookFor);
|
|
316
302
|
|
|
317
|
-
const
|
|
318
|
-
const newSet = newTable as Set<string>;
|
|
303
|
+
const newSet = deepCopy(oldSet, SerializationType.NONE, "copiedSetIsSet");
|
|
319
304
|
|
|
320
305
|
if (!isTSTLSet(newSet)) {
|
|
321
306
|
error(`The copied Set was not a Set and has a type of: ${typeof newSet}`);
|
|
@@ -327,12 +312,7 @@ function copiedSetHasValue() {
|
|
|
327
312
|
const oldSet = new Set<string>();
|
|
328
313
|
oldSet.add(valueToLookFor);
|
|
329
314
|
|
|
330
|
-
const
|
|
331
|
-
oldSet,
|
|
332
|
-
SerializationType.NONE,
|
|
333
|
-
"copiedSetHasValue",
|
|
334
|
-
);
|
|
335
|
-
const newSet = newTable as Set<string>;
|
|
315
|
+
const newSet = deepCopy(oldSet, SerializationType.NONE, "copiedSetHasValue");
|
|
336
316
|
|
|
337
317
|
if (!isTSTLSet(newSet)) {
|
|
338
318
|
error(`The copied Set was not a Set and has a type of: ${typeof newSet}`);
|
|
@@ -354,12 +334,11 @@ function copiedMapHasChildMap() {
|
|
|
354
334
|
const oldMap = new Map<string, Map<number, number>>();
|
|
355
335
|
oldMap.set(keyToLookFor, oldChildMap);
|
|
356
336
|
|
|
357
|
-
const
|
|
337
|
+
const newMap = deepCopy(
|
|
358
338
|
oldMap,
|
|
359
339
|
SerializationType.NONE,
|
|
360
340
|
"copiedMapHasChildMap",
|
|
361
341
|
);
|
|
362
|
-
const newMap = newTable as typeof oldMap;
|
|
363
342
|
|
|
364
343
|
if (!isTSTLMap(newMap)) {
|
|
365
344
|
error(`The copied Map was not a Map and had a type of: ${typeof newMap}`);
|
|
@@ -398,12 +377,11 @@ function copiedDefaultMapHasChildDefaultMap() {
|
|
|
398
377
|
oldChildMap.getAndSetDefault(childMapKey1);
|
|
399
378
|
oldChildMap.set(childMapKey2, childMapCustomValue);
|
|
400
379
|
|
|
401
|
-
const
|
|
380
|
+
const newParentMap = deepCopy(
|
|
402
381
|
oldParentMap,
|
|
403
382
|
SerializationType.NONE,
|
|
404
383
|
"copiedDefaultMapHasChildDefaultMap",
|
|
405
384
|
);
|
|
406
|
-
const newParentMap = newTable as typeof oldParentMap;
|
|
407
385
|
|
|
408
386
|
if (!isDefaultMap(newParentMap)) {
|
|
409
387
|
error(
|
package/src/functions/doors.ts
CHANGED
|
@@ -259,7 +259,10 @@ export function getRoomShapeDoorSlotCoordinates(
|
|
|
259
259
|
return coordinatesMap.get(doorSlot);
|
|
260
260
|
}
|
|
261
261
|
|
|
262
|
-
/**
|
|
262
|
+
/**
|
|
263
|
+
* Helper function to find unused door slots in the current room that can be used to make custom
|
|
264
|
+
* doors.
|
|
265
|
+
*/
|
|
263
266
|
export function getUnusedDoorSlots(): DoorSlot[] {
|
|
264
267
|
const room = game.GetRoom();
|
|
265
268
|
const doorSlots = getEnumValues(DoorSlot);
|
|
@@ -269,6 +272,15 @@ export function getUnusedDoorSlots(): DoorSlot[] {
|
|
|
269
272
|
);
|
|
270
273
|
}
|
|
271
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Helper function to check if the current room has one or more open door slots that can be used to
|
|
277
|
+
* make custom doors.
|
|
278
|
+
*/
|
|
279
|
+
export function hasUnusedDoorSlot(): boolean {
|
|
280
|
+
const unusedDoorSlots = getUnusedDoorSlots();
|
|
281
|
+
return unusedDoorSlots.length > 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
272
284
|
export function isAngelRoomDoor(door: GridEntityDoor): boolean {
|
|
273
285
|
return door.TargetRoomType === RoomType.ANGEL;
|
|
274
286
|
}
|
package/src/functions/kColor.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
|
+
import { CopyableIsaacAPIClassType } from "isaac-typescript-definitions";
|
|
1
2
|
import { SerializationBrand } from "../enums/private/SerializationBrand";
|
|
2
3
|
import { isaacAPIClassEquals, isIsaacAPIClassOfType } from "./isaacAPIClass";
|
|
3
4
|
import { getRandom } from "./random";
|
|
4
5
|
import { getRandomSeed, isRNG, newRNG } from "./rng";
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
copyUserdataValuesToTable,
|
|
8
|
+
getNumbersFromTable,
|
|
9
|
+
tableHasKeys,
|
|
10
|
+
} from "./table";
|
|
6
11
|
import { isTable } from "./types";
|
|
7
12
|
|
|
8
13
|
export type SerializedKColor = LuaMap<string, unknown> & {
|
|
9
14
|
readonly __serializedKColorBrand: symbol;
|
|
15
|
+
readonly __kind: CopyableIsaacAPIClassType.K_COLOR;
|
|
10
16
|
};
|
|
11
17
|
|
|
12
18
|
const OBJECT_NAME = "KColor";
|
|
@@ -117,7 +123,7 @@ export function serializeKColor(kColor: KColor): SerializedKColor {
|
|
|
117
123
|
}
|
|
118
124
|
|
|
119
125
|
const kColorTable = new LuaMap<string, unknown>();
|
|
120
|
-
|
|
126
|
+
copyUserdataValuesToTable(kColor, KEYS, kColorTable);
|
|
121
127
|
kColorTable.set(SerializationBrand.K_COLOR, "");
|
|
122
128
|
return kColorTable as SerializedKColor;
|
|
123
129
|
}
|
package/src/functions/rng.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CopyableIsaacAPIClassType } from "isaac-typescript-definitions";
|
|
1
2
|
import { game } from "../core/cachedClasses";
|
|
2
3
|
import { SerializationBrand } from "../enums/private/SerializationBrand";
|
|
3
4
|
import { isaacAPIClassEquals, isIsaacAPIClassOfType } from "./isaacAPIClass";
|
|
@@ -6,6 +7,7 @@ import { isTable } from "./types";
|
|
|
6
7
|
|
|
7
8
|
export type SerializedRNG = LuaMap<string, unknown> & {
|
|
8
9
|
readonly __serializedRNGBrand: symbol;
|
|
10
|
+
readonly __kind: CopyableIsaacAPIClassType.RNG;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
import { CopyableIsaacAPIClassType } from "
|
|
1
|
+
import { CopyableIsaacAPIClassType } from "isaac-typescript-definitions";
|
|
2
2
|
import { ISAAC_API_CLASS_TYPE_TO_BRAND } from "../objects/isaacAPIClassTypeToBrand";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
CopyableIsaacAPIClass,
|
|
5
|
+
IsaacAPIClassTypeFunctions,
|
|
6
|
+
IsaacAPIClassTypeToSerializedType,
|
|
7
|
+
IsaacAPIClassTypeToType,
|
|
8
|
+
ISAAC_API_CLASS_TYPE_TO_FUNCTIONS,
|
|
9
|
+
SerializedIsaacAPIClass,
|
|
10
|
+
} from "../objects/isaacAPIClassTypeToFunctions";
|
|
5
11
|
import { getIsaacAPIClassName } from "./isaacAPIClass";
|
|
6
12
|
import { isTable, isUserdata } from "./types";
|
|
7
13
|
|
|
@@ -11,7 +17,9 @@ import { isTable, isUserdata } from "./types";
|
|
|
11
17
|
*
|
|
12
18
|
* For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
|
|
13
19
|
*/
|
|
14
|
-
export function copyIsaacAPIClass
|
|
20
|
+
export function copyIsaacAPIClass<T extends CopyableIsaacAPIClass>(
|
|
21
|
+
isaacAPIClass: T,
|
|
22
|
+
): T {
|
|
15
23
|
if (!isUserdata(isaacAPIClass)) {
|
|
16
24
|
error(
|
|
17
25
|
`Failed to copy an Isaac API class since the provided object was of type: ${typeof isaacAPIClass}`,
|
|
@@ -27,9 +35,19 @@ export function copyIsaacAPIClass(isaacAPIClass: unknown): unknown {
|
|
|
27
35
|
|
|
28
36
|
const copyableIsaacAPIClassType =
|
|
29
37
|
isaacAPIClassType as CopyableIsaacAPIClassType;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
38
|
+
|
|
39
|
+
type ThisIsaacAPIClassType = T;
|
|
40
|
+
type ThisSerializedIsaacAPIClassType =
|
|
41
|
+
IsaacAPIClassTypeToSerializedType[T["__kind"]];
|
|
42
|
+
|
|
43
|
+
const functions = ISAAC_API_CLASS_TYPE_TO_FUNCTIONS[
|
|
44
|
+
copyableIsaacAPIClassType
|
|
45
|
+
] as unknown as
|
|
46
|
+
| IsaacAPIClassTypeFunctions<
|
|
47
|
+
ThisIsaacAPIClassType,
|
|
48
|
+
ThisSerializedIsaacAPIClassType
|
|
49
|
+
>
|
|
50
|
+
| undefined;
|
|
33
51
|
if (functions === undefined) {
|
|
34
52
|
error(
|
|
35
53
|
`Failed to copy an Isaac API class since the associated functions were not found for Isaac API class type: ${copyableIsaacAPIClassType}`,
|
|
@@ -46,9 +64,11 @@ export function copyIsaacAPIClass(isaacAPIClass: unknown): unknown {
|
|
|
46
64
|
*
|
|
47
65
|
* For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
|
|
48
66
|
*/
|
|
49
|
-
export function deserializeIsaacAPIClass
|
|
50
|
-
|
|
51
|
-
|
|
67
|
+
export function deserializeIsaacAPIClass<
|
|
68
|
+
SerializedT extends SerializedIsaacAPIClass,
|
|
69
|
+
>(
|
|
70
|
+
serializedIsaacAPIClass: SerializedT,
|
|
71
|
+
): IsaacAPIClassTypeToType[SerializedT["__kind"]] {
|
|
52
72
|
if (!isTable(serializedIsaacAPIClass)) {
|
|
53
73
|
error(
|
|
54
74
|
`Failed to deserialize an Isaac API class since the provided object was of type: ${typeof serializedIsaacAPIClass}`,
|
|
@@ -64,9 +84,17 @@ export function deserializeIsaacAPIClass(
|
|
|
64
84
|
);
|
|
65
85
|
}
|
|
66
86
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
87
|
+
type ThisIsaacAPIClassType = IsaacAPIClassTypeToType[SerializedT["__kind"]];
|
|
88
|
+
type ThisSerializedIsaacAPIClassType = SerializedT;
|
|
89
|
+
|
|
90
|
+
const functions = ISAAC_API_CLASS_TYPE_TO_FUNCTIONS[
|
|
91
|
+
copyableIsaacAPIClassType
|
|
92
|
+
] as unknown as
|
|
93
|
+
| IsaacAPIClassTypeFunctions<
|
|
94
|
+
ThisIsaacAPIClassType,
|
|
95
|
+
ThisSerializedIsaacAPIClassType
|
|
96
|
+
>
|
|
97
|
+
| undefined;
|
|
70
98
|
if (functions === undefined) {
|
|
71
99
|
error(
|
|
72
100
|
`Failed to deserialize an Isaac API class since the associated functions were not found for class type: ${copyableIsaacAPIClassType}`,
|
|
@@ -81,7 +109,7 @@ export function deserializeIsaacAPIClass(
|
|
|
81
109
|
* serialized table for brands.
|
|
82
110
|
*/
|
|
83
111
|
function getSerializedTableType(
|
|
84
|
-
serializedIsaacAPIClass:
|
|
112
|
+
serializedIsaacAPIClass: SerializedIsaacAPIClass,
|
|
85
113
|
): CopyableIsaacAPIClassType | undefined {
|
|
86
114
|
for (const [copyableIsaacAPIClassType, serializationBrand] of Object.entries(
|
|
87
115
|
ISAAC_API_CLASS_TYPE_TO_BRAND,
|
|
@@ -94,6 +122,20 @@ function getSerializedTableType(
|
|
|
94
122
|
return undefined;
|
|
95
123
|
}
|
|
96
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Helper function to generically check if a given object is a copyable Isaac API class. (This is
|
|
127
|
+
* used by the save data manager when determining what is safe to copy.)
|
|
128
|
+
*
|
|
129
|
+
* For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
|
|
130
|
+
*/
|
|
131
|
+
export function isCopyableIsaacAPIClass(
|
|
132
|
+
object: unknown,
|
|
133
|
+
): object is CopyableIsaacAPIClass {
|
|
134
|
+
const allFunctions = Object.values(ISAAC_API_CLASS_TYPE_TO_FUNCTIONS);
|
|
135
|
+
const isFunctions = allFunctions.map((functions) => functions.is);
|
|
136
|
+
return isFunctions.some((identityFunction) => identityFunction(object));
|
|
137
|
+
}
|
|
138
|
+
|
|
97
139
|
/**
|
|
98
140
|
* Helper function to generically check if a given Lua table is a serialized Isaac API class. (This
|
|
99
141
|
* is used by the save data manager when reading data from the "save#.dat" file.)
|
|
@@ -118,7 +160,9 @@ export function isSerializedIsaacAPIClass(
|
|
|
118
160
|
*
|
|
119
161
|
* For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
|
|
120
162
|
*/
|
|
121
|
-
export function serializeIsaacAPIClass
|
|
163
|
+
export function serializeIsaacAPIClass<T extends CopyableIsaacAPIClass>(
|
|
164
|
+
isaacAPIClass: T,
|
|
165
|
+
): IsaacAPIClassTypeToSerializedType[T["__kind"]] {
|
|
122
166
|
if (!isUserdata(isaacAPIClass)) {
|
|
123
167
|
error(
|
|
124
168
|
`Failed to serialize an Isaac API class since the provided object was of type: ${typeof isaacAPIClass}`,
|
|
@@ -134,9 +178,19 @@ export function serializeIsaacAPIClass(isaacAPIClass: unknown): unknown {
|
|
|
134
178
|
|
|
135
179
|
const copyableIsaacAPIClassType =
|
|
136
180
|
isaacAPIClassType as CopyableIsaacAPIClassType;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
181
|
+
|
|
182
|
+
type ThisIsaacAPIClassType = T;
|
|
183
|
+
type ThisSerializedIsaacAPIClassType =
|
|
184
|
+
IsaacAPIClassTypeToSerializedType[T["__kind"]];
|
|
185
|
+
|
|
186
|
+
const functions = ISAAC_API_CLASS_TYPE_TO_FUNCTIONS[
|
|
187
|
+
copyableIsaacAPIClassType
|
|
188
|
+
] as unknown as
|
|
189
|
+
| IsaacAPIClassTypeFunctions<
|
|
190
|
+
ThisIsaacAPIClassType,
|
|
191
|
+
ThisSerializedIsaacAPIClassType
|
|
192
|
+
>
|
|
193
|
+
| undefined;
|
|
140
194
|
if (functions === undefined) {
|
|
141
195
|
error(
|
|
142
196
|
`Failed to serialize an Isaac API class since the associated functions were not found for class type: ${copyableIsaacAPIClassType}`,
|