isaacscript-common 2.3.2 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cachedClasses.d.ts +6 -4
- package/cachedClasses.lua +24 -0
- package/callbacks/customRevive.lua +2 -0
- package/callbacks/itemPickup.lua +2 -0
- package/callbacks/postBombInitLate.lua +2 -0
- package/callbacks/postBoneSwing.lua +2 -0
- package/callbacks/postCollectibleInitFirst.lua +2 -0
- package/callbacks/postCursedTeleport.lua +2 -0
- package/callbacks/postCustomDoorEnter.lua +44 -0
- package/callbacks/postDoorRender.lua +2 -0
- package/callbacks/postDoorUpdate.lua +2 -0
- package/callbacks/postEffectInitLate.lua +2 -0
- package/callbacks/postEffectStateChanged.lua +2 -0
- package/callbacks/postEsauJr.lua +2 -0
- package/callbacks/postFamiliarInitLate.lua +2 -0
- package/callbacks/postFamiliarStateChanged.lua +2 -0
- package/callbacks/postFlip.lua +2 -0
- package/callbacks/postGreedModeWave.lua +2 -0
- package/callbacks/postGridEntity.lua +2 -0
- package/callbacks/postGridEntityCollision.lua +2 -0
- package/callbacks/postGridEntityRender.lua +2 -0
- package/callbacks/postHolyMantleRemoved.lua +2 -0
- package/callbacks/postKnifeInitLate.lua +2 -0
- package/callbacks/postLaserInitLate.lua +2 -0
- package/callbacks/postNPCInitLate.lua +2 -0
- package/callbacks/postNPCStateChanged.lua +2 -0
- package/callbacks/postNewRoomEarly.lua +2 -0
- package/callbacks/postPickupCollect.lua +2 -0
- package/callbacks/postPickupInitFirst.d.ts +1 -0
- package/callbacks/postPickupInitFirst.lua +55 -0
- package/callbacks/postPickupInitLate.lua +2 -0
- package/callbacks/postPickupStateChanged.lua +2 -0
- package/callbacks/postPitRender.lua +2 -0
- package/callbacks/postPitUpdate.lua +2 -0
- package/callbacks/postPlayerChangeHealth.lua +2 -0
- package/callbacks/postPlayerChangeType.lua +2 -0
- package/callbacks/postPlayerFatalDamage.lua +2 -0
- package/callbacks/postPlayerInitLate.lua +2 -0
- package/callbacks/postPlayerReordered.lua +2 -0
- package/callbacks/postPoopRender.lua +2 -0
- package/callbacks/postPoopUpdate.lua +2 -0
- package/callbacks/postPressurePlateRender.lua +2 -0
- package/callbacks/postPressurePlateUpdate.lua +2 -0
- package/callbacks/postProjectileInitLate.lua +2 -0
- package/callbacks/postPurchase.lua +2 -0
- package/callbacks/postRockRender.lua +2 -0
- package/callbacks/postRockUpdate.lua +2 -0
- package/callbacks/postRoomClearChanged.lua +2 -0
- package/callbacks/postSacrifice.lua +2 -0
- package/callbacks/postSlotDestroyed.d.ts +1 -0
- package/callbacks/postSlotDestroyed.lua +66 -0
- package/callbacks/postSlotInitUpdate.lua +2 -0
- package/callbacks/postSlotRender.lua +5 -21
- package/callbacks/postSpikesRender.lua +2 -0
- package/callbacks/postSpikesUpdate.lua +2 -0
- package/callbacks/postTNTRender.lua +2 -0
- package/callbacks/postTNTUpdate.lua +2 -0
- package/callbacks/postTearInitLate.lua +2 -0
- package/callbacks/postTearInitVeryLate.lua +2 -0
- package/callbacks/postTransformation.lua +2 -0
- package/callbacks/postTrinketBreak.lua +2 -0
- package/callbacks/preBerserkDeath.lua +2 -0
- package/callbacks/preNewLevel.lua +2 -0
- package/callbacks/reorderedCallbacks.lua +16 -0
- package/callbacks/subscriptions/postBombInitLate.lua +6 -0
- package/callbacks/subscriptions/postBoneSwing.lua +6 -0
- package/callbacks/subscriptions/postCollectibleInitFirst.lua +6 -0
- package/callbacks/subscriptions/postCursedTeleport.lua +6 -0
- package/callbacks/subscriptions/postCustomDoorEnter.lua +6 -0
- package/callbacks/subscriptions/postCustomRevive.d.ts +1 -0
- package/callbacks/subscriptions/postCustomRevive.lua +6 -0
- package/callbacks/subscriptions/postDoorRender.d.ts +1 -0
- package/callbacks/subscriptions/postDoorRender.lua +6 -0
- package/callbacks/subscriptions/postDoorUpdate.d.ts +1 -0
- package/callbacks/subscriptions/postDoorUpdate.lua +6 -0
- package/callbacks/subscriptions/postEffectInitLate.lua +6 -0
- package/callbacks/subscriptions/postEffectStateChanged.lua +6 -0
- package/callbacks/subscriptions/postEsauJr.lua +6 -0
- package/callbacks/subscriptions/postFamiliarInitLate.lua +6 -0
- package/callbacks/subscriptions/postFamiliarStateChanged.lua +6 -0
- package/callbacks/subscriptions/postFirstEsauJr.lua +6 -0
- package/callbacks/subscriptions/postFirstFlip.lua +6 -0
- package/callbacks/subscriptions/postFlip.lua +6 -0
- package/callbacks/subscriptions/postGameStartedReordered.lua +6 -0
- package/callbacks/subscriptions/postGreedModeWave.lua +6 -0
- package/callbacks/subscriptions/postGridEntityBroken.lua +6 -0
- package/callbacks/subscriptions/postGridEntityCollision.lua +6 -0
- package/callbacks/subscriptions/postGridEntityInit.lua +6 -0
- package/callbacks/subscriptions/postGridEntityRemove.lua +6 -0
- package/callbacks/subscriptions/postGridEntityRender.lua +6 -0
- package/callbacks/subscriptions/postGridEntityStateChanged.lua +6 -0
- package/callbacks/subscriptions/postGridEntityUpdate.lua +6 -0
- package/callbacks/subscriptions/postHolyMantleRemoved.lua +6 -0
- package/callbacks/subscriptions/postItemDischarged.lua +6 -0
- package/callbacks/subscriptions/postItemPickup.lua +6 -0
- package/callbacks/subscriptions/postKnifeInitLate.lua +6 -0
- package/callbacks/subscriptions/postLaserInitLate.lua +6 -0
- package/callbacks/subscriptions/postNPCInitLate.lua +6 -0
- package/callbacks/subscriptions/postNPCStateChanged.lua +6 -0
- package/callbacks/subscriptions/postNewLevelReordered.lua +6 -0
- package/callbacks/subscriptions/postNewRoomEarly.lua +6 -0
- package/callbacks/subscriptions/postNewRoomReordered.lua +6 -0
- package/callbacks/subscriptions/postPEffectUpdateReordered.lua +6 -0
- package/callbacks/subscriptions/postPickupCollect.d.ts +1 -0
- package/callbacks/subscriptions/postPickupCollect.lua +6 -0
- package/callbacks/subscriptions/postPickupInitFirst.d.ts +3 -0
- package/callbacks/subscriptions/postPickupInitFirst.lua +29 -0
- package/callbacks/subscriptions/postPickupInitLate.lua +6 -0
- package/callbacks/subscriptions/postPickupStateChanged.d.ts +1 -0
- package/callbacks/subscriptions/postPickupStateChanged.lua +6 -0
- package/callbacks/subscriptions/postPitRender.d.ts +1 -0
- package/callbacks/subscriptions/postPitRender.lua +6 -0
- package/callbacks/subscriptions/postPitUpdate.d.ts +1 -0
- package/callbacks/subscriptions/postPitUpdate.lua +6 -0
- package/callbacks/subscriptions/postPlayerChangeHealth.lua +6 -0
- package/callbacks/subscriptions/postPlayerChangeType.lua +6 -0
- package/callbacks/subscriptions/postPlayerFatalDamage.lua +6 -0
- package/callbacks/subscriptions/postPlayerInitLate.lua +6 -0
- package/callbacks/subscriptions/postPlayerInitReordered.lua +6 -0
- package/callbacks/subscriptions/postPlayerRenderReordered.lua +6 -0
- package/callbacks/subscriptions/postPlayerUpdateReordered.lua +6 -0
- package/callbacks/subscriptions/postPoopRender.d.ts +1 -0
- package/callbacks/subscriptions/postPoopRender.lua +6 -0
- package/callbacks/subscriptions/postPoopUpdate.d.ts +1 -0
- package/callbacks/subscriptions/postPoopUpdate.lua +6 -0
- package/callbacks/subscriptions/postPressurePlateRender.d.ts +1 -0
- package/callbacks/subscriptions/postPressurePlateRender.lua +6 -0
- package/callbacks/subscriptions/postPressurePlateUpdate.d.ts +1 -0
- package/callbacks/subscriptions/postPressurePlateUpdate.lua +6 -0
- package/callbacks/subscriptions/postProjectileInitLate.lua +6 -0
- package/callbacks/subscriptions/postPurchase.lua +6 -0
- package/callbacks/subscriptions/postRockRender.d.ts +1 -0
- package/callbacks/subscriptions/postRockRender.lua +6 -0
- package/callbacks/subscriptions/postRockUpdate.d.ts +1 -0
- package/callbacks/subscriptions/postRockUpdate.lua +6 -0
- package/callbacks/subscriptions/postRoomClearChanged.lua +6 -0
- package/callbacks/subscriptions/postSacrifice.lua +6 -0
- package/callbacks/subscriptions/postSlotAnimationChanged.lua +6 -0
- package/callbacks/subscriptions/postSlotDestroyed.lua +6 -0
- package/callbacks/subscriptions/postSlotInit.lua +6 -0
- package/callbacks/subscriptions/postSlotRender.lua +6 -0
- package/callbacks/subscriptions/postSlotUpdate.lua +6 -0
- package/callbacks/subscriptions/postSpikesRender.d.ts +1 -0
- package/callbacks/subscriptions/postSpikesRender.lua +6 -0
- package/callbacks/subscriptions/postSpikesUpdate.d.ts +1 -0
- package/callbacks/subscriptions/postSpikesUpdate.lua +6 -0
- package/callbacks/subscriptions/postTNTRender.d.ts +1 -0
- package/callbacks/subscriptions/postTNTRender.lua +6 -0
- package/callbacks/subscriptions/postTNTUpdate.d.ts +1 -0
- package/callbacks/subscriptions/postTNTUpdate.lua +6 -0
- package/callbacks/subscriptions/postTearInitLate.lua +6 -0
- package/callbacks/subscriptions/postTearInitVeryLate.lua +6 -0
- package/callbacks/subscriptions/postTransformation.lua +6 -0
- package/callbacks/subscriptions/postTrinketBreak.lua +6 -0
- package/callbacks/subscriptions/preBerserkDeath.lua +6 -0
- package/callbacks/subscriptions/preCustomRevive.lua +6 -0
- package/callbacks/subscriptions/preItemPickup.lua +6 -0
- package/callbacks/subscriptions/preNewLevel.lua +6 -0
- package/classes/DefaultMap.d.ts +70 -39
- package/classes/DefaultMap.lua +94 -43
- package/classes/ModUpgraded.d.ts +3 -3
- package/classes/ModUpgraded.lua +5 -0
- package/constants.lua +41 -0
- package/constantsFirstLast.lua +63 -0
- package/enums/HealthType.lua +3 -0
- package/enums/ModCallbackCustom.d.ts +62 -40
- package/enums/ModCallbackCustom.lua +46 -38
- package/enums/private/CopyableIsaacAPIClassType.lua +1 -0
- package/enums/private/SerializationBrand.lua +5 -0
- package/features/characterHealthConversion.lua +6 -0
- package/features/characterStats.lua +17 -0
- package/features/debugDisplay/exports.d.ts +17 -0
- package/features/debugDisplay/exports.lua +90 -0
- package/features/debugDisplay/v.d.ts +17 -0
- package/features/deployJSONRoom.d.ts +1 -0
- package/features/deployJSONRoom.lua +56 -0
- package/features/disableInputs.lua +45 -0
- package/features/disableSound.lua +14 -0
- package/features/extraConsoleCommands/commandsDisplay.lua +90 -0
- package/features/extraConsoleCommands/init.lua +16 -0
- package/features/extraConsoleCommands/listCommands.lua +172 -0
- package/features/fadeInRemover.lua +10 -0
- package/features/fastReset.lua +10 -0
- package/features/forgottenSwitch.lua +4 -0
- package/features/getCollectibleItemPoolType.lua +5 -0
- package/features/playerInventory.lua +18 -0
- package/features/ponyDetection.lua +4 -0
- package/features/preventCollectibleRotation.lua +9 -0
- package/features/runInNFrames.lua +50 -0
- package/features/saveDataManager/constants.lua +1 -0
- package/features/saveDataManager/exports.lua +115 -0
- package/features/saveDataManager/load.lua +12 -8
- package/features/saveDataManager/main.lua +16 -3
- package/features/saveDataManager/maps.lua +3 -0
- package/features/saveDataManager/merge.lua +53 -21
- package/features/saveDataManager/save.lua +12 -7
- package/features/sirenHelpers.lua +13 -0
- package/features/taintedLazarusPlayers.lua +11 -0
- package/featuresInitialized.lua +6 -0
- package/functions/array.d.ts +2 -0
- package/functions/array.lua +85 -0
- package/functions/benchmark.lua +6 -0
- package/functions/bombs.d.ts +3 -0
- package/functions/bombs.lua +12 -0
- package/functions/boss.lua +35 -0
- package/functions/cacheFlag.lua +4 -0
- package/functions/cards.lua +60 -0
- package/functions/challenges.lua +1 -0
- package/functions/character.lua +23 -0
- package/functions/charge.lua +39 -0
- package/functions/chargeBar.d.ts +1 -0
- package/functions/chargeBar.lua +4 -0
- package/functions/collectibleCacheFlag.lua +15 -0
- package/functions/collectibleSet.lua +3 -0
- package/functions/collectibleTag.lua +9 -0
- package/functions/collectibles.d.ts +13 -8
- package/functions/collectibles.lua +147 -3
- package/functions/color.lua +18 -0
- package/functions/debug.lua +18 -0
- package/functions/deepCopy.lua +60 -26
- package/functions/deepCopyTests.lua +8 -5
- package/functions/direction.d.ts +8 -0
- package/functions/direction.lua +27 -0
- package/functions/doors.d.ts +1 -0
- package/functions/doors.lua +58 -0
- package/functions/entity.d.ts +4 -4
- package/functions/entity.lua +94 -6
- package/functions/entitySpecific.d.ts +20 -20
- package/functions/entitySpecific.lua +182 -0
- package/functions/entityTypes.d.ts +1 -1
- package/functions/entityTypes.lua +1 -0
- package/functions/enums.d.ts +2 -0
- package/functions/enums.lua +62 -0
- package/functions/familiars.lua +52 -0
- package/functions/flag.lua +77 -0
- package/functions/flying.lua +10 -0
- package/functions/globals.lua +8 -10
- package/functions/gridEntity.lua +105 -0
- package/functions/gridEntitySpecific.d.ts +5 -0
- package/functions/gridEntitySpecific.lua +8 -0
- package/functions/input.lua +11 -0
- package/functions/isaacAPIClass.d.ts +4 -4
- package/functions/isaacAPIClass.lua +15 -3
- package/functions/jsonHelpers.lua +11 -0
- package/functions/jsonRoom.d.ts +2 -0
- package/functions/jsonRoom.lua +5 -0
- package/functions/kColor.lua +9 -0
- package/functions/language.lua +5 -0
- package/functions/log.lua +31 -3
- package/functions/map.lua +18 -0
- package/functions/math.lua +26 -0
- package/functions/npc.lua +24 -0
- package/functions/pickupVariants.d.ts +11 -11
- package/functions/pickupVariants.lua +11 -0
- package/functions/pickups.d.ts +9 -9
- package/functions/pickups.lua +67 -0
- package/functions/pills.lua +45 -0
- package/functions/player.d.ts +7 -0
- package/functions/player.lua +210 -9
- package/functions/playerDataStructures.lua +65 -0
- package/functions/playerHealth.d.ts +3 -0
- package/functions/playerHealth.lua +92 -63
- package/functions/playerIndex.d.ts +2 -0
- package/functions/playerIndex.lua +47 -0
- package/functions/pocketItems.lua +18 -0
- package/functions/positionVelocity.d.ts +3 -0
- package/functions/positionVelocity.lua +46 -0
- package/functions/random.d.ts +2 -0
- package/functions/random.lua +32 -0
- package/functions/revive.d.ts +2 -0
- package/functions/revive.lua +15 -0
- package/functions/rng.d.ts +1 -0
- package/functions/rng.lua +19 -0
- package/functions/roomData.lua +68 -0
- package/functions/roomGrid.lua +21 -0
- package/functions/roomShape.lua +22 -0
- package/functions/rooms.lua +100 -0
- package/functions/run.lua +5 -0
- package/functions/seeds.lua +4 -0
- package/functions/serialization.lua +6 -2
- package/functions/set.d.ts +1 -0
- package/functions/set.lua +22 -0
- package/functions/spawnCollectible.lua +24 -0
- package/functions/sprite.d.ts +2 -0
- package/functions/sprite.lua +25 -0
- package/functions/stage.lua +16 -0
- package/functions/string.lua +6 -0
- package/functions/table.d.ts +12 -0
- package/functions/table.lua +53 -0
- package/functions/tears.d.ts +1 -0
- package/functions/tears.lua +12 -0
- package/functions/transformations.lua +18 -0
- package/functions/trinketCacheFlag.lua +3 -0
- package/functions/trinketGive.lua +24 -0
- package/functions/trinkets.lua +52 -0
- package/functions/tstlClass.d.ts +34 -0
- package/functions/tstlClass.lua +63 -9
- package/functions/ui.d.ts +2 -0
- package/functions/ui.lua +16 -0
- package/functions/utils.d.ts +16 -0
- package/functions/utils.lua +108 -0
- package/functions/vector.lua +13 -16
- package/index.d.ts +1 -0
- package/index.lua +8 -0
- package/initCustomCallbacks.lua +6 -0
- package/interfaces/AddCallbackParameterCustom.d.ts +2 -0
- package/interfaces/ChargeBarSprites.d.ts +1 -0
- package/interfaces/private/TSTLClassMetatable.d.ts +2 -0
- package/lualib_bundle.lua +21 -34
- package/maps/cardMap.lua +1 -0
- package/maps/characterMap.lua +1 -0
- package/maps/defaultPlayerStatMap.lua +1 -0
- package/maps/gridEntityXMLMap.lua +2 -0
- package/maps/pillEffectMap.lua +1 -0
- package/maps/roomShapeToTopLeftWallGridIndexMap.lua +2 -0
- package/maps/roomTypeMap.lua +1 -0
- package/objects/LRoomShapeToRectangles.lua +2 -0
- package/objects/callbackRegisterFunctions.lua +3 -0
- package/objects/colors.lua +4 -0
- package/objects/oppositeDoorSlots.d.ts +4 -0
- package/objects/oppositeDoorSlots.lua +15 -0
- package/objects/roomShapeBounds.lua +2 -0
- package/objects/roomShapeLayoutSizes.lua +4 -0
- package/objects/roomShapeToBottomRightPosition.lua +2 -0
- package/objects/roomShapeToDoorSlotsToGridIndexDelta.lua +2 -0
- package/objects/roomShapeToTopLeftPosition.lua +2 -0
- package/objects/roomShapeVolumes.lua +3 -0
- package/package.json +2 -2
- package/patchErrorFunctions.lua +8 -0
- package/sets/bossSets.lua +23 -0
- package/sets/charactersWithNoRedHeartsSet.lua +2 -0
- package/sets/charactersWithNoSoulHeartsSet.lua +2 -0
- package/sets/lostStyleCharactersSet.lua +2 -0
- package/types/AnyEntity.d.ts +10 -0
- package/types/PickingUpItem.lua +7 -0
- package/upgradeMod.d.ts +4 -4
- package/upgradeMod.lua +18 -0
package/features/fastReset.lua
CHANGED
|
@@ -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)
|
|
@@ -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
|
-
|
|
45
|
-
|
|
46
|
+
iterateTableDeterministically(
|
|
47
|
+
nil,
|
|
48
|
+
newSaveData,
|
|
49
|
+
function(____, key, value)
|
|
46
50
|
if type(key) ~= "string" then
|
|
47
|
-
|
|
51
|
+
return
|
|
48
52
|
end
|
|
49
53
|
local valueType = type(value)
|
|
50
54
|
if valueType ~= "table" then
|
|
51
|
-
|
|
55
|
+
return
|
|
52
56
|
end
|
|
53
57
|
local oldSaveDataForSubscriber = oldSaveData[key]
|
|
54
58
|
if oldSaveDataForSubscriber == nil then
|
|
55
|
-
|
|
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
|
-
|
|
63
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
61
|
-
|
|
88
|
+
iterateTableDeterministically(
|
|
89
|
+
nil,
|
|
90
|
+
newTable,
|
|
91
|
+
function(____, key, value)
|
|
62
92
|
if isSerializationBrand(nil, key) then
|
|
63
|
-
|
|
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
|
-
|
|
99
|
+
return
|
|
70
100
|
end
|
|
71
101
|
keyToUse = numberKey
|
|
72
102
|
end
|
|
73
|
-
if
|
|
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
|
|
112
|
+
elseif isTSTLSet(nil, oldObject) then
|
|
83
113
|
oldObject:add(keyToUse)
|
|
84
114
|
end
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
|
|
115
|
+
end,
|
|
116
|
+
SAVE_DATA_MANAGER_DEBUG
|
|
117
|
+
)
|
|
88
118
|
end
|
|
89
119
|
function mergeTable(self, oldTable, newTable, traversalDescription)
|
|
90
|
-
|
|
91
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
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
|
-
|
|
34
|
+
return
|
|
30
35
|
end
|
|
31
36
|
local saveDataCopy = deepCopy(nil, saveDataWithoutRoom, SerializationType.SERIALIZE, subscriberName)
|
|
32
37
|
allSaveData[subscriberName] = saveDataCopy
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
end,
|
|
39
|
+
SAVE_DATA_MANAGER_DEBUG
|
|
40
|
+
)
|
|
36
41
|
return allSaveData
|
|
37
42
|
end
|
|
38
43
|
function ____exports.saveToDisk(self, mod, saveDataMap, saveDataConditionalFuncMap)
|