DataStore not Saving

Goal/Aim

  • I am trying to write a script that chops trees and awards the player a random amount of [treeType]. This all works fine and what not. However, I’m having trouble getting the DataStore to save the values this script outputs.

Script

-- LocalScript inside Axe (tool)
local tool = script.Parent
local player = game.Players.LocalPlayer
local oreInventory = player.OreInventory
local mouse = player:GetMouse()
local equipped = false
local handle = tool.Handle
local can_cut = false
local debounce = false

tool.Equipped:Connect(function()
	equipped = true
end)

tool.Unequipped:Connect(function()
	equipped = false
end)

mouse.Button1Down:connect(function()
	if equipped and debounce == false then
		debounce = true
		can_cut = true
	end
end)

handle.Touched:connect(function(hit)
	if equipped and can_cut then
		can_cut = false
		if (string.lower(hit.Parent.Name) == "tree") then
			local tree = hit.Parent
			local treeHealth = tree:WaitForChild("HP")
			local treeType = tree:WaitForChild("TreeType").Value
			if treeHealth.Value > 0 then
				treeHealth.Value = treeHealth.Value - 1
				oreInventory[treeType].Value = oreInventory[treeType].Value + math.random(1,2)
				print(treeHealth.Value)
			else
				for i,v in pairs(tree:GetChildren()) do
					if v:IsA("Part") then
						for i = 1,10 do
							v.Transparency = (i/10)
							game:GetService("RunService").Heartbeat:Wait()
						end
						v:Destroy()
					end
				end
			end
		end
		wait(1)
		debounce = false
	end
end)

And secondly,

-- Script in ServerScriptService
local dataService = game:GetService("DataStoreService")
local httpService = game:GetService("HttpService")
local petStore = dataService:GetDataStore("Pets")
local moneyStore = dataService:GetDataStore("Money")
local oreStore = dataService:GetDataStore("Ore")

game.Players.PlayerRemoving:connect(function(player)
	local playerKey = tostring(player.UserId)
	local stats = player.leaderstats
	local pets = {}
	local money = stats.Money
	local ore = {}
	local ingots = {}
	local petInventory = player:WaitForChild("PetInventory")
	local oreInventory = player:WaitForChild("OreInventory")
	
	for i,v in pairs(petInventory:GetChildren()) do
		table.insert(pets, v.ID.Value)
	end
	
	for i,v in pairs(oreInventory:GetChildren()) do
		table.insert(ore, (v.Name.."-"..v.Value))
	end
	
	local petJSON = httpService:JSONEncode(pets)
	local moneyJSON = httpService:JSONEncode(money)
	local oreJSON = httpService:JSONEncode(ore)

	petStore:SetAsync(playerKey, petJSON)
	moneyStore:SetAsync(playerKey, moneyJSON)
	oreStore:SetAsync(playerKey, oreJSON)
end)

game.Players.PlayerAdded:connect(function(player)
	local playerKey = tostring(player.UserId)
	local stats = player:WaitForChild("leaderstats")
	local petInventory = player:WaitForChild("PetInventory")
	local oreInventory = player:WaitForChild("OreInventory")
	local petStorage = game.ReplicatedStorage.Pets
	local pets = {}
	local ore = {}
	local money = {}
	local ingots = {}
	
	local petStoreLOAD = petStore:GetAsync(playerKey)
	local petJSON = httpService:JSONDecode(petStoreLOAD)
	
	local moneyLOAD = moneyStore:GetAsync(playerKey)
	local moneyJSON = httpService:JSONDecode(moneyLOAD)
	
	local oreLOAD = oreStore:GetAsync(playerKey)
	local oreJSON = httpService:JSONDecode(oreLOAD)
	
	for _,pet in pairs(petJSON) do
		for _,target in pairs(petStorage:GetChildren()) do
			if target.ID.Value == pet then
				local newPet = target:Clone()
				newPet.Parent = petInventory
			end
		end
	end
	
	for _,ore in pairs(oreJSON) do
		local hyphen = string.find(ore, "-")
		local oretype = string.sub(ore, 1, (hyphen-1))
		local quantity = tonumber(string.sub(ore, (hyphen+1), string.len(ore)))
		for _,target in pairs(oreInventory:GetChildren()) do
			if target.Name == oretype then
				target.Value = quantity
			end
		end
	end
end)

I have tried looking at other posts and websites for help to at least try and understand a source of errors yet I seem to fail to find one. Any help would be greatly appreciated!

First off, you don’t need to do “local playerKey = tostring(player.UserId)” , numbers can be used as keys (so no need for tostring())

Furthermore, it would help to find errors if you showed us what the error is. Also, you can save tables within tables so you don’t need to save and load 3 different tables.
Ex:

PlayerData = {pets = {}, ore = {}, money = {}, ingots = {}}

Also, I don’t see why you’re encoding/decoding, you don’t need to.

1 Like

This might be relevant. How to properly save player data in data stores upon server close

Also please do what @viindicater said, and no need to JSON-encode anything. This is already done for you.

Is this enabled? image

This really doesn’t answer my question at all; I did not ask to be reprimanded on the necessities of a DataStore. There is no error, it simply just doesn’t save the value gotten from the LocalScript in the tool. Alternatively, when I use a normal Script to set values, it works fine.

Ok. I fixed the problem myself. I’m not that good at scripting and didn’t realise that LocalScript meant client-side only. I changed to a normal Script and rewrote some things i.e:

mouse.Button1Down:connect(function()
	if equipped and debounce == false then
		debounce = true
		can_cut = true
	end
end)

Became:

tool.Activated:connect(function()
	if equipped and debounce == false then
		debounce = true
		can_cut = true
	end
end)

And now all works well.

I appreciate yours and @viindicater’s comments but I will continue to write them with JSON-encode because I actually did need them. I was storing a mixed table and therefore, roblox would not allow me to store that sort of array. Any further comments, I’d be happy to explain myself. Thanks for your time, ^-^.

Yes. I should have made myself more clear, apologies. Some values were saving and loading completely functionally; some were not - turns out, I was a victim of client-server confuzzlement. Thank you for your reply, ^-^.