Skip to main content

Getting Started

caution

Persist is not production-ready yet, you might experience bugs and missing features!

Example Game

Here is an uncopylocked example game using Persist: https://www.roblox.com/games/13789071125/Persist-Example-Game

Installation

Roblox Studio

If you're using Roblox Studio, you can install Persist by downloading the .rbxm file from the latest release and then insert it into ServerScriptService.

Rojo/Wally

If you're using Wally and Rojo, you can install Persist by adding the following line to your wally.toml:

[dependencies]
Persist = "lukadev-0/persist@0.1.0"

Basic Usage

Lets create a simple script that will put the data into leaderstats.

First, we must get the Players service and require the Persist module:

local Players = game:GetService("Players")
local Persist = require(path.to.persist)

Then, we must create a store, the store will allow us to load the data:

local store = Persist.Store.new("PlayerData", {
-- ...
})

Persist allows anything to be a "key", a key is a unique identifier for our data.

In this case, we want the player to be the key, however, the key must be converted into a string in order to work with datastores, so we must tell Persist how to convert the key (a Player) into a string key.

This is done by passing a key function, this function takes in a key, which is a player in this case, and returns a string

We're going to make the key Player_ followed by the user id of the player:

local store = Persist.Store.new("PlayerData", {
key = function(player: Player)
return `Player_{player.UserId}`
end,
})

Next, we need to add a data function, this will take the player and return the data that needs to be saved.

We're going to get our data from the leaderstats:

local store = Persist.Store.new("PlayerData", {
key = --[[ ... ]],

data = function(player: Player)
return {
money = player.leaderstats.Money.Value,
}
end,
})

Next, we need to add a default function, this will return the default data that the player should have.

local store = Persist.Store.new("PlayerData", {
key = --[[ ... ]],

data = --[[ ... ]],

default = function()
return {
money = 0,
}
end,
})

Next, we'll add a userIds function, this function will return the user ids associated with the key.

Here, we only have one user id, but for more complicated stuff, such as a "groups" system you might have multiple ids.

local store = Persist.Store.new("PlayerData", {
key = --[[ ... ]],

data = --[[ ... ]],

default = --[[ ... ]],

userIds = function(player: Player)
return { player.UserId }
end,
})

Now that we have our store, we need to implement the logic that actually loads and saves the data.

We need to load the player's data whenever a player joins:

Players.PlayerAdded:Connect(function(player)
store:load(player)
end)

store:load() returns a Promise, so we need to use :andThen to get the resolved value.

Players.PlayerAdded:Connect(function(player)
store:load(player)
:andThen(function(session)
-- The player might've left before the session finished loading
if not player:IsDescendantOf(Players) then
return session:release()
end
end)
end)

We added a check to see if the player is still in the game after the session finished loading, we release the session if they left, otherwise that player's data cannot be loaded for 30 minutes.

Next, we're going to listen if the session is released and then kick the player if it did, this is because once a session is released the server can't save their data anymore.

Players.PlayerAdded:Connect(function(player)
store:load(player)
:andThen(function(session)
-- ...

session.released:Connect(function()
player:Kick("Session was released")
end)
end)
end)

Now, we can create the leaderstats using the data in the session.

Players.PlayerAdded:Connect(function(player)
store:load(player)
:andThen(function(session)
-- ...

local money = Instance.new("NumberValue")
money.Value = session.data.money
money.Name = "Money"
money.Parent = leaderstats

leaderstats.Parent = player
end)
end)

We also need to catch and handle any errors that come up, we will kick the player and warn the error.

Players.PlayerAdded:Connect(function(player)
store:load(player)
:andThen(--[[ ... ]])
:catch(function(err)
warn(err)
player:Kick("Data failed to load")
end)
end)

Then, when the player leaves, we must release the session.

Players.PlayerRemoving:Connect(function(player)
local session = store:getSession(player)
if session then
session:release()
end
end)

And that's it! The leaderstats should now save.

Finished Script

Your whole script should look like this:

local Players = game:GetService("Players")
local Persist = require(path.to.persist)

local store = Persist.Store.new("PlayerData", {
key = function(player: Player)
return `Player_{player.UserId}`
end,

data = function(player: Player)
return {
money = player.leaderstats.Money.Value,
}
end,

default = function()
return {
money = 0,
}
end,

userIds = function(player: Player)
return { player.UserId }
end,
})

Players.PlayerAdded:Connect(function(player)
store:load(player)
:andThen(function(session)
-- The player might've left before the session finished loading
if not player:IsDescendantOf(Players) then
return session:release()
end

session.released:Connect(function()
player:Kick("Session was released")
end)

local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"

local money = Instance.new("NumberValue")
money.Value = session.data.money
money.Name = "Money"
money.Parent = leaderstats

leaderstats.Parent = player
end)
:catch(function(err)
warn(err)
player:Kick("Data failed to load")
end)
end)

Players.PlayerRemoving:Connect(function(player)
local session = store:getSession(player)
if session then
session:release()
end
end)