summaryrefslogtreecommitdiff
path: root/homedecor/handlers/inventory.lua
blob: dd0913397d2d28a4ef8fe289b0e62b7960881940 (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189

local S = homedecor_i18n.gettext

local default_can_dig = function(pos,player)
	local meta = minetest.get_meta(pos)
	return meta:get_inventory():is_empty("main")
end

local background = default.gui_bg .. default.gui_bg_img .. default.gui_slots
local default_inventory_formspecs = {
	["4"]="size[8,6]".. background ..
	"list[context;main;2,0;4,1;]" ..
	"list[current_player;main;0,2;8,4;]" ..
	"listring[]",

	["6"]="size[8,6]".. background ..
	"list[context;main;1,0;6,1;]"..
	"list[current_player;main;0,2;8,4;]" ..
	"listring[]",

	["8"]="size[8,6]".. background ..
	"list[context;main;0,0;8,1;]"..
	"list[current_player;main;0,2;8,4;]" ..
	"listring[]",

	["12"]="size[8,7]".. background ..
	"list[context;main;1,0;6,2;]"..
	"list[current_player;main;0,3;8,4;]" ..
	"listring[]",

	["16"]="size[8,7]".. background ..
	"list[context;main;0,0;8,2;]"..
	"list[current_player;main;0,3;8,4;]" ..
	"listring[]",

	["24"]="size[8,8]".. background ..
	"list[context;main;0,0;8,3;]"..
	"list[current_player;main;0,4;8,4;]" ..
	"listring[]",

	["32"]="size[8,9]".. background ..
	"list[context;main;0,0.3;8,4;]"..
	"list[current_player;main;0,4.85;8,1;]"..
	"list[current_player;main;0,6.08;8,3;8]"..
	"listring[context;main]" ..
	"listring[current_player;main]" ..
	default.get_hotbar_bg(0,4.85),

	["50"]="size[10,10]".. background ..
	"list[context;main;0,0;10,5;]"..
	"list[current_player;main;1,6;8,4;]" ..
	"listring[]",
}

local function get_formspec_by_size(size)
	--TODO heuristic to use the "next best size"
	local formspec = default_inventory_formspecs[tostring(size)]
	return formspec or default_inventory_formspecs
end

----
-- handle inventory setting
-- inventory = {
--	size = 16,
--	formspec = …,
--	locked = false,
--	lockable = true,
-- }
--
function homedecor.handle_inventory(name, def, original_def)
	local inventory = def.inventory
	if not inventory then return end
	def.inventory = nil

	if inventory.size then
		local on_construct = def.on_construct
		def.on_construct = function(pos)
			local size = inventory.size
			local meta = minetest.get_meta(pos)
			meta:get_inventory():set_size("main", size)
			meta:set_string("formspec", inventory.formspec or get_formspec_by_size(size))
			if on_construct then on_construct(pos) end
		end
	end

	def.can_dig = def.can_dig or default_can_dig
	def.on_metadata_inventory_move = def.on_metadata_inventory_move or function(pos, from_list, from_index, to_list, to_index, count, player)
		minetest.log("action", S("@1 moves stuff in @2 at @3",
			player:get_player_name(), name, minetest.pos_to_string(pos)
		))
	end
	def.on_metadata_inventory_put = def.on_metadata_inventory_put or function(pos, listname, index, stack, player)
		minetest.log("action", S("@1 moves @2 to @3 at @4",
			player:get_player_name(), stack:get_name(), name, minetest.pos_to_string(pos)
		))
	end
	def.on_metadata_inventory_take = def.on_metadata_inventory_take or function(pos, listname, index, stack, player)
		minetest.log("action", S("@1 takes @2 from @3 at @4",
			player:get_player_name(), stack:get_name(), name, minetest.pos_to_string(pos)
		))
	end

	local locked = inventory.locked
	if locked then
		local after_place_node = def.after_place_node
		def.after_place_node = function(pos, placer)
			local meta = minetest.get_meta(pos)
			local owner = placer:get_player_name() or ""

			meta:set_string("owner", owner)
			meta:set_string("infotext", S("@1 (owned by @2)", def.infotext or def.description, owner))
			return after_place_node and after_place_node(pos, placer)
		end

		local allow_move = def.allow_metadata_inventory_move
		def.allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
			local meta = minetest.get_meta(pos)
			local owner = meta:get_string("owner")
			local playername = player:get_player_name()

			if playername == owner or
					minetest.check_player_privs(playername, "protection_bypass") then
				return allow_move and
						allow_move(pos, from_list, from_index, to_list, to_index, count, player) or
						count
			end

			minetest.log("action", S("@1 tried to access a @2 belonging to @3 at @4",
				playername, name, owner, minetest.pos_to_string(pos)
			))
			return 0
		end

		local allow_put = def.allow_metadata_inventory_put
		def.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
			local meta = minetest.get_meta(pos)
			local owner = meta:get_string("owner")
			local playername = player:get_player_name()

			if playername == owner or
					minetest.check_player_privs(playername, "protection_bypass") then
				return allow_put and allow_put(pos, listname, index, stack, player) or
						stack:get_count()
			end

			minetest.log("action", S("@1 tried to access a @2 belonging to @3 at @4",
				playername, name, owner, minetest.pos_to_string(pos)
			))
			return 0
		end

		local allow_take = def.allow_metadata_inventory_take
		def.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
			local meta = minetest.get_meta(pos)
			local owner = meta:get_string("owner")
			local playername = player:get_player_name()

			if playername == owner or
					minetest.check_player_privs(playername, "protection_bypass") then
				return allow_take and allow_take(pos, listname, index, stack, player) or
						stack:get_count()
			end

			minetest.log("action", S("@1 tried to access a @2 belonging to @3 at @4",
				playername, name, owner, minetest.pos_to_string(pos)
			))
			return 0
		end
	end

	local lockable = inventory.lockable
	if lockable then
		local locked_def = table.copy(original_def)
		locked_def.description = S("@1 (Locked)", def.description or name)

		local locked_inventory = locked_def.inventory
		locked_inventory.locked = true
		locked_inventory.lockable = nil -- avoid loops of locked locked stuff

		local locked_name = name .. "_locked"
		homedecor.register(locked_name, locked_def)
		minetest.register_craft({
			type = "shapeless",
			output = "homedecor:" .. locked_name,
			recipe = { "homedecor:" .. name, "basic_materials:padlock" }
		})
	end

end