diff options
Diffstat (limited to 'gamemode/shared/inventory_common.lua')
| -rw-r--r-- | gamemode/shared/inventory_common.lua | 205 |
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 |
