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