diff --git a/api/api.lua b/api/api.lua index 838c044..61765f5 100644 --- a/api/api.lua +++ b/api/api.lua @@ -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") diff --git a/api/bucket_emptier.lua b/api/bucket_emptier.lua new file mode 100644 index 0000000..59e3f8a --- /dev/null +++ b/api/bucket_emptier.lua @@ -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 diff --git a/api/bucket_filler.lua b/api/bucket_filler.lua index bef8ab1..05a52c6 100644 --- a/api/bucket_filler.lua +++ b/api/bucket_filler.lua @@ -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) diff --git a/logic/bucket_emptier.lua b/logic/bucket_emptier.lua new file mode 100644 index 0000000..0fad479 --- /dev/null +++ b/logic/bucket_emptier.lua @@ -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 diff --git a/logic/bucket_filler.lua b/logic/bucket_filler.lua index 13645cf..bf723f4 100644 --- a/logic/bucket_filler.lua +++ b/logic/bucket_filler.lua @@ -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 diff --git a/logic/groups.lua b/logic/groups.lua index 5d7f741..e96c993 100644 --- a/logic/groups.lua +++ b/logic/groups.lua @@ -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 diff --git a/logic/logic.lua b/logic/logic.lua index 102c22a..2b63f7a 100644 --- a/logic/logic.lua +++ b/logic/logic.lua @@ -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") diff --git a/logic/network_logic.lua b/logic/network_logic.lua index 03d2f8b..a5a1c2d 100644 --- a/logic/network_logic.lua +++ b/logic/network_logic.lua @@ -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 diff --git a/logic/network_storage.lua b/logic/network_storage.lua index e0ba528..dd51177 100644 --- a/logic/network_storage.lua +++ b/logic/network_storage.lua @@ -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) diff --git a/logic/requester.lua b/logic/requester.lua index 751aac3..67d0180 100644 --- a/logic/requester.lua +++ b/logic/requester.lua @@ -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 diff --git a/registration/machines_api_reg.lua b/registration/machines_api_reg.lua index ea041f4..25bc6fe 100644 --- a/registration/machines_api_reg.lua +++ b/registration/machines_api_reg.lua @@ -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 -------------------------------- diff --git a/registration/node_recipes.lua b/registration/node_recipes.lua index d96ea9d..0947b81 100644 --- a/registration/node_recipes.lua +++ b/registration/node_recipes.lua @@ -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")}, + } +}) diff --git a/textures/logistica_bucket_emptier_side.png b/textures/logistica_bucket_emptier_side.png new file mode 100644 index 0000000..f5d3d2a Binary files /dev/null and b/textures/logistica_bucket_emptier_side.png differ diff --git a/textures/logistica_bucket_emptier_top.png b/textures/logistica_bucket_emptier_top.png new file mode 100644 index 0000000..3f8742e Binary files /dev/null and b/textures/logistica_bucket_emptier_top.png differ diff --git a/util/ui_logic.lua b/util/ui_logic.lua index 48ec458..d7a1e44 100644 --- a/util/ui_logic.lua +++ b/util/ui_logic.lua @@ -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)