aboutsummaryrefslogtreecommitdiff
path: root/gamemode/core/inventory/item.lua
blob: 16b30dd8737416b3244b1f5eb5da4f093527f9f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
---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