Add nil checks for placer
[oweals/minetest_game.git] / mods / bucket / init.lua
1 -- Minetest 0.4 mod: bucket
2 -- See README.txt for licensing and other information.
3
4 minetest.register_alias("bucket", "bucket:bucket_empty")
5 minetest.register_alias("bucket_water", "bucket:bucket_water")
6 minetest.register_alias("bucket_lava", "bucket:bucket_lava")
7
8 minetest.register_craft({
9         output = 'bucket:bucket_empty 1',
10         recipe = {
11                 {'default:steel_ingot', '', 'default:steel_ingot'},
12                 {'', 'default:steel_ingot', ''},
13         }
14 })
15
16 bucket = {}
17 bucket.liquids = {}
18
19 local function check_protection(pos, name, text)
20         if minetest.is_protected(pos, name) then
21                 minetest.log("action", (name ~= "" and name or "A mod")
22                         .. " tried to " .. text
23                         .. " at protected position "
24                         .. minetest.pos_to_string(pos)
25                         .. " with a bucket")
26                 minetest.record_protection_violation(pos, name)
27                 return true
28         end
29         return false
30 end
31
32 -- Register a new liquid
33 --    source = name of the source node
34 --    flowing = name of the flowing node
35 --    itemname = name of the new bucket item (or nil if liquid is not takeable)
36 --    inventory_image = texture of the new bucket item (ignored if itemname == nil)
37 --    name = text description of the bucket item
38 --    groups = (optional) groups of the bucket item, for example {water_bucket = 1}
39 --    force_renew = (optional) bool. Force the liquid source to renew if it has a
40 --                  source neighbour, even if defined as 'liquid_renewable = false'.
41 --                  Needed to avoid creating holes in sloping rivers.
42 -- This function can be called from any mod (that depends on bucket).
43 function bucket.register_liquid(source, flowing, itemname, inventory_image, name,
44                 groups, force_renew)
45         bucket.liquids[source] = {
46                 source = source,
47                 flowing = flowing,
48                 itemname = itemname,
49                 force_renew = force_renew,
50         }
51         bucket.liquids[flowing] = bucket.liquids[source]
52
53         if itemname ~= nil then
54                 minetest.register_craftitem(itemname, {
55                         description = name,
56                         inventory_image = inventory_image,
57                         stack_max = 1,
58                         liquids_pointable = true,
59                         groups = groups,
60
61                         on_place = function(itemstack, user, pointed_thing)
62                                 -- Must be pointing to node
63                                 if pointed_thing.type ~= "node" then
64                                         return
65                                 end
66
67                                 local node = minetest.get_node_or_nil(pointed_thing.under)
68                                 local ndef = node and minetest.registered_nodes[node.name]
69
70                                 -- Call on_rightclick if the pointed node defines it
71                                 if ndef and ndef.on_rightclick and
72                                                 not (user and user:is_player() and
73                                                 user:get_player_control().sneak) then
74                                         return ndef.on_rightclick(
75                                                 pointed_thing.under,
76                                                 node, user,
77                                                 itemstack)
78                                 end
79
80                                 local lpos
81
82                                 -- Check if pointing to a buildable node
83                                 if ndef and ndef.buildable_to then
84                                         -- buildable; replace the node
85                                         lpos = pointed_thing.under
86                                 else
87                                         -- not buildable to; place the liquid above
88                                         -- check if the node above can be replaced
89
90                                         lpos = pointed_thing.above
91                                         node = minetest.get_node_or_nil(lpos)
92                                         local above_ndef = node and minetest.registered_nodes[node.name]
93
94                                         if not above_ndef or not above_ndef.buildable_to then
95                                                 -- do not remove the bucket with the liquid
96                                                 return itemstack
97                                         end
98                                 end
99
100                                 if check_protection(lpos, user
101                                                 and user:get_player_name()
102                                                 or "", "place "..source) then
103                                         return
104                                 end
105
106                                 minetest.set_node(lpos, {name = source})
107                                 return ItemStack("bucket:bucket_empty")
108                         end
109                 })
110         end
111 end
112
113 minetest.register_craftitem("bucket:bucket_empty", {
114         description = "Empty Bucket",
115         inventory_image = "bucket.png",
116         stack_max = 99,
117         liquids_pointable = true,
118         on_use = function(itemstack, user, pointed_thing)
119                 if pointed_thing.type == "object" then
120                         pointed_thing.ref:punch(user, 1.0, { full_punch_interval=1.0 }, nil)
121                         return user:get_wielded_item()
122                 elseif pointed_thing.type ~= "node" then
123                         -- do nothing if it's neither object nor node
124                         return
125                 end
126                 -- Check if pointing to a liquid source
127                 local node = minetest.get_node(pointed_thing.under)
128                 local liquiddef = bucket.liquids[node.name]
129                 local item_count = user:get_wielded_item():get_count()
130
131                 if liquiddef ~= nil
132                 and liquiddef.itemname ~= nil
133                 and node.name == liquiddef.source then
134                         if check_protection(pointed_thing.under,
135                                         user:get_player_name(),
136                                         "take ".. node.name) then
137                                 return
138                         end
139
140                         -- default set to return filled bucket
141                         local giving_back = liquiddef.itemname
142
143                         -- check if holding more than 1 empty bucket
144                         if item_count > 1 then
145
146                                 -- if space in inventory add filled bucked, otherwise drop as item
147                                 local inv = user:get_inventory()
148                                 if inv:room_for_item("main", {name=liquiddef.itemname}) then
149                                         inv:add_item("main", liquiddef.itemname)
150                                 else
151                                         local pos = user:getpos()
152                                         pos.y = math.floor(pos.y + 0.5)
153                                         minetest.add_item(pos, liquiddef.itemname)
154                                 end
155
156                                 -- set to return empty buckets minus 1
157                                 giving_back = "bucket:bucket_empty "..tostring(item_count-1)
158
159                         end
160
161                         -- force_renew requires a source neighbour
162                         local source_neighbor = false
163                         if liquiddef.force_renew then
164                                 source_neighbor =
165                                         minetest.find_node_near(pointed_thing.under, 1, liquiddef.source)
166                         end
167                         if not (source_neighbor and liquiddef.force_renew) then
168                                 minetest.add_node(pointed_thing.under, {name = "air"})
169                         end
170
171                         return ItemStack(giving_back)
172                 else
173                         -- non-liquid nodes will have their on_punch triggered
174                         local node_def = minetest.registered_nodes[node.name]
175                         if node_def then
176                                 node_def.on_punch(pointed_thing.under, node, user, pointed_thing)
177                         end
178                         return user:get_wielded_item()
179                 end
180         end,
181 })
182
183 bucket.register_liquid(
184         "default:water_source",
185         "default:water_flowing",
186         "bucket:bucket_water",
187         "bucket_water.png",
188         "Water Bucket",
189         {water_bucket = 1}
190 )
191
192 bucket.register_liquid(
193         "default:river_water_source",
194         "default:river_water_flowing",
195         "bucket:bucket_river_water",
196         "bucket_river_water.png",
197         "River Water Bucket",
198         {water_bucket = 1},
199         true
200 )
201
202 bucket.register_liquid(
203         "default:lava_source",
204         "default:lava_flowing",
205         "bucket:bucket_lava",
206         "bucket_lava.png",
207         "Lava Bucket"
208 )
209
210 minetest.register_craft({
211         type = "fuel",
212         recipe = "bucket:bucket_lava",
213         burntime = 60,
214         replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}},
215 })
216