Always return the leftover ItemStack for on_place and on_rightclick
[oweals/minetest_game.git] / mods / beds / api.lua
1
2 local reverse = true
3
4 local function destruct_bed(pos, n)
5         local node = minetest.get_node(pos)
6         local other
7
8         if n == 2 then
9                 local dir = minetest.facedir_to_dir(node.param2)
10                 other = vector.subtract(pos, dir)
11         elseif n == 1 then
12                 local dir = minetest.facedir_to_dir(node.param2)
13                 other = vector.add(pos, dir)
14         end
15
16         if reverse then
17                 reverse = not reverse
18                 minetest.remove_node(other)
19                 nodeupdate(other)
20         else
21                 reverse = not reverse
22         end
23 end
24
25 function beds.register_bed(name, def)
26         minetest.register_node(name .. "_bottom", {
27                 description = def.description,
28                 inventory_image = def.inventory_image,
29                 wield_image = def.wield_image,
30                 drawtype = "nodebox",
31                 tiles = def.tiles.bottom,
32                 paramtype = "light",
33                 paramtype2 = "facedir",
34                 is_ground_content = false,
35                 stack_max = 1,
36                 groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 1},
37                 sounds = default.node_sound_wood_defaults(),
38                 node_box = {
39                         type = "fixed",
40                         fixed = def.nodebox.bottom,
41                 },
42                 selection_box = {
43                         type = "fixed",
44                         fixed = def.selectionbox,
45                 },
46
47                 on_place = function(itemstack, placer, pointed_thing)
48                         local under = pointed_thing.under
49                         local pos
50                         if minetest.registered_items[minetest.get_node(under).name].buildable_to then
51                                 pos = under
52                         else
53                                 pos = pointed_thing.above
54                         end
55
56                         if minetest.is_protected(pos, placer:get_player_name()) and
57                                         not minetest.check_player_privs(placer, "protection_bypass") then
58                                 minetest.record_protection_violation(pos, placer:get_player_name())
59                                 return itemstack
60                         end
61
62                         local def = minetest.registered_nodes[minetest.get_node(pos).name]
63                         if not def or not def.buildable_to then
64                                 return itemstack
65                         end
66
67                         local dir = minetest.dir_to_facedir(placer:get_look_dir())
68                         local botpos = vector.add(pos, minetest.facedir_to_dir(dir))
69
70                         if minetest.is_protected(botpos, placer:get_player_name()) and
71                                         not minetest.check_player_privs(placer, "protection_bypass") then
72                                 minetest.record_protection_violation(botpos, placer:get_player_name())
73                                 return itemstack
74                         end
75
76                         local botdef = minetest.registered_nodes[minetest.get_node(botpos).name]
77                         if not botdef or not botdef.buildable_to then
78                                 return itemstack
79                         end
80
81                         minetest.set_node(pos, {name = name .. "_bottom", param2 = dir})
82                         minetest.set_node(botpos, {name = name .. "_top", param2 = dir})
83
84                         if not minetest.setting_getbool("creative_mode") then
85                                 itemstack:take_item()
86                         end
87                         return itemstack
88                 end,
89
90                 on_destruct = function(pos)
91                         destruct_bed(pos, 1)
92                 end,
93
94                 on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
95                         beds.on_rightclick(pos, clicker)
96                         return itemstack
97                 end,
98
99                 on_rotate = function(pos, node, user, mode, new_param2)
100                         local dir = minetest.facedir_to_dir(node.param2)
101                         local p = vector.add(pos, dir)
102                         local node2 = minetest.get_node_or_nil(p)
103                         if not node2 or not minetest.get_item_group(node2.name, "bed") == 2 or
104                                         not node.param2 == node2.param2 then
105                                 return false
106                         end
107                         if minetest.is_protected(p, user:get_player_name()) then
108                                 minetest.record_protection_violation(p, user:get_player_name())
109                                 return false
110                         end
111                         if mode ~= screwdriver.ROTATE_FACE then
112                                 return false
113                         end
114                         local newp = vector.add(pos, minetest.facedir_to_dir(new_param2))
115                         local node3 = minetest.get_node_or_nil(newp)
116                         local def = node3 and minetest.registered_nodes[node3.name]
117                         if not def or not def.buildable_to then
118                                 return false
119                         end
120                         if minetest.is_protected(newp, user:get_player_name()) then
121                                 minetest.record_protection_violation(newp, user:get_player_name())
122                                 return false
123                         end
124                         node.param2 = new_param2
125                         -- do not remove_node here - it will trigger destroy_bed()
126                         minetest.set_node(p, {name = "air"})
127                         minetest.set_node(pos, node)
128                         minetest.set_node(newp, {name = name .. "_top", param2 = new_param2})
129                         return true
130                 end,
131         })
132
133         minetest.register_node(name .. "_top", {
134                 drawtype = "nodebox",
135                 tiles = def.tiles.top,
136                 paramtype = "light",
137                 paramtype2 = "facedir",
138                 is_ground_content = false,
139                 pointable = false,
140                 groups = {snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 3, bed = 2},
141                 sounds = default.node_sound_wood_defaults(),
142                 drop = name .. "_bottom",
143                 node_box = {
144                         type = "fixed",
145                         fixed = def.nodebox.top,
146                 },
147                 on_destruct = function(pos)
148                         destruct_bed(pos, 2)
149                 end,
150         })
151
152         minetest.register_alias(name, name .. "_bottom")
153
154         minetest.register_craft({
155                 output = name,
156                 recipe = def.recipe
157         })
158 end