From 342671200645a0c0ae17b57a2119806b0e877752 Mon Sep 17 00:00:00 2001 From: Joachim Stolberg Date: Fri, 2 Sep 2022 21:12:25 +0200 Subject: [PATCH] Change behavior of push_items function --- basic_machines/distributor.lua | 13 +- basic_machines/flow_limiter.lua | 195 +++++++++++++++++++++++++ basic_machines/itemsource.lua | 14 +- basic_machines/pusher.lua | 9 +- basic_machines/ta4_chest.lua | 17 +-- basis/command.lua | 69 +++------ basis/conf_inv.lua | 7 +- init.lua | 2 + logic/detector.lua | 23 ++- teleport/teleport_tube.lua | 5 +- textures/techage_appl_flow_limiter.png | Bin 0 -> 286 bytes 11 files changed, 278 insertions(+), 76 deletions(-) create mode 100644 basic_machines/flow_limiter.lua create mode 100644 textures/techage_appl_flow_limiter.png diff --git a/basic_machines/distributor.lua b/basic_machines/distributor.lua index 66dd51c..44785e9 100644 --- a/basic_machines/distributor.lua +++ b/basic_machines/distributor.lua @@ -277,10 +277,17 @@ local function push_item(pos, base_filter, itemstack, num_items, nvm) num_of_trials = num_of_trials + 1 local push_dir = filter[idx] local num_to_push = math.min(amount, num_items - num_pushed) - if techage.push_items(pos, push_dir, itemstack:peek_item(num_to_push)) then - num_pushed = num_pushed + num_to_push - nvm.port_counter[push_dir] = (nvm.port_counter[push_dir] or 0) + num_to_push + local leftover = techage.push_items(pos, push_dir, itemstack:peek_item(num_to_push)) + local pushed + if not leftover then + pushed = 0 + elseif leftover ~= true then + pushed = num_to_push - leftover:get_count() + else -- leftover == true + pushed = num_to_push end + num_pushed = num_pushed + pushed + nvm.port_counter[push_dir] = (nvm.port_counter[push_dir] or 0) + pushed -- filter start offset idx = idx + 1 if idx > num_ports then diff --git a/basic_machines/flow_limiter.lua b/basic_machines/flow_limiter.lua new file mode 100644 index 0000000..9a5be24 --- /dev/null +++ b/basic_machines/flow_limiter.lua @@ -0,0 +1,195 @@ +--[[ + + TechAge + ======= + + Copyright (C) 2019-2022 Joachim Stolberg + + AGPL v3 + See LICENSE.txt for more information + + TA3/TA4 Item Flow Limiter + +]]-- + +-- for lazy programmers +local M = minetest.get_meta +local S = techage.S + +-- Consumer Related Data +local CRD = function(pos) return (minetest.registered_nodes[techage.get_node_lvm(pos).name] or {}).consumer end +local Tube = techage.Tube + +local STANDBY_TICKS = 8 +local CYCLE_TIME = 8 + +local function formspec(self, pos, nvm) + return "size[6,3]" .. + "box[0,-0.1;5.8,0.5;#c6e8ff]" .. + "label[0.2,-0.1;" .. minetest.colorize("#000000", S("Item Flow Limiter")) .. "]" .. + "field[0.3,1.2;3.3,1;number;" .. S("Number of items") .. ";" .. (nvm.limit or 0) .. "]" .. + "button[3.5,0.9;2.5,1;store;" .. S("Store") .. "]" .. + "image_button[2.5,2;1,1;".. self:get_state_button_image(nvm) .. ";state_button;]" .. + "tooltip[2.5,2;1,1;" .. self:get_state_tooltip(nvm) .. "]" +end + +local function keep_running(pos, elapsed) + local nvm = techage.get_nvm(pos) + CRD(pos).State:is_active(nvm) +end + +local function on_receive_fields(pos, formname, fields, player) + if minetest.is_protected(pos, player:get_player_name()) then + return + end + local nvm = techage.get_nvm(pos) + + if fields.number and fields.store then + nvm.limit = tonumber(fields.number) or 0 + nvm.num_items = 0 + CRD(pos).State:stop(pos, nvm) + end + CRD(pos).State:state_button_event(pos, nvm, fields) + M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm)) +end + +local function can_start(pos, nvm, state) + nvm.num_items = 0 + return true +end + +local tiles = {} +-- '#' will be replaced by the stage number +-- '{power}' will be replaced by the power PNG +tiles.pas = { + "techage_filling_ta#.png^techage_frame_ta#_top.png^techage_appl_arrow.png", + "techage_filling_ta#.png^techage_frame_ta#_bottom.png^techage_appl_arrow.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_outp.png", + "techage_filling_ta#.png^techage_frame_ta#.png^techage_appl_inp.png", + "techage_filling_ta#.png^techage_appl_flow_limiter.png^techage_frame_ta#.png", + "techage_filling_ta#.png^techage_appl_flow_limiter.png^techage_frame_ta#.png", +} + +tiles.act = tiles.pas + +local tubing = { + -- push item through until limit is reached + on_push_item = function(pos, in_dir, stack) + print("on_push_item", stack:get_name(), stack:get_count()) + local nvm = techage.get_nvm(pos) + local count = math.min(stack:get_count(), (nvm.limit or 0) - (nvm.num_items or 0)) + if nvm.techage_state == techage.RUNNING and count > 0 and in_dir == M(pos):get_int("push_dir") then + local leftover = techage.safe_push_items(pos, in_dir, ItemStack({name = stack:get_name(), count = count})) + + local num_pushed + if not leftover then + num_pushed = 0 + elseif leftover == true then + num_pushed = count + else + num_pushed = count - leftover:get_count() + end + + if num_pushed == 0 then + return false + else + nvm.num_items = (nvm.num_items or 0) + num_pushed + if nvm.num_items == nvm.limit then + CRD(pos).State:stop(pos, nvm) + end + stack:set_count(stack:get_count() - num_pushed) + return stack + end + end + return false + end, + is_pusher = true, -- is a pulling/pushing node + + on_recv_message = function(pos, src, topic, payload) + if topic == "set" then -- set limit + local nvm = techage.get_nvm(pos) + CRD(pos).State:stop(pos, nvm) + nvm.limit = tonumber(payload) or 0 + nvm.num_items = 0 + M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm)) + return true + elseif topic == "count" then + local nvm = techage.get_nvm(pos) + return nvm.num_items or 0 + else + return CRD(pos).State:on_receive_message(pos, topic, payload) + end + end, + on_beduino_receive_cmnd = function(pos, src, topic, payload) + if topic == 68 and payload then -- set limit + local nvm = techage.get_nvm(pos) + CRD(pos).State:stop(pos, nvm) + nvm.limit = payload[1] or 0 + nvm.num_items = 0 + M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm)) + return 0 + else + return CRD(pos).State:on_beduino_receive_cmnd(pos, topic, payload) + end + end, + on_beduino_request_data = function(pos, src, topic, payload) + if topic == 150 then -- Request count + local nvm = techage.get_nvm(pos) + return 0, {nvm.num_items or 0} + else + return CRD(pos).State:on_beduino_request_data(pos, topic, payload) + end + end, +} + +local node_name_ta2, node_name_ta3, node_name_ta4 = + techage.register_consumer("item_flow_limiter", S("Item Flow Limiter"), tiles, { + cycle_time = CYCLE_TIME, + standby_ticks = STANDBY_TICKS, + formspec = formspec, + tubing = tubing, + can_start = can_start, + after_place_node = function(pos, placer) + local meta = M(pos) + local node = minetest.get_node(pos) + meta:set_int("pull_dir", techage.side_to_outdir("L", node.param2)) + meta:set_int("push_dir", techage.side_to_outdir("R", node.param2)) + local nvm = techage.get_nvm(pos) + M(pos):set_string("formspec", formspec(CRD(pos).State, pos, nvm)) + end, + ta_rotate_node = function(pos, node, new_param2) + Tube:after_dig_node(pos) + minetest.swap_node(pos, {name = node.name, param2 = new_param2}) + Tube:after_place_node(pos) + local meta = M(pos) + meta:set_int("pull_dir", techage.side_to_outdir("L", new_param2)) + meta:set_int("push_dir", techage.side_to_outdir("R", new_param2)) + end, + on_receive_fields = on_receive_fields, + node_timer = keep_running, + on_rotate = screwdriver.disallow, + + groups = {choppy=2, cracky=2, crumbly=2}, + is_ground_content = false, + sounds = default.node_sound_wood_defaults(), + num_items = {0,2,6,12}, + tube_sides = {L=1, R=1}, + }, {false, false, true, true}) + +minetest.register_craft({ + output = node_name_ta3, + recipe = { + {"", "techage:iron_ingot", ""}, + {"techage:baborium_ingot", node_name_ta2, "techage:usmium_nuggets"}, + {"", "techage:vacuum_tube", ""}, + }, +}) + +minetest.register_craft({ + output = node_name_ta4, + recipe = { + {"", "techage:iron_ingot", ""}, + {"", node_name_ta3, ""}, + {"", "techage:ta4_wlanchip", ""}, + }, +}) diff --git a/basic_machines/itemsource.lua b/basic_machines/itemsource.lua index ae28a40..cb93602 100644 --- a/basic_machines/itemsource.lua +++ b/basic_machines/itemsource.lua @@ -73,11 +73,17 @@ minetest.register_node("techage:itemsource", { local stack = inv:get_stack('main', 1) if stack:get_count() > 0 then local push_dir = meta:get_int("push_dir") - if techage.push_items(pos, push_dir, stack) then - local cnt = meta:get_int("counter") + stack:get_count() - meta:set_int("counter", cnt) - meta:set_string("infotext", "Techage Item Source: "..cnt) + local leftover = techage.push_items(pos, push_dir, stack) + local pushed + if not leftover then + pushed = 0 + elseif leftover ~= true then + pushed = stack:get_count() - leftover:get_count() + else -- leftover == true + pushed = stack:get_count() end + meta:set_int("counter", pushed) + meta:set_string("infotext", "Techage Item Source: "..pushed) end return true end, diff --git a/basic_machines/pusher.lua b/basic_machines/pusher.lua index bc5d147..570a59d 100644 --- a/basic_machines/pusher.lua +++ b/basic_machines/pusher.lua @@ -93,11 +93,18 @@ local function pushing(pos, crd, meta, nvm) local num = nvm.item_count or nvm.num_items or crd.num_items local items = techage.pull_items(pos, pull_dir, num, nvm.item_name) if items ~= nil then - if techage.push_items(pos, push_dir, items) ~= true then + local leftover = techage.push_items(pos, push_dir, items) + print("leftover", dump(leftover)) + if not leftover then -- place item back techage.unpull_items(pos, pull_dir, items) crd.State:blocked(pos, nvm) return + elseif leftover ~= true then + -- place item back + techage.unpull_items(pos, pull_dir, leftover) + crd.State:blocked(pos, nvm) + return end if nvm.item_count then -- remote job? nvm.item_count = nil diff --git a/basic_machines/ta4_chest.lua b/basic_machines/ta4_chest.lua index 49bdb83..041228d 100644 --- a/basic_machines/ta4_chest.lua +++ b/basic_machines/ta4_chest.lua @@ -18,7 +18,7 @@ local M = minetest.get_meta local S = techage.S local DESCRIPTION = S("TA4 8x2000 Chest") -local STACK_SIZE = 2000 +local STACK_SIZE = 200 local function gen_stack(inv, idx) inv[idx] = {name = "", count = 0} @@ -133,7 +133,7 @@ local function doesItemStackMatchNvmStack(itemstack, nvmstack) -- The following seems to be the most reliable approach to compare meta. local nvm_meta = ItemStack():get_meta() - nvm_meta:from_table(minetest.deserialize(nvmstack.meta)) + nvm_meta:from_table(minetest.deserialize(nvmstack.meta or "")) if not nvm_meta:equals(itemstack:get_meta()) then return false, "Mismatching meta" end @@ -197,7 +197,7 @@ local function take_from_chest(pos, idx, output_stack, max_total_count, keep_ass count = count, wear = nvm_stack.wear, })) - output_stack:get_meta():from_table(minetest.deserialize(nvm_stack.meta)) + output_stack:get_meta():from_table(minetest.deserialize(nvm_stack.meta or "")) nvm_stack.count = nvm_stack.count - count if nvm_stack.count == 0 then gen_stack(nvm.inventory or {}, idx) @@ -210,21 +210,14 @@ local function tube_add_to_chest(pos, input_stack) local nvm = techage.get_nvm(pos) nvm.inventory = nvm.inventory or {} - -- Backup some values needed for restoring the old - -- state if items can't fully be added to chest. - local orig_count = input_stack:get_count() - local backup = table.copy(nvm.inventory) - for idx = 1,8 do input_stack:take_item(add_to_chest(pos, input_stack, idx)) end if input_stack:get_count() > 0 then - nvm.inventory = backup -- Restore old nvm inventory - input_stack:set_count(orig_count) -- Restore input_stack - return false -- No items were added to chest + return input_stack -- Not all items were added to chest else - return true -- Items were added successfully + return true -- All items were added end end diff --git a/basis/command.lua b/basis/command.lua index 11246a5..ff08086 100644 --- a/basis/command.lua +++ b/basis/command.lua @@ -460,7 +460,7 @@ function techage.push_items(pos, out_dir, stack, idx) minetest.add_item(npos, stack) return true end - return false + return stack end -- Check for recursion and too long distances @@ -485,7 +485,7 @@ function techage.safe_push_items(pos, out_dir, stack, idx) end end end - return false + return stack end function techage.unpull_items(pos, out_dir, stack) @@ -496,37 +496,6 @@ function techage.unpull_items(pos, out_dir, stack) return false end -------------------------------------------------------------------- --- Client side Push/Pull item functions for hopper like nodes --- (nodes with no tube support) -------------------------------------------------------------------- - -function techage.neighbour_pull_items(pos, out_dir, num) - local res, npos, in_dir, name = get_next_node(pos, out_dir) - if res and NodeDef[name] and NodeDef[name].on_pull_item then - return NodeDef[name].on_pull_item(npos, in_dir, num) - end -end - -function techage.neighbour_push_items(pos, out_dir, stack) - local res, npos, in_dir, name = get_next_node(pos, out_dir) - if res and NodeDef[name] and NodeDef[name].on_push_item then - return NodeDef[name].on_push_item(npos, in_dir, stack) - elseif name == "air" then - minetest.add_item(npos, stack) - return true - end - return false -end - -function techage.neighbour_unpull_items(pos, out_dir, stack) - local res, npos, in_dir, name = get_next_node(pos, out_dir) - if res and NodeDef[name] and NodeDef[name].on_unpull_item then - return NodeDef[name].on_unpull_item(npos, in_dir, stack) - end - return false -end - ------------------------------------------------------------------- -- Server side helper functions ------------------------------------------------------------------- @@ -554,23 +523,33 @@ function techage.get_items(pos, inv, listname, num) return nil end --- Put the given stack into the given ItemList. --- Function returns false if ItemList is full. +-- Put the given stack into the given ItemList/inventory. +-- Function returns: +-- - true, if all items are moved +-- - false, if no item is moved +-- - leftover, if less than all items are moved +-- (true/false is the legacy mode and can't be removed) function techage.put_items(inv, listname, item, idx) + local leftover if idx and inv and idx <= inv:get_size(listname) then local stack = inv:get_stack(listname, idx) - if stack:item_fits(item) then - stack:add_item(item) - inv:set_stack(listname, idx, stack) - return true - end + leftover = stack:add_item(item) + inv:set_stack(listname, idx, stack) + elseif inv then + leftover = inv:add_item(listname, item) else - if inv and inv:room_for_item(listname, item) then - inv:add_item(listname, item) - return true - end + return false end - return false + + local cnt = leftover:get_count() + if cnt == item:get_count() then + return false + elseif cnt == 0 then + return true + else + return leftover + end + end -- Return "full", "loaded", or "empty" depending diff --git a/basis/conf_inv.lua b/basis/conf_inv.lua index f64aca6..376d05c 100644 --- a/basis/conf_inv.lua +++ b/basis/conf_inv.lua @@ -79,11 +79,12 @@ function inv_lib.put_items(pos, inv, listname, item, stacks, idx) for _, i in ipairs(stacks or {}) do if not idx or idx == i then local stack = inv:get_stack(listname, i) - if stack:item_fits(item) then - stack:add_item(item) - inv:set_stack(listname, i, stack) + local leftover = stack:add_item(item) + inv:set_stack(listname, i, stack) + if leftover:get_count() == 0 then return true end + return leftover end end return false diff --git a/init.lua b/init.lua index 3863a85..58b337e 100644 --- a/init.lua +++ b/init.lua @@ -198,6 +198,7 @@ dofile(MP.."/basic_machines/recycler.lua") dofile(MP.."/basic_machines/concentrator.lua") dofile(MP.."/basic_machines/recipeblock.lua") dofile(MP.."/basic_machines/ta5_chest.lua") +dofile(MP.."/basic_machines/flow_limiter.lua") -- Liquids II dofile(MP.."/liquids/tank.lua") @@ -316,6 +317,7 @@ if techage.recipe_checker_enabled then end dofile(MP.."/.test/sink.lua") dofile(MP.."/.test/testblock.lua") +dofile(MP.."/.test/minichest.lua") -- Solar dofile(MP.."/solar/minicell.lua") diff --git a/logic/detector.lua b/logic/detector.lua index a7f66d0..937b49a 100644 --- a/logic/detector.lua +++ b/logic/detector.lua @@ -249,12 +249,13 @@ minetest.register_craft({ techage.register_node({"techage:ta3_detector_off", "techage:ta3_detector_on"}, { on_push_item = function(pos, in_dir, stack) - if techage.safe_push_items(pos, in_dir, stack) then + local leftover = techage.safe_push_items(pos, in_dir, stack) + if leftover then local inv = minetest.get_inventory({type = "node", pos = pos}) if not inv or inv:is_empty("cfg") or inv:contains_item("cfg", ItemStack(stack:get_name())) then switch_on(pos) end - return true + return leftover end return false end, @@ -263,11 +264,19 @@ techage.register_node({"techage:ta3_detector_off", "techage:ta3_detector_on"}, { techage.register_node({"techage:ta4_detector_off", "techage:ta4_detector_on"}, { on_push_item = function(pos, in_dir, stack) - if techage.safe_push_items(pos, in_dir, stack) then - switch_on(pos) - local nvm = techage.get_nvm(pos) - nvm.counter = (nvm.counter or 0) + stack:get_count() - return true + local leftover = techage.safe_push_items(pos, in_dir, stack) + if leftover then + local inv = minetest.get_inventory({type = "node", pos = pos}) + if not inv or inv:is_empty("cfg") or inv:contains_item("cfg", ItemStack(stack:get_name())) then + switch_on(pos) + local nvm = techage.get_nvm(pos) + if leftover == true then + nvm.counter = (nvm.counter or 0) + stack:get_count() + else + nvm.counter = (nvm.counter or 0) + stack:get_count() - leftover:get_count() + end + end + return leftover end return false end, diff --git a/teleport/teleport_tube.lua b/teleport/teleport_tube.lua index d1e278a..2f3c993 100644 --- a/teleport/teleport_tube.lua +++ b/teleport/teleport_tube.lua @@ -158,11 +158,14 @@ techage.register_node({"techage:ta5_tele_tube"}, { local rmt_nvm = techage.get_nvm(rmt_pos) if techage.is_operational(rmt_nvm) then local tube_dir = M(rmt_pos):get_int("tube_dir") - if techage.push_items(rmt_pos, tube_dir, stack) then + local leftover = techage.push_items(rmt_pos, tube_dir, stack) + -- Moved any items + if leftover then State:keep_running(pos, nvm, COUNTDOWN_TICKS) State:keep_running(rmt_pos, rmt_nvm, COUNTDOWN_TICKS) return true end + return leftover else State:blocked(pos, nvm, S("Remote block error")) end diff --git a/textures/techage_appl_flow_limiter.png b/textures/techage_appl_flow_limiter.png new file mode 100644 index 0000000000000000000000000000000000000000..8ef9db929b36635974f4002c6cdb28b49a3d86dc GIT binary patch literal 286 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?O3?zSk_}l@c*aCb)T-^(N3=IsNWq4NtMHowh z{DK)Ap4~_Ta*lbrIEHu}e|y=GuUSEaEkTOit?xjfg_IdzpWMO48J7=cPbhieb!j1A z+kO+-C&yW?^Zns$zV9IS-nMnc%Ab=p67-r`ZW)<0XdGsJ$Z|w*8_yfYYepG~HIIX4 z^oFzeRr?Cq^B!C#!_l$Nig%>lDI& i-L(#{e=%!Tk)3X7PY&<>@UK80F?hQAxvX