--[[ An inventory, with a shape! Items are stored in a 1-d array, array is 1-indexed ]] local reg = nrequire("inventory/inventory.lua") local itm = nrequire("item.lua") local inv = {} if CLIENT then inv = nrequire("cl_shaped.lua") end inv.Name = "Shaped Inventory" inv.tracker = {} inv.width = 5 inv.height = 5 local function calcposition(width,height,row,col) return ((row-1) * width) + col end local function canfitin(self,arow,acol,shape) for rn,row in ipairs(shape) do for cn,col in ipairs(row) do local absrow,abscol = arow + rn - 1, acol + cn - 1 local slot = calcposition(self.width,self.height,absrow,abscol) if col and ((self.tracker[slot] ~= nil) or (absrow > self.width) or (abscol > self.height)) then return false end end end return true end function inv:FindPlaceFor(item) if item.Shape == nil then return nil end for row = 1, self.height do for col = 1, self.width do if canfitin(self,row,col,item.Shape) then return {row,col} end end end return nil end function inv:CanFitIn(tbl,item) if item.Shape == nil then return false end if canfitin(self,tbl[1],tbl[2],item.Shape) then return true else return "Could not fit :(" end end function inv:Put(tbl,item) --Set the item's shape to true for rn,row in ipairs(item.Shape) do for cn,col in ipairs(row) do if col then local slot = calcposition(self.width,self.height,tbl[1] + rn - 1,tbl[2] + cn - 1) self.tracker[slot] = 1 end end end --Now set the item in the correct slot local slot = calcposition(self.width,self.height,tbl[1],tbl[2]) self.tracker[slot] = item end function inv:Has(ptr) local compare_func = ptr if type(ptr) == "string" then compare_func = function(t) return t.Name == ptr end end for k,v in pairs(self.tracker) do if type(v) == "table" and compare_func(v) then local row = math.ceil(k / self.width) local col = ((k - 1) % self.width) + 1 return {row,col} end end return nil end function inv:Remove(tbl) local slot = calcposition(self.width,self.height,tbl[1],tbl[2]) local item = self.tracker[slot] self.tracker[slot] = nil for rn,row in ipairs(item.Shape) do for cn,col in ipairs(row) do if col then slot = calcposition(self.width,self.height,tbl[1] + rn - 1,tbl[2] + cn - 1) self.tracker[slot] = nil end end end return item end function inv:Get(tbl) local slot = calcposition(self.width,self.height,tbl[1],tbl[2]) return self.tracker[slot] end function inv:Serialize() --Turn it into a sparse table local ret = {} for k,v in pairs(self.tracker) do if type(v) == "table" then local row = math.ceil(k / self.width) local col = k % self.width ret[v.Name] = {{row,col},v:Serialize()} end end return util.TableToJSON(ret) end function inv:DeSerialize(str) self.tracker = {} local tbl = util.JSONToTable(str) tbl = tbl or {} for k,v in pairs(tbl) do local name = k local pos = v[1] local data = v[2] local item = itm.GetItemFromData(name,data) self:Put(pos,item) --ret.tracker[pos] = itm.GetItemFromData(name,data) end return self end reg.RegisterInventory(inv)