UNPKG

isaacscript-common

Version:

Helper functions and features for IsaacScript mods.

262 lines • 12.4 kB
import { SaveDataKey } from "../../../enums/SaveDataKey"; import type { SaveData } from "../../../interfaces/SaveData"; import type { AnyClass } from "../../../types/AnyClass"; import { Feature } from "../../private/Feature"; export declare class SaveDataManager extends Feature { /** * We store a local reference to the mod object so that we can access the corresponding methods * that read and write to the "save#.dat" file. */ private readonly mod; /** * The save data map is indexed by subscriber name. We use Lua tables instead of TypeScriptToLua * Maps for the master map so that we can access the variables via the in-game console when * debugging. (TSTL Maps don't expose the map keys as normal keys.) */ private readonly saveDataMap; /** * When mod feature data is initialized, we copy the initial values into a separate map so that we * can restore them later on. */ private readonly saveDataDefaultsMap; /** * Each mod feature can optionally provide a function that can control whether the save data is * written to disk. */ private readonly saveDataConditionalFuncMap; /** * We backup some save data keys on every new room for the purposes of restoring it when Glowing * Hour Glass is used. * * Note that the save data is backed up in serialized form so that we can use the `merge` function * to restore it. */ private readonly saveDataGlowingHourGlassMap; /** * End-users can register their classes with the save data manager for proper serialization when * contained in nested maps, sets, and arrays. */ private readonly classConstructors; private inARun; private restoreGlowingHourGlassDataOnNextRoom; private readonly postUseItemGlowingHourGlass; private readonly postPlayerInit; private readonly preGameExit; private readonly postNewLevel; private readonly postNewRoomEarly; /** * This is the entry point to the save data manager, a system which provides two major features: * * 1. Automatic resetting of variables on a new run, on a new level, or on a new room (as * desired). * 2. Automatic saving and loading of all tracked data to the "save#.dat" file. * * You provide this function with an object containing your variables, and then it will * automatically manage them for you. (See below for an example.) * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * (Upgrade your mod before registering any of your own callbacks so that the save data manager * will run before any of your code does.) * * The save data manager is meant to be called once for each feature of your mod. In other words, * you should not put all of the variables for your mod on the same object. Instead, scope your * variables locally to a single file that contains a mod feature, and then call this function to * register them. For example: * * ```ts * // In file: feature1.ts * * // Declare local variables for this file or feature. * const v = { * // These variables are never reset; manage them yourself at will. * persistent: { * foo1: 0, * }, * * // These variables are reset at the beginning of every run. * run: { * foo2: 0, * }, * * // These variables are reset at the beginning of every level. * level: { * foo3: 0, * }, * * // These variables are reset at the beginning of every room. * room: { * foo4: 0, * }, * }; * // The child objects of "persistent", "run", "level", and "room are optional; only create the * // ones that you need. * * // Now, give `v` to the save data manager, and it will automatically manage the variables for * // you. * mod.saveDataManager("feature1", v); * * // Elsewhere in the file, use your variables. * function feature1Function() { * if (v.run.foo1 > 0) { * // Insert code here. * } * } * ``` * * - Save data is loaded from disk in the `POST_PLAYER_INIT` callback (i.e. the first callback * that can possibly run). * - Save data is recorded to disk in the `PRE_GAME_EXIT` callback. * * You can use many different variable types on your variable object, but not everything is * supported. For the specific things that are supported, see the documentation for the `deepCopy` * helper function. * * If you want the save data manager to load data before the `POST_PLAYER_INIT` callback (i.e. in * the main menu), then you should explicitly call the `saveDataManagerLoad` function. (The save * data manager cannot do this on its own because it cannot know when your mod features are * finished initializing.) * * Some features may have variables that need to be automatically reset per run/level, but not * saved to disk on game exit. (For example, if they contain functions or other non-serializable * data.) For these cases, set the second argument of this function to `false`. * * Note that when the player uses Glowing Hourglass, the save data manager will automatically * restore any variables on a "run" or "level" object with a backup that was created when the room * was entered. Thus, you should not have to explicitly program support for Glowing Hourglass into * your mod features that use the save data manager. If this is undesired for your specific * use-case, then add a key of `__ignoreGlowingHourGlass: true` to your "run" or "level" object. * * By default, the Glowing Hour Glass functionality will not apply to "persistent" objects. If * this is undesired, you can add a key of `__rewindWithGlowingHourGlass: true` to the object. * * @param key The name of the file or feature that is submitting data to be managed by the save * data manager. The save data manager will throw an error if the key is already * registered. Note that you can also pass a TSTL class instead of a string and the * save data manager will use the name of the class as the key. * @param v An object that corresponds to the `SaveData` interface. The object is conventionally * called "v" for brevity. ("v" is short for "local variables"). * @param conditionalFunc Optional. A function to run to check if this save data should be written * to disk. Default is `() => true`, meaning that this save data will * always be written to disk. Use a conditional function for the situations * when the local variables are for a feature that the end-user can * disable. (If the feature is disabled, then there would be no point in * writing any of the variables to the "save#.dat" file.) You can also * specify `false` to this argument in order to completely disable saving * data. (Specifying `false` will allow you to use non-serializable objects * in your save data, such as `EntityPtr`. * @public */ saveDataManager<Persistent, Run, Level>(key: string | object, v: SaveData<Persistent, Run, Level>, conditionalFunc?: () => boolean): void; saveDataManager(key: string | object, v: SaveData, conditionalFunc: false): void; /** * Recursively traverses an object, collecting all of the class constructors that it encounters. */ private storeClassConstructorsFromObject; /** * The save data manager will automatically load variables from disk at the appropriate times * (i.e. when a new run is started). Use this function to explicitly force the save data manager * to load all of its variables from disk immediately. * * Obviously, doing this will overwrite the current data, so using this function can potentially * result in lost state. * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * * @public */ saveDataManagerLoad(): void; /** * The save data manager will automatically save variables to disk at the appropriate times (i.e. * when the run is exited). Use this function to explicitly force the save data manager to write * all of its variables to disk immediately. * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * * @public */ saveDataManagerSave(): void; /** * Sets the global variable of "g" equal to all of the save data variables for this mod. * * This can make debugging easier, as you can access the variables from the game's debug console. * e.g. `l print(g.feature1.run.foo)` * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * * @public */ saveDataManagerSetGlobal(): void; /** * By default, the save data manager will not be able to serialize/deserialize classes that are * nested inside of maps, sets, and arrays, because it does not have access to the corresponding * class constructor. If you want to use nested classes in this way, then use this function to * register the class constructor with the save data manager. Once registered, the save data * manager will automatically run the constructor when deserializing (in addition to copying over * the data fields). * * This function is variadic, which means you can pass as many classes as you want to register. * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * * @public */ saveDataManagerRegisterClass(...tstlClasses: readonly AnyClass[]): void; /** * Removes a previously registered key from the save data manager. This is the opposite of the * "saveDataManager" method. * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * * @public */ saveDataManagerRemove(key: string): void; /** * The save data manager will automatically reset variables at the appropriate times, like when a * player enters a new room. Use this function to explicitly force the save data manager to reset * a specific variable group. * * For example: * * ```ts * const v = { * room: { * foo: 123, * }, * }; * * mod.saveDataManager("file1", v); * * // Then, later on, to explicit reset all of the "room" variables: * mod.saveDataManagerReset("file1", "room"); * ``` * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * * @public */ saveDataManagerReset(key: string, childObjectKey: SaveDataKey): void; /** * Helper function to check to see if the game is in the menu, as far as the save data manager is * concerned. This function will return true when the game is first opened until the * `POST_PLAYER_INIT` callback fires. It will also return true in between the `PRE_GAME_EXIT` * callback firing and the `POST_PLAYER_INIT` callback firing. * * This function is useful because the `POST_ENTITY_REMOVE` callback fires after the * `PRE_GAME_EXIT` callback. Thus, if save data needs to be updated from the `POST_ENTITY_REMOVE` * callback and the player is in the process of saving and quitting, the feature will have to * explicitly call the `saveDataManagerSave` function. * * In order to use this function, you must upgrade your mod with `ISCFeature.SAVE_DATA_MANAGER`. * * @public */ saveDataManagerInMenu(): boolean; /** * Helper function to see all of the mod features that are using the save data manager. Useful for * debugging if a certain mod feature is not getting its data saved correctly. * * @public */ saveDataManagerLogSubscribers(): void; } //# sourceMappingURL=SaveDataManager.d.ts.map