Renaming some cauldron-associated symbols.

Item group comparision against 0 instead of greater than.
Cauldron callbacks assigned function references instead of functions defined in-place.
Short-hand invocation of callback with default alternate value.
local helper function merge_tables made recursive to allow selective subkey override/substituion.
Cauldron fill heights determined by table lookup instead of cascading "if"s.
Trimming some dead code.
This commit is contained in:
Phaethon H 2021-11-05 17:12:50 -07:00
parent ad46840fa9
commit 407903b73a
6 changed files with 129 additions and 162 deletions

View File

@ -212,12 +212,12 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
-- Check if pointing to a liquid source
local liquiddef = mcl_buckets.liquids[nn]
local new_bucket
local cauldron_stuff
local cauldron_substance
if mcl_cauldrons.is_cauldron(node) then
if mcl_cauldrons.get_level(node, "cauldron_water") > 0 then
cauldron_stuff = "cauldron_water"
cauldron_substance = "cauldron_water"
elseif mcl_cauldrons.get_level(node, "cauldron_river_water") > 0 then
cauldron_stuff = "cauldron_river_water"
cauldron_substance = "cauldron_river_water"
end
end
if liquiddef ~= nil and liquiddef.itemname ~= nil and (nn == liquiddef.source_take) then
@ -237,7 +237,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", nn)
end
elseif cauldron_stuff then
elseif cauldron_substance then
-- Cauldron
local newnode
local CAULDRON_TO_BUCKET = {
@ -245,7 +245,7 @@ minetest.register_craftitem("mcl_buckets:bucket_empty", {
["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)
newnode = mcl_cauldrons.drain_levels(node, mcl_cauldrons.BUCKET_FILL_LEVELS, cauldron_specifier)
if node ~= newnode then
-- substance was taken out.
minetest.set_node(pointed_thing.under, newnode)

View File

@ -17,6 +17,28 @@ end
end
end]]
function mcl_buckets.get_bucket_from_cauldron(bucket_name, sound_name, cauldron_substance, pos, placer)
local node = minetest.get_node(pos)
if not mcl_cauldrons.is_cauldron(node) then
return nil
end
local placer_name = ""
if placer ~= nil then
placer_name = placer:get_player_name()
end
if placer and minetest.is_protected(pos, placer_name) then
minetest.record_protection_violation(pos, placer_name)
return nil
end
local newnode = mcl_cauldrons.fill_levels(node, mcl_cauldrons.BUCKET_FILL_LEVELS, cauldron_substance)
if newnode ~= node then
minetest.set_node(pos, newnode)
sound_place(sound_name, pos)
return bucket_name
end
return nil
end
if mod_mcl_core then
-- Lava bucket
mcl_buckets.register_liquid({
@ -73,25 +95,7 @@ if mod_mcl_core then
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
return nil
end
local placer_name = ""
if placer ~= nil then
placer_name = placer:get_player_name()
end
if placer and minetest.is_protected(pos, placer_name) then
minetest.record_protection_violation(pos, placer_name)
return nil
end
local newnode = mcl_cauldrons.fill_levels(node, mcl_cauldrons.BUCKETFUL, "cauldron_water")
if newnode ~= node then
minetest.set_node(pos, newnode)
sound_place("mcl_core:water_source", pos)
return "mcl_buckets:bucket_water"
end
return nil
return mcl_buckets.get_bucket_from_cauldron("mcl_buckets:bucket_water", "mcl_core:water_source", "cauldron_water", pos, placer)
end,
})
end
@ -127,25 +131,7 @@ if mod_mclx_core then
end,
groups = { water_bucket = 1 },
_mcl_get_bucket_from_cauldron = function(pos, placer)
local node = minetest.get_node(pos)
if not mcl_cauldrons.is_cauldron(node) then
return nil
end
local placer_name = ""
if placer ~= nil then
placer_name = placer:get_player_name()
end
if placer and minetest.is_protected(pos, placer_name) then
minetest.record_protection_violation(pos, placer_name)
return nil
end
local newnode = mcl_cauldrons.fill_levels(node, mcl_cauldrons.BUCKETFUL, "cauldron_river_water")
if newnode ~= node then
minetest.set_node(pos, newnode)
sound_place("mcl_core:water_source", pos)
return "mcl_buckets:bucket_river_water"
end
return nil
return mcl_buckets.get_bucket_from_cauldron("mcl_buckets:bucket_river_water", "mcl_core:water_source", "cauldron_river_water", pos, placer)
end,
})
end

View File

@ -14,8 +14,8 @@ Extensions to the base node definition descriptor (as passed to `minetest.regist
* `.groups.cauldron_water`: 1 - contains water
* `.groups.cauldron_river_water`: 1 - contains river water
* `.mcl_on_fill(node, amount)`: returns node { name, param1, param2 }
* `.mcl_on_drain(node, amount)`: returns node { name, param1, param2 }
* `._mcl_on_fill(node, amount)`: returns node { name, param1, param2 }
* `._mcl_on_drain(node, amount)`: returns node { name, param1, param2 }
### `mcl_cauldrons.registered_cauldrons`

View File

@ -4,8 +4,8 @@ mcl_cauldrons.registered_cauldrons = {}
-- symbolic constants.
mcl_cauldrons.BUCKETFUL = 3
mcl_cauldrons.BOTTLEFUL = 1
mcl_cauldrons.BUCKET_FILL_LEVELS = 3
mcl_cauldrons.BOTTLE_FILL_LEVELS = 1
-- Find cauldron from registered cauldrons -> string, table
@ -15,31 +15,32 @@ mcl_cauldrons.BOTTLEFUL = 1
-- Returns 2 values: node_name:string, node_definition:table;
-- if nothing else matches, returns empty cauldron ("mcl_cauldrons:cauldron").
function mcl_cauldrons.find_cauldron(substance, fill_level)
local empty_nodename = "mcl_cauldrons:cauldron"
local empty_nodedef = mcl_cauldrons.registered_cauldrons[empty_nodename]
if (substance == "") then
fill_level = 0
return empty_nodename, empty_nodedef
end
for nodename, nodedef in pairs(mcl_cauldrons.registered_cauldrons) do
-- matched on substance: 'any', or exact match from .groups.
local substantial = (substance == nil) or (nodedef.groups[substance] and (nodedef.groups[substance] > 0))
local match_substance = (substance == nil) or (nodedef.groups[substance] and (nodedef.groups[substance] ~= 0))
-- matched on fill_level: 'any', or exact match from .groups.
local filling = (fill_level == nil) or (nodedef.groups.cauldron_filled == fill_level)
if substantial and filling then
local match_level = (fill_level == nil) or (nodedef.groups.cauldron_filled == fill_level)
if match_substance and match_level then
return nodename, nodedef
end
end
-- no match, use empty.
local nodename = "mcl_cauldrons:cauldron"
return nodename, mcl_cauldrons.registered_cauldrons[nodename]
return empty_nodename, empty_nodedef
end
-- Test: node describes a cauldron -> boolean
function mcl_cauldrons.is_cauldron(node)
return (minetest.get_item_group(node.name, "cauldron") > 0)
return (minetest.get_item_group(node.name, "cauldron") ~= 0)
end
-- Test: cauldron node contains specified substance -> boolean
function mcl_cauldrons.has_substance(node, substance)
return (minetest.get_item_group(node.name, substance) > 0)
return (minetest.get_item_group(node.name, substance) ~= 0)
end
-- Get maximum number of levels available for cauldron node -> number
@ -98,32 +99,18 @@ end
-- returns a node table as accepted by minetest.set_node()
function mcl_cauldrons.fill_levels(node, change_levels, substance)
local nodedef = mcl_cauldrons.registered_cauldrons[node.name]
local callback = nodedef.mcl_on_fill
local newnode
if callback then
-- specific rules.
newnode = callback(node, change_levels, substance)
end
if newnode == nil then
-- revert changes.
newnode = node
end
local callback = nodedef._mcl_on_fill
-- use callback if available, else revert.
local newnode = callback and callback(node, change_levels, substance) or node
return newnode
end
-- drain counterpart to fill_levels()
function mcl_cauldrons.drain_levels(node, change_levels, substance)
local nodedef = mcl_cauldrons.registered_cauldrons[node.name]
local callback = nodedef.mcl_on_drain
local newnode
if callback then
-- specific rules.
newnode = callback(node, change_levels, substance)
end
if newnode == nil then
-- revert changes.
newnode = node
end
local callback = nodedef._mcl_on_drain
-- use callback if available, else revert.
local newnode = callback and callback(node, change_levels, substance) or node
return newnode
end

View File

@ -3,16 +3,13 @@ local S = minetest.get_translator(minetest.get_current_modname())
-- Convenience function because the cauldron nodeboxes are very similar
local create_cauldron_nodebox = function(water_level)
local floor_y
if water_level == 0 then -- empty
floor_y = -0.1875
elseif water_level == 1 then -- 1/3 filled
floor_y = 1/16
elseif water_level == 2 then -- 2/3 filled
floor_y = 4/16
elseif water_level == 3 then -- full
floor_y = 7/16
end
local floors_table = {
[0]=-0.1875, -- empty
[1]=1/16, -- 1/3 filled
[2]=4/16, -- 2/3 filled
[3]=7/16, -- full
}
local floor_y = floors_table[water_level]
return {
type = "fixed",
fixed = {
@ -42,17 +39,82 @@ end
-- The normal Lua means of inheritance uses setmetatable.
-- For node definitions, minetest.register_node() breaks/overwrite the metatable for its own use.
-- This function copies in the "old" keys/values, to lets them be overwritten by another (newer) table.
-- Care should be exercised updating/modifying the return value, as nested tables are copied by reference (viz. followup code might end up modifying nested tables in the *parent* defintion).
-- This function copies in the "old" keys/values, to let them be overwritten by another (newer) table.
-- Nested tables are recursively merged/copied, so nested keys may be selectively overridden.
-- Modifying the returned table does not risk mangling the source/parent table.
-- This workaround happens to work as declarative objects do not change after instantiation.
local function merge_tables(a,b)
local result = {}
for k,v in pairs(a) do result[k]=v end
for k,v in pairs(b) do result[k]=v end
for k,v in pairs(b) do
if type(a[k]) == "table" then
-- recursive merge table (with copy).
result[k] = merge_tables(a[k], v)
else
result[k] = v
end
end
return result
end
function mcl_cauldrons.empty_cauldron_on_fill(node, change_levels, substance)
-- base rules for cauldrons.
if change_levels <= 0 then
-- no change.
return nil
end
local old_level = mcl_cauldrons.get_level(node)
local whole, fraction = math.modf(change_levels)
local new_level
if fraction > 0 then
if math.random() < fraction then
whole = whole + 1
end
end
if (substance and mcl_cauldrons.has_substance(node, substance)) or (substance == nil) then
-- same substance, add more.
new_level = old_level + whole
else
-- different substance, delete old content.
new_level = whole
end
-- clamp 0 through 3 inclusive.
new_level = math.max(0, math.min(new_level, 3))
local newnode = mcl_cauldrons.set_level(node, new_level, substance)
return newnode
end
function mcl_cauldrons.empty_cauldron_on_drain(node, change_levels, substance)
-- base rules for cauldrons.
if change_levels <= 0 then
-- no change.
return nil
end
if (substance and not mcl_cauldrons.has_substance(node, substance)) then
-- different substance, cannot drain.
return nil
end
local old_level = mcl_cauldrons.get_level(node)
local whole, fraction = math.modf(change_levels)
local new_level
if fraction > 0 then
if math.random() < fraction then
whole = whole + 1
end
end
if (whole > old_level) then
-- insufficient amount, no change.
return nil
end
-- same substance, drain.
new_level = old_level - whole
-- clamp 0 through 3 inclusive.
new_level = math.max(0, math.min(new_level, 3))
local newnode = mcl_cauldrons.set_level(node, new_level, substance)
return newnode
end
-- Empty cauldron
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron", {
description = S("Cauldron"),
@ -77,60 +139,11 @@ mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron", {
_mcl_hardness = 2,
_mcl_blast_resistance = 2,
mcl_on_fill = function(node, change_levels, substance)
-- base rules for cauldrons.
if change_levels <= 0 then
-- no change.
return nil
end
local old_level = mcl_cauldrons.get_level(node)
local whole, fraction = math.modf(change_levels)
local new_level
if fraction > 0 then
if math.random() < fraction then
whole = whole + 1
end
end
if (substance and mcl_cauldrons.has_substance(node, substance)) or (substance == nil) then
-- same substance, add more.
new_level = old_level + whole
else
-- different substance, delete old content.
new_level = whole
end
-- clamp 0 through 3 inclusive.
new_level = math.max(0, math.min(new_level, 3))
local newnode = mcl_cauldrons.set_level(node, new_level, substance)
return newnode
_mcl_on_fill = function(node, change_levels, substance)
return mcl_cauldrons.empty_cauldron_on_fill(node, change_levels, substance)
end,
mcl_on_drain = function(node, change_levels, substance)
-- base rules for cauldrons.
if change_levels <= 0 then
-- no change.
return nil
end
if (substance and not mcl_cauldrons.has_substance(node, substance)) then
-- different substance, cannot drain.
return nil
end
local old_level = mcl_cauldrons.get_level(node)
local whole, fraction = math.modf(change_levels)
local new_level
if fraction > 0 then
if math.random() < fraction then
whole = whole + 1
end
end
if (whole > old_level) then
-- insufficient amount, no change.
return nil
end
-- same substance, drain.
new_level = old_level - whole
-- clamp 0 through 3 inclusive.
new_level = math.max(0, math.min(new_level, 3))
local newnode = mcl_cauldrons.set_level(node, new_level, substance)
return newnode
_mcl_on_drain = function(node, change_levels, substance)
return mcl_cauldrons.empty_cauldron_on_drain(node, change_levels, substance)
end,
})
@ -161,11 +174,7 @@ mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_2",
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_water_1"], {
description = S("Cauldron (2/3 Water)"),
groups = {
pickaxey = 1,
cauldron = 1,
cauldron_filled = 2,
cauldron_maximum = 3,
cauldron_water = 1,
},
node_box = mcl_cauldrons.cauldron_nodeboxes[2],
}), "mcl_cauldrons:cauldron")
@ -175,19 +184,12 @@ mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_water_3",
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_water_1"], {
description = S("Cauldron (3/3 Water)"),
groups = {
pickaxey = 1,
cauldron = 1,
cauldron_filled = 3,
cauldron_maximum = 3,
cauldron_water = 1,
},
node_box = mcl_cauldrons.cauldron_nodeboxes[3],
}), "mcl_cauldrons:cauldron")
if minetest.get_modpath("mclx_core") then
--register_filled_cauldron(1, S("Cauldron (1/3 River Water)"), true)
--register_filled_cauldron(2, S("Cauldron (2/3 River Water)"), true)
--register_filled_cauldron(3, S("Cauldron (3/3 River Water)"), true)
-- river water cauldron as extension of empty cauldron.
mcl_cauldrons.register_cauldron_node("mcl_cauldrons:cauldron_river_water_1",
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron"], {
@ -213,11 +215,7 @@ if minetest.get_modpath("mclx_core") then
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_river_water_1"], {
description = S("Cauldron (2/3 River Water)"),
groups = {
pickaxey = 1,
cauldron = 1,
cauldron_filled = 2,
cauldron_maximum = 3,
cauldron_river_water = 1,
},
node_box = mcl_cauldrons.cauldron_nodeboxes[2],
}), "mcl_cauldrons:cauldron")
@ -226,11 +224,7 @@ if minetest.get_modpath("mclx_core") then
merge_tables(mcl_cauldrons.registered_cauldrons["mcl_cauldrons:cauldron_river_water_1"], {
description = S("Cauldron (3/3 River Water)"),
groups = {
pickaxey = 1,
cauldron = 1,
cauldron_filled = 3,
cauldron_maximum = 3,
cauldron_river_water = 1,
},
node_box = mcl_cauldrons.cauldron_nodeboxes[3],
}), "mcl_cauldrons:cauldron")

View File

@ -115,7 +115,7 @@ local function take_from_cauldron(pos, node, itemstack, placer)
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)
local newnode = mcl_cauldrons.drain_levels(node, mcl_cauldrons.BOTTLE_FILL_LEVELS, cauldron_substance)
if newnode ~= node then
-- change happening (success).
minetest.set_node(pos, newnode)
@ -145,7 +145,7 @@ local function give_to_cauldron(pos, node, itemstack, placer, substance)
local fit = maximum - level
if fit > 0 then
-- sufficiently low level, add; old contents are lost.
local newnode = mcl_cauldrons.fill_levels(node, mcl_cauldrons.BOTTLEFUL, substance)
local newnode = mcl_cauldrons.fill_levels(node, mcl_cauldrons.BOTTLE_FILL_LEVELS, substance)
if node ~= newnode then
-- change happening (success).
minetest.set_node(pos, newnode)