All keys updated in dictionary, when only trying to update 1

I have made a dictionary that stores the all the player data on the server, when i update the data in the dictionary on a specific players key, it adds the data to all of the other keys. Ive tried printing it out, making sure the update data function doesnt run for all the players, it doesnt.

Here is the update data function:

local function GiveItem(Player, Class, SubjectName)
	if PlayersData[Player.UserId] then
		print("Ran")
		print(PlayersData) -- {[129409203] = { ["Wins"] = 1}; [5802880] = { ["Wins"] = 1}}
		-- Update data
		PlayersData[Player.UserId][Class].Owns[SubjectName] = {["Wins"] = 2}
		print("Updated")
		print(PlayersData) -- {[129409203] = { ["Wins"] = 2}; [5802880] = { ["Wins"] = 2}}
	end
end

I dont know what to do at this point, i have never encountered this issue. Any help is appreciated!

2 Likes

The data return seems inconsistent and doesn’t match your table, where the .Owns comes from.

Based on what you send, PlayersData[Player.UserId] = {["Wins"] = 2} is enough.
This probably doesn’t answer your question but without the correct data we can’t help you.

1 Like

Alright, i will send the full data

This is the data layout

local DataTemplate = {
	["Vehicles"] = {
		Equipped = "";
		Owns = {}
	};

	["Hammers"] = {
		Equipped = "";
		Owns = {}
	};
	["RampTokens"] = 0
}

The GiveItem function takes 3 params, Player, Class(The class the item is in, EG: Hammer) and Name(Name of the item)

local function GiveItem(Player, Class, SubjectName)
	if PlayersData[Player.UserId] then
		print("E")
		print(PlayersData)
		-- Update data
		PlayersData[Player.UserId][Class].Owns[SubjectName] = {["TimeBought"] = 5}
		print("A")
		print(PlayersData)
	end
end

The pattern im noticing is when 1 player buys an item, it saves it to everyones “Owns” dictionary, with the class bought from.

This is the code being ran from the client when the player clicks the buy button.

Shop.BuyTextButton.MouseButton1Click:Connect(function()
			if SelectedShopItem then
				BuyItem:FireServer(SelectedShopItem.Class, SelectedShopItem.Name)
			end
		end)

Most likely you are not setting the data correctly, can you throw off the part of the code where PlayersData[Player.UserId] is filled in?

Do you mean the if statement? i cant remove the PlayersData[Player.UserId] because thats how you get the dictionary from the playersdata dictionary

Have you actually tested your code to see if it is actually doing as your saying?

Your code has no problems as far as I can see.

What you are doing however:

print(PlayersData)

Which prints the entire table, are you sure you don’t mean print(PlayersData[Player.UserId])?

No, at the very beginning, when the player joined or something else where you set the player table

Most likely, it does not have tables, but links to tables, which is why it changes everywhere (this can be bypassed using table.clone)

Oh wait I see your problem entirely now, what has likely happened is when you’ve made the template for the data you haven’t made a deep copy of it.

As such your data marker is the same for each instance as they are sharing the same memory pointer.

You can see this behaviour here:

When creating and loading the data, make a deep copy.

Yeah i have, printing the whole PlayersData table was what made me realise that data was being updated on every single player dictionary.

Yeah that does make sense, currently the code that adds the player table is this.

local function AddData(Player)
	local PlayerData
	local s, e = pcall(function()
		 PlayerData = Store:GetAsync("Player_"..Player.UserId)
	end)
	
	if s then
		if PlayerData == nil then PlayerData = DataTemplate end
		PlayersData[Player.UserId] = PlayerData
	else
		warn(e)
	end
end

You need to copy the table recursively using table.clone (clone both the main table and all tables inside)

Yes, as you have done:

PlayerData = DataTemplate

When you make the new data they all share the same DataTemplate (as this is a memory pointer).

As such to fix this:

local function deepCopy(original)
	local copy = {}
	for k, v in pairs(original) do
		if type(v) == "table" then
			v = deepCopy(v)
		end
		copy[k] = v
	end
	return copy
end

local function AddData(Player)
	local PlayerData
	local s, e = pcall(function()
		 PlayerData = Store:GetAsync("Player_"..Player.UserId)
	end)
	
	if s then
		if PlayerData == nil then PlayerData = deepCopy(DataTemplate) end
		PlayersData[Player.UserId] = PlayerData
	else
		warn(e)
	end
end

I will test this, give me 2 minutes! :slight_smile:

This works, actual legend, thankyou so much!!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.