Issue with Table Values

Hello!

I have a datastore script where it gets the IntValue in player.playerstats named “Coins”. However, it has trouble here:


	-- tries to fetch data from datastore until either succeeds or takes too many attempts

	repeat
		success, err = pcall(function()
			data = CoinsStore:GetAsync(key)
			print('got data')
			print(data)
		end)

		count = count + 1
	until count >= tries or success

-- if data exists (player left the game, and then rejoined some time later)

		-- for data creates values, puts them in playerstats

		--[[ saved table looks like this at the point of writing:
		data = {
			[1] = {
				["Name"] = "Coins",
				["Value "] = 3
			}
			[2] = {
				["Name"] = "DataId",
				["Value"] = 10
			}
		}
		keep in mind its random values, yours will be different, cuz you set them yourself, i picked 2 random ones
		]]

where instead of printing what is in the comments, it prints this:


and inside like all of the tables except 2, all it says is:

image


it should only print out [1] and [2] and not all of these.

[1] is Coins and its value, and [2] is the DataId value you can see in the comments in the script I provided.

could you make the output window bigger so the prints dont go to the next line? right now its hard to read.

1 Like

Sure thing! Here are both of the screenshots I provided in a bigger output size:

try swapping the until part of the loop, like this:

repeat
until success or count >= tries

also, you can use val += anotherval instead of val = val + anotherval

this also works with subtraction (-=), division (/=), and multiplication (*=)

How would this help the table issue? All it does is rewrite the code but use 10 fewer characters.

I tried this and it didn’t help my problem.

try using an if success then statement to make sure that the success variable is actually returning true

I put a print(success) and it prints true right after the repeat statement.

if you want i can provide the full code.

try adding a print outside of the for loop to see if the repeat continues to loop.
also, check the datastore and make sure that only the values you want are in it.
you could also try adding a break inside it, like this:

repeat
	success, err = pcall(function()
		data = CoinsStore:GetAsync(key)
        if data then
		    print('got data')
		    print(data)
            break
        end
	end)
    if err then
        print(tostring(err))
    end
    print("looped")
	count = count + 1
until count >= tries or success

Can you provide the save script and the data structure?

Sure, here it is:

local DataStoreService = game:GetService("DataStoreService")
local CoinsStore = DataStoreService:GetDataStore("CoinStore")
local repStorage = game:GetService("ReplicatedStorage")

local tries = 3
local dataloaded = nil

local function save(player)
	--make sure that data has actually loaded in (to not clear by accident)
	if dataloaded then
		local key = player.UserId
		local count = 0

		local data = {}

		--adds the name and value of every IntValue in playerstats to the "data" table
		for i, Value in pairs(player.playerstats:GetChildren()) do
			local Thing = {
				["Name"] = tostring(Value.Name),
				["Value"] = tostring(Value.Value)
			}
			table.insert(data, Thing)
		end

		print(data)

		local success, err

		---keeps trying to set async until it either succeeds or goes over the allowed tries to save
		repeat
			success, err = pcall(function()
				CoinsStore:SetAsync(key, data)
				print(player.playerstats.Coins.Value)
				print('Saved!')
			end)

			count += 1
		until success or count >= tries
		print(success)

		-- warns if data could not be set
		if not success then
			warn("Data could not be set: " .. tostring(err))
			return
		end
	else
		-- warns that data has not loaded.
		warn("Data has not been loaded. Do not attempt to set data when it has not been loaded.")

		return
	end
end

local function load(player)

	-- creates playerstats
	local playerstats = Instance.new("Folder")
	playerstats.Name = "playerstats"
	playerstats.Parent = player
	
	local Coins = Instance.new("IntValue")
	Coins.Name = "Coins"
	Coins.Parent = playerstats
	
	local dataId = Instance.new("IntValue")
	dataId.Name = "DataId"
	dataId.Parent = playerstats

	print('playerstats created')


	local key = player.UserId
	local count = 0

	local data

	local success, err

	-- tries to fetch data from datastore until either succeeds or takes too many attempts
	repeat
		success, err = pcall(function()
			data = CoinsStore:GetAsync(key)
			print('got data')
			print(data)
		end)

		count = count + 1
	until count >= tries or success

	-- if didnt fetch data
	if not success then
		warn("Failed to read data." .. tostring(err))

		--kicks to force player to try again
		player:Kick("Failed to read data. Please rejoin the game.")

		return
	end

	-- if data exists (player left the game, and then rejoined some time later)
	if data then
		-- for data creates values, puts them in playerstats

		--[[ saved table looks like this at the point of writing:
		data = {
			[1] = {
				["Name"] = "Coins",
				["Value "] = 3
			}
			[2] = {
				["Name"] = "DataId",
				["Value"] = 10
			}
		}
		keep in mind its random values, yours will be different, cuz you set them yourself, i picked 2 random ones
		]]
		for _, savedInstance in pairs(data) do
			local Value = Instance.new("IntValue")
			Value.Name = "Coins"
			Value.Value = savedInstance.Name
			Value.Parent = playerstats
		end
		dataloaded = true
	else
		-- does not exist (player joined first time) so we create instance, set value, and parent
		warn('Player has no data! Creating new data for them.')
		local coins = Instance.new("IntValue")
		coins.Name = "Coins"
		coins.Parent = playerstats

		local dataId = Instance.new("IntValue")
		dataId.Name = "DataId"
		dataId.Value = 0
		dataId.Parent = playerstats 

		dataloaded = true
	end

end

--load when player joins
game.Players.PlayerAdded:Connect(load)

--save when player leaves
game.Players.PlayerRemoving:Connect(save)

--save when game gets shut down
game:BindToClose(function()
	for i, plr in ipairs(game.Players:GetPlayers()) do
		save(plr)
		print('fired save function')
	end
end)

Btw your dataloaded check is pointless since it’s global meaning that anybody that has their data loaded will be loaded for everyone else.

The problem with your script is here:

for i, Value in pairs(player.playerstats:GetChildren()) do
		local Thing = {
			["Name"] = tostring(Value.Name),
			["Value"] = tostring(Value.Value)
		}
		table.insert(data, Thing)
end

In this iteration, there may be more than 1 child in playerstats so you have duplicated values or if that isn’t the issue I recommend deleting the data you have and try again.

Yes you are right, I just tested in game and went to Players > myName > playerstats and there is around 20 IntValues named coins.

It also seems that it duplicates 2 times each time I join.

How do I fix this?

Send me the script that create this instances maybe I can fix it.

The script I provided IS the script lol

Alright gimme couple minutes while I take a look at what’s wrong.

1 Like

Alright the problem is here

		for _, savedInstance in pairs(data) do
			local Value = Instance.new("IntValue")
			Value.Name = "Coins"
			Value.Value = savedInstance.Name
			Value.Parent = playerstats
		end

I can’t help you fix right now I’ll be back in a few hours time but that is the problem ^^

1 Like

alright, ill probably be asleep by the time you come back so if you don’t see a response from me that’s why xd

Do you still need help to fix that or is it already fixed?

1 Like