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.
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
Right now i’m trying to figure out what could be wrong, yet I am breaking my head on it…
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.
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.
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.
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)
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.
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
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 (so change that aswell)
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
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
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
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