ProfileDB
A class for managing player profiles. This class is used to store and retrieve player data. It can be used to store player data such as currency, inventory, and other player-specific data.
Key Features:
- Automatically loads and saves player data to the data store
- Automatically reconciles player data with a template
- Supports saving player data to a web API if provided
- Session locking to prevent multiple servers from saving the same player data at the same time
- Supports saving player data in Studio
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local ProfileDB = require(ServerScriptService.ProfileDB)
local ProfileDataTemplate = {
coins = 100,
inventory = {},
}
local profileDBSettings: ProfileDB.Settings = {
mockDataStore = false,
dataStoreName = "Profile",
dataStoreVersion = 1,
template = ProfileDataTemplate,
}
Players.PlayerAdded:Connect(function(player)
local profile = ProfileDB.new(player.UserId, profileDBSettings)
profile:Reconcile() -- Add any missing tables to the player's profile
local profileData = profile:GetData()
profileData.coins += 100 -- Add 100 coins to the player's profile
profile:Save() -- Save the player's profile data
end)
Need to track updates to the player's profile data?
profile.Changed:Connect(function(profileData)
print("Player data was updated", profileData.data.coins)
end)
Install with wally by adding the following to your wally.toml
:
ProfileDB = "dig1t/profiledb@1.0.5"
Types
ProfileData
type
ProfileData =
{
[
string
]
:
any
}
ProfileData contains the player's data
ProfileMetadata
interface
ProfileMetadata {
created:
number
--
The time the profile was created.
last_seen:
number
--
The time the player was last seen.
sessions:
number
--
The number of times the player has joined the game.
sessionData:
{
lastUpdate:
number
,
jobId:
string
}
?
--
Session data for the player.
}
ProfileMetadata contains everything that's saved to Roblox.
The data
table will contain the player's data.
Template
Template is the template for the profile data. It can be a table of default values or a function that returns a table of default values.
Properties
canSaveToDataStore
ProfileDB.canSaveToDataStore:
boolean
Whether or not the game can save to the data store.
Functions
new
ProfileDB.
new
(
userId:
number
,
--
The user ID of the player
) →
Profile
--
The new ProfileDB instance
Types
interface
Settings {
saveToDataStore:
boolean
--
If the mock data store should be used.
dataStoreName:
string
--
The name of the data store.
dataStoreVersion:
number?
--
The version of the data store.
apiURL:
string?
--
If provided, this URL will be used to send saved player data to an API.
saveInStudio:
boolean?
--
If the data store should be used in Studio.
saveInterval:
number
--
The interval in seconds to save the player's data.
keysToIgnore:
{
string
}
?
--
The keys to ignore when saving the player's data.
}
Creates a new ProfileDB instance
A settings table can be provided to configure the ProfileDB instance.
GetTemplate
ProfileDB:
GetTemplate
(
) →
ProfileData
--
The template provided in the constructor or the result of the template function if the template is a function
Returns the template given in the constructor
GetLastVersion
ProfileDB:
GetLastVersion
(
) →
(
boolean
,
string?
)
--
Whether or not the fetch was successful and the last version if successful
Fetches the last version from the version history data store
GetNewData
Creates a new profile data object
Save
ProfileDB:
Save
(
releaseSession:
boolean?
--
Whether or not to release the session lock
) →
boolean
--
Whether or not the profile was saved
Returns whether or not the profile was saved
Reconcile
ProfileDB:
Reconcile
(
) →
(
)
Reconciles the profile data with the template provided in the constructor
Reset
ProfileDB:
Reset
(
) →
(
)
Resets the profile data to the template provided in the constructor
Get
ProfileDB:
Get
(
path:
string?
--
The path to the value
) →
any
--
The value at the given path or nil if the value does not exist
Returns the value at the given path in the profile data
Not providing a path will return the entire profile data table
Set
ProfileDB:
Set
(
path:
string
,
--
The path to the value
value:
any
,
--
The value to set
skipUpdate:
boolean?
--
Whether or not to skip firing the Changed signal
) →
boolean
--
Whether or not the value was set
Sets the value at the given path in the profile data.
If nil is provided as the value, the key will be removed from the path.
If you want to insert a value into a table, you can use "++" as the last key in the path.
Example:
profile:Set("purchases.++", "dev_product_receipt_12345")
Need to store unique data in a table?
profile:Set("inventory.weapons.++", {
uniqueWeaponId = "weapon_12345",
skin = "RARE_SKIN_ID",
})
If the weapon were to be sold or removed, you can remove it by finding its index.
for index, weapon in profile:Get("inventory.weapons") do
if weapon.uniqueWeaponId == "weapon_12345" then
profile:Set("inventory.weapons.--", index)
break
end
end
SetMultiple
ProfileDB:
SetMultiple
(
data:
{
[
string
]
:
any
}
--
The data paths to set
) →
{
string
}
--
The keys that were updated
Sets multiple values in the profile data.
Unset
ProfileDB:
Unset
(
path:
string
--
The path to the value
) →
boolean
--
Whether or not the value was unset
Unsets the value at the given path in the profile data.
Alias for profile:Set(path, nil)
.
UnsetMultiple
ProfileDB:
UnsetMultiple
(
data:
{
string
}
--
The data paths to unset
) →
{
string
}
--
The keys that were removed
Unsets multiple values in the profile data.
Insert
ProfileDB:
Insert
(
path:
string
,
--
The path to the table
value:
any
,
--
The value to insert
skipUpdate:
boolean?
--
Whether or not to skip firing the Changed signal
) →
boolean
--
Whether or not the value was inserted
Inserts a number indexed value into a table at the given path.
Example
print(profile.metadata.data.inventory) -- { "item_12345", "item_67890" }
profile:Insert("inventory", "item_54321")
print(profile.metadata.data.inventory) -- { "item_12345", "item_67890", "item_54321" }
Need to insert it into a nested table?
print(profile.metadata.data.inventory.weapons) -- { "weapon_12345", "weapon_67890" }
profile:Insert("inventory.weapons", "weapon_54321")
print(profile.metadata.data.inventory) -- { "weapon_12345", "weapon_67890", "weapon_54321" }
InsertMultiple
ProfileDB:
InsertMultiple
(
path:
string
,
--
The path to the table
data:
{
any
}
--
The values to insert
) →
{
string
}
--
The keys that were updated
Inserts multiple values into a table at the given path.
RemoveValue
ProfileDB:
RemoveValue
(
path:
string
,
--
The path to the table
value:
any
,
--
The value to remove
skipUpdate:
boolean?
--
Whether or not to skip firing the Changed signal
) →
boolean
--
Whether or not the value was removed
This method will remove a value from a table.
Example
print(profile.metadata.data) -- { inventory = { "item_12345", "item_67890" } }
profile:RemoveValue("inventory", "item_12345")
print(profile.metadata.data) -- { inventory = { "item_67890" } }
RemoveMultiple
ProfileDB:
RemoveMultiple
(
path:
string
,
--
The path to the table
data:
{
[
string
]
:
any
}
--
The path and values to remove
) →
{
string
}
--
The keys that were removed
Removes multiple values from a table at the given path.
Increment
ProfileDB:
Increment
(
path:
string
,
--
The path to the value
value:
number
--
The value to increment by
) →
boolean
--
Whether or not the value was incremented
Increments the value at the given path in the profile data.
SetData
ProfileDB:
SetData
(
) →
boolean
--
Whether or not the data was updated
Updates the profile data using a callback function.
This method can be dangerous and destructive if used incorrectly. For example yielding in the callback function can cause data loss.
Example
profile:SetData(function(data: ProfileDB.ProfileMetadata)
data.coins = 100
end)
Destroy
CleanupProfileDB:
Destroy
(
) →
(
)
Destroys the profile and disconnects all events.