Data saving to wrong datastore

Hello, could someone help me fix this issue in my script?

  1. What do you want to achieve? I am saving data by converting multiple types of data of the same type (e.g. true/false values for owning tools) into strings and then unpacking them when the player joins with string.split.

  2. What is the issue? For some reason, some value is carrying through between packsave() functions (I am assuming tosavevalue) that is making the data from the 1st function get added to the start of the 2nd.

  1. What solutions have you tried so far? I have tried to clear all my data and setting tosavevalue to local, but nothing has worked yet.

Script:

local players = game.Players
local datastoreserv = game:GetService("DataStoreService")
local coins_store = datastoreserv:GetDataStore("Coins")
local tools_store = datastoreserv:GetDataStore("Tools")
local tempstats_store = datastoreserv:GetDataStore("TemporaryStats")

--Player-independent functions

function tobool(str)
	if str == "true" or str == "false" or str == "nil" then
		local boolNew

		if str == "true" then
			boolNew = true
		elseif str == "false" then
			boolNew = false
		elseif str == "nil" then
			boolNew = nil
		end

		return boolNew
	else
		warn("Parameter must be a string!")
		return
	end
end

function test()
	print("a")
end

players.PlayerAdded:Connect(function(player)
	userId = player.UserId
	print(tostring(coins_store:GetAsync(userId)))
	print(tools_store:GetAsync(userId))
	print(tempstats_store:GetAsync(userId))
	
	--Player-dependent functions
	
	local tosavevalue = ""

	function packsave(folder_to_search, datastore_to_search)
		for i, v in folder_to_search do
			if i <= 1 then
				local tosavevalue = tosavevalue ..tostring(v.Value)
			else
				tosavevalue = tosavevalue.. "," ..tostring(v.Value)
			end

			datastore_to_search:SetAsync(userId, tosavevalue)
			print(tosavevalue, tostring(v.Value))
		end
	end

	function unpack_bool_save(target_datastore, target_folder, target_table)
		packedstring = target_datastore:GetAsync(userId)
		print(packedstring)
		
		if packedstring == nil then
			print("no data yet!")
		elseif packedstring == string then
			local unpacked_table = string.split(packedstring, ",")
			
			for i, v in unpacked_table do
				player:WaitForChild(tostring(target_folder.Name))[target_table[i]].Value = tobool(v)
			end
		end

	end
	
	function unpack_int_save(target_datastore, target_folder, target_table)
		packedstring = target_datastore:GetAsync(userId)
		print(packedstring)
		
		if packedstring == nil then
			print("no data yet!")
		elseif packedstring == string then
			unpacked_table = string.split(packedstring, ",")

			for i, v in unpacked_table do
				player:WaitForChild(tostring(target_folder.Name))[target_table[i]].Value = tonumber(v)
			end
		end
	end
	
	function instanceload(values_table, names_table, target_folder, type_of_instance)
		for i, v in values_table do
			local newInstance = Instance.new(type_of_instance)
			newInstance.Name = names_table[i]
			newInstance.Value = v
			newInstance.Parent = target_folder
		end
	end
	
	--Setting leaderstats
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	coins = Instance.new("IntValue")
	coins.Name = "Coins"
	coins.Parent = leaderstats
	coins.Value = 0
	
	--Setting hidden values (folders)
	toolfolder = Instance.new("Folder")
	toolfolder.Name = "ToolsFolder"
	toolfolder.Parent = player
	
	tempstatfolder = Instance.new("Folder")
	tempstatfolder.Name = "TempStats"
	tempstatfolder.Parent = player
	
	--Setting hidden values (tables)
	--NOTE: tools_owned and similar tables are only used in pre-data loading (instance generation)
	tools = {"rustybucket", "woodenbucket"}
	local tools_owned = {false, false}
	
	tempstats = {"capacity", "max_capacity"}
	local tempstat_values = {0, 10}
	
	--Setting hidden values (instances) (Nothing for now :( )

	instanceload(tools_owned, tools, toolfolder, "BoolValue")
	
	instanceload(tempstat_values, tempstats, tempstatfolder, "NumberValue")
	
	--Loading data
	wait(3)

	local savedcoins = coins_store:GetAsync(userId)
	print("You have "..tostring(savedcoins).." coins!")
	coins.Value = savedcoins
	
	unpack_bool_save(tools_store, toolfolder, tools)
	
	packedstring = ""
	
	unpack_int_save(tempstats_store, tempstatfolder, tempstats)
	
	
	
end)

players.PlayerRemoving:Connect(function()

	local setSuccess, errorMessage = pcall(function()
		
		coins_store:SetAsync(userId, coins.Value)
		
		--Saving multivalues with string to unpack
		
		packsave(toolfolder:GetChildren(), tools_store)
		
		packsave(tempstatfolder:GetChildren(), tempstats_store)
		
		
	end)

	if not setSuccess then
		errorMessage = "Data not saved!"
		warn(errorMessage)
	end

end)

Thanks for reading this post!

For some reason trying to fix it made it worse (the pack data function is ignoring the 1st instance now)

I recommend that you save a table of data instead of ‘Tools’ and ‘Coins.’ Being in separate Datastores, I’d just flat-out. Just a suggestion

Code Example
local PlayerStats = datastoreserv:GetDataStore("PlayerStats")
local Default_PlayerStats = {
Coins = 0,
Tools = {},
--Other Data Values 
}
PlayerDataTable = {} -- Table of current player& there data 
-- Functions for PlayerAdded - Adding there data after retrevial 
--Other Functions  - Player Removed Coins Add/Remove
function AddTool(Player)
--Add Tool to Data Indexing PlayerStats
end
function RemoveTool(Player)
--Remove Tool to Data
end

Strictly an example of a suggestion

edit:

--Connected to a PlayerAdded Event you'd have
function AddPlayerData(Player)
local PlayerData =  PlayerStats:GetAsync(Player.UserId)
PlayerDataTable[Player.UserId] = PlayerData
end

function RemovePlayerData(Player)
--Save PlayerData & Remove from table

end

I’m not sure how to save tables to datastores, as most sources say u have to turn it into a JSON thing(?) and read it somehow? I’ll try testing if tables can save now.

I usually use premade datastore modules by experts using roblox assistant I asked “How to save data tables using dataservice” it save this simple code snippet

local DataStoreService = game:GetService("DataStoreService")
local experienceStore = DataStoreService:GetDataStore("PlayerExperience")

local dataTable = { /* your data table contents */ }
local success, errorMessage = pcall(function()
    experienceStore:SetAsync("User_1234", dataTable)
end)
if not success then
    print(errorMessage)
end

edit: then you just make functions to edit the table but first off you save the data table to table of player data tables like I shown before