Change behavior of push_items function
This commit is contained in:
parent
1182912724
commit
3426712006
@ -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
|
||||
|
195
basic_machines/flow_limiter.lua
Normal file
195
basic_machines/flow_limiter.lua
Normal file
@ -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", ""},
|
||||
},
|
||||
})
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
leftover = stack:add_item(item)
|
||||
inv:set_stack(listname, idx, stack)
|
||||
return true
|
||||
end
|
||||
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
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
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
|
||||
|
@ -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)
|
||||
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
|
||||
|
2
init.lua
2
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")
|
||||
|
@ -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
|
||||
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()
|
||||
return true
|
||||
else
|
||||
nvm.counter = (nvm.counter or 0) + stack:get_count() - leftover:get_count()
|
||||
end
|
||||
end
|
||||
return leftover
|
||||
end
|
||||
return false
|
||||
end,
|
||||
|
@ -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
|
||||
|
BIN
textures/techage_appl_flow_limiter.png
Normal file
BIN
textures/techage_appl_flow_limiter.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 286 B |
Loading…
Reference in New Issue
Block a user