Player Data
Saves use Scribe 2.5, set up in ReplicatedStorage > Shared > Accounts:
| Module | What it is |
|---|---|
Template | The saved shape and its defaults. |
AccountTypes | The matching Luau types. |
AccountData | The Scribe bundle, and the leaderboards. |
Migrations | Steps that update old saves. |
The save keys are in Config > Project.
Stored Fields
| Field | Holds |
|---|---|
towers, allJumps | Completion points, Normal and All Jumps. |
elo | The player's Elo. |
completedTowers, completedAjTowers | Towers beaten, by acronym. |
completedTowerRushes | Rushes beaten. |
towerStats, towerRushStats | Attempts, wins, time spent and best times. |
tickets | Ticket balance. |
ownedShopItems, ownedCosmetics, equippedCosmetics | Shop items and cosmetics. |
backpackSlots, backpackFilters | Backpack order and hidden items. |
uiLayout | Where the player moved each control with Edit UI Layout. |
settings | Settings and keybinds, including settings.custom for your own settings. |
custom | Your own values, through Server > CustomData. See Hooking Into the Kit. |
eloTowers, eloAjTowers, eloHistoryImported, claimedGamePassRewards | Bookkeeping, never sent to clients. |
Lists of IDs are Scribe.SetOf: use Has, Add and Remove on them.
Leaderboards
Three leaderboards rank every player who has ever played:
| Board | Ranks | Data store |
|---|---|---|
Towers | towers | LB_Towers |
AllJumps | allJumps | LB_AllJumps |
Elo | elo | LB_Elo |
To show one with Roblox's own leaderboard:
- In the Creator Hub, open your experience.
- Register the data store from the table. The key is the player's
UserId. - Turn on Active leaderboard.
Roblox shows one active leaderboard per experience. Never rename these stores after release; a new name is a new, empty board.
The leaderboard admin command prints the top of any board. In code:
for _, entry in ipairs(Data.GetLeaderboard("Elo", 10)) do
print(entry.Rank, entry.Name, entry.Score)
endIn Studio, Mock and NoSave modes use a temporary board that's gone when the test stops.
Add A Saved Field
You probably don't need to
- Your own numbers, text and flags:
Server > CustomData. See Hooking Into the Kit. - A player setting: one entry in
Config > CustomSettings. See Adding A Saved Setting.
To change the kit's own shape:
- Add the field and its default to
Template. - Add it to
PlayerDatainAccountTypes. - Read and write it through Scribe from the feature that owns it.
- Test with
dataStoreStudioMode = "Mock".
In a released game, rename or reshape a field with a numbered step in Migrations: add the next number, never reuse one. See Scribe's templates and configuration guides.
Reading Saved Data On The Client
Watch the part of the save you read, never the root:
Data.settings.Observe(function(settings)
-- runs only when a setting changes
end)A root observer re-runs on every write, so earning one ticket would rebuild everything that watches it.
When Data Fails
Scribe removes a player whose save can't load, or whose session moved to another server. What they're told is under dataKicks in Config > Messages.
Admins can use data-summary, data-save and, for a deletion request, data-erase. See Admin Commands.
Recovering Lost Completions
recount-badges <player> rebuilds a player's completions from the badges they own, for when a save is lost. It reads the badgeIds in Config > Towers, not tower attributes, so every tower needs its badge there. Best times and attempts are kept. If reading badges fails, nothing is changed.