1 local S
= minetest
.get_translator("mcl_buckets")
3 -- Minetest 0.4 mod: bucket
4 -- See README.txt for licensing and other information.
6 minetest
.register_alias("bucket:bucket_empty", "mcl_buckets:bucket_empty")
7 minetest
.register_alias("bucket:bucket_water", "mcl_buckets:bucket_water")
8 minetest
.register_alias("bucket:bucket_lava", "mcl_buckets:bucket_lava")
10 local mod_doc
= minetest
.get_modpath("doc")
11 local mod_mcl_core
= minetest
.get_modpath("mcl_core")
12 local mod_mclx_core
= minetest
.get_modpath("mclx_core")
15 minetest
.register_craft({
16 output
= 'mcl_buckets:bucket_empty 1',
18 {'mcl_core:iron_ingot', '', 'mcl_core:iron_ingot'},
19 {'', 'mcl_core:iron_ingot', ''},
25 mcl_buckets
.liquids
= {}
27 -- Sound helper functions for placing and taking liquids
28 local sound_place
= function(itemname
, pos
)
29 local def
= minetest
.registered_nodes
[itemname
]
30 if def
and def
.sounds
and def
.sounds
.place
then
31 minetest
.sound_play(def
.sounds
.place
, {gain
=1.0, pos
= pos
, pitch
= 1 + math
.random(-10, 10)*0.005}, true)
35 local sound_take
= function(itemname
, pos
)
36 local def
= minetest
.registered_nodes
[itemname
]
37 if def
and def
.sounds
and def
.sounds
.dug
then
38 minetest
.sound_play(def
.sounds
.dug
, {gain
=1.0, pos
= pos
, pitch
= 1 + math
.random(-10, 10)*0.005}, true)
42 local place_liquid
= function(pos
, itemstring
)
43 local fullness
= minetest
.registered_nodes
[itemstring
].liquid_range
44 sound_place(itemstring
, pos
)
45 minetest
.add_node(pos
, {name
=itemstring
, param2
=fullness
})
48 -- Register a new liquid
49 -- source_place = a string or function.
50 -- * string: name of the node to place
51 -- * function(pos): will returns name of the node to place with pos being the placement position
52 -- source_take = table of liquid source node names to take
53 -- itemname = itemstring of the new bucket item (or nil if liquid is not takeable)
54 -- inventory_image = texture of the new bucket item (ignored if itemname == nil)
55 -- name = user-visible bucket description
56 -- longdesc = long explanatory description (for help)
57 -- usagehelp = short usage explanation (for help)
58 -- tt_help = very short tooltip help
59 -- extra_check(pos, placer) = optional function(pos) which can returns false to avoid placing the liquid.
60 -- placer is object/player who is placing the liquid, can be nil
61 -- groups = optional list of item groups
63 -- This function can be called from any mod (which depends on this one)
64 function mcl_buckets
.register_liquid(source_place
, source_take
, itemname
, inventory_image
, name
, longdesc
, usagehelp
, tt_help
, extra_check
, groups
)
65 for i
=1, #source_take
do
66 mcl_buckets
.liquids
[source_take
[i]]
= {
67 source_place
= source_place
,
68 source_take
= source_take
[i
],
71 if type(source_place
) == "string" then
72 mcl_buckets
.liquids
[source_place
] = mcl_buckets
.liquids
[source_take
[i]]
76 if itemname
~= nil then
77 minetest
.register_craftitem(itemname
, {
79 _doc_items_longdesc
= longdesc
,
80 _doc_items_usagehelp
= usagehelp
,
82 inventory_image
= inventory_image
,
85 on_place
= function(itemstack
, user
, pointed_thing
)
86 -- Must be pointing to node
87 if pointed_thing
.type ~= "node" then
91 local node
= minetest
.get_node(pointed_thing
.under
)
92 local place_pos
= pointed_thing
.under
94 -- Call on_rightclick if the pointed node defines it
95 if user
and not user
:get_player_control().sneak
then
96 if minetest
.registered_nodes
[nn
] and minetest
.registered_nodes
[nn
].on_rightclick
then
97 return minetest
.registered_nodes
[nn
].on_rightclick(place_pos
, node
, user
, itemstack
) or itemstack
102 if type(source_place
) == "function" then
103 node_place
= source_place(place_pos
)
105 node_place
= source_place
107 -- Check if pointing to a buildable node
108 local item
= itemstack
:get_name()
110 if extra_check
and extra_check(place_pos
, user
) == false then
111 -- Fail placement of liquid
112 elseif minetest
.registered_nodes
[nn
] and minetest
.registered_nodes
[nn
].buildable_to
then
113 -- buildable; replace the node
114 local pns
= user
:get_player_name()
115 if minetest
.is_protected(place_pos
, pns
) then
116 minetest
.record_protection_violation(place_pos
, pns
)
119 place_liquid(place_pos
, node_place
)
120 if mod_doc
and doc
.entry_exists("nodes", node_place
) then
121 doc
.mark_entry_as_revealed(user
:get_player_name(), "nodes", node_place
)
124 -- not buildable to; place the liquid above
125 -- check if the node above can be replaced
126 local abovenode
= minetest
.get_node(pointed_thing
.above
)
127 if minetest
.registered_nodes
[abovenode
.name
] and minetest
.registered_nodes
[abovenode
.name
].buildable_to
then
128 local pn
= user
:get_player_name()
129 if minetest
.is_protected(pointed_thing
.above
, pn
) then
130 minetest
.record_protection_violation(pointed_thing
.above
, pn
)
133 place_liquid(pointed_thing
.above
, node_place
)
134 if mod_doc
and doc
.entry_exists("nodes", node_place
) then
135 doc
.mark_entry_as_revealed(user
:get_player_name(), "nodes", node_place
)
138 -- do not remove the bucket with the liquid
143 -- Handle bucket item and inventory stuff
144 if not minetest
.is_creative_enabled(user
:get_player_name()) then
145 -- Add empty bucket and put it into inventory, if possible.
146 -- Drop empty bucket otherwise.
147 local new_bucket
= ItemStack("mcl_buckets:bucket_empty")
148 if itemstack
:get_count() == 1 then
151 local inv
= user
:get_inventory()
152 if inv
:room_for_item("main", new_bucket
) then
153 inv
:add_item("main", new_bucket
)
155 minetest
.add_item(user
:get_pos(), new_bucket
)
157 itemstack
:take_item()
164 _on_dispense
= function(stack
, pos
, droppos
, dropnode
, dropdir
)
165 local iname
= stack
:get_name()
166 local buildable
= minetest
.registered_nodes
[dropnode
.name
].buildable_to
168 if extra_check
and extra_check(droppos
, nil) == false then
169 -- Fail placement of liquid
170 elseif buildable
then
171 -- buildable; replace the node
173 if type(source_place
) == "function" then
174 node_place
= source_place(droppos
)
176 node_place
= source_place
178 place_liquid(droppos
, node_place
)
179 stack
:set_name("mcl_buckets:bucket_empty")
187 minetest
.register_craftitem("mcl_buckets:bucket_empty", {
188 description
= S("Empty Bucket"),
189 _doc_items_longdesc
= S("A bucket can be used to collect and release liquids."),
190 _doc_items_usagehelp
= S("Punch a liquid source to collect it. You can then use the filled bucket to place the liquid somewhere else."),
191 _tt_help
= S("Collects liquids"),
193 liquids_pointable
= true,
194 inventory_image
= "bucket.png",
196 on_place
= function(itemstack
, user
, pointed_thing
)
197 -- Must be pointing to node
198 if pointed_thing
.type ~= "node" then
202 -- Call on_rightclick if the pointed node defines it
203 local node
= minetest
.get_node(pointed_thing
.under
)
205 if user
and not user
:get_player_control().sneak
then
206 if minetest
.registered_nodes
[nn
] and minetest
.registered_nodes
[nn
].on_rightclick
then
207 return minetest
.registered_nodes
[nn
].on_rightclick(pointed_thing
.under
, node
, user
, itemstack
) or itemstack
211 -- Can't steal liquids
212 if minetest
.is_protected(pointed_thing
.above
, user
:get_player_name()) then
213 minetest
.record_protection_violation(pointed_thing
.under
, user
:get_player_name())
217 -- Check if pointing to a liquid source
218 local liquiddef
= mcl_buckets
.liquids
[nn
]
220 if liquiddef
~= nil and liquiddef
.itemname
~= nil and (nn
== liquiddef
.source_take
) then
222 -- Fill bucket, but not in Creative Mode
223 if not minetest
.is_creative_enabled(user
:get_player_name()) then
224 new_bucket
= ItemStack({name
= liquiddef
.itemname
})
227 minetest
.add_node(pointed_thing
.under
, {name
="air"})
228 sound_take(nn
, pointed_thing
.under
)
230 if mod_doc
and doc
.entry_exists("nodes", nn
) then
231 doc
.mark_entry_as_revealed(user
:get_player_name(), "nodes", nn
)
234 elseif nn
== "mcl_cauldrons:cauldron_3" then
235 -- Take water out of full cauldron
236 minetest
.set_node(pointed_thing
.under
, {name
="mcl_cauldrons:cauldron"})
237 if not minetest
.is_creative_enabled(user
:get_player_name()) then
238 new_bucket
= ItemStack("mcl_buckets:bucket_water")
240 sound_take("mcl_core:water_source", pointed_thing
.under
)
241 elseif nn
== "mcl_cauldrons:cauldron_3r" then
242 -- Take river water out of full cauldron
243 minetest
.set_node(pointed_thing
.under
, {name
="mcl_cauldrons:cauldron"})
244 if not minetest
.is_creative_enabled(user
:get_player_name()) then
245 new_bucket
= ItemStack("mcl_buckets:bucket_river_water")
247 sound_take("mclx_core:river_water_source", pointed_thing
.under
)
250 -- Add liquid bucket and put it into inventory, if possible.
251 -- Drop new bucket otherwise.
253 if itemstack
:get_count() == 1 then
256 local inv
= user
:get_inventory()
257 if inv
:room_for_item("main", new_bucket
) then
258 inv
:add_item("main", new_bucket
)
260 minetest
.add_item(user
:get_pos(), new_bucket
)
262 if not minetest
.is_creative_enabled(user
:get_player_name()) then
263 itemstack
:take_item()
269 _on_dispense
= function(stack
, pos
, droppos
, dropnode
, dropdir
)
270 -- Fill empty bucket with liquid or drop bucket if no liquid
271 local collect_liquid
= false
273 local liquiddef
= mcl_buckets
.liquids
[dropnode
.name
]
275 if liquiddef
~= nil and liquiddef
.itemname
~= nil and (dropnode
.name
== liquiddef
.source_take
) then
277 new_bucket
= ItemStack({name
= liquiddef
.itemname
})
278 sound_take(dropnode
.name
, droppos
)
279 collect_liquid
= true
281 if collect_liquid
then
282 minetest
.set_node(droppos
, {name
="air"})
284 -- Fill bucket with liquid
287 -- No liquid found: Drop empty bucket
288 minetest
.add_item(droppos
, stack
)
297 mcl_buckets
.register_liquid(
299 local dim
= mcl_worlds
.pos_to_dimension(pos
)
300 if dim
== "nether" then
301 return "mcl_nether:nether_lava_source"
303 return "mcl_core:lava_source"
306 {"mcl_core:lava_source", "mcl_nether:nether_lava_source"},
307 "mcl_buckets:bucket_lava",
310 S("A bucket can be used to collect and release liquids. This one is filled with hot lava, safely contained inside. Use with caution."),
311 S("Get in a safe distance and place the bucket to empty it and create a lava source at this spot. Don't burn yourself!"),
312 S("Places a lava source")
316 mcl_buckets
.register_liquid(
317 "mcl_core:water_source",
318 {"mcl_core:water_source"},
319 "mcl_buckets:bucket_water",
322 S("A bucket can be used to collect and release liquids. This one is filled with water."),
323 S("Place it to empty the bucket and create a water source."),
324 S("Places a water source"),
325 function(pos
, placer
)
327 local placer_name
= ""
328 if placer
~= nil then
329 placer_name
= placer
:get_player_name()
331 if placer
and minetest
.is_protected(pos
, placer_name
) then
332 minetest
.record_protection_violation(pos
, placer_name
)
335 local nn
= minetest
.get_node(pos
).name
336 -- Pour water into cauldron
337 if minetest
.get_item_group(nn
, "cauldron") ~= 0 then
338 -- Put water into cauldron
339 if nn
~= "mcl_cauldrons:cauldron_3" then
340 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_3"})
342 sound_place("mcl_core:water_source", pos
)
344 -- Evaporate water if used in Nether (except on cauldron)
346 local dim
= mcl_worlds
.pos_to_dimension(pos
)
347 if dim
== "nether" then
348 minetest
.sound_play("fire_extinguish_flame", {pos
= pos
, gain
= 0.25, max_hear_distance
= 16}, true)
357 if mod_mclx_core
then
358 -- River water bucket
359 mcl_buckets
.register_liquid(
360 "mclx_core:river_water_source",
361 {"mclx_core:river_water_source"},
362 "mcl_buckets:bucket_river_water",
363 "bucket_river_water.png",
364 S("River Water Bucket"),
365 S("A bucket can be used to collect and release liquids. This one is filled with river water."),
366 S("Place it to empty the bucket and create a river water source."),
367 S("Places a river water source"),
368 function(pos
, placer
)
370 local placer_name
= ""
371 if placer
~= nil then
372 placer_name
= placer
:get_player_name()
374 if placer
and minetest
.is_protected(pos
, placer_name
) then
375 minetest
.record_protection_violation(pos
, placer_name
)
378 local nn
= minetest
.get_node(pos
).name
379 -- Pour into cauldron
380 if minetest
.get_item_group(nn
, "cauldron") ~= 0 then
381 -- Put water into cauldron
382 if nn
~= "mcl_cauldrons:cauldron_3r" then
383 minetest
.set_node(pos
, {name
="mcl_cauldrons:cauldron_3r"})
385 sound_place("mcl_core:water_source", pos
)
388 -- Evaporate water if used in Nether (except on cauldron)
389 local dim
= mcl_worlds
.pos_to_dimension(pos
)
390 if dim
== "nether" then
391 minetest
.sound_play("fire_extinguish_flame", {pos
= pos
, gain
= 0.25, max_hear_distance
= 16}, true)
400 minetest
.register_craft({
402 recipe
= "mcl_buckets:bucket_lava",
404 replacements
= {{"mcl_buckets:bucket_lava", "mcl_buckets:bucket_empty"}},