logistica-cd2025/logic/reservoir.lua
2023-11-28 21:57:54 +00:00

141 lines
5.2 KiB
Lua

local S = logistica.TRANSLATOR
local BUCKET_TO_NAME = {}
local NAME_TO_BUCKET = {}
local NAME_TO_EMPTY_BUCKET = {}
local EMPTY_BUCKET = "bucket:bucket_empty"
local EMPTY_SUFFIX = "_empty"
local META_LIQUID_LEVEL = "liquidLevel"
local LIQUID_NONE = ""
local BUCKET_ANY = "BUCKET_ANY"
local strDescription = S("Reservoir")
local strEmpty = S("Empty")
local getStrContains = function(number, max, ofWhat)
if number == 0 then
return S("@1 / @2 buckets", number, max)
else
return S("@1 / @2 buckets of @3", number, max, ofWhat)
end
end
local function ends_with(str, ending)
return ending == "" or string.sub(str, -#ending) == ending
end
local function get_empty_bucket_needed_for(liquidName)
local savedBucket = NAME_TO_EMPTY_BUCKET[liquidName]
if savedBucket then return savedBucket
else return EMPTY_BUCKET end
end
local function get_full_bucket_needed_for(liquidName)
if liquidName == LIQUID_NONE then return BUCKET_ANY end
return NAME_TO_BUCKET[liquidName]
end
local function get_empty_reservoir_name(nodeName, liquidName)
if not ends_with(nodeName, liquidName) then return nodeName end
if ends_with(nodeName, EMPTY_SUFFIX) then return nodeName end
local nodeBase = string.sub(nodeName, 1, (#nodeName) - (#liquidName) - 1)
return nodeBase..EMPTY_SUFFIX
end
local function get_liquid_reservoir_name_for(nodeName, liquidName)
if not ends_with(nodeName, EMPTY_SUFFIX) then return nodeName end
local nodeBase = string.sub(nodeName, 1, (#nodeName) - (#EMPTY_SUFFIX))
local newName = nodeBase.."_"..liquidName
if not minetest.registered_nodes[newName] then return nodeName
else return newName end
end
--------------------------------
-- public functions
--------------------------------
function logistica.reservoir_make_param2(val, max)
local ret = math.floor(63*(val/max))
if val > 0 and ret == 0 then
ret = 1 -- this ensures we always have at least 1 visible liquid level
end
return ret
end
function logistica.reservoir_get_description(currBuckets, maxBuckets, liquidName)
return strDescription.."\n"..getStrContains(currBuckets, maxBuckets, liquidName)
end
function logistica.reservoir_register_names(liquidName, bucketName, emptyBucketName)
BUCKET_TO_NAME[bucketName] = liquidName
NAME_TO_BUCKET[liquidName] = bucketName
if emptyBucketName then
NAME_TO_EMPTY_BUCKET[liquidName] = emptyBucketName
end
end
-- returns nil if item had no effect<br>
-- returns an ItemStack to replace the item, if it had effect (e.g. took or stored liquid)
function logistica.reservoir_use_item_on(pos, itemstack, optNode)
local node = optNode or minetest.get_node(pos)
local nodeDef = minetest.registered_nodes[node.name]
if not nodeDef or not nodeDef.logistica or not nodeDef.logistica.liquidName or not nodeDef.logistica.maxBuckets then return end
local itemStackName = itemstack:get_name()
local meta = minetest.get_meta(pos)
local nodeLiquidLevel = meta:get_int(META_LIQUID_LEVEL)
local liquidName = nodeDef.logistica.liquidName
local maxBuckets = nodeDef.logistica.maxBuckets
local liquidDesc = nodeDef.logistica.liquidDesc
local emptyBucket = get_empty_bucket_needed_for(liquidName)
local fullBucket = get_full_bucket_needed_for(liquidName)
if itemStackName == emptyBucket then
if nodeLiquidLevel == 0 then
-- make sure we swap this for the empty reservoir
logistica.swap_node(pos, get_empty_reservoir_name(node.name, liquidName))
return nil
end
if not fullBucket then return nil end
nodeLiquidLevel = nodeLiquidLevel - 1
if nodeLiquidLevel == 0 then
node.param2 = 0
else
node.param2 = logistica.reservoir_make_param2(nodeLiquidLevel, maxBuckets)
end
minetest.swap_node(pos, node)
meta:set_int(META_LIQUID_LEVEL, nodeLiquidLevel)
if nodeLiquidLevel == 0 then
local newNodeName = get_empty_reservoir_name(node.name, liquidName)
if not minetest.registered_nodes[newNodeName] then return nil end
logistica.swap_node(pos, newNodeName)
end
meta:set_string("infotext", logistica.reservoir_get_description(nodeLiquidLevel, maxBuckets, liquidDesc))
return ItemStack(fullBucket)
elseif fullBucket == BUCKET_ANY or itemStackName == fullBucket then
local newLiquidName = BUCKET_TO_NAME[itemStackName]
if not newLiquidName then return nil end -- wasn't a bucket we can use
local newEmptyBucket = get_empty_bucket_needed_for(newLiquidName)
if not newEmptyBucket then return nil end
nodeLiquidLevel = nodeLiquidLevel + 1
if nodeLiquidLevel > maxBuckets then return nil end
node.param2 = logistica.reservoir_make_param2(nodeLiquidLevel, maxBuckets)
minetest.swap_node(pos, node)
local newNodeName = get_liquid_reservoir_name_for(node.name, newLiquidName)
if not minetest.registered_nodes[newNodeName] then return nil end
if nodeLiquidLevel == 1 then -- first bucket we added, swap to that reservoir type
logistica.swap_node(pos, newNodeName)
end
local newLiquidDesc = minetest.registered_nodes[newNodeName].logistica.liquidDesc
meta:set_string("infotext", logistica.reservoir_get_description(nodeLiquidLevel, maxBuckets, newLiquidDesc))
meta:set_int(META_LIQUID_LEVEL, nodeLiquidLevel)
return ItemStack(newEmptyBucket)
end
return nil
end