Bucket: Correct liquid placing in protected areas
[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 -- This function can be called from any mod (that depends on bucket).
40 function bucket.register_liquid(source, flowing, itemname, inventory_image, name, groups)
41         bucket.liquids[source] = {
42                 source = source,
43                 flowing = flowing,
44                 itemname = itemname,
45         }
46         bucket.liquids[flowing] = bucket.liquids[source]
47
48         if itemname ~= nil then
49                 minetest.register_craftitem(itemname, {
50                         description = name,
51                         inventory_image = inventory_image,
52                         stack_max = 1,
53                         liquids_pointable = true,
54                         groups = groups,
55
56                         on_place = function(itemstack, user, pointed_thing)
57                                 -- Must be pointing to node
58                                 if pointed_thing.type ~= "node" then
59                                         return
60                                 end
61
62                                 local node = minetest.get_node_or_nil(pointed_thing.under)
63                                 if not node then
64                                         return
65                                 end
66                                 local ndef = minetest.registered_nodes[node.name]
67                                 if not ndef then
68                                         return
69                                 end
70
71                                 -- Call on_rightclick if the pointed node defines it
72                                 if ndef.on_rightclick and
73                                    user and not 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.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                                         lpos = pointed_thing.above
90                                         local node = minetest.get_node_or_nil(lpos)
91                                         if not node
92                                         or not minetest.registered_nodes[node.name].buildable_to then
93                                                 -- do not remove the bucket with the liquid
94                                                 return
95                                         end
96                                 end
97
98                                 if check_protection(lpos, user
99                                                 and user:get_player_name()
100                                                 or "", "place "..source) then
101                                         return
102                                 end
103
104                                 minetest.set_node(lpos, {name = source})
105                                 return ItemStack("bucket:bucket_empty")
106                         end
107                 })
108         end
109 end
110
111 minetest.register_craftitem("bucket:bucket_empty", {
112         description = "Empty Bucket",
113         inventory_image = "bucket.png",
114         stack_max = 99,
115         liquids_pointable = true,
116         on_use = function(itemstack, user, pointed_thing)
117                 -- Must be pointing to node
118                 if pointed_thing.type ~= "node" then
119                         return
120                 end
121                 -- Check if pointing to a liquid source
122                 local node = minetest.get_node(pointed_thing.under)
123                 local liquiddef = bucket.liquids[node.name]
124                 local item_count = user:get_wielded_item():get_count()
125
126                 if liquiddef ~= nil
127                 and liquiddef.itemname ~= nil
128                 and node.name == liquiddef.source then
129                         if check_protection(pointed_thing.under,
130                                         user:get_player_name(),
131                                         "take ".. node.name) then
132                                 return
133                         end
134
135                         -- default set to return filled bucket
136                         local giving_back = liquiddef.itemname
137
138                         -- check if holding more than 1 empty bucket
139                         if item_count > 1 then
140
141                                 -- if space in inventory add filled bucked, otherwise drop as item
142                                 local inv = user:get_inventory()
143                                 if inv:room_for_item("main", {name=liquiddef.itemname}) then
144                                         inv:add_item("main", liquiddef.itemname)
145                                 else
146                                         local pos = user:getpos()
147                                         pos.y = math.floor(pos.y + 0.5)
148                                         core.add_item(pos, liquiddef.itemname)
149                                 end
150
151                                 -- set to return empty buckets minus 1
152                                 giving_back = "bucket:bucket_empty "..tostring(item_count-1)
153
154                         end
155
156                         minetest.add_node(pointed_thing.under, {name="air"})
157
158                         return ItemStack(giving_back)
159                 end
160         end,
161 })
162
163 bucket.register_liquid(
164         "default:water_source",
165         "default:water_flowing",
166         "bucket:bucket_water",
167         "bucket_water.png",
168         "Water Bucket",
169         {water_bucket = 1}
170 )
171
172 bucket.register_liquid(
173         "default:river_water_source",
174         "default:river_water_flowing",
175         "bucket:bucket_river_water",
176         "bucket_river_water.png",
177         "River Water Bucket",
178         {water_bucket = 1}
179 )
180
181 bucket.register_liquid(
182         "default:lava_source",
183         "default:lava_flowing",
184         "bucket:bucket_lava",
185         "bucket_lava.png",
186         "Lava Bucket"
187 )
188
189 minetest.register_craft({
190         type = "fuel",
191         recipe = "bucket:bucket_lava",
192         burntime = 60,
193         replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}},
194 })
195