1 -- Minetest 0.4 mod: bucket
2 -- See README.txt for licensing and other information.
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")
8 minetest.register_craft({
9 output = 'bucket:bucket_empty 1',
11 {'default:steel_ingot', '', 'default:steel_ingot'},
12 {'', 'default:steel_ingot', ''},
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)
26 minetest.record_protection_violation(pos, name)
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,
45 bucket.liquids[source] = {
49 force_renew = force_renew,
51 bucket.liquids[flowing] = bucket.liquids[source]
53 if itemname ~= nil then
54 minetest.register_craftitem(itemname, {
56 inventory_image = inventory_image,
58 liquids_pointable = true,
61 on_place = function(itemstack, user, pointed_thing)
62 -- Must be pointing to node
63 if pointed_thing.type ~= "node" then
67 local node = minetest.get_node_or_nil(pointed_thing.under)
68 local ndef = node and minetest.registered_nodes[node.name]
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(
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
86 -- not buildable to; place the liquid above
87 -- check if the node above can be replaced
89 lpos = pointed_thing.above
90 node = minetest.get_node_or_nil(lpos)
91 local above_ndef = node and minetest.registered_nodes[node.name]
93 if not above_ndef or not above_ndef.buildable_to then
94 -- do not remove the bucket with the liquid
99 if check_protection(lpos, user
100 and user:get_player_name()
101 or "", "place "..source) then
105 minetest.set_node(lpos, {name = source})
106 return ItemStack("bucket:bucket_empty")
112 minetest.register_craftitem("bucket:bucket_empty", {
113 description = "Empty Bucket",
114 inventory_image = "bucket.png",
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
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()
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
139 -- default set to return filled bucket
140 local giving_back = liquiddef.itemname
142 -- check if holding more than 1 empty bucket
143 if item_count > 1 then
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)
150 local pos = user:getpos()
151 pos.y = math.floor(pos.y + 0.5)
152 minetest.add_item(pos, liquiddef.itemname)
155 -- set to return empty buckets minus 1
156 giving_back = "bucket:bucket_empty "..tostring(item_count-1)
160 -- force_renew requires a source neighbour
161 local source_neighbor = false
162 if liquiddef.force_renew then
164 minetest.find_node_near(pointed_thing.under, 1, liquiddef.source)
166 if not (source_neighbor and liquiddef.force_renew) then
167 minetest.add_node(pointed_thing.under, {name = "air"})
170 return ItemStack(giving_back)
172 -- non-liquid nodes will have their on_punch triggered
173 local node_def = minetest.registered_nodes[node.name]
175 node_def.on_punch(pointed_thing.under, node, user, pointed_thing)
177 return user:get_wielded_item()
182 bucket.register_liquid(
183 "default:water_source",
184 "default:water_flowing",
185 "bucket:bucket_water",
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",
201 bucket.register_liquid(
202 "default:lava_source",
203 "default:lava_flowing",
204 "bucket:bucket_lava",
209 minetest.register_craft({
211 recipe = "bucket:bucket_lava",
213 replacements = {{"bucket:bucket_lava", "bucket:bucket_empty"}},