Hi.
I created a game in which I keep the players’ data in a ModuleScript, namely module.data = {} (all examples will be given below).
The problem is that when a player enters the game, his data is loaded and placed in this module, but before that, some checks are made, for example, for the integrity or relevance of the variables in the table.
Server Script 1 :
> local ReplicatedStorage = game:GetService("ReplicatedStorage")
> local RequiredFunctions = require(script.Parent.ModuleScript)
>
> local function CharacterAdded(character)
> local player = game.Players:GetPlayerFromCharacter(character)
> RequiredFunctions.GiveTools(player.UserId)
> end
>
> local function PlayerAdded(player)
> RequiredFunctions.load(player.UserId)
> local remote_event = Instance.new("RemoteEvent",game.ReplicatedStorage.RemoteEvents)
> remote_event.Name = player.UserId
> player.CharacterAdded:Connect(CharacterAdded)
> end
>
> local function PlayerRemoving(player)
> RequiredFunctions.save(player.UserId)
> if game.ReplicatedStorage.RemoteEvents:FindFirstChild(player.UserId) then
> game.ReplicatedStorage.RemoteEvents:FindFirstChild(player.UserId):Destroy()
> end
> end
>
> game.Players.PlayerAdded:Connect(PlayerAdded)
> game.Players.PlayerRemoving:Connect(PlayerRemoving)
Module Script :
local module = {}
local DataStore = game:GetService("DataStoreService"):GetDataStore("DSQ004")
local ReplicatedData = game:GetService("ReplicatedStorage"):WaitForChild("ReplicatedData")
local defaultData = {
Parts = 0,
LeaveTime = math.floor(tick()),
TimePlayed = 0,
TimesJoined = 0,
Name = "",
Face = 144080495,
Color = "29292f",
Material = "SmoothPlastic",
CarryingType = 0,
}
local VariablesToNil = {
CarryingType = true,
}
module.data = {}
module.SetDataTable = function(id, data)
for variable, value in pairs(defaultData) do
if not data[variable] then
data[variable] = value
elseif typeof(value) ~= typeof(data[variable]) then
data[variable] = value
end
end
for variable, value in pairs(data) do
if defaultData[variable] == nil then
data[variable] = nil
end
end
data.TimesJoined += 1
module.data[id] = data
end
module.save = function(id, delete)
local data = module.data[id] or defaultData
for variable, value in pairs(data) do
if VariablesToNil[variable] then
data[variable] = nil
end
end
data.LeaveTime = math.floor(tick())
local success, error = pcall(function()
DataStore:SetAsync(id, data)
end)
if not success then
local retries = 0
repeat
task.wait(5)
success, error = pcall(function()
DataStore:SetAsync(tostring(id), data)
end)
retries += 1
until success or retries >= 2
end
if delete == nil then
module.data[id] = nil
end
end
module.load = function(id)
if module.data[id] then
module.data[id] = nil
end
local function tryGetDataFromStore()
local success, data = pcall(function()
return DataStore:GetAsync(id)
end)
return success, data
end
local retries = 0
local success, data = tryGetDataFromStore()
while not success and retries < 2 do
retries += 1
success, data = tryGetDataFromStore()
end
if success then
if data then
module.SetDataTable(id, data)
else
module.SetDataTable(id, defaultData)
end
return true
else
local player = game:GetService("Players"):GetPlayerByUserId(id)
if player then
player:Kick()
end
return false
end
end
return module
Server Script 2:
local ServerScriptService = game:GetService("ServerScriptService")
local MarketplaceService = game:GetService("MarketplaceService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local RequiredFunctions = require(script.Parent.ModuleScript) -- module script
local function GetPlayerData(id)
return RequiredFunctions.data[id]
end
local functions2 = {
["CarryingType"] = function(player, args)
if GetPlayerData(player.UserId)then
GetPlayerData(player.UserId).CarryingType = args[2]
end
end
}
ReplicatedStorage.RemoteEvents.ChildAdded:Connect(function(remote)
if remote:IsA("RemoteEvent") then
remote.OnServerEvent:Connect(function(player,args)
if player.UserId ~= tonumber(remote.Name) then return end
if functions2[args[1]] then functions2[args[1]](player,args) end
end)
end
end)
coroutine.wrap(function()
while true do
task.wait(1)
for _, player in ipairs(game:GetService("Players"):GetChildren()) do
local data = RequiredFunctions.data[player.UserId]
data.TimePlayed += 1
end
end
end)()
In general, the point is that any call for me happens like this:
local module = require(game.ServerScriptService.ModuleScript)
module.data["user id"] = {} -- "default data"
module.data["user id"].Parts += 1 -- example
if module.data["user id"].Parts == 1 then
print("")
end
The point is that the data is mixed and, for example, when player 1 calls an event to change a variable in the table, this is replicated to the data of all players + they are superimposed. Let’s say 5 players logged in and now TimePlayed increases by 5 per second and not by 1 as required