Hello Devs!
Today I’ve made this Data Store ModuleScript and I want to learn more about this topic and how I can improve my methods to storing/loading player data.
Made this with a basic understandment of “Session Locking” concept, but I still having doubts about the viability of this code and if a did it correctly.
The “PlayerDataService” is another module I also made to handle in-game checking and changing data, but it doesn’t interfer in this module I’m sharing now. The same for “DefaultPlayerData” ModuleScript.
The playerData:GetInfo()
is a method that returns a dictionary with the values I want to save in data store.
Whatever tips not including data store topic is very appreciated as well!
Here is the code:
local DataStoreService = game:GetService("DataStoreService")
local ServerScriptService = game:GetService("ServerScriptService")
local MemoryStoreService = game:GetService("MemoryStoreService")
local PlayerDataService = require(ServerScriptService.Modules.PlayerDataService)
local DefaultPlayerData = require(ServerScriptService.Modules.PlayerDataService.PlayerData.DefaultPlayerData)
local DataStoreModule = {
Settings = {
MaxTries = 6,
}
}
DataStoreModule.__index = DataStoreModule
local function Try(f, ...)
local success, result
for try = 1, DataStoreModule.Settings.MaxTries do
success, result = pcall(f, ...)
if success then break end
task.wait(2)
end
print(success, result, ...)
return success, result
end
function DataStoreModule.new(name: string)
local newDataStore = setmetatable({}, DataStoreModule)
newDataStore.DataStore = DataStoreService:GetDataStore(name)
newDataStore.MemoryStore = MemoryStoreService:GetSortedMap(name)
return newDataStore
end
function DataStoreModule:StartPlayerSession(player: Player)
local success, sessionJobId = Try(self.MemoryStore.GetAsync, self.MemoryStore, player.UserId)
if success and sessionJobId and sessionJobId ~= game.JobId then
return player:Kick("Your player has joined twice. Please rejoin")
end
Try(self.MemoryStore.SetAsync, self.MemoryStore, player.UserId, game.JobId, 3000000)
end
function DataStoreModule:EndPlayerSession(player: Player)
local success, sessionJobId = Try(self.MemoryStore.GetAsync, self.MemoryStore, player.UserId)
if success and sessionJobId == game.JobId then
Try(self.MemoryStore.RemoveAsync, self.MemoryStore, player.UserId)
end
end
function DataStoreModule:LoadData(player: Player)
local success, result = Try(self.DataStore.GetAsync, self.DataStore, player.UserId)
if not success then
return player:Kick("Failed to load your data. Please rejoin")
end
local playerData = PlayerDataService:GetPlayerData(player)
for key, value in result or {} do
playerData[key] = value
end
return playerData
end
function DataStoreModule:SavePlayerData(player: Player)
local playerData = PlayerDataService:GetPlayerData(player)
local success, result = Try(self.DataStore.SetAsync, self.DataStore, player.UserId, playerData:GetInfo())
if not success then
warn(result)
end
end
return DataStoreModule
Edit: I’ve forgot to add a little code of how I’m using this Module. Here is:
PlayersService.PlayerAdded:Connect(function(player: Player)
PlayerDataStore:StartPlayerSession(player)
local loadedData = PlayerDataStore:LoadData(player)
-- ...
end)
PlayersService.PlayerRemoving:Connect(function(player: Player)
PlayerDataStore:SavePlayerData(player)
PlayerDataStore:EndPlayerSession(player)
-- ...
end)