Leaderstats
Maps profile or session fields onto the Roblox player-list leaderstats folder and keeps the values current while players are in the server.
- Realm
- Server
- Require
ServerScriptService.ChloeKernelServer .Leaderstats - Since
- v0.1.0
- Source
- Leaderstats.luau
Leaderstats wires the leaderstats folder that the Roblox player list reads: the per-server numbers beside each name.
Declare which data field each stat shows, and the module creates the value objects when a session starts, keeps them
current, and removes them when it ends. It never writes data anywhere. For a persisted, cross-server ranking, use
Leaderboards; the two are independent and often fed from the same fields.
Mental model
Section titled “Mental model”The player list works by convention: a Folder named leaderstats under the player, holding IntValue,
NumberValue or StringValue instances. Leaderstats owns that folder against the kernel’s
session lifecycle:
- On every session start (
kernel:onSession), it creates theleaderstatsfolder, or asks yourGetContainerfor one, and one value object per declared stat, seeded from the data. - It refreshes a session the moment its profile loads (
Kernel.ProfileLoaded), so persisted values appear as soon as the DataDriver profile arrives instead of on the next sweep. - A sweep copies current data into the value objects every
UpdateSeconds(default 1 s) atBackgroundpriority. Plain data tables have no change events, which is why it sweeps. The sweep job starts with the first session and is cancelled when the last session ends, so an empty server runs nothing. - On session end (
session:bind), it destroys the folder it created, or only its own value objects when the folder came fromGetContainer.
Each stat reads its field from session.Profile.Data (the persisted record) or session.Data (per-visit). By default it
reads the profile when one exists and session data otherwise, so persisted stats show persisted values with no extra
configuration.
A nil field leaves the value object as it is. An IntValue shows 0 until the field exists; seed the field in your
profile Defaults if 0 on first join is wrong.
Type checks
Section titled “Type checks”Each field is assigned on its own, so one bad field cannot stop the others. IntValue and NumberValue do not throw
on a value they cannot convert: the engine prints a warning with a stack trace and keeps the old value. Leaderstats
therefore checks number stats first, and a value that tonumber cannot convert (a table, a boolean) is skipped with one
warning per stat: [Leaderstats] could not show Coins = true: expected a number, got boolean. StringValue assignments
run inside a pcall and warn the same way. The warning fires once per stat name for the life of the handle, not once
per player or sweep.
--!strict-- StatsService: coins, best stage and title in the player list.
local ServerScriptService = game:GetService("ServerScriptService")
local Leaderstats = require(ServerScriptService.ChloeKernelServer.Leaderstats)
local StatsService = { Name = "StatsService", Dependencies = { "DataService" },}
function StatsService.init(self: any, kernel: any) self.Stats = Leaderstats.attach(kernel, { Coins = { Field = "Coins" }, -- session.Profile.Data.Coins Stage = { Field = "BestStage" }, Title = { Field = "Title", Kind = "StringValue", From = "Session" }, -- session.Data.Title })end
function StatsService.stop(self: any) if self.Stats then self.Stats.detach() endend
return StatsServicesession.Profile.Data.Coins += 100 shows in the player list within one sweep. The keys of the stats table are the
names the player list shows.
Configuration
Section titled “Configuration”Leaderstats.attach(kernel, stats, options?). stats maps each display name to:
| Field | Default | Description |
|---|---|---|
Field |
required | The data field to read. |
From |
the profile if one exists, else the session | "Profile" reads session.Profile.Data; "Session" reads session.Data. |
Kind |
"IntValue" |
"IntValue", "NumberValue" or "StringValue". |
Options:
| Option | Default | Description |
|---|---|---|
UpdateSeconds |
1 |
Sweep cadence while sessions exist. |
GetContainer |
creates leaderstats |
(player) -> Instance. Supply a container another system also writes to; the module then owns only its value objects. |
SkipLoop |
false |
Never schedule the sweep; specs call sweep() by hand. |
API reference
Section titled “API reference”| Member | Description |
|---|---|
Leaderstats.attach(kernel, stats, options?) -> handle |
Wires the mapping. Hooks session start and Kernel.ProfileLoaded at once; the sweep starts with the first session. |
handle.sweep() |
Runs one refresh pass over every tracked session. |
handle.detach() |
Cancels the sweep, disconnects the session and profile listeners, and cleans up every tracked container or value object. |
Bus topics
Section titled “Bus topics”Leaderstats publishes nothing. It consumes Kernel.ProfileLoaded(session, profile) to refresh a session as soon as its
profile loads.