Add bucket emptier, fix minor issues with filler

This commit is contained in:
Zenon Seth 2024-03-15 00:09:04 +00:00
parent e52b3cb43d
commit b4dfa3fef9
15 changed files with 332 additions and 42 deletions

View File

@ -20,3 +20,4 @@ dofile(path.."/synchronizer.lua")
dofile(path.."/reservoir.lua")
dofile(path.."/lava_furnace_fueler.lua")
dofile(path.."/bucket_filler.lua")
dofile(path.."/bucket_emptier.lua")

171
api/bucket_emptier.lua Normal file
View File

@ -0,0 +1,171 @@
local S = logistica.TRANSLATOR
local FORMSPEC_NAME = "logistica_bktempt"
local INV_INPUT = "input"
local INV_MAIN = "main"
local ON_OFF_BTN = "onffbtn"
local forms = {}
--------------------------------
-- Formspec
--------------------------------
local function get_emptier_formspec(pos, _isOn)
local isOn = _isOn
local posForm = "nodemeta:"..pos.x..","..pos.y..","..pos.z
if isOn == nil then isOn = logistica.is_machine_on(pos) end
return "formspec_version[4]"..
"size["..logistica.inv_size(10.5, 12.0).."]" ..
logistica.ui.background..
"label[0.4,0.4;"..S("Provided with filled buckets, empties them into any network reservoirs").."]"..
"label[0.4,0.8;"..S("Resulting empty buckets are provided as passive supply to network").."]"..
"list["..posForm..";"..INV_INPUT..";0.3,1.3;6,4;0]"..
"list["..posForm..";"..INV_MAIN..";9.1,1.3;1,4;0]"..
"image[7.8,3.1;1,1;logistica_icon_next.png]"..
"label[1.4,6.4;"..S("Input: Filled Buckets to be emptied").."]"..
logistica.ui.on_off_btn(isOn, 7.7, 2.2, ON_OFF_BTN, S("Enable"))..
logistica.player_inv_formspec(0.4, 7.0)..
"listring["..posForm..";"..INV_INPUT.."]"..
"listring[current_player;main]"..
"listring["..posForm..";"..INV_INPUT.."]"..
"listring["..posForm..";"..INV_MAIN.."]"..
"listring[current_player;main]"
end
local function show_emptier_formspec(playerName, pos)
if not forms[playerName] then forms[playerName] = {position = pos} end
minetest.show_formspec(playerName, FORMSPEC_NAME, get_emptier_formspec(pos))
end
--------------------------------
-- Callbacks
--------------------------------
local function emptier_after_place(pos, placer, itemstack)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
inv:set_size(INV_INPUT, 24)
inv:set_size(INV_MAIN, 4)
logistica.set_node_tooltip_from_state(pos)
logistica.on_supplier_change(pos)
end
local function emptier_can_dig(pos)
local inv = minetest.get_meta(pos):get_inventory()
return inv:is_empty(INV_INPUT) and inv:is_empty(INV_MAIN)
end
local function emptier_allow_metadata_inv_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then return 0 end
if listname == INV_MAIN then return 0 end
if listname == INV_INPUT then
if logistica.reservoir_is_full_bucket(stack:get_name()) then return stack:get_count()
else return 0 end
end
return stack:get_count()
end
local function emptier_allow_metadata_inv_take(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then return 0 end
return stack:get_count()
end
local function emptier_allow_metadata_inv_move(pos, from_list, from_index, to_list, to_index, count, player)
if minetest.is_protected(pos, player:get_player_name()) then return 0 end
if to_list == INV_MAIN then return 0 end
return count
end
local function emptier_on_inv_change(pos)
local inv = minetest.get_meta(pos):get_inventory()
logistica.start_node_timer(pos, 1)
end
local function on_emptier_rightclick(pos, node, clicker, itemstack, pointed_thing)
if not clicker or not clicker:is_player() then return end
if minetest.is_protected(pos, clicker:get_player_name()) then return end
show_emptier_formspec(clicker:get_player_name(), pos)
end
local function on_player_receive_fields(player, formname, fields)
if not player or not player:is_player() then return false end
if formname ~= FORMSPEC_NAME then return false end
local playerName = player:get_player_name()
if not forms[playerName] then return false end
local pos = forms[playerName].position
if minetest.is_protected(pos, playerName) then return true end
if fields[ON_OFF_BTN] then
logistica.toggle_machine_on_off(pos)
show_emptier_formspec(playerName, pos)
end
end
----------------------------------------------------------------
-- Minetest registration
----------------------------------------------------------------
minetest.register_on_player_receive_fields(on_player_receive_fields)
minetest.register_on_leaveplayer(function(objRef, timed_out)
if objRef:is_player() then
forms[objRef:get_player_name()] = nil
end
end)
--------------------------------
-- Public API
--------------------------------
function logistica.register_bucket_emptier(desc, name, tiles)
local lname = name:gsub("%s", "_"):lower()
local emptier_name = "logistica:"..lname
logistica.bucketemptiers[emptier_name] = true
local def = {
description = S(desc),
tiles = tiles,
paramtype2 = "facedir",
groups = { cracky= 2, pickaxey = 2, [logistica.TIER_ALL] = 1 },
is_ground_content = false,
sounds = logistica.sound_mod.node_sound_stone_defaults(),
can_dig = emptier_can_dig,
on_timer = logistica.on_timer_powered(logistica.emptier_timer),
after_place_node = emptier_after_place,
after_dig_node = logistica.on_supplier_change,
on_rightclick = on_emptier_rightclick,
on_metadata_inventory_move = emptier_on_inv_change,
on_metadata_inventory_put = emptier_on_inv_change,
on_metadata_inventory_take = emptier_on_inv_change,
allow_metadata_inventory_put = emptier_allow_metadata_inv_put,
allow_metadata_inventory_move = emptier_allow_metadata_inv_move,
allow_metadata_inventory_take = emptier_allow_metadata_inv_take,
logistica = {
on_power = logistica.emptier_on_power,
on_connect_to_network = function(pos, networkId)
logistica.start_node_timer(pos, 1)
end,
},
_mcl_hardness = 3,
_mcl_blast_resistance = 10,
}
minetest.register_node(emptier_name, def)
local def_disabled = table.copy(def)
local tiles_disabled = {}
for k, v in pairs(def.tiles) do tiles_disabled[k] = v.."^logistica_disabled.png" end
def_disabled.tiles = tiles_disabled
def_disabled.groups = { oddly_breakable_by_hand = 3, cracky = 3, choppy = 3, not_in_creative_inventory = 1, pickaxey = 1, axey = 1, handy = 1 }
def_disabled.on_construct = nil
def_disabled.after_dig_node = nil
def_disabled.on_punch = nil
def_disabled.on_rightclick = nil
def_disabled.on_timer = nil
def_disabled.logistica = nil
minetest.register_node(emptier_name.."_disabled", def_disabled)
end

View File

@ -74,12 +74,16 @@ local function after_place_filler(pos, placer, itemstack)
inv:set_size(INV_INPUT, 4)
logistica.set_node_tooltip_from_state(pos)
logistica.filler_change_selected_bucket(pos, 1000000) -- makes sure the 1st liquid is selected
logistica.on_supplier_change(pos)
end
local function allow_filler_inv_put(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then return 0 end
if listname == INV_MAIN then return 0 end
return stack:get_count()
if listname == INV_INPUT then
if logistica.reservoir_is_empty_bucket(stack:get_name()) then return stack:get_count()
else return 0 end
end
end
local function allow_filler_inv_take(pos, listname, index, stack, player)

59
logic/bucket_emptier.lua Normal file
View File

@ -0,0 +1,59 @@
local S = logistica.TRANSLATOR
local INV_INPUT = "input"
local INV_MAIN = "main"
local TIMER_SHORT = 1.0
local TIMER_LONG = 3.0
function logistica.emptier_on_power(pos, power)
if power then
logistica.start_node_timer(pos, TIMER_SHORT)
end
local meta = minetest.get_meta(pos)
logistica.set_node_tooltip_from_state(pos, nil, power)
end
function logistica.emptier_timer(pos, elapsed)
local network = logistica.get_network_or_nil(pos)
if not network then return false end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local firstSlot = logistica.get_next_filled_item_slot(meta, INV_INPUT)
local currSlot = firstSlot
local success = false
if currSlot > 0 then
repeat
local stack = inv:get_stack(INV_INPUT, currSlot)
local stackName = stack:get_name()
local liquidName = logistica.reservoir_get_liquid_name_for_bucket(stackName)
if liquidName then
local emptyBucket = logistica.reservoir_get_empty_bucket_for_liquid(liquidName)
if inv:room_for_item(INV_MAIN, ItemStack(emptyBucket)) then
local newStack = logistica.empty_bucket_into_network(network, stack)
if newStack then
success = true
local replaceStack = ItemStack("")
if stack:get_count() > 1 then
replaceStack = ItemStack(stackName)
replaceStack:set_count(stack:get_count() - 1)
end
inv:set_stack(INV_INPUT, currSlot, replaceStack)
inv:add_item(INV_MAIN, newStack)
logistica.update_cache_at_pos(pos, LOG_CACHE_SUPPLIER, network)
end
end
end
if not success then currSlot = logistica.get_next_filled_item_slot(meta, INV_INPUT) end
until(success or currSlot == firstSlot)
end
if success then logistica.start_node_timer(pos, TIMER_SHORT)
else logistica.start_node_timer(pos, TIMER_LONG) end
return false
end

View File

@ -48,7 +48,7 @@ function logistica.filler_change_selected_bucket(pos, change)
mainList[1] = ItemStack(allBucketsToNames[index].bucketName)
end
inv:set_list(INV_MAIN, mainList)
logistica.on_supplier_change(pos) -- notify we got new item (well probably)
logistica.update_cache_at_pos(pos, LOG_CACHE_SUPPLIER) -- notify we got new item (well probably)
end
-- return a table of {remaining = int, erroMsg = ""}, indicating how many items remain to be fulfilled, and an optional error msg if any

View File

@ -4,6 +4,7 @@ logistica.injectors = {}
logistica.requesters = {}
logistica.suppliers = {}
logistica.craftsups = {}
logistica.bucketemptiers = {}
logistica.bucketfillers = {}
logistica.mass_storage = {}
logistica.item_storage = {}
@ -23,6 +24,7 @@ function logistica.is_machine(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_reservoir(name) or logistica.is_bucket_filler(name)
or logistica.is_bucket_emptier(name)
end
function logistica.is_cable(name)
@ -76,3 +78,7 @@ end
function logistica.is_bucket_filler(name)
return logistica.bucketfillers[name] ~= nil
end
function logistica.is_bucket_emptier(name)
return logistica.bucketemptiers[name] ~= nil
end

View File

@ -21,3 +21,4 @@ dofile(path.."/synchronizer.lua")
dofile(path.."/reservoir.lua")
dofile(path.."/lava_furnace_fueler.lua")
dofile(path.."/bucket_filler.lua")
dofile(path.."/bucket_emptier.lua")

View File

@ -187,6 +187,7 @@ local function recursive_scan_for_nodes_for_controller(network, positionHashes,
or logistica.is_crafting_supplier(otherName)
or logistica.is_vaccuum_supplier(otherName)
or logistica.is_bucket_filler(otherName)
or logistica.is_bucket_emptier(otherName)
then
network.suppliers[otherHash] = true
valid = true

View File

@ -16,6 +16,7 @@ end
-- returns the new stack to replace the empty bucket given, or nil if not successful
function logistica.fill_bucket_from_network(network, bucketItemStack, liquidName)
if not logistica.reservoir_is_empty_bucket(bucketItemStack:get_name()) then return nil end
local lowestReservoirPos = nil
local lowestReservoirLvl = 999999
for hash, _ in pairs(network.reservoirs or {}) do
@ -39,6 +40,8 @@ end
-- returns the new stack to replace the filled bucket given, or nil if not successful
function logistica.empty_bucket_into_network(network, bucketItemStack)
if not logistica.reservoir_is_full_bucket(bucketItemStack:get_name()) then return nil end
local bucketName = bucketItemStack:get_name()
local liquidName = logistica.reservoir_get_liquid_name_for_bucket(bucketName)
@ -109,7 +112,10 @@ function logistica.take_stack_from_suppliers(stackToTake, network, collectorFunc
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
if logistica.is_supplier(nodeName)
or logistica.is_vaccuum_supplier(nodeName)
or logistica.is_bucket_emptier(nodeName)
then
remaining = logistica.take_item_from_supplier(pos, takeStack, network, collectorFunc, useMetadata, dryRun)
elseif logistica.is_crafting_supplier(nodeName) then
remaining = logistica.take_item_from_crafting_supplier(pos, takeStack, network, collectorFunc, useMetadata, dryRun, depth)

View File

@ -1,29 +1,35 @@
local TIMER_DURATION_SHORT = 1.0
local TIMER_DURATION_LONG = 3.0
local META_REQUESTER_LISTNAME = "demtarlist"
local TARGET_NODES_REQUIRING_TIMER = {}
TARGET_NODES_REQUIRING_TIMER["default:furnace"] = true
TARGET_NODES_REQUIRING_TIMER["mcl_furnaces:furnace"] = true
TARGET_NODES_REQUIRING_TIMER["mcl_furnaces:blast_furnace"] = true
TARGET_NODES_REQUIRING_TIMER["mcl_furnaces:smoker"] = true
TARGET_NODES_REQUIRING_TIMER["logistica:lava_furnace"] = true
TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve0"] = true
TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve1"] = true
TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve2"] = true
TARGET_NODES_REQUIRING_TIMER["gravelsieve:auto_sieve3"] = true
TARGET_NODES_REQUIRING_TIMER["techachge:ta2_grinder_pas"] = true
TARGET_NODES_REQUIRING_TIMER["techachge:ta3_grinder_pas"] = true
TARGET_NODES_REQUIRING_TIMER["techachge:ta4_grinder_pas"] = true
TARGET_NODES_REQUIRING_TIMER["techachge:ta2_gravelsieve_pas"] = true
TARGET_NODES_REQUIRING_TIMER["techachge:ta3_gravelsieve_pas"] = true
TARGET_NODES_REQUIRING_TIMER["techachge:ta4_gravelsieve_pas"] = true
TARGET_NODES_REQUIRING_TIMER["tubelub_addons1:grinder"] = true
local TARGET_NODES_REQUIRING_TIMER = {
["default:furnace"] = true,
["mcl_furnaces:furnace"] = true,
["mcl_furnaces:blast_furnace"] = true,
["mcl_furnaces:smoker"] = true,
["logistica:lava_furnace"] = true,
["logistica:bucket_emptier"] = true,
["gravelsieve:auto_sieve0"] = true,
["gravelsieve:auto_sieve1"] = true,
["gravelsieve:auto_sieve2"] = true,
["gravelsieve:auto_sieve3"] = true,
["techachge:ta2_grinder_pas"] = true,
["techachge:ta3_grinder_pas"] = true,
["techachge:ta4_grinder_pas"] = true,
["techachge:ta2_gravelsieve_pas"] = true,
["techachge:ta3_gravelsieve_pas"] = true,
["techachge:ta4_gravelsieve_pas"] = true,
["tubelub_addons1:grinder"] = true,
}
local function get_meta(pos)
logistica.load_position(pos)
return minetest.get_meta(pos)
end
local function is_prohibited_logistica_machine(name)
return logistica.is_machine(name) and not logistica.is_bucket_emptier(name)
end
local function get_max_rate_for_requester(pos)
local node = minetest.get_node_or_nil(pos)
if not node then return 0 end
@ -44,8 +50,8 @@ local function get_valid_requester_and_target_inventory(requesterPos)
local targetPos = logistica.get_requester_target(requesterPos)
if not targetPos then return end
-- exclude logistica machines from this
if logistica.is_machine(minetest.get_node(targetPos).name) then return end
-- exclude logistica machines from this (with exceptions)
if is_prohibited_logistica_machine(minetest.get_node(targetPos).name) then return end
local targetInv = get_meta(targetPos):get_inventory()
if not targetInv:get_list(targetList) then return end
@ -155,10 +161,11 @@ function logistica.on_requester_timer(pos, elapsed)
local targetPos = logistica.get_requester_target(pos)
if not targetPos then return true end
local targetNode = minetest.get_node_or_nil(targetPos)
if not targetNode or logistica.is_machine(targetNode.name) then
if not targetNode or is_prohibited_logistica_machine(targetNode.name) then
logistica.start_node_timer(pos, TIMER_DURATION_LONG)
return false
end
logistica.set_node_tooltip_from_state(pos)
update_requester_actual_request(pos)
if take_requested_items_from_network(pos, network) then

View File

@ -21,6 +21,16 @@ logistica.register_autocrafter("Autocrafter", "autocrafter", {
"logistica_autocrafter.png"
})
--------------------------------
-- Bucket Emptier
--------------------------------
logistica.register_bucket_emptier("Bucket Emptier", "bucket_emptier", {
"logistica_bucket_emptier_top.png",
"logistica_bucket_emptier_top.png",
"logistica_bucket_emptier_side.png",
})
--------------------------------
-- Bucket Filler
--------------------------------

View File

@ -200,3 +200,12 @@ minetest.register_craft({
{L("silverin_plate"), itemstrings.empty_bucket, L("silverin_plate")},
}
})
minetest.register_craft({
output = L("bucket_emptier"),
recipe = {
{L("silverin_plate"), itemstrings.empty_bucket, L("silverin_plate")},
{L("optic_cable"), L("photonizer"), ""},
{L("silverin_plate"), "", L("silverin_plate")},
}
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,29 +1,44 @@
local allowedPull = {}
allowedPull["main"] = true
--allowedPull["src"] = true
allowedPull["dst"] = true
allowedPull["output"] = true
--allowedPull["fuel"] = true
local allowedPull = {
["main"] = true,
--["src"] = true,
["dst"] = true,
["output"] = true,
--["fuel"] = true,
}
local allowedPush = {}
allowedPush["main"] = true
allowedPush["src"] = true
allowedPush["fuel"] = true
allowedPush["input"] = true
allowedPush["shift"] = true
local allowedPush = {
["main"] = true,
["src"] = true,
["fuel"] = true,
["input"] = true,
["shift"] = true,
}
local function get_lists(targetPosition, allowedLists)
-- this MUST be a subset of the allowed push list above
local logisticaBucketEmptierAllowedPush = {
["input"] = true,
}
local function get_lists(targetPosition, usePushLists)
logistica.load_position(targetPosition)
local node = minetest.get_node(targetPosition)
if logistica.is_machine(node.name) then return {} end
local allowedLists = {}
if logistica.is_bucket_emptier(node.name) then
if usePushLists then allowedLists = logisticaBucketEmptierAllowedPush
else return {} end -- can only push to bucket emptier, it acts as a supplier so no need to pull
elseif logistica.is_machine(node.name) then return {}
elseif usePushLists then allowedLists = allowedPush
else allowedLists = allowedPull end
local availableLists = minetest.get_meta(targetPosition):get_inventory():get_lists()
local pushLists = {}
local lists = {}
for name, _ in pairs(availableLists) do
if allowedLists[name] then
table.insert(pushLists, name)
table.insert(lists, name)
end
end
return pushLists
return lists
end
----------------------------------------------------------------
@ -32,12 +47,12 @@ end
-- returns a string of comma separated lists allowed to push to at the given position
function logistica.get_push_lists(targetPosition)
return get_lists(targetPosition, allowedPush)
return get_lists(targetPosition, true)
end
-- returns a string of comma separated lists allowed to pull to at the given position
function logistica.get_pull_lists(targetPosition)
return get_lists(targetPosition, allowedPull)
return get_lists(targetPosition, false)
end
function logistica.is_allowed_pull_list(listName)