Hello everyone,
I recently developed a DataManager Module for Roblox that is designed to load and save player data. It’s kept simple but is also flexible and reusable for different data stores (e.g., for Leaderstats or Items). It uses UpdateAsync
to efficiently update player data.
Here is the ModuleScript: (80 Lines)
local DataStoreService = game:GetService("DataStoreService")
local httpService = game:GetService("HttpService")
local DataManager = {}
-- //: If plr isn't valid: false.
-- //: If player is valid: true.
local function checkPlayer(plr: Player)
if not plr or not plr:IsA("Player") then
warn("Invalid Player as argument, got: "..tostring(typeof(plr)))
return false
end
return true
end
-- //: Function for Loading Data
DataManager.LoadData = function(plr: Player, dataStoreName: string)
if not checkPlayer(plr) then return end -- Check if player argument is valid
-- Get the DataStore and the key:
local dataStore = DataStoreService:GetDataStore(dataStoreName)
local key = plr.UserId
-- Try to get the Data for the Player:
local success, returnValue = pcall(function()
return dataStore:GetAsync(key)
end)
if success then
-- Check if loaded data is nil or not:
if returnValue ~= nil then
print(plr.Name .. " Successfully Loaded this Data: " .. httpService:JSONEncode(returnValue))
return returnValue
else
warn("No Data was found for Player: " .. plr.Name .. " (Key: " .. plr.UserId .. ")")
return nil
end
else
warn(plr.Name..": Error while Loading Data:", returnValue)
return nil
end
end
-- //: Function for Changing the players Data to something new
DataManager.ChangeData = function(plr: Player, dataStoreName: string, indexToChange: any, newValue: any)
if not checkPlayer(plr) then return end -- Check if player argument is valid
-- Get the DataStore and the key:
local dataStore = DataStoreService:GetDataStore(dataStoreName)
local key = plr.UserId
-- If the key is empty, just create new table and assign value
-- If key is not empty, just add the value to the table
local success, err = pcall(function()
dataStore:UpdateAsync(key, function(data)
if data ~= nil then
data[indexToChange] = newValue
else
data = { [indexToChange] = newValue }
end
return data -- Save the Changes
end)
end)
if success then
print("Successfully Changed Data for: "..plr.Name.." (Key: "..key..")")
else
warn("Error while Chaninging Data for: "..plr.Name.." (Key: "..key.."):", err)
end
end
return DataManager
The module provides two main functions:
-
LoadData: Loads the player’s saved data from the specified DataStore.
-
ChangeData: Changes specific values in the key of the player.
Example usage with Leaderstats, ServerScript: (29 Lines)
local dataManager = require(game:GetService("ServerScriptService").Modules.DataManager)
game.Players.PlayerAdded:Connect(function(plr)
-- Leaderstats:
local leaderstats = Instance.new("Folder", plr)
leaderstats.Name = "leaderstats"
local money = Instance.new("NumberValue", leaderstats)
money.Name = "Money"
local level = Instance.new("NumberValue", leaderstats)
level.Name = "Level"
-- Load Data:
local loadedData = dataManager.LoadData(plr, "PlayerData")
if not loadedData then warn("No Data") return end
plr.leaderstats.Money.Value = loadedData["Money"]
plr.leaderstats.Level.Value = loadedData["Level"]
end)
game.Players.PlayerRemoving:Connect(function(plr)
dataManager.ChangeData(plr, "PlayerData", "Money", plr.leaderstats.Money.Value)
dataManager.ChangeData(plr, "PlayerData", "Level", plr.leaderstats.Level.Value)
end)
I tested it and it works
I’m looking for feedback and suggestions for improvement, especially regarding efficiency and best practices. Are there any optimizations I might have missed? Or is there something I should pay more attention to?
Thanks for your time and help!