If you removed the data id part then just delete everything related to it. So the changed event should only have that last line
With the folder i made for @H0angg itâs under the player instance. I explain how it works you should read the posts above if you havenât yet.
local Val = CreateInstance(`{Type}Value`, SubFolder, Name, Value)
Val.Changed:Connect(function(ChangedValue: number)
--local OldID = PlayerDataTable[PlrId]["DataID"]
--local NewId = GetRandomID(ChangedValue, OldID)
--PlayerDataTable[PlrId]["DataID"] = NewId
PlayerDataTable[PlrId][SectionName][Name] = ChangedValue
end)
like this?
but my data arent saved, its just the base data
hey @sonic_848 i actually got ur code to work after changing something
local dss = game:GetService("DataStoreService")
local MainStore = dss:GetDataStore("PlayerData")
local PlayerDataTable = {}
local BaseData = { --Base data for when a player joins for the first time
Settings = {Music = true, CustomCursor = true},
Inventory = {Cake = 10, ChimBall = 10, Slingshot = 10},
Misc = {Coins = 0, SaveCoins = 0},
Slots = {Slot1 = "Cake", Slot2 = "Slingshot"},
DataID = 0
}
local Idk = {
number = "Number",
boolean = "Bool",
string = "String"
}
--Repeat delay is for how long the function waits before retrying to get/set data
local function PlayerDataRequest(UserID : number, Get : boolean, Tries : number, RepeatDelay : number, SetData : {}?)
if not (Tries and RepeatDelay and UserID) then
warn("Check params")
return nil
end
if Get == false and not SetData then
warn("Set data not provided.")
return nil
end
local CurrentTries = 0
local Success, Error, Data = false, nil, nil
repeat
CurrentTries += 1
if Get then
Success, Error = pcall(function()
Data = MainStore:GetAsync(UserID)
end)
else
Success, Error = pcall(function()
--if OldData["DataID"] == SetData["DataID"] then
-- return nil
--else
-- return SetData
--end
Data = MainStore:SetAsync(UserID, SetData)
end)
end
if Success then
break
else
task.wait(RepeatDelay)
end
until (CurrentTries == Tries) or Success
return Success, Error, Data
end
local function CreateInstance(InstanceName : string, Parent : Instance, Name : string, Value:any?) : NumberValue|BoolValue|StringValue
local X = Instance.new(InstanceName)
X.Name = Name
if Value then X.Value = Value end
X.Parent = Parent
return X
end
local function GetRandomID(Last:number) : number
local Rand = Random.new(os.clock() + math.random(0, 1000))
local Num = Rand:NextNumber(0,100)
if Num == Last then
Num = GetRandomID(Last)
task.wait()
end
return Num
end
local function PlayerJoin(Player)
local PlrId = Player.UserId
local Success, Error, PlayerData = PlayerDataRequest(PlrId, true, 3, 1)
if not Success then
warn(Error)
Player:Kick("Data store issues.")
return
end
PlayerDataTable[PlrId] = (PlayerData and PlayerData["DataID"]) and PlayerData or BaseData
local Folder = CreateInstance("Folder", Player, "PlayerDataFolder")
for SectionName, Data in PlayerDataTable[PlrId] do
if typeof(Data) ~= "table" then
continue
end
local SubFolder = CreateInstance("Folder", Folder, SectionName)
for Name, Value in Data do
local Type = Idk[typeof(Value)]
if not Type then
continue
end
local Val = CreateInstance(`{Type}Value`, SubFolder, Name, Value)
Val.Changed:Connect(function(ChangedValue: number)
--local OldID = PlayerDataTable[PlrId]["DataID"]
--local NewId = GetRandomID(ChangedValue, OldID)
--PlayerDataTable[PlrId]["DataID"] = NewId
PlayerDataTable[PlrId][SectionName][Name] = ChangedValue
print(PlayerDataTable)
end)
end
end
end
local function PlayerLeave(Player:Player)
local PlayerData = PlayerDataTable[Player.UserId]
if not PlayerData then
return
end
local Success, Err = PlayerDataRequest(Player.UserId, false, 3, 1, PlayerData)
if Success then
print("saved")
end
if Err then
warn(Err)
end
PlayerDataTable[Player.UserId] = nil
end
is it okay to use setasync instead of updateasync
Why not RunService:IsClient()
& RunService:IsServer()
?
Yea you can use set async.
Original save function with set async here:
This is a server script not a module
That doesnât disallow you from using IsClient()
instead of C =
or some hacky way?
Itâs a function connected to both a OnServerInvoke
and a OnInvoke
event so you cant use that
is there a way to save more instance in a table, like more settings and inventory, idk how to explain atp
local BaseData = { --Base data for when a player joins for the first time
Settings = {Music = true, CustomCursor = true, test = false},
Inventory = {Cake = 10, ChimBall = 10, Slingshot = 10},
Coins = {Coins = 0, SaveCoins = 0},
Slots = {Slot1 = "Cake", Slot2 = "Slingshot"},
DataID = 0
}
when i add the test in, it doesnt appears in the players data
I just updated the entire code to make it work because there was stuff I had to add. So, the new way it will work is if you update the base data, make sure to change the version number. Version number HAS to be in both tables and donât remove it. So basically if you have saved data and your version is like 0 and the base data one is like 1 then the playerâs data will change too (you can test and see). Also, the data store name had to change because we couldnât do it with the previous one but everything should work now. DataID and updateasync shenanigans were removed btw and they follow what youâve been wanting. To make the playersâ data switch just change the version number
Code:
local players = game:GetService("Players")
local dss = game:GetService("DataStoreService")
local MainStore = dss:GetDataStore("PlayerData_1")
local PlayerDataTable = {}
local BaseData = { --Base data for when a player joins for the first time
Settings = {Music = true, CustomCursor = true, test = false},
Inventory = {Cake = 10, ChimBall = 10, Slingshot = 10},
Coins = {Coins = 0, SaveCoins = 0},
Slots = {Slot1 = "Cake", Slot2 = "Slingshot"},
Version = 0
}
local Idk = {
number = "Number",
boolean = "Bool",
string = "String"
}
--Repeat delay is for how long the function waits before retrying to get/set data
local function PlayerDataRequest(UserID:number, Get:boolean, Tries:number, RepeatDelay:number, SetData:{}?)
if not (Tries and RepeatDelay and UserID) then warn("Check params") return nil end
if Get == false and not SetData then warn("Set data not provided.") return nil end
local CurrentTries = 0
local Success, Data = false, nil
repeat
CurrentTries += 1
if Get then
Success, Data = pcall(MainStore.GetAsync, MainStore, UserID)
else
Success, Data = pcall(MainStore.SetAsync, MainStore, UserID, SetData)
end
if Success then
break
else
task.wait(RepeatDelay)
end
until (CurrentTries == Tries) or Success
return Success, Data
end
local function CreateInstance(InstanceName:string, Parent:Instance, Name:string, Value:any?) : NumberValue|BoolValue|StringValue
local X = Instance.new(InstanceName)
X.Name = Name
if Value then X.Value = Value end
X.Parent = Parent
return X
end
local function MatchTableKeys(T1:{}, T2:{})
-- Add missing keys from T2 to T1
for key, value in pairs(T2) do
if type(value) == "table" then
T1[key] = T1[key] or {}
MatchTableKeys(T1[key], T2[key])
else
if T1[key] == nil then
T1[key] = value
end
end
end
for key in pairs(T1) do
if T2[key] == nil then
T1[key] = nil
end
end
end
local function PlayerJoin(Player:Player)
local PlrId = Player.UserId
local Success, PlayerData = PlayerDataRequest(PlrId, true, 3, 1)
if not Success then warn(PlayerData) Player:Kick("Data store issues.") return end
PlayerDataTable[PlrId] = (PlayerData and PlayerData["Version"]) and PlayerData or BaseData
if PlayerDataTable[PlrId]["Version"] ~= BaseData["Version"] then
MatchTableKeys(PlayerDataTable[PlrId], BaseData)
PlayerDataTable[PlrId]["Version"] = BaseData["Version"]
end
local Folder = CreateInstance("Folder", Player, "PlayerDataFolder")
for SectionName, Data in PlayerDataTable[PlrId] do
if typeof(Data) ~= "table" then continue end
local SubFolder = CreateInstance("Folder", Folder, SectionName)
for Name, Value in Data do
local Type = Idk[typeof(Value)]
if not Type then continue end
local Val = CreateInstance(`{Type}Value`, SubFolder, Name, Value)
Val.Changed:Connect(function(ChangedValue: number)
PlayerDataTable[PlrId][SectionName][Name] = ChangedValue
end)
end
end
end
local function PlayerLeave(Player:Player)
local PlayerData = PlayerDataTable[Player.UserId]
if not PlayerData then return end
local Success, Err = PlayerDataRequest(Player.UserId, false, 3, 1, PlayerData)
if not Success then warn(Err) end
PlayerDataTable[Player.UserId] = nil
end
players.PlayerAdded:Connect(PlayerJoin)
players.PlayerRemoving:Connect(PlayerLeave)
Edit: Donât increment down on the version number when updating your base data only go up. Also, you can use decimals for the version number so like 1.2 and 1.002.
thank you so much, everything works fine