Issues with Datastores

I’m currently working on a game in which you catch a random fish, and the game will attempt to save the current fish in your inventory (backpack) via Datastore. The datastore saves the names of all the tools you have currently and then creates duplicates with those names and distributes them upon rejoining. Fish can also be sold for coins, and the datastore for coins works flawlessly.

The code works seemingly perfect in studio, but on Roblox it just continues to wipe my datastore after each rejoin no matter what piece of the code I change. I’m very inexperienced with using datastores and so I’m hoping there’s just something silly that I’m overlooking. At first I tried to make it automatic, but after that started breaking I opted for a manual button which seems to yield the same results.

local ServerScriptService = game:GetService("ServerScriptService")
local MainModule = require(ServerScriptService:WaitForChild("MainModule"))
local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local FishArchive = ServerStorage:WaitForChild("FishArchive")

local SavePart = game.Workspace:WaitForChild("SavePart")
local ClickDetector = SavePart:WaitForChild("ClickDetector")

local Player_Data = DataStoreService:GetDataStore("Player_Data2")
local InventoryData = {}

local function addLeaderstats(Player)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = Player
	
	local Coins = Instance.new("IntValue")
	Coins.Name = "Coins"
	Coins.Parent = leaderstats
	return Coins
end

local function SpawnCloneFish(InventoryData,Player)
	if InventoryData ~= nil then
		for _,v in InventoryData do
			if FishArchive:FindFirstChild(v) then
				local NewFish = FishArchive:FindFirstChild(v):Clone()
				for _,CoinFishValue in MainModule.CoinValuesTable do
					if CoinFishValue[1] == NewFish.Name then
						local Coins = Instance.new("IntValue")
						Coins.Name = "Coins"
						Coins.Value = math.random(CoinFishValue[2],CoinFishValue[3])
						Coins.Parent = NewFish
						NewFish.Parent = Player.Backpack
					end
				end
			end
		end
	end
end

local function loadData(Player)
	local Coins = addLeaderstats(Player)
	
	local InventoryKey = Player.UserId .. "_Inventory"
	local CoinKey = Player.UserId .. "_Coins"
	
	local CoinData = nil
	
	local Success,Failure = pcall(function()
		CoinData = Player_Data:GetAsync(CoinKey)
		InventoryData = Player_Data:GetAsync(InventoryKey)
	end)

	SpawnCloneFish(InventoryData,Player)

	if Success and MainModule.DebugMessages then
		Coins.Value = CoinData
		if MainModule.DebugMessages then
			print("Data loaded for " .. Player.Name .. "," .. Player.UserId)
			print(InventoryData)
		end
	end
	while wait(2) do
		print(InventoryData)
	end
end

local function saveData(Player)
	local leaderstats = Player:FindFirstChild("leaderstats")
	
	local CoinKey = Player.UserId .. "_Coins"
	local InventoryKey = Player.UserId .. "_Inventory"

	InventoryData = {}
	for _,v in Player.Backpack:GetChildren() do
		table.insert(InventoryData,v.Name)	
	end

	local Success, Failure = pcall(function()
		Player_Data:SetAsync(CoinKey,leaderstats.Coins.Value)
		Player_Data:SetAsync(InventoryKey,InventoryData)
	end)
	
	if Success and MainModule.DebugMessages then
		print("Saved data for " .. Player.Name .. "," .. Player.UserId)
		print(InventoryData)
	elseif Failure and MainModule.DebugMessages then
		print("Error saving data for " .. Player.Name)
		warn(Failure)
	end
end

Players.PlayerAdded:Connect(function(Player)
	loadData(Player)
end)

ClickDetector.MouseClick:Connect(function(Player)
	saveData(Player)
end)

Here is my current rendition of the script, what could I be doing wrong? The script doesn’t seem to fire any errors and says its saving and loading correctly, except it isn’t.

1 Like

Couple questions as comments in the code.

--saveData function
if Success and MainModule.DebugMessages then
		print("Saved data for " .. Player.Name .. "," .. Player.UserId) --does this print when saving?
		print(InventoryData)

I’d imagine that print(InventoryData) doesn’t output much usable data, maybe try this to get more details.

for _, item in ipairs(InventoryData) do
	print(item.Name)
end

In your loadData function

--loadData function

local Success,Failure = pcall(function()
	CoinData = Player_Data:GetAsync(CoinKey)
	InventoryData = Player_Data:GetAsync(InventoryKey)
end)

--if you print the InventoryData at this point, does the data exist and is it correct?
print("InventoryData is: " .. #InventoryData .. " long.")
for _, item in ipairs(InventoryData) do
	print(item.Name)
end

SpawnCloneFish(InventoryData,Player) --if good to this point it's likely to do with how you're (re)spawning the fish.

Other note, in loadData() your checking if Success and MainModule.DebugMessages is true, then you have an if MainModule.DebugMessages is true again, nested below that first if. Should work either way, but you already know MainModule.DebugMessages is true so no need to check it again. You don’t seem to be doing that in saveData().

Not sure why you need the while wait(2) the data should already be there at this point. Also, it’s suggest to use task.wait() over wait() but I don’t see the need for either.

Add some prints before/after SpawnCloneFish() and see if things are as you expect.

Thank you, a lot of the strange inconsistencies and print statements are just from me trying to add checks wherever I could in the code to see what was going wrong. The while wait(2) loop is meant to make sure that saving data is actually adding the fish to the Inventory table and it’s not remaining empty.

SpawnCloneFish() seems to work without issue, however the problem I’m having involves the inventory table somehow getting wiped. Initially, the saving was done automatically upon leaving, but I read around that roblox can sometimes have trouble saving data before the player disappears, so I swapped it to a manual save instead.

In game, the debug message claims that the data has been saved, and the print statements confirm that the fish has been added to the inventory table, however when I rejoin the inventory table is inconsistently either working correctly or wiping completely.

After reviewing some of my code, I realize that it may be a small issue with how I’m grabbing the data to clone the fish? I’m not too familiar with pairs or ipairs but they may be part of the solution due to how my data is formatted in the table.

I have a folder in ServerStorage called “FishArchive” which is an archive of every catchable fish in the game.

archive

but the fish also have a “Coins” value that is inserted into them upon being caught. To replicate this,
the SpawnCloneFish() function grabs their data from the same table (MainModule.CoinValuesTable) and generates a new Coins value.

‘’’
MainModule.CoinValuesTable = {
–Name Of Fish, Minimum Coins, Maximum Coins

--Trash
{"Soda",1,1},

--Fish
{"Blubberfish",3,5},

{"Figfish",5,10},
{"Shiny Figfish",20,25},

{"Fishwig",5,15},
{"Giant Fishwig",50,75},

{"Glowfish",5,10},

{"Dogfish",1,3},
{"Shiny Dogfish",3,8},

{"Fish.png",50,100},

{"Blubbort",100,150},
{"Pink Fish", 400,560},

{"Flatfish",10,15},
{"Shiny Flatfish",20,35},
{"Giant Flatfish",50,100},

{"Carp",1,5},
{"Shiny Carp",20,30},

{"Minefish",200,250}

}
‘’’

This is how the table is formatted, and the constant searching through tables and grabbing different sub-tables/values may be my issue.

I toyed with the script a few minutes ago and was able to fix the entire system by moving things to the MainModule as well as making use of ipairs and pairs for the tables. Thanks for the help!