How to create an inventory properly

I’m trying to make an inventory for my game that holds collectibles known as ‘Artifacts’. I’ve tried making it with tables but this gives me errors sometimes and isn’t easy to add/delete things.

Is there any better way of doing this? Especially for adding stuff to the inventory from other scripts.

Could you show us the original code you tried? Also what kind of inventory system. Be more specific on what features it should have, etc.

Sure thing,

I’m aiming for an inventory system that is something like a pet inventory in many simulator games. I want players to be able to equip Artifacts and also for the inventory to have a searching feature and a deleting feature. Here’s my current code with the inventory gui (which I haven’t coded yet)

local DataStore = DataStoreService:GetDataStore("InvData") 
local RepStorage = game.ReplicatedStorage
local Artifacts = RepStorage:WaitForChild("Artifacts")
InvTableData = {}

game.Players.PlayerAdded:Connect(function(Player)
	
	local Data = DataStore:GetAsync(Player.UserId)
	if Data then
		InvTableData = Data.InvTableData
		print("Loaded Data!")
		print(InvTableData)
	else
		print("No Data found")
	end
end)

game.Players.PlayerRemoving:Connect(function(Player)
	DataStore:SetAsync(Player.UserId, {
		["InvTableData"] = InvTableData;
	})
	print("saved data")
end)

Instead of overriding the “InvTableData” every time a player joins just make a new table for each player.

E.g

local Default = { -- this is default table players get if they have no data
     Level = 1;
     Artifacts = {"NoobArtifact"};
};

local InvTableData = {} -- holds all the players current data


-- I'm on mobile so it's hard to write out the entire code block 

function AddArtifact(Player, ArtifactName) -- call this function when u want to add an artifact. U just need to pass the player and the name of the Artifact 
    local PlayerData = InvTableData[Player.UserId];
    if PlayerData then
          table.insert(InvTableData[Player.UserId].Artifact, ArtifactName)
    end
end

game.Players.PlayerAdded:Connect(function(Player)
	
	local Data = DataStore:GetAsync(Player.UserId) -- wrap this in a pcall btw incase it errors!
	if Data then
		InvTableData[Player.UserId] = Data 
		print("Loaded Data!")
		print(InvTableData)
	else
                InvTableData[Player.UserId] = Default
		print("No Data found")
	end
end)

game.Players.PlayerRemoving:Connect(function(Player)
	DataStore:SetAsync(Player.UserId, InvTableData[Player.UserId]) -- wrap in pcall!!
	print("saved data")
end)

I’m on mobile so prob typos but that’s the general idea

2 Likes

Oh yeah I don’t know how I missed that, thanks.
Im just about to leave for work but there’s another issue I’m having with adding stuff to the table I’d like to show you when when I get back if that’s alright.

No worries. Just reply whenever u want and I or someone else will respond!

Sorry for replying so late but here. This script is meant to add the Artifact to their inventory after they have purchased the developer product. But for some reason I keep getting this error and I tried debugging it but didn’t find anything wrong other than the table is currently empty but still exists.

local RepStorage = game.ReplicatedStorage
local Quantitys = RepStorage:WaitForChild("LimitedArifactQuantity")
local Events = RepStorage:WaitForChild("Events")
local PurchaseArtifactEvent = Events:WaitForChild("PurchaseArtfactEvent")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("InvData") 

local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")


local productFunctions = {}

productFunctions[(removedID)] = function(receipt, player)
	local InvTableData = {}
	local Data = DataStore:GetAsync(player.UserId)
	if Data then
		print("Found data")
		print(InvTableData)	
		InvTableData = Data.InvTableData
	table.insert(InvTableData,RepStorage.Artifacts:WaitForChild("Dice Of Destiny").Name)
	print(InvTableData)
		
		DataStore:SetAsync(player.UserId, {
			["InvTableData"] = InvTableData;
		})
		print("saved data")
	Quantitys.DiceOfDestiny.Value = Quantitys.DiceOfDestiny.Value - 1
	end
end


local function processReceipt(receiptInfo)
	local userId = receiptInfo.PlayerId
	local productId = receiptInfo.ProductId

	local player = Players:GetPlayerByUserId(userId)
	if player then
		-- Get the handler function associated with the developer product ID and attempt to run it
		local handler = productFunctions[productId]
		local success, result = pcall(handler, receiptInfo, player)
		if success then
			-- The user has received their benefits!
			-- return PurchaseGranted to confirm the transaction.
			return Enum.ProductPurchaseDecision.PurchaseGranted
		else
			warn("Failed to process receipt:", receiptInfo, result)
		end
	end

	-- the user's benefits couldn't be awarded.
	-- return NotProcessedYet to try again next time the user joins.
	return Enum.ProductPurchaseDecision.NotProcessedYet
end

-- Set the callback; this can only be done once by one script on the server!
MarketplaceService.ProcessReceipt = processReceipt

Sorry its kinda messy right now.
Error:
Failed to process receipt: :arrow_forward: {…} ServerScriptService.Events.PurchaseArtifactScript:21: invalid argument #1 to ‘insert’ (table expected, got nil)

1 Like

The error message indicates that InvTableData is nil when you’re trying to insert an element into it with table.insert(InvTableData, ...). This means that InvTableData is not being properly initialized as a table.

From your code, it seems that you’re trying to set InvTableData to Data.InvTableData if Data exists. If Data or Data.InvTableData is nil, InvTableData will remain an empty table as initialized at the start of your function.

However, if Data.InvTableData is nil, then InvTableData will be set to nil, which would cause the error you’re seeing when you later try to insert into it.

You can prevent this by adding a check to make sure Data.InvTableData is not nil before setting InvTableData to it. If Data.InvTableData is nil, you can keep InvTableData as an empty table.

You can just skip what I just said earlier. This code should fix the problem:

productFunctions[(removedID)] = function(receipt, player)
	local InvTableData = {}
	local Data = DataStore:GetAsync(player.UserId)
	if Data and Data.InvTableData then
		print("Found data")
		InvTableData = Data.InvTableData
	else
		print("Data not found or InvTableData is nil")
	end
	table.insert(InvTableData, RepStorage.Artifacts:WaitForChild("Dice Of Destiny").Name)
	print(InvTableData)
end

1 Like

That makes so much sense now thank you for explaining it.

1 Like

Well it fixed the error I was getting and it prints that it saved the data and everything but when I test again the table is nil. Is there anything wrong with my data stores that you can see?

Does it give any errors? and if so please provide

Nah it doesnt, it prints saved and loaded when leaving and joining just fine. Could it be because im testing in studio or something