DataStores: leaderstat replication issue
Game: Minigames by @MejjyBoi
Goal: @MejjyBoi and I want to create a datastore system that displays how much Robux a player as spent on Developer Products
(ex: A player purchases 10 Robux DevProduct, the server recongizes it and adds 10 to their Donated leaderstat value and saves their data.)
Issue: If someone donates 250 Robux, and they are inside a Server housing about 50 clients, only the player who donated gets their data updated and saved. This has been confirmed through server console log. However, if the same players join a new Server, all players who were inside the previous server with the donator will get 250 added to their datastore, and it will be saved. This means that it will appear as if everyone in said server donated 250 Robux, when in reality only one donated.
Solutions attempted: We have searched for the developer forum for answers but have not come across a viable solution yet. Multiple attempts to patch the before-mentioned issue have already been made, with little progress achieved.
Code (SaveClientDataHandler) (contains 2 BindableEvents: SavePlayerData and ModifyClientData):
– BEGIN CODE
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local DataStoreService = game:GetService("DataStoreService")
local ServerDatabase = DataStoreService:GetDataStore("PlayerData23")
local CurrentSessionData = {}
local Enabled = true
local folder = script.Parent
local SavePlayerDataEvent = folder:WaitForChild("SavePlayerData")
local ModifyClientDataEvent = folder:WaitForChild("ModifyClientData")
local DefaultData = {
["Donated"] = 0,
}
local function DatabaseConnect(player)
-- SETTING VALUES
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local Donated = Instance.new("NumberValue")
Donated.Name = "Donated"
Donated.Parent = leaderstats
-- SAVING DATA TO SERVERDATABASE
local success = nil
local PlayerData = nil
local attempt = 0
repeat
success,PlayerData = pcall(function()
return ServerDatabase:GetAsync(player.UserId)
end)
if not success then
warn(PlayerData)
task.wait(1)
end
attempt += 1
until success or attempt == 5
if success then
print("[DATASTORES]: Roblox Server successfully connected to ServerDatabase")
if not PlayerData then
warn("[DATASTORES]: User data not found. Assigining the default values.")
PlayerData = DefaultData
end
CurrentSessionData[player.UserId] = PlayerData
else
warn("[DATASTORES]: Unable to retrieve data for " ..player.UserId .. " (" .. player.Name .. ")")
player:Kick("Connection terminated: DataStore warning")
end
-- SYNCING DATASTORES
Donated.Value = CurrentSessionData[player.UserId].Donated
Donated.Changed:Connect(function()
CurrentSessionData[player.UserId].Donated = Donated.Value
end)
leaderstats.Parent = player
end
local function SavePlayerData(player)
if player then
local targetPlayerId = game.Players[player].UserId
local targetPlayerName = game.Players[player].Name
if CurrentSessionData[targetPlayerId] then
local success = nil
local errorMsg = nil
local attempt = 0
repeat
success, errorMsg = pcall(function()
ServerDatabase:SetAsync(targetPlayerId, CurrentSessionData[targetPlayerId])
end)
if not success then
warn("[DATASTORES]: Fault in data saving for " .. targetPlayerId .. " (" .. targetPlayerName .. ")")
warn(errorMsg)
task.wait(3)
end
attempt += 1
until success or attempt == 5
if success then
print("[DATASTORES]: Successfully saved data for " .. targetPlayerId .. " (" .. targetPlayerName .. ")")
else
warn("[DATASTORES]: Unable to save data for " .. targetPlayerId .. " (" .. targetPlayerName .. ")")
end
end
end
end
SavePlayerDataEvent.Event:Connect(function(savingFor)
if savingFor then
--print("Found")
if savingFor == true then
print("[DATASTORES]: Attempting to save data for all connected clients")
for i, plr in ipairs(Players:GetPlayers()) do
task.spawn(function()
SavePlayerData(plr.Name)
end)
end
else
--print(savingFor)
SavePlayerData(savingFor)
end
else
warn("[DATASTORES]: Couldn't find client to save data for!")
end
end)
Players.PlayerAdded:Connect(DatabaseConnect)
Players.PlayerRemoving:Connect(function(plr)
if Enabled == true then
SavePlayerDataEvent:Fire(plr.Name, plr)
else
print("[DATASTORES]: Data Saving is not enabled in this session")
end
end)
ModifyClientDataEvent.Event:Connect(function(targetedPlayer, key, value, changeType)
local playerLeaderstatsFolder = game.Players[targetedPlayer.Name]:WaitForChild("leaderstats")
local targetedKey = playerLeaderstatsFolder:FindFirstChild(key)
if targetedKey and Enabled == true then
if changeType == true then
targetedKey.Value += value
print("[DATASTORES]: Successfully modified client data for player: " .. targetedPlayer.Name .. " | Changed: " .. key .. " += " .. value)
SavePlayerDataEvent:Fire(targetedPlayer.Name)
elseif changeType == false then
targetedKey.Value -= value
print("[DATASTORES]: Successfully modified client data for player: " .. targetedPlayer.Name .. " | Changed: " .. key .. " -= " .. value)
SavePlayerDataEvent:Fire(targetedPlayer.Name)
else
targetedKey.Value = value
print("[DATASTORES]: Successfully modified client data for player: " .. targetedPlayer.Name .. " | Changed: " .. key .. " = " .. value)
SavePlayerDataEvent:Fire(targetedPlayer.Name)
end
else
warn("[DATASTORES]: Cannot modify client data, invalid key recieved")
end
end)
while true do
wait(30)
SavePlayerDataEvent:Fire(true)
end
-- MODIFY DATASTORE FOR A SPECIFIC CLIENT
-- game.ServerScriptService.DataStoreService.ModifyClientData:Fire("Trecinus", "Wins", 100, true)
-- SAVE DATASTORE FOR A SPECIFIC CLIENT
-- game.ServerScriptService.DataStoreService.SavePlayerData:Fire("Trecinus")
-- SAVE DATASTORES FOR ALL CLIENTS
-- game.ServerScriptService.DataStoreService.SavePlayerData:Fire(true)
– END OF CODE