DataStore / SaveData code error

I hope I make sense. Lets start with the basic.
you enter a game with 100 Gold,
5 Strawberries and 2 Gold Strawberries. Nothing else.

Simple, we got 100 bucks and 7 Produce. That data is set up and then saved. But once I leave and come back, the numbers are all swapped.
You enter a game with 2 Gold,
100 Strawberries and 0 Gold Strawberries. Nothing else. (You didn’t sell or make any new produce before).

I know It HAS to be this script below because when I disable it; the game plays fine. All the mechanics and functions work properly.
(It wouldn’t save But) I would still have my 100 Gold, 5 Strawberries and 2 Golden Strawberries. And if I was to grow and sell more Strawberries/Golden Strawberries, their produce will correctly add up on the chart. (100 gold, 6 Strawberries, 3 Gold Strawberries. Assuming I harvested 1 from each plant).

Now idk if it’s maybe the order in which this script is coded. But I’m just confused.

Script: (I’m getting no errors that I can directly see, Unless there is a way to see errors In public games) It’s just for some reason, jumping up the values every time you enter the game.

local ds = game:GetService("DataStoreService"):GetDataStore("SaveData")
game.Players.PlayerAdded:Connect(function(plr)
	wait()
	local plyKey = "id_"..plr.UserId
	local saveStraw = plr.ProduceNumberFolder.StrawberryCount
	local saveGoldStraw = plr.ProduceNumberFolder.GoldStrawCount
	local saveCarrot = plr.ProduceNumberFolder.CarrotCount
	local savePotato = plr.ProduceNumberFolder.PotatoCount
	local saveCabbage = plr.ProduceNumberFolder.CabbageCount
	local saveSpinach = plr.ProduceNumberFolder.SpinachCount
	local saveSpringOn = plr.ProduceNumberFolder.SpringOnionCount
	local saveLettuce = plr.ProduceNumberFolder.LettuceCount
	
	local saveMoney = plr.MoneyFolder.Gold
	
	local GetSaved = ds:GetAsync(plyKey)
	if GetSaved then
		
		saveStraw.Value = GetSaved[1]
		saveGoldStraw.Value = GetSaved[2]
		saveCarrot.Value = GetSaved[3]
		savePotato.Value = GetSaved[4]
		saveCabbage.Value = GetSaved[5]
		saveSpinach.Value = GetSaved[6]
		saveSpringOn.Value = GetSaved[7]
		saveLettuce.Value = GetSaved[8]
		saveMoney.Value = GetSaved[9]	
			
		else
			local SavingNumbers = {
			saveStraw.Value,
			saveGoldStraw.Value,
			saveCarrot.Value,
			savePotato.Value,
			saveCabbage.Value,
			saveSpinach.Value,
			saveSpringOn.Value,
			saveLettuce.Value,
			saveMoney.Value}
		
		ds:GetAsync(plyKey,SavingNumbers)
		end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	ds:SetAsync("id_"..plr.userId,{
		plr.ProduceNumberFolder.GoldStrawCount.Value,
		plr.ProduceNumberFolder.StrawberryCount.Value,
		plr.ProduceNumberFolder.CarrotCount.Value,
		plr.ProduceNumberFolder.PotatoCount.Value,
		plr.ProduceNumberFolder.CabbageCount.Value,
		plr.ProduceNumberFolder.SpinachCount.Value,
		plr.ProduceNumberFolder.SpringOnionCount.Value,
		plr.ProduceNumberFolder.LettuceCount.Value,
		plr.MoneyFolder.Gold.Value
	})
end)

PLEASE NOTE: the only produce working and implemented in the game are Strawberries, Golden Strawberries, Carrots and Cabbages. None of the other values (Like Potato, Spinach etc) have actual data. I assume If I had all the produce coded and added, I’d still have the issue stated at the top of this post.

Any help is appreciated because I’ve spent the last 5 hours trying to figure it out. The closest I got to was figuring out that it had to be the save Data script.

2 Likes

You can assign tables like this
local data = {
gold = 100,
strawberries = 5,
gold_strawberries = 2}

and then to simply fetch the data you can use data.gold over trying to find it through index number.

If I was to set it up as

local ds = game:GetService("DataStoreService"):GetDataStore("SaveData")

game.Players.PlayerAdded:Connect(function(plr)
	wait()
	local plrKey = "id_"..plr.UserId
	local Data = {
		Strawberries = plr.ProduceNumberFolder.StrawberryCount,
		GoldenStrawberries = plr.ProduceNumberFolder.GoldStrawCount,
		Carrots = plr.ProduceNumberFolder.CarrotCount,
		Potatoes = plr.ProduceNumberFolder.PotatoCount,
		Cabbage = plr.ProduceNumberFolder.CabbageCount,
		Spinach = plr.ProduceNumberFolder.SpinachCount,
		SpringOnion = plr.ProduceNumberFolder.SpringOnionCount,
		Lettuce = plr.ProduceNumberFolder.LettuceCount,

		Gold = plr.MoneyRelated.Gold
	}
	
	local GetSaved = ds:GetAsync(plrKey)
	if GetSaved then
	Data.Strawberries.Value = GetSaved[1]
	Data.GoldenStrawberries.Value = GetSaved[2]
	Data.Carrots.Value = GetSaved[4]
	Data.Potatoes.Value = GetSaved[5]
	Data.Cabbage.Value = GetSaved[6]
	Data.Spinach.Value = GetSaved[7]
	Data.SpringOnion.Value = GetSaved[8]
	Data.Lettuce.Value = GetSaved[9]
	Data.Gold.Value = GetSaved[10]
	
	else
	local SavingNumbers = {
		Data.Strawberries.Value,
		Data.GoldenStrawberries.Value,
		Data.Carrots.Value,
		Data.Potatoes.Value,
		Data.Cabbage.Value,
		Data.Spinach.Value,
		Data.SpringOnion.Value,
		Data.Lettuce.Value,
		Data.Gold.Value} 
		ds:GetAsync(plrKey,SavingNumbers)
	end
end)
game.Players.PlayerRemoving:Connect(function(plr)
	local Data = {
		Strawberries = plr.ProduceNumberFolder.StrawberryCount,
		GoldenStrawberries = plr.ProduceNumberFolder.GoldStrawCount,
		Carrots = plr.ProduceNumberFolder.CarrotCount,
		Potatoes = plr.ProduceNumberFolder.PotatoCount,
		Cabbage = plr.ProduceNumberFolder.CabbageCount,
		Spinach = plr.ProduceNumberFolder.SpinachCount,
		SpringOnion = plr.ProduceNumberFolder.SpringOnionCount,
		Lettuce = plr.ProduceNumberFolder.LettuceCount,

		Gold = plr.MoneyRelated.Gold
	}
	ds:SetAsync("id_"..plr.userId,{
		
		Data.Strawberries.Value,
		Data.GoldenStrawberries.Value,
		Data.Carrots.Value,
		Data.Potatoes.Value,
		Data.Cabbage.Value,
		Data.Spinach.Value,
		Data.SpringOnion.Value,
		Data.Lettuce.Value,
		Data.Gold.Value
		
	})
end)

would that work?

Or would that be wrong? Because I want each player to have their own inventory and gold as opposed to a global inventory and gold system. If I made sense? I can link the game or something? It will show you how I would intend you to play it (It just has the saving mechanic disabled for the public version atm).
no pressure, just let me know xD.

It will not work, this is how you should do for it to work properly:

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local dataStoreKey = DataStoreService:GetDataStore("TestKey")
local maximumTries = 5

local basicData = {
	gold = 100,
	strawberries = 5,
}

function retrieveData(key, tries)
	local playerData = nil
	
	local success, message = pcall(function()
		playerData = dataStoreKey:GetAsync(key)
	end)
	
	if success or tries < maximumTries then
		return playerData
	else
		retrieveData(key, tries + 1)
	end
end

function saveData(data, key, tries)
	local success, message = pcall(function()
		dataStoreKey:SetAsync(key, data)
	end)

	if not success and tries >= maximumTries then
		retrieveData(key, tries + 1)
	end
end

Players.PlayerAdded:Connect(function(player)
	local playerData = retrieveData("plr"..player.UserId, 0) or basicData
	
	local gold = Instance.new("NumberValue")
	gold.Name = "Gold"
	
	local strawberies = gold:Clone()
	strawberies.Name = "Strawberries"
	
	gold.Value = playerData.gold
	strawberies.Value = playerData.strawberries
	
	gold.Parent = player
	strawberies.Parent = player
end)

Players.PlayerRemoving:Connect(function(player)
	local playerData = {
		gold = player.Gold.Value,
		strawberries = player.Strawberries.Value
	}
	
	saveData(playerData, "plr"..player.UserId, 0)
end)

As you can see, over storing data without an index, we add an index so we can use data.gold over having to use data[1] where the table might not retain its previous sorting, that way no matter where we put gold in the table we can always use data.gold and it will show up that exact value.

Hey! Sorry for my silence. I did exactly what you did, granted I had to reroute some other scripts to match what was here. But it still doesn’t work. But I just quickly want to say thank you, as annoying as I might be, I appreciate this!

Originally I had another script that produced the Instances and then the datastore script called for them after they were already made. So I deleted the script that made the instances and proceeded to copy your set up in the script above.

I had to reroute some outputs from other scripts (Such as the HUD showing how many of the produce you have, including the gold). but none of those scripts actually create or rearrange the instances. I can link the script I have though it’s a bit long.

Small issue I’ve made in the retrieveData() function, tested it and it’s proving to be working.

local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

local dataStoreKey = DataStoreService:GetDataStore("TestKey")
local maximumTries = 5

local basicData = {
	gold = 100,
	strawberries = 5,
}

function retrieveData(key, tries)
	local playerData = nil

	local success, message = pcall(function()
		playerData = dataStoreKey:GetAsync(key)
	end)

	if success then
		return playerData
	else
		if tries < maximumTries then
			retrieveData(key, tries + 1)
		end
	end
end

function saveData(data, key, tries)
	local success, message = pcall(function()
		dataStoreKey:SetAsync(key, data)
	end)

	if not success and tries < maximumTries then
		saveData(data, key, tries + 1)
	end
end

Players.PlayerAdded:Connect(function(player)
	local playerData = retrieveData("plr"..player.UserId, 0)
	
	if not playerData then
		playerData = basicData
	end

	local gold = Instance.new("NumberValue")
	gold.Name = "Gold"

	local strawberies = gold:Clone()
	strawberies.Name = "Strawberries"

	gold.Value = playerData.gold
	strawberies.Value = playerData.strawberries

	gold.Parent = player
	strawberies.Parent = player
	
	print(playerData)
end)

Players.PlayerRemoving:Connect(function(player)
	local playerData = {
		gold = player.Gold.Value,
		strawberries = player.Strawberries.Value
	}

	saveData(playerData, "plr"..player.UserId, 0)
end)
1 Like

Yes! Thank you so much! Really! I hope I wasn’t a bother! It works! Again thank you! :slight_smile:

1 Like