Nah. We still have a bit more to do with the hotbar and making sure it works properly with all slots, then the armor equipping and unequipping, which might take a while, then finally the saving and loading, and THEN the bug fixes episode. It'll be a long series but I think it'll be worth it for the completed and functional system. I'm also starting college now, but I hope to still keep releasing weekly if I can, but we'll see how it goes.
The next episode should be coming out tomorrow just after noon, and in that I finish the hotbar equipping and unequipping. Though sadly we still have a fair bit left to do before the system is entirely complete, but I'll try to get the videos done as fast as possible.
you sometimes cut some clips too short and i have to guess the code, great series tho keep it up. i would prefer slower paced and more explanation but idk what everyone else prefers
Yeah, I've been experimenting with different techniques for recording and editing these videos. The editing should get better as this series goes on (in theory), but I've been thinking of strategies for future series that would be a little bit more organized and easier to edit/explain.
One question, are you going to include somethign like a sorting system for example when you pick up armor, that it automatically gets sorted into the armor part of the inventory (not the slots) and when you pick up a normal item or a weapon it gets sorted into the item or weapon part of your inventory?
I was originally planning on adding something like that since I made something similar for an inventory I made for someone's project, but it ended up slipping my mind in the process. It should be fairly easy to just modify the UpdateDisplay function to only show stacks of a certain ItemType attribute though. That's partially why I set it up that way, even though I forgot the actual sorting portion.
Ahh yeah I was originally going to include a sorting method for specific item types and maybe even a search bar but it ended up slipping my mind through it all. Sorting by category would be pretty simple though, as you'd just change the udpatedisplay to only show stacks with a specific ItemType value.
I mean I'm not an expert on the topic other than just making sure you know what the client does and doesn't have access too, but I could share some key points and things to keep in mind and maybe do some extra research for some other tips other people suggest too. I'll add the video to my list of ideas, but I might not get around to it until maybe after the shop series, we'll see. Depends on how busy I get in college.
this is really great inentory system, but i think i missed some parts, so i need to see your InventoryClient and InventoryServer codes :) btw my problem is that on line 146 in InventoryClient this code pops up eror which says: "invalid argument #1 to 'pairs' (table expected, got nil)" -- Creating Item Frames for i, stackData in pairs(InventoryClient.InvData.Inventory) do can anyone help me ?
You can get access to the code for $2.99/month either by pressing "Join" on UA-cam and joining the Discord server or by subscribing for the same price and perks on the Discord server itself. Otherwise, though, you can post questions there too and I'll probably be more likely to respond faster as well. I couldn't really say what's going wrong with your system with that information alone, but to translate the error into English, it's basically saying "InventoryClient.InvData.Inventory" doesn't exist. "InventoryClient.InvData" does exist, it just can't find a ".Inventory" inside that for whatever reason, but there could be a variety of reasons as to why that might be that all depend on what the rest of your code looks like.
I don't remember when I first declared it in the series, but "stackData" refers to the data for an individual stack in the inventory. The inventory as a whole consists of one big table with a few sub tables and properties, such as the Inventory, Hotbar, and Armor. The Inventory is just an array of stackData tables, which contain information for each stack of items, including the tools contained in that stack. The Hotbar is a dictionary that maps hotbar slots to stack IDs of stacks that are equipped in that slot. I haven't gotten to the Armor in this series yet, but it's essentially going to be the same as the hotbar. I hope that helps, and let me know if you have any more questions with it.
@@Knineteen19 Hey, Im a bit late to the series but my stackdata is not loading the description and image in the InventoryClient but works fine in the inventoryServer. Do you know any reason this might be happening?
ok now im stuck. my equip button does not work. it neither changes to the nor lets me put the item i selected into the hotbar. unequip works and the button does change to say equip tho im confused.
and heres my inventoryserver: --Services local StarterPack = game:GetService("StarterPack") local Players = game:GetService("Players") local RS = game:FindService("ReplicatedStorage") local SS = game:GetService("ServerStorage") local HS = game:GetService("HttpService") --modules local Signal = require(RS.Modules.Signal) local Janitor = require(RS.Modules.Janitor) --module local InventoryServer = {} InventoryServer.AllInventories = {} InventoryServer.MaxStacks = 20 InventoryServer.MaxStackData = { Weapon = 1; Armor = 1; Consumable = 5; Resource =10; } --equipping item to hotbar function InventoryServer.EquipToHotbar(player, equipTo, stackId)
--getting inventory local inv = InventoryServer.AllInventories[player]
--removing if exists already InventoryServer.UnequipFromHotbar(player, stackId)
--Validating Stack local isValid = false for i, stackData in pairs(inv.Inventory) do if stackData.StackId == stackId then isValid = true end end if not isValid then return end
end --unequipping item from hotbar function InventoryServer.UnequipFromHotbar(player, stackId)
--getting inventory local inv = InventoryServer.AllInventories[player]
--removing if exists already local found = false for slotNum, equippedId in pairs(inv.Hotbar) do if equippedId == stackId then inv.Hotbar[slotNum] = nil found = true end end --updating client if found then Signal.FireClient(player, "Inventory:ItemsUpdated", InventoryServer.GetInventoryJSON(player)) end
end --adding items function InventoryServer.RegisterItem(player, tool) if tool.ClassName ~= "Tool" then return end
--getting inventory local inv = InventoryServer.AllInventories[player] --shortcut
--looping all stacks local foundStack = nil --TODO: autoequip to hotbar if slots are empty for i, stackData in pairs(inv.Inventory) do
--checking stack data if table.find(stackData.Items, tool) then return --the tool is already registered in inventory elseif stackData.Name == tool.Name and #stackData.Items < InventoryServer.MaxStackData[stackData.ItemType] then table.insert(stackData.Items, tool) -- adding to existing stack foundStack = stackData break end
end
--checking if stack found if not foundStack then if #inv.Inventory < InventoryServer.MaxStacks then --creating new stack local stack = { Name = tool.Name; Description = tool.ToolTip; Image = tool.TextureId; ItemType = tool:GetAttribute("ItemType"); IsDroppable = tool:GetAttribute("IsDroppable"); Items = {tool}; StackId = inv.LastStackId; } inv.LastStackId += 1 table.insert(inv.Inventory, stack)
--equipping to first open slot for slotNum = 1, 9 do if inv.Hotbar[slotNum] == nil then InventoryServer.EquipToHotbar(player, slotNum, stack.StackId) break end end
else error("The user has more than the max stacks of 20 items! Our code doesnt handle that yet!") end end
--updating client Signal.FireClient(player, "Inventory:ItemsUpdated", InventoryServer.GetInventoryJSON(player)) end --removing items function InventoryServer.UnregisterItem(player, tool) if tool.ClassName ~= "Tool" then return end
--getting inventory local inv = InventoryServer.AllInventories[player]
--finding tool for i, stackData in pairs(inv.Inventory) do local found = table.find(stackData.Items, tool) if found then
--removing stack if #stackData.Items == 0 then table.remove(inv.Inventory, table.find(inv.Inventory, stackData)) InventoryServer.UnequipFromHotbar(player, stackData.StackId) end
end --player added function InventoryServer.PlayerAdded(player)
--waiting for starterpack for i, tool in pairs(StarterPack:GetChildren()) do while not player.Backpack:FindFirstChild(tool.Name) do task.wait() end end
for i, stackData in pairs(inv.Inventory) do table.insert(adjustInv.Inventory, { Name = stackData.Name; Description = stackData.Description; Image = stackData.Image; ItemType = stackData.ItemType; IsDroppable = stackData.IsDroppable; Count = #stackData.Items; -- replacing tool list with count StackId = stackData.StackId; }) end
return HS:JSONEncode(adjustInv) end --initializing function InventoryServer.Start()
--player added for i, player in pairs(Players:GetPlayers()) do task.spawn(InventoryServer.PlayerAdded, player) end Players.PlayerAdded:Connect(InventoryServer.PlayerAdded)
--getting Inventory From Client Signal.ListenRemote("Inventory:GetInventoryJSON", InventoryServer.GetInventoryJSON) Signal.ListenRemote("Inventory:EquipToHotbar", InventoryServer.EquipToHotbar) Signal.ListenRemote("Inventory:UnequipFromHotbar", InventoryServer.UnequipFromHotbar)
do i have to make a local itemF at the beginning of the script and if yes what am i supposed to make it? i cannot find it in the video and studio is screaming at me for not having it defined at this part of the code: --select item function InventoryClient.SelectItem(stackData, item)
--setting selected InventoryClient.SelectedStackId = stackData and stackData.StackId or nil
--setting frame colors for i, otheritemF in pairs(itemsSF:GetChildren()) do if otheritemF.ClassName == "ImageButton" and otheritemF ~= itemSample then if otheritemF == itemF then otheritemF.BackgroundColor3 = otheritemF:GetAttribute("SelectedColor") else otheritemF.BackgroundColor3 = otheritemF:GetAttribute("NormalColor") end end end specifically the part about if otheritemF == itemF
Is this the last episode of the series, other than the bug fixing one?
Nah. We still have a bit more to do with the hotbar and making sure it works properly with all slots, then the armor equipping and unequipping, which might take a while, then finally the saving and loading, and THEN the bug fixes episode. It'll be a long series but I think it'll be worth it for the completed and functional system.
I'm also starting college now, but I hope to still keep releasing weekly if I can, but we'll see how it goes.
Also, can you add other slots to the armor like backpacks and vests? and if you can how?
I have been looking/waiting for this kind of series to come out for months or maybe even years so thank you very much!
I'm glad I could help!
U are a legend bro! Ty for explaining, helps me learning lua even more
Lets goo next Part!!!!!!
Woot woot! Now I'm off to college so we'll see how well I can keep this whole weekly thing up lol.
awesome tutorial
Glad to help!
So glad i could go through all of this, just to have to wait a few days, to finally complete it. Bruh
The next episode should be coming out tomorrow just after noon, and in that I finish the hotbar equipping and unequipping. Though sadly we still have a fair bit left to do before the system is entirely complete, but I'll try to get the videos done as fast as possible.
A lot of typing but Hella worth it
How do you make your tool images look so nice? plus love the vids
you sometimes cut some clips too short and i have to guess the code, great series tho keep it up. i would prefer slower paced and more explanation but idk what everyone else prefers
Yeah, I've been experimenting with different techniques for recording and editing these videos. The editing should get better as this series goes on (in theory), but I've been thinking of strategies for future series that would be a little bit more organized and easier to edit/explain.
One question, are you going to include somethign like a sorting system for example when you pick up armor, that it automatically gets sorted into the armor part of the inventory (not the slots) and when you pick up a normal item or a weapon it gets sorted into the item or weapon part of your inventory?
I was originally planning on adding something like that since I made something similar for an inventory I made for someone's project, but it ended up slipping my mind in the process. It should be fairly easy to just modify the UpdateDisplay function to only show stacks of a certain ItemType attribute though. That's partially why I set it up that way, even though I forgot the actual sorting portion.
I think it'd be awesome if the inventory had different categories, for example: armour , weapon , resource categories etc.
Ahh yeah I was originally going to include a sorting method for specific item types and maybe even a search bar but it ended up slipping my mind through it all. Sorting by category would be pretty simple though, as you'd just change the udpatedisplay to only show stacks with a specific ItemType value.
the "Slot.image = " " make my images be empty, i have to remove them but if i do it works perfectly and ik that isnt supposed to work
After the inventory series, could you make a video about ways to prevent exploits and hackers in your games?
I mean I'm not an expert on the topic other than just making sure you know what the client does and doesn't have access too, but I could share some key points and things to keep in mind and maybe do some extra research for some other tips other people suggest too. I'll add the video to my list of ideas, but I might not get around to it until maybe after the shop series, we'll see. Depends on how busy I get in college.
Ok!
this is really great inentory system, but i think i missed some parts, so i need to see your InventoryClient and InventoryServer codes :)
btw my problem is that on line 146 in InventoryClient this code pops up eror which says: "invalid argument #1 to 'pairs' (table expected, got nil)"
-- Creating Item Frames
for i, stackData in pairs(InventoryClient.InvData.Inventory) do
can anyone help me ?
You can get access to the code for $2.99/month either by pressing "Join" on UA-cam and joining the Discord server or by subscribing for the same price and perks on the Discord server itself. Otherwise, though, you can post questions there too and I'll probably be more likely to respond faster as well.
I couldn't really say what's going wrong with your system with that information alone, but to translate the error into English, it's basically saying "InventoryClient.InvData.Inventory" doesn't exist. "InventoryClient.InvData" does exist, it just can't find a ".Inventory" inside that for whatever reason, but there could be a variety of reasons as to why that might be that all depend on what the rest of your code looks like.
I returned this tutorials after months, what is "stackData" exactly? in what moment was declared
I don't remember when I first declared it in the series, but "stackData" refers to the data for an individual stack in the inventory. The inventory as a whole consists of one big table with a few sub tables and properties, such as the Inventory, Hotbar, and Armor. The Inventory is just an array of stackData tables, which contain information for each stack of items, including the tools contained in that stack. The Hotbar is a dictionary that maps hotbar slots to stack IDs of stacks that are equipped in that slot. I haven't gotten to the Armor in this series yet, but it's essentially going to be the same as the hotbar.
I hope that helps, and let me know if you have any more questions with it.
@@Knineteen19 Hey, Im a bit late to the series but my stackdata is not loading the description and image in the InventoryClient but works fine in the inventoryServer. Do you know any reason this might be happening?
ok now im stuck. my equip button does not work. it neither changes to the nor lets me put the item i selected into the hotbar. unequip works and the button does change to say equip tho im confused.
and heres my inventoryserver:
--Services
local StarterPack = game:GetService("StarterPack")
local Players = game:GetService("Players")
local RS = game:FindService("ReplicatedStorage")
local SS = game:GetService("ServerStorage")
local HS = game:GetService("HttpService")
--modules
local Signal = require(RS.Modules.Signal)
local Janitor = require(RS.Modules.Janitor)
--module
local InventoryServer = {}
InventoryServer.AllInventories = {}
InventoryServer.MaxStacks = 20
InventoryServer.MaxStackData = {
Weapon = 1;
Armor = 1;
Consumable = 5;
Resource =10;
}
--equipping item to hotbar
function InventoryServer.EquipToHotbar(player, equipTo, stackId)
--getting inventory
local inv = InventoryServer.AllInventories[player]
--removing if exists already
InventoryServer.UnequipFromHotbar(player, stackId)
--Validating Stack
local isValid = false
for i, stackData in pairs(inv.Inventory) do
if stackData.StackId == stackId then
isValid = true
end
end
if not isValid then return end
--equipping
inv.Hotbar[equipTo] = stackId
--updating client
Signal.FireClient(player, "Inventory:ItemsUpdated", InventoryServer.GetInventoryJSON(player))
end
--unequipping item from hotbar
function InventoryServer.UnequipFromHotbar(player, stackId)
--getting inventory
local inv = InventoryServer.AllInventories[player]
--removing if exists already
local found = false
for slotNum, equippedId in pairs(inv.Hotbar) do
if equippedId == stackId then
inv.Hotbar[slotNum] = nil
found = true
end
end
--updating client
if found then
Signal.FireClient(player, "Inventory:ItemsUpdated", InventoryServer.GetInventoryJSON(player))
end
end
--adding items
function InventoryServer.RegisterItem(player, tool)
if tool.ClassName ~= "Tool" then return end
--getting inventory
local inv = InventoryServer.AllInventories[player] --shortcut
--looping all stacks
local foundStack = nil --TODO: autoequip to hotbar if slots are empty
for i, stackData in pairs(inv.Inventory) do
--checking stack data
if table.find(stackData.Items, tool) then
return --the tool is already registered in inventory
elseif stackData.Name == tool.Name and #stackData.Items < InventoryServer.MaxStackData[stackData.ItemType] then
table.insert(stackData.Items, tool) -- adding to existing stack
foundStack = stackData
break
end
end
--checking if stack found
if not foundStack then
if #inv.Inventory < InventoryServer.MaxStacks then
--creating new stack
local stack = {
Name = tool.Name;
Description = tool.ToolTip;
Image = tool.TextureId;
ItemType = tool:GetAttribute("ItemType");
IsDroppable = tool:GetAttribute("IsDroppable");
Items = {tool};
StackId = inv.LastStackId;
}
inv.LastStackId += 1
table.insert(inv.Inventory, stack)
--equipping to first open slot
for slotNum = 1, 9 do
if inv.Hotbar[slotNum] == nil then
InventoryServer.EquipToHotbar(player, slotNum, stack.StackId)
break
end
end
else
error("The user has more than the max stacks of 20 items! Our code doesnt handle that yet!")
end
end
--updating client
Signal.FireClient(player, "Inventory:ItemsUpdated", InventoryServer.GetInventoryJSON(player))
end
--removing items
function InventoryServer.UnregisterItem(player, tool)
if tool.ClassName ~= "Tool" then return end
--getting inventory
local inv = InventoryServer.AllInventories[player]
--finding tool
for i, stackData in pairs(inv.Inventory) do
local found = table.find(stackData.Items, tool)
if found then
--removing tool
table.remove(stackData.Items, found)
--removing stack
if #stackData.Items == 0 then
table.remove(inv.Inventory, table.find(inv.Inventory, stackData))
InventoryServer.UnequipFromHotbar(player, stackData.StackId)
end
end
end
--updating client
Signal.FireClient(player, "Inventory:ItemsUpdated", InventoryServer.GetInventoryJSON(player))
end
--player added
function InventoryServer.PlayerAdded(player)
--waiting for starterpack
for i, tool in pairs(StarterPack:GetChildren()) do
while not player.Backpack:FindFirstChild(tool.Name) do
task.wait()
end
end
--creating Inventory
InventoryServer.AllInventories[player] = {
Inventory = {};
Hotbar = {};
Armor = {
Head = nil;
Chest = nil;
Feet = nil;
};
LastStackId = 0;
}
--registering items
for i, tool in pairs(player.Backpack:GetChildren()) do
InventoryServer.RegisterItem(player, tool)
end
--connecting events
player.Backpack.ChildAdded:Connect(function(child)
InventoryServer.RegisterItem(player, child)
end)
player.Backpack.ChildRemoved:Connect(function(child)
InventoryServer.UnregisterItem(player, child)
end)
--character added
local function charAdded(char)
--connecting Events
char.ChildAdded:Connect(function(child)
InventoryServer.RegisterItem(player, child)
end)
char.ChildRemoved:Connect(function(child)
InventoryServer.UnregisterItem(player, child)
end)
end
if player.Character then
task.spawn(charAdded, player.Character)
end
player.CharacterAdded:Connect(charAdded)
end
--getting inventory data
function InventoryServer.GetInventoryJSON(player)
--waiting for inventory
while not InventoryServer.AllInventories[player] do task.wait() end
local inv = InventoryServer.AllInventories[player]
--altering inventory
local adjustInv = {
Inventory = {};
Hotbar = inv.Hotbar;
Armor = inv.Armor;
LastStackId = inv.LastStackId;
}
for i, stackData in pairs(inv.Inventory) do
table.insert(adjustInv.Inventory, {
Name = stackData.Name;
Description = stackData.Description;
Image = stackData.Image;
ItemType = stackData.ItemType;
IsDroppable = stackData.IsDroppable;
Count = #stackData.Items; -- replacing tool list with count
StackId = stackData.StackId;
})
end
return HS:JSONEncode(adjustInv)
end
--initializing
function InventoryServer.Start()
--player added
for i, player in pairs(Players:GetPlayers()) do
task.spawn(InventoryServer.PlayerAdded, player)
end
Players.PlayerAdded:Connect(InventoryServer.PlayerAdded)
--getting Inventory From Client
Signal.ListenRemote("Inventory:GetInventoryJSON", InventoryServer.GetInventoryJSON)
Signal.ListenRemote("Inventory:EquipToHotbar", InventoryServer.EquipToHotbar)
Signal.ListenRemote("Inventory:UnequipFromHotbar", InventoryServer.UnequipFromHotbar)
end
--returning
return InventoryServer
do i have to make a local itemF at the beginning of the script and if yes what am i supposed to make it? i cannot find it in the video and studio is screaming at me for not having it defined at this part of the code:
--select item
function InventoryClient.SelectItem(stackData, item)
--setting selected
InventoryClient.SelectedStackId = stackData and stackData.StackId or nil
--setting frame colors
for i, otheritemF in pairs(itemsSF:GetChildren()) do
if otheritemF.ClassName == "ImageButton" and otheritemF ~= itemSample then
if otheritemF == itemF then
otheritemF.BackgroundColor3 = otheritemF:GetAttribute("SelectedColor")
else
otheritemF.BackgroundColor3 = otheritemF:GetAttribute("NormalColor")
end
end
end
specifically the part about if otheritemF == itemF
nvm i found it my dumbah got the function inventoryClient.SelectItem(stackData, itemF) wrong cuz i forgot the F on itemF
12:00 i give up this