isaacscript-common
Version:
Helper functions and features for IsaacScript mods.
262 lines • 12.4 kB
TypeScript
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