Allow filling up glass bottles from cauldrons with river water.

Play sounds for filling bottles from water sources.
Play water_source sound for taking bucket of river water from cauldron.
Remove redundant check to skip building water source due to filling cauldron.
This commit is contained in:
Phaethon H 2021-10-25 14:31:24 -07:00
parent 3b9c553b6c
commit ad46840fa9
3 changed files with 85 additions and 67 deletions

View File

@ -96,11 +96,7 @@ function mcl_buckets.register_liquid(def)
if handle_fill_cauldron then
local new_bucketname = handle_fill_cauldron(place_pos, user)
if not new_bucketname then
-- revoke cauldron codepath.
-- fall back to placing node normally.
handle_fill_cauldron = nil
else
if new_bucketname then
skip_build = true
end
end
@ -246,7 +242,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
local newnode
local CAULDRON_TO_BUCKET = {
["cauldron_water"]={bucket="mcl_buckets:bucket_water", sound="mcl_core:water_source"},
["cauldron_river_water"]={bucket="mcl_buckets:bucket_river_water", sound="mcl_core:river_water_source"},
["cauldron_river_water"]={bucket="mcl_buckets:bucket_river_water", sound="mcl_core:water_source"},
}
for cauldron_specifier, bucket_spec in pairs(CAULDRON_TO_BUCKET) do
newnode = mcl_cauldrons.drain_levels(node, mcl_cauldrons.BUCKETFUL, cauldron_specifier)

View File

@ -71,6 +71,7 @@ if mod_mcl_core then
end
end,
groups = { water_bucket = 1 },
-- TODO: this is getting clunkier by the commit, re-do handling of bucket/cauldron interaction (as a node callback, this function contains too many side effects).
_mcl_get_bucket_from_cauldron = function(pos, placer)
local node = minetest.get_node(pos)
if not mcl_cauldrons.is_cauldron(node) then

View File

@ -41,8 +41,20 @@ minetest.register_craft({
})
local function deposit_player_inventory(placer, itemstack, item_name)
local new_itemstack = ItemStack({name=item_name})
local function is_cauldron_protected(pos, placer)
local pname = placer:get_player_name()
if minetest.is_protected(pos, pname) then
-- no take, no changing.
minetest.record_protection_violation(pos, pname)
return true
end
return false
end
-- exchange one count of `from_itemstack` for one count of `to_item_name`.
-- creative mode does not consume any items, but also does not provide more than one of `item_name`.
local function exchange_player_inventory(placer, from_itemstack, to_item_name)
local new_itemstack = ItemStack({name=to_item_name})
local inv = placer:get_inventory()
if minetest.is_creative_enabled(placer:get_player_name()) then
-- creative mode: have at most one.
@ -51,42 +63,73 @@ local function deposit_player_inventory(placer, itemstack, item_name)
end
else
-- survival mode
if itemstack:get_count() <= 1 then
if from_itemstack:get_count() <= 1 then
-- swap in place.
return new_itemstack
elseif inv:room_for_item("main", new_itemstack) then
-- add to inventory, take one.
itemstack:take_item()
inv:add_item("main", new_itemstack)
return itemstack
else
-- drop in place.
itemstack:take_item()
minetest.add_item(placer:get_pos(), item_name)
-- take one.
from_itemstack:take_item()
-- add to inventory, or drop in place.
if inv:room_for_item("main", new_itemstack) then
-- add to inventory.
inv:add_item("main", new_itemstack)
else
-- drop in place.
minetest.add_item(placer:get_pos(), new_itemstack)
end
return from_itemstack
end
end
-- no change in inventory.
return itemstack
return from_itemstack
end
-- determine if object `placer` allowed to use a potion on cauldron `node`(nilable) at world position `pos`.
local function may_use_cauldron(placer, pos, node)
-- potion may interact (change state of) cauldron if:
-- 1. mcl_cauldrons mod enabled.
-- 2. node is cauldron.
-- 3. modifying node is permitted (node protection).
if node == nil then
node = minetest.get_node(pos)
end
if mcl_cauldrons and mcl_cauldrons.is_cauldron(node) then
-- check protection.
if is_cauldron_protected(pos, placer) then
return false
end
return true
end
-- not a cauldron.
return false
end
local function take_from_cauldron(pos, node, itemstack, placer)
local sounds = mcl_sounds.node_sound_metal_defaults() -- TODO: should come from declarative object
-- check cauldron limits.
local new_bottlename
if mcl_cauldrons.get_level(node, "cauldron_water") > 0 then
-- has water, try to take water.
local newnode = mcl_cauldrons.drain_levels(node, mcl_cauldrons.BOTTLEFUL, "cauldron_water")
if newnode ~= node then
-- changes happening (success).
minetest.set_node(pos, newnode)
minetest.sound_play("mcl_potions_bottle_fill", {pos=pos, gain=0.5, max_hear_range=16}, true)
new_bottlename = "mcl_potions:water"
-- lookup table, from cauldron substance to the potion returned.
local CAULDRON_TO_BOTTLE = {
["cauldron_water"]="mcl_potions:water",
["cauldron_river_water"]="mcl_potions:river_water",
}
for cauldron_substance, bottle_name in pairs(CAULDRON_TO_BOTTLE) do
-- check cauldron limit.
if mcl_cauldrons.get_level(node, cauldron_substance) > 0 then
local newnode = mcl_cauldrons.drain_levels(node, mcl_cauldrons.BOTTLEFUL, cauldron_substance)
if newnode ~= node then
-- change happening (success).
minetest.set_node(pos, newnode)
local soundname = "mcl_potions_bottle_fill" -- TODO: from data structure.
minetest.sound_play(soundname, {pos=pos, gain=0.5, max_hear_range=16}, true)
new_bottlename = bottle_name
break
end
end
end
if new_bottlename then
return deposit_player_inventory(placer, itemstack, new_bottlename)
return exchange_player_inventory(placer, itemstack, new_bottlename)
end
-- no change in inventory.
-- else no change in inventory.
return itemstack
end
@ -104,14 +147,14 @@ local function give_to_cauldron(pos, node, itemstack, placer, substance)
-- sufficiently low level, add; old contents are lost.
local newnode = mcl_cauldrons.fill_levels(node, mcl_cauldrons.BOTTLEFUL, substance)
if node ~= newnode then
-- change happened
-- change happening (success).
minetest.set_node(pos, newnode)
minetest.sound_play("mcl_potions_bottle_pour", {pos=pos, gain=0.5, max_hear_range=16}, true)
new_bottlename = "mcl_potions:glass_bottle"
end
end
if new_bottlename then
return deposit_player_inventory(placer, itemstack, new_bottlename)
return exchange_player_inventory(placer, itemstack, new_bottlename)
end
-- no change in inventory.
return itemstack
@ -143,27 +186,21 @@ minetest.register_craftitem("mcl_potions:glass_bottle", {
local get_water = false
--local from_liquid_source = false
local river_water = false
local from_cauldron = false
if mcl_cauldrons.is_cauldron(node) then
from_cauldron = not mcl_cauldrons.is_empty(node)
end
local from_cauldron = may_use_cauldron(placer, pointed_thing.under, node)
if def and def.groups and def.groups.water and def.liquidtype == "source" then
-- Water source
get_water = true
--from_liquid_source = true
river_water = node.name == "mclx_core:river_water_source"
local new_bottlename = river_water and "mcl_potions:river_water" or "mcl_potions:water"
return deposit_player_inventory(placer, itemstack, new_bottlename)
minetest.sound_play("mcl_potions_bottle_fill", {pos=pointed_thing.under, gain=0.5, max_hear_range=16}, true)
return exchange_player_inventory(placer, itemstack, new_bottlename)
-- Or reduce water level of cauldron by 1
elseif from_cauldron then
if mcl_cauldrons.get_level(node, "cauldron_water") > 0 then
-- take bottle of water.
local pname = placer:get_player_name()
if minetest.is_protected(pointed_thing.under, pname) then
minetest.record_protection_violation(pointed_thing.under, pname)
return itemstack
end
if mcl_cauldrons.get_level(node, nil) > 0 then
-- something in cauldron.
-- attempt to take bottleful from cauldron.
-- if bottle cannot be filled, no change in inventory.
return take_from_cauldron(pointed_thing.under, node, itemstack, placer)
end
end
@ -213,14 +250,9 @@ minetest.register_craftitem("mcl_potions:water", {
end
end
if mcl_cauldrons.is_cauldron(node) then
-- apply water bottle to empty or water cauldron
-- anything else, replace content.
local pname = placer:get_player_name()
if minetest.is_protected(pointed_thing.under, pname) then
minetest.record_protection_violation(pointed_thing.under, pname)
return itemstack
end
if may_use_cauldron(placer, pointed_thing.under, node) then
-- try to put substance into cauldron;
-- returns ItemStack (no change if interact not allowed, else the potion resulting from filling cauldron (typ. glass bottle))
return give_to_cauldron(pointed_thing.under, node, itemstack, placer, "cauldron_water")
end
end
@ -254,21 +286,10 @@ minetest.register_craftitem("mcl_potions:river_water", {
end
end
local cauldron = fill_cauldron(node.name, "mclx_core:river_water_source")
if cauldron then
local pname = placer:get_player_name()
if minetest.is_protected(pointed_thing.under, pname) then
minetest.record_protection_violation(pointed_thing.under, pname)
return itemstack
end
-- Increase water level of cauldron by 1
minetest.set_node(pointed_thing.under, {name=cauldron})
minetest.sound_play("mcl_potions_bottle_pour", {pos=pointed_thing.under, gain=0.5, max_hear_range=16}, true)
if minetest.is_creative_enabled(placer:get_player_name()) then
return itemstack
else
return "mcl_potions:glass_bottle"
end
if may_use_cauldron(placer, pointed_thing.under, node) then
-- try to put substance into cauldron;
-- returns ItemStack (no change if interact not allowed, else the potion resulting from filling cauldron (typ. glass bottle))
return give_to_cauldron(pointed_thing.under, node, itemstack, placer, "cauldron_river_water")
end
end