HasSaveSlots
Functions
ObserveActiveSlotStoreBrio
HasSaveSlots.ObserveActiveSlotStoreBrio(self: HasSaveSlots) → Observable.Observable<Brio.Brio<DataStoreStage.DataStoreStage>>Observes the DataStoreStage for the active slot as a Brio
PromiseActiveSlotStore
HasSaveSlots.PromiseActiveSlotStore(self: HasSaveSlots) → Promise.Promise<DataStoreStage.DataStoreStage?>Returns the DataStoreStage for the active slot
PromiseSlotsLoaded
Promises that all slots have loaded
PromiseHasSlot
HasSaveSlots.PromiseHasSlot(slotId: SaveSlotData.SlotId?) → Promise.Promise<boolean>Returns whether the slot with the given ID exists
PromiseSelectSlot
HasSaveSlots.PromiseSelectSlot(slotId: SaveSlotData.SlotId) → Promise.Promise<any>Selects the slot with the given ID
PromiseDeselectSlot
Clears the active slot selection, returning the player to a no-slot state -- the counterpart to HasSaveSlots.PromiseSelectSlot, backing a "back to menu" affordance. The active slot's progress is flushed first (mirroring the save PromiseSelectSlot runs when switching away), and the last-active slot is remembered, so HasSaveSlots.PromiseSelectLastSaveSlot can resume it later. A no-op when no slot is active.
PromiseCreateSlot
HasSaveSlots.PromiseCreateSlot() → Promise.Promise<SaveSlotData.SlotId>Creates a slot at the given index
PromiseExportSlot
Exports a slot's saved data into a plain, serializable SaveSlotExportUtils.SaveSlotExport. Rejects the main/default slot by default: its store is the player's shared root datastore, so exporting it would leak the SaveSlots system data and universe-scoped global data living alongside it. Only isolated non-main slot substores are exportable.
allowMainSlot opts out of that refusal for trusted admin tooling (see SaveSlotCmdrService).
The SaveSlots system data is always stripped from the result, so the export never carries the
slot roster or the other slots' saved data. Universe-scoped global data sharing the root store
is indistinguishable from the main slot's own data and is still carried, which is why this is
not exposed through SaveSlotService.
PromiseImportSlot
Imports an exported slot into a fresh slot at the lowest free non-main index, seeding the new slot's store with the exported data. Never uses the main/default index -- importing onto the shared root store would wipe the player's global data. Resolves to the new slot's id. Rejects a malformed export, or when no non-main index is free.
PromiseSaveSlotToSharedDataStore
Exports a non-main slot (see HasSaveSlots.PromiseExportSlot) and writes it to the shared save slot store under the given key.
PromiseImportSlotFromSharedDataStore
Reads an export from the shared save slot store and imports it into a fresh non-main slot (see HasSaveSlots.PromiseImportSlot). Rejects when no export is stored under the key.
PromiseSelectTransferableEphemeralSlot
Loads the export stored under the given shared-store key into a fresh ephemeral slot and selects it, remembering the key so a teleport can carry the slot forward (see the transferable-ephemeral teleport provider in SaveSlotService). Like every ephemeral slot it is never persisted, stays out of the slot list, and is torn down on deselect. Rejects when no valid export is stored under the key.
PromiseBuildEphemeralTransferSlice
Builds this player's teleport slice for a transferable ephemeral slot: re-saves the active slot's current live data to the shared store under its key and returns a slice carrying that key. Resolves nil when the active slot is not a transferable ephemeral slot. A failed re-save degrades to nil so a teleport is never blocked (the destination then re-loads the last saved state). Asynchronous -- it is consumed through TeleportDataService.PromiseBuildTeleportData.
PromiseLoadTransferableEphemeralSlotFromTeleport
HasSaveSlots.PromiseLoadTransferableEphemeralSlotFromTeleport(self: HasSaveSlots) → Promise<SlotId?>Selects the transferable ephemeral slot the player teleported in with, from the shared-store key in their arrived data. Reads the unified band (not trusted-only) so a client-initiated teleport -- the common case, e.g. a menu resume hop -- carries it too; a server-initiated teleport still works via the trusted band. Resolves to the slot id, or nil when none arrived.
Because the client band is honored, a client can present any key it knows. The key resolves to a server-side shared-store entry and only ever seeds a throwaway (never-persisted) slot, so the exposure is read-only visibility of a snapshot whose code you already have -- acceptable for the dev/Cmdr tooling this backs. Harden (longer code entropy / ownership) before exposing it to a player-facing surface.
SetCodeGenerator
Overrides the share-code generator for this player's exports (see SaveSlotCodeUtils.CodeGenerator). Games inject a custom format; the default is SaveSlotCodeUtils.generateDefaultCode. Usually set game-wide via SaveSlotService.SetCodeGenerator rather than per player.
PromiseExportSaveSlotToCode
HasSaveSlots.PromiseExportSaveSlotToCode(slotId: SlotId?,--
defaults to the active slot
) → Promise<string>
Exports a slot to the shared store under a fresh generated code and resolves to that code. The code
is a shareable handle other sessions load with HasSaveSlots.PromiseImportEphemeralSaveSlotFromCode.
Defaults to the active slot. Refuses the main slot unless allowMainSlot is set (see
HasSaveSlots.PromiseExportSlot). The code format comes from the configured generator (see
HasSaveSlots.SetCodeGenerator).
PromiseImportEphemeralSaveSlotFromCode
Loads the slot stored under the given code into a fresh transferable ephemeral slot and selects it (see HasSaveSlots.PromiseSelectTransferableEphemeralSlot). Resolves to the new slot id.
PromiseExportSaveSlotToJson
HasSaveSlots.PromiseExportSaveSlotToJson(slotId: SlotId?,--
defaults to the active slot
) → Promise<string>
Exports a slot as a raw JSON string (no shared store), for direct inspection or attaching to a bug
report. Defaults to the active slot. Refuses the main slot unless allowMainSlot is set (see
HasSaveSlots.PromiseExportSlot).
PromiseDuplicateSlot
HasSaveSlots.PromiseDuplicateSlot(slotId: SaveSlotData.SlotId) → Promise.Promise<SaveSlotData.SlotId>Duplicates the slot with the given ID into a new slot at the lowest free index, copying its saved data. Resolves to the new slot's id. The copy is not selected, its metadata (playtime, timestamps) starts fresh, and its name is suffixed with " (Copy)". Rejects when the source slot is missing or every index is in use.
An ephemeral slot may be duplicated: the copy is a real, persisted slot seeded with the ephemeral slot's live in-memory data, which is how a throwaway session is turned into a save. It keeps the source's name unsuffixed (the copy is the first real slot for that session, not a second copy of an existing save) and, like any duplicate, is not selected -- see HasSaveSlots.PromisePersistEphemeralSlot for the version that continues play on the new slot.
PromisePersistEphemeralSlot
HasSaveSlots.PromisePersistEphemeralSlot(slotId: SlotId?--
defaults to the active slot
) → Promise<SlotId>Turns an ephemeral slot into a real save: duplicates it into a fresh persisted slot at the lowest free index (see HasSaveSlots.PromiseDuplicateSlot) and selects that slot, so play continues on data that is now being written. Defaults to the active slot, which in practice is the only ephemeral slot there is -- one stops existing the moment it stops being active. Resolves to the new slot's id.
The copy is taken from the ephemeral slot's live in-memory data at the moment this runs, and selecting the new slot retires the ephemeral one, so anything written to the old store between the copy and the selection is dropped. Rejects when no slot is active, the slot is missing, the slot is not ephemeral, or every index is in use.
PromiseDeleteSlot
HasSaveSlots.PromiseDeleteSlot(slotId: SaveSlotData.SlotId) → Promise.Promise<any>Deletes the slot with the given ID. Deleting an ephemeral slot ends that session -- it is deselected and retired along with its in-memory store -- rather than being refused for being the active slot.
PromiseDeleteAllSlots
Deletes every slot for the player and clears the active/last-active selection, resetting the player to a fresh state. Resolves once all slots are gone.
PromiseResetSlot
HasSaveSlots.PromiseResetSlot(slotId: SaveSlotData.SlotId) → Promise.Promise<SaveSlotData.SlotId>Resets the slot with the given id to a fresh empty one -- equivalent to deleting the slot and creating a new one at the same index. The slot keeps its index and name; its saved data and metadata (timestamps) start fresh. Resolves to the new slot id.
When the reset slot is the active slot, the selection clears and then reselects the fresh slot: everything bound to HasSaveSlots.ObserveActiveSlotStoreBrio tears down as the selection clears and rebuilds against the empty store on reselect, so consumers reset reactively without wiping their own state. A non-active slot is left unselected, and its "Continue" pointer (when it was the last-active slot) is carried across to the fresh id so the reset slot stays resumable. Rejects when the slot is missing.
PromiseResetActiveSlot
Resets the active slot to a fresh empty one -- see HasSaveSlots.PromiseResetSlot. The slot keeps its index and name; its saved data and metadata (timestamps) start fresh, and the fresh slot stays selected. Resolves to the new slot id, or nil when no slot is active.
PromiseSetSlotMetadata
HasSaveSlots.PromiseSetSlotMetadata() → Promise.Promise<any>Sets the metadata for the slot with the given ID
PromiseGetSlotMetadata
HasSaveSlots.PromiseGetSlotMetadata(slotId: SaveSlotData.SlotId) → Promise.Promise<SaveSlotData.SaveSlotMetadata?>Gets the metadata for the slot with the given ID
PromiseSlotIdFromIndex
HasSaveSlots.PromiseSlotIdFromIndex(slotIndex: number) → Promise.Promise<SaveSlotData.SlotId?>Returns the slot ID from the given index
PromiseLastActiveSlotId
Gets the last active slot ID
PromiseSelectLastSaveSlot
Selects the player's last active slot if one still exists, resolving to the selected slot id -- or nil when there is no slot to continue on. Backs a "Continue" affordance that every save-slot consumer tends to need.
PromiseSelectNewSaveSlot
Creates a new slot at the lowest free index and selects it, resolving to the new slot id -- or nil when every slot is already in use. Backs a "New Game" affordance.
PromiseSelectEphemeralSlot
HasSaveSlots.PromiseSelectEphemeralSlot(metadata: SaveSlotCreateMetadata?--
optional SlotName/Summary for the in-memory slot
) → Promise<SlotId>Creates a fresh ephemeral slot and selects it, resolving to its id. An ephemeral slot is selectable and active exactly like a real one -- it drives HasSaveSlots.ObserveActiveSlotStoreBrio, summaries, and playtime the same way, and its metadata replicates to the client like any other slot's, so UI can render the active session's name and summary -- but it is never persisted: no metadata is written, its data store is in-memory, and it is torn down the moment it stops being the active slot. It is also excluded from the save list (SaveSlotDataService.GetSlotList / SaveSlotDataService.ObserveSlotList), so it never shows up as something the player can return to. Selecting it never disturbs the persisted active-slot pointer or the "Continue" target, so the real slot the player came from resumes untouched afterward. Backs a throwaway session (e.g. exploring a lobby) that must leave no trace on save data.
RegisterSummaryProvider
HasSaveSlots.RegisterSummaryProvider() → () → ()
Registers a named summary provider. Every registered provider's current value is aggregated into
the active slot's Summary, keyed by name (see HasSaveSlots.PromiseGetSlotMetadata). Registering
the same name again replaces the previous provider. Returns a function that unregisters the provider
(also give it to a [Maid]).
_setupPlaytimeTracking
Accrues per-slot playtime automatically. A "session" spans the time a slot is the active slot: selecting a slot begins one (bumping PlayCount), and deselecting, switching, or unbinding ends it. Elapsed wall time is folded into the slot's TimePlayed from a datastore saving callback, so it persists on exactly the cadence the data is written -- always fresh at save time, with no separate timer -- and again at each session boundary.