MineClone2/mods/ITEMS/mcl_cauldrons/api.lua

157 lines
5.6 KiB
Lua

local has_doc = minetest.get_modpath(minetest.get_current_modname())
mcl_cauldrons.registered_cauldrons = {}
-- symbolic constants.
mcl_cauldrons.BUCKET_FILL_LEVELS = 3
mcl_cauldrons.BOTTLE_FILL_LEVELS = 1
-- list of substances accepted by cauldron.
-- N.B. hopefully this will be obsoleted by the liquids API.
mcl_cauldrons.substances = {
"cauldron_water",
"cauldron_river_water",
}
-- Find cauldron from registered cauldrons -> string, table
-- `substance` == nil for any cauldron content (incl. empty), "" = only empty.
-- `fill_level` == nil for any/first fill level satisfying `substance`.
-- e.g. find_cauldron("cauldron_water", 2) -> "mcl_cauldrons:cauldron_water_2"
-- 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
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 match_substance = (substance == nil) or (nodedef.groups[substance] and (nodedef.groups[substance] ~= 0))
-- matched on fill_level: 'any', or exact match from .groups.
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.
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)
end
-- Test: cauldron node contains specified substance -> boolean
function mcl_cauldrons.has_substance(node, substance)
return (minetest.get_item_group(node.name, substance) ~= 0)
end
-- list of supported substances -> table
function mcl_cauldrons.list_substances()
return mcl_cauldron.substances
end
-- Get substance inside cauldron -> string or nil
function mcl_cauldrons.get_substance(node)
local nodename = node.name
-- data-driven to avoid if-cascade.
-- until liquids API is available, the substance name matches the group key in the node definition (e.g. "cauldron_water").
for i, probe_key in ipairs(mcl_cauldrons.substances) do
if minetest.get_item_group(node.name, probe_key) ~= 0 then
return probe_key
end
end
-- claim cauldron is empty.
return nil
end
-- Get maximum number of levels available for cauldron node -> number
-- Optionally specify `substance` (mainly to determine a change in cauldron substance, e.g. filling a full one with bucket of something else)
-- substance == nil to ignore substance criteria
function mcl_cauldrons.get_maximum(node, substance)
local nodename
if substance == nil then
nodename = node.name
else
nodename = mcl_cauldrons.find_cauldron(substance, nil)
end
return minetest.get_item_group(nodename, "cauldron_maximum")
end
-- Get current level of cauldron -> number
-- Optionally specify `substance`, substance==nil to indicate current content.
function mcl_cauldrons.get_level(node, substance)
if substance and (minetest.get_item_group(node.name, substance) == 0) then
return 0
end
return minetest.get_item_group(node.name, "cauldron_filled")
end
-- Test: cauldron is empty -> boolean
-- (i.e. fill level is 0, or contents is empty)
function mcl_cauldrons.is_empty(node)
if not mcl_cauldrons.is_cauldron(node) then
error("not a cauldron", node.name)
end
if minetest.get_item_group(node.name, "cauldron_filled") == 0 then
return true
end
return false
end
-- Test: cauldron is full -> boolean
-- (i.e. current fill level matches maximum level.
function mcl_cauldrons.is_full(node)
local maximum = mcl_cauldrons.get_maximum(node)
local current = mcl_cauldrons.get_level(node)
return (current >= maximum)
end
-- Set fill level, bypassing game rules -> table
-- Optionally indicate substance (to change cauldron content); nil to preserve.
-- returns a node table as accepted by minetest.set_node()
function mcl_cauldrons.set_level(node, fill_level, substance)
if substance == nil then
-- determine current substance.
substance = mcl_cauldrons.get_substance(node)
end
local nodename, nodedef = mcl_cauldrons.find_cauldron(substance, fill_level)
local newnode = { name = nodename, param1 = node.param1, param2 = node.param2 }
return newnode
end
-- Change content of cauldron by number of levels with indicated substance -> table
-- Subject to game rules (delegated to node definition's on_fill callback)
-- 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
-- use callback if available, else revert.
return callback and callback(node, change_levels, substance) or node
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
-- use callback if available, else revert.
return callback and callback(node, change_levels, substance) or node
end
-- Wrapper to register cauldron-specific nodes.
-- additional bookkeeping specific to mcl_cauldrons.
function mcl_cauldrons.register_cauldron_node(nodename, nodedef, doc_alias)
mcl_cauldrons.registered_cauldrons[nodename] = nodedef
minetest.register_node(nodename, nodedef)
if doc_alias and has_doc then
doc.add_entry_alias("nodes", doc_alias, "nodes", nodename)
end
end