Inventory UI / Tool Saving system not working

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I need help creating a saving inventory system for my scfi game, so theres this thing called a HoloGlass, which is basically a screengui supposed to be like a mobile holographic phone kind of thing, in the Tradermart app (the shop) you can buy items from there with ingame money, and once you do buy an item, it shows in the inventory app, and you can retrieve it by clicking on that item and it will add it to your player backpack, and you can put it back by pressing the V key while its equipped. All of that is already scripted. I just need it to save everything thats in the inventory app, and reload it once you join the game again. Each tool has an item ID inside of it, which apple is item id 1, and for example if a pencil was item id 2, for saving the data, in a table, it would show up as (1,1,2) for two apples and one pencil for example. But I need help with figuring out how to get every item inside the inventory scrolling frame with each of its linked item in the object id for saving it, and then looking through all of the item ids inside the items folder under replicated storage and recreating each of the item uis in the scrolling frame, because I’m bad at understanding for loops and I haven’t really needed to use them that much.

  2. What is the issue? Include screenshots / videos if possible!
    The items in the inventory Ui won’t save.

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I’ve tried looking at other devforum posts, which none of them really match the same thing I’m trying to do to actually help anything, and I tried AI which isn’t really working either.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

This is my code from the AI that it scripted me if that will help any of you:

Server Script (server script service):

-- Services
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local MarketplaceService = game:GetService("MarketplaceService")
local InventoryDataStore = DataStoreService:GetDataStore("InventoryDataStore")

-- RemoteEvents
local InventoryRemoteEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("InventoryRemoteEvent")

-- Get the inventory limit based on gamepass
local function getInventoryLimit(player)
	local gamepassId = 13600173502  -- Replace with your gamepass ID
	local hasGamepass = false

	local success, result = pcall(function()
		hasGamepass = MarketplaceService:UserOwnsGamePassAsync(player.UserId, gamepassId)
	end)

	if not success then
		warn("Error checking gamepass for " .. player.Name .. ": " .. result)
	end

	return hasGamepass and 35 or 20
end

-- Save player's inventory to DataStore
local function saveInventory(player, inventory)
	local playerId = tostring(player.UserId)

	local success, errorMessage = pcall(function()
		InventoryDataStore:SetAsync(playerId, inventory)
	end)

	if not success then
		warn("Failed to save inventory for " .. player.Name .. ": " .. errorMessage)
	else
		print("Inventory successfully saved for " .. player.Name)
	end
end

-- Load player's inventory from DataStore
local function loadInventory(player)
	local playerId = tostring(player.UserId)
	local inventoryLimit = getInventoryLimit(player)

	local success, inventory = pcall(function()
		return InventoryDataStore:GetAsync(playerId)
	end)

	if success then
		if inventory then
			-- Fire a remote event to ask the client to load inventory data
			InventoryRemoteEvent:FireClient(player, "LoadInventory", inventory)
		else
			print("No inventory data found for " .. player.Name)
		end
	else
		warn("Failed to load inventory for " .. player.Name .. ": " .. inventory)
	end
end

-- Connect functions to Player events
Players.PlayerAdded:Connect(function(player)
	loadInventory(player)
end)

Players.PlayerRemoving:Connect(function(player)
	-- Use a RemoteEvent to save inventory
	InventoryRemoteEvent:FireClient(player, "SaveInventory")
end)

Local Script (starter player scripts):

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local Player = Players.LocalPlayer
local InventoryRemoteEvent = ReplicatedStorage:WaitForChild("Events"):WaitForChild("InventoryRemoteEvent")

-- Function to get inventory from the GUI
local function getInventoryFromGUI()
	local inventory = {}
	local inventoryUI = Player:WaitForChild("PlayerGui"):FindFirstChild("Main"):FindFirstChild("HoloGlass"):FindFirstChild("Apps"):FindFirstChild("Inventory")
	local scrollingFrame = inventoryUI:FindFirstChild("AppInfo"):FindFirstChild("ScrollingFrame")

	for _, button in ipairs(scrollingFrame:GetChildren()) do
		if button:IsA("TextButton") and button.Name ~= "Item" then
			local linkedItem = button:FindFirstChild("LinkedItem")
			if linkedItem and linkedItem:IsA("ObjectValue") then
				local itemID = linkedItem.Value:GetAttribute("ID")
				if itemID then
					table.insert(inventory, itemID)
				end
			end
		end
	end

	return inventory
end

-- Function to save inventory
local function saveInventory()
	local inventory = getInventoryFromGUI()
	-- Send inventory data to server
	InventoryRemoteEvent:FireServer("SaveInventory", inventory)
end

-- Function to load inventory
local function loadInventory(inventory)
	local inventoryUI = Player:WaitForChild("PlayerGui"):FindFirstChild("Main"):FindFirstChild("HoloGlass"):FindFirstChild("Apps"):FindFirstChild("Inventory")
	local scrollingFrame = inventoryUI:FindFirstChild("AppInfo"):FindFirstChild("ScrollingFrame")

	-- Clear existing items
	for _, item in ipairs(scrollingFrame:GetChildren()) do
		if item:IsA("TextButton") and item.Name ~= "Item" then
			item:Destroy()
		end
	end

	-- Load saved items
	for i, itemID in ipairs(inventory) do
		if i > getInventoryLimit(Player) then break end
		local item = ReplicatedStorage.Items:FindFirstChildWhichIsA("Tool", true, function(tool)
			return tool:GetAttribute("ID") == itemID
		end)
		if item then
			local itemClone = inventoryUI.AppInfo.Item:Clone()
			itemClone.Name = itemID
			itemClone.Visible = true
			itemClone.Text = item.Name  -- Set button text or description

			local linkedItem = Instance.new("ObjectValue")
			linkedItem.Name = "LinkedItem"
			linkedItem.Value = item
			linkedItem.Parent = itemClone

			itemClone.Parent = scrollingFrame
		else
			warn("Item not found in ReplicatedStorage: " .. itemID)
		end
	end
end

-- Listen to remote events
InventoryRemoteEvent.OnClientEvent:Connect(function(action, data)
	if action == "LoadInventory" then
		loadInventory(data)
	elseif action == "SaveInventory" then
		saveInventory()
	end
end)

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

I just want it to be able to save/load, I already have the rest of it scripted basicallly.

Outlined in the blue is template to recreate the ui off of once loading in each item:
Screenshot 2024-07-21 213512

Screenshot of replicated storage:
Screenshot 2024-07-21 213615

1 Like

I am wondering how a player adds items to this Gui and how a server validates that data. Never trust the client.
I tend to create a folder under the Player object literally called Inventory. I then use this to store all player items. When a player purchases and item, the request is fired to the server, which then updates the Inventory folder after the relevant sanity checks.
When saving and loading the Inventory data, I just dump the entire folder to/from the well known ProfileService module which is really simple.
When a player opens the relevant Gui, it reads the Inventory folder and populates the relevant data.

I have did my research on ProfileService, it seems a bit complex and I’ve had some issues with it. Maybe I could try something else like this instead because all that is saving is an object value inside of each textbutton and this converts data to save with objectvalues and other things: Converter Module: Instance ↔ Table | Save Instances to DataStores and More!

My game also has multiple different places for each of the different planets and moons in the game (it’s a sc fi game) which is a big part, but I’m not sure if that saves between multiple different places