aboutsummaryrefslogtreecommitdiff
path: root/gamemode/shared/inventory_common.lua
diff options
context:
space:
mode:
Diffstat (limited to 'gamemode/shared/inventory_common.lua')
-rw-r--r--gamemode/shared/inventory_common.lua205
1 files changed, 205 insertions, 0 deletions
diff --git a/gamemode/shared/inventory_common.lua b/gamemode/shared/inventory_common.lua
new file mode 100644
index 0000000..e86d0a6
--- /dev/null
+++ b/gamemode/shared/inventory_common.lua
@@ -0,0 +1,205 @@
+--[[
+ Some functions that are needed multiple places in the code, to deal with player inventories.
+]]
+local invfuncs = {}
+
+--Forcibly put an item in a backpack, you should check to make sure there's room first
+invfuncs.PutItemInBackpack = function(backpack,x,y,item)
+ backpack[1][x][y] = item
+ for k = 1,#item.Shape do
+ for i = 1,#(item.Shape[k]) do
+ if k == 1 and i == 1 then continue end
+ backpack[1][x + k - 1][y + i - 1] = item.Shape[k][i]
+ end
+ end
+end
+
+--Writes a backpack to the net stream
+invfuncs.SerializeBackpack = function(backpack)
+ net.WriteString(backpack[3]) --Name
+ net.WriteUInt(backpack[2][1],16) --width
+ net.WriteUInt(backpack[2][2],16) --height
+ for k,v in pairs(backpack[1]) do
+ for i,j in pairs(v) do
+ if type(j) ~= "table" then continue end
+ net.WriteString(j.Name)
+ net.WriteUInt(k,16)
+ net.WriteUInt(i,16)
+ local data = j:Serialize()
+ net.WriteUInt(#data,32)
+ net.WriteData(data,#data)
+ end
+ end
+ net.WriteString("END_ITEMS")
+end
+
+--Loads a backpack from the net stream
+invfuncs.DeSerializeBackpack = function()
+ local backpackname = net.ReadString()
+ local width = net.ReadUInt(16)
+ local height = net.ReadUInt(16)
+ --Build the backpack
+ local tb = {}
+ tb[1] = {}
+ tb[2] = {width,height}
+ tb[3] = backpackname
+ for x = 1,width do
+ tb[1][x] = {}
+ for y = 1,height do
+ tb[1][x][y] = false
+ end
+ end
+
+ local nitemname = net.ReadString()
+ while nitemname ~= "END_ITEMS" do
+ local xpos = net.ReadUInt(16)
+ local ypos = net.ReadUInt(16)
+ local data = net.ReadData(net.ReadUInt(32))
+ local nitem = ART.GetItemByName(nitemname):DeSerialize(data)
+ invfuncs.PutItemInBackpack(tb,xpos,ypos,nitem)
+ nitemname = net.ReadString()
+ end
+
+ return tb
+
+end
+
+--Checks to see if an item can fit in the backpack at a certain position
+invfuncs.CanFitInBackpack = function(backpack,x,y,item)
+ for k,v in pairs(item.Shape) do
+ for i,j in pairs(v) do
+ if not j then continue end
+ if backpack[1][x + k - 1] == nil then
+ return false
+ end
+ if backpack[1][x + k - 1][y + i - 1] or backpack[1][x + k - 1][y + i - 1] == nil then
+ return false
+ end
+ end
+ end
+ return true
+end
+
+--Creates a new backpack, this is NOT called when players join the server, even new ones.
+invfuncs.CreateBackpack = function(name,width,height)
+ local backpack = {}
+ backpack[1] = {}
+ backpack[2] = {width,height}
+ backpack[3] = name
+ for i = 1,width do --the width of the backpack.
+ backpack[1][i] = {}
+ end
+ for k,v in pairs(backpack[1]) do
+ for i = 1,height do --the height of the backpack.
+ backpack[1][k][i] = false
+ end
+ end
+ return backpack
+end
+
+--Displays a dropdown of options under the players mouse, if the option is clicked, does the function
+--Requires a table of strings to functions, or strings to tables of strings to functions.
+--Be careful not to make this a recursive table.
+local function createMenuFor(menu, tbl)
+ for k,v in pairs(tbl) do
+ if(isfunction(v)) then --This is a dead-end, add the menu
+ local thisoption = menu:AddOption(k,v)
+ else --Otherwise it should be a table, recursively call to create
+ local submenu = menu:AddSubMenu(k)
+ createMenuFor(submenu,v)
+ end
+ end
+end
+
+--Draws a backpack on the dpanel, client side only
+invfuncs.DrawBackpackOnDPanel = function(dp, backpack, backpacknum, tent)
+ local width = ScrW()
+ local height = ScrH()
+ local slotsize = math.Round(width / 32)
+ local backgrid = vgui.Create( "DGrid", dp )
+ backgrid:SetPos( 10, 30 )
+ backgrid:SetCols( backpack[2][1] )
+ backgrid:SetColWide( backpack[2][2] )
+ backgrid:Dock(FILL)
+ for i = 1,#(backpack[1]) do
+ for j = 1,#(backpack[1][i]) do
+ local item = backpack[1][j][i]
+ if type(backpack[1][j][i]) == "table" then
+ local itemwidth = 0
+ for _,l in pairs(item.Shape) do
+ itemwidth = math.Max(itemwidth,#l)
+ end
+ local itemheight = #item.Shape
+ local invicon = vgui.Create( "DButton", dp )
+ invicon:SetSize(slotsize * itemwidth, slotsize * itemheight)
+ invicon:SetPos(slotsize * (i - 1), slotsize * (j - 1))
+ invicon:SetText(item.Name)
+ if item.Tooltip then
+ invicon:SetTooltip(item.Tooltip)
+ end
+ --invicon.Paint = function(self, w, h) draw.RoundedBox(4, 0,0,w,h,Color(0,100,0)) end
+ invicon.DoClick = function()
+ if not item.GetOptions then return end
+ local menu = vgui.Create("DMenu")
+ createMenuFor(menu,item:GetOptions())
+ menu:Open()
+ end
+ invicon.Item = item
+ invicon.invpos = {j,i}
+ invicon.ent = tent
+ invicon.backpacknum = backpacknum
+ invicon:Droppable("Inventory")
+ elseif not backpack[1][j][i] then
+ local emptyslot = vgui.Create("DPanel", dp)
+ emptyslot:SetSize(slotsize,slotsize)
+ emptyslot:SetPos(slotsize * (i - 1), slotsize * (j - 1))
+ --emptyslot.Paint = function(self, w, h) draw.RoundedBox(4, 0,0,w,h,Color(0,0,100)) end
+ emptyslot:Receiver( "Inventory", function( receiver, tableOfDroppedPanels, isDropped, menuIndex, mouseX, mouseY )
+ if not isDropped then return end
+ local icon = tableOfDroppedPanels[1]
+ local item = icon.Item
+ local curpos = icon.invpos
+ --Set the shape it was at to false
+ if not icon.wasequiped and icon.ent == tent then
+ assert(curpos ~= nil, "print curpos was nil when not equiped")
+ for k = 1,#item.Shape do
+ for l = 1,#(item.Shape[k]) do
+ if k == 1 and l == 1 then continue end
+ backpack[1][curpos[1] + k - 1][curpos[2] + l - 1] = false
+ end
+ end
+ backpack[1][curpos[1]][curpos[2]] = false
+ end
+ if invfuncs.CanFitInBackpack(backpack,j,i,item) then
+ local fromtbl = icon.invpos
+ local wasequiped = icon.wasequiped
+ if wasequiped then
+ net.Start("unequipitem")
+ net.WriteString(wasequiped)
+ net.WriteUInt(backpacknum,16)
+ net.WriteUInt(i,16)
+ net.WriteUInt(j,16)
+ net.SendToServer()
+ else
+ net.Start("moveitem")
+ net.WriteEntity(icon.ent) -- from ent
+ net.WriteEntity(tent) -- to ent
+ net.WriteUInt(icon.backpacknum,16) -- from backpack number
+ net.WriteUInt(backpacknum,16) -- to backpack number
+ net.WriteUInt(fromtbl[1],16) -- From position
+ net.WriteUInt(fromtbl[2],16)
+ net.WriteUInt(j,16) -- To position
+ net.WriteUInt(i,16)
+ net.SendToServer()
+ if item.onEquip ~= nil then
+ item:onEquip(LocalPlayer())
+ end
+ end
+ end
+ end, {} )
+ end
+ end
+ end
+end
+
+return invfuncs