isaacscript-common 6.6.1-dev.1 → 6.6.1-dev.2

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 (412) hide show
  1. package/cachedClasses.d.ts +1 -0
  2. package/cachedClasses.js +59 -0
  3. package/callbacks/customRevive.js +153 -0
  4. package/callbacks/itemPickup.js +64 -0
  5. package/callbacks/postAmbush.js +54 -0
  6. package/callbacks/postBombExploded.js +20 -0
  7. package/callbacks/postBombInitLate.js +28 -0
  8. package/callbacks/postBoneSwing.js +49 -0
  9. package/callbacks/postCollectibleEmpty.js +32 -0
  10. package/callbacks/postCollectibleInitFirst.js +27 -0
  11. package/callbacks/postCursedTeleport.js +120 -0
  12. package/callbacks/postCustomDoorEnter.js +205 -0
  13. package/callbacks/postDiceRoomActivated.js +39 -0
  14. package/callbacks/postDoorRender.js +20 -0
  15. package/callbacks/postDoorUpdate.js +20 -0
  16. package/callbacks/postEffectInitLate.js +28 -0
  17. package/callbacks/postEffectStateChanged.js +31 -0
  18. package/callbacks/postEsauJr.js +70 -0
  19. package/callbacks/postFamiliarInitLate.js +28 -0
  20. package/callbacks/postFamiliarStateChanged.js +31 -0
  21. package/callbacks/postFlip.js +59 -0
  22. package/callbacks/postGreedModeWave.js +31 -0
  23. package/callbacks/postGridEntity.js +107 -0
  24. package/callbacks/postGridEntityCollision.js +49 -0
  25. package/callbacks/postGridEntityRender.js +20 -0
  26. package/callbacks/postHolyMantleRemoved.js +33 -0
  27. package/callbacks/postItemDischarged.js +94 -0
  28. package/callbacks/postKnifeInitLate.js +28 -0
  29. package/callbacks/postLaserInitLate.js +28 -0
  30. package/callbacks/postNPCInitLate.js +28 -0
  31. package/callbacks/postNPCStateChanged.js +31 -0
  32. package/callbacks/postNewRoomEarly.js +69 -0
  33. package/callbacks/postPickupCollect.js +37 -0
  34. package/callbacks/postPickupInitFirst.js +52 -0
  35. package/callbacks/postPickupInitLate.js +28 -0
  36. package/callbacks/postPickupStateChanged.js +31 -0
  37. package/callbacks/postPitRender.js +20 -0
  38. package/callbacks/postPitUpdate.js +20 -0
  39. package/callbacks/postPlayerChangeHealth.js +43 -0
  40. package/callbacks/postPlayerChangeType.js +31 -0
  41. package/callbacks/postPlayerCollectible.js +74 -0
  42. package/callbacks/postPlayerFatalDamage.js +74 -0
  43. package/callbacks/postPlayerInitLate.js +28 -0
  44. package/callbacks/postPlayerReordered.js +109 -0
  45. package/callbacks/postPoopRender.js +20 -0
  46. package/callbacks/postPoopUpdate.js +20 -0
  47. package/callbacks/postPressurePlateRender.js +20 -0
  48. package/callbacks/postPressurePlateUpdate.js +20 -0
  49. package/callbacks/postProjectileInitLate.js +28 -0
  50. package/callbacks/postPurchase.js +39 -0
  51. package/callbacks/postRockRender.js +20 -0
  52. package/callbacks/postRockUpdate.js +20 -0
  53. package/callbacks/postRoomClearChanged.js +41 -0
  54. package/callbacks/postSacrifice.js +38 -0
  55. package/callbacks/postSlotDestroyed.js +64 -0
  56. package/callbacks/postSlotInitUpdate.js +49 -0
  57. package/callbacks/postSlotRender.js +48 -0
  58. package/callbacks/postSpikesRender.js +20 -0
  59. package/callbacks/postSpikesUpdate.js +20 -0
  60. package/callbacks/postTNTRender.js +20 -0
  61. package/callbacks/postTNTUpdate.js +20 -0
  62. package/callbacks/postTearInitLate.js +28 -0
  63. package/callbacks/postTearInitVeryLate.js +32 -0
  64. package/callbacks/postTransformation.js +37 -0
  65. package/callbacks/postTrinketBreak.js +64 -0
  66. package/callbacks/preBerserkDeath.js +35 -0
  67. package/callbacks/preNewLevel.js +45 -0
  68. package/callbacks/reorderedCallbacks.js +136 -0
  69. package/callbacks/subscriptions/postAmbushFinished.js +20 -0
  70. package/callbacks/subscriptions/postAmbushStarted.js +20 -0
  71. package/callbacks/subscriptions/postBombInitLate.js +20 -0
  72. package/callbacks/subscriptions/postBoneExploded.js +20 -0
  73. package/callbacks/subscriptions/postBoneSwing.js +16 -0
  74. package/callbacks/subscriptions/postCollectibleEmpty.js +21 -0
  75. package/callbacks/subscriptions/postCollectibleInitFirst.js +21 -0
  76. package/callbacks/subscriptions/postCursedTeleport.js +16 -0
  77. package/callbacks/subscriptions/postCustomDoorEnter.js +21 -0
  78. package/callbacks/subscriptions/postCustomRevive.js +21 -0
  79. package/callbacks/subscriptions/postDiceRoomActivated.js +21 -0
  80. package/callbacks/subscriptions/postDoorRender.js +22 -0
  81. package/callbacks/subscriptions/postDoorUpdate.js +22 -0
  82. package/callbacks/subscriptions/postEffectInitLate.js +20 -0
  83. package/callbacks/subscriptions/postEffectStateChanged.js +20 -0
  84. package/callbacks/subscriptions/postEsauJr.js +16 -0
  85. package/callbacks/subscriptions/postFamiliarInitLate.js +20 -0
  86. package/callbacks/subscriptions/postFamiliarStateChanged.js +20 -0
  87. package/callbacks/subscriptions/postFirstEsauJr.js +16 -0
  88. package/callbacks/subscriptions/postFirstFlip.js +16 -0
  89. package/callbacks/subscriptions/postFlip.js +16 -0
  90. package/callbacks/subscriptions/postGameStartedReordered.js +16 -0
  91. package/callbacks/subscriptions/postGreedModeWave.js +16 -0
  92. package/callbacks/subscriptions/postGridEntityBroken.js +28 -0
  93. package/callbacks/subscriptions/postGridEntityCollision.js +28 -0
  94. package/callbacks/subscriptions/postGridEntityInit.js +28 -0
  95. package/callbacks/subscriptions/postGridEntityRemove.js +26 -0
  96. package/callbacks/subscriptions/postGridEntityRender.js +28 -0
  97. package/callbacks/subscriptions/postGridEntityStateChanged.js +28 -0
  98. package/callbacks/subscriptions/postGridEntityUpdate.js +28 -0
  99. package/callbacks/subscriptions/postHolyMantleRemoved.js +25 -0
  100. package/callbacks/subscriptions/postItemDischarged.js +21 -0
  101. package/callbacks/subscriptions/postItemPickup.js +25 -0
  102. package/callbacks/subscriptions/postKnifeInitLate.js +20 -0
  103. package/callbacks/subscriptions/postLaserInitLate.js +20 -0
  104. package/callbacks/subscriptions/postNPCInitLate.js +20 -0
  105. package/callbacks/subscriptions/postNPCStateChanged.js +24 -0
  106. package/callbacks/subscriptions/postNewLevelReordered.js +16 -0
  107. package/callbacks/subscriptions/postNewRoomEarly.js +16 -0
  108. package/callbacks/subscriptions/postNewRoomReordered.js +16 -0
  109. package/callbacks/subscriptions/postPEffectUpdateReordered.js +25 -0
  110. package/callbacks/subscriptions/postPickupCollect.js +20 -0
  111. package/callbacks/subscriptions/postPickupInitFirst.js +20 -0
  112. package/callbacks/subscriptions/postPickupInitLate.js +20 -0
  113. package/callbacks/subscriptions/postPickupStateChanged.js +20 -0
  114. package/callbacks/subscriptions/postPitRender.js +22 -0
  115. package/callbacks/subscriptions/postPitUpdate.js +22 -0
  116. package/callbacks/subscriptions/postPlayerChangeHealth.js +25 -0
  117. package/callbacks/subscriptions/postPlayerChangeType.js +20 -0
  118. package/callbacks/subscriptions/postPlayerCollectibleAdded.js +21 -0
  119. package/callbacks/subscriptions/postPlayerCollectibleRemoved.js +21 -0
  120. package/callbacks/subscriptions/postPlayerFatalDamage.js +29 -0
  121. package/callbacks/subscriptions/postPlayerInitLate.js +25 -0
  122. package/callbacks/subscriptions/postPlayerInitReordered.js +25 -0
  123. package/callbacks/subscriptions/postPlayerRenderReordered.js +25 -0
  124. package/callbacks/subscriptions/postPlayerUpdateReordered.js +25 -0
  125. package/callbacks/subscriptions/postPoopRender.js +22 -0
  126. package/callbacks/subscriptions/postPoopUpdate.js +22 -0
  127. package/callbacks/subscriptions/postPressurePlateRender.js +22 -0
  128. package/callbacks/subscriptions/postPressurePlateUpdate.js +22 -0
  129. package/callbacks/subscriptions/postProjectileInitLate.js +21 -0
  130. package/callbacks/subscriptions/postPurchase.js +16 -0
  131. package/callbacks/subscriptions/postRockRender.js +22 -0
  132. package/callbacks/subscriptions/postRockUpdate.js +22 -0
  133. package/callbacks/subscriptions/postRoomClearChanged.js +20 -0
  134. package/callbacks/subscriptions/postSacrifice.js +25 -0
  135. package/callbacks/subscriptions/postSlotAnimationChanged.js +20 -0
  136. package/callbacks/subscriptions/postSlotDestroyed.js +26 -0
  137. package/callbacks/subscriptions/postSlotInit.js +20 -0
  138. package/callbacks/subscriptions/postSlotRender.js +20 -0
  139. package/callbacks/subscriptions/postSlotUpdate.js +20 -0
  140. package/callbacks/subscriptions/postSpikesRender.js +22 -0
  141. package/callbacks/subscriptions/postSpikesUpdate.js +22 -0
  142. package/callbacks/subscriptions/postTNTRender.js +22 -0
  143. package/callbacks/subscriptions/postTNTUpdate.js +22 -0
  144. package/callbacks/subscriptions/postTearInitLate.js +20 -0
  145. package/callbacks/subscriptions/postTearInitVeryLate.js +20 -0
  146. package/callbacks/subscriptions/postTransformation.js +20 -0
  147. package/callbacks/subscriptions/postTrinketBreak.js +21 -0
  148. package/callbacks/subscriptions/preBerserkDeath.js +26 -0
  149. package/callbacks/subscriptions/preCustomRevive.js +29 -0
  150. package/callbacks/subscriptions/preItemPickup.js +25 -0
  151. package/callbacks/subscriptions/preNewLevel.js +16 -0
  152. package/classes/DefaultMap.js +145 -0
  153. package/classes/ModUpgraded.js +57 -0
  154. package/constants.js +143 -0
  155. package/constantsFirstLast.js +156 -0
  156. package/enums/AmbushType.js +6 -0
  157. package/enums/CornerType.js +8 -0
  158. package/enums/DecorationVariant.js +11 -0
  159. package/enums/HealthType.js +18 -0
  160. package/enums/ModCallbackCustom.js +1213 -0
  161. package/enums/PocketItemType.js +10 -0
  162. package/enums/RockAltType.js +9 -0
  163. package/enums/SerializationType.js +7 -0
  164. package/enums/SlotDestructionType.js +6 -0
  165. package/enums/private/CopyableIsaacAPIClassType.js +9 -0
  166. package/enums/private/SaveDataKey.js +8 -0
  167. package/enums/private/SerializationBrand.js +41 -0
  168. package/features/characterHealthConversion.js +86 -0
  169. package/features/characterStats.js +52 -0
  170. package/features/collectibleItemPoolType.js +45 -0
  171. package/features/customGridEntity.js +148 -0
  172. package/features/customStage/backdrop.js +191 -0
  173. package/features/customStage/customStageConstants.js +2 -0
  174. package/features/customStage/exports.js +147 -0
  175. package/features/customStage/gridEntities.js +138 -0
  176. package/features/customStage/init.js +104 -0
  177. package/features/customStage/metadata.json +1 -0
  178. package/features/customStage/shadows.js +63 -0
  179. package/features/customStage/streakText.js +35 -0
  180. package/features/customStage/util.js +36 -0
  181. package/features/customStage/v.js +18 -0
  182. package/features/customStage/versusScreen.js +184 -0
  183. package/features/debugDisplay/debugDisplay.js +183 -0
  184. package/features/debugDisplay/exports.js +441 -0
  185. package/features/debugDisplay/v.d.ts +18 -0
  186. package/features/debugDisplay/v.js +61 -0
  187. package/features/deployJSONRoom.js +532 -0
  188. package/features/disableAllSound.js +63 -0
  189. package/features/disableInputs.js +130 -0
  190. package/features/extraConsoleCommands/commandsDisplay.js +236 -0
  191. package/features/extraConsoleCommands/commandsSubroutines.js +109 -0
  192. package/features/extraConsoleCommands/exports.js +53 -0
  193. package/features/extraConsoleCommands/init.js +239 -0
  194. package/features/extraConsoleCommands/listCommands.js +1081 -0
  195. package/features/extraConsoleCommands/v.js +25 -0
  196. package/features/fadeInRemover.js +51 -0
  197. package/features/fastReset.js +61 -0
  198. package/features/forgottenSwitch.js +33 -0
  199. package/features/pause.js +68 -0
  200. package/features/persistentEntities.js +120 -0
  201. package/features/playerInventory.js +89 -0
  202. package/features/ponyDetection.js +63 -0
  203. package/features/preventCollectibleRotation.js +81 -0
  204. package/features/registerHotkey.js +91 -0
  205. package/features/roomClearFrame.js +42 -0
  206. package/features/runInNFrames.js +189 -0
  207. package/features/runNextRoom.js +34 -0
  208. package/features/saveDataManager/exports.js +183 -0
  209. package/features/saveDataManager/load.js +69 -0
  210. package/features/saveDataManager/main.js +131 -0
  211. package/features/saveDataManager/maps.js +9 -0
  212. package/features/saveDataManager/merge.js +139 -0
  213. package/features/saveDataManager/save.js +43 -0
  214. package/features/saveDataManager/saveDataManagerConstants.js +4 -0
  215. package/features/saveDataManager/serializationBrand.js +12 -0
  216. package/features/sirenHelpers.js +90 -0
  217. package/features/stageHistory.js +43 -0
  218. package/features/taintedLazarusPlayers.js +92 -0
  219. package/featuresInitialized.js +16 -0
  220. package/functions/ambush.js +35 -0
  221. package/functions/array.js +423 -0
  222. package/functions/benchmark.js +28 -0
  223. package/functions/bitwise.js +74 -0
  224. package/functions/bombs.js +11 -0
  225. package/functions/boss.js +137 -0
  226. package/functions/cacheFlag.js +11 -0
  227. package/functions/cards.js +217 -0
  228. package/functions/challenges.js +9 -0
  229. package/functions/character.js +102 -0
  230. package/functions/charge.js +202 -0
  231. package/functions/chargeBar.js +44 -0
  232. package/functions/collectibleCacheFlag.js +68 -0
  233. package/functions/collectibleSet.js +108 -0
  234. package/functions/collectibleTag.js +65 -0
  235. package/functions/collectibles.js +469 -0
  236. package/functions/color.d.ts +1 -1
  237. package/functions/color.js +60 -0
  238. package/functions/debug.js +60 -0
  239. package/functions/deepCopy.js +361 -0
  240. package/functions/deepCopyTests.js +308 -0
  241. package/functions/direction.js +41 -0
  242. package/functions/doors.js +326 -0
  243. package/functions/easing.js +142 -0
  244. package/functions/eden.js +32 -0
  245. package/functions/effects.js +11 -0
  246. package/functions/entity.js +324 -0
  247. package/functions/entitySpecific.js +481 -0
  248. package/functions/entityTypes.js +6 -0
  249. package/functions/enums.js +151 -0
  250. package/functions/familiars.js +85 -0
  251. package/functions/flag.js +137 -0
  252. package/functions/flying.js +88 -0
  253. package/functions/globals.js +230 -0
  254. package/functions/gridEntity.js +488 -0
  255. package/functions/gridEntitySpecific.js +109 -0
  256. package/functions/input.js +95 -0
  257. package/functions/isaacAPIClass.js +48 -0
  258. package/functions/jsonHelpers.js +40 -0
  259. package/functions/jsonRoom.js +132 -0
  260. package/functions/kColor.d.ts +1 -1
  261. package/functions/kColor.js +63 -0
  262. package/functions/language.js +13 -0
  263. package/functions/level.js +20 -0
  264. package/functions/log.js +567 -0
  265. package/functions/map.js +45 -0
  266. package/functions/math.js +103 -0
  267. package/functions/mergeTests.js +213 -0
  268. package/functions/minimap.js +80 -0
  269. package/functions/nextStage.js +290 -0
  270. package/functions/npc.js +101 -0
  271. package/functions/pickupVariants.js +47 -0
  272. package/functions/pickups.js +219 -0
  273. package/functions/pills.js +160 -0
  274. package/functions/player.js +808 -0
  275. package/functions/playerCenter.js +50 -0
  276. package/functions/playerDataStructures.js +114 -0
  277. package/functions/playerHealth.js +321 -0
  278. package/functions/playerIndex.js +160 -0
  279. package/functions/pocketItems.js +124 -0
  280. package/functions/positionVelocity.js +136 -0
  281. package/functions/random.js +73 -0
  282. package/functions/revive.js +140 -0
  283. package/functions/rng.d.ts +1 -1
  284. package/functions/rng.js +117 -0
  285. package/functions/roomData.js +174 -0
  286. package/functions/roomGrid.js +81 -0
  287. package/functions/roomShape.js +99 -0
  288. package/functions/rooms.js +487 -0
  289. package/functions/run.js +53 -0
  290. package/functions/saveFile.js +104 -0
  291. package/functions/seeds.js +18 -0
  292. package/functions/serialization.js +52 -0
  293. package/functions/set.js +99 -0
  294. package/functions/sound.js +9 -0
  295. package/functions/spawnCollectible.js +66 -0
  296. package/functions/sprite.js +80 -0
  297. package/functions/stage.js +172 -0
  298. package/functions/string.js +37 -0
  299. package/functions/table.js +143 -0
  300. package/functions/tears.js +31 -0
  301. package/functions/transformations.js +101 -0
  302. package/functions/trinketCacheFlag.js +46 -0
  303. package/functions/trinketGive.js +121 -0
  304. package/functions/trinkets.js +169 -0
  305. package/functions/tstlClass.js +125 -0
  306. package/functions/types.js +27 -0
  307. package/functions/ui.js +124 -0
  308. package/functions/utils.js +172 -0
  309. package/functions/vector.js +68 -0
  310. package/index.js +140 -0
  311. package/initCustomCallbacks.js +133 -0
  312. package/initFeatures.js +51 -0
  313. package/interfaces/AddCallbackParameterCustom.js +2 -0
  314. package/interfaces/ChargeBarSprites.js +2 -0
  315. package/interfaces/Corner.js +2 -0
  316. package/interfaces/CustomGridEntityData.js +2 -0
  317. package/interfaces/CustomStage.js +2 -0
  318. package/interfaces/CustomStageLua.js +13 -0
  319. package/interfaces/JSONRoomsFile.js +2 -0
  320. package/interfaces/PlayerHealth.js +2 -0
  321. package/interfaces/PocketItemDescription.js +2 -0
  322. package/interfaces/SaveData.js +2 -0
  323. package/interfaces/TrinketSituation.js +2 -0
  324. package/interfaces/private/TSTLClassMetatable.js +2 -0
  325. package/maps/PHDPillConversions.js +20 -0
  326. package/maps/cardMap.js +208 -0
  327. package/maps/characterMap.js +86 -0
  328. package/maps/collectibleDescriptionMap.js +728 -0
  329. package/maps/collectibleNameMap.js +727 -0
  330. package/maps/defaultPlayerStatMap.js +14 -0
  331. package/maps/falsePHDPillConversions.js +34 -0
  332. package/maps/gridEntityTypeToBrokenStateMap.js +29 -0
  333. package/maps/gridEntityXMLMap.js +128 -0
  334. package/maps/pillEffectMap.js +88 -0
  335. package/maps/roomShapeToTopLeftWallGridIndexMap.js +14 -0
  336. package/maps/roomTypeMap.js +39 -0
  337. package/maps/trinketDescriptionMap.js +196 -0
  338. package/maps/trinketNameMap.js +195 -0
  339. package/objects/LRoomShapeToRectangles.js +33 -0
  340. package/objects/backdropTypeToRockAltType.js +66 -0
  341. package/objects/bossNamePNGFileNames.js +112 -0
  342. package/objects/bossPortraitPNGFileNames.js +115 -0
  343. package/objects/callbackRegisterFunctions.js +170 -0
  344. package/objects/cardDescriptions.js +104 -0
  345. package/objects/cardNames.js +104 -0
  346. package/objects/cardTypes.js +103 -0
  347. package/objects/challengeNames.js +51 -0
  348. package/objects/characterNames.js +46 -0
  349. package/objects/coinSubTypeToValue.js +13 -0
  350. package/objects/colors.d.ts +1 -0
  351. package/objects/colors.js +24 -0
  352. package/objects/directionNames.js +9 -0
  353. package/objects/directionToDegrees.js +9 -0
  354. package/objects/directionToVector.js +10 -0
  355. package/objects/doorSlotFlagToDoorSlot.js +13 -0
  356. package/objects/doorSlotToDirection.js +13 -0
  357. package/objects/doorSlotToDoorSlotFlag.js +13 -0
  358. package/objects/isaacAPIClassTypeToBrand.js +9 -0
  359. package/objects/isaacAPIClassTypeToCopyFunction.js +12 -0
  360. package/objects/languageNames.js +11 -0
  361. package/objects/oppositeDoorSlots.js +13 -0
  362. package/objects/pillEffectClasses.js +56 -0
  363. package/objects/pillEffectNames.js +55 -0
  364. package/objects/pillEffectTypes.js +55 -0
  365. package/objects/playerNamePNGFileNames.js +55 -0
  366. package/objects/playerPortraitPNGFileNames.js +52 -0
  367. package/objects/roomShapeBounds.js +46 -0
  368. package/objects/roomShapeCorners.js +268 -0
  369. package/objects/roomShapeLayoutSizes.js +39 -0
  370. package/objects/roomShapeToBottomRightPosition.js +22 -0
  371. package/objects/roomShapeToDoorSlotCoordinates.js +109 -0
  372. package/objects/roomShapeToDoorSlots.js +69 -0
  373. package/objects/roomShapeToDoorSlotsToGridIndexDelta.js +113 -0
  374. package/objects/roomShapeToGridWidth.js +18 -0
  375. package/objects/roomShapeToTopLeftPosition.js +23 -0
  376. package/objects/roomShapeVolumes.js +30 -0
  377. package/objects/roomTypeGotoPrefixes.js +33 -0
  378. package/objects/roomTypeNames.js +34 -0
  379. package/objects/serializedIsaacAPIClassTypeToIdentityFunction.js +12 -0
  380. package/objects/stageTypeSuffixes.js +10 -0
  381. package/objects/stageTypeToLetter.js +12 -0
  382. package/objects/transformationNames.js +18 -0
  383. package/objects/versusScreenBackgroundColors.js +36 -0
  384. package/objects/versusScreenDirtSpotColors.js +36 -0
  385. package/package.json +1 -1
  386. package/patchErrorFunctions.js +67 -0
  387. package/sets/LRoomShapesSet.js +8 -0
  388. package/sets/bossSets.js +374 -0
  389. package/sets/charactersThatStartWithAnActiveItemSet.js +15 -0
  390. package/sets/charactersWithBlackHeartFromEternalHeartSet.js +6 -0
  391. package/sets/charactersWithFreeDevilDealsSet.js +3 -0
  392. package/sets/charactersWithNoRedHeartsSet.js +16 -0
  393. package/sets/charactersWithNoSoulHeartsSet.js +13 -0
  394. package/sets/chestPickupVariantsSet.js +16 -0
  395. package/sets/consoleCommandsSet.js +61 -0
  396. package/sets/familiarsThatShootPlayerTearsSet.js +12 -0
  397. package/sets/lostStyleCharactersSet.js +13 -0
  398. package/sets/mineShaftRoomSubTypesSet.js +9 -0
  399. package/sets/narrowRoomShapesSet.js +8 -0
  400. package/sets/redHeartSubTypesSet.js +7 -0
  401. package/sets/sinEntityTypesSet.js +11 -0
  402. package/sets/singleUseActiveCollectibleTypesSet.js +12 -0
  403. package/sets/storyBossesSet.js +17 -0
  404. package/shaderCrashFix.js +17 -0
  405. package/types/AnyEntity.js +2 -0
  406. package/types/CollectibleIndex.js +2 -0
  407. package/types/PickingUpItem.js +38 -0
  408. package/types/PlayerIndex.js +2 -0
  409. package/types/private/IsaacAPIClass.js +2 -0
  410. package/types/private/SerializedIsaacAPIClass.js +2 -0
  411. package/types/private/TSTLClass.js +2 -0
  412. package/upgradeMod.js +47 -0
@@ -0,0 +1,131 @@
1
+ import { ModCallback } from "isaac-typescript-definitions";
2
+ import { game } from "../../cachedClasses";
3
+ import { ModCallbackCustom } from "../../enums/ModCallbackCustom";
4
+ import { SaveDataKey } from "../../enums/private/SaveDataKey";
5
+ import { SerializationType } from "../../enums/SerializationType";
6
+ import { deepCopy } from "../../functions/deepCopy";
7
+ import { logError } from "../../functions/log";
8
+ import { clearTable, iterateTableInOrder } from "../../functions/table";
9
+ import { loadFromDisk } from "./load";
10
+ import { saveDataConditionalFuncMap, saveDataDefaultsMap, saveDataMap, } from "./maps";
11
+ import { saveToDisk } from "./save";
12
+ import { SAVE_DATA_MANAGER_DEBUG, SAVE_DATA_MANAGER_FEATURE_NAME, } from "./saveDataManagerConstants";
13
+ const RESETTABLE_SAVE_DATA_KEYS = new Set([
14
+ SaveDataKey.RUN,
15
+ SaveDataKey.LEVEL,
16
+ SaveDataKey.ROOM,
17
+ ]);
18
+ let mod = null;
19
+ let loadedDataOnThisRun = false;
20
+ /** @internal */
21
+ export function saveDataManagerInit(incomingMod) {
22
+ mod = incomingMod;
23
+ mod.AddCallback(ModCallback.POST_PLAYER_INIT, postPlayerInit); // 9
24
+ mod.AddCallback(ModCallback.PRE_GAME_EXIT, preGameExit); // 17
25
+ mod.AddCallback(ModCallback.POST_NEW_LEVEL, postNewLevel); // 18
26
+ mod.AddCallbackCustom(ModCallbackCustom.POST_NEW_ROOM_EARLY, postNewRoomEarly); // 19
27
+ }
28
+ // ModCallback.POST_PLAYER_INIT (9)
29
+ function postPlayerInit() {
30
+ if (mod === null) {
31
+ error(`The mod for the ${SAVE_DATA_MANAGER_FEATURE_NAME} was not initialized.`);
32
+ }
33
+ if (loadedDataOnThisRun) {
34
+ return;
35
+ }
36
+ loadedDataOnThisRun = true;
37
+ // We want to unconditionally load save data on every new run since there might be persistent data
38
+ // that is not tied to an individual run.
39
+ loadFromDisk(mod, saveDataMap);
40
+ const gameFrameCount = game.GetFrameCount();
41
+ const isContinued = gameFrameCount !== 0;
42
+ if (!isContinued) {
43
+ restoreDefaultsAll();
44
+ }
45
+ // On continued runs, the PostNewLevel callback will not fire, so we do not have to worry about
46
+ // saved data based on level getting overwritten.
47
+ }
48
+ // ModCallback.PRE_GAME_EXIT (17)
49
+ function preGameExit() {
50
+ if (mod === null) {
51
+ error(`The mod for the ${SAVE_DATA_MANAGER_FEATURE_NAME} was not initialized.`);
52
+ }
53
+ // We unconditionally save variables to disk (because regardless of a save & quit or a death,
54
+ // persistent variables should be recorded).
55
+ saveToDisk(mod, saveDataMap, saveDataConditionalFuncMap);
56
+ restoreDefaultsAll();
57
+ loadedDataOnThisRun = false;
58
+ }
59
+ // ModCallback.POST_NEW_LEVEL (18)
60
+ function postNewLevel() {
61
+ restoreDefaults(SaveDataKey.LEVEL);
62
+ }
63
+ // ModCallbackCustom.POST_NEW_ROOM_EARLY
64
+ function postNewRoomEarly() {
65
+ restoreDefaults(SaveDataKey.ROOM);
66
+ }
67
+ function restoreDefaultsAll() {
68
+ restoreDefaults(SaveDataKey.RUN);
69
+ restoreDefaults(SaveDataKey.LEVEL);
70
+ restoreDefaults(SaveDataKey.ROOM);
71
+ }
72
+ function restoreDefaults(saveDataKey) {
73
+ iterateTableInOrder(saveDataMap, (subscriberName, saveData) => {
74
+ restoreDefaultSaveData(subscriberName, saveData, saveDataKey);
75
+ }, SAVE_DATA_MANAGER_DEBUG);
76
+ }
77
+ export function restoreDefaultSaveData(subscriberName, saveData, saveDataKey) {
78
+ // Only allow certain save data keys to be reset.
79
+ if (!RESETTABLE_SAVE_DATA_KEYS.has(saveDataKey)) {
80
+ error(`Unknown save data key name of: ${saveDataKey}`);
81
+ }
82
+ const childTable = saveData[saveDataKey];
83
+ if (childTable === undefined) {
84
+ // This feature does not happen to store any variables on this particular child table.
85
+ return;
86
+ }
87
+ // Get the default values for this feature.
88
+ const saveDataDefaults = saveDataDefaultsMap.get(subscriberName);
89
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
90
+ if (saveDataDefaults === undefined) {
91
+ logError(`Failed to find the default copy of the save data for subscriber: ${subscriberName}`);
92
+ return;
93
+ }
94
+ // Get the default values for the specific sub-table of this feature.
95
+ const childTableDefaults = saveDataDefaults[saveDataKey];
96
+ if (childTableDefaults === undefined) {
97
+ logError(`Failed to find the default copy of the child table "${saveDataKey}" for subscriber "${subscriberName}". This error usually means that your save data is out of date. You can try purging all of your save data by deleting the following directory: C:\\Program Files (x86)\\Steam\\steamapps\\common\\The Binding of Isaac Rebirth\\data`);
98
+ return;
99
+ }
100
+ // Make a new copy of the default child table.
101
+ const childTableDefaultsCopy = deepCopy(childTableDefaults, SerializationType.NONE, `${subscriberName} --> ${saveDataKey}`);
102
+ // We do not want to blow away the existing child table because we don't want to break any
103
+ // existing references. Instead, empty the table and copy all of the elements from the copy of the
104
+ // defaults table.
105
+ clearAndCopyAllElements(childTable, childTableDefaultsCopy);
106
+ }
107
+ /**
108
+ * Will empty the old table of all elements, and then shallow copy all the elements from the new
109
+ * table to the old table.
110
+ */
111
+ function clearAndCopyAllElements(oldTable, newTable) {
112
+ clearTable(oldTable);
113
+ for (const [key, value] of pairs(newTable)) {
114
+ oldTable.set(key, value);
115
+ }
116
+ }
117
+ /** @internal */
118
+ export function forceSaveDataManagerSave() {
119
+ if (mod === null) {
120
+ return;
121
+ }
122
+ saveToDisk(mod, saveDataMap, saveDataConditionalFuncMap);
123
+ }
124
+ /** @internal */
125
+ export function forceSaveDataManagerLoad() {
126
+ if (mod === null) {
127
+ return;
128
+ }
129
+ loadFromDisk(mod, saveDataMap);
130
+ }
131
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFpbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2lzYWFjc2NyaXB0LWNvbW1vbi9zcmMvZmVhdHVyZXMvc2F2ZURhdGFNYW5hZ2VyL21haW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQzNELE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUUzQyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDOUQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsVUFBVSxFQUFFLG1CQUFtQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFeEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUN0QyxPQUFPLEVBQ0wsMEJBQTBCLEVBQzFCLG1CQUFtQixFQUNuQixXQUFXLEdBQ1osTUFBTSxRQUFRLENBQUM7QUFDaEIsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNwQyxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLDhCQUE4QixHQUMvQixNQUFNLDRCQUE0QixDQUFDO0FBRXBDLE1BQU0seUJBQXlCLEdBQTZCLElBQUksR0FBRyxDQUFDO0lBQ2xFLFdBQVcsQ0FBQyxHQUFHO0lBQ2YsV0FBVyxDQUFDLEtBQUs7SUFDakIsV0FBVyxDQUFDLElBQUk7Q0FDakIsQ0FBQyxDQUFDO0FBRUgsSUFBSSxHQUFHLEdBQXVCLElBQUksQ0FBQztBQUNuQyxJQUFJLG1CQUFtQixHQUFH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
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The save data map is indexed by subscriber name. We use Lua tables instead of TypeScriptToLua
3
+ * Maps for the master map so that we can access the variables via the in-game console when
4
+ * debugging. (TSTL Maps don't expose the map keys as normal keys.)
5
+ */
6
+ export const saveDataMap = new LuaTable();
7
+ export const saveDataDefaultsMap = new LuaTable();
8
+ export const saveDataConditionalFuncMap = new Map();
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2lzYWFjc2NyaXB0LWNvbW1vbi9zcmMvZmVhdHVyZXMvc2F2ZURhdGFNYW5hZ2VyL21hcHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUE7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLFdBQVcsR0FBRyxJQUFJLFFBQVEsRUFBb0IsQ0FBQztBQUU1RCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLFFBQVEsRUFBb0IsQ0FBQztBQUNwRSxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxJQUFJLEdBQUcsRUFBeUIsQ0FBQyJ9
@@ -0,0 +1,139 @@
1
+ import { SerializationBrand } from "../../enums/private/SerializationBrand";
2
+ import { SerializationType } from "../../enums/SerializationType";
3
+ import { isArray } from "../../functions/array";
4
+ import { deepCopy } from "../../functions/deepCopy";
5
+ import { log } from "../../functions/log";
6
+ import { deserializeIsaacAPIClass, isSerializedIsaacAPIClass, } from "../../functions/serialization";
7
+ import { clearTable, iterateTableInOrder } from "../../functions/table";
8
+ import { isTSTLMap, isTSTLSet } from "../../functions/tstlClass";
9
+ import { isTable } from "../../functions/types";
10
+ import { getTraversalDescription } from "../../functions/utils";
11
+ import { SAVE_DATA_MANAGER_DEBUG } from "./saveDataManagerConstants";
12
+ import { isSerializationBrand } from "./serializationBrand";
13
+ /**
14
+ * `merge` takes the values from a new table and recursively merges them into an old object (while
15
+ * performing appropriate deserialization).
16
+ *
17
+ * It supports the following object types:
18
+ *
19
+ * - `LuaTable` / basic TSTL objects
20
+ * - TSTL `Map`
21
+ * - TSTL `Set`
22
+ * - TSTL classes
23
+ * - `DefaultMap`
24
+ * - Isaac `Color` objects
25
+ * - Isaac `KColor` objects
26
+ * - Isaac `RNG` objects
27
+ * - Isaac `Vector` objects
28
+ *
29
+ * Since it is common for a variable to have a type of `something | null`, we must iterate over the
30
+ * new object and copy over all of the values. (A value of null transpiles to nil, which means the
31
+ * table key does not exist.) The consequence of this is that it can copy over old variables that
32
+ * are no longer used in the code, or copy over old variables of a different type, which can cause
33
+ * run-time errors. In such cases, users will have to manually delete their save data.
34
+ */
35
+ export function merge(oldObject, newTable, traversalDescription) {
36
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
37
+ if (SAVE_DATA_MANAGER_DEBUG) {
38
+ log(`merge is traversing: ${traversalDescription}`);
39
+ }
40
+ if (!isTable(oldObject)) {
41
+ error("The first argument given to the merge function is not a table.");
42
+ }
43
+ if (!isTable(newTable)) {
44
+ error("The second argument given to the merge function is not a table.");
45
+ }
46
+ // First, handle the special case of an array with a shallow copy.
47
+ if (isArray(oldObject) && isArray(newTable)) {
48
+ mergeArray(oldObject, newTable);
49
+ return;
50
+ }
51
+ // Depending on whether we are working on a Lua table or a TypeScriptToLua object, we need to
52
+ // iterate in a specific way.
53
+ if (isTSTLMap(oldObject) || isTSTLSet(oldObject)) {
54
+ mergeTSTLObject(oldObject, newTable, traversalDescription);
55
+ }
56
+ else {
57
+ mergeTable(oldObject, newTable, traversalDescription);
58
+ }
59
+ }
60
+ function mergeArray(oldArray, newArray) {
61
+ // Assume that we should blow away all array values with whatever is present in the incoming
62
+ // array.
63
+ clearTable(oldArray);
64
+ iterateTableInOrder(newArray, (key, value) => {
65
+ oldArray.set(key, value);
66
+ }, SAVE_DATA_MANAGER_DEBUG);
67
+ }
68
+ function mergeTSTLObject(oldObject, newTable, traversalDescription) {
69
+ // We blow away the old object and recursively copy over all of the incoming values.
70
+ oldObject.clear();
71
+ // During serialization, we brand some Lua tables with a special identifier to signify that it has
72
+ // keys that should be deserialized to numbers.
73
+ const convertStringKeysToNumbers = newTable.has(SerializationBrand.OBJECT_WITH_NUMBER_KEYS);
74
+ iterateTableInOrder(newTable, (key, value) => {
75
+ if (isSerializationBrand(key)) {
76
+ return;
77
+ }
78
+ let keyToUse = key;
79
+ if (convertStringKeysToNumbers) {
80
+ const numberKey = tonumber(key);
81
+ if (numberKey === undefined) {
82
+ return;
83
+ }
84
+ keyToUse = numberKey;
85
+ }
86
+ if (isTSTLMap(oldObject)) {
87
+ let valueCopy;
88
+ if (isTable(value)) {
89
+ valueCopy = deepCopy(value, SerializationType.DESERIALIZE, traversalDescription);
90
+ }
91
+ else {
92
+ valueCopy = value;
93
+ }
94
+ oldObject.set(keyToUse, valueCopy);
95
+ }
96
+ else if (isTSTLSet(oldObject)) {
97
+ oldObject.add(keyToUse);
98
+ }
99
+ }, SAVE_DATA_MANAGER_DEBUG);
100
+ }
101
+ function mergeTable(oldTable, newTable, traversalDescription) {
102
+ iterateTableInOrder(newTable, (key, value) => {
103
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
104
+ if (SAVE_DATA_MANAGER_DEBUG) {
105
+ const valueToPrint = value === "" ? "(empty string)" : `${value}`;
106
+ log(`merge is merging: ${traversalDescription} --> ${valueToPrint}`);
107
+ }
108
+ if (isSerializationBrand(key)) {
109
+ return;
110
+ }
111
+ // Handle the special case of serialized Isaac API classes.
112
+ if (isSerializedIsaacAPIClass(value)) {
113
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
114
+ if (SAVE_DATA_MANAGER_DEBUG) {
115
+ log("merge found a serialized Isaac API class.");
116
+ }
117
+ const deserializedObject = deserializeIsaacAPIClass(value);
118
+ oldTable.set(key, deserializedObject);
119
+ return;
120
+ }
121
+ if (isTable(value)) {
122
+ let oldValue = oldTable.get(key);
123
+ if (!isTable(oldValue)) {
124
+ // The child table does not exist on the old table. However, we still need to copy over
125
+ // the new table, because we need to handle data types like "Foo | null". Thus, set up a
126
+ // blank sub-table on the old table, and continue to recursively merge..
127
+ oldValue = new LuaTable();
128
+ oldTable.set(key, oldValue);
129
+ }
130
+ traversalDescription = getTraversalDescription(key, traversalDescription);
131
+ merge(oldValue, value, traversalDescription);
132
+ }
133
+ else {
134
+ // Base case: copy the value
135
+ oldTable.set(key, value);
136
+ }
137
+ }, SAVE_DATA_MANAGER_DEBUG);
138
+ }
139
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVyZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy9pc2FhY3NjcmlwdC1jb21tb24vc3JjL2ZlYXR1cmVzL3NhdmVEYXRhTWFuYWdlci9tZXJnZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUM1RSxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxQyxPQUFPLEVBQ0wsd0JBQXdCLEVBQ3hCLHlCQUF5QixHQUMxQixNQUFNLCtCQUErQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxVQUFVLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2pFLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNoRCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUNoRSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUU1RDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUJHO0FBQ0gsTUFBTSxVQUFVLEtBQUssQ0FDbkIsU0FHa0IsRUFDbEIsUUFBc0MsRUFDdEMsb0JBQTRCO0lBRTVCLHVFQUF1RTtJQUN2RSxJQUFJLHVCQUF1QixFQUFFO1FBQzNCLEdBQUcsQ0FBQyx3QkFBd0Isb0JBQW9CLEVBQUUsQ0FBQyxDQUFDO0tB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
@@ -0,0 +1,43 @@
1
+ import { SerializationType } from "../../enums/SerializationType";
2
+ import { deepCopy } from "../../functions/deepCopy";
3
+ import { jsonEncode } from "../../functions/jsonHelpers";
4
+ import { log } from "../../functions/log";
5
+ import { iterateTableInOrder } from "../../functions/table";
6
+ import { SAVE_DATA_MANAGER_DEBUG, SAVE_DATA_MANAGER_FEATURE_NAME, } from "./saveDataManagerConstants";
7
+ export function saveToDisk(mod, saveDataMap, saveDataConditionalFuncMap) {
8
+ const allSaveData = getAllSaveDataToWriteToDisk(saveDataMap, saveDataConditionalFuncMap);
9
+ const jsonString = jsonEncode(allSaveData);
10
+ mod.SaveData(jsonString); // Write it to the "save#.dat" file
11
+ log(`The ${SAVE_DATA_MANAGER_FEATURE_NAME} wrote data to the "save#.dat" file.`);
12
+ }
13
+ function getAllSaveDataToWriteToDisk(saveDataMap, saveDataConditionalFuncMap) {
14
+ const allSaveData = new LuaTable();
15
+ iterateTableInOrder(saveDataMap, (subscriberName, saveData) => {
16
+ // Handle the feature of the save data manager where certain mod features can conditionally
17
+ // write their data to disk.
18
+ const conditionalFunc = saveDataConditionalFuncMap.get(subscriberName);
19
+ if (conditionalFunc !== undefined) {
20
+ const shouldSave = conditionalFunc();
21
+ if (!shouldSave) {
22
+ return;
23
+ }
24
+ }
25
+ // Strip out the room part of the save data.
26
+ const saveDataWithoutRoom = {
27
+ persistent: saveData.persistent,
28
+ run: saveData.run,
29
+ level: saveData.level,
30
+ };
31
+ // If there is no data, then we can move on to the next feature.
32
+ if (Object.keys(saveDataWithoutRoom).length === 0) {
33
+ return;
34
+ }
35
+ // If we encode TypeScriptToLua Maps into JSON, it will result in a lot of extraneous data
36
+ // that is unnecessary. Make a copy of the data and recursively convert all TypeScriptToLua
37
+ // Maps into Lua tables.
38
+ const saveDataCopy = deepCopy(saveDataWithoutRoom, SerializationType.SERIALIZE, subscriberName);
39
+ allSaveData.set(subscriberName, saveDataCopy);
40
+ }, SAVE_DATA_MANAGER_DEBUG);
41
+ return allSaveData;
42
+ }
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2F2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL2lzYWFjc2NyaXB0LWNvbW1vbi9zcmMvZmVhdHVyZXMvc2F2ZURhdGFNYW5hZ2VyL3NhdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDbEUsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDMUMsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFNUQsT0FBTyxFQUNMLHVCQUF1QixFQUN2Qiw4QkFBOEIsR0FDL0IsTUFBTSw0QkFBNEIsQ0FBQztBQUVwQyxNQUFNLFVBQVUsVUFBVSxDQUN4QixHQUFRLEVBQ1IsV0FBdUMsRUFDdkMsMEJBQXNEO0lBRXRELE1BQU0sV0FBVyxHQUFHLDJCQUEyQixDQUM3QyxXQUFXLEVBQ1gsMEJBQTBCLENBQzNCLENBQUM7SUFDRixNQUFNLFVBQVUsR0FBRyxVQUFVLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDM0MsR0FBRyxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLG1DQUFtQztJQUM3RCxHQUFHLENBQ0QsT0FBTyw4QkFBOEIsc0NBQXNDLENBQzVFLENBQUM7QUFDSixDQUFDO0FBRUQsU0FBUywyQkFBMkIsQ0FDbEMsV0FBdUMsRUFDdkMsMEJBQXNEO0lBRXRELE1BQU0sV0FBVyxHQUFHLElBQUksUUFBUSxFQUFzQixDQUFDO0lBRXZELG1CQUFtQixDQUNqQixXQUFXLEVBQ1gsQ0FBQyxjQUFjLEVBQUUsUUFBUSxFQUFFLEVBQUU7UUFDM0IsMkZBQTJGO1FBQzNGLDRCQUE0QjtRQUM1QixNQUFNLGVBQWUsR0FBRywwQkFBMEIsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdkUsSUFBSSxlQUFlLEtBQUssU0FBUyxFQUFFO1lBQ2pDLE1BQU0sVUFBVSxHQUFHLGVBQWUsRUFBRSxDQUFDO1lBQ3JDLElBQUksQ0FBQyxVQUFVLEVBQUU7Z0JBQ2YsT0FBTzthQUNSO1NBQ0Y7UUFFRCw0Q0FBNEM7UUFDNUMsTUFBTSxtQkFBbUIsR0FBYTtZQUNwQyxVQUFVLEVBQUUsUUFBUSxDQUFDLFVBQVU7WUFDL0IsR0FBRyxFQUFFLFFBQVEsQ0FBQyxHQUFHO1lBQ2pCLEtBQUssRUFBRSxRQUFRLENBQUMsS0FBSztTQUN0QixDQUFDO1FBRUYsZ0VBQWdFO1FBQ2hFLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDakQsT0FBTztTQUNSO1FBRUQsMEZBQTBGO1FBQzFGLDJGQUEyRjtRQUMzRix3QkFBd0I7UUFDeEIsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUMzQixtQkFBK0IsRUFDL0IsaUJBQWlCLENBQUMsU0FBUyxFQUMzQixjQUFjLENBQ2YsQ0FBQztRQUVGLFdBQVcsQ0FBQyxHQUFHLENBQUMsY0FBYyxFQUFFLFlBQVksQ0FBQyxDQUFDO0lBQ2hELENBQUMsRUFDRCx1QkFBdUIsQ0FDeEIsQ0FBQztJQUVGLE9BQU8sV0FBVyxDQUFDO0FBQ3JCLENBQUMifQ==
@@ -0,0 +1,4 @@
1
+ /** Set this to true to enable more verbosity in the save data manger. */
2
+ export const SAVE_DATA_MANAGER_DEBUG = false;
3
+ export const SAVE_DATA_MANAGER_FEATURE_NAME = "save data manager";
4
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2F2ZURhdGFNYW5hZ2VyQ29uc3RhbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvaXNhYWNzY3JpcHQtY29tbW9uL3NyYy9mZWF0dXJlcy9zYXZlRGF0YU1hbmFnZXIvc2F2ZURhdGFNYW5hZ2VyQ29uc3RhbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLHlFQUF5RTtBQUN6RSxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxLQUFLLENBQUM7QUFFN0MsTUFBTSxDQUFDLE1BQU0sOEJBQThCLEdBQUcsbUJBQW1CLENBQUMifQ==
@@ -0,0 +1,12 @@
1
+ import { SerializationBrand } from "../../enums/private/SerializationBrand";
2
+ import { getEnumValues } from "../../functions/enums";
3
+ import { isString } from "../../functions/types";
4
+ const SERIALIZATION_BRANDS = getEnumValues(SerializationBrand);
5
+ const SERIALIZATION_BRAND_SET = new Set(SERIALIZATION_BRANDS);
6
+ export function isSerializationBrand(key) {
7
+ if (!isString(key)) {
8
+ return false;
9
+ }
10
+ return SERIALIZATION_BRAND_SET.has(key);
11
+ }
12
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VyaWFsaXphdGlvbkJyYW5kLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvaXNhYWNzY3JpcHQtY29tbW9uL3NyYy9mZWF0dXJlcy9zYXZlRGF0YU1hbmFnZXIvc2VyaWFsaXphdGlvbkJyYW5kLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFakQsTUFBTSxvQkFBb0IsR0FBRyxhQUFhLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUMvRCxNQUFNLHVCQUF1QixHQUF3QixJQUFJLEdBQUcsQ0FDMUQsb0JBQW9CLENBQ3JCLENBQUM7QUFFRixNQUFNLFVBQVUsb0JBQW9CLENBQUMsR0FBWTtJQUMvQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQ2xCLE9BQU8sS0FBSyxDQUFDO0tBQ2Q7SUFFRCxPQUFPLHVCQUF1QixDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUMxQyxDQUFDIn0=
@@ -0,0 +1,90 @@
1
+ import { EntityType, ModCallback, } from "isaac-typescript-definitions";
2
+ import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
3
+ import { getEntities } from "../functions/entity";
4
+ import { saveDataManager } from "./saveDataManager/exports";
5
+ const FEATURE_NAME = "sirenHelpers";
6
+ const v = {
7
+ run: {
8
+ familiarBlacklist: [],
9
+ },
10
+ };
11
+ /** @internal */
12
+ export function sirenHelpersInit(mod) {
13
+ saveDataManager(FEATURE_NAME, v);
14
+ mod.AddCallback(ModCallback.POST_NPC_INIT, postNPCInitSirenHelper, EntityType.SIREN_HELPER);
15
+ }
16
+ // ModCallback.POST_NPC_INIT (27)
17
+ // EntityType.SIREN_HELPER (966)
18
+ function postNPCInitSirenHelper(npc) {
19
+ checkReturnFamiliarToPlayer(npc);
20
+ }
21
+ function checkReturnFamiliarToPlayer(npc) {
22
+ if (npc.Target === undefined) {
23
+ return;
24
+ }
25
+ const familiar = npc.Target.ToFamiliar();
26
+ if (familiar === undefined) {
27
+ return;
28
+ }
29
+ if (blacklistEntryExists(familiar.Variant, familiar.SubType)) {
30
+ npc.Remove();
31
+ familiar.AddToFollowers();
32
+ }
33
+ }
34
+ function blacklistEntryExists(incomingFamiliarVariant, incomingFamiliarSubType) {
35
+ for (const [familiarVariant, familiarSubType] of v.run.familiarBlacklist) {
36
+ if (incomingFamiliarVariant === familiarVariant &&
37
+ familiarSubType === incomingFamiliarSubType) {
38
+ // There is an entry that matches the variant and sub-type exactly.
39
+ return true;
40
+ }
41
+ if (incomingFamiliarVariant === familiarVariant &&
42
+ familiarSubType === undefined) {
43
+ // There is an entry that matches all sub-types for this variant.
44
+ return true;
45
+ }
46
+ }
47
+ return false;
48
+ }
49
+ /**
50
+ * Blacklists a familiar from being stolen by The Siren boss. This should be called once at the
51
+ * beginning of every run.
52
+ *
53
+ * @param familiarVariant The familiar variant to blacklist.
54
+ * @param familiarSubType The sub-type to blacklist. Optional. The default is to blacklist all
55
+ * sub-types of the given variant.
56
+ */
57
+ export function setFamiliarNoSirenSteal(familiarVariant, familiarSubType) {
58
+ errorIfFeaturesNotInitialized(FEATURE_NAME);
59
+ if (blacklistEntryExists(familiarVariant, familiarSubType)) {
60
+ return;
61
+ }
62
+ v.run.familiarBlacklist.push([familiarVariant, familiarSubType]);
63
+ }
64
+ /**
65
+ * Helper function to check if the Siren boss has stolen a familiar. Some familiars may need to
66
+ * behave differently when under The Siren's control (e.g. if they auto-target enemies).
67
+ *
68
+ * @param familiar The familiar to be checked.
69
+ * @returns Returns whether the familiar has been stolen by The Siren.
70
+ */
71
+ export function hasSirenStolenFamiliar(familiar) {
72
+ errorIfFeaturesNotInitialized(FEATURE_NAME);
73
+ return getSirenHelper(familiar) !== undefined;
74
+ }
75
+ /**
76
+ * When The Siren boss "steals" your familiars, a hidden "Siren Helper" entity is spawned to control
77
+ * each familiar stolen. (Checking for this entity seems to be the only way to detect when the Siren
78
+ * steals a familiar.)
79
+ *
80
+ * @param familiar The familiar to be checked.
81
+ * @returns Returns the hidden "Siren Helper" entity corresponding to the given familiar, if it
82
+ * exists. Returns undefined otherwise.
83
+ */
84
+ function getSirenHelper(familiar) {
85
+ const familiarPtrHash = GetPtrHash(familiar);
86
+ const sirenHelpers = getEntities(EntityType.SIREN_HELPER);
87
+ return sirenHelpers.find((sirenHelper) => sirenHelper.Target !== undefined &&
88
+ GetPtrHash(sirenHelper.Target) === familiarPtrHash);
89
+ }
90
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2lyZW5IZWxwZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvaXNhYWNzY3JpcHQtY29tbW9uL3NyYy9mZWF0dXJlcy9zaXJlbkhlbHBlcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFVBQVUsRUFFVixXQUFXLEdBQ1osTUFBTSw4QkFBOEIsQ0FBQztBQUN0QyxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN2RSxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbEQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBRTVELE1BQU0sWUFBWSxHQUFHLGNBQWMsQ0FBQztBQUVwQyxNQUFNLENBQUMsR0FBRztJQUNSLEdBQUcsRUFBRTtRQUNILGlCQUFpQixFQUFFLEVBRWxCO0tBQ0Y7Q0FDRixDQUFDO0FBRUYsZ0JBQWdCO0FBQ2hCLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxHQUFRO0lBQ3ZDLGVBQWUsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFFakMsR0FBRyxDQUFDLFdBQVcsQ0FDYixXQUFXLENBQUMsYUFBYSxFQUN6QixzQkFBc0IsRUFDdEIsVUFBVSxDQUFDLFlBQVksQ0FDeEIsQ0FBQztBQUNKLENBQUM7QUFFRCxpQ0FBaUM7QUFDakMsZ0NBQWdDO0FBQ2hDLFNBQVMsc0JBQXNCLENBQUMsR0FBYztJQUM1QywyQkFBMkIsQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNuQyxDQUFDO0FBRUQsU0FBUywyQkFBMkIsQ0FBQyxHQUFjO0lBQ2pELElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxTQUFTLEVBQUU7UUFDNUIsT0FBTztLQUNSO0lBRUQsTUFBTSxRQUFRLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUN6QyxJQUFJLFFBQVEsS0FBSyxTQUFTLEVBQUU7UUFDMUIsT0FBTztLQUNSO0lBRUQsSUFBSSxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUM1RCxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDYixRQUFRLENBQUMsY0FBYyxFQUFFLENBQUM7S0FDM0I7QUFDSCxDQUFDO0FBRUQsU0FBUyxvQkFBb0IsQ0FDM0IsdUJBQXdDLEVBQ3hDLHVCQUF3QztJQUV4QyxLQUFLLE1BQU0sQ0FBQyxlQUFlLEVBQUUsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRTtRQUN4RSxJQUNFLHVCQUF1QixLQUFLLGVBQWU7WUFDM0MsZUFBZSxLQUFLLHVCQUF1QixFQUMzQztZQUNBLG1FQUFtRTtZQUNuRSxPQUFPLElBQUksQ0FBQztTQUNiO1FBRUQsSUFDRSx1QkFBdUIsS0FBSyxlQUFlO1lBQzNDLGVBQWUsS0FBSyxTQUFTLEVBQzdCO1lBQ0EsaUVBQWlFO1lBQ2pFLE9BQU8sSUFBSSxDQUFDO1NBQ2I7S0FDRjtJQUVELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsdUJBQXVCLENBQ3JDLGVBQWdDLEVBQ2hDLGVBQXFCO0lBRXJCLDZCQUE2QixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRTVDLElBQUksb0JBQW9CLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxFQUFFO1FBQzFELE9BQU87S0FDUjtJQUVELENBQUMsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxDQUFDLENBQUM7QUFDbkUsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxzQkFBc0IsQ0FBQyxRQUF3QjtJQUM3RCw2QkFBNkIsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUM1QyxPQUFPLGNBQWMsQ0FBQyxRQUFRLENBQUMsS0FBSyxTQUFTLENBQUM7QUFDaEQsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBUyxjQUFjLENBQUMsUUFBd0I7SUFDOUMsTUFBTSxlQUFlLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBRTdDLE1BQU0sWUFBWSxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDMUQsT0FBTyxZQUFZLENBQUMsSUFBSSxDQUN0QixDQUFDLFdBQVcsRUFBRSxFQUFFLENBQ2QsV0FBVyxDQUFDLE1BQU0sS0FBSyxTQUFTO1FBQ2hDLFVBQVUsQ0FBQyxXQUFXLENBQUMsTUFBTSxDQUFDLEtBQUssZUFBZSxDQUNyRCxDQUFDO0FBQ0osQ0FBQyJ9
@@ -0,0 +1,43 @@
1
+ import { game } from "../cachedClasses";
2
+ import { ModCallbackCustom } from "../enums/ModCallbackCustom";
3
+ import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
4
+ import { saveDataManager } from "./saveDataManager/exports";
5
+ const FEATURE_NAME = "stageHistory";
6
+ const v = {
7
+ run: {
8
+ stageHistory: [],
9
+ },
10
+ };
11
+ /** @internal */
12
+ export function stageHistoryInit(mod) {
13
+ saveDataManager(FEATURE_NAME, v);
14
+ mod.AddCallbackCustom(ModCallbackCustom.POST_NEW_LEVEL_REORDERED, postNewLevelReordered);
15
+ }
16
+ // ModCallbackCustom.POST_NEW_LEVEL_REORDERED
17
+ function postNewLevelReordered() {
18
+ const level = game.GetLevel();
19
+ const stage = level.GetStage();
20
+ const stageType = level.GetStageType();
21
+ v.run.stageHistory.push([stage, stageType]);
22
+ }
23
+ /** Helper function to get all of the stages that a player has visited thus far on this run. */
24
+ export function getStageHistory() {
25
+ errorIfFeaturesNotInitialized(FEATURE_NAME);
26
+ return v.run.stageHistory;
27
+ }
28
+ /**
29
+ * Helper function to check if a player has previous visited a particular stage (or stage + stage
30
+ * type combination) on this run.
31
+ *
32
+ * @param stage The stage to check for.
33
+ * @param stageType Optional. If provided, will check for a specific stage and stage type
34
+ * combination.
35
+ */
36
+ export function hasVisitedStage(stage, stageType) {
37
+ errorIfFeaturesNotInitialized(FEATURE_NAME);
38
+ if (stageType === undefined) {
39
+ return v.run.stageHistory.some(([previousStage]) => previousStage === stage);
40
+ }
41
+ return v.run.stageHistory.some(([previousStage, previousStageType]) => previousStage === stage && previousStageType === stageType);
42
+ }
43
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhZ2VIaXN0b3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvaXNhYWNzY3JpcHQtY29tbW9uL3NyYy9mZWF0dXJlcy9zdGFnZUhpc3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRXhDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9ELE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUU1RCxNQUFNLFlBQVksR0FBRyxjQUFjLENBQUM7QUFFcEMsTUFBTSxDQUFDLEdBQUc7SUFDUixHQUFHLEVBQUU7UUFDSCxZQUFZLEVBQUUsRUFBc0Q7S0FDckU7Q0FDRixDQUFDO0FBRUYsZ0JBQWdCO0FBQ2hCLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxHQUFnQjtJQUMvQyxlQUFlLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBRWpDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FDbkIsaUJBQWlCLENBQUMsd0JBQXdCLEVBQzFDLHFCQUFxQixDQUN0QixDQUFDO0FBQ0osQ0FBQztBQUVELDZDQUE2QztBQUM3QyxTQUFTLHFCQUFxQjtJQUM1QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDOUIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQy9CLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUV2QyxDQUFDLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLENBQUMsQ0FBQztBQUM5QyxDQUFDO0FBRUQsK0ZBQStGO0FBQy9GLE1BQU0sVUFBVSxlQUFlO0lBRzdCLDZCQUE2QixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBQzVDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUM7QUFDNUIsQ0FBQztBQUVEOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUM3QixLQUFpQixFQUNqQixTQUFxQjtJQUVyQiw2QkFBNkIsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUU1QyxJQUFJLFNBQVMsS0FBSyxTQUFTLEVBQUU7UUFDM0IsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQzVCLENBQUMsQ0FBQyxhQUFhLENBQUMsRUFBRSxFQUFFLENBQUMsYUFBYSxLQUFLLEtBQUssQ0FDN0MsQ0FBQztLQUNIO0lBRUQsT0FBTyxDQUFDLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQzVCLENBQUMsQ0FBQyxhQUFhLEVBQUUsaUJBQWlCLENBQUMsRUFBRSxFQUFFLENBQ3JDLGFBQWEsS0FBSyxLQUFLLElBQUksaUJBQWlCLEtBQUssU0FBUyxDQUM3RCxDQUFDO0FBQ0osQ0FBQyJ9
@@ -0,0 +1,92 @@
1
+ // This feature provides a way for end-users to get the `EntityPlayer` object for the other Tainted
2
+ // Lazarus.
3
+ import { ModCallback, PlayerType } from "isaac-typescript-definitions";
4
+ import { errorIfFeaturesNotInitialized } from "../featuresInitialized";
5
+ import { saveDataManager } from "./saveDataManager/exports";
6
+ const FEATURE_NAME = "taintedLazarusPlayers";
7
+ const v = {
8
+ run: {
9
+ queuedTaintedLazarus: [],
10
+ queuedDeadTaintedLazarus: [],
11
+ /**
12
+ * The PostPlayerInit callback fires for Dead Tainted Lazarus at the beginning of the run.
13
+ * However, the player index for the Dead Tainted Lazarus player object at that time does not
14
+ * actually correspond to the player index for the real player once Flip has been used. Thus, we
15
+ * revert to using PtrHash as an index for our map, which is consistent between the Dead Tainted
16
+ * Lazarus object in the PostPlayerInit callback and the "real" Dead Tainted Lazarus.
17
+ */
18
+ subPlayerMap: new Map(),
19
+ },
20
+ };
21
+ /** @internal */
22
+ export function taintedLazarusPlayersInit(mod) {
23
+ saveDataManager(FEATURE_NAME, v, () => false);
24
+ mod.AddCallback(ModCallback.POST_PLAYER_INIT, postPlayerInit);
25
+ }
26
+ // ModCallback.POST_PLAYER_INIT (9)
27
+ function postPlayerInit(player) {
28
+ const entityPtr = EntityPtr(player);
29
+ const character = player.GetPlayerType();
30
+ if (character === PlayerType.LAZARUS_B) {
31
+ v.run.queuedTaintedLazarus.push(entityPtr);
32
+ }
33
+ else if (character === PlayerType.LAZARUS_2_B) {
34
+ v.run.queuedDeadTaintedLazarus.push(entityPtr);
35
+ }
36
+ else {
37
+ return;
38
+ }
39
+ checkDequeue();
40
+ }
41
+ /**
42
+ * When starting a run, the PostPlayerInit callback will fire first for Dead Tainted Lazarus, then
43
+ * for Tainted Lazarus. When continuing a run, the PostPlayerInit callback will fire first for the
44
+ * character that is currently active. Thus, since the order of the characters is not certain, we
45
+ * insert each of their pointers into a queue, and then only populate the map when we have one
46
+ * Tainted Lazarus and one Dead Tainted Lazarus.
47
+ */
48
+ function checkDequeue() {
49
+ if (v.run.queuedTaintedLazarus.length === 0 ||
50
+ v.run.queuedDeadTaintedLazarus.length === 0) {
51
+ return;
52
+ }
53
+ const taintedLazarusPtr = v.run.queuedTaintedLazarus.shift();
54
+ const deadTaintedLazarusPtr = v.run.queuedDeadTaintedLazarus.shift();
55
+ if (taintedLazarusPtr === undefined || deadTaintedLazarusPtr === undefined) {
56
+ return;
57
+ }
58
+ const taintedLazarus = taintedLazarusPtr.Ref;
59
+ const deadTaintedLazarus = deadTaintedLazarusPtr.Ref;
60
+ if (taintedLazarus === undefined || deadTaintedLazarus === undefined) {
61
+ return;
62
+ }
63
+ const taintedLazarusPtrHash = GetPtrHash(taintedLazarus);
64
+ const deadTaintedLazarusPtrHash = GetPtrHash(deadTaintedLazarus);
65
+ v.run.subPlayerMap.set(taintedLazarusPtrHash, deadTaintedLazarusPtr);
66
+ v.run.subPlayerMap.set(deadTaintedLazarusPtrHash, taintedLazarusPtr);
67
+ }
68
+ /**
69
+ * Helper function to get the other version of Tainted Lazarus.
70
+ *
71
+ * - On Tainted Lazarus, returns the player object for Dead Tainted Lazarus.
72
+ * - On Dead Tainted Lazarus, returns the player object for Tainted Lazarus.
73
+ * - Returns undefined if player object retrieval failed for any reason.
74
+ *
75
+ * If you call the `EntityPlayer.Exists` method on the returned object, it will return false.
76
+ * However, you can still call the other methods like you normally would (e.g.
77
+ * `EntityPlayer.AddCollectible`).
78
+ */
79
+ export function getTaintedLazarusSubPlayer(player) {
80
+ errorIfFeaturesNotInitialized(FEATURE_NAME);
81
+ const ptrHash = GetPtrHash(player);
82
+ const entityPtr = v.run.subPlayerMap.get(ptrHash);
83
+ if (entityPtr === undefined) {
84
+ return undefined;
85
+ }
86
+ const entity = entityPtr.Ref;
87
+ if (entity === undefined) {
88
+ return undefined;
89
+ }
90
+ return entity.ToPlayer();
91
+ }
92
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFpbnRlZExhemFydXNQbGF5ZXJzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGFja2FnZXMvaXNhYWNzY3JpcHQtY29tbW9uL3NyYy9mZWF0dXJlcy90YWludGVkTGF6YXJ1c1BsYXllcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsbUdBQW1HO0FBQ25HLFdBQVc7QUFFWCxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSw2QkFBNkIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUU1RCxNQUFNLFlBQVksR0FBRyx1QkFBdUIsQ0FBQztBQUU3QyxNQUFNLENBQUMsR0FBRztJQUNSLEdBQUcsRUFBRTtRQUNILG9CQUFvQixFQUFFLEVBQWlCO1FBQ3ZDLHdCQUF3QixFQUFFLEVBQWlCO1FBRTNDOzs7Ozs7V0FNRztRQUNILFlBQVksRUFBRSxJQUFJLEdBQUcsRUFBc0I7S0FDNUM7Q0FDRixDQUFDO0FBRUYsZ0JBQWdCO0FBQ2hCLE1BQU0sVUFBVSx5QkFBeUIsQ0FBQyxHQUFRO0lBQ2hELGVBQWUsQ0FBQyxZQUFZLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRTlDLEdBQUcsQ0FBQyxXQUFXLENBQUMsV0FBVyxDQUFDLGdCQUFnQixFQUFFLGNBQWMsQ0FBQyxDQUFDO0FBQ2hFLENBQUM7QUFFRCxtQ0FBbUM7QUFDbkMsU0FBUyxjQUFjLENBQUMsTUFBb0I7SUFDMUMsTUFBTSxTQUFTLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQ3BDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxhQUFhLEVBQUUsQ0FBQztJQUV6QyxJQUFJLFNBQVMsS0FBSyxVQUFVLENBQUMsU0FBUyxFQUFFO1FBQ3RDLENBQUMsQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0tBQzVDO1NBQU0sSUFBSSxTQUFTLEtBQUssVUFBVSxDQUFDLFdBQVcsRUFBRTtRQUMvQyxDQUFDLENBQUMsR0FBRyxDQUFDLHdCQUF3QixDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztLQUNoRDtTQUFNO1FBQ0wsT0FBTztLQUNSO0lBRUQsWUFBWSxFQUFFLENBQUM7QUFDakIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILFNBQVMsWUFBWTtJQUNuQixJQUNFLENBQUMsQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsTUFBTSxLQUFLLENBQUM7UUFDdkMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyx3QkFBd0IsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUMzQztRQUNBLE9BQU87S0FDUjtJQUVELE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUM3RCxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsd0JBQXdCLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFckUsSUFBSSxpQkFBaUIsS0FBSyxTQUFTLElBQUkscUJBQXFCLEtBQUssU0FBUyxFQUFFO1FBQzFFLE9BQU87S0FDUjtJQUVELE1BQU0sY0FBYyxHQUFHLGlCQUFpQixDQUFDLEdBQUcsQ0FBQztJQUM3QyxNQUFNLGtCQUFrQixHQUFHLHFCQUFxQixDQUFDLEdBQUcsQ0FBQztJQUVyRCxJQUFJLGNBQWMsS0FBSyxTQUFTLElBQUksa0JBQWtCLEtBQUssU0FBUyxFQUFFO1FBQ3BFLE9BQU87S0FDUjtJQUVELE1BQU0scUJBQXFCLEdBQUcsVUFBVSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQ3pELE1BQU0seUJBQXlCLEdBQUcsVUFBVSxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFFakUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLHFCQUFxQixFQUFFLHFCQUFxQixDQUFDLENBQUM7SUFDckUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLHlCQUF5QixFQUFFLGlCQUFpQixDQUFDLENBQUM7QUFDdkUsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsMEJBQTBCLENBQ3hDLE1BQW9CO0lBRXBCLDZCQUE2QixDQUFDLFlBQVksQ0FBQyxDQUFDO0lBRTVDLE1BQU0sT0FBTyxHQUFHLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNuQyxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbEQsSUFBSSxTQUFTLEtBQUssU0FBUyxFQUFFO1FBQzNCLE9BQU8sU0FBUyxDQUFDO0tBQ2xCO0lBRUQsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLEdBQUcsQ0FBQztJQUM3QixJQUFJLE1BQU0sS0FBSyxTQUFTLEVBQUU7UUFDeEIsT0FBTyxTQUFTLENBQUM7S0FDbEI7SUFFRCxPQUFPLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUMzQixDQUFDIn0=
@@ -0,0 +1,16 @@
1
+ let featuresInitialized = false;
2
+ /** @internal */
3
+ export function areFeaturesInitialized() {
4
+ return featuresInitialized;
5
+ }
6
+ /** @internal */
7
+ export function errorIfFeaturesNotInitialized(featureName) {
8
+ if (!areFeaturesInitialized()) {
9
+ error(`The "${featureName}" feature is not initialized. You must first upgrade your mod object by calling the "upgradeMod" function.`);
10
+ }
11
+ }
12
+ /** @internal */
13
+ export function setFeaturesInitialized() {
14
+ featuresInitialized = true;
15
+ }
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZXNJbml0aWFsaXplZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3BhY2thZ2VzL2lzYWFjc2NyaXB0LWNvbW1vbi9zcmMvZmVhdHVyZXNJbml0aWFsaXplZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxJQUFJLG1CQUFtQixHQUFHLEtBQUssQ0FBQztBQUVoQyxnQkFBZ0I7QUFDaEIsTUFBTSxVQUFVLHNCQUFzQjtJQUNwQyxPQUFPLG1CQUFtQixDQUFDO0FBQzdCLENBQUM7QUFFRCxnQkFBZ0I7QUFDaEIsTUFBTSxVQUFVLDZCQUE2QixDQUFDLFdBQW1CO0lBQy9ELElBQUksQ0FBQyxzQkFBc0IsRUFBRSxFQUFFO1FBQzdCLEtBQUssQ0FDSCxRQUFRLFdBQVcsNEdBQTRHLENBQ2hJLENBQUM7S0FDSDtBQUNILENBQUM7QUFFRCxnQkFBZ0I7QUFDaEIsTUFBTSxVQUFVLHNCQUFzQjtJQUNwQyxtQkFBbUIsR0FBRyxJQUFJLENBQUM7QUFDN0IsQ0FBQyJ9