Add Reservoir access to Access Point; add related network storage funcs

This commit is contained in:
Zenon Seth 2023-11-29 21:30:22 +00:00
parent 2bf30a11b6
commit 370e6162c3
10 changed files with 380 additions and 29 deletions

View File

@ -43,6 +43,11 @@ local function on_access_point_rightclick(pos, node, clicker, itemstack, pointed
logistica.access_point_on_rightclick(pos, node, clicker, itemstack, pointed_thing)
end
local function after_dig_access_point(pos, oldnode, oldmeta, digger)
logistica.on_access_point_change(pos, oldnode, oldmeta)
logistica.access_point_on_dug(pos)
end
local function can_dig_access_point(pos, player)
return true
end
@ -83,7 +88,7 @@ function logistica.register_access_point(desc, name, tiles)
can_dig = can_dig_access_point,
connect_sides = {"top", "bottom", "left", "back", "right" },
after_place_node = after_place_access_point,
after_dig_node = logistica.on_access_point_change,
after_dig_node = after_dig_access_point,
on_rightclick = on_access_point_rightclick,
-- on_metadata_inventory_move = on_access_point_inv_move,
-- on_metadata_inventory_put = on_access_point_inv_put,

View File

@ -66,13 +66,14 @@ local function after_place_node(pos, placer, itemstack, pointed_thing)
if not nodeDef or not nodeDef.logistica then return end
local liquidLevel = stackMeta:get_int(META_LIQUID_LEVEL)
local liquidDesc = nodeDef.logistica.liquidDesc
local liquidDesc = logistica.reservoir_get_description_of_liquid(nodeDef.logistica.liquidName)
local maxBuckets = nodeDef.logistica.maxBuckets
nodeMeta:set_int(META_LIQUID_LEVEL, liquidLevel)
node.param2 = logistica.reservoir_make_param2(liquidLevel, maxBuckets)
minetest.swap_node(pos, node)
nodeMeta:set_string("infotext", logistica.reservoir_get_description(liquidLevel, maxBuckets, liquidDesc))
logistica.on_reservoir_change(pos)
end
@ -84,7 +85,7 @@ local function preserve_metadata(pos, oldnode, oldmeta, drops)
local meta = minetest.get_meta(pos)
local drop = drops[1]
local dropMeta = drop:get_meta()
local liquidDesc = nodeDef.logistica.liquidDesc
local liquidDesc = logistica.reservoir_get_description_of_liquid(nodeDef.logistica.liquidName)
local maxBuckets = nodeDef.logistica.maxBuckets
local liquidLevel = meta:get_int(META_LIQUID_LEVEL)
@ -118,9 +119,10 @@ local commonDef = {
paramtype2 = "glasslikeliquidlevel",
is_ground_content = false,
sunlight_propagates = false,
groups = {cracky = 3, level = 1},
groups = {cracky = 3, level = 1, [logistica.TIER_ALL] = 1},
preserve_metadata = preserve_metadata,
after_place_node = after_place_node,
after_dig_node = logistica.on_reservoir_change,
on_rightclick = on_rightclick,
stack_max = 1,
backface_culling = false,
@ -144,8 +146,8 @@ for _, variantName in ipairs(variants) do
local nodeName = L("reservoir_"..variantName..EMPTY_SUFFIX)
def.drops = nodeName
def.logistica.liquidName = LIQUID_NONE
def.logistica.liquidDesc = LIQUID_NONE
minetest.register_node(nodeName, def)
logistica.reservoirs[nodeName] = true
end
--[[
@ -165,12 +167,12 @@ function logistica.register_reservoir(liquidName, liquidDesc, bucketItemName, li
def.drops = nodeName
def.special_tiles = {liquidTexture}
def.logistica.liquidName = lname
def.logistica.liquidDesc = liquidDesc
def.groups.not_in_creative_inventory = 1
def.light_source = optLight
minetest.register_node(nodeName, def)
logistica.reservoirs[nodeName] = true
logistica.reservoir_register_names(lname, bucketItemName, optEmptyBucketName)
logistica.reservoir_register_names(lname, bucketItemName, optEmptyBucketName, liquidDesc, liquidTexture)
end
end

View File

@ -1,10 +1,19 @@
local S = logistica.TRANSLATOR
local META_CURR_PAGE = "ap_curr_p"
local META_SORT_TYPE = "ap_sort"
local META_FILTER_TYPE = "ap_fltr"
local META_CURR_SEARCH = "ap_curr_s"
local META_IGNORE_METADATA = "ap_usemd"
local META_CURR_LIQUID_INDEX = "ap_curr_l"
local STR_NO_LIQUID = S("No Liquid Storage")
local STR_EMPTY_RESERVOIRS = S("Free Capacity:")
local fakeInvMap = {}
local liquidsMap = {}
local LIQUID_NONE = -1
local SORT_NAME = 1
local SORT_MOD = 2
@ -126,6 +135,26 @@ local function build_stack_list(pos)
}
end
-- { description = "description here", capacity = "3/32", texture = "texture_name.png"}
local function make_display_info(name, currBuckets, maxBuckets)
if not currBuckets or not maxBuckets then return { description = name, capacity = "", texture = ""} end
local desc, cap
if name == "" then
desc = STR_EMPTY_RESERVOIRS
cap = tostring(maxBuckets)
else
desc = logistica.reservoir_get_description_of_liquid(name)
cap = tostring(currBuckets).." / "..tostring(maxBuckets)
end
local texture = logistica.reservoir_get_texture_of_liquid(name)
return {
description = desc,
capacity = cap,
texture = texture,
}
end
--------------------------------
-- public functions
@ -133,6 +162,7 @@ end
function logistica.access_point_on_player_close(playerName)
fakeInvMap[playerName] = nil
liquidsMap[playerName] = nil
end
function logistica.update_fake_inv(pos, invName, listName, listSize, playerName)
@ -242,4 +272,62 @@ end
function logistica.access_point_get_current_search_term(meta)
return meta:get_string(META_CURR_SEARCH)
end
end
function logistica.access_point_change_liquid(meta, dir, playerName)
local liquidsInfo = liquidsMap[playerName]
if not liquidsInfo then return end
local currLiquidIndex = meta:get_int(META_CURR_LIQUID_INDEX)
if currLiquidIndex == LIQUID_NONE then return end
local numLiquids = #liquidsInfo
if numLiquids <= 0 then return end
local next = currLiquidIndex + dir
if next > numLiquids then next = 1 end
if next < 1 then next = numLiquids end
meta:set_int(META_CURR_LIQUID_INDEX, next)
return true
end
function logistica.access_point_refresh_liquids(pos, playerName)
local liquidsInfo = logistica.get_available_liquids_in_network(pos)
liquidsMap[playerName] = liquidsInfo
local meta = minetest.get_meta(pos)
if #liquidsInfo <= 0 then
meta:set_int(META_CURR_LIQUID_INDEX, LIQUID_NONE)
return
end
local currLiquid = meta:get_int(META_CURR_LIQUID_INDEX)
local validSelected = currLiquid >= 1 and currLiquid <= #liquidsInfo
if not validSelected then
meta:set_int(META_CURR_LIQUID_INDEX, 1)
end
end
-- returns a table: { description = "description here", capacity = "3/32", texture = "texture_name.png"}
function logistica.access_point_get_current_liquid_display_info(meta, playerName)
local liquidsInfo = liquidsMap[playerName]
if not liquidsInfo then return make_display_info(STR_NO_LIQUID, nil, nil) end
local currLiquid = meta:get_int(META_CURR_LIQUID_INDEX)
local liquidInfo = liquidsInfo[currLiquid]
if currLiquid == LIQUID_NONE or not liquidInfo then return make_display_info(STR_NO_LIQUID, nil, nil) end
return make_display_info(liquidInfo.name, liquidInfo.curr, liquidInfo.max)
end
-- returns the current liquid name (which may be "" for the empty reservoirs) or nil if invalid/no reservoirs
function logistica.access_point_get_current_liquid_name(meta, playerName)
local liquidsInfo = liquidsMap[playerName]
if not liquidsInfo then return nil end
local currLiquid = meta:get_int(META_CURR_LIQUID_INDEX)
if currLiquid == LIQUID_NONE then return "" end
local liquidInfo = liquidsInfo[currLiquid]
if not liquidInfo then return nil
else return liquidInfo.name end
end

View File

@ -19,9 +19,12 @@ local SORT_COUNT_BTN = "sort_cnt"
local SORT_WEAR_BTN = "sort_wer"
local SEARCH_FIELD = "srch_fld"
local USE_META_BTN = "tgl_meta"
local LIQUID_NEXT_BTN = "liq_nxt"
local LIQUID_PREV_BTN = "liq_prv"
local INV_FAKE = "fake"
local INV_INSERT = "isert"
local INV_LIQUID = "liqd"
local FAKE_INV_W = 12
local FAKE_INV_H = 4
local FAKE_INV_SIZE = FAKE_INV_W * FAKE_INV_H
@ -49,15 +52,16 @@ local STR_LIGHT_DESC = S("Show Light sources only")
local STR_SERCH_DESC = S("Search by text\nUse group:some_group to find items belongong to some_group")
local STR_CLEAR_DESC = S("Clear search")
local detachedInventories = {}
local accessPointForms = {}
-- creates the inv and returns the inv name
local function get_or_create_detached_inventory(pos, playerName)
if accessPointForms[playerName] and accessPointForms[playerName].invName then
return accessPointForms[playerName].invName
local hash = minetest.hash_node_position(pos)
if detachedInventories[hash] then
return detachedInventories[hash]
end
local invName = playerName.."_LAP_"..logistica.get_rand_string_for(pos)
local invName = "Logistica_AP_"..logistica.get_rand_string_for(pos)
local inv = minetest.create_detached_inventory(invName, {
allow_move = logistica.access_point_allow_move,
allow_put = logistica.access_point_allow_put,
@ -68,6 +72,8 @@ local function get_or_create_detached_inventory(pos, playerName)
}, playerName)
inv:set_size(INV_FAKE, FAKE_INV_SIZE)
inv:set_size(INV_INSERT, 1)
inv:set_size(INV_LIQUID, 1)
detachedInventories[hash] = invName
return invName
end
@ -144,6 +150,17 @@ local function get_search_and_page_section(searchTerm, pageInfo) return
"image_button[13.9,6.5;0.8,0.8;logistica_icon_last.png;"..LAST_BTN..";;false;false;]"
end
local function get_liquid_section(invName, meta, playerName)
local currInfo = logistica.access_point_get_current_liquid_display_info(meta, playerName)
return
"list[detached:"..invName..";"..INV_LIQUID..";1.2,7.3;1,1;0]"..
"image[1.3,6;0.8,0.8;"..currInfo.texture.."]"..
"label[1.0,7.1;"..currInfo.description.." "..currInfo.capacity.."]"..
"image_button[0.7,6;0.6,0.8;logistica_icon_prev.png;"..LIQUID_PREV_BTN..";;false;false]"..
"image_button[2.1,6;0.6,0.8;logistica_icon_next.png;"..LIQUID_NEXT_BTN..";;false;false]"
end
local function get_access_point_formspec(pos, invName, optMeta, playerName)
--local posForm = "nodemeta:"..pos.x..","..pos.y..","..pos.z
local meta = optMeta or minetest.get_meta(pos)
@ -158,12 +175,13 @@ local function get_access_point_formspec(pos, invName, optMeta, playerName)
"size[15.2,12.5]"..
logistica.ui.background..
"list[detached:"..invName..";"..INV_FAKE..";0.2,0.2;"..FAKE_INV_W..","..FAKE_INV_H..";0]"..
"image[2.8,6.4;1,1;logistica_icon_input.png]"..
"list[detached:"..invName..";"..INV_INSERT..";3.8,6.4;1,1;0]"..
"image[3.2,6.5;0.8,0.8;logistica_icon_input.png]"..
"list[detached:"..invName..";"..INV_INSERT..";4.0,6.4;1,1;0]"..
"list[current_player;main;5.2,7.5;8.0,4.0;0]"..
"label[1.4,12.2;"..S("Crafting").."]"..
"list[current_player;craft;0.2,8.4;3,3;]"..
"list[current_player;craftpreview;3.9,8.4;1,1;]"..
get_liquid_section(invName, meta, playerName)..
get_listrings(invName)..
get_filter_section(usesMetaStr, filterHighImg)..
get_tooltips()..
@ -180,6 +198,7 @@ local function show_access_point_formspec(pos, playerName, optMeta)
invName = invName,
}
logistica.access_point_refresh_fake_inv(pos, invName, INV_FAKE, FAKE_INV_SIZE, playerName)
logistica.access_point_refresh_liquids(pos, playerName)
minetest.show_formspec(
playerName,
FORMSPEC_NAME,
@ -207,7 +226,6 @@ function logistica.on_receive_access_point_formspec(player, formname, fields)
if minetest.is_protected(pos, playerName) or not pos then return true end
if fields.quit and not fields.key_enter_field then
logistica.access_point_on_player_leave(playerName)
return true
elseif fields[FRST_BTN] then
if not logistica.access_point_change_page(pos, -2, playerName, FAKE_INV_SIZE) then return true end
@ -241,6 +259,10 @@ function logistica.on_receive_access_point_formspec(player, formname, fields)
logistica.access_point_on_search_clear(pos)
elseif fields[SEARCH_BTN] or fields.key_enter_field then
logistica.access_point_on_search_change(pos, fields[SEARCH_FIELD])
elseif fields[LIQUID_PREV_BTN] then
if not logistica.access_point_change_liquid(minetest.get_meta(pos),-1, playerName) then return true end
elseif fields[LIQUID_NEXT_BTN] then
if not logistica.access_point_change_liquid(minetest.get_meta(pos), 1, playerName) then return true end
end
show_access_point_formspec(pos, playerName)
return true
@ -252,9 +274,18 @@ end
function logistica.access_point_allow_put(inv, listname, index, stack, player)
if listname == INV_FAKE then return 0 end
local pos = get_curr_pos(player)
if not pos then return 0 end
if not logistica.get_network_or_nil(pos) then return 0 end
if listname == INV_LIQUID then
if logistica.reservoir_is_known_bucket(stack:get_name()) then
local currStack = inv:get_stack(listname, index)
if currStack:is_empty() then return 1 else return 0 end
else return 0 end
end
return stack:get_count()
end
@ -298,6 +329,7 @@ end
function logistica.access_point_allow_move(inv, from_list, from_index, to_list, to_index, count, player)
if from_list == INV_FAKE or to_list == INV_FAKE then return 0 end
if to_list == INV_LIQUID then return 0 end
return count
end
@ -319,6 +351,13 @@ function logistica.access_point_on_put(inv, listname, index, stack, player)
end
inv:set_stack(listname, index, ItemStack(""))
show_access_point_formspec(pos, player:get_player_name())
elseif listname == INV_LIQUID then
local currLiquid = logistica.access_point_get_current_liquid_name(minetest.get_meta(pos), player:get_player_name())
local newStack = logistica.use_bucket_for_liquid_in_network(pos, stack, currLiquid)
if newStack then
inv:set_stack(listname, index, newStack)
show_access_point_formspec(pos, player:get_player_name())
end
end
end
@ -342,8 +381,28 @@ end
function logistica.access_point_on_player_leave(playerName)
local info = accessPointForms[playerName]
if info and info.invName then
minetest.remove_detached_inventory(info.invName)
local onlyRef = true
for _, otherInfo in pairs(accessPointForms) do
if otherInfo.invName == info.invName then onlyRef = false end
end
if onlyRef then
minetest.remove_detached_inventory(info.invName)
end
end
accessPointForms[playerName] = nil
logistica.access_point_on_player_close(playerName)
end
function logistica.access_point_on_dug(pos)
local removeForPlayers = {}
local i =0
for playerName, info in pairs(accessPointForms) do
if info.position and vector.equals(pos, info.position) then
i = i + 1
removeForPlayers[i] = playerName
end
end
for _, playerName in ipairs(removeForPlayers) do
logistica.access_point_on_player_leave(playerName)
end
end

View File

@ -9,6 +9,7 @@ logistica.item_storage = {}
logistica.misc_machines = {}
logistica.trashcans = {}
logistica.vaccuum_suppliers = {}
logistica.reservoirs = {}
logistica.TIER_ALL = "logistica_all_tiers"
logistica.GROUP_ALL = "group:" .. logistica.TIER_ALL
logistica.TIER_CONTROLLER = "logistica_controller"
@ -20,7 +21,7 @@ function logistica.is_machine(name)
return logistica.is_requester(name) or logistica.is_supplier(name) or logistica.is_mass_storage(name)
or logistica.is_item_storage(name) or logistica.is_controller(name) or logistica.is_injector(name)
or logistica.is_crafting_supplier(name) or logistica.is_trashcan(name) or logistica.is_vaccuum_supplier(name)
or logistica.is_misc(name)
or logistica.is_misc(name) or logistica.is_reservoir(name)
end
function logistica.is_cable(name)
@ -66,3 +67,7 @@ end
function logistica.is_vaccuum_supplier(name)
return logistica.vaccuum_suppliers[name] ~= nil
end
function logistica.is_reservoir(name)
return logistica.reservoirs[name] ~= nil
end

View File

@ -23,6 +23,7 @@ local function has_machine(network, id)
or network.injectors[id]
or network.misc[id]
or network.trashcans[id]
or network.reservoirs[id]
then
return true
else
@ -204,6 +205,10 @@ local function recursive_scan_for_nodes_for_controller(network, positionHashes,
network.trashcans[otherHash] = true
valid = true
end
if logistica.is_reservoir(otherName) then
network.reservoirs[otherHash] = true
valid = true
end
if valid then
newToScan = newToScan + 1
set_cache_network_id(minetest.get_meta(otherPos), network.controller)
@ -242,6 +247,7 @@ local function create_network(controllerPosition, oldNetworkName)
network.storage_cache = {}
network.supplier_cache = {}
network.requester_cache = {}
network.reservoirs = {}
local startPos = {}
startPos[controllerHash] = true
local status = recursive_scan_for_nodes_for_controller(network, startPos)
@ -369,6 +375,12 @@ local TRASHCAN_OPS = {
update_cache_node_removed = function(_) end,
}
local RESERVOIR_OPS = {
get_list = function(network) return network.reservoirs end,
update_cache_node_added = function(_) end,
update_cache_node_removed = function(_) end,
}
local function cable_can_extend_network_from(pos)
local node = minetest.get_node_or_nil(pos)
if not node then return false end
@ -494,3 +506,7 @@ end
function logistica.on_trashcan_change(pos, oldNode, oldMeta)
on_node_change(pos, oldNode, oldMeta, TRASHCAN_OPS)
end
function logistica.on_reservoir_change(pos, oldNode, oldMeta)
on_node_change(pos, oldNode, oldMeta, RESERVOIR_OPS)
end

View File

@ -3,11 +3,75 @@ local MASS_STORAGE_LIST_NAME = "storage"
local ITEM_STORAGE_LIST_NAME = "main"
local MAX_NETWORK_DEPTH_SEARCH = 16 -- somewhat arbitrary but prevents stackoverflows
local h2p = minetest.get_position_from_hash
local function get_meta(pos)
logistica.load_position(pos)
return minetest.get_meta(pos)
end
local function fill_bucket_from_network(network, bucketItemStack, liquidName)
local lowestReservoirPos = nil
local lowestReservoirLvl = 999999
for hash, _ in pairs(network.reservoirs or {}) do
local pos = h2p(hash)
logistica.load_position(pos)
if logistica.reservoir_get_liquid_name(pos) == liquidName then
local levels = logistica.reservoir_get_liquid_level(pos)
if levels and levels[1] < lowestReservoirLvl then
lowestReservoirPos = pos
lowestReservoirLvl = levels[1]
end
end
end
if lowestReservoirPos then
return logistica.reservoir_use_item_on(lowestReservoirPos, bucketItemStack)
else
return nil
end
end
local function empty_bucket_into_network(network, bucketItemStack)
local bucketName = bucketItemStack:get_name()
local liquidName = logistica.reservoir_get_liquid_name_for_bucket(bucketName)
local highestReservoirPos = nil
local emptyReservoirPos = nil
local emptyResrvoirMinCap = 999999
local highestReservoirLvl = 0
for hash, _ in pairs(network.reservoirs or {}) do
local pos = h2p(hash)
logistica.load_position(pos)
local liquidInReservoir = logistica.reservoir_get_liquid_name(pos)
if liquidInReservoir == liquidName then
local levels = logistica.reservoir_get_liquid_level(pos)
if levels and levels[1] < levels[2] and levels[1] > highestReservoirLvl then
highestReservoirPos = pos
highestReservoirLvl = levels[1]
end
elseif liquidInReservoir == "" then
local levels = logistica.reservoir_get_liquid_level(pos)
if levels and levels[2] < emptyResrvoirMinCap then
emptyResrvoirMinCap = levels[2]
emptyReservoirPos = pos
end
end
end
if highestReservoirPos then
return logistica.reservoir_use_item_on(highestReservoirPos, bucketItemStack)
elseif emptyReservoirPos then
return logistica.reservoir_use_item_on(emptyReservoirPos, bucketItemStack)
else
return nil
end
end
--------------------------------
-- public functions
--------------------------------
-- tries to take a stack from the network locations
-- calls the collectorFunc with the stack - collectorFunc needs to return how many were left-over<br>
-- `collectorFunc = function(stackToInsert)`<br>
@ -40,7 +104,7 @@ function logistica.take_stack_from_suppliers(stackToTake, network, collectorFunc
local stackName = stackToTake:get_name()
local validSupplers = network.supplier_cache[stackName] or {}
for hash, _ in pairs(validSupplers) do
local pos = minetest.get_position_from_hash(hash)
local pos = h2p(hash)
logistica.load_position(pos)
local nodeName = minetest.get_node(pos).name
if logistica.is_supplier(nodeName) or logistica.is_vaccuum_supplier(nodeName) then
@ -64,7 +128,7 @@ function logistica.take_stack_from_item_storage(stack, network, collectorFunc, i
if useMetadata then eq = function(s1, s2) return s1:equals(s2) end end
for storageHash, _ in pairs(network.item_storage) do
local storagePos = minetest.get_position_from_hash(storageHash)
local storagePos = h2p(storageHash)
local storageInv = get_meta(storagePos):get_inventory()
local storageList = storageInv:get_list(ITEM_STORAGE_LIST_NAME) or {}
for i, storedStack in ipairs(storageList) do
@ -97,7 +161,7 @@ function logistica.take_stack_from_mass_storage(stackToTake, network, collectorF
if stackToTake:get_count() == 0 then return end
if massLocations == nil then return end
for storageHash, _ in pairs(massLocations) do
local storagePos = minetest.get_position_from_hash(storageHash)
local storagePos = h2p(storageHash)
local meta = get_meta(storagePos)
local storageInv = meta:get_inventory()
local storageList = storageInv:get_list(MASS_STORAGE_LIST_NAME) or {}
@ -155,7 +219,7 @@ function logistica.insert_item_in_network(itemstack, networkId, dryRun)
-- check requesters first
local listOfRequestersInNeedOfItem = network.requester_cache[itemstack:get_name()] or {}
for hash, _ in pairs(listOfRequestersInNeedOfItem) do
local pos = minetest.get_position_from_hash(hash)
local pos = h2p(hash)
logistica.load_position(pos)
local leftover = logistica.insert_itemstack_for_requester(pos, workingStack, true)
if leftover <= 0 then return 0 end -- we took all items
@ -173,7 +237,7 @@ function logistica.insert_item_in_network(itemstack, networkId, dryRun)
addFunc = logistica.insert_item_into_mass_storage
end
for hash, _ in pairs(storages) do
local pos = minetest.get_position_from_hash(hash)
local pos = h2p(hash)
local inv = get_meta(pos):get_inventory()
local remainingStack = addFunc(pos, inv, workingStack, dryRun)
if remainingStack:is_empty() then return 0 end -- we took all items
@ -183,7 +247,7 @@ function logistica.insert_item_in_network(itemstack, networkId, dryRun)
-- try to add to passive suppliers that accept this
local suppliers = network.suppliers
for hash, _ in pairs(suppliers) do
local pos = minetest.get_position_from_hash(hash)
local pos = h2p(hash)
logistica.load_position(pos)
local leftover = logistica.put_item_in_supplier(pos, workingStack)
if leftover:is_empty() then return 0 end
@ -193,11 +257,67 @@ function logistica.insert_item_in_network(itemstack, networkId, dryRun)
-- [Keep this last] delete the item if any trashcan accepts it
local trashcans = network.trashcans or {}
for hash, _ in pairs(trashcans) do
local pos = minetest.get_position_from_hash(hash)
local pos = h2p(hash)
logistica.load_position(pos)
workingStack = logistica.trashcan_trash_item(pos, workingStack)
if workingStack:is_empty() then return 0 end
end
return workingStack:get_count()
end
end
--[[ returns a natural-indexed list of tables - or empty table if there's no network or no liquids:
```
[1] = {
name = "liquid_name", -- name of the liquid or "" if for empty reservoirs
curr = 0 -- amount of liquid stored in network
max = 32 -- combined max capacity of the reservoirs occupied by liquid
},
[2] = {...}
```
]]
function logistica.get_available_liquids_in_network(pos)
local network = logistica.get_network_or_nil(pos)
if not network then return {} end
local liquidInfo = {}
for hash, _ in pairs(network.reservoirs or {}) do
local resPos = h2p(hash)
local liquidName = logistica.reservoir_get_liquid_name(resPos)
local liquidLevels = logistica.reservoir_get_liquid_level(resPos)
if liquidName and liquidLevels then
local info = liquidInfo[liquidName] or {curr = 0, max = 0}
info.curr = info.curr + liquidLevels[1]
info.max = info.max + liquidLevels[2]
liquidInfo[liquidName] = info
end
end
return
logistica.table_to_list_indexed(liquidInfo, function(lName, lInfo)
return {
name = lName,
curr = lInfo.curr,
max = lInfo.max,
}
end)
end
-- attempts to use, either fill or empty, the given bucket in/from liquid storage on
-- the network.<br>
-- `liquidName` is only used if the bucketItem is a type of empty bucket<br>
-- Otherwise a full bucket will attempt to fill any applicable reservoir on the network.
-- This function attempts to take from the lowest filled reservoir, and insert into the highest filled reservoir first.<br>
-- returns new itemstack to replace the old one, or `nil` if it wasn't changed
function logistica.use_bucket_for_liquid_in_network(pos, bucketItemStack, liquidName)
local network = logistica.get_network_or_nil(pos)
if not network then return nil end
local bucketName = bucketItemStack:get_name()
local isEmptyBucket = logistica.reservoir_is_empty_bucket(bucketName)
local isFullBucket = logistica.reservoir_is_full_bucket(bucketName)
if isEmptyBucket then
if not liquidName then return nil end
return fill_bucket_from_network(network, bucketItemStack, liquidName)
elseif isFullBucket then
return empty_bucket_into_network(network, bucketItemStack)
end
end

View File

@ -3,6 +3,9 @@ local S = logistica.TRANSLATOR
local BUCKET_TO_NAME = {}
local NAME_TO_BUCKET = {}
local NAME_TO_EMPTY_BUCKET = {}
local NAME_TO_DESC = {}
local NAME_TO_TEXTURE = {}
local EMPTY_BUCKET = "bucket:bucket_empty"
local EMPTY_SUFFIX = "_empty"
@ -54,6 +57,14 @@ end
-- public functions
--------------------------------
function logistica.reservoir_get_description_of_liquid(liquidName)
return NAME_TO_DESC[liquidName] or LIQUID_NONE
end
function logistica.reservoir_get_texture_of_liquid(liquidName)
return NAME_TO_TEXTURE[liquidName] or ""
end
function logistica.reservoir_make_param2(val, max)
local ret = math.floor(63*(val/max))
if val > 0 and ret == 0 then
@ -66,12 +77,14 @@ function logistica.reservoir_get_description(currBuckets, maxBuckets, liquidName
return strDescription.."\n"..getStrContains(currBuckets, maxBuckets, liquidName)
end
function logistica.reservoir_register_names(liquidName, bucketName, emptyBucketName)
function logistica.reservoir_register_names(liquidName, bucketName, emptyBucketName, liquidDesc, liquidTexture)
BUCKET_TO_NAME[bucketName] = liquidName
NAME_TO_BUCKET[liquidName] = bucketName
if emptyBucketName then
NAME_TO_EMPTY_BUCKET[liquidName] = emptyBucketName
end
NAME_TO_DESC[liquidName] = liquidDesc
NAME_TO_TEXTURE[liquidName] = liquidTexture
end
-- returns nil if item had no effect<br>
@ -86,7 +99,7 @@ function logistica.reservoir_use_item_on(pos, itemstack, optNode)
local nodeLiquidLevel = meta:get_int(META_LIQUID_LEVEL)
local liquidName = nodeDef.logistica.liquidName
local maxBuckets = nodeDef.logistica.maxBuckets
local liquidDesc = nodeDef.logistica.liquidDesc
local liquidDesc = logistica.reservoir_get_description_of_liquid(liquidName)
local emptyBucket = get_empty_bucket_needed_for(liquidName)
local fullBucket = get_full_bucket_needed_for(liquidName)
@ -127,14 +140,57 @@ function logistica.reservoir_use_item_on(pos, itemstack, optNode)
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
local nodeDef = minetest.registered_nodes[newNodeName]
if not nodeDef or not nodeDef.logistica 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
local newLiquidDesc = logistica.reservoir_get_description_of_liquid(nodeDef.logistica.liquidName)
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
-- returns the liquid name for the reservoir; or "" if there's no liquid stored, or nil if its not a reservoir
function logistica.reservoir_get_liquid_name(pos)
local node = minetest.get_node(pos)
if not logistica.is_reservoir(node.name) then return nil end
local def = minetest.registered_nodes[node.name]
if not def or not def.logistica or not def.logistica.liquidName then return nil end
return def.logistica.liquidName
end
-- return {currentLevel, maxLevel} measured in buckets; or nil if its not a reservoir
function logistica.reservoir_get_liquid_level(pos)
local node = minetest.get_node(pos)
if not logistica.is_reservoir(node.name) then return nil end
local def = minetest.registered_nodes[node.name]
if not def or not def.logistica or not def.logistica.maxBuckets then return nil end
local meta = minetest.get_meta(pos)
return { meta:get_int(META_LIQUID_LEVEL), def.logistica.maxBuckets }
end
function logistica.reservoir_is_empty_bucket(bucketName)
if bucketName == EMPTY_BUCKET then return true end
for _, bucket in pairs(NAME_TO_EMPTY_BUCKET) do
if bucket == bucketName then return true end
end
return false
end
function logistica.reservoir_is_full_bucket(bucketName)
if BUCKET_TO_NAME[bucketName] ~= nil then return true end
return false
end
-- returns true if the itemname is a known empty or filled bucket that can be used in a reservoir
function logistica.reservoir_is_known_bucket(bucketName)
return logistica.reservoir_is_empty_bucket(bucketName) or logistica.reservoir_is_full_bucket(bucketName)
end
-- return the liquid name for the given bucket name, or nil if there's none registered
function logistica.reservoir_get_liquid_name_for_bucket(bucketName)
return BUCKET_TO_NAME[bucketName]
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB