---The main module to use when createing new items. -- Registers items that will work with the inventory system --@shared item.lua --@alias itm --[[ An itemsystem public functions: RegisterItem(table_item) ::nil Registers a new item GetItemByName(string_name) ::table_item Returns the master copy of an item by name DeriveItem(table_item,string_name) ::nil Sets the table to a copy of an item. Copying happens in order, so if two items we derive from have a "DoThing" method, and "DoThing" is not defined in the item, the second derived item's "DoThing" method gets called on .DoThing() Item: item.Name ::string Items must have unique names item:Serialize() ::string Turn any instace specific data of this item into a string, should be able to recreate an exact copy of this item in DeSerialize with this data item:DeSerialize(string_data) ::nil Recreate an item. If this item has any instance specific data, it should return a table.Copy(self) with the appropriate fields set. The above must be defined for every item ]] local log = nrequire("log.lua") local itm = {} local required_fields = { "Name","Serialize","DeSerialize" } local items = items or {} --Master table of all item prototypes ---Registers an item. -- Registers an item that can be gotten later. It usually dosn't make sense for only parts of the level to have an item (the player probably can travel between all the parts of your world with the item in their inventory), therefore you should make sure items are loaded globally. --@tparam itemtbl tbl The table to register for the item prototype function itm.RegisterItem(tbl) for k,v in pairs(required_fields) do assert(tbl[v] ~= nil, string.format("Attempted to register item without field %q",v)) end --assert(items[tbl.Name] == nil, string.format("Attempted to register 2 items with the same name %q",tbl.Name)) if items[tbl.Name] ~= nil then log.warn(string.format("Attempted to register 2 items with the same name: %q, overwriteing previous",tbl.Name)) else --log.info(string.format("Registered item %s",tbl.Name)) end items[tbl.Name] = tbl --print("Registered item: " .. tbl.Name) end ---Gets an instance of an item. -- Gets an instanced copy of an item registered with RegisterItem() --@tparam string name The name of the item --@treturn itemtbl The item function itm.GetItemByName(name) assert(type(name) == "string",string.format("Attempted to get an item by name with a %s.",type(name))) assert(items[name] ~= nil,string.format("Attempted to get item with invalid name %q Valid item names are:\n\t%s",name,table.concat(table.GetKeys(items),"\n\t"))) local item_m = { __index = items[name] } local item = {} setmetatable(item,item_m) if item.init then item:init() end return item end ---Gets an item, with data. -- Just gets the item, then calls DeSerialize(), returning whatever deserialize returned --@tparam string name The name of the item --@tparam string data The data to instantiate the item with --@treturn itemtbl The item that was deserialized function itm.GetItemFromData(name,data) assert(items[name] ~= nil,string.format("Attempted to get item with invalid name %q",name)) local ret_m = { __index = items[name] } local ret = {} setmetatable(ret,ret_m) ret:DeSerialize(data) return ret end local function printitems() local tbl = {} for k,v in pairs(items) do tbl[#tbl + 1] = k end print(table.concat(tbl,"\n")) end ---To be depriciated. function itm.DeriveItem(tbl,name) print("Attempting to derive item",name) while items[name] == nil do print("it dosen't exist yet, items are") printitems() coroutine.yield() end print(name,"exists!") --Create a flywieght copy local ret = tbl local mt = { __index = function(ntbl,key) return items[name][key] end } setmetatable(ret,mt) end hook.Call("artery_include_items") ---Prints a list of all items the client/server knows about --@concommand artery_printitems --@usage artery_printitems concommand.Add("artery_printitems",printitems) return itm