I’m trying to fix my data and emotes system(which needs to be saved).
The problem is my previous data is overwriting current data. The emote progress data value(max: 2) would have a max of 10 because of it reverted back to a previous data session.
I did my research and found out SetAsync is not good practice when in using large scale tables(sessionData) for saving data. Now I’m using UpdateAsync which is specificially used for preventing this issue.
I used this and this source for my information.
The problem now is that I don’t know how to use UpdateAsync properly. Both tutorials have shown something similar to an ID and version which both were added(+=1) if the sessionData was saved to the datastore. I don’t know how to save the versions themselves across the datastore if overwriting is the issue. The posts I’ve seen didn’t show how to create a versionTable or add an IntValue acting as the Version to the player.
Any ideas?
PlayerDataScript
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Assets = ReplicatedStorage.Assets
local Bindables = ReplicatedStorage.Bindables
local Remotes = ReplicatedStorage.Remotes
local DataStore = DataStoreService:GetDataStore("Players")
local sessionData = {}
local versionTable = {}
local Leaderboards = require(script.Leaderboards)
local Leveling = require(script.Leveling)
local Battlepass = require(script.Battlepass)
local EmotesList = require(script.EmotesList)
local function data(player)
--for i,v in pairs(sessionData[player]) do print(i,v) end
end
Bindables.OnServer.Event:Connect(function(signal,player)
if signal == "InitServer" then
ReplicatedStorage.Remotes.ToClient:FireClient(player,"CreateBattlepass",sessionData[player]["Level"],sessionData[player]["Experience"],Battlepass)
elseif signal == "ResetPlayer" then
sessionData[player] = nil
end
end)
local function leaderstats(player)
local folder = Instance.new("Folder")
folder.Name = "leaderstats"
local wins = Instance.new("IntValue")
wins.Name = "Wins"
wins.Value = sessionData[player]["Wins"]
local kills = Instance.new("IntValue")
kills.Name = "Kills"
kills.Value = sessionData[player]["Kills"]
local money = Instance.new("IntValue")
money.Name = "Money"
local ver = Instance.new("IntValue")
ver.Name = "Version"
ver.Value = sessionData[player]["Version"]
versionTable[tostring(player.UserId)] = ver.Value
money.Changed:Connect(function(value)
sessionData[player]["Money"] = value
end)
ver.Parent = player
money.Parent = player
wins.Parent = folder
kills.Parent = folder
folder.Parent = player
end
ReplicatedStorage.Data.Event:Connect(function(signal,player,key,update)
if signal == "Set" then
sessionData[player][key] = update
elseif signal == "Update" then
local value = update(sessionData[player][key])
ReplicatedStorage.Data:Fire("Set",player,key,value)
end
if key == "Wins" or key == "Kills" then
player.leaderstats:FindFirstChild(key).Value = sessionData[player][key]
end
end)
ReplicatedStorage.Get.OnInvoke = function(player,key)
return sessionData[player][key]
end
local function Abilities(tab_)
tab_ = {}
for _,ability in Assets.Shop:GetChildren() do
if ability:IsA("ModuleScript") then continue end
tab_[ability.Name] = {false,0}
end
return tab_
end
local function deepCopy(tab_)
local copy = {}
for k, v in pairs(tab_) do
if type(v) == "table" then
v = deepCopy(v)
end
copy[k] = v
end
return copy
end
local function Emotes(tab_)
tab_ = {}
for emote,value in pairs(EmotesList) do
tab_[emote] = value
end
deepCopy(tab_)
return tab_
end
Players.PlayerAdded:Connect(function(player)
local key = tostring(player.UserId)
sessionData[player] = {}
sessionData[player]["Version"] = 0
sessionData[player]["Money"] = 0
sessionData[player]["Equipped"] = ""
sessionData[player]["Abilities"] = Abilities(sessionData[player]["Abilities"])
sessionData[player]["Kills"] = 0
sessionData[player]["Wins"] = 0
sessionData[player]["Level"] = 1
sessionData[player]["Experience"] = 0
sessionData[player]["Emotes"] = Emotes(sessionData[player]["Emotes"]) -- this is empty despite being filled in with a list of values
sessionData[player]["EmoteProgress"] = 2 -- This changes to 10 to players just joining because it was a previous initialization, but I want 2 now
sessionData[player]["Gamepasses"] = {
["DoubleEmotes"] = false
}
local success,result = pcall(function()
return DataStore:GetAsync(key)
end)
print(sessionData[player]["EmoteProgress"])
if success and result then
for i,v in pairs(result) do
sessionData[player][i] = v
end
end
print(sessionData[player]["EmoteProgress"])
leaderstats(player)
data(player)
task.spawn(function()
while true do
if DataStore:GetAsync(key) then
Leaderboards:Set(player,"Kills",sessionData[player]["Kills"])
Leaderboards:Set(player,"Wins",sessionData[player]["Wins"])
end
task.wait(100)
end
end)
Leveling:Init(player)
end)
Players.PlayerRemoving:Connect(function(player)
local key = tostring(player.UserId)
if sessionData[player] then
data(player)
DataStore:UpdateAsync(key,function(pastData)
if pastData.Version ~= versionTable[key] then
print("Data version is not the same.")
return nil
else
versionTable[key] += 1
return sessionData[player]
end
end)
end
Leveling:Set(player)
end)
task.spawn(function()
while true do
Leaderboards:Refresh("Kills")
Leaderboards:Refresh("Wins")
task.wait(100)
end
end)