isaacscript-common 2.3.1 → 3.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.
Files changed (327) hide show
  1. package/cachedClasses.d.ts +6 -4
  2. package/cachedClasses.lua +24 -0
  3. package/callbacks/customRevive.lua +2 -0
  4. package/callbacks/itemPickup.lua +2 -0
  5. package/callbacks/postBombInitLate.lua +2 -0
  6. package/callbacks/postBoneSwing.lua +2 -0
  7. package/callbacks/postCollectibleInitFirst.lua +2 -0
  8. package/callbacks/postCursedTeleport.lua +2 -0
  9. package/callbacks/postCustomDoorEnter.lua +44 -0
  10. package/callbacks/postDoorRender.lua +2 -0
  11. package/callbacks/postDoorUpdate.lua +2 -0
  12. package/callbacks/postEffectInitLate.lua +2 -0
  13. package/callbacks/postEffectStateChanged.lua +2 -0
  14. package/callbacks/postEsauJr.lua +2 -0
  15. package/callbacks/postFamiliarInitLate.lua +2 -0
  16. package/callbacks/postFamiliarStateChanged.lua +2 -0
  17. package/callbacks/postFlip.lua +2 -0
  18. package/callbacks/postGreedModeWave.lua +2 -0
  19. package/callbacks/postGridEntity.lua +2 -0
  20. package/callbacks/postGridEntityCollision.lua +2 -0
  21. package/callbacks/postGridEntityRender.lua +2 -0
  22. package/callbacks/postHolyMantleRemoved.lua +2 -0
  23. package/callbacks/postKnifeInitLate.lua +2 -0
  24. package/callbacks/postLaserInitLate.lua +2 -0
  25. package/callbacks/postNPCInitLate.lua +2 -0
  26. package/callbacks/postNPCStateChanged.lua +2 -0
  27. package/callbacks/postNewRoomEarly.lua +2 -0
  28. package/callbacks/postPickupCollect.lua +2 -0
  29. package/callbacks/postPickupInitLate.lua +2 -0
  30. package/callbacks/postPickupStateChanged.lua +2 -0
  31. package/callbacks/postPitRender.lua +2 -0
  32. package/callbacks/postPitUpdate.lua +2 -0
  33. package/callbacks/postPlayerChangeHealth.lua +2 -0
  34. package/callbacks/postPlayerChangeType.lua +2 -0
  35. package/callbacks/postPlayerFatalDamage.lua +2 -0
  36. package/callbacks/postPlayerInitLate.lua +2 -0
  37. package/callbacks/postPlayerReordered.lua +2 -0
  38. package/callbacks/postPoopRender.lua +2 -0
  39. package/callbacks/postPoopUpdate.lua +2 -0
  40. package/callbacks/postPressurePlateRender.lua +2 -0
  41. package/callbacks/postPressurePlateUpdate.lua +2 -0
  42. package/callbacks/postProjectileInitLate.lua +2 -0
  43. package/callbacks/postPurchase.lua +2 -0
  44. package/callbacks/postRockRender.lua +2 -0
  45. package/callbacks/postRockUpdate.lua +2 -0
  46. package/callbacks/postRoomClearChanged.lua +2 -0
  47. package/callbacks/postSacrifice.lua +2 -0
  48. package/callbacks/postSlotDestroyed.d.ts +1 -0
  49. package/callbacks/postSlotDestroyed.lua +66 -0
  50. package/callbacks/postSlotInitUpdate.lua +2 -0
  51. package/callbacks/postSlotRender.lua +5 -21
  52. package/callbacks/postSpikesRender.lua +2 -0
  53. package/callbacks/postSpikesUpdate.lua +2 -0
  54. package/callbacks/postTNTRender.lua +2 -0
  55. package/callbacks/postTNTUpdate.lua +2 -0
  56. package/callbacks/postTearInitLate.lua +2 -0
  57. package/callbacks/postTearInitVeryLate.lua +2 -0
  58. package/callbacks/postTransformation.lua +2 -0
  59. package/callbacks/postTrinketBreak.lua +2 -0
  60. package/callbacks/preBerserkDeath.lua +2 -0
  61. package/callbacks/preNewLevel.lua +2 -0
  62. package/callbacks/reorderedCallbacks.lua +16 -0
  63. package/callbacks/subscriptions/postBombInitLate.lua +6 -0
  64. package/callbacks/subscriptions/postBoneSwing.lua +6 -0
  65. package/callbacks/subscriptions/postCollectibleInitFirst.lua +6 -0
  66. package/callbacks/subscriptions/postCursedTeleport.lua +6 -0
  67. package/callbacks/subscriptions/postCustomDoorEnter.lua +6 -0
  68. package/callbacks/subscriptions/postCustomRevive.d.ts +1 -0
  69. package/callbacks/subscriptions/postCustomRevive.lua +6 -0
  70. package/callbacks/subscriptions/postDoorRender.d.ts +1 -0
  71. package/callbacks/subscriptions/postDoorRender.lua +6 -0
  72. package/callbacks/subscriptions/postDoorUpdate.d.ts +1 -0
  73. package/callbacks/subscriptions/postDoorUpdate.lua +6 -0
  74. package/callbacks/subscriptions/postEffectInitLate.lua +6 -0
  75. package/callbacks/subscriptions/postEffectStateChanged.lua +6 -0
  76. package/callbacks/subscriptions/postEsauJr.lua +6 -0
  77. package/callbacks/subscriptions/postFamiliarInitLate.lua +6 -0
  78. package/callbacks/subscriptions/postFamiliarStateChanged.lua +6 -0
  79. package/callbacks/subscriptions/postFirstEsauJr.lua +6 -0
  80. package/callbacks/subscriptions/postFirstFlip.lua +6 -0
  81. package/callbacks/subscriptions/postFlip.lua +6 -0
  82. package/callbacks/subscriptions/postGameStartedReordered.lua +6 -0
  83. package/callbacks/subscriptions/postGreedModeWave.lua +6 -0
  84. package/callbacks/subscriptions/postGridEntityBroken.lua +6 -0
  85. package/callbacks/subscriptions/postGridEntityCollision.lua +6 -0
  86. package/callbacks/subscriptions/postGridEntityInit.lua +6 -0
  87. package/callbacks/subscriptions/postGridEntityRemove.lua +6 -0
  88. package/callbacks/subscriptions/postGridEntityRender.lua +6 -0
  89. package/callbacks/subscriptions/postGridEntityStateChanged.lua +6 -0
  90. package/callbacks/subscriptions/postGridEntityUpdate.lua +6 -0
  91. package/callbacks/subscriptions/postHolyMantleRemoved.lua +6 -0
  92. package/callbacks/subscriptions/postItemDischarged.lua +6 -0
  93. package/callbacks/subscriptions/postItemPickup.lua +6 -0
  94. package/callbacks/subscriptions/postKnifeInitLate.lua +6 -0
  95. package/callbacks/subscriptions/postLaserInitLate.lua +6 -0
  96. package/callbacks/subscriptions/postNPCInitLate.lua +6 -0
  97. package/callbacks/subscriptions/postNPCStateChanged.lua +6 -0
  98. package/callbacks/subscriptions/postNewLevelReordered.lua +6 -0
  99. package/callbacks/subscriptions/postNewRoomEarly.lua +6 -0
  100. package/callbacks/subscriptions/postNewRoomReordered.lua +6 -0
  101. package/callbacks/subscriptions/postPEffectUpdateReordered.lua +6 -0
  102. package/callbacks/subscriptions/postPickupCollect.d.ts +1 -0
  103. package/callbacks/subscriptions/postPickupCollect.lua +6 -0
  104. package/callbacks/subscriptions/postPickupInitLate.lua +6 -0
  105. package/callbacks/subscriptions/postPickupStateChanged.d.ts +1 -0
  106. package/callbacks/subscriptions/postPickupStateChanged.lua +6 -0
  107. package/callbacks/subscriptions/postPitRender.d.ts +1 -0
  108. package/callbacks/subscriptions/postPitRender.lua +6 -0
  109. package/callbacks/subscriptions/postPitUpdate.d.ts +1 -0
  110. package/callbacks/subscriptions/postPitUpdate.lua +6 -0
  111. package/callbacks/subscriptions/postPlayerChangeHealth.lua +6 -0
  112. package/callbacks/subscriptions/postPlayerChangeType.lua +6 -0
  113. package/callbacks/subscriptions/postPlayerFatalDamage.lua +6 -0
  114. package/callbacks/subscriptions/postPlayerInitLate.lua +6 -0
  115. package/callbacks/subscriptions/postPlayerInitReordered.lua +6 -0
  116. package/callbacks/subscriptions/postPlayerRenderReordered.lua +6 -0
  117. package/callbacks/subscriptions/postPlayerUpdateReordered.lua +6 -0
  118. package/callbacks/subscriptions/postPoopRender.d.ts +1 -0
  119. package/callbacks/subscriptions/postPoopRender.lua +6 -0
  120. package/callbacks/subscriptions/postPoopUpdate.d.ts +1 -0
  121. package/callbacks/subscriptions/postPoopUpdate.lua +6 -0
  122. package/callbacks/subscriptions/postPressurePlateRender.d.ts +1 -0
  123. package/callbacks/subscriptions/postPressurePlateRender.lua +6 -0
  124. package/callbacks/subscriptions/postPressurePlateUpdate.d.ts +1 -0
  125. package/callbacks/subscriptions/postPressurePlateUpdate.lua +6 -0
  126. package/callbacks/subscriptions/postProjectileInitLate.lua +6 -0
  127. package/callbacks/subscriptions/postPurchase.lua +6 -0
  128. package/callbacks/subscriptions/postRockRender.d.ts +1 -0
  129. package/callbacks/subscriptions/postRockRender.lua +6 -0
  130. package/callbacks/subscriptions/postRockUpdate.d.ts +1 -0
  131. package/callbacks/subscriptions/postRockUpdate.lua +6 -0
  132. package/callbacks/subscriptions/postRoomClearChanged.lua +6 -0
  133. package/callbacks/subscriptions/postSacrifice.lua +6 -0
  134. package/callbacks/subscriptions/postSlotAnimationChanged.lua +6 -0
  135. package/callbacks/subscriptions/postSlotDestroyed.lua +6 -0
  136. package/callbacks/subscriptions/postSlotInit.lua +6 -0
  137. package/callbacks/subscriptions/postSlotRender.lua +6 -0
  138. package/callbacks/subscriptions/postSlotUpdate.lua +6 -0
  139. package/callbacks/subscriptions/postSpikesRender.d.ts +1 -0
  140. package/callbacks/subscriptions/postSpikesRender.lua +6 -0
  141. package/callbacks/subscriptions/postSpikesUpdate.d.ts +1 -0
  142. package/callbacks/subscriptions/postSpikesUpdate.lua +6 -0
  143. package/callbacks/subscriptions/postTNTRender.d.ts +1 -0
  144. package/callbacks/subscriptions/postTNTRender.lua +6 -0
  145. package/callbacks/subscriptions/postTNTUpdate.d.ts +1 -0
  146. package/callbacks/subscriptions/postTNTUpdate.lua +6 -0
  147. package/callbacks/subscriptions/postTearInitLate.lua +6 -0
  148. package/callbacks/subscriptions/postTearInitVeryLate.lua +6 -0
  149. package/callbacks/subscriptions/postTransformation.lua +6 -0
  150. package/callbacks/subscriptions/postTrinketBreak.lua +6 -0
  151. package/callbacks/subscriptions/preBerserkDeath.lua +6 -0
  152. package/callbacks/subscriptions/preCustomRevive.lua +6 -0
  153. package/callbacks/subscriptions/preItemPickup.lua +6 -0
  154. package/callbacks/subscriptions/preNewLevel.lua +6 -0
  155. package/classes/DefaultMap.d.ts +70 -39
  156. package/classes/DefaultMap.lua +94 -43
  157. package/classes/ModUpgraded.d.ts +3 -3
  158. package/classes/ModUpgraded.lua +5 -0
  159. package/constants.lua +41 -0
  160. package/constantsFirstLast.lua +63 -0
  161. package/enums/HealthType.lua +3 -0
  162. package/enums/ModCallbackCustom.d.ts +1 -1
  163. package/enums/ModCallbackCustom.lua +6 -0
  164. package/enums/private/CopyableIsaacAPIClassType.lua +1 -0
  165. package/enums/private/SerializationBrand.lua +5 -0
  166. package/features/characterHealthConversion.lua +6 -0
  167. package/features/characterStats.lua +17 -0
  168. package/features/debugDisplay/exports.d.ts +17 -0
  169. package/features/debugDisplay/exports.lua +90 -0
  170. package/features/debugDisplay/v.d.ts +17 -0
  171. package/features/deployJSONRoom.d.ts +1 -0
  172. package/features/deployJSONRoom.lua +56 -0
  173. package/features/disableInputs.lua +45 -0
  174. package/features/disableSound.lua +14 -0
  175. package/features/extraConsoleCommands/commandsDisplay.lua +90 -0
  176. package/features/extraConsoleCommands/init.lua +16 -0
  177. package/features/extraConsoleCommands/listCommands.lua +172 -0
  178. package/features/fadeInRemover.lua +10 -0
  179. package/features/fastReset.lua +10 -0
  180. package/features/forgottenSwitch.lua +4 -0
  181. package/features/getCollectibleItemPoolType.lua +5 -0
  182. package/features/playerInventory.lua +18 -0
  183. package/features/ponyDetection.lua +4 -0
  184. package/features/preventCollectibleRotation.lua +9 -0
  185. package/features/runInNFrames.lua +50 -0
  186. package/features/saveDataManager/constants.lua +1 -0
  187. package/features/saveDataManager/exports.lua +115 -0
  188. package/features/saveDataManager/load.lua +12 -8
  189. package/features/saveDataManager/main.lua +16 -3
  190. package/features/saveDataManager/maps.lua +3 -0
  191. package/features/saveDataManager/merge.lua +53 -21
  192. package/features/saveDataManager/save.lua +12 -7
  193. package/features/sirenHelpers.lua +13 -0
  194. package/features/taintedLazarusPlayers.lua +11 -0
  195. package/featuresInitialized.lua +6 -0
  196. package/functions/array.d.ts +2 -0
  197. package/functions/array.lua +85 -0
  198. package/functions/benchmark.lua +6 -0
  199. package/functions/boss.lua +35 -0
  200. package/functions/cacheFlag.lua +4 -0
  201. package/functions/cards.lua +60 -0
  202. package/functions/challenges.lua +1 -0
  203. package/functions/character.lua +23 -0
  204. package/functions/charge.lua +39 -0
  205. package/functions/chargeBar.d.ts +1 -0
  206. package/functions/chargeBar.lua +4 -0
  207. package/functions/collectibleCacheFlag.lua +15 -0
  208. package/functions/collectibleSet.lua +3 -0
  209. package/functions/collectibleTag.lua +9 -0
  210. package/functions/collectibles.d.ts +6 -1
  211. package/functions/collectibles.lua +146 -2
  212. package/functions/color.lua +18 -0
  213. package/functions/debug.lua +18 -0
  214. package/functions/deepCopy.lua +60 -26
  215. package/functions/deepCopyTests.lua +8 -5
  216. package/functions/direction.d.ts +1 -0
  217. package/functions/direction.lua +22 -0
  218. package/functions/doors.d.ts +1 -0
  219. package/functions/doors.lua +58 -0
  220. package/functions/entity.d.ts +4 -4
  221. package/functions/entity.lua +94 -6
  222. package/functions/entitySpecific.d.ts +20 -20
  223. package/functions/entitySpecific.lua +182 -0
  224. package/functions/entityTypes.d.ts +1 -1
  225. package/functions/entityTypes.lua +1 -0
  226. package/functions/enums.d.ts +2 -0
  227. package/functions/enums.lua +62 -0
  228. package/functions/familiars.lua +52 -0
  229. package/functions/flag.lua +77 -0
  230. package/functions/flying.lua +10 -0
  231. package/functions/globals.lua +8 -10
  232. package/functions/gridEntity.lua +105 -0
  233. package/functions/gridEntitySpecific.d.ts +5 -0
  234. package/functions/gridEntitySpecific.lua +8 -0
  235. package/functions/input.lua +11 -0
  236. package/functions/isaacAPIClass.d.ts +4 -4
  237. package/functions/isaacAPIClass.lua +15 -3
  238. package/functions/jsonHelpers.lua +11 -0
  239. package/functions/jsonRoom.d.ts +2 -0
  240. package/functions/jsonRoom.lua +5 -0
  241. package/functions/kColor.lua +9 -0
  242. package/functions/language.lua +5 -0
  243. package/functions/log.lua +31 -3
  244. package/functions/map.lua +18 -0
  245. package/functions/math.lua +26 -0
  246. package/functions/npc.lua +24 -0
  247. package/functions/pickupVariants.d.ts +11 -11
  248. package/functions/pickupVariants.lua +11 -0
  249. package/functions/pickups.d.ts +9 -9
  250. package/functions/pickups.lua +67 -0
  251. package/functions/pills.lua +45 -0
  252. package/functions/player.lua +166 -0
  253. package/functions/playerDataStructures.lua +65 -0
  254. package/functions/playerHealth.d.ts +1 -0
  255. package/functions/playerHealth.lua +10 -0
  256. package/functions/playerIndex.d.ts +2 -0
  257. package/functions/playerIndex.lua +47 -0
  258. package/functions/pocketItems.lua +18 -0
  259. package/functions/positionVelocity.d.ts +3 -0
  260. package/functions/positionVelocity.lua +46 -0
  261. package/functions/random.d.ts +2 -0
  262. package/functions/random.lua +32 -0
  263. package/functions/revive.d.ts +2 -0
  264. package/functions/revive.lua +15 -0
  265. package/functions/rng.d.ts +1 -0
  266. package/functions/rng.lua +19 -0
  267. package/functions/roomData.lua +68 -0
  268. package/functions/roomGrid.lua +21 -0
  269. package/functions/roomShape.lua +22 -0
  270. package/functions/rooms.lua +100 -0
  271. package/functions/run.lua +5 -0
  272. package/functions/seeds.lua +4 -0
  273. package/functions/serialization.lua +6 -2
  274. package/functions/set.d.ts +1 -0
  275. package/functions/set.lua +22 -0
  276. package/functions/spawnCollectible.lua +24 -0
  277. package/functions/sprite.d.ts +2 -0
  278. package/functions/sprite.lua +25 -0
  279. package/functions/stage.lua +16 -0
  280. package/functions/string.lua +6 -0
  281. package/functions/table.d.ts +12 -0
  282. package/functions/table.lua +53 -0
  283. package/functions/tears.d.ts +1 -0
  284. package/functions/tears.lua +12 -0
  285. package/functions/transformations.lua +18 -0
  286. package/functions/trinketCacheFlag.lua +3 -0
  287. package/functions/trinketGive.lua +24 -0
  288. package/functions/trinkets.lua +52 -0
  289. package/functions/tstlClass.d.ts +34 -0
  290. package/functions/tstlClass.lua +63 -9
  291. package/functions/ui.d.ts +2 -0
  292. package/functions/ui.lua +16 -0
  293. package/functions/utils.d.ts +16 -0
  294. package/functions/utils.lua +108 -0
  295. package/functions/vector.lua +13 -16
  296. package/index.d.ts +1 -0
  297. package/initCustomCallbacks.lua +3 -0
  298. package/interfaces/ChargeBarSprites.d.ts +1 -0
  299. package/interfaces/private/TSTLClassMetatable.d.ts +2 -0
  300. package/lualib_bundle.lua +21 -34
  301. package/maps/cardMap.lua +1 -0
  302. package/maps/characterMap.lua +1 -0
  303. package/maps/defaultPlayerStatMap.lua +1 -0
  304. package/maps/gridEntityXMLMap.lua +2 -0
  305. package/maps/pillEffectMap.lua +1 -0
  306. package/maps/roomShapeToTopLeftWallGridIndexMap.lua +2 -0
  307. package/maps/roomTypeMap.lua +1 -0
  308. package/objects/LRoomShapeToRectangles.lua +2 -0
  309. package/objects/colors.lua +4 -0
  310. package/objects/oppositeDoorSlots.d.ts +4 -0
  311. package/objects/oppositeDoorSlots.lua +15 -0
  312. package/objects/roomShapeBounds.lua +2 -0
  313. package/objects/roomShapeLayoutSizes.lua +4 -0
  314. package/objects/roomShapeToBottomRightPosition.lua +2 -0
  315. package/objects/roomShapeToDoorSlotsToGridIndexDelta.lua +2 -0
  316. package/objects/roomShapeToTopLeftPosition.lua +2 -0
  317. package/objects/roomShapeVolumes.lua +3 -0
  318. package/package.json +2 -2
  319. package/patchErrorFunctions.lua +8 -0
  320. package/sets/bossSets.lua +23 -0
  321. package/sets/charactersWithNoRedHeartsSet.lua +2 -0
  322. package/sets/charactersWithNoSoulHeartsSet.lua +2 -0
  323. package/sets/lostStyleCharactersSet.lua +2 -0
  324. package/types/AnyEntity.d.ts +10 -0
  325. package/types/PickingUpItem.lua +7 -0
  326. package/upgradeMod.d.ts +4 -4
  327. package/upgradeMod.lua +18 -0
@@ -35,13 +35,23 @@ function checkResetInput(self)
35
35
  end
36
36
  local FEATURE_NAME = "fast reset"
37
37
  enabled = false
38
+ ---
39
+ -- @internal
38
40
  function ____exports.fastResetInit(self, mod)
39
41
  mod:AddCallback(ModCallback.POST_RENDER, postRender)
40
42
  end
43
+ --- Enables the fast-reset feature, which allows you to restart the game instantaneously. If this
44
+ -- behavior is desired, call this function once at the beginning of your mod.
45
+ --
46
+ -- This is useful for debugging, when you are resetting the game often.
47
+ --
48
+ -- You can disable the fast-reset feature with the `disableFastReset` function.
41
49
  function ____exports.enableFastReset(self)
42
50
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
43
51
  enabled = true
44
52
  end
53
+ --- Disables the fast-reset feature. Only useful if you have previously called the `enableFastReset`
54
+ -- function.
45
55
  function ____exports.disableFastReset(self)
46
56
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
47
57
  enabled = false
@@ -17,10 +17,14 @@ function isActionTriggered(self, _entity, _inputHook, buttonAction)
17
17
  end
18
18
  local FEATURE_NAME = "forgotten switcher"
19
19
  v = {run = {shouldSwitch = false}}
20
+ ---
21
+ -- @internal
20
22
  function ____exports.forgottenSwitchInit(self, mod)
21
23
  saveDataManager(nil, "forgottenSwitch", v)
22
24
  mod:AddCallback(ModCallback.INPUT_ACTION, isActionTriggered, InputHook.IS_ACTION_TRIGGERED)
23
25
  end
26
+ --- When used on The Forgotten, switches to The Soul. When used on The Soul, switches to The
27
+ -- Forgotten. This takes 1 game frame to take effect.
24
28
  function ____exports.forgottenSwitch(self)
25
29
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
26
30
  v.run.shouldSwitch = true
@@ -26,10 +26,15 @@ function postPickupInitCollectible(self, pickup)
26
26
  end
27
27
  local FEATURE_NAME = "get collectible item pool type"
28
28
  v = {run = {collectibleItemPoolTypeMap = __TS__New(Map)}}
29
+ ---
30
+ -- @internal
29
31
  function ____exports.getCollectibleItemPoolTypeInit(self, mod)
30
32
  saveDataManager(nil, "getCollectibleItemPoolType", v)
31
33
  mod:AddCallback(ModCallback.POST_PICKUP_INIT, postPickupInitCollectible, PickupVariant.COLLECTIBLE)
32
34
  end
35
+ --- Helper function to get the item pool type that a given collectible came from. Since there is no
36
+ -- native method in the API to get this, we listen in the PreGetCollectible callback for item pool
37
+ -- types, and then assume that the next spawned collectible will match.
33
38
  function ____exports.getCollectibleItemPoolType(self, collectible)
34
39
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
35
40
  if not isCollectible(nil, collectible) then
@@ -94,12 +94,24 @@ v = {run = {
94
94
  function() return {} end
95
95
  )
96
96
  }}
97
+ ---
98
+ -- @internal
97
99
  function ____exports.playerInventoryInit(self, mod)
98
100
  saveDataManager(nil, "playerInventory", v)
99
101
  mod:AddCallback(ModCallback.POST_USE_ITEM, useItemD4, CollectibleType.D4)
100
102
  mod:AddCallback(ModCallback.POST_GAME_STARTED, postGameStarted)
101
103
  mod:AddCallbackCustom(ModCallbackCustom.POST_ITEM_PICKUP, postItemPickup)
102
104
  end
105
+ --- Helper function to get all of the collectibles that the player has gotten so far on this run, in
106
+ -- order.
107
+ --
108
+ -- Note that this does not include active collectibles that have since been dropped for other
109
+ -- collectibles.
110
+ --
111
+ -- In the case of inventory initialization or the case where the player rerolls their build in the
112
+ -- middle of the run (e.g. with D4), the order of the inventory will not correspond to the order
113
+ -- that the items were actually given to the player. In this case, the inventory will be in the
114
+ -- order of the lowest `CollectibleType` to the highest.
103
115
  function ____exports.getPlayerInventory(self, player, includeActiveCollectibles)
104
116
  if includeActiveCollectibles == nil then
105
117
  includeActiveCollectibles = true
@@ -116,6 +128,12 @@ function ____exports.getPlayerInventory(self, player, includeActiveCollectibles)
116
128
  function(____, collectibleType) return not isActiveCollectible(nil, collectibleType) end
117
129
  )
118
130
  end
131
+ --- Helper function to add a collectible to a player. Use this instead of the
132
+ -- `EntityPlayer.AddCollectible` method if you want the collectible that is added to be
133
+ -- automatically tracked by the player inventory tracker feature.
134
+ --
135
+ -- You only need to use this function if you are using the inventory feature from the standard
136
+ -- library.
119
137
  function ____exports.addCollectible(self, player, collectibleType, charge, firstTimePickingUp, activeSlot, varData)
120
138
  player:AddCollectible(
121
139
  collectibleType,
@@ -38,10 +38,14 @@ end
38
38
  local FEATURE_NAME = "pony activation detector"
39
39
  FLAGS_WHEN_PONY_IS_ACTIVE = {EntityFlag.NO_KNOCKBACK, EntityFlag.NO_PHYSICS_KNOCKBACK, EntityFlag.NO_DAMAGE_BLINK}
40
40
  v = {run = {playersIsPonyActive = __TS__New(Set)}}
41
+ ---
42
+ -- @internal
41
43
  function ____exports.ponyDetectionInit(self, mod)
42
44
  saveDataManager(nil, "ponyDetection", v)
43
45
  mod:AddCallbackCustom(ModCallbackCustom.POST_PEFFECT_UPDATE_REORDERED, postPEffectUpdateReordered)
44
46
  end
47
+ --- Helper function to see if the player is under the effects of A Pony or White Pony charge.
48
+ -- Detecting this is difficult, as the temporary effect will disappear upon entering a new room.
45
49
  function ____exports.isPonyActive(self, player)
46
50
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
47
51
  return setHasPlayer(nil, v.run.playersIsPonyActive, player)
@@ -40,11 +40,20 @@ function getMapIndex(self, collectible)
40
40
  end
41
41
  local FEATURE_NAME = "prevent collectible rotation"
42
42
  v = {room = {trackedCollectibles = __TS__New(Map)}}
43
+ ---
44
+ -- @internal
43
45
  function ____exports.preventCollectibleRotationInit(self, mod)
44
46
  saveDataManager(nil, "preventCollectibleRotation", v)
45
47
  mod:AddCallback(ModCallback.POST_USE_CARD, useCardSoulOfIsaac, Card.SOUL_ISAAC)
46
48
  mod:AddCallback(ModCallback.POST_PICKUP_UPDATE, postPickupUpdateCollectible, PickupVariant.COLLECTIBLE)
47
49
  end
50
+ --- Helper function to prevent a collectible from being affected by Tainted Isaac's rotation
51
+ -- mechanic. (This mechanic also happens from Glitched Crown and Binge Eater.) This is useful
52
+ -- because quest items that are manually spawned by mods will be automatically be affected by this
53
+ -- mechanic.
54
+ --
55
+ -- It is required to pass the intended collectible type to this function since it is possible for
56
+ -- collectibles to rotate on the first frame that they are spawned.
48
57
  function ____exports.preventCollectibleRotation(self, collectible, collectibleType)
49
58
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
50
59
  if not isCollectible(nil, collectible) then
@@ -41,6 +41,8 @@ function checkExecuteQueuedFunctions(self, frameCount, functionTuples)
41
41
  end
42
42
  local FEATURE_NAME = "run in N frames"
43
43
  v = {run = {queuedGameFunctionTuples = {}, queuedRenderFunctionTuples = {}}}
44
+ ---
45
+ -- @internal
44
46
  function ____exports.runInNFramesInit(self, mod)
45
47
  saveDataManager(
46
48
  nil,
@@ -51,6 +53,14 @@ function ____exports.runInNFramesInit(self, mod)
51
53
  mod:AddCallback(ModCallback.POST_UPDATE, postUpdate)
52
54
  mod:AddCallback(ModCallback.POST_RENDER, postRender)
53
55
  end
56
+ --- Supply a function to run N game frames from now in the PostUpdate callback.
57
+ --
58
+ -- For a usage example, see the documentation for the `runNextGameFrame`, which is used in a similar
59
+ -- way.
60
+ --
61
+ -- Note that this function will not handle saving and quitting. If a player saving and quitting
62
+ -- before the deferred function fires would cause a bug in your mod, then you should handle deferred
63
+ -- functions manually using serializable data.
54
64
  function ____exports.runInNGameFrames(self, func, gameFrames)
55
65
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
56
66
  local gameFrameCount = game:GetFrameCount()
@@ -59,6 +69,14 @@ function ____exports.runInNGameFrames(self, func, gameFrames)
59
69
  local ____v_run_queuedGameFunctionTuples_0 = v.run.queuedGameFunctionTuples
60
70
  ____v_run_queuedGameFunctionTuples_0[#____v_run_queuedGameFunctionTuples_0 + 1] = tuple
61
71
  end
72
+ --- Supply a function to run N render frames from now in the PostRender callback.
73
+ --
74
+ -- For a usage example, see the documentation for the `runNextGameFrame`, which is used in a similar
75
+ -- way.
76
+ --
77
+ -- Note that this function will not handle saving and quitting. If a player saving and quitting
78
+ -- before the deferred function fires would cause a bug in your mod, then you should handle deferred
79
+ -- functions manually using serializable data.
62
80
  function ____exports.runInNRenderFrames(self, func, renderFrames)
63
81
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
64
82
  local renderFrameCount = Isaac.GetFrameCount()
@@ -67,10 +85,42 @@ function ____exports.runInNRenderFrames(self, func, renderFrames)
67
85
  local ____v_run_queuedRenderFunctionTuples_1 = v.run.queuedRenderFunctionTuples
68
86
  ____v_run_queuedRenderFunctionTuples_1[#____v_run_queuedRenderFunctionTuples_1 + 1] = tuple
69
87
  end
88
+ --- Supply a function to run on the next PostUpdate callback.
89
+ --
90
+ -- For example:
91
+ --
92
+ -- ```ts
93
+ -- const NUM_EXPLODER_EXPLOSIONS = 5;
94
+ --
95
+ -- function useItemExploder(player: EntityPlayer) {
96
+ -- playSound("exploderBegin");
97
+ -- explode(player, NUM_EXPLODER_EXPLOSIONS);
98
+ -- }
99
+ --
100
+ -- function explode(player: EntityPlayer, numFramesLeft: int) {
101
+ -- Isaac.Explode(player, undefined, 1);
102
+ -- numFramesLeft -= 1;
103
+ -- if (numFramesLeft === 0) {
104
+ -- runNextFrame(() => {
105
+ -- explode(player, numFramesLeft);
106
+ -- });
107
+ -- }
108
+ -- }
109
+ -- ```
110
+ --
111
+ -- Note that this function will not handle saving and quitting. If a player saving and quitting
112
+ -- before the deferred function fires would cause a bug in your mod, then you should handle deferred
113
+ -- functions manually using serializable data.
70
114
  function ____exports.runNextGameFrame(self, func)
71
115
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
72
116
  ____exports.runInNGameFrames(nil, func, 1)
73
117
  end
118
+ --- Supply a function to run on the next PostRender callback.
119
+ --
120
+ -- For a usage example, see the documentation for the `runNextGameFrame`, which is used in a similar
121
+ -- way.
122
+ --
123
+ -- Note that this function will not handle saving and quitting.
74
124
  function ____exports.runNextRenderFrame(self, func)
75
125
  errorIfFeaturesNotInitialized(nil, FEATURE_NAME)
76
126
  ____exports.runInNRenderFrames(nil, func, 1)
@@ -1,4 +1,5 @@
1
1
  local ____exports = {}
2
+ --- Set this to true to enable more verbosity in the save data manger.
2
3
  ____exports.SAVE_DATA_MANAGER_DEBUG = false
3
4
  ____exports.SAVE_DATA_MANAGER_FEATURE_NAME = "save data manager"
4
5
  return ____exports
@@ -18,6 +18,89 @@ local ____maps = require("features.saveDataManager.maps")
18
18
  local saveDataConditionalFuncMap = ____maps.saveDataConditionalFuncMap
19
19
  local saveDataDefaultsMap = ____maps.saveDataDefaultsMap
20
20
  local saveDataMap = ____maps.saveDataMap
21
+ --- This is the entry point to the save data manager, a system which provides two major features:
22
+ --
23
+ -- 1. automatic resetting of variables on a new run, on a new level, or on a new room (as desired)
24
+ -- 2. automatic saving and loading of all tracked data to the "save#.dat" file
25
+ --
26
+ -- You feed this function with an anonymous object containing your variables, and then it will
27
+ -- automatically manage them for you. (See below for an example.)
28
+ --
29
+ -- The save data manager is meant to be called once for each feature of your mod. In other words,
30
+ -- you should not put all of the data for your mod on the same object. Instead, scope your variables
31
+ -- locally to a single file that contains a mod feature, and then call this function to register
32
+ -- them. For example:
33
+ --
34
+ -- ```ts
35
+ -- // in file: feature1.ts
36
+ -- import { saveDataManager } from "isaacscript-common";
37
+ --
38
+ -- // Declare local variables for this file or feature.
39
+ -- const v = {
40
+ -- // These variables are never reset; manage them yourself at will.
41
+ -- persistent: {
42
+ -- foo1: 0,
43
+ -- },
44
+ --
45
+ -- // These variables are reset at the beginning of every run.
46
+ -- run: {
47
+ -- foo2: 0,
48
+ -- },
49
+ --
50
+ -- // These variables are reset at the beginning of every level.
51
+ -- level: {
52
+ -- foo3: 0,
53
+ -- },
54
+ --
55
+ -- // These variables are reset at the beginning of every room.
56
+ -- room: {
57
+ -- foo4: 0,
58
+ -- },
59
+ -- };
60
+ -- // Every child object is optional; only create the ones that you need.
61
+ --
62
+ -- // Register the variables with the save data manager. (We need to provide a string key that
63
+ -- // matches the name of this file.)
64
+ -- function feature1Init() {
65
+ -- saveDataManager("feature1", v);
66
+ -- }
67
+ --
68
+ -- // Elsewhere in the file, use your variables.
69
+ -- function feature1Function() {
70
+ -- if (v.run.foo1 > 0) {
71
+ -- // Insert code here.
72
+ -- }
73
+ -- }
74
+ -- ```
75
+ --
76
+ -- - Save data is loaded from disk in the `POST_PLAYER_INIT` callback (i.e. the first callback that
77
+ -- can possibly run).
78
+ -- - Save data is recorded to disk in the `PRE_GAME_EXIT` callback.
79
+ --
80
+ -- Note that before using the save data manager, you must call the `upgradeMod` function. (Upgrade
81
+ -- your mod before registering any of your own callbacks so that the save data manager will run
82
+ -- before any of your code does.)
83
+ --
84
+ -- If you want the save data manager to load data before the `POST_PLAYER_INIT` callback (i.e. in
85
+ -- the main menu), then you should explicitly call the `saveDataManagerLoad` function. (The save
86
+ -- data manager cannot do this on its own because it cannot know when your mod features are finished
87
+ -- initializing.)
88
+ --
89
+ -- Finally, some features may have variables that need to be automatically reset per run/level, but
90
+ -- not saved to disk on game exit. (For example, if they contain functions or other non-serializable
91
+ -- data.) For these cases, set the second argument to `() => false`.
92
+ --
93
+ -- @param key The name of the file or feature that is submitting data to be managed by the save data
94
+ -- manager. The save data manager will throw an error if the key is already registered.
95
+ -- @param v An object that corresponds to the `SaveData` interface. The object is conventionally
96
+ -- called "v" for brevity. ("v" is short for "local variables").
97
+ -- @param conditionalFunc An optional function to run upon saving this key to disk. For example,
98
+ -- this allows features to only save data to disk if the feature is enabled.
99
+ -- Specify a value of `() => false` to completely disable saving this feature
100
+ -- to disk. Disabling saving to disk is useful if you are using data that is
101
+ -- not serializable. Alternatively, it could be useful if you want to use the
102
+ -- save data manager to automatically reset variables on run/level/room, but
103
+ -- not clutter the the "save#.dat" file with unnecessary keys.
21
104
  function ____exports.saveDataManager(self, key, v, conditionalFunc)
22
105
  errorIfFeaturesNotInitialized(nil, SAVE_DATA_MANAGER_FEATURE_NAME)
23
106
  local keyType = type(key)
@@ -39,18 +122,50 @@ function ____exports.saveDataManager(self, key, v, conditionalFunc)
39
122
  saveDataConditionalFuncMap:set(key, conditionalFunc)
40
123
  end
41
124
  end
125
+ --- The save data manager will automatically load variables from disk at the appropriate times (i.e.
126
+ -- when a new run is started). Use this function to explicitly force the save data manager to load
127
+ -- all of its variables from disk immediately.
128
+ --
129
+ -- Obviously, doing this will overwrite the current data, so using this function can potentially
130
+ -- result in lost state.
42
131
  function ____exports.saveDataManagerLoad(self)
43
132
  errorIfFeaturesNotInitialized(nil, SAVE_DATA_MANAGER_FEATURE_NAME)
44
133
  forceSaveDataManagerLoad(nil)
45
134
  end
135
+ --- The save data manager will automatically save variables to disk at the appropriate times (i.e.
136
+ -- when the run is exited). Use this function to explicitly force the save data manager to write all
137
+ -- of its variables to disk immediately.
46
138
  function ____exports.saveDataManagerSave(self)
47
139
  errorIfFeaturesNotInitialized(nil, SAVE_DATA_MANAGER_FEATURE_NAME)
48
140
  forceSaveDataManagerSave(nil)
49
141
  end
142
+ --- - Sets the global variable of "g" equal to all of the save data variables for this mod.
143
+ -- - Sets the global variable of "gd" equal to all of the save data default variables for this mod.
144
+ --
145
+ -- This can make debugging easier, as you can access the variables from the game's debug console.
146
+ -- e.g. `l print(g.feature1.foo)`
50
147
  function ____exports.saveDataManagerSetGlobal(self)
51
148
  g = saveDataMap
52
149
  gd = saveDataDefaultsMap
53
150
  end
151
+ --- The save data manager will automatically reset variables at the appropriate times (i.e. when a
152
+ -- player enters a new room). Use this function to explicitly force the save data manager to reset a
153
+ -- specific variable group.
154
+ --
155
+ -- For example:
156
+ --
157
+ -- ```ts
158
+ -- const v = {
159
+ -- room: {
160
+ -- foo: 123,
161
+ -- },
162
+ -- };
163
+ --
164
+ -- saveDataManager("file1", v);
165
+ --
166
+ -- // Then, later on, to explicit reset all of the "room" variables:
167
+ -- saveDataManagerReset("file1", "room");
168
+ -- ```
54
169
  function ____exports.saveDataManagerReset(self, key, childObjectKey)
55
170
  errorIfFeaturesNotInitialized(nil, SAVE_DATA_MANAGER_FEATURE_NAME)
56
171
  local keyType = type(key)
@@ -7,6 +7,8 @@ local jsonDecode = ____jsonHelpers.jsonDecode
7
7
  local ____log = require("functions.log")
8
8
  local log = ____log.log
9
9
  local logError = ____log.logError
10
+ local ____table = require("functions.table")
11
+ local iterateTableDeterministically = ____table.iterateTableDeterministically
10
12
  local ____constants = require("features.saveDataManager.constants")
11
13
  local SAVE_DATA_MANAGER_DEBUG = ____constants.SAVE_DATA_MANAGER_DEBUG
12
14
  local SAVE_DATA_MANAGER_FEATURE_NAME = ____constants.SAVE_DATA_MANAGER_FEATURE_NAME
@@ -41,26 +43,28 @@ function ____exports.loadFromDisk(self, mod, oldSaveData)
41
43
  if SAVE_DATA_MANAGER_DEBUG then
42
44
  log("Converted data from the \"save#.dat\" to a Lua table.")
43
45
  end
44
- for key, value in pairs(newSaveData) do
45
- do
46
+ iterateTableDeterministically(
47
+ nil,
48
+ newSaveData,
49
+ function(____, key, value)
46
50
  if type(key) ~= "string" then
47
- goto __continue5
51
+ return
48
52
  end
49
53
  local valueType = type(value)
50
54
  if valueType ~= "table" then
51
- goto __continue5
55
+ return
52
56
  end
53
57
  local oldSaveDataForSubscriber = oldSaveData[key]
54
58
  if oldSaveDataForSubscriber == nil then
55
- goto __continue5
59
+ return
56
60
  end
57
61
  if SAVE_DATA_MANAGER_DEBUG then
58
62
  log("Merging in stored data for feature: " .. key)
59
63
  end
60
64
  merge(nil, oldSaveDataForSubscriber, value, key)
61
- end
62
- ::__continue5::
63
- end
65
+ end,
66
+ SAVE_DATA_MANAGER_DEBUG
67
+ )
64
68
  log(("The " .. SAVE_DATA_MANAGER_FEATURE_NAME) .. " loaded data from the \"save#.dat\" file.")
65
69
  end
66
70
  return ____exports
@@ -19,7 +19,9 @@ local ____log = require("functions.log")
19
19
  local logError = ____log.logError
20
20
  local ____table = require("functions.table")
21
21
  local clearTable = ____table.clearTable
22
+ local iterateTableDeterministically = ____table.iterateTableDeterministically
22
23
  local ____constants = require("features.saveDataManager.constants")
24
+ local SAVE_DATA_MANAGER_DEBUG = ____constants.SAVE_DATA_MANAGER_DEBUG
23
25
  local SAVE_DATA_MANAGER_FEATURE_NAME = ____constants.SAVE_DATA_MANAGER_FEATURE_NAME
24
26
  local ____load = require("features.saveDataManager.load")
25
27
  local loadFromDisk = ____load.loadFromDisk
@@ -64,9 +66,14 @@ function restoreDefaultsAll(self)
64
66
  restoreDefaults(nil, SaveDataKey.ROOM)
65
67
  end
66
68
  function restoreDefaults(self, saveDataKey)
67
- for subscriberName, saveData in pairs(saveDataMap) do
68
- ____exports.restoreDefaultSaveData(nil, subscriberName, saveData, saveDataKey)
69
- end
69
+ iterateTableDeterministically(
70
+ nil,
71
+ saveDataMap,
72
+ function(____, subscriberName, saveData)
73
+ ____exports.restoreDefaultSaveData(nil, subscriberName, saveData, saveDataKey)
74
+ end,
75
+ SAVE_DATA_MANAGER_DEBUG
76
+ )
70
77
  end
71
78
  function ____exports.restoreDefaultSaveData(self, subscriberName, saveData, saveDataKey)
72
79
  if not RESETTABLE_SAVE_DATA_KEYS:has(saveDataKey) then
@@ -97,6 +104,8 @@ function clearAndCopyAllElements(self, oldTable, newTable)
97
104
  end
98
105
  mod = nil
99
106
  loadedDataOnThisRun = false
107
+ ---
108
+ -- @internal
100
109
  function ____exports.saveDataManagerInit(self, incomingMod)
101
110
  mod = incomingMod
102
111
  mod:AddCallback(ModCallback.POST_PLAYER_INIT, postPlayerInit)
@@ -104,12 +113,16 @@ function ____exports.saveDataManagerInit(self, incomingMod)
104
113
  mod:AddCallback(ModCallback.POST_NEW_LEVEL, postNewLevel)
105
114
  mod:AddCallbackCustom(ModCallbackCustom.POST_NEW_ROOM_EARLY, postNewRoomEarly)
106
115
  end
116
+ ---
117
+ -- @internal
107
118
  function ____exports.forceSaveDataManagerSave(self)
108
119
  if mod == nil then
109
120
  return
110
121
  end
111
122
  saveToDisk(nil, mod, saveDataMap, saveDataConditionalFuncMap)
112
123
  end
124
+ ---
125
+ -- @internal
113
126
  function ____exports.forceSaveDataManagerLoad(self)
114
127
  if mod == nil then
115
128
  return
@@ -2,6 +2,9 @@ local ____lualib = require("lualib_bundle")
2
2
  local Map = ____lualib.Map
3
3
  local __TS__New = ____lualib.__TS__New
4
4
  local ____exports = {}
5
+ --- The save data map is indexed by subscriber name. We use Lua tables instead of TypeScriptToLua
6
+ -- Maps for the master map so that we can access the variables via the in-game console when
7
+ -- debugging. (TSTL Maps don't expose the map keys as normal keys.)
5
8
  ____exports.saveDataMap = {}
6
9
  ____exports.saveDataDefaultsMap = {}
7
10
  ____exports.saveDataConditionalFuncMap = __TS__New(Map)
@@ -1,6 +1,5 @@
1
1
  local ____lualib = require("lualib_bundle")
2
2
  local Map = ____lualib.Map
3
- local __TS__InstanceOf = ____lualib.__TS__InstanceOf
4
3
  local Set = ____lualib.Set
5
4
  local ____exports = {}
6
5
  local mergeArray, mergeTSTLObject, mergeTable
@@ -19,12 +18,36 @@ local deserializeIsaacAPIClass = ____serialization.deserializeIsaacAPIClass
19
18
  local isSerializedIsaacAPIClass = ____serialization.isSerializedIsaacAPIClass
20
19
  local ____table = require("functions.table")
21
20
  local clearTable = ____table.clearTable
21
+ local iterateTableDeterministically = ____table.iterateTableDeterministically
22
+ local ____tstlClass = require("functions.tstlClass")
23
+ local isTSTLMap = ____tstlClass.isTSTLMap
24
+ local isTSTLSet = ____tstlClass.isTSTLSet
22
25
  local ____utils = require("functions.utils")
23
26
  local getTraversalDescription = ____utils.getTraversalDescription
24
27
  local ____constants = require("features.saveDataManager.constants")
25
28
  local SAVE_DATA_MANAGER_DEBUG = ____constants.SAVE_DATA_MANAGER_DEBUG
26
29
  local ____serializationBrand = require("features.saveDataManager.serializationBrand")
27
30
  local isSerializationBrand = ____serializationBrand.isSerializationBrand
31
+ --- `merge` takes the values from a new table and recursively merges them into an old object (while
32
+ -- performing appropriate deserialization).
33
+ --
34
+ -- It supports the following object types:
35
+ --
36
+ -- - `LuaTable` / basic TSTL objects
37
+ -- - TSTL `Map`
38
+ -- - TSTL `Set`
39
+ -- - TSTL classes
40
+ -- - `DefaultMap`
41
+ -- - Isaac `Color` objects
42
+ -- - Isaac `KColor` objects
43
+ -- - Isaac `RNG` objects
44
+ -- - Isaac `Vector` objects
45
+ --
46
+ -- Since it is common for a variable to have a type of `something | null`, we must iterate over the
47
+ -- new object and copy over all of the values. (A value of null transpiles to nil, which means the
48
+ -- table key does not exist.) The consequence of this is that it can copy over old variables that
49
+ -- are no longer used in the code, or copy over old variables of a different type, which can cause
50
+ -- run-time errors. In such cases, users will have to manually delete their save data.
28
51
  function ____exports.merge(self, oldObject, newTable, traversalDescription)
29
52
  if SAVE_DATA_MANAGER_DEBUG then
30
53
  log("merge is traversing: " .. traversalDescription)
@@ -42,7 +65,7 @@ function ____exports.merge(self, oldObject, newTable, traversalDescription)
42
65
  mergeArray(nil, oldTable, newTable)
43
66
  return
44
67
  end
45
- if __TS__InstanceOf(oldObject, Map) or __TS__InstanceOf(oldObject, Set) then
68
+ if isTSTLMap(nil, oldObject) or isTSTLSet(nil, oldObject) then
46
69
  mergeTSTLObject(nil, oldObject, newTable, traversalDescription)
47
70
  else
48
71
  mergeTable(nil, oldObject, newTable, traversalDescription)
@@ -50,27 +73,34 @@ function ____exports.merge(self, oldObject, newTable, traversalDescription)
50
73
  end
51
74
  function mergeArray(self, oldArray, newArray)
52
75
  clearTable(nil, oldArray)
53
- for key, value in pairs(newArray) do
54
- oldArray[key] = value
55
- end
76
+ iterateTableDeterministically(
77
+ nil,
78
+ newArray,
79
+ function(____, key, value)
80
+ oldArray[key] = value
81
+ end,
82
+ SAVE_DATA_MANAGER_DEBUG
83
+ )
56
84
  end
57
85
  function mergeTSTLObject(self, oldObject, newTable, traversalDescription)
58
86
  oldObject:clear()
59
87
  local convertStringKeysToNumbers = newTable[SerializationBrand.OBJECT_WITH_NUMBER_KEYS] ~= nil
60
- for key, value in pairs(newTable) do
61
- do
88
+ iterateTableDeterministically(
89
+ nil,
90
+ newTable,
91
+ function(____, key, value)
62
92
  if isSerializationBrand(nil, key) then
63
- goto __continue12
93
+ return
64
94
  end
65
95
  local keyToUse = key
66
96
  if convertStringKeysToNumbers then
67
97
  local numberKey = tonumber(key)
68
98
  if numberKey == nil then
69
- goto __continue12
99
+ return
70
100
  end
71
101
  keyToUse = numberKey
72
102
  end
73
- if __TS__InstanceOf(oldObject, Map) then
103
+ if isTSTLMap(nil, oldObject) then
74
104
  local valueType = type(value)
75
105
  local valueCopy
76
106
  if valueType == "table" then
@@ -79,22 +109,24 @@ function mergeTSTLObject(self, oldObject, newTable, traversalDescription)
79
109
  valueCopy = value
80
110
  end
81
111
  oldObject:set(keyToUse, valueCopy)
82
- elseif __TS__InstanceOf(oldObject, Set) then
112
+ elseif isTSTLSet(nil, oldObject) then
83
113
  oldObject:add(keyToUse)
84
114
  end
85
- end
86
- ::__continue12::
87
- end
115
+ end,
116
+ SAVE_DATA_MANAGER_DEBUG
117
+ )
88
118
  end
89
119
  function mergeTable(self, oldTable, newTable, traversalDescription)
90
- for key, value in pairs(newTable) do
91
- do
120
+ iterateTableDeterministically(
121
+ nil,
122
+ newTable,
123
+ function(____, key, value)
92
124
  if SAVE_DATA_MANAGER_DEBUG then
93
125
  local valueToPrint = value == "" and "(empty string)" or tostring(value)
94
126
  log((("merge is merging: " .. traversalDescription) .. " --> ") .. valueToPrint)
95
127
  end
96
128
  if isSerializationBrand(nil, key) then
97
- goto __continue21
129
+ return
98
130
  end
99
131
  if isSerializedIsaacAPIClass(nil, value) then
100
132
  if SAVE_DATA_MANAGER_DEBUG then
@@ -102,7 +134,7 @@ function mergeTable(self, oldTable, newTable, traversalDescription)
102
134
  end
103
135
  local deserializedObject = deserializeIsaacAPIClass(nil, value)
104
136
  oldTable[key] = deserializedObject
105
- goto __continue21
137
+ return
106
138
  end
107
139
  local valueType = type(value)
108
140
  if valueType == "table" then
@@ -117,8 +149,8 @@ function mergeTable(self, oldTable, newTable, traversalDescription)
117
149
  else
118
150
  oldTable[key] = value
119
151
  end
120
- end
121
- ::__continue21::
122
- end
152
+ end,
153
+ SAVE_DATA_MANAGER_DEBUG
154
+ )
123
155
  end
124
156
  return ____exports
@@ -11,28 +11,33 @@ local ____jsonHelpers = require("functions.jsonHelpers")
11
11
  local jsonEncode = ____jsonHelpers.jsonEncode
12
12
  local ____log = require("functions.log")
13
13
  local log = ____log.log
14
+ local ____table = require("functions.table")
15
+ local iterateTableDeterministically = ____table.iterateTableDeterministically
14
16
  local ____constants = require("features.saveDataManager.constants")
17
+ local SAVE_DATA_MANAGER_DEBUG = ____constants.SAVE_DATA_MANAGER_DEBUG
15
18
  local SAVE_DATA_MANAGER_FEATURE_NAME = ____constants.SAVE_DATA_MANAGER_FEATURE_NAME
16
19
  function getAllSaveDataToWriteToDisk(self, saveDataMap, saveDataConditionalFuncMap)
17
20
  local allSaveData = {}
18
- for subscriberName, saveData in pairs(saveDataMap) do
19
- do
21
+ iterateTableDeterministically(
22
+ nil,
23
+ saveDataMap,
24
+ function(____, subscriberName, saveData)
20
25
  local conditionalFunc = saveDataConditionalFuncMap:get(subscriberName)
21
26
  if conditionalFunc ~= nil then
22
27
  local shouldSave = conditionalFunc(nil)
23
28
  if not shouldSave then
24
- goto __continue4
29
+ return
25
30
  end
26
31
  end
27
32
  local saveDataWithoutRoom = {persistent = saveData.persistent, run = saveData.run, level = saveData.level}
28
33
  if #__TS__ObjectKeys(saveDataWithoutRoom) == 0 then
29
- goto __continue4
34
+ return
30
35
  end
31
36
  local saveDataCopy = deepCopy(nil, saveDataWithoutRoom, SerializationType.SERIALIZE, subscriberName)
32
37
  allSaveData[subscriberName] = saveDataCopy
33
- end
34
- ::__continue4::
35
- end
38
+ end,
39
+ SAVE_DATA_MANAGER_DEBUG
40
+ )
36
41
  return allSaveData
37
42
  end
38
43
  function ____exports.saveToDisk(self, mod, saveDataMap, saveDataConditionalFuncMap)