Creative: Make the placenode registration check for non-player placers
[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                                    user and not user:get_player_control().sneak then
73                                         return ndef.on_rightclick(
74                                                 pointed_thing.under,
75                                                 node, user,
76                                                 itemstack)
77                                 end
78
79                                 local lpos
80
81                                 -- Check if pointing to a buildable node
82                                 if ndef and ndef.buildable_to then
83                                         -- buildable; replace the node
84                                         lpos = pointed_thing.under
85                                 else
86                                         -- not buildable to; place the liquid above
87                                         -- check if the node above can be replaced
88
89                                         lpos = pointed_thing.above
90                                         node = minetest.get_node_or_nil(lpos)
91                                         local above_ndef = node and minetest.registered_nodes[node.name]
92
93                                         if not above_ndef or not above_ndef.buildable_to then
94                                                 -- do not remove the bucket with the liquid
95                                                 return itemstack
96                                         end
97                                 end
98
99                                 if check_protection(lpos, user
100                                                 and user:get_player_name()
101                                                 or "", "place "..source) then
102                                         return
103                                 end
104
105                                 minetest.set_node(lpos, {name = source})
106                                 return ItemStack("bucket:bucket_empty")
107                         end
108                 })
109         end
110 end
111
112 minetest.register_craftitem("bucket:bucket_empty", {
113         description = "Empty Bucket",
114         inventory_image = "bucket.png",
115         stack_max = 99,
116         liquids_pointable = true,
117         on_use = function(itemstack, user, pointed_thing)
118                 if pointed_thing.type == "object" then
119                         pointed_thing.ref:punch(user, 1.0, { full_punch_interval=1.0 }, nil)
120                         return user:get_wielded_item()
121                 elseif pointed_thing.type ~= "node" then
122                         -- do nothing if it's neither object nor node
123                         return
124                 end
125                 -- Check if pointing to a liquid source
126                 local node = minetest.get_node(pointed_thing.under)
127                 local liquiddef = bucket.liquids[node.name]
128                 local item_count = user:get_wielded_item():get_count()
129
130                 if liquiddef ~= nil
131                 and liquiddef.itemname ~= nil
132                 and node.name == liquiddef.source then
133                         if check_protection(pointed_thing.under,
134                                         user:get_player_name(),
135                                         "take ".. node.name) then
136                                 return
137                         end
138
139                         -- default set to return filled bucket
140                         local giving_back = liquiddef.itemname
141
142                         -- check if holding more than 1 empty bucket
143                         if item_count > 1 then
144
145                                 -- if space in inventory add filled bucked, otherwise drop as item
146                                 local inv = user:get_inventory()
147                                 if inv:room_for_item("main", {name=liquiddef.itemname}) then
148                                         inv:add_item("main", liquiddef.itemname)
149                                 else
150                                         local pos = user:getpos()
151                                         pos.y = math.floor(pos.y + 0.5)
152                                         minetest.add_item(pos, liquiddef.itemname)
153                                 end
154
155                                 -- set to return empty buckets minus 1
156                                 giving_back = "bucket:bucket_empty "..tostring(item_count-1)
157
158                         end
159
160                         -- force_renew requires a source neighbour
161                         local source_neighbor = false
162                         if liquiddef.force_renew then
163                                 source_neighbor =
164                                         minetest.find_node_near(pointed_thing.under, 1, liquiddef.source)
165                         end
166                         if not (source_neighbor and liquiddef.force_renew) then
167                                 minetest.add_node(pointed_thing.under, {name = "air"})
168                         end
169
170                         return ItemStack(giving_back)
171                 else
172                         -- non-liquid nodes will have their on_punch triggered
173                         local node_def = minetest.registered_nodes[node.name]
174                         if node_def then
175                                 node_def.on_punch(pointed_thing.under, node, user, pointed_thing)
176                         end
177                         return user:get_wielded_item()
178                 end
179         end,
180 })
181
182 bucket.register_liquid(
183         "default:water_source",
184         "default:water_flowing",
185         "bucket:bucket_water",
186         "bucket_water.png",
187         "Water Bucket",
188         {water_bucket = 1}
189 )
190
191 bucket.register_liquid(
192         "default:river_water_source",
193         "default:river_water_flowing",
194         "bucket:bucket_river_water",
195         "bucket_river_water.png",
196         "River Water Bucket",
197         {water_bucket = 1},
198         true
199 )
200
201 bucket.register_liquid(
202         "default:lava_source",
203         "default:lava_flowing",
204         "bucket:bucket_lava",
205         "bucket_lava.png",
206         "Lava Bucket"
207 )
208
209 minetest.register_craft({
210         type = "fuel",
211         recipe = "bucket:bucket_lava",
212         burntime = 60,
213         replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}},
214 })
215