Datastore on table not working

Hello, I was trying to create an inventory system as a table in a modulescript inside each player and now I am trying to make the table save everytime the player leaves and rejoins but it isn’t working.

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

game.Players.PlayerAdded:Connect(function(plr)
	local InvModule = plr:WaitForChild("PlayerGui"):WaitForChild("Interfaces"):WaitForChild("InventoryUI"):WaitForChild("ScrollingFrame"):WaitForChild("InventoryModule")
	local Inv = require(InvModule)
	
	Inv = datastore:SetAsync("SaveData"..plr.UserId, Inv)
	
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local InvModule = plr:WaitForChild("PlayerGui"):WaitForChild("Interfaces"):WaitForChild("InventoryUI"):WaitForChild("ScrollingFrame"):WaitForChild("InventoryModule")
	local Inv = require(InvModule)
	
	pcall(function()
		datastore:GetAsync("SaveData"..plr.UserId, Inv)
	end)
	
end)


There is a button that adds an item to the table as well, but I think this is working fine

local Inv = script.Parent.Parent.InventoryUI.ScrollingFrame.Inventory
local itemValue = script.Parent.ItemValue.Value

local InvModule = require(script.Parent.Parent.InventoryUI.ScrollingFrame.InventoryModule)

script.Parent.MouseButton1Up:Connect(function()
	if
		true
	then
		
		if not InvModule[itemValue] then
			InvModule[itemValue] = 1
		else
			InvModule[itemValue] += 1
		end
		
		
		
		print(InvModule)
	end
end)

The first thing I can come up with is the fact that ModuleScripts do not replicate between the client and the server. If you want your changes to the module script to save then you must make the changes on the server side with a server script.

You can make a remote event that fires when you click the button on the client. Then on the server side, you can listen for when that event fires and then make the changes to the module script there.

Note that this with no additional safety checks will be very vulnerable to exploiters, since they can run client-side code.

Are you trying to change the data within the ModuleScript itself, and not the Datastore? If so, you cannot change anything within a ModuleScript inside of the game.

Ohhh alright, would this still work if I used a server script for the button instead of a local script?

I’ve a saving tools in backpack and Player Datastore you can use it if you would like.

local DataStoreService = game:GetService("DataStoreService")
local ToolsDataStore = DataStoreService:GetDataStore("ToolsDataStore")


function PlayerJoined(Player)
	local Success, KeyInfo
	local ToolData


	if ToolData ~= nil then
		for i, data in ipairs(ToolData) do

			local PlayerOwnsTool = Player.Character:FindFirstChild(data[1]) or Player.Backpack:FindFirstChild(data[1]) 
			if ShopItems:FindFirstChild(data[1]) and PlayerOwnsTool == nil then

				local ItemClone = ShopItems[data[1]]:Clone()
				ItemClone.Handle.Quantity.Value = data[2]
				ItemClone.Parent = Player.Backpack

			elseif ShopItems:FindFirstChild(data[1]) and PlayerOwnsTool then
				PlayerOwnsTool.Handle.Quantity.Value = data[2]
			end
		end
	end
end

function PlayerLeft(Player)
local ToolTable = {}

for i,v in pairs(Player.Backpack:GetChildren()) do
		table.insert(ToolTable,{v.Name, v.Handle.Quantity.Value})
	end
	if ToolTable ~= nil then
		local Success, errorMessage = pcall(function()
			ToolsDataStore:SetAsync(Player.UserId, ToolTable)
		end)

		if errorMessage then
			warn(errorMessage)
		end
	end
end

game.Players.PlayerAdded:Connect(PlayerJoined)
game.Players.PlayerRemoving:Connect(PlayerLeft)

No, server scripts can’t listen for input from your keyboard, mouse, ui or gamepad. I would like to point out when you require a module script it returns the value you set to return in the module script with return. In this case it returns a table but that table is not being edited in the module script. You are editing the table returned which will only apply to that server script. No other server script will see those changes.

Hope that made sense, not the best at explaining.

You are saving the data when the player joins, and getting the data when they leave.

Also, you are saving all the data with a single key, which means that (if im right) everyone will have shared inventories. (nvm about this part, i just read the script again, and i am stupid)

1 Like

Nice catch, didn’t even notice that.

Alr, so I tried adding remote events (and swapping the GetAsync and SetAsync) but it still doesn’t save.

Could you show the current code for the scripts, please? It’d help me a lot, as at the moment I’d have to try and guess what’s happening.

Alr here are the scripts.

Button Local Script:

local Inv = script.Parent.Parent.InventoryUI.ScrollingFrame.Inventory
local itemValue = script.Parent.ItemValue.Value

local InvModule = require(script.Parent.Parent.InventoryUI.ScrollingFrame.InventoryModule)

script.Parent.MouseButton1Up:Connect(function()
	game.Workspace.GiveItem:FireServer(itemValue,script.Parent.Parent.InventoryUI.ScrollingFrame.InventoryModule)
end)

Serverscript:

script.Parent.OnServerEvent:Connect(function(plr,itemValue,InvModule2)
	
	local InvModule = require(InvModule2)
	
	if not InvModule[itemValue] then
		InvModule[itemValue] = 1
		print("new item is "..itemValue)
	else
		InvModule[itemValue] += 1
		print("added item "..itemValue)
	end
	

	print(InvModule)
end)

DataStore Script:

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


game.Players.PlayerAdded:Connect(function(plr)
	local InvModule = plr:WaitForChild("PlayerGui"):WaitForChild("Interfaces"):WaitForChild("InventoryUI"):WaitForChild("ScrollingFrame"):WaitForChild("InventoryModule")
	local Inv = require(InvModule)
	
	Inv = datastore:GetAsync("SaveData"..plr.UserId, Inv)
end)


game.Players.PlayerRemoving:Connect(function(plr)
	local InvModule = plr:WaitForChild("PlayerGui"):WaitForChild("Interfaces"):WaitForChild("InventoryUI"):WaitForChild("ScrollingFrame"):WaitForChild("InventoryModule")
	local Inv = require(InvModule)
	
	pcall(function()
		datastore:SetAsync("SaveData"..plr.UserId, Inv)
	end)
	
end)

It prints out the stuff in the table, but when i leave and rejoin, it doesn’t save it

This doesn’t go anywhere, this is not setting the module script to return the data. This is setting the “Inv” variable to the data saved. I’d find another way to store, edit, and save data. For example you could store the table as a JSON string in an attribute or string value. That’s what I’ve done with one of my most recent games.

If you want to go for the JSON string method you could read into HttpService. It has functions to convert a table into a JSON string and vice versa.

image