Table only counts last thing that added

I have a problem, I have a ‘buttons’ table for my GUI, and this is my code:

local dropdown = nil
local invtable = {}
local buttons = {}

function updateInventory() -- The Issue begins here.
	for _,v in pairs(buttons) do
		local button = v[1]
		local item = v[2]
		if button then
			button.Selection.MouseButton2Click:Connect(function()
				for i,d in pairs(invtable) do
					if dropdown ~= nil then
						dropdown:Destroy()
					end
					dropdown = script.DropdownMenu:Clone()
					dropdown.Position = UDim2.new(0, mouse.X + 2, 0, mouse.Y + 2)
					dropdown.Parent = script.Parent
					dropdown.Drop.MouseButton1Click:Connect(function()
						if dropdown ~= nil then
							dropdown:Destroy()
							dropdown = nil
						end
					end)
					dropdown.Option1.MouseButton1Click:Connect(function()
                        print(item.UniqueId)
						reps.Events.EquipItem:FireServer(item)
						if dropdown ~= nil then
							dropdown:Destroy()
							dropdown = nil
						end
					end)
				end
			end)
		end
	end
end

function newInv(inv) -- I completely reset all of the buttons by destroying them and then re-placing them with new ones
	invtable = {}
	for d,x in pairs(slotsFrame:GetChildren()) do
		if x:FindFirstChild("Selection") then
			x:Destroy()
		end
	end
	invtable = inv
	buttons = {}
	for i,v in pairs(inv["Items"]) do
		local itemFrame = script.ItemPreview:Clone()
		itemFrame.ItemName.Text = v.Name
		itemFrame.Parent = slotsFrame
		local buttonTable = {
			[1] = itemFrame,
			[2] = v,
		}
		table.insert(buttons,buttonTable)
	end
	updateInventory()
end

reps.Events.InventoryInfo.OnClientEvent:Connect(function(inv)
	if inv then
		newInv(inv)
	end
end)

The issue is at the first section, at the dropdown, where I click “Option1” and I intend it to print the actual button that I pressed, and not the last one at that was added to the table.

https://gyazo.com/a7eaccf98cb98a16b544675546f62a36.gif
This gif explains that it prints the ID of the last added item, not the first ones or the actual ones that I click on.

How can I fix this?

1 Like

Are you able to show a snippet of code on how you’re constructing the inventory table?
I’m talking about the item.UniqueId and stuff.

2 Likes

I have just realized it is something wrong with my inventory implementation, cause even when I print after creating an item it seems to replace all the previous items with the newest one…

				table.insert(inventories[Player]["Items"],itemData)
				for _,x in pairs(inventories[Player]["Items"]) do
					print(x.UniqueId)
				end

Here is something from my inventory but wait a minute and i’ll edit this and add more info.

This is where I add a new item into my inventory (inside a module script)

function inventoryHandler:AddItem(Player, itemData)
	if not inventories[Player] then
		inventories[Player] = {}
	end
	local inventory = inventories[Player]
	if itemData then
		local function checkItemExistence(name) -- itemsData is a module that includes all the items in my game
			for _,v in pairs(itemsData) do
				if v.Name == itemData.Name then
					return true
				end
			end
		end
		if #inventories[Player]["Items"] < 40 then
			if checkItemExistence(itemData.Name) then
				local unique = httpService:GenerateGUID(false)
				itemData.UniqueId = unique
				itemData.Equipped = false
				table.insert(inventories[Player]["Items"],itemData)
				for _,x in pairs(inventories[Player]["Items"]) do
					print(x.UniqueId)
				end
				reps.Events.InventoryInfo:FireClient(Player,inventories[Player])
			end
		end
	end
	return true
end

This is also the creation of my inventory for each player:

function inventoryHandler:CreateInventory(Player, Inventory)
	if not Inventory then
		Inventory = {
			["Items"] = {

			}
		}
	end
	inventories[Player] = Inventory
	return inventories[Player]
end

And last but not least:
The actual item data:

	{
		Name = "Firecracker";
		Type = "MagicWeapon";
		Description = "This magical stick casts a fireball that explodes upon contact! \n20 Magic Damage.";
		UII = "rbxassetid://4851526783";
		Rarity = "Unique";
		UniqueId = nil;
		Equipped = false;
	},

I apologize for sending you walls of code :sweat_smile:
Right now i’m trying to figure out what could be wrong, yet I am breaking my head on it…

1 Like

I just wanted to point this out, you’re creating a new function for “checkItemExistence” each time you add an item to the inventory, you should probably move that out.

I’ve got another question, can you try printing x instead of just x.UniqueId when you do

				for _,x in pairs(inventories[Player]["Items"]) do
					print(x.UniqueId)
				end

That’s probably the issue, he’s not creating a new table each time. Otherwise, it makes no sense because the code isn’t interrupted; as shown it shouldn’t overwrite everything, unless everything in the items table is identical.

1 Like

Just printing X supposedly fires the same tables, which looks like its just creating a new item with the same id.

I’ll move that function out, but where should it be?

I am inserting the same item into my inventory, but the ID should be randomized.

It should be above that function, also that’s exactly your issue like @Darkmist101 said, you’re not creating a new table each time you add the item to the inventory so you’re basically modifying the same table each time you add the same item.

To explain :
When you require a module script it caches the result for all the scripts so when you require twice you’re getting the same table and when you edit the result you get you’re basically editing it globally.

So, in order to fix your issue, all you have to do is create a new table for every new item.

You could just do this :

local newItemData = {}
for i,v in ipairs(itemData) do
   newItemData[i] = v
end

then you change the newItemData UniqueID and insert that to the inventory table.

You have to make a new table. Tables are passed by reference, not by value; which is saying you are passing a pointer to a table in memory, not creating a new one (which has to be done explicitly).

When printing a table, it defaults to table: [Memory address]; as you can see in your output, that memory address is identical.

2 Likes

Where should I do this though? Where should I put this newItemData, and how can I insert it into my player inventory I am a bit conflicted. :grimacing:

Actually I am starting to realize, hold up!

So it seems like newItemData is a table that I am adding to my inv table every time, and it just takes all the information and puts it there. (I cannot explain it that well)

1 Like

In your current AddItem it’ll be like this :


		local function checkItemExistence(name) -- itemsData is a module that includes all the items in my game
			for _,v in pairs(itemsData) do
				if v.Name == name then
					return true
				end
			end
		end

function inventoryHandler:AddItem(Player, itemData)
	if not inventories[Player] then
		inventories[Player] = {}
	end
	local inventory = inventories[Player]
	if itemData then
		if #inventories[Player]["Items"] < 40 then
			if checkItemExistence(itemData.Name) then
                                local newItemData = {} 
                                for i,v in ipairs(itemData) do
                                      newItemData[i] = v
                                end
				local unique = httpService:GenerateGUID(false)
				newItemData.UniqueId = unique
				newItemData.Equipped = false
				table.insert(inventories[Player]["Items"],newItemData)
				for _,x in pairs(inventories[Player]["Items"]) do
					print(x.UniqueId)
				end
				reps.Events.InventoryInfo:FireClient(Player,inventories[Player])
			end
		end
	end
	return true
end

Sorry for the indenting issues, I’m just using the message box to edit the script.

2 Likes

Alright, so this does create a new item every time which is perfect!
https://gyazo.com/437fc87d29240ed8d62d0694f4bbaa1c.png

But now inside my client script (which is supposed to replicate the new items added) I get this error, and I don’t get it for print(v.UniqueId) but for v.Name

https://gyazo.com/833e729b29733be3ad2b2b0764001b5e.jp

function newInv(inv)
	invtable = {}
	for d,x in pairs(slotsFrame:GetChildren()) do
		if x:FindFirstChild("Selection") then
			x:Destroy()
		end
	end
	invtable = inv
	buttons = {}
	for i,v in pairs(inv["Items"]) do
		print(v.UniqueId)
		local itemFrame = script.ItemPreview:Clone()
		itemFrame.ItemName.Text = v.Name -- IT ERRORS HERE.
		itemFrame.Parent = slotsFrame
		itemFrame.ID.Value = v.UniqueId
		local buttonTable = {
			[1] = itemFrame,
			[2] = v,
		}
		table.insert(buttons,buttonTable)
	end
	updateInventory()
end

In this specfic code in your AddItem function can you add print(i,v) and show me the output?
Also meant to use pairs not ipairs :laughing: (so change that aswell)

1 Like

Don’t use ipairs, use regular pairs. ipairs is for numbered indexes, which you have none of.

2 Likes

Yeah that was my bad, I forgot it was a dictionary not an array :pensive:

1 Like

ipairs, that was it! Thank you both for helping each other and me! If I have any other questions then I hope you will be embraced to answer them as well :innocent:

1 Like

Already got to a question.
In my equipitem event I fire the ID once the player clicks the ‘equip’ button on their gui, then I want to do a check on the server to loop through their inventory and check if the id they sent matches any of the id’s they have in their inventory.

I have the itemdata in this order:

	{
		Name = "Firecracker";
		Type = "MagicWeapon";
		Description = "This magical stick casts a fireball that explodes upon contact! 20 Magic Damage.";
		UII = "rbxassetid://4851526783";
		Rarity = "Unique";
		UniqueId = nil;
		Equipped = false;
	},

When we added all the data to the new item, it doesn’t add it in the same order?

				for i,v in pairs(itemData) do
					newItemData[i] = v
				end

This is how I am attempting to check:

	local inv = invmod:GetInventory(plr)
	for _,v in pairs(inv["Items"]) do
		for i,x in pairs(v) do
			print(i,x)
			if x.UniqueId == id then -- line 47

What bugs me other than this error is that it’s not in the correct order.
https://gyazo.com/d65045a847bdea0b51dc3f08f2381b36.png

Well, when you do pairs() it does not give the same order instead it’ll order it in an arbitrary order, I don’t really know anything to change it since it’s a dictionary not an array.

Why do you need it to be in the same order though? It shouldn’t matter since again it’s a dictionary not an array so when you index the key you don’t need it to be in the same order.

Also again since the keys are not numbered indexes you could just do :

for _,v in pairs(inv.Items) do
   if v.UniqueId == id then
       -- gottem
   end
end

You can read more about it here :
https://www.lua.org/pil/7.3.html

1 Like

I understand, i’ll learn about this. Thanks.

1 Like

Hey BasedFX, I ran into another issue.
From the things we did yesterday, right now I wrote this in attempt to remove the items from my inventory.

But it looks like that if I “spam” drop my items, it will output this error:

And I won’t be able to drop/equip any items until I refresh the inventory again.

This is my remove item code:

function inventoryHandler:RemoveItem(Player, itemID)
	local inventory = inventories[Player]
	if itemID then
		for i,v in pairs(inventory.Items) do
			if v.UniqueId == itemID then
				if v.Equipped == false then
					inventory.Items[i] = nil
				end
			end
		end
		reps.Events.InventoryInfo:FireClient(Player,inventory) -- line 75
	end
	return true
end

I surely am doing something wrong here.