isaacscript-common 6.6.4 → 6.6.5

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.
@@ -39,7 +39,7 @@ export declare function initCustomDoor(mod: ModUpgraded, effectVariant: EffectVa
39
39
  * The custom door is an `EntityEffect`. You can manually open or close the door by modifying its
40
40
  * state. (The values to use correspond to the `DoorState` enum.)
41
41
  *
42
- * This function will throw a runtime error if:
42
+ * This function will throw a run-time error if:
43
43
  * - the door slot already has a vanilla door
44
44
  * - the door slot already has a custom door
45
45
  * - the tile at the door slot does not have a wall
@@ -199,7 +199,7 @@ end
199
199
  -- The custom door is an `EntityEffect`. You can manually open or close the door by modifying its
200
200
  -- state. (The values to use correspond to the `DoorState` enum.)
201
201
  --
202
- -- This function will throw a runtime error if:
202
+ -- This function will throw a run-time error if:
203
203
  -- - the door slot already has a vanilla door
204
204
  -- - the door slot already has a custom door
205
205
  -- - the tile at the door slot does not have a wall
@@ -16,10 +16,6 @@ export declare enum SerializationBrand {
16
16
  /**
17
17
  * This is set to the value that represents the default value (instead of an empty string like the
18
18
  * other brands are).
19
- *
20
- * Default maps that use a factory function are unserializable, but do not throw runtime errors
21
- * because the merge function can derive the factory function from the already-instantiated
22
- * object.
23
19
  */
24
20
  DEFAULT_MAP_VALUE = "__TSTL_DEFAULT_MAP_VALUE",
25
21
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"SerializationBrand.d.ts","sourceRoot":"","sources":["../../../src/enums/private/SerializationBrand.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,oBAAY,kBAAkB;IAE5B,WAAW,uBAAuB;IAClC,GAAG,eAAe;IAClB,GAAG,eAAe;IAGlB,KAAK,YAAY;IACjB,OAAO,cAAc;IACrB,GAAG,UAAU;IACb,MAAM,aAAa;IAEnB;;;;;;;OAOG;IACH,iBAAiB,6BAA6B;IAE9C;;;;;;;;;;OAUG;IACH,uBAAuB,mCAAmC;CAC3D"}
1
+ {"version":3,"file":"SerializationBrand.d.ts","sourceRoot":"","sources":["../../../src/enums/private/SerializationBrand.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,oBAAY,kBAAkB;IAE5B,WAAW,uBAAuB;IAClC,GAAG,eAAe;IAClB,GAAG,eAAe;IAGlB,KAAK,YAAY;IACjB,OAAO,cAAc;IACrB,GAAG,UAAU;IACb,MAAM,aAAa;IAEnB;;;OAGG;IACH,iBAAiB,6BAA6B;IAE9C;;;;;;;;;;OAUG;IACH,uBAAuB,mCAAmC;CAC3D"}
@@ -21,10 +21,13 @@ import { SerializationType } from "../enums/SerializationType";
21
21
  * - other Isaac API objects such as `EntityPtr` (that have a type of "userdata")
22
22
  *
23
23
  * @param value The primitive or object to copy.
24
- * @param serializationType Has 3 possible values. Can leave objects as-is, or can serialize objects
25
- * to Lua tables, or can deserialize Lua tables to objects. Default is
26
- * `SerializationType.NONE`.
27
- * @param traversalDescription Used to track the current key that we are operating on.
24
+ * @param serializationType Optional. Has 3 possible values. Can copy objects as-is, or can
25
+ * serialize objects to Lua tables, or can deserialize Lua tables to
26
+ * objects. Default is `SerializationType.NONE`.
27
+ * @param traversalDescription Optional. Used to track the current key that we are operating on.
28
+ * Default is an empty string.
29
+ * @param insideMap Optional. Tracks whether or not the deep copy function is in the process of
30
+ * recursively copying a TSTL Map. Default is false.
28
31
  */
29
- export declare function deepCopy(value: unknown, serializationType?: SerializationType, traversalDescription?: string): unknown;
32
+ export declare function deepCopy(value: unknown, serializationType?: SerializationType, traversalDescription?: string, insideMap?: boolean): unknown;
30
33
  //# sourceMappingURL=deepCopy.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deepCopy.d.ts","sourceRoot":"","sources":["../../src/functions/deepCopy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AA4B/D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,OAAO,EACd,iBAAiB,oBAAyB,EAC1C,oBAAoB,SAAK,GACxB,OAAO,CA6CT"}
1
+ {"version":3,"file":"deepCopy.d.ts","sourceRoot":"","sources":["../../src/functions/deepCopy.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AA4B/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,OAAO,EACd,iBAAiB,oBAAyB,EAC1C,oBAAoB,SAAK,EACzB,SAAS,UAAQ,GAChB,OAAO,CAkDT"}
@@ -66,17 +66,23 @@ local twoDimensionalSort = ____utils.twoDimensionalSort
66
66
  -- - other Isaac API objects such as `EntityPtr` (that have a type of "userdata")
67
67
  --
68
68
  -- @param value The primitive or object to copy.
69
- -- @param serializationType Has 3 possible values. Can leave objects as-is, or can serialize objects
70
- -- to Lua tables, or can deserialize Lua tables to objects. Default is
71
- -- `SerializationType.NONE`.
72
- -- @param traversalDescription Used to track the current key that we are operating on.
73
- function ____exports.deepCopy(self, value, serializationType, traversalDescription)
69
+ -- @param serializationType Optional. Has 3 possible values. Can copy objects as-is, or can
70
+ -- serialize objects to Lua tables, or can deserialize Lua tables to
71
+ -- objects. Default is `SerializationType.NONE`.
72
+ -- @param traversalDescription Optional. Used to track the current key that we are operating on.
73
+ -- Default is an empty string.
74
+ -- @param insideMap Optional. Tracks whether or not the deep copy function is in the process of
75
+ -- recursively copying a TSTL Map. Default is false.
76
+ function ____exports.deepCopy(self, value, serializationType, traversalDescription, insideMap)
74
77
  if serializationType == nil then
75
78
  serializationType = SerializationType.NONE
76
79
  end
77
80
  if traversalDescription == nil then
78
81
  traversalDescription = ""
79
82
  end
83
+ if insideMap == nil then
84
+ insideMap = false
85
+ end
80
86
  if SAVE_DATA_MANAGER_DEBUG then
81
87
  local logString = "deepCopy is operating on: " .. traversalDescription
82
88
  if serializationType == SerializationType.SERIALIZE then
@@ -109,7 +115,13 @@ function ____exports.deepCopy(self, value, serializationType, traversalDescripti
109
115
  if ____cond6 then
110
116
  do
111
117
  local luaTable = value
112
- return deepCopyTable(nil, luaTable, serializationType, traversalDescription)
118
+ return deepCopyTable(
119
+ nil,
120
+ luaTable,
121
+ serializationType,
122
+ traversalDescription,
123
+ insideMap
124
+ )
113
125
  end
114
126
  end
115
127
  ____cond6 = ____cond6 or ____switch6 == "userdata"
@@ -120,15 +132,33 @@ function ____exports.deepCopy(self, value, serializationType, traversalDescripti
120
132
  end
121
133
  until true
122
134
  end
123
- function deepCopyTable(self, luaTable, serializationType, traversalDescription)
135
+ function deepCopyTable(self, luaTable, serializationType, traversalDescription, insideMap)
124
136
  if isDefaultMap(nil, luaTable) or luaTable[SerializationBrand.DEFAULT_MAP] ~= nil then
125
- return deepCopyDefaultMap(nil, luaTable, serializationType, traversalDescription)
137
+ return deepCopyDefaultMap(
138
+ nil,
139
+ luaTable,
140
+ serializationType,
141
+ traversalDescription,
142
+ insideMap
143
+ )
126
144
  end
127
145
  if isTSTLMap(nil, luaTable) or luaTable[SerializationBrand.MAP] ~= nil then
128
- return deepCopyMap(nil, luaTable, serializationType, traversalDescription)
146
+ return deepCopyMap(
147
+ nil,
148
+ luaTable,
149
+ serializationType,
150
+ traversalDescription,
151
+ insideMap
152
+ )
129
153
  end
130
154
  if isTSTLSet(nil, luaTable) or luaTable[SerializationBrand.SET] ~= nil then
131
- return deepCopySet(nil, luaTable, serializationType, traversalDescription)
155
+ return deepCopySet(
156
+ nil,
157
+ luaTable,
158
+ serializationType,
159
+ traversalDescription,
160
+ insideMap
161
+ )
132
162
  end
133
163
  local className = getTSTLClassName(nil, luaTable)
134
164
  if className == "WeakMap" then
@@ -138,18 +168,36 @@ function deepCopyTable(self, luaTable, serializationType, traversalDescription)
138
168
  error("The deep copy function does not support copying the \"WeakSet\" class for: " .. traversalDescription)
139
169
  end
140
170
  if isUserDefinedTSTLClass(nil, luaTable) then
141
- return deepCopyTSTLClass(nil, luaTable, serializationType, traversalDescription)
171
+ return deepCopyTSTLClass(
172
+ nil,
173
+ luaTable,
174
+ serializationType,
175
+ traversalDescription,
176
+ insideMap
177
+ )
142
178
  end
143
179
  checkMetatable(nil, luaTable, traversalDescription)
144
180
  if isSerializedIsaacAPIClass(nil, luaTable) and serializationType == SerializationType.DESERIALIZE then
145
181
  return deserializeIsaacAPIClass(nil, luaTable)
146
182
  end
147
183
  if isArray(nil, luaTable) then
148
- return deepCopyArray(nil, luaTable, serializationType, traversalDescription)
149
- end
150
- return deepCopyNormalLuaTable(nil, luaTable, serializationType, traversalDescription)
184
+ return deepCopyArray(
185
+ nil,
186
+ luaTable,
187
+ serializationType,
188
+ traversalDescription,
189
+ insideMap
190
+ )
191
+ end
192
+ return deepCopyNormalLuaTable(
193
+ nil,
194
+ luaTable,
195
+ serializationType,
196
+ traversalDescription,
197
+ insideMap
198
+ )
151
199
  end
152
- function deepCopyDefaultMap(self, defaultMap, serializationType, traversalDescription)
200
+ function deepCopyDefaultMap(self, defaultMap, serializationType, traversalDescription, insideMap)
153
201
  local ____isDefaultMap_result_0
154
202
  if isDefaultMap(nil, defaultMap) then
155
203
  ____isDefaultMap_result_0 = defaultMap:getConstructorArg()
@@ -158,7 +206,17 @@ function deepCopyDefaultMap(self, defaultMap, serializationType, traversalDescri
158
206
  end
159
207
  local constructorArg = ____isDefaultMap_result_0
160
208
  if serializationType == SerializationType.SERIALIZE and not isPrimitive(nil, constructorArg) then
161
- return deepCopyMap(nil, defaultMap, serializationType, traversalDescription)
209
+ if insideMap then
210
+ error("Failed to deep copy a DefaultMap because it was instantiated with a factory function and was also inside of another map. You cannot use a nested DefaultMap in this way because factory functions are not serializable. (In other words, there is no way to copy the function that you are using for the DefaultMap into the \"save#.dat\" file.) Instead, refactor your data structure so that the DefaultMap is not nested.")
211
+ else
212
+ return deepCopyMap(
213
+ nil,
214
+ defaultMap,
215
+ serializationType,
216
+ traversalDescription,
217
+ insideMap
218
+ )
219
+ end
162
220
  end
163
221
  local newDefaultMap = getNewDefaultMap(
164
222
  nil,
@@ -167,7 +225,14 @@ function deepCopyDefaultMap(self, defaultMap, serializationType, traversalDescri
167
225
  traversalDescription,
168
226
  constructorArg
169
227
  )
170
- local ____getCopiedEntries_result_1 = getCopiedEntries(nil, defaultMap, serializationType, traversalDescription)
228
+ insideMap = true
229
+ local ____getCopiedEntries_result_1 = getCopiedEntries(
230
+ nil,
231
+ defaultMap,
232
+ serializationType,
233
+ traversalDescription,
234
+ insideMap
235
+ )
171
236
  local entries = ____getCopiedEntries_result_1.entries
172
237
  local convertedNumberKeysToStrings = ____getCopiedEntries_result_1.convertedNumberKeysToStrings
173
238
  if convertedNumberKeysToStrings then
@@ -186,19 +251,20 @@ function deepCopyDefaultMap(self, defaultMap, serializationType, traversalDescri
186
251
  newDefaultMap[key] = value
187
252
  end
188
253
  end
254
+ insideMap = false
189
255
  return newDefaultMap
190
256
  end
191
257
  function getNewDefaultMap(self, defaultMap, serializationType, traversalDescription, constructorArg)
192
258
  repeat
193
- local ____switch31 = serializationType
194
- local ____cond31 = ____switch31 == SerializationType.NONE
195
- if ____cond31 then
259
+ local ____switch33 = serializationType
260
+ local ____cond33 = ____switch33 == SerializationType.NONE
261
+ if ____cond33 then
196
262
  do
197
263
  return __TS__New(DefaultMap, constructorArg)
198
264
  end
199
265
  end
200
- ____cond31 = ____cond31 or ____switch31 == SerializationType.SERIALIZE
201
- if ____cond31 then
266
+ ____cond33 = ____cond33 or ____switch33 == SerializationType.SERIALIZE
267
+ if ____cond33 then
202
268
  do
203
269
  local newDefaultMap = {}
204
270
  newDefaultMap[SerializationBrand.DEFAULT_MAP] = ""
@@ -206,8 +272,8 @@ function getNewDefaultMap(self, defaultMap, serializationType, traversalDescript
206
272
  return newDefaultMap
207
273
  end
208
274
  end
209
- ____cond31 = ____cond31 or ____switch31 == SerializationType.DESERIALIZE
210
- if ____cond31 then
275
+ ____cond33 = ____cond33 or ____switch33 == SerializationType.DESERIALIZE
276
+ if ____cond33 then
211
277
  do
212
278
  if isDefaultMap(nil, defaultMap) then
213
279
  error(("The deep copy function failed to deserialize a default map of \"" .. traversalDescription) .. "\", since it was not a Lua table.")
@@ -221,7 +287,7 @@ function getNewDefaultMap(self, defaultMap, serializationType, traversalDescript
221
287
  end
222
288
  until true
223
289
  end
224
- function deepCopyMap(self, map, serializationType, traversalDescription)
290
+ function deepCopyMap(self, map, serializationType, traversalDescription, insideMap)
225
291
  local newMap
226
292
  if serializationType == SerializationType.SERIALIZE then
227
293
  newMap = {}
@@ -229,7 +295,14 @@ function deepCopyMap(self, map, serializationType, traversalDescription)
229
295
  else
230
296
  newMap = __TS__New(Map)
231
297
  end
232
- local ____getCopiedEntries_result_2 = getCopiedEntries(nil, map, serializationType, traversalDescription)
298
+ insideMap = true
299
+ local ____getCopiedEntries_result_2 = getCopiedEntries(
300
+ nil,
301
+ map,
302
+ serializationType,
303
+ traversalDescription,
304
+ insideMap
305
+ )
233
306
  local entries = ____getCopiedEntries_result_2.entries
234
307
  local convertedNumberKeysToStrings = ____getCopiedEntries_result_2.convertedNumberKeysToStrings
235
308
  if convertedNumberKeysToStrings then
@@ -248,9 +321,10 @@ function deepCopyMap(self, map, serializationType, traversalDescription)
248
321
  newMap[key] = value
249
322
  end
250
323
  end
324
+ insideMap = false
251
325
  return newMap
252
326
  end
253
- function deepCopySet(self, set, serializationType, traversalDescription)
327
+ function deepCopySet(self, set, serializationType, traversalDescription, insideMap)
254
328
  local newSet
255
329
  if serializationType == SerializationType.SERIALIZE then
256
330
  newSet = {}
@@ -258,7 +332,13 @@ function deepCopySet(self, set, serializationType, traversalDescription)
258
332
  else
259
333
  newSet = __TS__New(Set)
260
334
  end
261
- local ____getCopiedEntries_result_3 = getCopiedEntries(nil, set, serializationType, traversalDescription)
335
+ local ____getCopiedEntries_result_3 = getCopiedEntries(
336
+ nil,
337
+ set,
338
+ serializationType,
339
+ traversalDescription,
340
+ insideMap
341
+ )
262
342
  local entries = ____getCopiedEntries_result_3.entries
263
343
  local convertedNumberKeysToStrings = ____getCopiedEntries_result_3.convertedNumberKeysToStrings
264
344
  if convertedNumberKeysToStrings then
@@ -278,14 +358,20 @@ function deepCopySet(self, set, serializationType, traversalDescription)
278
358
  end
279
359
  return newSet
280
360
  end
281
- function deepCopyTSTLClass(self, tstlClass, serializationType, traversalDescription)
361
+ function deepCopyTSTLClass(self, tstlClass, serializationType, traversalDescription, insideMap)
282
362
  local newClass
283
363
  if serializationType == SerializationType.SERIALIZE then
284
364
  newClass = {}
285
365
  else
286
366
  newClass = newTSTLClass(nil, tstlClass)
287
367
  end
288
- local ____getCopiedEntries_result_4 = getCopiedEntries(nil, tstlClass, serializationType, traversalDescription)
368
+ local ____getCopiedEntries_result_4 = getCopiedEntries(
369
+ nil,
370
+ tstlClass,
371
+ serializationType,
372
+ traversalDescription,
373
+ insideMap
374
+ )
289
375
  local entries = ____getCopiedEntries_result_4.entries
290
376
  local convertedNumberKeysToStrings = ____getCopiedEntries_result_4.convertedNumberKeysToStrings
291
377
  if convertedNumberKeysToStrings then
@@ -298,17 +384,29 @@ function deepCopyTSTLClass(self, tstlClass, serializationType, traversalDescript
298
384
  end
299
385
  return newClass
300
386
  end
301
- function deepCopyArray(self, array, serializationType, traversalDescription)
387
+ function deepCopyArray(self, array, serializationType, traversalDescription, insideMap)
302
388
  local newArray = {}
303
389
  for ____, value in ipairs(array) do
304
- local newValue = ____exports.deepCopy(nil, value, serializationType, traversalDescription)
390
+ local newValue = ____exports.deepCopy(
391
+ nil,
392
+ value,
393
+ serializationType,
394
+ traversalDescription,
395
+ insideMap
396
+ )
305
397
  newArray[#newArray + 1] = newValue
306
398
  end
307
399
  return newArray
308
400
  end
309
- function deepCopyNormalLuaTable(self, luaTable, serializationType, traversalDescription)
401
+ function deepCopyNormalLuaTable(self, luaTable, serializationType, traversalDescription, insideMap)
310
402
  local newTable = {}
311
- local ____getCopiedEntries_result_5 = getCopiedEntries(nil, luaTable, serializationType, traversalDescription)
403
+ local ____getCopiedEntries_result_5 = getCopiedEntries(
404
+ nil,
405
+ luaTable,
406
+ serializationType,
407
+ traversalDescription,
408
+ insideMap
409
+ )
312
410
  local entries = ____getCopiedEntries_result_5.entries
313
411
  local convertedNumberKeysToStrings = ____getCopiedEntries_result_5.convertedNumberKeysToStrings
314
412
  if convertedNumberKeysToStrings then
@@ -321,7 +419,7 @@ function deepCopyNormalLuaTable(self, luaTable, serializationType, traversalDesc
321
419
  end
322
420
  return newTable
323
421
  end
324
- function getCopiedEntries(self, object, serializationType, traversalDescription)
422
+ function getCopiedEntries(self, object, serializationType, traversalDescription, insideMap)
325
423
  local entries = {}
326
424
  if isTSTLMap(nil, object) or isTSTLSet(nil, object) or isDefaultMap(nil, object) then
327
425
  for ____, ____value in __TS__Iterator(object:entries()) do
@@ -353,14 +451,20 @@ function getCopiedEntries(self, object, serializationType, traversalDescription)
353
451
  local value = ____value[2]
354
452
  do
355
453
  if isSerializationBrand(nil, key) then
356
- goto __continue78
454
+ goto __continue80
357
455
  end
358
456
  traversalDescription = getTraversalDescription(nil, key, traversalDescription)
359
- local newValue = ____exports.deepCopy(nil, value, serializationType, traversalDescription)
457
+ local newValue = ____exports.deepCopy(
458
+ nil,
459
+ value,
460
+ serializationType,
461
+ traversalDescription,
462
+ insideMap
463
+ )
360
464
  local keyToUse = convertNumberKeysToStrings and tostring(key) or key
361
465
  copiedEntries[#copiedEntries + 1] = {keyToUse, newValue}
362
466
  end
363
- ::__continue78::
467
+ ::__continue80::
364
468
  end
365
469
  return {entries = copiedEntries, convertedNumberKeysToStrings = convertNumberKeysToStrings}
366
470
  end
@@ -64,7 +64,7 @@ export declare function logSounds(this: void): void;
64
64
  * recursively call itself if it counters a table within a table.
65
65
  *
66
66
  * This function will only work on tables that have string keys (because it logs the keys in order,
67
- * instead of randomly). It will throw a runtime error if it encounters a non-string key.
67
+ * instead of randomly). It will throw a run-time error if it encounters a non-string key.
68
68
  */
69
69
  export declare function logTable(this: void, luaTable: unknown, parentTables?: number): void;
70
70
  /**
@@ -464,7 +464,7 @@ end
464
464
  -- recursively call itself if it counters a table within a table.
465
465
  --
466
466
  -- This function will only work on tables that have string keys (because it logs the keys in order,
467
- -- instead of randomly). It will throw a runtime error if it encounters a non-string key.
467
+ -- instead of randomly). It will throw a run-time error if it encounters a non-string key.
468
468
  function ____exports.logTable(luaTable, parentTables)
469
469
  if parentTables == nil then
470
470
  parentTables = 0
@@ -34,7 +34,7 @@ export declare function getStringsFromTable(luaTable: LuaTable<string, unknown>,
34
34
  * This function will sort the table entries based on the value of the key.
35
35
  *
36
36
  * This function will only work on tables that have number keys or string keys. It will throw a
37
- * runtime error if it encounters a key of another type.
37
+ * run-time error if it encounters a key of another type.
38
38
  *
39
39
  * @param luaTable The table to iterate over.
40
40
  * @param func The function to run for each iteration.
@@ -96,7 +96,7 @@ end
96
96
  -- This function will sort the table entries based on the value of the key.
97
97
  --
98
98
  -- This function will only work on tables that have number keys or string keys. It will throw a
99
- -- runtime error if it encounters a key of another type.
99
+ -- run-time error if it encounters a key of another type.
100
100
  --
101
101
  -- @param luaTable The table to iterate over.
102
102
  -- @param func The function to run for each iteration.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isaacscript-common",
3
- "version": "6.6.4",
3
+ "version": "6.6.5",
4
4
  "description": "Helper functions and features for IsaacScript mods.",
5
5
  "keywords": [
6
6
  "isaac",
@@ -119,7 +119,7 @@ function incrementNumSacrifices(damageFlags: BitFlags<DamageFlag>) {
119
119
  const isSpikeDamage = hasFlag(damageFlags, DamageFlag.SPIKES);
120
120
 
121
121
  if (roomType === RoomType.SACRIFICE && isSpikeDamage) {
122
- v.level.numSacrifices += 1;
122
+ v.level.numSacrifices++;
123
123
  }
124
124
  }
125
125
 
@@ -219,7 +219,7 @@ function postRoomClearChanged(
219
219
  * The custom door is an `EntityEffect`. You can manually open or close the door by modifying its
220
220
  * state. (The values to use correspond to the `DoorState` enum.)
221
221
  *
222
- * This function will throw a runtime error if:
222
+ * This function will throw a run-time error if:
223
223
  * - the door slot already has a vanilla door
224
224
  * - the door slot already has a custom door
225
225
  * - the tile at the door slot does not have a wall
@@ -102,7 +102,7 @@ function collectibleCountChanged(
102
102
  } else {
103
103
  postPlayerCollectibleRemovedFire(player, collectibleType);
104
104
  }
105
- numFired += 1;
105
+ numFired++;
106
106
  });
107
107
 
108
108
  if (numFired === numCollectiblesChanged) {
@@ -56,7 +56,7 @@ function entityTakeDmgPlayer(
56
56
  const isSpikeDamage = hasFlag(damageFlags, DamageFlag.SPIKES);
57
57
 
58
58
  if (roomType === RoomType.SACRIFICE && isSpikeDamage) {
59
- v.level.numSacrifices += 1;
59
+ v.level.numSacrifices++;
60
60
  postSacrificeFire(player, v.level.numSacrifices);
61
61
  }
62
62
 
@@ -20,10 +20,6 @@ export enum SerializationBrand {
20
20
  /**
21
21
  * This is set to the value that represents the default value (instead of an empty string like the
22
22
  * other brands are).
23
- *
24
- * Default maps that use a factory function are unserializable, but do not throw runtime errors
25
- * because the merge function can derive the factory function from the already-instantiated
26
- * object.
27
23
  */
28
24
  DEFAULT_MAP_VALUE = "__TSTL_DEFAULT_MAP_VALUE",
29
25
 
@@ -337,7 +337,7 @@ export function cards(): void {
337
337
 
338
338
  const position = gridCoordinatesToWorldPosition(x, y);
339
339
  spawnCard(cardType as Card, position);
340
- cardType += 1;
340
+ cardType++;
341
341
  }
342
342
  }
343
343
  }
@@ -647,7 +647,7 @@ export function gridEntities(): void {
647
647
  let gridEntityTypeIndex = -1;
648
648
  for (let y = 0; y <= 6; y++) {
649
649
  for (let x = 0; x <= 12; x++) {
650
- gridEntityTypeIndex += 1;
650
+ gridEntityTypeIndex++;
651
651
  const gridEntityType = gridEntityTypes[gridEntityTypeIndex];
652
652
  if (gridEntityType === undefined) {
653
653
  return;
@@ -884,7 +884,7 @@ export function pills(): void {
884
884
  let pillColorIndex = -1;
885
885
  for (let y = 0; y <= 6; y++) {
886
886
  for (let x = 0; x <= 12; x++) {
887
- pillColorIndex += 1;
887
+ pillColorIndex++;
888
888
  const pillColor = pillColors[pillColorIndex];
889
889
  if (pillColor === undefined) {
890
890
  return;
@@ -123,7 +123,7 @@ export function spawnPersistentEntity(
123
123
  ): [Entity, int] {
124
124
  errorIfFeaturesNotInitialized(FEATURE_NAME);
125
125
 
126
- persistentEntityIndexCounter += 1;
126
+ persistentEntityIndexCounter++;
127
127
 
128
128
  const entity = spawnAndTrack(
129
129
  entityType,
@@ -527,7 +527,7 @@ export function shuffleArrayInPlace<T>(
527
527
  const rng = isRNG(seedOrRNG) ? seedOrRNG : newRNG(seedOrRNG);
528
528
 
529
529
  while (currentIndex > 0) {
530
- currentIndex -= 1;
530
+ currentIndex--;
531
531
 
532
532
  const randomIndex = getRandomArrayIndex(array, rng);
533
533
  swapArrayElements(array, currentIndex, randomIndex);
@@ -57,7 +57,7 @@ export function countSetBits(n: int): int {
57
57
 
58
58
  while (n > 0) {
59
59
  n &= n - 1;
60
- count += 1;
60
+ count++;
61
61
  }
62
62
 
63
63
  return count;
@@ -72,7 +72,7 @@ export function getKBitOfN(k: int, n: int): int {
72
72
  export function getNumBitsOfN(n: int): int {
73
73
  let numBits = 0;
74
74
  while (n > 0) {
75
- numBits += 1;
75
+ numBits++;
76
76
  n >>>= 1;
77
77
  }
78
78
 
@@ -51,15 +51,19 @@ const COPYABLE_ISAAC_API_CLASS_TYPES_SET = new Set<string>(
51
51
  * - other Isaac API objects such as `EntityPtr` (that have a type of "userdata")
52
52
  *
53
53
  * @param value The primitive or object to copy.
54
- * @param serializationType Has 3 possible values. Can leave objects as-is, or can serialize objects
55
- * to Lua tables, or can deserialize Lua tables to objects. Default is
56
- * `SerializationType.NONE`.
57
- * @param traversalDescription Used to track the current key that we are operating on.
54
+ * @param serializationType Optional. Has 3 possible values. Can copy objects as-is, or can
55
+ * serialize objects to Lua tables, or can deserialize Lua tables to
56
+ * objects. Default is `SerializationType.NONE`.
57
+ * @param traversalDescription Optional. Used to track the current key that we are operating on.
58
+ * Default is an empty string.
59
+ * @param insideMap Optional. Tracks whether or not the deep copy function is in the process of
60
+ * recursively copying a TSTL Map. Default is false.
58
61
  */
59
62
  export function deepCopy(
60
63
  value: unknown,
61
64
  serializationType = SerializationType.NONE,
62
65
  traversalDescription = "",
66
+ insideMap = false,
63
67
  ): unknown {
64
68
  // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
65
69
  if (SAVE_DATA_MANAGER_DEBUG) {
@@ -98,7 +102,12 @@ export function deepCopy(
98
102
 
99
103
  case "table": {
100
104
  const luaTable = value as LuaTable<AnyNotNil, unknown>;
101
- return deepCopyTable(luaTable, serializationType, traversalDescription);
105
+ return deepCopyTable(
106
+ luaTable,
107
+ serializationType,
108
+ traversalDescription,
109
+ insideMap,
110
+ );
102
111
  }
103
112
 
104
113
  case "userdata": {
@@ -111,6 +120,7 @@ function deepCopyTable(
111
120
  luaTable: LuaTable<AnyNotNil, unknown>,
112
121
  serializationType: SerializationType,
113
122
  traversalDescription: string,
123
+ insideMap: boolean,
114
124
  ) {
115
125
  // First, handle the cases of TSTL classes or serialized TSTL classes.
116
126
  if (isDefaultMap(luaTable) || luaTable.has(SerializationBrand.DEFAULT_MAP)) {
@@ -118,15 +128,26 @@ function deepCopyTable(
118
128
  luaTable,
119
129
  serializationType,
120
130
  traversalDescription,
131
+ insideMap,
121
132
  );
122
133
  }
123
134
 
124
135
  if (isTSTLMap(luaTable) || luaTable.has(SerializationBrand.MAP)) {
125
- return deepCopyMap(luaTable, serializationType, traversalDescription);
136
+ return deepCopyMap(
137
+ luaTable,
138
+ serializationType,
139
+ traversalDescription,
140
+ insideMap,
141
+ );
126
142
  }
127
143
 
128
144
  if (isTSTLSet(luaTable) || luaTable.has(SerializationBrand.SET)) {
129
- return deepCopySet(luaTable, serializationType, traversalDescription);
145
+ return deepCopySet(
146
+ luaTable,
147
+ serializationType,
148
+ traversalDescription,
149
+ insideMap,
150
+ );
130
151
  }
131
152
 
132
153
  const className = getTSTLClassName(luaTable);
@@ -144,7 +165,12 @@ function deepCopyTable(
144
165
  }
145
166
 
146
167
  if (isUserDefinedTSTLClass(luaTable)) {
147
- return deepCopyTSTLClass(luaTable, serializationType, traversalDescription);
168
+ return deepCopyTSTLClass(
169
+ luaTable,
170
+ serializationType,
171
+ traversalDescription,
172
+ insideMap,
173
+ );
148
174
  }
149
175
 
150
176
  // This is not a TSTL Map/Set/class. If it has a metatable, abort.
@@ -160,7 +186,12 @@ function deepCopyTable(
160
186
 
161
187
  // Handle the special case of an array.
162
188
  if (isArray(luaTable)) {
163
- return deepCopyArray(luaTable, serializationType, traversalDescription);
189
+ return deepCopyArray(
190
+ luaTable,
191
+ serializationType,
192
+ traversalDescription,
193
+ insideMap,
194
+ );
164
195
  }
165
196
 
166
197
  // Base case: copy a normal Lua table
@@ -168,6 +199,7 @@ function deepCopyTable(
168
199
  luaTable,
169
200
  serializationType,
170
201
  traversalDescription,
202
+ insideMap,
171
203
  );
172
204
  }
173
205
 
@@ -175,19 +207,39 @@ function deepCopyDefaultMap(
175
207
  defaultMap: DefaultMap<AnyNotNil, unknown> | LuaTable<AnyNotNil, unknown>,
176
208
  serializationType: SerializationType,
177
209
  traversalDescription: string,
210
+ insideMap: boolean,
178
211
  ) {
179
- // First, handle the special case of serializing a DefaultMap instantiated with a factory
180
- // function. If this is the case, then we cannot serialize it, so we serialize it as a normal
181
- // `Map` instead. We do not throw a runtime error because the merge function does not need to
182
- // instantiate the DefaultMap class in most circumstances.
183
212
  const constructorArg = isDefaultMap(defaultMap)
184
213
  ? defaultMap.getConstructorArg()
185
- : undefined;
214
+ : undefined; // The undefined case is handled explicitly in the "getNewDefaultMap" function.
215
+
216
+ // First, handle the special case of serializing a DefaultMap instantiated with a factory
217
+ // function. If this is the case, then we cannot serialize it (because there is no way to
218
+ // serialize a function).
186
219
  if (
187
220
  serializationType === SerializationType.SERIALIZE &&
188
221
  !isPrimitive(constructorArg)
189
222
  ) {
190
- return deepCopyMap(defaultMap, serializationType, traversalDescription);
223
+ if (insideMap) {
224
+ // The case of a DefaultMap within another map is complicated. Unlike a DefaultMap attached to
225
+ // a "normal" object, the `merge` function will have no reference to the factory function that
226
+ // was used to instantiate it. Thus, there is no way to copy this object. In this case, we
227
+ // throw a run-time error to immediately alert the end-user that their data structure is
228
+ // invalid.
229
+ error(
230
+ 'Failed to deep copy a DefaultMap because it was instantiated with a factory function and was also inside of another map. You cannot use a nested DefaultMap in this way because factory functions are not serializable. (In other words, there is no way to copy the function that you are using for the DefaultMap into the "save#.dat" file.) Instead, refactor your data structure so that the DefaultMap is not nested.',
231
+ );
232
+ } else {
233
+ // In most cases, the DefaultMap will be attached to a normal table element. In this case, if
234
+ // we serialize it as a normal `Map`, then everything will work out fine, because the `merge`
235
+ // function only needs to copy the values (and not instantiate the object itself).
236
+ return deepCopyMap(
237
+ defaultMap,
238
+ serializationType,
239
+ traversalDescription,
240
+ insideMap,
241
+ );
242
+ }
191
243
  }
192
244
 
193
245
  const newDefaultMap = getNewDefaultMap(
@@ -196,11 +248,13 @@ function deepCopyDefaultMap(
196
248
  traversalDescription,
197
249
  constructorArg,
198
250
  );
251
+ insideMap = true;
199
252
 
200
253
  const { entries, convertedNumberKeysToStrings } = getCopiedEntries(
201
254
  defaultMap,
202
255
  serializationType,
203
256
  traversalDescription,
257
+ insideMap,
204
258
  );
205
259
 
206
260
  if (convertedNumberKeysToStrings) {
@@ -223,12 +277,14 @@ function deepCopyDefaultMap(
223
277
  }
224
278
  }
225
279
 
280
+ insideMap = false;
281
+
226
282
  return newDefaultMap;
227
283
  }
228
284
 
229
285
  /**
230
- * The new default map with either be a TSTL `DefaultMap` class or a Lua table, depending on whether
231
- * we are serializing or not.
286
+ * The new copied default map with either be a TSTL `DefaultMap` class or a Lua table, depending on
287
+ * whether we are serializing or not.
232
288
  */
233
289
  function getNewDefaultMap(
234
290
  defaultMap: DefaultMap<AnyNotNil, unknown> | LuaTable<AnyNotNil, unknown>,
@@ -278,6 +334,7 @@ function deepCopyMap(
278
334
  map: Map<AnyNotNil, unknown> | LuaTable<AnyNotNil, unknown>,
279
335
  serializationType: SerializationType,
280
336
  traversalDescription: string,
337
+ insideMap: boolean,
281
338
  ) {
282
339
  let newMap: Map<AnyNotNil, unknown> | LuaTable<AnyNotNil, unknown>;
283
340
  if (serializationType === SerializationType.SERIALIZE) {
@@ -287,11 +344,13 @@ function deepCopyMap(
287
344
  } else {
288
345
  newMap = new Map();
289
346
  }
347
+ insideMap = true;
290
348
 
291
349
  const { entries, convertedNumberKeysToStrings } = getCopiedEntries(
292
350
  map,
293
351
  serializationType,
294
352
  traversalDescription,
353
+ insideMap,
295
354
  );
296
355
 
297
356
  if (convertedNumberKeysToStrings) {
@@ -314,6 +373,8 @@ function deepCopyMap(
314
373
  }
315
374
  }
316
375
 
376
+ insideMap = false;
377
+
317
378
  return newMap;
318
379
  }
319
380
 
@@ -321,6 +382,7 @@ function deepCopySet(
321
382
  set: Set<AnyNotNil> | LuaTable<AnyNotNil, unknown>,
322
383
  serializationType: SerializationType,
323
384
  traversalDescription: string,
385
+ insideMap: boolean,
324
386
  ) {
325
387
  let newSet: Set<AnyNotNil> | LuaTable<AnyNotNil, string>;
326
388
  if (serializationType === SerializationType.SERIALIZE) {
@@ -336,6 +398,7 @@ function deepCopySet(
336
398
  set,
337
399
  serializationType,
338
400
  traversalDescription,
401
+ insideMap,
339
402
  );
340
403
 
341
404
  if (convertedNumberKeysToStrings) {
@@ -368,6 +431,7 @@ function deepCopyTSTLClass(
368
431
  tstlClass: TSTLClass,
369
432
  serializationType: SerializationType,
370
433
  traversalDescription: string,
434
+ insideMap: boolean,
371
435
  ) {
372
436
  let newClass: TSTLClass | LuaTable<AnyNotNil, unknown>;
373
437
  if (serializationType === SerializationType.SERIALIZE) {
@@ -383,6 +447,7 @@ function deepCopyTSTLClass(
383
447
  tstlClass,
384
448
  serializationType,
385
449
  traversalDescription,
450
+ insideMap,
386
451
  );
387
452
 
388
453
  if (convertedNumberKeysToStrings) {
@@ -400,11 +465,17 @@ function deepCopyArray(
400
465
  array: unknown[],
401
466
  serializationType: SerializationType,
402
467
  traversalDescription: string,
468
+ insideMap: boolean,
403
469
  ) {
404
470
  const newArray: unknown[] = [];
405
471
 
406
472
  for (const value of array) {
407
- const newValue = deepCopy(value, serializationType, traversalDescription);
473
+ const newValue = deepCopy(
474
+ value,
475
+ serializationType,
476
+ traversalDescription,
477
+ insideMap,
478
+ );
408
479
  newArray.push(newValue);
409
480
  }
410
481
 
@@ -415,12 +486,14 @@ function deepCopyNormalLuaTable(
415
486
  luaTable: LuaTable<AnyNotNil, unknown>,
416
487
  serializationType: SerializationType,
417
488
  traversalDescription: string,
489
+ insideMap: boolean,
418
490
  ) {
419
491
  const newTable = new LuaTable<AnyNotNil, unknown>();
420
492
  const { entries, convertedNumberKeysToStrings } = getCopiedEntries(
421
493
  luaTable,
422
494
  serializationType,
423
495
  traversalDescription,
496
+ insideMap,
424
497
  );
425
498
 
426
499
  if (convertedNumberKeysToStrings) {
@@ -442,6 +515,7 @@ function getCopiedEntries(
442
515
  object: unknown,
443
516
  serializationType: SerializationType,
444
517
  traversalDescription: string,
518
+ insideMap: boolean,
445
519
  ): {
446
520
  entries: Array<[key: AnyNotNil, value: unknown]>;
447
521
  convertedNumberKeysToStrings: boolean;
@@ -479,7 +553,12 @@ function getCopiedEntries(
479
553
  }
480
554
 
481
555
  traversalDescription = getTraversalDescription(key, traversalDescription);
482
- const newValue = deepCopy(value, serializationType, traversalDescription);
556
+ const newValue = deepCopy(
557
+ value,
558
+ serializationType,
559
+ traversalDescription,
560
+ insideMap,
561
+ );
483
562
 
484
563
  const keyToUse = convertNumberKeysToStrings ? tostring(key) : key;
485
564
  copiedEntries.push([keyToUse, newValue]);
@@ -131,6 +131,7 @@ function copiedTableDoesNotCoerceTypes() {
131
131
  }
132
132
  }
133
133
 
134
+ /** In this context, a reference is a pointer. */
134
135
  function copiedObjectHasNoReferencesForPrimitivesForward() {
135
136
  const originalStringValue = "abcdef";
136
137
  const originalNumberValue = 123;
@@ -181,6 +182,7 @@ function copiedObjectHasNoReferencesForPrimitivesBackward() {
181
182
  }
182
183
  }
183
184
 
185
+ /** In this context, a reference is a pointer. */
184
186
  function copiedObjectHasNoReferencesForArray() {
185
187
  const oldObject = {
186
188
  abc: [1, 2, 3],
@@ -200,21 +202,21 @@ function copiedObjectHasNoReferencesForArray() {
200
202
  error("The copied object does not have an equal array.");
201
203
  }
202
204
 
203
- oldObject.abc[0] += 1;
205
+ oldObject.abc[0]++;
204
206
  if (arrayEquals(oldObject.abc, newObject.abc)) {
205
207
  error(
206
208
  "The copied object has an equal array after a modification to the old array.",
207
209
  );
208
210
  }
209
- oldObject.abc[0] -= 1;
211
+ oldObject.abc[0]--;
210
212
 
211
- newObject.abc[0] += 1;
213
+ newObject.abc[0]++;
212
214
  if (arrayEquals(oldObject.abc, newObject.abc)) {
213
215
  error(
214
216
  "The copied object has an equal array after a modification to the new array.",
215
217
  );
216
218
  }
217
- newObject.abc[0] -= 1;
219
+ newObject.abc[0]--;
218
220
  }
219
221
 
220
222
  function copiedObjectHasChildObject() {
@@ -228,7 +228,7 @@ export function logEntities(
228
228
  msg += ` - CanShutDoors: ${npc.CanShutDoors}\n`;
229
229
  }
230
230
 
231
- numMatchedEntities += 1;
231
+ numMatchedEntities++;
232
232
  });
233
233
 
234
234
  if (numMatchedEntities === 0) {
@@ -404,7 +404,7 @@ export function logGridEntities(
404
404
  msg += ` - TargetRoomType: ${door.TargetRoomType}\n`;
405
405
  }
406
406
 
407
- numMatchedEntities += 1;
407
+ numMatchedEntities++;
408
408
  });
409
409
 
410
410
  if (numMatchedEntities === 0) {
@@ -572,7 +572,7 @@ export function logSounds(this: void): void {
572
572
  * recursively call itself if it counters a table within a table.
573
573
  *
574
574
  * This function will only work on tables that have string keys (because it logs the keys in order,
575
- * instead of randomly). It will throw a runtime error if it encounters a non-string key.
575
+ * instead of randomly). It will throw a run-time error if it encounters a non-string key.
576
576
  */
577
577
  export function logTable(
578
578
  this: void,
@@ -134,7 +134,7 @@ export function getStringsFromTable(
134
134
  * This function will sort the table entries based on the value of the key.
135
135
  *
136
136
  * This function will only work on tables that have number keys or string keys. It will throw a
137
- * runtime error if it encounters a key of another type.
137
+ * run-time error if it encounters a key of another type.
138
138
  *
139
139
  * @param luaTable The table to iterate over.
140
140
  * @param func The function to run for each iteration.
@@ -98,7 +98,7 @@ export function temporarilyRemoveTrinket(
98
98
  let numTrinkets = 0;
99
99
  while (player.HasTrinket(trinketType)) {
100
100
  player.TryRemoveTrinket(trinketType);
101
- numTrinkets += 1;
101
+ numTrinkets++;
102
102
  }
103
103
 
104
104
  let numSmeltedTrinkets = numTrinkets;
@@ -106,13 +106,13 @@ export function temporarilyRemoveTrinket(
106
106
  trinketType1 === trinketType ||
107
107
  trinketType1 === getGoldenTrinketType(trinketType);
108
108
  if (trinketWasInSlot1) {
109
- numSmeltedTrinkets -= 1;
109
+ numSmeltedTrinkets--;
110
110
  }
111
111
  const trinketWasInSlot2 =
112
112
  trinketType2 === trinketType ||
113
113
  trinketType2 === getGoldenTrinketType(trinketType);
114
114
  if (trinketWasInSlot2) {
115
- numSmeltedTrinkets -= 1;
115
+ numSmeltedTrinkets--;
116
116
  }
117
117
 
118
118
  return {
@@ -100,7 +100,7 @@ export function isUserDefinedTSTLClass(object: unknown): object is TSTLClass {
100
100
 
101
101
  let numKeys = 0;
102
102
  for (const [key] of pairs(metatable)) {
103
- numKeys += 1;
103
+ numKeys++;
104
104
 
105
105
  if (!isString(key)) {
106
106
  return false;
@@ -27,10 +27,10 @@ export function getHUDOffsetVector(): Vector {
27
27
  const x = hudOffset * 2;
28
28
  let y = hudOffset;
29
29
  if (y >= 4) {
30
- y += 1;
30
+ y++;
31
31
  }
32
32
  if (y >= 9) {
33
- y += 1;
33
+ y++;
34
34
  }
35
35
 
36
36
  return Vector(x, y);
@@ -69,7 +69,7 @@ export function getHeartsUIWidth(): int {
69
69
 
70
70
  let heartRowLength = getHeartRowLength(player);
71
71
  if (hasHolyMantleEffect) {
72
- heartRowLength += 1;
72
+ heartRowLength++;
73
73
  }
74
74
  if (curses === LevelCurse.UNKNOWN) {
75
75
  heartRowLength = 1;