From ca4837f1c662b955a933e4d9219dc028c90b0319 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 17:18:53 +0100 Subject: [PATCH 01/75] changelog.txt: back-entries for new flow logic work --- changelog.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/changelog.txt b/changelog.txt index 251df29..d766fc0 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,26 @@ Changelog --------- +2017-09-27 (thetaepsilon) +Start of new flow logic re-implementation. +This mode is current *very* incomplete, and requires a per-world setting to enable. +Adds a pressure value stored in all pipe node metadata, and a mechanism to balance it out with nearby nodes on ABM trigger. +Currently, this inhibits the old behaviour when enabled, and (again WHEN ENABLED) breaks pretty much everything but normal pipes, spigots and pumps. +For this reason it is far from being intended as the default for some time to come yet. +What *does* work: ++ Pumps will try to take in water (and removes it!) as long as internal pressure does not exceed a threshold. + - a TODO is to make this pressure threshold configurable. ++ Pipes will balance this pressure between themselves, and will slowly average out over time. ++ Spigots will try to make the node beneath them a water source if the pressure is great enough and the existing node is flowing water or air. + - This is admittedly of fairly limited use with default water mechanics; those looking for more realistic mechanics might want to look at the dynamic_liquid mod, though that mod comes with it's own caveats (most notably drastic changes to previous worlds...). +What *does not* work: ++ Flow sensors, valves. Valves in particular currently do not function as a barrier to water's path under the experimental logic. + - TODO: internal code to allow this to be overriden. + + + +*seems this hasn't been updated in a while* + 2013-01-13: Tubes can transport items now! Namely, I added Novatux/Nore's item transport mod as a default part of this mod, to make tubes do something useful! Thanks to Nore and RealBadAngel for the code contributions! From 10221c6c153e4d20bf1d289fe218d29477400a4d Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 17:32:09 +0100 Subject: [PATCH 02/75] add TODO list extracted from new_flow_logic changelog entries --- todo/new_flow_logic.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 todo/new_flow_logic.txt diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt new file mode 100644 index 0000000..acd6d1a --- /dev/null +++ b/todo/new_flow_logic.txt @@ -0,0 +1,6 @@ +-- Per-world configuration of pump thresholds +This should be relatively trivial to do, just a case of adding another property to the pipeworks global that can be set per-world with pipeworks_settings.txt. +This does not appear to be that big a deal right now, as the internal threshold can always be changed. + +-- Internal code to the effect of "is_node_flowable()" +This is basically to implement valves - currently the flow logic will happily balance pipes with neighbour nodes that just happen to have the pressure property in their metadata. From 40eeaac2ecb25dbc55f7315342e74723d6248534 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 20:16:00 +0100 Subject: [PATCH 03/75] internal refactoring of flowable node registration in preparation for enhanced flow checking logic --- flowable_node_registry.lua | 59 ++++++++++++++++++++++++++++++++++++ flowable_nodes_add_pipes.lua | 45 +++++++++++++++++++++++++++ init.lua | 6 +++- new_flow_logic.lua | 15 ++++----- register_flow_logic.lua | 40 +++++++++++------------- 5 files changed, 133 insertions(+), 32 deletions(-) create mode 100644 flowable_node_registry.lua create mode 100644 flowable_nodes_add_pipes.lua diff --git a/flowable_node_registry.lua b/flowable_node_registry.lua new file mode 100644 index 0000000..def9649 --- /dev/null +++ b/flowable_node_registry.lua @@ -0,0 +1,59 @@ +-- registration code for nodes under new flow logic +-- written 2017 by thetaepsilon + +pipeworks.flowables = {} +pipeworks.flowables.list = {} +pipeworks.flowables.list.all = {} +-- pipeworks.flowables.list.nodenames = {} + +-- simple flowables - balance pressure in any direction +pipeworks.flowables.list.simple = {} +pipeworks.flowables.list.simple_nodenames = {} + +-- simple intakes - try to absorb any adjacent water nodes +pipeworks.flowables.inputs = {} +pipeworks.flowables.inputs.list = {} +pipeworks.flowables.inputs.nodenames = {} + +-- registration functions +pipeworks.flowables.register = {} +local register = pipeworks.flowables.register + +-- some sanity checking for passed args, as this could potentially be made an external API eventually +local checkexists = function(nodename) + if type(nodename) ~= "string" then error("pipeworks.flowables nodename must be a string!") end + return pipeworks.flowables.list.all[nodename] +end + +local insertbase = function(nodename) + if checkexists(nodename) then error("pipeworks.flowables duplicate registration!") end + pipeworks.flowables.list.all[nodename] = true + -- table.insert(pipeworks.flowables.list.nodenames, nodename) +end + +-- Register a node as a simple flowable. +-- Simple flowable nodes have no considerations for direction of flow; +-- A cluster of adjacent simple flowables will happily average out in any direction. +-- This does *not* register the ABM, as that is done in register_flow_logic.lua; +-- this is so that the new flow logic can remain optional during development. +register.simple = function(nodename) + insertbase(nodename) + pipeworks.flowables.list.simple[nodename] = true + table.insert(pipeworks.flowables.list.simple_nodenames, nodename) +end + +local checkbase = function(nodename) + if not checkexists(nodename) then error("pipeworks.flowables node doesn't exist as a flowable!") end +end + +-- Register a node as a simple intake. +-- See new_flow_logic for the details of this. +-- Expects node to be registered as a flowable (is present in flowables.list.all), +-- so that water can move out of it. +-- maxpressure is the maximum pipeline pressure that this node can drive. +-- possible WISHME here: technic-driven high-pressure pumps +register.intake_simple = function(nodename, maxpressure) + checkbase(nodename) + pipeworks.flowables.inputs.list[nodename] = { maxpressure=maxpressure } + table.insert(pipeworks.flowables.inputs.nodenames, nodename) +end diff --git a/flowable_nodes_add_pipes.lua b/flowable_nodes_add_pipes.lua new file mode 100644 index 0000000..e681619 --- /dev/null +++ b/flowable_nodes_add_pipes.lua @@ -0,0 +1,45 @@ +-- conditional registration of pipe nodes for the new pipe logic, depending on enable flags. +-- otherwise register_flow_logic.lua would be attempting to register ABMs for non-existant nodes. +-- written 2017 by thetaepsilon + + + +-- global values and thresholds for water behaviour +-- TODO: add some way of setting this per-world +local thresholds = {} +-- limit on pump pressure - will not absorb more than can be taken +thresholds.pump_pressure = 2 + + + +local pipes_full_nodenames = pipeworks.pipes_full_nodenames +local pipes_empty_nodenames = pipeworks.pipes_empty_nodenames + +local register = pipeworks.flowables.register + + + +-- FIXME: DRY principle for names, move this to devices.lua? +-- FIXME: all devices still considered simple +local pump_on = "pipeworks:pump_on" +local pump_off = "pipeworks:pump_off" +local spigot_off = "pipeworks:spigot" +local spigot_on = "pipeworks:spigot_pouring" + +if pipeworks.enable_pipes then + for _, pipe in ipairs(pipes_full_nodenames) do + register.simple(pipe) + end + for _, pipe in ipairs(pipes_empty_nodenames) do + register.simple(pipe) + end + + if pipeworks.enable_pipe_devices then + register.simple(pump_off) + register.simple(pump_on) + register.simple(spigot_on) + register.simple(spigot_off) + + register.intake_simple(pump_on, thresholds.pump_pressure) + end +end diff --git a/init.lua b/init.lua index 470db2e..a64be4e 100644 --- a/init.lua +++ b/init.lua @@ -115,12 +115,16 @@ dofile(pipeworks.modpath.."/filter-injector.lua") dofile(pipeworks.modpath.."/trashcan.lua") dofile(pipeworks.modpath.."/wielder.lua") +-- note that pipes still don't appear until registered in the files below this one, so can still be turned off +dofile(pipeworks.modpath.."/flowable_node_registry.lua") + if pipeworks.enable_pipes then dofile(pipeworks.modpath.."/pipes.lua") end if pipeworks.enable_teleport_tube then dofile(pipeworks.modpath.."/teleport_tube.lua") end if pipeworks.enable_pipe_devices then dofile(pipeworks.modpath.."/devices.lua") end --- individual enable flags also checked in register_flow_logic.lua +-- individual enable flags also checked in flowable_nodes_add_pipes.lua if pipeworks.enable_new_flow_logic then dofile(pipeworks.modpath.."/new_flow_logic.lua") + dofile(pipeworks.modpath.."/flowable_nodes_add_pipes.lua") dofile(pipeworks.modpath.."/register_flow_logic.lua") end diff --git a/new_flow_logic.lua b/new_flow_logic.lua index 3fd1bb6..1b4abf4 100644 --- a/new_flow_logic.lua +++ b/new_flow_logic.lua @@ -3,14 +3,6 @@ --- global values and thresholds for water behaviour --- TODO: add some way of setting this per-world -local thresholds = {} --- limit on pump pressure - will not absorb more than can be taken -thresholds.pump_pressure = 2 - - - -- borrowed from above: might be useable to replace the above coords tables local make_coords_offsets = function(pos, include_base) local coords = { @@ -95,9 +87,14 @@ end pipeworks.run_pump_intake = function(pos, node) -- try to absorb nearby water nodes, but only up to limit. -- NB: check_for_liquids_v2 handles zero or negative from the following subtraction + + local properties = pipeworks.flowables.inputs.list[node.name] + local maxpressure = properties.maxpressure + local meta = minetest.get_meta(pos) local currentpressure = meta:get_float(label_pressure) - local intake_limit = thresholds.pump_pressure - currentpressure + + local intake_limit = maxpressure - currentpressure local actual_intake = pipeworks.check_for_liquids_v2(pos, intake_limit) local newpressure = actual_intake + currentpressure -- debuglog("oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake.." newpressure "..newpressure) diff --git a/register_flow_logic.lua b/register_flow_logic.lua index c9df09c..8580188 100644 --- a/register_flow_logic.lua +++ b/register_flow_logic.lua @@ -1,29 +1,11 @@ -- register new flow logic ABMs -- written 2017 by thetaepsilon -local pipes_full_nodenames = pipeworks.pipes_full_nodenames -local pipes_empty_nodenames = pipeworks.pipes_empty_nodenames - --- run pressure balancing ABM over all water-moving nodes --- FIXME: DRY principle, get this from elsewhere in the code -local pump_on = "pipeworks:pump_on" -local pump_off = "pipeworks:pump_off" -local spigot_off = "pipeworks:spigot" -local spigot_on = "pipeworks:spigot_pouring" - -local pipes_all_nodenames = pipes_full_nodenames -for _, pipe in ipairs(pipes_empty_nodenames) do - table.insert(pipes_all_nodenames, pipe) -end - -if pipeworks.enable_pipe_devices then - table.insert(pipes_all_nodenames, pump_off) - table.insert(pipes_all_nodenames, pump_on) - table.insert(pipes_all_nodenames, spigot_on) - table.insert(pipes_all_nodenames, spigot_off) -end +-- note that checking for feature toggles (because otherwise certain pipes aren't define) +-- is now done by flowable_nodes_add_pipes.lua +--[[ if pipeworks.enable_pipes then minetest.register_abm({ nodenames = pipes_all_nodenames, @@ -34,19 +16,32 @@ if pipeworks.enable_pipes then end }) end +]] +-- flowables.register.simple takes care of creating an array-like table of node names +minetest.register_abm({ + nodenames = pipeworks.flowables.list.simple_nodenames, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + pipeworks.balance_pressure(pos, node) + end +}) if pipeworks.enable_pipe_devices then -- absorb water into pumps if it'll fit minetest.register_abm({ - nodenames = { pump_on }, + nodenames = pipeworks.flowables.inputs.nodenames, interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) pipeworks.run_pump_intake(pos, node) end }) + -- output water from spigots -- add both "on/off" spigots so one can be used to indicate a certain level of fluid. + -- temp. disabled as the node names were moved to flowable_node_add_pipes.lua + --[[ minetest.register_abm({ nodenames = { spigot_on, spigot_off }, interval = 1, @@ -55,4 +50,5 @@ if pipeworks.enable_pipe_devices then pipeworks.run_spigot_output(pos, node) end }) + ]] end From 0251baf692741c5cf3173ff9415c94dbbc3719f3 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 20:47:00 +0100 Subject: [PATCH 04/75] new_flow_logic.lua: move logic functions inside pipeworks.flowlogic sub-table --- new_flow_logic.lua | 13 +++++++++---- register_flow_logic.lua | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/new_flow_logic.lua b/new_flow_logic.lua index 1b4abf4..a65ac23 100644 --- a/new_flow_logic.lua +++ b/new_flow_logic.lua @@ -3,6 +3,11 @@ +local flowlogic = {} +pipeworks.flowlogic = flowlogic + + + -- borrowed from above: might be useable to replace the above coords tables local make_coords_offsets = function(pos, include_base) local coords = { @@ -28,7 +33,7 @@ end -- and returns it so that the receptacle can update it's pressure values. -- this should ensure that water blocks aren't vanished from existance. -- will take care of zero or negative-valued limits. -pipeworks.check_for_liquids_v2 = function(pos, limit) +flowlogic.check_for_liquids_v2 = function(pos, limit) if not limit then limit = 6 end @@ -50,7 +55,7 @@ end local label_pressure = "pipeworks.water_pressure" local label_haspressure = "pipeworks.is_pressure_node" -pipeworks.balance_pressure = function(pos, node) +flowlogic.balance_pressure = function(pos, node) -- debuglog("balance_pressure() "..node.name.." at "..pos.x.." "..pos.y.." "..pos.z) -- check the pressure of all nearby nodes, and average it out. -- for the moment, only balance neighbour nodes if it already has a pressure value. @@ -84,7 +89,7 @@ end -pipeworks.run_pump_intake = function(pos, node) +flowlogic.run_pump_intake = function(pos, node) -- try to absorb nearby water nodes, but only up to limit. -- NB: check_for_liquids_v2 handles zero or negative from the following subtraction @@ -103,7 +108,7 @@ end -pipeworks.run_spigot_output = function(pos, node) +flowlogic.run_spigot_output = function(pos, node) -- try to output a water source node if there's enough pressure and space below. local meta = minetest.get_meta(pos) local currentpressure = meta:get_float(label_pressure) diff --git a/register_flow_logic.lua b/register_flow_logic.lua index 8580188..3a8df8e 100644 --- a/register_flow_logic.lua +++ b/register_flow_logic.lua @@ -23,7 +23,7 @@ minetest.register_abm({ interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.balance_pressure(pos, node) + pipeworks.flowlogic.balance_pressure(pos, node) end }) @@ -34,7 +34,7 @@ if pipeworks.enable_pipe_devices then interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.run_pump_intake(pos, node) + pipeworks.flowlogic.run_pump_intake(pos, node) end }) From 8dfbcad949b7751d4ddb56f033d82c0432d2e112 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 22:41:38 +0100 Subject: [PATCH 05/75] register_flow_logic.lua: begin refactoring abm registration to allow use by other mods --- register_flow_logic.lua | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/register_flow_logic.lua b/register_flow_logic.lua index 3a8df8e..f82b8a9 100644 --- a/register_flow_logic.lua +++ b/register_flow_logic.lua @@ -17,15 +17,20 @@ if pipeworks.enable_pipes then }) end ]] --- flowables.register.simple takes care of creating an array-like table of node names -minetest.register_abm({ - nodenames = pipeworks.flowables.list.simple_nodenames, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.flowlogic.balance_pressure(pos, node) - end -}) + +local register_abm_balance = function(nodename) + minetest.register_abm({ + nodenames = { nodename }, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + pipeworks.flowlogic.balance_pressure(pos, node) + end + }) +end +for nodename, _ in pairs(pipeworks.flowables.list.simple) do + register_abm_balance(nodename) +end if pipeworks.enable_pipe_devices then -- absorb water into pumps if it'll fit From 7498a32364fd859d6b735661fc3de4281f75389a Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 22:46:21 +0100 Subject: [PATCH 06/75] new_flow_logic.lua: fix callback crash due to check_for_liquids_v2() being moved to sub-table --- new_flow_logic.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/new_flow_logic.lua b/new_flow_logic.lua index a65ac23..7360668 100644 --- a/new_flow_logic.lua +++ b/new_flow_logic.lua @@ -33,7 +33,7 @@ end -- and returns it so that the receptacle can update it's pressure values. -- this should ensure that water blocks aren't vanished from existance. -- will take care of zero or negative-valued limits. -flowlogic.check_for_liquids_v2 = function(pos, limit) +local check_for_liquids_v2 = function(pos, limit) if not limit then limit = 6 end @@ -49,7 +49,7 @@ flowlogic.check_for_liquids_v2 = function(pos, limit) end return total end - +flowlogic.check_for_liquids_v2 = check_for_liquids_v2 @@ -100,7 +100,7 @@ flowlogic.run_pump_intake = function(pos, node) local currentpressure = meta:get_float(label_pressure) local intake_limit = maxpressure - currentpressure - local actual_intake = pipeworks.check_for_liquids_v2(pos, intake_limit) + local actual_intake = check_for_liquids_v2(pos, intake_limit) local newpressure = actual_intake + currentpressure -- debuglog("oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake.." newpressure "..newpressure) meta:set_float(label_pressure, newpressure) From aaef5eb22b439c3e410942c39726e58c0c041c40 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 22:56:12 +0100 Subject: [PATCH 07/75] register_flow_logic.lua: factor out per-node input ABM registration --- register_flow_logic.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/register_flow_logic.lua b/register_flow_logic.lua index f82b8a9..60fc820 100644 --- a/register_flow_logic.lua +++ b/register_flow_logic.lua @@ -32,16 +32,22 @@ for nodename, _ in pairs(pipeworks.flowables.list.simple) do register_abm_balance(nodename) end -if pipeworks.enable_pipe_devices then - -- absorb water into pumps if it'll fit +local register_abm_input = function(nodename, properties) minetest.register_abm({ - nodenames = pipeworks.flowables.inputs.nodenames, + nodenames = { nodename }, interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) pipeworks.flowlogic.run_pump_intake(pos, node) end }) +end + +if pipeworks.enable_pipe_devices then + -- absorb water into pumps if it'll fit + for nodename, properties in pairs(pipeworks.flowables.inputs.list) do + register_abm_input(nodename, properties) + end -- output water from spigots -- add both "on/off" spigots so one can be used to indicate a certain level of fluid. From afcec82ae336cba3e874f6afd1b4e46e04245f7d Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 23:02:11 +0100 Subject: [PATCH 08/75] register_flow_logic.lua: expose ABM registration functions --- register_flow_logic.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/register_flow_logic.lua b/register_flow_logic.lua index 60fc820..f3e8fbd 100644 --- a/register_flow_logic.lua +++ b/register_flow_logic.lua @@ -3,6 +3,11 @@ +local register = {} +pipeworks.flowlogic.abmregister = register + + + -- note that checking for feature toggles (because otherwise certain pipes aren't define) -- is now done by flowable_nodes_add_pipes.lua --[[ @@ -28,6 +33,7 @@ local register_abm_balance = function(nodename) end }) end +register.balance = register_abm_balance for nodename, _ in pairs(pipeworks.flowables.list.simple) do register_abm_balance(nodename) end @@ -42,6 +48,7 @@ local register_abm_input = function(nodename, properties) end }) end +register.input = register_abm_input if pipeworks.enable_pipe_devices then -- absorb water into pumps if it'll fit From d69941a0ae763d6681ede2185ad88e25b11fead5 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 23:22:04 +0100 Subject: [PATCH 09/75] temporarily move ABM registration out of register_flow_logic.lua to allow refactoring it into flowable registry --- flowable_nodes_add_pipes.lua | 8 ++++++++ init.lua | 2 +- register_flow_logic.lua | 39 ++++++++---------------------------- 3 files changed, 17 insertions(+), 32 deletions(-) diff --git a/flowable_nodes_add_pipes.lua b/flowable_nodes_add_pipes.lua index e681619..6fe8b7e 100644 --- a/flowable_nodes_add_pipes.lua +++ b/flowable_nodes_add_pipes.lua @@ -16,6 +16,7 @@ local pipes_full_nodenames = pipeworks.pipes_full_nodenames local pipes_empty_nodenames = pipeworks.pipes_empty_nodenames local register = pipeworks.flowables.register +local abmregister = pipeworks.flowlogic.abmregister @@ -29,9 +30,11 @@ local spigot_on = "pipeworks:spigot_pouring" if pipeworks.enable_pipes then for _, pipe in ipairs(pipes_full_nodenames) do register.simple(pipe) + abmregister.balance(pipe) end for _, pipe in ipairs(pipes_empty_nodenames) do register.simple(pipe) + abmregister.balance(pipe) end if pipeworks.enable_pipe_devices then @@ -39,7 +42,12 @@ if pipeworks.enable_pipes then register.simple(pump_on) register.simple(spigot_on) register.simple(spigot_off) + abmregister.balance(pump_off) + abmregister.balance(pump_on) + abmregister.balance(spigot_on) + abmregister.balance(spigot_off) register.intake_simple(pump_on, thresholds.pump_pressure) + abmregister.input(pump_on, thresholds.pump_pressure) end end diff --git a/init.lua b/init.lua index a64be4e..d70e4f4 100644 --- a/init.lua +++ b/init.lua @@ -124,8 +124,8 @@ if pipeworks.enable_pipe_devices then dofile(pipeworks.modpath.."/devices.lua") -- individual enable flags also checked in flowable_nodes_add_pipes.lua if pipeworks.enable_new_flow_logic then dofile(pipeworks.modpath.."/new_flow_logic.lua") - dofile(pipeworks.modpath.."/flowable_nodes_add_pipes.lua") dofile(pipeworks.modpath.."/register_flow_logic.lua") + dofile(pipeworks.modpath.."/flowable_nodes_add_pipes.lua") end if pipeworks.enable_redefines then diff --git a/register_flow_logic.lua b/register_flow_logic.lua index f3e8fbd..e7bed6a 100644 --- a/register_flow_logic.lua +++ b/register_flow_logic.lua @@ -8,21 +8,8 @@ pipeworks.flowlogic.abmregister = register --- note that checking for feature toggles (because otherwise certain pipes aren't define) --- is now done by flowable_nodes_add_pipes.lua ---[[ -if pipeworks.enable_pipes then - minetest.register_abm({ - nodenames = pipes_all_nodenames, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.balance_pressure(pos, node) - end - }) -end -]] - +-- register a node name for the pressure balancing ABM. +-- currently this only exists as a per-node function to allow nodes to be registered outside pipeworks. local register_abm_balance = function(nodename) minetest.register_abm({ nodenames = { nodename }, @@ -34,11 +21,10 @@ local register_abm_balance = function(nodename) }) end register.balance = register_abm_balance -for nodename, _ in pairs(pipeworks.flowables.list.simple) do - register_abm_balance(nodename) -end -local register_abm_input = function(nodename, properties) +-- register a node for the pump ABM. +-- maxpressure is the maximum pressure that this pump can drive. +local register_abm_input = function(nodename, maxpressure) minetest.register_abm({ nodenames = { nodename }, interval = 1, @@ -50,16 +36,8 @@ local register_abm_input = function(nodename, properties) end register.input = register_abm_input -if pipeworks.enable_pipe_devices then - -- absorb water into pumps if it'll fit - for nodename, properties in pairs(pipeworks.flowables.inputs.list) do - register_abm_input(nodename, properties) - end - - -- output water from spigots - -- add both "on/off" spigots so one can be used to indicate a certain level of fluid. - -- temp. disabled as the node names were moved to flowable_node_add_pipes.lua - --[[ +-- old spigot ABM code, not yet migrated +--[[ minetest.register_abm({ nodenames = { spigot_on, spigot_off }, interval = 1, @@ -68,5 +46,4 @@ if pipeworks.enable_pipe_devices then pipeworks.run_spigot_output(pos, node) end }) - ]] -end +]] From c3627551b091d27819c242da204ed1e9dd8f15f0 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 23:42:26 +0100 Subject: [PATCH 10/75] move all current new_flow_logic code to dedicated sub-directory --- init.lua | 11 ++++++----- .../abm_register.lua | 0 new_flow_logic.lua => new_flow_logic/abms.lua | 0 .../flowable_node_registry.lua | 0 .../register_local_pipes.lua | 0 5 files changed, 6 insertions(+), 5 deletions(-) rename register_flow_logic.lua => new_flow_logic/abm_register.lua (100%) rename new_flow_logic.lua => new_flow_logic/abms.lua (100%) rename flowable_node_registry.lua => new_flow_logic/flowable_node_registry.lua (100%) rename flowable_nodes_add_pipes.lua => new_flow_logic/register_local_pipes.lua (100%) diff --git a/init.lua b/init.lua index d70e4f4..a081759 100644 --- a/init.lua +++ b/init.lua @@ -115,17 +115,18 @@ dofile(pipeworks.modpath.."/filter-injector.lua") dofile(pipeworks.modpath.."/trashcan.lua") dofile(pipeworks.modpath.."/wielder.lua") +local logicdir = "/new_flow_logic/" -- note that pipes still don't appear until registered in the files below this one, so can still be turned off -dofile(pipeworks.modpath.."/flowable_node_registry.lua") +dofile(pipeworks.modpath..logicdir.."flowable_node_registry.lua") if pipeworks.enable_pipes then dofile(pipeworks.modpath.."/pipes.lua") end if pipeworks.enable_teleport_tube then dofile(pipeworks.modpath.."/teleport_tube.lua") end if pipeworks.enable_pipe_devices then dofile(pipeworks.modpath.."/devices.lua") end --- individual enable flags also checked in flowable_nodes_add_pipes.lua +-- individual enable flags also checked in register_local_pipes.lua if pipeworks.enable_new_flow_logic then - dofile(pipeworks.modpath.."/new_flow_logic.lua") - dofile(pipeworks.modpath.."/register_flow_logic.lua") - dofile(pipeworks.modpath.."/flowable_nodes_add_pipes.lua") + dofile(pipeworks.modpath..logicdir.."abms.lua") + dofile(pipeworks.modpath..logicdir.."abm_register.lua") + dofile(pipeworks.modpath..logicdir.."register_local_pipes.lua") end if pipeworks.enable_redefines then diff --git a/register_flow_logic.lua b/new_flow_logic/abm_register.lua similarity index 100% rename from register_flow_logic.lua rename to new_flow_logic/abm_register.lua diff --git a/new_flow_logic.lua b/new_flow_logic/abms.lua similarity index 100% rename from new_flow_logic.lua rename to new_flow_logic/abms.lua diff --git a/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua similarity index 100% rename from flowable_node_registry.lua rename to new_flow_logic/flowable_node_registry.lua diff --git a/flowable_nodes_add_pipes.lua b/new_flow_logic/register_local_pipes.lua similarity index 100% rename from flowable_nodes_add_pipes.lua rename to new_flow_logic/register_local_pipes.lua From 21892456f529e099a0c1d47ae780101d172f818a Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 30 Sep 2017 23:55:16 +0100 Subject: [PATCH 11/75] init.lua: move non-destructive new_flow_logic code outside if-guard --- init.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/init.lua b/init.lua index a081759..d6067e5 100644 --- a/init.lua +++ b/init.lua @@ -116,7 +116,10 @@ dofile(pipeworks.modpath.."/trashcan.lua") dofile(pipeworks.modpath.."/wielder.lua") local logicdir = "/new_flow_logic/" --- note that pipes still don't appear until registered in the files below this one, so can still be turned off + +-- note that even with these files the new flow logic is not yet default +dofile(pipeworks.modpath..logicdir.."abms.lua") +dofile(pipeworks.modpath..logicdir.."abm_register.lua") dofile(pipeworks.modpath..logicdir.."flowable_node_registry.lua") if pipeworks.enable_pipes then dofile(pipeworks.modpath.."/pipes.lua") end @@ -124,8 +127,6 @@ if pipeworks.enable_teleport_tube then dofile(pipeworks.modpath.."/teleport_tube if pipeworks.enable_pipe_devices then dofile(pipeworks.modpath.."/devices.lua") end -- individual enable flags also checked in register_local_pipes.lua if pipeworks.enable_new_flow_logic then - dofile(pipeworks.modpath..logicdir.."abms.lua") - dofile(pipeworks.modpath..logicdir.."abm_register.lua") dofile(pipeworks.modpath..logicdir.."register_local_pipes.lua") end From 31741e33e20c2ed366f80c01c7d6b4a6a23e0d4c Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 00:00:33 +0100 Subject: [PATCH 12/75] new_flow_logic/abms.lua: run_pump_intake(): use passed-in maxpressure instead of table lookup, pass through in abm_register.lua --- new_flow_logic/abm_register.lua | 2 +- new_flow_logic/abms.lua | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index e7bed6a..505ca4b 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -30,7 +30,7 @@ local register_abm_input = function(nodename, maxpressure) interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.flowlogic.run_pump_intake(pos, node) + pipeworks.flowlogic.run_pump_intake(pos, node, maxpressure) end }) end diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 7360668..ece81c1 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -89,13 +89,10 @@ end -flowlogic.run_pump_intake = function(pos, node) +flowlogic.run_pump_intake = function(pos, node, maxpressure) -- try to absorb nearby water nodes, but only up to limit. -- NB: check_for_liquids_v2 handles zero or negative from the following subtraction - local properties = pipeworks.flowables.inputs.list[node.name] - local maxpressure = properties.maxpressure - local meta = minetest.get_meta(pos) local currentpressure = meta:get_float(label_pressure) From ec9cf1df5019c915cf7f5776c90cca760670569f Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 00:13:43 +0100 Subject: [PATCH 13/75] new_flow_logic/flowable_node_registry.lua: integrate existing ABM registration from register_local_pipes.lua --- new_flow_logic/flowable_node_registry.lua | 11 +++++++++-- new_flow_logic/register_local_pipes.lua | 6 ------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index def9649..3cb2a67 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -1,6 +1,9 @@ -- registration code for nodes under new flow logic -- written 2017 by thetaepsilon +-- use for hooking up ABMs as nodes are registered +local abmregister = pipeworks.flowlogic.abmregister + pipeworks.flowables = {} pipeworks.flowables.list = {} pipeworks.flowables.list.all = {} @@ -34,12 +37,13 @@ end -- Register a node as a simple flowable. -- Simple flowable nodes have no considerations for direction of flow; -- A cluster of adjacent simple flowables will happily average out in any direction. --- This does *not* register the ABM, as that is done in register_flow_logic.lua; --- this is so that the new flow logic can remain optional during development. register.simple = function(nodename) insertbase(nodename) pipeworks.flowables.list.simple[nodename] = true table.insert(pipeworks.flowables.list.simple_nodenames, nodename) + if pipeworks.enable_new_flow_logic then + abmregister.balance(nodename) + end end local checkbase = function(nodename) @@ -56,4 +60,7 @@ register.intake_simple = function(nodename, maxpressure) checkbase(nodename) pipeworks.flowables.inputs.list[nodename] = { maxpressure=maxpressure } table.insert(pipeworks.flowables.inputs.nodenames, nodename) + if pipeworks.enable_new_flow_logic then + abmregister.input(nodename, maxpressure) + end end diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua index 6fe8b7e..62b787b 100644 --- a/new_flow_logic/register_local_pipes.lua +++ b/new_flow_logic/register_local_pipes.lua @@ -16,7 +16,6 @@ local pipes_full_nodenames = pipeworks.pipes_full_nodenames local pipes_empty_nodenames = pipeworks.pipes_empty_nodenames local register = pipeworks.flowables.register -local abmregister = pipeworks.flowlogic.abmregister @@ -42,12 +41,7 @@ if pipeworks.enable_pipes then register.simple(pump_on) register.simple(spigot_on) register.simple(spigot_off) - abmregister.balance(pump_off) - abmregister.balance(pump_on) - abmregister.balance(spigot_on) - abmregister.balance(spigot_off) register.intake_simple(pump_on, thresholds.pump_pressure) - abmregister.input(pump_on, thresholds.pump_pressure) end end From aee23d76426734892f1d7129c02c56b58cc813af Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 00:24:45 +0100 Subject: [PATCH 14/75] new_flow_logic/register_local_pipes.lua: remove old ABM note in header --- new_flow_logic/register_local_pipes.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua index 62b787b..989ff0c 100644 --- a/new_flow_logic/register_local_pipes.lua +++ b/new_flow_logic/register_local_pipes.lua @@ -1,5 +1,4 @@ --- conditional registration of pipe nodes for the new pipe logic, depending on enable flags. --- otherwise register_flow_logic.lua would be attempting to register ABMs for non-existant nodes. +-- registration of pipework's own pipes. -- written 2017 by thetaepsilon From 3486ee319ee4fafbf83c583dd9fedfaed92db7c4 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 00:44:14 +0100 Subject: [PATCH 15/75] abms.lua: refactor and generalise run_pump_intake() to allow passing custom intake functions --- new_flow_logic/abm_register.lua | 4 ++-- new_flow_logic/abms.lua | 20 ++++++++++---------- new_flow_logic/flowable_node_registry.lua | 3 +-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index 505ca4b..57c8a47 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -24,13 +24,13 @@ register.balance = register_abm_balance -- register a node for the pump ABM. -- maxpressure is the maximum pressure that this pump can drive. -local register_abm_input = function(nodename, maxpressure) +local register_abm_input = function(nodename, maxpressure, intakefn) minetest.register_abm({ nodenames = { nodename }, interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.flowlogic.run_pump_intake(pos, node, maxpressure) + pipeworks.flowlogic.run_input(pos, node, maxpressure, intakefn) end }) end diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index ece81c1..48dcb0b 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -31,12 +31,7 @@ end -- new version of liquid check -- accepts a limit parameter to only delete water blocks that the receptacle can accept, -- and returns it so that the receptacle can update it's pressure values. --- this should ensure that water blocks aren't vanished from existance. --- will take care of zero or negative-valued limits. local check_for_liquids_v2 = function(pos, limit) - if not limit then - limit = 6 - end local coords = make_coords_offsets(pos, false) local total = 0 for index, tpos in ipairs(coords) do @@ -89,15 +84,20 @@ end -flowlogic.run_pump_intake = function(pos, node, maxpressure) - -- try to absorb nearby water nodes, but only up to limit. - -- NB: check_for_liquids_v2 handles zero or negative from the following subtraction +flowlogic.run_input = function(pos, node, maxpressure, intakefn) + -- intakefn allows a given input node to define it's own intake logic. + -- this function will calculate the maximum amount of water that can be taken in; + -- the intakefn will be given this and is expected to return the actual absorption amount. local meta = minetest.get_meta(pos) local currentpressure = meta:get_float(label_pressure) - local intake_limit = maxpressure - currentpressure - local actual_intake = check_for_liquids_v2(pos, intake_limit) + if intake_limit <= 0 then return end + + local actual_intake = intakefn(pos, intake_limit) + if actual_intake <= 0 then return end + if actual_intake >= intake_limit then actual_intake = intake_limit end + local newpressure = actual_intake + currentpressure -- debuglog("oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake.." newpressure "..newpressure) meta:set_float(label_pressure, newpressure) diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index 3cb2a67..1465561 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -51,7 +51,6 @@ local checkbase = function(nodename) end -- Register a node as a simple intake. --- See new_flow_logic for the details of this. -- Expects node to be registered as a flowable (is present in flowables.list.all), -- so that water can move out of it. -- maxpressure is the maximum pipeline pressure that this node can drive. @@ -61,6 +60,6 @@ register.intake_simple = function(nodename, maxpressure) pipeworks.flowables.inputs.list[nodename] = { maxpressure=maxpressure } table.insert(pipeworks.flowables.inputs.nodenames, nodename) if pipeworks.enable_new_flow_logic then - abmregister.input(nodename, maxpressure) + abmregister.input(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) end end From 4cf9c90bb9a2a1f3c1fc938b543198b4ebd885c3 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 12:25:03 +0100 Subject: [PATCH 16/75] new flow logic: register_local_pipes.lua: fix leftover calls to abmregister --- new_flow_logic/register_local_pipes.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua index 989ff0c..ca12244 100644 --- a/new_flow_logic/register_local_pipes.lua +++ b/new_flow_logic/register_local_pipes.lua @@ -28,11 +28,9 @@ local spigot_on = "pipeworks:spigot_pouring" if pipeworks.enable_pipes then for _, pipe in ipairs(pipes_full_nodenames) do register.simple(pipe) - abmregister.balance(pipe) end for _, pipe in ipairs(pipes_empty_nodenames) do register.simple(pipe) - abmregister.balance(pipe) end if pipeworks.enable_pipe_devices then From 463e7a206af8e2b98617b549e3bc6dc5eb181ffc Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 12:25:43 +0100 Subject: [PATCH 17/75] new flow logic: abms.lua: start splitting apart spigot code into generalised output ABM --- new_flow_logic/abms.lua | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 48dcb0b..640493a 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -4,6 +4,7 @@ local flowlogic = {} +flowlogic.helpers = {} pipeworks.flowlogic = flowlogic @@ -105,6 +106,43 @@ end +-- flowlogic output helper for spigots +-- tries to place a water block in the world beneath the spigot. +-- threshold checking is assumed to be handled by the node registration; +-- see register_local_pipes.lua for the pipeworks default spigot. +flowlogic.helpers.output_spigot = function(pos, node, currentpressure) + local taken = 0 + local below = {x=pos.x, y=pos.y-1, z=pos.z} + local name = minetest.get_node(below).name + if (name == "air") or (name == "default:water_flowing") then + minetest.set_node(below, {name="default:water_source"}) + taken = taken + 1 + end + return taken +end + + + +flowlogic.run_output = function(pos, node, threshold, outputfn) + -- callback for output devices. + -- takes care of checking a minimum pressure value and updating the node metadata. + -- the outputfn is provided the current pressure and returns the pressure "taken". + -- as an example, using this with the above spigot function, + -- the spigot function tries to output a water source if it will fit in the world. + local meta = minetest.get_meta(pos) + -- sometimes I wonder if meta:get_* returning default values would ever be problematic. + -- though here it doesn't matter, an uninit'd node returns 0, which is fine for a new, empty node. + local currentpressure = meta:get_float(label_pressure) + if currentpressure > threshold then + local takenpressure = outputfn(pos, node, currentpressure) + local newpressure = currentpressure - takenpressure + if newpressure < 0 then currentpressure = 0 end + meta:set_float(label_pressure, newpressure) + end +end + + + flowlogic.run_spigot_output = function(pos, node) -- try to output a water source node if there's enough pressure and space below. local meta = minetest.get_meta(pos) From 15b41d14f3923ce3cea8418a792f83e7763d5b00 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 12:28:22 +0100 Subject: [PATCH 18/75] new flow logic: abm_register.lua: update doc comments for register_abm_input() --- new_flow_logic/abm_register.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index 57c8a47..793ea83 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -22,8 +22,9 @@ local register_abm_balance = function(nodename) end register.balance = register_abm_balance --- register a node for the pump ABM. --- maxpressure is the maximum pressure that this pump can drive. +-- register a node for the input ABM. +-- intakefn is run on the node to determine how much water can be taken (and update it's environment accordingly). +-- maxpressure is the maximum pressure that this input can drive, beyond which pressure will not be raised. local register_abm_input = function(nodename, maxpressure, intakefn) minetest.register_abm({ nodenames = { nodename }, From f3a94fcd248df35b4afb992941a58af4cc17f446 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 12:34:20 +0100 Subject: [PATCH 19/75] new flow logic: abm_register.lua: add register_abm_output routine --- new_flow_logic/abm_register.lua | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index 793ea83..c1b2d7d 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -6,7 +6,11 @@ local register = {} pipeworks.flowlogic.abmregister = register +local flowlogic = pipeworks.flowlogic +-- A possible DRY violation here... +-- DISCUSS: should it be possible later on to raise the the rate of ABMs, or lower the chance? +-- Currently all the intervals and chances are hardcoded below. -- register a node name for the pressure balancing ABM. -- currently this only exists as a per-node function to allow nodes to be registered outside pipeworks. @@ -16,7 +20,7 @@ local register_abm_balance = function(nodename) interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.flowlogic.balance_pressure(pos, node) + flowlogic.balance_pressure(pos, node) end }) end @@ -31,12 +35,28 @@ local register_abm_input = function(nodename, maxpressure, intakefn) interval = 1, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.flowlogic.run_input(pos, node, maxpressure, intakefn) + flowlogic.run_input(pos, node, maxpressure, intakefn) end }) end register.input = register_abm_input +-- register a node for the output ABM. +-- threshold determines the minimum pressure, over which outputfn is called. +-- outputfn is then given the current pressure, and returns the pressure relieved by the output process. +-- outputfn is expected to update environment, nearby world etc. as appropriate for the node. +local register_abm_output = function(nodename, threshold, outputfn) + minetest.register_abm({ + nodenames = { nodename }, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + flowlogic.run_output(pos, node, threshold, outputfn) + end + }) +end +register.output = register_abm_output + -- old spigot ABM code, not yet migrated --[[ minetest.register_abm({ From e615a1013b621daff64500fb74a6202fdca0093f Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 12:45:12 +0100 Subject: [PATCH 20/75] new flow logic: flowable_node_registry.lua: add output node registration --- new_flow_logic/flowable_node_registry.lua | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index 1465561..f3548a4 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -18,6 +18,11 @@ pipeworks.flowables.inputs = {} pipeworks.flowables.inputs.list = {} pipeworks.flowables.inputs.nodenames = {} +-- outputs - takes pressure from pipes and update world to do something with it +pipeworks.flowables.outputs = {} +pipeworks.flowables.outputs.list = {} +-- not currently any nodenames arraylist for this one as it's not currently needed. + -- registration functions pipeworks.flowables.register = {} local register = pipeworks.flowables.register @@ -63,3 +68,20 @@ register.intake_simple = function(nodename, maxpressure) abmregister.input(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) end end + +-- Register a node as an output. +-- Expects node to already be a flowable. +-- threshold and outputfn are currently as documented for register_abm_output() in abm_register.lua. +register.output = function(nodename, threshold, outputfn) + checkbase(nodename) + pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } + if pipeworks.enable_new_flow_logic then + abmregister.output(nodename, maxpressure, outputfn) + end +end + +-- TODOs here: +-- The spigot's output behaviour (and possibly the fountain) could be abstracted out into a "simple output" of sorts, +-- which tries to place water nodes around it. +-- possibly this could be given a helper function to determine which faces a node should try, +-- to allow things like rotation or other param values determining "direction" to be respected. From 3a1edac06ce193179b58ffcd055b492839d30018 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 13:00:41 +0100 Subject: [PATCH 21/75] new flow logic: register_local_pipes.lua: make spigots work again --- new_flow_logic/flowable_node_registry.lua | 2 +- new_flow_logic/register_local_pipes.lua | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index f3548a4..f2ebdcb 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -76,7 +76,7 @@ register.output = function(nodename, threshold, outputfn) checkbase(nodename) pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } if pipeworks.enable_new_flow_logic then - abmregister.output(nodename, maxpressure, outputfn) + abmregister.output(nodename, threshold, outputfn) end end diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua index ca12244..b8cb7f0 100644 --- a/new_flow_logic/register_local_pipes.lua +++ b/new_flow_logic/register_local_pipes.lua @@ -8,6 +8,9 @@ local thresholds = {} -- limit on pump pressure - will not absorb more than can be taken thresholds.pump_pressure = 2 +-- activation threshold for spigot +-- should not be below 1, as spigot helper code indiscriminately places a water source node if run. +thresholds.spigot_min = 1 @@ -15,6 +18,7 @@ local pipes_full_nodenames = pipeworks.pipes_full_nodenames local pipes_empty_nodenames = pipeworks.pipes_empty_nodenames local register = pipeworks.flowables.register +local flowlogic = pipeworks.flowlogic @@ -40,5 +44,9 @@ if pipeworks.enable_pipes then register.simple(spigot_off) register.intake_simple(pump_on, thresholds.pump_pressure) + -- TODO: the code doesn't currently care if the spigot is the visually flowing node or not. + -- So some mechanism to register on/off states would be nice + register.output(spigot_off, thresholds.spigot_min, flowlogic.helpers.output_spigot) + register.output(spigot_on, thresholds.spigot_min, flowlogic.helpers.output_spigot) end end From f7b17197677ea3675eee6bc667370fe3e23ac099 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 15:18:00 +0100 Subject: [PATCH 22/75] new flow logic: node registry: split registration functions into seperate file to allow ABM code to inspect tables --- init.lua | 3 +- new_flow_logic/flowable_node_registry.lua | 73 ++----------------- .../flowable_node_registry_install.lua | 70 ++++++++++++++++++ 3 files changed, 79 insertions(+), 67 deletions(-) create mode 100644 new_flow_logic/flowable_node_registry_install.lua diff --git a/init.lua b/init.lua index d6067e5..e91c4dc 100644 --- a/init.lua +++ b/init.lua @@ -118,9 +118,10 @@ dofile(pipeworks.modpath.."/wielder.lua") local logicdir = "/new_flow_logic/" -- note that even with these files the new flow logic is not yet default +dofile(pipeworks.modpath..logicdir.."flowable_node_registry.lua") dofile(pipeworks.modpath..logicdir.."abms.lua") dofile(pipeworks.modpath..logicdir.."abm_register.lua") -dofile(pipeworks.modpath..logicdir.."flowable_node_registry.lua") +dofile(pipeworks.modpath..logicdir.."flowable_node_registry_install.lua") if pipeworks.enable_pipes then dofile(pipeworks.modpath.."/pipes.lua") end if pipeworks.enable_teleport_tube then dofile(pipeworks.modpath.."/teleport_tube.lua") end diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index f2ebdcb..8fb925c 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -1,8 +1,12 @@ --- registration code for nodes under new flow logic +-- registry of flowable node behaviours in new flow logic -- written 2017 by thetaepsilon --- use for hooking up ABMs as nodes are registered -local abmregister = pipeworks.flowlogic.abmregister +-- the actual registration functions which edit these tables can be found in flowable_node_registry_install.lua +-- this is because the ABM code needs to inspect these tables, +-- but the registration code needs to reference said ABM code. +-- so those functions were split out to resolve a circular dependency. + + pipeworks.flowables = {} pipeworks.flowables.list = {} @@ -22,66 +26,3 @@ pipeworks.flowables.inputs.nodenames = {} pipeworks.flowables.outputs = {} pipeworks.flowables.outputs.list = {} -- not currently any nodenames arraylist for this one as it's not currently needed. - --- registration functions -pipeworks.flowables.register = {} -local register = pipeworks.flowables.register - --- some sanity checking for passed args, as this could potentially be made an external API eventually -local checkexists = function(nodename) - if type(nodename) ~= "string" then error("pipeworks.flowables nodename must be a string!") end - return pipeworks.flowables.list.all[nodename] -end - -local insertbase = function(nodename) - if checkexists(nodename) then error("pipeworks.flowables duplicate registration!") end - pipeworks.flowables.list.all[nodename] = true - -- table.insert(pipeworks.flowables.list.nodenames, nodename) -end - --- Register a node as a simple flowable. --- Simple flowable nodes have no considerations for direction of flow; --- A cluster of adjacent simple flowables will happily average out in any direction. -register.simple = function(nodename) - insertbase(nodename) - pipeworks.flowables.list.simple[nodename] = true - table.insert(pipeworks.flowables.list.simple_nodenames, nodename) - if pipeworks.enable_new_flow_logic then - abmregister.balance(nodename) - end -end - -local checkbase = function(nodename) - if not checkexists(nodename) then error("pipeworks.flowables node doesn't exist as a flowable!") end -end - --- Register a node as a simple intake. --- Expects node to be registered as a flowable (is present in flowables.list.all), --- so that water can move out of it. --- maxpressure is the maximum pipeline pressure that this node can drive. --- possible WISHME here: technic-driven high-pressure pumps -register.intake_simple = function(nodename, maxpressure) - checkbase(nodename) - pipeworks.flowables.inputs.list[nodename] = { maxpressure=maxpressure } - table.insert(pipeworks.flowables.inputs.nodenames, nodename) - if pipeworks.enable_new_flow_logic then - abmregister.input(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) - end -end - --- Register a node as an output. --- Expects node to already be a flowable. --- threshold and outputfn are currently as documented for register_abm_output() in abm_register.lua. -register.output = function(nodename, threshold, outputfn) - checkbase(nodename) - pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } - if pipeworks.enable_new_flow_logic then - abmregister.output(nodename, threshold, outputfn) - end -end - --- TODOs here: --- The spigot's output behaviour (and possibly the fountain) could be abstracted out into a "simple output" of sorts, --- which tries to place water nodes around it. --- possibly this could be given a helper function to determine which faces a node should try, --- to allow things like rotation or other param values determining "direction" to be respected. diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua new file mode 100644 index 0000000..06d69fd --- /dev/null +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -0,0 +1,70 @@ +-- flowable node registry: add entries and install ABMs if new flow logic is enabled +-- written 2017 by thetaepsilon + + + +-- use for hooking up ABMs as nodes are registered +local abmregister = pipeworks.flowlogic.abmregister + +-- registration functions +pipeworks.flowables.register = {} +local register = pipeworks.flowables.register + +-- some sanity checking for passed args, as this could potentially be made an external API eventually +local checkexists = function(nodename) + if type(nodename) ~= "string" then error("pipeworks.flowables nodename must be a string!") end + return pipeworks.flowables.list.all[nodename] +end + +local insertbase = function(nodename) + if checkexists(nodename) then error("pipeworks.flowables duplicate registration!") end + pipeworks.flowables.list.all[nodename] = true + -- table.insert(pipeworks.flowables.list.nodenames, nodename) +end + +-- Register a node as a simple flowable. +-- Simple flowable nodes have no considerations for direction of flow; +-- A cluster of adjacent simple flowables will happily average out in any direction. +register.simple = function(nodename) + insertbase(nodename) + pipeworks.flowables.list.simple[nodename] = true + table.insert(pipeworks.flowables.list.simple_nodenames, nodename) + if pipeworks.enable_new_flow_logic then + abmregister.balance(nodename) + end +end + +local checkbase = function(nodename) + if not checkexists(nodename) then error("pipeworks.flowables node doesn't exist as a flowable!") end +end + +-- Register a node as a simple intake. +-- Expects node to be registered as a flowable (is present in flowables.list.all), +-- so that water can move out of it. +-- maxpressure is the maximum pipeline pressure that this node can drive. +-- possible WISHME here: technic-driven high-pressure pumps +register.intake_simple = function(nodename, maxpressure) + checkbase(nodename) + pipeworks.flowables.inputs.list[nodename] = { maxpressure=maxpressure } + table.insert(pipeworks.flowables.inputs.nodenames, nodename) + if pipeworks.enable_new_flow_logic then + abmregister.input(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) + end +end + +-- Register a node as an output. +-- Expects node to already be a flowable. +-- threshold and outputfn are currently as documented for register_abm_output() in abm_register.lua. +register.output = function(nodename, threshold, outputfn) + checkbase(nodename) + pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } + if pipeworks.enable_new_flow_logic then + abmregister.output(nodename, threshold, outputfn) + end +end + +-- TODOs here: +-- The spigot's output behaviour (and possibly the fountain) could be abstracted out into a "simple output" of sorts, +-- which tries to place water nodes around it. +-- possibly this could be given a helper function to determine which faces a node should try, +-- to allow things like rotation or other param values determining "direction" to be respected. From d9b616c5f05b1c512988fd5eef5f91aba5bf12cf Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 15:47:21 +0100 Subject: [PATCH 23/75] new flow logic: node registry: add initial stub for flow directionality check --- new_flow_logic/flowable_node_registry.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index 8fb925c..b0634d0 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -26,3 +26,16 @@ pipeworks.flowables.inputs.nodenames = {} pipeworks.flowables.outputs = {} pipeworks.flowables.outputs.list = {} -- not currently any nodenames arraylist for this one as it's not currently needed. + + + +-- checks if a given node can flow in a given direction. +-- used to implement directional devices such as pumps, +-- which only visually connect in a certain direction. +-- node is the usual name + param structure. +-- direction is an x/y/z vector of the flow direction; +-- this function answers the question "can this node flow in this direction?" +pipeworks.flowables.flow_check = function(node, direction) + minetest.log("warning", "pipeworks.flowables.flow_check() stub!") + return true +end From f3cd1b61d771824ed9f42b32caa95ae08538bb64 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 16:17:35 +0100 Subject: [PATCH 24/75] new flow logic: flowable_node_registry_install.lua: add registration tracing --- init.lua | 4 ++++ new_flow_logic/flowable_node_registry_install.lua | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/init.lua b/init.lua index e91c4dc..e8a8d2f 100644 --- a/init.lua +++ b/init.lua @@ -94,6 +94,10 @@ function pipeworks.replace_name(tbl,tr,name) return ntbl end +pipeworks.logger = function(msg) + print("[pipeworks] "..msg) +end + ------------------------------------------- -- Load the various other parts of the mod diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 06d69fd..f83f8ad 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -22,6 +22,12 @@ local insertbase = function(nodename) -- table.insert(pipeworks.flowables.list.nodenames, nodename) end +local regwarning = function(kind, nodename) + local tail = "" + if pipeworks.enable_new_flow_logic then tail = " but new_flow_logic not enabled" end + pipeworks.logger("[pipeworks] "..kind.." flow logic registry requested for "..nodename..tail) +end + -- Register a node as a simple flowable. -- Simple flowable nodes have no considerations for direction of flow; -- A cluster of adjacent simple flowables will happily average out in any direction. @@ -32,6 +38,7 @@ register.simple = function(nodename) if pipeworks.enable_new_flow_logic then abmregister.balance(nodename) end + regwarning("simple", nodename) end local checkbase = function(nodename) @@ -50,6 +57,7 @@ register.intake_simple = function(nodename, maxpressure) if pipeworks.enable_new_flow_logic then abmregister.input(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) end + regwarning("simple intake", nodename) end -- Register a node as an output. @@ -61,6 +69,7 @@ register.output = function(nodename, threshold, outputfn) if pipeworks.enable_new_flow_logic then abmregister.output(nodename, threshold, outputfn) end + regwarning("output node", nodename) end -- TODOs here: From 0fb0eab7235db267aece1cecee7c1d6a1a5b42a1 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 16:54:24 +0100 Subject: [PATCH 25/75] move pipe node registration for new flow logic closer to their definition in pipes.lua --- .../flowable_node_registry_install.lua | 4 +- new_flow_logic/register_local_pipes.lua | 2 + pipes.lua | 43 ++++++++++++++----- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index f83f8ad..ac305dc 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -24,8 +24,8 @@ end local regwarning = function(kind, nodename) local tail = "" - if pipeworks.enable_new_flow_logic then tail = " but new_flow_logic not enabled" end - pipeworks.logger("[pipeworks] "..kind.." flow logic registry requested for "..nodename..tail) + if not pipeworks.enable_new_flow_logic then tail = " but new_flow_logic not enabled" end + pipeworks.logger(kind.." flow logic registry requested for "..nodename..tail) end -- Register a node as a simple flowable. diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua index b8cb7f0..5128d47 100644 --- a/new_flow_logic/register_local_pipes.lua +++ b/new_flow_logic/register_local_pipes.lua @@ -30,12 +30,14 @@ local spigot_off = "pipeworks:spigot" local spigot_on = "pipeworks:spigot_pouring" if pipeworks.enable_pipes then + --[[ for _, pipe in ipairs(pipes_full_nodenames) do register.simple(pipe) end for _, pipe in ipairs(pipes_empty_nodenames) do register.simple(pipe) end + ]] if pipeworks.enable_pipe_devices then register.simple(pump_off) diff --git a/pipes.lua b/pipes.lua index 54dfbd7..80fb0b3 100644 --- a/pipes.lua +++ b/pipes.lua @@ -5,6 +5,8 @@ local REGISTER_COMPATIBILITY = true local pipes_empty_nodenames = {} local pipes_full_nodenames = {} +local new_flow_logic_register = pipeworks.flowables.register + local vti = {4, 3, 2, 1, 6, 5} local cconnects = {{}, {1}, {1, 2}, {1, 3}, {1, 3, 5}, {1, 2, 3}, {1, 2, 3, 5}, {1, 2, 3, 4}, {1, 2, 3, 4, 5}, {1, 2, 3, 4, 5, 6}} for index, connects in ipairs(cconnects) do @@ -116,8 +118,12 @@ for index, connects in ipairs(cconnects) do on_rotate = false }) - table.insert(pipes_empty_nodenames, "pipeworks:pipe_"..index.."_empty") - table.insert(pipes_full_nodenames, "pipeworks:pipe_"..index.."_loaded") + local emptypipe = "pipeworks:pipe_"..index.."_empty" + local fullpipe = "pipeworks:pipe_"..index.."_loaded" + table.insert(pipes_empty_nodenames, emptypipe) + table.insert(pipes_full_nodenames, fullpipe) + new_flow_logic_register.simple(emptypipe) + new_flow_logic_register.simple(fullpipe) end @@ -182,14 +188,31 @@ if REGISTER_COMPATIBILITY then }) end -table.insert(pipes_empty_nodenames,"pipeworks:valve_on_empty") -table.insert(pipes_empty_nodenames,"pipeworks:valve_off_empty") -table.insert(pipes_empty_nodenames,"pipeworks:entry_panel_empty") -table.insert(pipes_empty_nodenames,"pipeworks:flow_sensor_empty") +-- appropriate registration for both old and new flow logic follows -table.insert(pipes_full_nodenames,"pipeworks:valve_on_loaded") -table.insert(pipes_full_nodenames,"pipeworks:entry_panel_loaded") -table.insert(pipes_full_nodenames,"pipeworks:flow_sensor_loaded") +-- FIXME/TODO: these aren't really "simple", they have directionality. +local valve_on = "pipeworks:valve_on_empty" +local valve_off = "pipeworks:valve_off_empty" +local entry_panel_empty = "pipeworks:entry_panel_empty" +local flow_sensor_empty = "pipeworks:flow_sensor_empty" +table.insert(pipes_empty_nodenames, valve_on) +table.insert(pipes_empty_nodenames, valve_off) +table.insert(pipes_empty_nodenames, entry_panel_empty) +table.insert(pipes_empty_nodenames, flow_sensor_empty) +new_flow_logic_register.simple(valve_on) +-- don't register valve_off, automatically makes it block flow in the new logic +new_flow_logic_register.simple(entry_panel_empty) +new_flow_logic_register.simple(flow_sensor_empty) + +local valve_on_loaded = "pipeworks:valve_on_loaded" +local entry_panel_loaded = "pipeworks:entry_panel_loaded" +local flow_sensor_loaded = "pipeworks:flow_sensor_loaded" +table.insert(pipes_full_nodenames, valve_on_loaded) +table.insert(pipes_full_nodenames, entry_panel_loaded) +table.insert(pipes_full_nodenames, flow_sensor_loaded) +new_flow_logic_register.simple(valve_on_loaded) +new_flow_logic_register.simple(entry_panel_loaded) +new_flow_logic_register.simple(flow_sensor_loaded) pipeworks.pipes_full_nodenames = pipes_full_nodenames pipeworks.pipes_empty_nodenames = pipes_empty_nodenames @@ -198,7 +221,7 @@ pipeworks.pipes_empty_nodenames = pipes_empty_nodenames if not pipeworks.enable_new_flow_logic then --- sorry, no indents... it messes with the patchlogs too much + minetest.register_abm({ From caacc2a2613706c53b7ee27b04b5a4d7584a83f7 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 17:24:39 +0100 Subject: [PATCH 26/75] devices.lua: create local variables for device node names in preparation for flow logic registration --- devices.lua | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/devices.lua b/devices.lua index 3b7fc78..26df862 100644 --- a/devices.lua +++ b/devices.lua @@ -129,7 +129,8 @@ for s in ipairs(states) do dgroups = {snappy=3, pipe=1, not_in_creative_inventory=1} end - minetest.register_node("pipeworks:pump_"..states[s], { + local pumpname = "pipeworks:pump_"..states[s] + minetest.register_node(pumpname, { description = "Pump/Intake Module", drawtype = "mesh", mesh = "pipeworks_pump.obj", @@ -162,8 +163,9 @@ for s in ipairs(states) do -- FIXME - does this preserve metadata? need to look at this on_rotate = screwdriver.rotate_simple }) - - minetest.register_node("pipeworks:valve_"..states[s].."_empty", { + + local nodename_valve_empty = "pipeworks:valve_"..states[s].."_empty" + minetest.register_node(nodename_valve_empty, { description = "Valve", drawtype = "mesh", mesh = "pipeworks_valve_"..states[s]..".obj", @@ -203,7 +205,8 @@ for s in ipairs(states) do }) end -minetest.register_node("pipeworks:valve_on_loaded", { +local nodename_valve_loaded = "pipeworks:valve_on_loaded" +minetest.register_node(nodename_valve_loaded, { description = "Valve", drawtype = "mesh", mesh = "pipeworks_valve_on.obj", @@ -244,6 +247,7 @@ minetest.register_node("pipeworks:valve_on_loaded", { -- grating +-- FIXME: should this do anything useful in the new flow logic? minetest.register_node("pipeworks:grating", { description = "Decorative grating", tiles = { @@ -276,7 +280,8 @@ minetest.register_node("pipeworks:grating", { -- outlet spigot -minetest.register_node("pipeworks:spigot", { +local nodename_spigot_empty = "pipeworks:spigot" +minetest.register_node(nodename_spigot_empty, { description = "Spigot outlet", drawtype = "mesh", mesh = "pipeworks_spigot.obj", @@ -306,7 +311,8 @@ minetest.register_node("pipeworks:spigot", { on_rotate = pipeworks.fix_after_rotation }) -minetest.register_node("pipeworks:spigot_pouring", { +local nodename_spigot_loaded = "pipeworks:spigot_pouring" +minetest.register_node(nodename_spigot_loaded, { description = "Spigot outlet", drawtype = "mesh", mesh = "pipeworks_spigot_pouring.obj", @@ -360,7 +366,8 @@ local panel_cbox = { } } -minetest.register_node("pipeworks:entry_panel_empty", { +local nodename_panel_empty = "pipeworks:entry_panel_empty" +minetest.register_node(nodename_panel_empty, { description = "Airtight Pipe entry/exit", drawtype = "mesh", mesh = "pipeworks_entry_panel.obj", @@ -379,7 +386,8 @@ minetest.register_node("pipeworks:entry_panel_empty", { on_rotate = pipeworks.fix_after_rotation }) -minetest.register_node("pipeworks:entry_panel_loaded", { +local nodename_panel_loaded = "pipeworks:entry_panel_loaded" +minetest.register_node(nodename_panel_loaded, { description = "Airtight Pipe entry/exit", drawtype = "mesh", mesh = "pipeworks_entry_panel.obj", @@ -399,7 +407,8 @@ minetest.register_node("pipeworks:entry_panel_loaded", { on_rotate = pipeworks.fix_after_rotation }) -minetest.register_node("pipeworks:flow_sensor_empty", { +local nodename_sensor_empty = "pipeworks:flow_sensor_empty" +minetest.register_node(nodename_sensor_empty, { description = "Flow Sensor", drawtype = "mesh", mesh = "pipeworks_flow_sensor.obj", @@ -437,7 +446,8 @@ minetest.register_node("pipeworks:flow_sensor_empty", { on_rotate = pipeworks.fix_after_rotation }) -minetest.register_node("pipeworks:flow_sensor_loaded", { +local nodename_sensor_loaded = "pipeworks:flow_sensor_loaded" +minetest.register_node(nodename_sensor_loaded, { description = "Flow sensor (on)", drawtype = "mesh", mesh = "pipeworks_flow_sensor.obj", @@ -478,6 +488,7 @@ minetest.register_node("pipeworks:flow_sensor_loaded", { -- tanks +-- TODO: these don't currently do anything under the new flow logic. for fill = 0, 10 do local filldesc="empty" local sgroups = {snappy=3, pipe=1, tankfill=fill+1} @@ -548,7 +559,8 @@ end -- fountainhead -minetest.register_node("pipeworks:fountainhead", { +local nodename_fountain_empty = "pipeworks:fountainhead" +minetest.register_node(nodename_fountain_empty, { description = "Fountainhead", drawtype = "mesh", mesh = "pipeworks_fountainhead.obj", @@ -581,7 +593,8 @@ minetest.register_node("pipeworks:fountainhead", { on_rotate = false }) -minetest.register_node("pipeworks:fountainhead_pouring", { +local nodename_fountain_loaded = "pipeworks:fountainhead_pouring" +minetest.register_node(nodename_fountain_loaded, { description = "Fountainhead", drawtype = "mesh", mesh = "pipeworks_fountainhead.obj", From e6b55028fc9b6a50ecd6c28c2af1ee94e041edcd Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 17:36:03 +0100 Subject: [PATCH 27/75] move pump flow logic registration to devices.lua --- devices.lua | 5 +++++ new_flow_logic/register_local_pipes.lua | 6 +++--- pipes.lua | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/devices.lua b/devices.lua index 26df862..670ed6c 100644 --- a/devices.lua +++ b/devices.lua @@ -1,3 +1,4 @@ +local new_flow_logic_register = pipeworks.flowables.register -- rotation handlers @@ -163,6 +164,10 @@ for s in ipairs(states) do -- FIXME - does this preserve metadata? need to look at this on_rotate = screwdriver.rotate_simple }) + new_flow_logic_register.simple(pumpname) + if states[s] ~= "off" then + new_flow_logic_register.intake_simple(pumpname, 2) + end local nodename_valve_empty = "pipeworks:valve_"..states[s].."_empty" minetest.register_node(nodename_valve_empty, { diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua index 5128d47..005a812 100644 --- a/new_flow_logic/register_local_pipes.lua +++ b/new_flow_logic/register_local_pipes.lua @@ -40,12 +40,12 @@ if pipeworks.enable_pipes then ]] if pipeworks.enable_pipe_devices then - register.simple(pump_off) - register.simple(pump_on) + --register.simple(pump_off) + --register.simple(pump_on) register.simple(spigot_on) register.simple(spigot_off) - register.intake_simple(pump_on, thresholds.pump_pressure) + --register.intake_simple(pump_on, thresholds.pump_pressure) -- TODO: the code doesn't currently care if the spigot is the visually flowing node or not. -- So some mechanism to register on/off states would be nice register.output(spigot_off, thresholds.spigot_min, flowlogic.helpers.output_spigot) diff --git a/pipes.lua b/pipes.lua index 80fb0b3..d907160 100644 --- a/pipes.lua +++ b/pipes.lua @@ -195,6 +195,7 @@ local valve_on = "pipeworks:valve_on_empty" local valve_off = "pipeworks:valve_off_empty" local entry_panel_empty = "pipeworks:entry_panel_empty" local flow_sensor_empty = "pipeworks:flow_sensor_empty" +-- XXX: why aren't these in devices.lua!? table.insert(pipes_empty_nodenames, valve_on) table.insert(pipes_empty_nodenames, valve_off) table.insert(pipes_empty_nodenames, entry_panel_empty) From a1fc493de18bebd41e8d285ef610c0f8209fb609 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 18:05:44 +0100 Subject: [PATCH 28/75] migrate flowable registration for valve nodes to devices.lua --- devices.lua | 13 +++++++++++++ pipes.lua | 3 --- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/devices.lua b/devices.lua index 670ed6c..8b1725b 100644 --- a/devices.lua +++ b/devices.lua @@ -164,6 +164,7 @@ for s in ipairs(states) do -- FIXME - does this preserve metadata? need to look at this on_rotate = screwdriver.rotate_simple }) + -- FIXME: currently a simple flow device, but needs directionality checking new_flow_logic_register.simple(pumpname) if states[s] ~= "off" then new_flow_logic_register.intake_simple(pumpname, 2) @@ -208,6 +209,12 @@ for s in ipairs(states) do end, on_rotate = pipeworks.fix_after_rotation }) + -- only register flow logic for the "on" ABM. + -- this means that the off state automatically blocks flow by not participating in the balancing operation. + if states[s] ~= "off" then + -- FIXME: this still a simple device, directionality not honoured + new_flow_logic_register.simple(nodename_valve_empty) + end end local nodename_valve_loaded = "pipeworks:valve_on_loaded" @@ -249,6 +256,12 @@ minetest.register_node(nodename_valve_loaded, { end, on_rotate = pipeworks.fix_after_rotation }) +-- register this the same as the on-but-empty variant, so existing nodes of this type work also. +-- note that as new_flow_logic code does not distinguish empty/full in node states, +-- right-clicking a "loaded" valve (becoming an off valve) then turning it on again will yield a on-but-empty valve, +-- but the flow logic will still function. +-- thus under new_flow_logic this serves as a kind of migration. +new_flow_logic_register.simple(nodename_valve_loaded) -- grating diff --git a/pipes.lua b/pipes.lua index d907160..751d460 100644 --- a/pipes.lua +++ b/pipes.lua @@ -200,8 +200,6 @@ table.insert(pipes_empty_nodenames, valve_on) table.insert(pipes_empty_nodenames, valve_off) table.insert(pipes_empty_nodenames, entry_panel_empty) table.insert(pipes_empty_nodenames, flow_sensor_empty) -new_flow_logic_register.simple(valve_on) --- don't register valve_off, automatically makes it block flow in the new logic new_flow_logic_register.simple(entry_panel_empty) new_flow_logic_register.simple(flow_sensor_empty) @@ -211,7 +209,6 @@ local flow_sensor_loaded = "pipeworks:flow_sensor_loaded" table.insert(pipes_full_nodenames, valve_on_loaded) table.insert(pipes_full_nodenames, entry_panel_loaded) table.insert(pipes_full_nodenames, flow_sensor_loaded) -new_flow_logic_register.simple(valve_on_loaded) new_flow_logic_register.simple(entry_panel_loaded) new_flow_logic_register.simple(flow_sensor_loaded) From 13383770ef61d93899ad272586daeb0d8d3b4072 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 18:18:47 +0100 Subject: [PATCH 29/75] move spigot behaviour registration to devices.lua --- devices.lua | 9 +++++++++ new_flow_logic/register_local_pipes.lua | 8 ++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/devices.lua b/devices.lua index 8b1725b..fd48033 100644 --- a/devices.lua +++ b/devices.lua @@ -372,6 +372,15 @@ minetest.register_node(nodename_spigot_loaded, { drop = "pipeworks:spigot", on_rotate = pipeworks.fix_after_rotation }) +-- new flow logic does not currently distinguish between these two visual states. +-- register both so existing flowing spigots continue to work (even if the visual doesn't match the spigot's behaviour). +new_flow_logic_register.simple(nodename_spigot_empty) +new_flow_logic_register.simple(nodename_spigot_loaded) +local spigot_min = 1 +new_flow_logic_register.output(nodename_spigot_empty, spigot_min, pipeworks.flowlogic.helpers.output_spigot) +new_flow_logic_register.output(nodename_spigot_loaded, spigot_min, pipeworks.flowlogic.helpers.output_spigot) + + -- sealed pipe entry/exit (horizontal pipe passing through a metal -- wall, for use in places where walls should look like they're airtight) diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua index 005a812..0de0056 100644 --- a/new_flow_logic/register_local_pipes.lua +++ b/new_flow_logic/register_local_pipes.lua @@ -42,13 +42,13 @@ if pipeworks.enable_pipes then if pipeworks.enable_pipe_devices then --register.simple(pump_off) --register.simple(pump_on) - register.simple(spigot_on) - register.simple(spigot_off) + --register.simple(spigot_on) + --register.simple(spigot_off) --register.intake_simple(pump_on, thresholds.pump_pressure) -- TODO: the code doesn't currently care if the spigot is the visually flowing node or not. -- So some mechanism to register on/off states would be nice - register.output(spigot_off, thresholds.spigot_min, flowlogic.helpers.output_spigot) - register.output(spigot_on, thresholds.spigot_min, flowlogic.helpers.output_spigot) + --register.output(spigot_off, thresholds.spigot_min, flowlogic.helpers.output_spigot) + --register.output(spigot_on, thresholds.spigot_min, flowlogic.helpers.output_spigot) end end From 396a4fdacdd6f80e3bba55cd6c26a2ae321179d1 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 18:23:58 +0100 Subject: [PATCH 30/75] remove register_local_pipes.lua as node registration has been moved to more appropriate files --- init.lua | 8 ++-- new_flow_logic/register_local_pipes.lua | 54 ------------------------- todo/new_flow_logic.txt | 4 -- 3 files changed, 3 insertions(+), 63 deletions(-) delete mode 100644 new_flow_logic/register_local_pipes.lua diff --git a/init.lua b/init.lua index e8a8d2f..2a95be6 100644 --- a/init.lua +++ b/init.lua @@ -121,7 +121,9 @@ dofile(pipeworks.modpath.."/wielder.lua") local logicdir = "/new_flow_logic/" --- note that even with these files the new flow logic is not yet default +-- note that even with these files the new flow logic is not yet default. +-- registration will take place but no actual ABMs/node logic will be installed, +-- unless pipeworks.enable_new_flow_logic has been set. dofile(pipeworks.modpath..logicdir.."flowable_node_registry.lua") dofile(pipeworks.modpath..logicdir.."abms.lua") dofile(pipeworks.modpath..logicdir.."abm_register.lua") @@ -130,10 +132,6 @@ dofile(pipeworks.modpath..logicdir.."flowable_node_registry_install.lua") if pipeworks.enable_pipes then dofile(pipeworks.modpath.."/pipes.lua") end if pipeworks.enable_teleport_tube then dofile(pipeworks.modpath.."/teleport_tube.lua") end if pipeworks.enable_pipe_devices then dofile(pipeworks.modpath.."/devices.lua") end --- individual enable flags also checked in register_local_pipes.lua -if pipeworks.enable_new_flow_logic then - dofile(pipeworks.modpath..logicdir.."register_local_pipes.lua") -end if pipeworks.enable_redefines then dofile(pipeworks.modpath.."/compat-chests.lua") diff --git a/new_flow_logic/register_local_pipes.lua b/new_flow_logic/register_local_pipes.lua deleted file mode 100644 index 0de0056..0000000 --- a/new_flow_logic/register_local_pipes.lua +++ /dev/null @@ -1,54 +0,0 @@ --- registration of pipework's own pipes. --- written 2017 by thetaepsilon - - - --- global values and thresholds for water behaviour --- TODO: add some way of setting this per-world -local thresholds = {} --- limit on pump pressure - will not absorb more than can be taken -thresholds.pump_pressure = 2 --- activation threshold for spigot --- should not be below 1, as spigot helper code indiscriminately places a water source node if run. -thresholds.spigot_min = 1 - - - -local pipes_full_nodenames = pipeworks.pipes_full_nodenames -local pipes_empty_nodenames = pipeworks.pipes_empty_nodenames - -local register = pipeworks.flowables.register -local flowlogic = pipeworks.flowlogic - - - --- FIXME: DRY principle for names, move this to devices.lua? --- FIXME: all devices still considered simple -local pump_on = "pipeworks:pump_on" -local pump_off = "pipeworks:pump_off" -local spigot_off = "pipeworks:spigot" -local spigot_on = "pipeworks:spigot_pouring" - -if pipeworks.enable_pipes then - --[[ - for _, pipe in ipairs(pipes_full_nodenames) do - register.simple(pipe) - end - for _, pipe in ipairs(pipes_empty_nodenames) do - register.simple(pipe) - end - ]] - - if pipeworks.enable_pipe_devices then - --register.simple(pump_off) - --register.simple(pump_on) - --register.simple(spigot_on) - --register.simple(spigot_off) - - --register.intake_simple(pump_on, thresholds.pump_pressure) - -- TODO: the code doesn't currently care if the spigot is the visually flowing node or not. - -- So some mechanism to register on/off states would be nice - --register.output(spigot_off, thresholds.spigot_min, flowlogic.helpers.output_spigot) - --register.output(spigot_on, thresholds.spigot_min, flowlogic.helpers.output_spigot) - end -end diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt index acd6d1a..46f6c22 100644 --- a/todo/new_flow_logic.txt +++ b/todo/new_flow_logic.txt @@ -1,6 +1,2 @@ --- Per-world configuration of pump thresholds -This should be relatively trivial to do, just a case of adding another property to the pipeworks global that can be set per-world with pipeworks_settings.txt. -This does not appear to be that big a deal right now, as the internal threshold can always be changed. - -- Internal code to the effect of "is_node_flowable()" This is basically to implement valves - currently the flow logic will happily balance pipes with neighbour nodes that just happen to have the pressure property in their metadata. From de44593b414cf024d70027297236f582309daa09 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 18:30:32 +0100 Subject: [PATCH 31/75] move flowable registration for airtight entry panel to devices.lua near node definition --- devices.lua | 6 ++++++ pipes.lua | 2 -- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/devices.lua b/devices.lua index fd48033..4344c83 100644 --- a/devices.lua +++ b/devices.lua @@ -433,6 +433,12 @@ minetest.register_node(nodename_panel_loaded, { drop = "pipeworks:entry_panel_empty", on_rotate = pipeworks.fix_after_rotation }) +-- FIXME requires-directionality +-- TODO: AFAIK the two panels have no visual difference, so are redundant under new flow logic - alias? +new_flow_logic_register.simple(nodename_panel_empty) +new_flow_logic_register.simple(nodename_panel_loaded) + + local nodename_sensor_empty = "pipeworks:flow_sensor_empty" minetest.register_node(nodename_sensor_empty, { diff --git a/pipes.lua b/pipes.lua index 751d460..46139ed 100644 --- a/pipes.lua +++ b/pipes.lua @@ -200,7 +200,6 @@ table.insert(pipes_empty_nodenames, valve_on) table.insert(pipes_empty_nodenames, valve_off) table.insert(pipes_empty_nodenames, entry_panel_empty) table.insert(pipes_empty_nodenames, flow_sensor_empty) -new_flow_logic_register.simple(entry_panel_empty) new_flow_logic_register.simple(flow_sensor_empty) local valve_on_loaded = "pipeworks:valve_on_loaded" @@ -209,7 +208,6 @@ local flow_sensor_loaded = "pipeworks:flow_sensor_loaded" table.insert(pipes_full_nodenames, valve_on_loaded) table.insert(pipes_full_nodenames, entry_panel_loaded) table.insert(pipes_full_nodenames, flow_sensor_loaded) -new_flow_logic_register.simple(entry_panel_loaded) new_flow_logic_register.simple(flow_sensor_loaded) pipeworks.pipes_full_nodenames = pipes_full_nodenames From df3d54f58a7b00880f6631e309fba08fb769cd33 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 18:34:55 +0100 Subject: [PATCH 32/75] move flowable registration for flow sensor to devices.lua near node definition --- devices.lua | 8 +++++++- pipes.lua | 5 +---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/devices.lua b/devices.lua index 4344c83..f4f2150 100644 --- a/devices.lua +++ b/devices.lua @@ -518,10 +518,15 @@ minetest.register_node(nodename_sensor_loaded, { mesecons = pipereceptor_on, on_rotate = pipeworks.fix_after_rotation }) +-- FIXME requires-directionality +new_flow_logic_register.simple(nodename_sensor_empty) +new_flow_logic_register.simple(nodename_sensor_loaded) + + -- tanks --- TODO: these don't currently do anything under the new flow logic. +-- TODO flow-logic-stub: these don't currently do anything under the new flow logic. for fill = 0, 10 do local filldesc="empty" local sgroups = {snappy=3, pipe=1, tankfill=fill+1} @@ -592,6 +597,7 @@ end -- fountainhead +-- TODO flow-logic-stub: fountainheads currently non-functional under new flow logic local nodename_fountain_empty = "pipeworks:fountainhead" minetest.register_node(nodename_fountain_empty, { description = "Fountainhead", diff --git a/pipes.lua b/pipes.lua index 46139ed..c6ba09b 100644 --- a/pipes.lua +++ b/pipes.lua @@ -188,9 +188,8 @@ if REGISTER_COMPATIBILITY then }) end --- appropriate registration for both old and new flow logic follows --- FIXME/TODO: these aren't really "simple", they have directionality. + local valve_on = "pipeworks:valve_on_empty" local valve_off = "pipeworks:valve_off_empty" local entry_panel_empty = "pipeworks:entry_panel_empty" @@ -200,7 +199,6 @@ table.insert(pipes_empty_nodenames, valve_on) table.insert(pipes_empty_nodenames, valve_off) table.insert(pipes_empty_nodenames, entry_panel_empty) table.insert(pipes_empty_nodenames, flow_sensor_empty) -new_flow_logic_register.simple(flow_sensor_empty) local valve_on_loaded = "pipeworks:valve_on_loaded" local entry_panel_loaded = "pipeworks:entry_panel_loaded" @@ -208,7 +206,6 @@ local flow_sensor_loaded = "pipeworks:flow_sensor_loaded" table.insert(pipes_full_nodenames, valve_on_loaded) table.insert(pipes_full_nodenames, entry_panel_loaded) table.insert(pipes_full_nodenames, flow_sensor_loaded) -new_flow_logic_register.simple(flow_sensor_loaded) pipeworks.pipes_full_nodenames = pipes_full_nodenames pipeworks.pipes_empty_nodenames = pipes_empty_nodenames From 9abdeb3d626c702c044d6d621bdea6c43dbd6647 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 20:12:19 +0100 Subject: [PATCH 33/75] new flow logic: abms.lua: use flowable nodes registry to determine viable neighbours --- new_flow_logic/abms.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 640493a..66349e9 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -49,8 +49,9 @@ flowlogic.check_for_liquids_v2 = check_for_liquids_v2 +--local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..tostring(vec.y)..sep..tostring(vec.z)..")" end + local label_pressure = "pipeworks.water_pressure" -local label_haspressure = "pipeworks.is_pressure_node" flowlogic.balance_pressure = function(pos, node) -- debuglog("balance_pressure() "..node.name.." at "..pos.x.." "..pos.y.." "..pos.z) -- check the pressure of all nearby nodes, and average it out. @@ -60,16 +61,19 @@ flowlogic.balance_pressure = function(pos, node) -- unconditionally include self in nodes to average over local meta = minetest.get_meta(pos) local currentpressure = meta:get_float(label_pressure) - meta:set_int(label_haspressure, 1) local connections = { meta } local totalv = currentpressure local totalc = 1 -- then handle neighbours, but if not a pressure node don't consider them at all for _, npos in ipairs(make_coords_offsets(pos, false)) do + local nodename = minetest.get_node(npos).name local neighbour = minetest.get_meta(npos) - local haspressure = (neighbour:get_int(label_haspressure) ~= 0) + -- for now, just check if it's in the simple table. + -- TODO: the "can flow from" logic in flowable_node_registry.lua + local haspressure = (pipeworks.flowables.list.simple[nodename]) if haspressure then + --pipeworks.logger("balance_pressure @ "..formatvec(pos).." "..nodename.." "..formatvec(npos).." added to neighbour set") local n = neighbour:get_float(label_pressure) table.insert(connections, neighbour) totalv = totalv + n From dc13ec619f7e49b0e75f845f8baa0559a8b11936 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 20:27:30 +0100 Subject: [PATCH 34/75] new flow logic: abms.lua: remove intake limit coercion causing water to be vanished --- new_flow_logic/abms.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 66349e9..afeb3b3 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -29,6 +29,8 @@ end +--local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..tostring(vec.y)..sep..tostring(vec.z)..")" end + -- new version of liquid check -- accepts a limit parameter to only delete water blocks that the receptacle can accept, -- and returns it so that the receptacle can update it's pressure values. @@ -43,14 +45,13 @@ local check_for_liquids_v2 = function(pos, limit) total = total + 1 end end + --pipeworks.logger("check_for_liquids_v2@"..formatvec(pos).." total "..total) return total end flowlogic.check_for_liquids_v2 = check_for_liquids_v2 ---local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..tostring(vec.y)..sep..tostring(vec.z)..")" end - local label_pressure = "pipeworks.water_pressure" flowlogic.balance_pressure = function(pos, node) -- debuglog("balance_pressure() "..node.name.." at "..pos.x.." "..pos.y.." "..pos.z) @@ -100,8 +101,8 @@ flowlogic.run_input = function(pos, node, maxpressure, intakefn) if intake_limit <= 0 then return end local actual_intake = intakefn(pos, intake_limit) + --pipeworks.logger("run_input@"..formatvec(pos).." oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake) if actual_intake <= 0 then return end - if actual_intake >= intake_limit then actual_intake = intake_limit end local newpressure = actual_intake + currentpressure -- debuglog("oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake.." newpressure "..newpressure) From 667eeb7d095f12d5c7e560d161697878ea485433 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 21:04:07 +0100 Subject: [PATCH 35/75] new flow logic: abms.lua: generalise spigot output code to support arbitary neighbour lists --- devices.lua | 5 +++-- new_flow_logic/abms.lua | 44 +++++++++++++++-------------------------- 2 files changed, 19 insertions(+), 30 deletions(-) diff --git a/devices.lua b/devices.lua index f4f2150..d12c84a 100644 --- a/devices.lua +++ b/devices.lua @@ -377,8 +377,9 @@ minetest.register_node(nodename_spigot_loaded, { new_flow_logic_register.simple(nodename_spigot_empty) new_flow_logic_register.simple(nodename_spigot_loaded) local spigot_min = 1 -new_flow_logic_register.output(nodename_spigot_empty, spigot_min, pipeworks.flowlogic.helpers.output_spigot) -new_flow_logic_register.output(nodename_spigot_loaded, spigot_min, pipeworks.flowlogic.helpers.output_spigot) +local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output({{x=0, y=-1, z=0}}) +new_flow_logic_register.output(nodename_spigot_empty, spigot_min, outputfn) +new_flow_logic_register.output(nodename_spigot_loaded, spigot_min, outputfn) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index afeb3b3..a07c390 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -111,19 +111,23 @@ end --- flowlogic output helper for spigots --- tries to place a water block in the world beneath the spigot. --- threshold checking is assumed to be handled by the node registration; --- see register_local_pipes.lua for the pipeworks default spigot. -flowlogic.helpers.output_spigot = function(pos, node, currentpressure) - local taken = 0 - local below = {x=pos.x, y=pos.y-1, z=pos.z} - local name = minetest.get_node(below).name - if (name == "air") or (name == "default:water_flowing") then - minetest.set_node(below, {name="default:water_source"}) - taken = taken + 1 +-- flowlogic output helper implementation: +-- outputs water by trying to place water nodes nearby in the world. +-- neighbours is a list of node offsets to try placing water in. +-- this is a constructor function, returning another function which satisfies the output helper requirements. +flowlogic.helpers.make_neighbour_output = function(neighbours) + return function(pos, node, currentpressure) + local taken = 0 + for _, offset in pairs(neighbours) do + local npos = vector.add(pos, offset) + local name = minetest.get_node(npos).name + if (name == "air") or (name == "default:water_flowing") then + minetest.swap_node(npos, {name="default:water_source"}) + taken = taken + 1 + end + end + return taken end - return taken end @@ -145,19 +149,3 @@ flowlogic.run_output = function(pos, node, threshold, outputfn) meta:set_float(label_pressure, newpressure) end end - - - -flowlogic.run_spigot_output = function(pos, node) - -- try to output a water source node if there's enough pressure and space below. - local meta = minetest.get_meta(pos) - local currentpressure = meta:get_float(label_pressure) - if currentpressure > 1 then - local below = {x=pos.x, y=pos.y-1, z=pos.z} - local name = minetest.get_node(below).name - if (name == "air") or (name == "default:water_flowing") then - minetest.set_node(below, {name="default:water_source"}) - meta:set_float(label_pressure, currentpressure - 1) - end - end -end From 76ebd0a0e1552e0b519716deca3d77e03d1b6b94 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 21:17:05 +0100 Subject: [PATCH 36/75] devices.lua: make fountains functional under new flow logic using new neighbour output helper --- devices.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/devices.lua b/devices.lua index d12c84a..995f1da 100644 --- a/devices.lua +++ b/devices.lua @@ -598,7 +598,6 @@ end -- fountainhead --- TODO flow-logic-stub: fountainheads currently non-functional under new flow logic local nodename_fountain_empty = "pipeworks:fountainhead" minetest.register_node(nodename_fountain_empty, { description = "Fountainhead", @@ -668,6 +667,14 @@ minetest.register_node(nodename_fountain_loaded, { drop = "pipeworks:fountainhead", on_rotate = false }) +new_flow_logic_register.simple(nodename_fountain_empty) +new_flow_logic_register.simple(nodename_fountain_loaded) +local fountain_min = 1 +local fountainfn = pipeworks.flowlogic.helpers.make_neighbour_output({{x=0, y=1, z=0}}) +new_flow_logic_register.output(nodename_fountain_empty, fountain_min, fountainfn) +new_flow_logic_register.output(nodename_fountain_loaded, fountain_min, fountainfn) + + minetest.register_alias("pipeworks:valve_off_loaded", "pipeworks:valve_off_empty") minetest.register_alias("pipeworks:entry_panel", "pipeworks:entry_panel_empty") From 8e53526b545e2dc0a05066fb18f064a394e20740 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 1 Oct 2017 21:20:30 +0100 Subject: [PATCH 37/75] new flow logic: abms.lua: rename neighbour output helper to better indicate lack of rotation support --- devices.lua | 4 ++-- new_flow_logic/abms.lua | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/devices.lua b/devices.lua index 995f1da..1eb18be 100644 --- a/devices.lua +++ b/devices.lua @@ -377,7 +377,7 @@ minetest.register_node(nodename_spigot_loaded, { new_flow_logic_register.simple(nodename_spigot_empty) new_flow_logic_register.simple(nodename_spigot_loaded) local spigot_min = 1 -local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output({{x=0, y=-1, z=0}}) +local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed({{x=0, y=-1, z=0}}) new_flow_logic_register.output(nodename_spigot_empty, spigot_min, outputfn) new_flow_logic_register.output(nodename_spigot_loaded, spigot_min, outputfn) @@ -670,7 +670,7 @@ minetest.register_node(nodename_fountain_loaded, { new_flow_logic_register.simple(nodename_fountain_empty) new_flow_logic_register.simple(nodename_fountain_loaded) local fountain_min = 1 -local fountainfn = pipeworks.flowlogic.helpers.make_neighbour_output({{x=0, y=1, z=0}}) +local fountainfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed({{x=0, y=1, z=0}}) new_flow_logic_register.output(nodename_fountain_empty, fountain_min, fountainfn) new_flow_logic_register.output(nodename_fountain_loaded, fountain_min, fountainfn) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index a07c390..15adcef 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -115,7 +115,8 @@ end -- outputs water by trying to place water nodes nearby in the world. -- neighbours is a list of node offsets to try placing water in. -- this is a constructor function, returning another function which satisfies the output helper requirements. -flowlogic.helpers.make_neighbour_output = function(neighbours) +-- note that this does *not* take rotation into account. +flowlogic.helpers.make_neighbour_output_fixed = function(neighbours) return function(pos, node, currentpressure) local taken = 0 for _, offset in pairs(neighbours) do From 894ea5174fb8c3be9038698cb119b24acbec8cea Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Tue, 3 Oct 2017 20:38:56 +0100 Subject: [PATCH 38/75] move new flow logic flag to dedicated toggles table --- init.lua | 8 +++++--- new_flow_logic/flowable_node_registry_install.lua | 8 ++++---- pipes.lua | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/init.lua b/init.lua index 2a95be6..8bae8e8 100644 --- a/init.lua +++ b/init.lua @@ -17,14 +17,16 @@ dofile(pipeworks.modpath.."/default_settings.lua") -- Read the external config file if it exists. +-- please add any new feature toggles to be a flag in this table... +pipeworks.toggles = {} local worldsettingspath = pipeworks.worldpath.."/pipeworks_settings.txt" local worldsettingsfile = io.open(worldsettingspath, "r") if worldsettingsfile then worldsettingsfile:close() dofile(worldsettingspath) end -if pipeworks.enable_new_flow_logic then - minetest.log("warning", "pipeworks new_flow_logic is WIP and incomplete!") +if pipeworks.toggles.pressure_logic then + minetest.log("warning", "pipeworks pressure-based logic is WIP and incomplete!") end -- Random variables @@ -123,7 +125,7 @@ local logicdir = "/new_flow_logic/" -- note that even with these files the new flow logic is not yet default. -- registration will take place but no actual ABMs/node logic will be installed, --- unless pipeworks.enable_new_flow_logic has been set. +-- unless the toggle flag is specifically enabled in the per-world settings flag. dofile(pipeworks.modpath..logicdir.."flowable_node_registry.lua") dofile(pipeworks.modpath..logicdir.."abms.lua") dofile(pipeworks.modpath..logicdir.."abm_register.lua") diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index ac305dc..defe877 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -24,7 +24,7 @@ end local regwarning = function(kind, nodename) local tail = "" - if not pipeworks.enable_new_flow_logic then tail = " but new_flow_logic not enabled" end + if not pipeworks.toggles.pressure_logic then tail = " but pressure logic not enabled" end pipeworks.logger(kind.." flow logic registry requested for "..nodename..tail) end @@ -35,7 +35,7 @@ register.simple = function(nodename) insertbase(nodename) pipeworks.flowables.list.simple[nodename] = true table.insert(pipeworks.flowables.list.simple_nodenames, nodename) - if pipeworks.enable_new_flow_logic then + if pipeworks.toggles.pressure_logic then abmregister.balance(nodename) end regwarning("simple", nodename) @@ -54,7 +54,7 @@ register.intake_simple = function(nodename, maxpressure) checkbase(nodename) pipeworks.flowables.inputs.list[nodename] = { maxpressure=maxpressure } table.insert(pipeworks.flowables.inputs.nodenames, nodename) - if pipeworks.enable_new_flow_logic then + if pipeworks.toggles.pressure_logic then abmregister.input(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) end regwarning("simple intake", nodename) @@ -66,7 +66,7 @@ end register.output = function(nodename, threshold, outputfn) checkbase(nodename) pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } - if pipeworks.enable_new_flow_logic then + if pipeworks.toggles.pressure_logic then abmregister.output(nodename, threshold, outputfn) end regwarning("output node", nodename) diff --git a/pipes.lua b/pipes.lua index c6ba09b..2acdfa9 100644 --- a/pipes.lua +++ b/pipes.lua @@ -213,7 +213,7 @@ pipeworks.pipes_empty_nodenames = pipes_empty_nodenames -if not pipeworks.enable_new_flow_logic then +if not pipeworks.toggles.pressure_logic then From 750612181a67b9bf4ad4bd01c2d90472e8a41a6d Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Tue, 3 Oct 2017 20:53:49 +0100 Subject: [PATCH 39/75] add finite water feature toggle and auto-detect code --- autodetect-finite-water.lua | 9 +++++++++ init.lua | 5 +++++ 2 files changed, 14 insertions(+) create mode 100644 autodetect-finite-water.lua diff --git a/autodetect-finite-water.lua b/autodetect-finite-water.lua new file mode 100644 index 0000000..d218e80 --- /dev/null +++ b/autodetect-finite-water.lua @@ -0,0 +1,9 @@ +-- enable finite liquid in the presence of dynamic liquid to preserve water volume. +local enable = false + +if minetest.get_modpath("dynamic_liquid") then + pipeworks.logger("detected mod dynamic_liquid, enabling finite liquid flag") + enable = true +end + +pipeworks.toggles.finite_water = enable diff --git a/init.lua b/init.lua index 8bae8e8..8974005 100644 --- a/init.lua +++ b/init.lua @@ -103,6 +103,11 @@ end ------------------------------------------- -- Load the various other parts of the mod +-- early auto-detection for finite water mode if not explicitly disabled +if pipeworks.toggles.finite_water == nil then + dofile(pipeworks.modpath.."/autodetect-finite-water.lua") +end + dofile(pipeworks.modpath.."/common.lua") dofile(pipeworks.modpath.."/models.lua") dofile(pipeworks.modpath.."/autoplace_pipes.lua") From 7eb5dc6aca664bbca5c81203f5d72d9abc39578c Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Wed, 4 Oct 2017 18:54:51 +0100 Subject: [PATCH 40/75] flowable_node_registry_install.lua: silence registration debugging by default --- new_flow_logic/flowable_node_registry_install.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index defe877..79f5997 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -25,7 +25,7 @@ end local regwarning = function(kind, nodename) local tail = "" if not pipeworks.toggles.pressure_logic then tail = " but pressure logic not enabled" end - pipeworks.logger(kind.." flow logic registry requested for "..nodename..tail) + --pipeworks.logger(kind.." flow logic registry requested for "..nodename..tail) end -- Register a node as a simple flowable. From 465e28cbd3e2d176a4ca0429711bc459fe37cf0d Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 12:16:36 +0100 Subject: [PATCH 41/75] devices.lua: factor out usage of flowlogic helper into dedicated registry function --- devices.lua | 12 ++++++------ new_flow_logic/flowable_node_registry_install.lua | 4 ++++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/devices.lua b/devices.lua index 1eb18be..61648da 100644 --- a/devices.lua +++ b/devices.lua @@ -377,9 +377,9 @@ minetest.register_node(nodename_spigot_loaded, { new_flow_logic_register.simple(nodename_spigot_empty) new_flow_logic_register.simple(nodename_spigot_loaded) local spigot_min = 1 -local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed({{x=0, y=-1, z=0}}) -new_flow_logic_register.output(nodename_spigot_empty, spigot_min, outputfn) -new_flow_logic_register.output(nodename_spigot_loaded, spigot_min, outputfn) +local spigot_neighbours={{x=0, y=-1, z=0}} +new_flow_logic_register.output_simple(nodename_spigot_empty, spigot_min, spigot_neighbours) +new_flow_logic_register.output_simple(nodename_spigot_loaded, spigot_min, spigot_neighbours) @@ -670,9 +670,9 @@ minetest.register_node(nodename_fountain_loaded, { new_flow_logic_register.simple(nodename_fountain_empty) new_flow_logic_register.simple(nodename_fountain_loaded) local fountain_min = 1 -local fountainfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed({{x=0, y=1, z=0}}) -new_flow_logic_register.output(nodename_fountain_empty, fountain_min, fountainfn) -new_flow_logic_register.output(nodename_fountain_loaded, fountain_min, fountainfn) +local fountain_neighbours={{x=0, y=1, z=0}} +new_flow_logic_register.output_simple(nodename_fountain_empty, fountain_min, fountain_neighbours) +new_flow_logic_register.output_simple(nodename_fountain_loaded, fountain_min, fountain_neighbours) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 79f5997..3d9ce0a 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -77,3 +77,7 @@ end -- which tries to place water nodes around it. -- possibly this could be given a helper function to determine which faces a node should try, -- to allow things like rotation or other param values determining "direction" to be respected. +register.output_simple = function(nodename, threshold, neighbours) + local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed(neighbours) + register.output(nodename, threshold, outputfn) +end From 4f58a3039c55783978d5f85fbf59f06025884384 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 13:05:52 +0100 Subject: [PATCH 42/75] new flow logic: flowable_node_registry_install.lua: separate pressure threshold into upper and lower hysteresis values --- devices.lua | 14 ++++++++------ .../flowable_node_registry_install.lua | 18 +++++++++++++----- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/devices.lua b/devices.lua index 61648da..26b9275 100644 --- a/devices.lua +++ b/devices.lua @@ -376,10 +376,11 @@ minetest.register_node(nodename_spigot_loaded, { -- register both so existing flowing spigots continue to work (even if the visual doesn't match the spigot's behaviour). new_flow_logic_register.simple(nodename_spigot_empty) new_flow_logic_register.simple(nodename_spigot_loaded) -local spigot_min = 1 +local spigot_upper = 1.5 +local spigot_lower = 1.0 local spigot_neighbours={{x=0, y=-1, z=0}} -new_flow_logic_register.output_simple(nodename_spigot_empty, spigot_min, spigot_neighbours) -new_flow_logic_register.output_simple(nodename_spigot_loaded, spigot_min, spigot_neighbours) +new_flow_logic_register.output_simple(nodename_spigot_empty, spigot_upper, spigot_lower, spigot_neighbours) +new_flow_logic_register.output_simple(nodename_spigot_loaded, spigot_upper, spigot_lower, spigot_neighbours) @@ -669,10 +670,11 @@ minetest.register_node(nodename_fountain_loaded, { }) new_flow_logic_register.simple(nodename_fountain_empty) new_flow_logic_register.simple(nodename_fountain_loaded) -local fountain_min = 1 +local fountain_upper = 1.5 +local fountain_lower = 1.0 local fountain_neighbours={{x=0, y=1, z=0}} -new_flow_logic_register.output_simple(nodename_fountain_empty, fountain_min, fountain_neighbours) -new_flow_logic_register.output_simple(nodename_fountain_loaded, fountain_min, fountain_neighbours) +new_flow_logic_register.output_simple(nodename_fountain_empty, fountain_upper, fountain_lower, fountain_neighbours) +new_flow_logic_register.output_simple(nodename_fountain_loaded, fountain_upper, fountain_lower, fountain_neighbours) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 3d9ce0a..7f414c4 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -62,12 +62,19 @@ end -- Register a node as an output. -- Expects node to already be a flowable. --- threshold and outputfn are currently as documented for register_abm_output() in abm_register.lua. -register.output = function(nodename, threshold, outputfn) +-- upper and lower thresholds have different meanings depending on whether finite liquid mode is in effect. +-- if not (the default unless auto-detected), +-- nodes above their upper threshold have their outputfn invoked (and pressure deducted), +-- nodes between upper and lower are left idle, +-- and nodes below lower have their cleanup fn invoked (to say remove water sources). +-- the upper and lower difference acts as a hysteresis to try and avoid "gaps" in the flow. +-- if finite mode is on, upper is ignored and lower is used to determine whether to run outputfn; +-- cleanupfn is ignored in this mode as finite mode assumes something causes water to move itself. +register.output = function(nodename, upper, lower, outputfn) checkbase(nodename) pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } if pipeworks.toggles.pressure_logic then - abmregister.output(nodename, threshold, outputfn) + abmregister.output(nodename, lower, outputfn) end regwarning("output node", nodename) end @@ -77,7 +84,8 @@ end -- which tries to place water nodes around it. -- possibly this could be given a helper function to determine which faces a node should try, -- to allow things like rotation or other param values determining "direction" to be respected. -register.output_simple = function(nodename, threshold, neighbours) +-- for meanings of upper and lower, see register.output() above. +register.output_simple = function(nodename, upper, lower, neighbours) local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed(neighbours) - register.output(nodename, threshold, outputfn) + register.output(nodename, upper, lower, outputfn) end From 31a67cf4f98f0c9850998799956063401efceef5 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 13:15:42 +0100 Subject: [PATCH 43/75] new flow logic: flowable_node_registry_install.lua: add proper documentation for register.output_simple() --- new_flow_logic/flowable_node_registry_install.lua | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 7f414c4..650d1da 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -79,12 +79,17 @@ register.output = function(nodename, upper, lower, outputfn) regwarning("output node", nodename) end --- TODOs here: --- The spigot's output behaviour (and possibly the fountain) could be abstracted out into a "simple output" of sorts, --- which tries to place water nodes around it. --- possibly this could be given a helper function to determine which faces a node should try, --- to allow things like rotation or other param values determining "direction" to be respected. +-- register a simple output: +-- drains pressure by attempting to place water in nearby nodes, +-- which can be set by passing a list of offset vectors. +-- will attempt to drain as many whole nodes as there are positions in the offset list. -- for meanings of upper and lower, see register.output() above. +-- non-finite mode: +-- above upper pressure: places water sources as appropriate, keeps draining pressure. +-- below lower presssure: removes it's neighbour water sources. +-- finite mode: +-- same as for above pressure in non-finite mode, +-- but only drains pressure when water source nodes are actually placed. register.output_simple = function(nodename, upper, lower, neighbours) local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed(neighbours) register.output(nodename, upper, lower, outputfn) From 6f90ee0875dd0f89f460b6ae75acac708a63cb4c Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 13:24:46 +0100 Subject: [PATCH 44/75] new flow logic: abms.lua: add companion cleaner helper for neighbour output --- new_flow_logic/abms.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 15adcef..7a720be 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -131,6 +131,21 @@ flowlogic.helpers.make_neighbour_output_fixed = function(neighbours) end end +-- complementary function to the above when using non-finite mode: +-- removes water sources from neighbor positions when the output is "off" due to lack of pressure. +flowlogic.helpers.make_neighbour_cleanup_fixed = function(neighbours) + return function(pos, node, currentpressure) + -- FIXME - this would indiscriminately take blocks while under-pressure, not just one time? + for _, offset in pairs(neighbours) do + local npos = vector.add(pos, offset) + local name = minetest.get_node(npos).name + if (name == "default:water_source") then + minetest.remove_node(pos) + end + end + end +end + flowlogic.run_output = function(pos, node, threshold, outputfn) From 57362118dc3a8cfc8eb19997ab54eb307e8e2b44 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 13:25:44 +0100 Subject: [PATCH 45/75] todo: remove old item for is_node_flowable() --- todo/new_flow_logic.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt index 46f6c22..e69de29 100644 --- a/todo/new_flow_logic.txt +++ b/todo/new_flow_logic.txt @@ -1,2 +0,0 @@ --- Internal code to the effect of "is_node_flowable()" -This is basically to implement valves - currently the flow logic will happily balance pipes with neighbour nodes that just happen to have the pressure property in their metadata. From 157f117c62fafc13994a96bfa5677c40e30ce1b3 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 13:40:38 +0100 Subject: [PATCH 46/75] todo: new flow logic: add directionality code and ABM ordering items --- todo/new_flow_logic.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt index e69de29..ab7eebd 100644 --- a/todo/new_flow_logic.txt +++ b/todo/new_flow_logic.txt @@ -0,0 +1,11 @@ +-- Directionality code +Currently, only "simple" flowable nodes exist, and they will always equalise pressure with all six neighbours. +A more sophisticated behaviour for this would be flowable node registration with some kind of custom callback, such that water can only flow into or out of these nodes in certain directions. +This would enable devices such as the airtight panels, sensor tubes and valves to have correct flow behaviour. + +-- ABM ordering for event-driven "dropped below threshold" events +For the non-finite liquid mode, cleanup handlers are invoked continuously while pressure is below a certain amount. +This could potentially mean that a below-pressure output node such as a spigot could potentially keep deleting the water source node beneath it, even when one is placed there afterwards by a player say. +Furthermore, attempting to fix this with a "previous pressure" metadata variable is of little use, as the output code is current run in a separate ABM - so the correct sequencing of events cannot be guaranteed. +Therefore, the current code needs revising such that a node's output (or input) handlers are invoked from the main flow logic ABM, in order to ensure correct ordering. +This would also allow the code to compare old and new pressure, and invoke the cleanup handler *only once* if the pressure has dropped from above to below the threshold, and not continuously. From d175f0b94f8164552dc141778f6d832b5faf73a0 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 13:49:33 +0100 Subject: [PATCH 47/75] todo: new flow logic: add item for node variant switching --- todo/new_flow_logic.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt index ab7eebd..5daa80d 100644 --- a/todo/new_flow_logic.txt +++ b/todo/new_flow_logic.txt @@ -9,3 +9,10 @@ This could potentially mean that a below-pressure output node such as a spigot c Furthermore, attempting to fix this with a "previous pressure" metadata variable is of little use, as the output code is current run in a separate ABM - so the correct sequencing of events cannot be guaranteed. Therefore, the current code needs revising such that a node's output (or input) handlers are invoked from the main flow logic ABM, in order to ensure correct ordering. This would also allow the code to compare old and new pressure, and invoke the cleanup handler *only once* if the pressure has dropped from above to below the threshold, and not continuously. + +-- Automated switching between node variants based on pressure thresholds +When the ABM ordering is complete, an additional callback which would be useful is a "node changer" callback, to switch between variations of a pipe depending on pressure level. +For regular pipes, this is mostly aesthetic, as the empty/loaded variants of the pipes have different texures. +However, the flow sensor is currently a broken device under the new flow logic, as there is nothing to switch this device between the "on" and "off" state - in order to produce a mesecons output, separate nodes are required due to mesecon's API being limited to only on/off for a given node, with no facility for a callback function which could e.g. inspect pressure metadata. +To make this work, a new registry table would be needed to check if a flowable node has this property. +In terms of ordering, this callback should be run after outputs have been processed. From 1669cfd4510a2dbb2ca3c754b414ae8c976ceca1 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 15:42:00 +0100 Subject: [PATCH 48/75] new flow logic: flowable_node_registry_install.lua: add duplicate registration guard for register.output() --- new_flow_logic/flowable_node_registry_install.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 650d1da..07001ef 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -71,6 +71,9 @@ end -- if finite mode is on, upper is ignored and lower is used to determine whether to run outputfn; -- cleanupfn is ignored in this mode as finite mode assumes something causes water to move itself. register.output = function(nodename, upper, lower, outputfn) + if pipeworks.flowables.outputs.list[nodename] then + error("pipeworks.flowables.outputs duplicate registration!") + end checkbase(nodename) pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } if pipeworks.toggles.pressure_logic then From 34cfee8a2faaa9366b1a9ae5035eedee3620aa56 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 16:12:36 +0100 Subject: [PATCH 49/75] new flow logic: start adding replacement ABM logic --- new_flow_logic/abm_register.lua | 19 +++++++++++++++++++ .../flowable_node_registry_install.lua | 4 ++++ 2 files changed, 23 insertions(+) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index c1b2d7d..d8bb6cc 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -12,6 +12,25 @@ local flowlogic = pipeworks.flowlogic -- DISCUSS: should it be possible later on to raise the the rate of ABMs, or lower the chance? -- Currently all the intervals and chances are hardcoded below. + + +-- register node list for the main logic function. +-- see flowlogic.run() in abms.lua. +--[[ +local register_flowlogic_abm = function(nodename) + minetest.register_abm({ + nodenames = { nodename }, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + flowlogic.run(pos, node) + end + }) +end +]] + + + -- register a node name for the pressure balancing ABM. -- currently this only exists as a per-node function to allow nodes to be registered outside pipeworks. local register_abm_balance = function(nodename) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 07001ef..5ebae61 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -79,6 +79,10 @@ register.output = function(nodename, upper, lower, outputfn) if pipeworks.toggles.pressure_logic then abmregister.output(nodename, lower, outputfn) end + -- output ABM now part of main flow logic ABM to preserve ordering. + -- note that because outputs have to be a flowable first + -- (and the installation of the flow logic ABM is conditional), + -- registered output nodes for new_flow_logic is also still conditional on the enable flag. regwarning("output node", nodename) end From 608a9a69808ee58d05dc115b37af1d53b00f0241 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 17:14:50 +0100 Subject: [PATCH 50/75] new flow logic: abms.lua: wrap up pressure value accesses behind accessor object --- new_flow_logic/abms.lua | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 7a720be..9e5eb2d 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -53,6 +53,18 @@ flowlogic.check_for_liquids_v2 = check_for_liquids_v2 local label_pressure = "pipeworks.water_pressure" +local get_pressure_access = function(pos) + local metaref = minetest.get_meta(pos) + return { + get = function() + return metaref:get_float(label_pressure) + end, + set = function(v) + metaref:set_float(label_pressure, v) + end + } +end + flowlogic.balance_pressure = function(pos, node) -- debuglog("balance_pressure() "..node.name.." at "..pos.x.." "..pos.y.." "..pos.z) -- check the pressure of all nearby nodes, and average it out. @@ -60,22 +72,23 @@ flowlogic.balance_pressure = function(pos, node) -- XXX: maybe this could be used to add fluid behaviour to other mod's nodes too? -- unconditionally include self in nodes to average over - local meta = minetest.get_meta(pos) - local currentpressure = meta:get_float(label_pressure) - local connections = { meta } + local pressure = get_pressure_access(pos) + local currentpressure = pressure.get() + -- pressure handles to average over + local connections = { pressure } local totalv = currentpressure local totalc = 1 -- then handle neighbours, but if not a pressure node don't consider them at all for _, npos in ipairs(make_coords_offsets(pos, false)) do local nodename = minetest.get_node(npos).name - local neighbour = minetest.get_meta(npos) -- for now, just check if it's in the simple table. -- TODO: the "can flow from" logic in flowable_node_registry.lua local haspressure = (pipeworks.flowables.list.simple[nodename]) if haspressure then + local neighbour = get_pressure_access(npos) --pipeworks.logger("balance_pressure @ "..formatvec(pos).." "..nodename.." "..formatvec(npos).." added to neighbour set") - local n = neighbour:get_float(label_pressure) + local n = neighbour.get() table.insert(connections, neighbour) totalv = totalv + n totalc = totalc + 1 @@ -83,8 +96,8 @@ flowlogic.balance_pressure = function(pos, node) end local average = totalv / totalc - for _, targetmeta in ipairs(connections) do - targetmeta:set_float(label_pressure, average) + for _, target in ipairs(connections) do + target.set(average) end end From 016f9de82f91b61a14ad1bc477ee18b501f77e39 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 17:33:42 +0100 Subject: [PATCH 51/75] new flow logic: abms.lua: refactor ABM logic into new master ABM, make balance_pressure() take current pressure and return new pressure --- new_flow_logic/abm_register.lua | 6 ++-- new_flow_logic/abms.lua | 33 ++++++++++++++----- .../flowable_node_registry_install.lua | 2 +- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index d8bb6cc..db6233f 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -16,7 +16,7 @@ local flowlogic = pipeworks.flowlogic -- register node list for the main logic function. -- see flowlogic.run() in abms.lua. ---[[ + local register_flowlogic_abm = function(nodename) minetest.register_abm({ nodenames = { nodename }, @@ -27,12 +27,13 @@ local register_flowlogic_abm = function(nodename) end }) end -]] +register.flowlogic = register_flowlogic_abm -- register a node name for the pressure balancing ABM. -- currently this only exists as a per-node function to allow nodes to be registered outside pipeworks. +--[[ local register_abm_balance = function(nodename) minetest.register_abm({ nodenames = { nodename }, @@ -44,6 +45,7 @@ local register_abm_balance = function(nodename) }) end register.balance = register_abm_balance +]] -- register a node for the input ABM. -- intakefn is run on the node to determine how much water can be taken (and update it's environment accordingly). diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 9e5eb2d..37b10bc 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -65,17 +65,30 @@ local get_pressure_access = function(pos) } end -flowlogic.balance_pressure = function(pos, node) - -- debuglog("balance_pressure() "..node.name.." at "..pos.x.." "..pos.y.." "..pos.z) - -- check the pressure of all nearby nodes, and average it out. - -- for the moment, only balance neighbour nodes if it already has a pressure value. - -- XXX: maybe this could be used to add fluid behaviour to other mod's nodes too? - -- unconditionally include self in nodes to average over - local pressure = get_pressure_access(pos) - local currentpressure = pressure.get() + +flowlogic.run = function(pos, node) + -- get the current pressure value. + local nodepressure = get_pressure_access(pos) + local currentpressure = nodepressure.get() + + -- balance pressure with neighbours + currentpressure = flowlogic.balance_pressure(pos, node, currentpressure) + + -- set the new pressure + nodepressure.set(currentpressure) +end + + + +flowlogic.balance_pressure = function(pos, node, currentpressure) + -- debuglog("balance_pressure() "..node.name.." at "..pos.x.." "..pos.y.." "..pos.z) + -- check the pressure of all nearby flowable nodes, and average it out. + -- pressure handles to average over - local connections = { pressure } + local connections = {} + -- unconditionally include self in nodes to average over. + -- result of averaging will be returned as new pressure for main flow logic callback local totalv = currentpressure local totalc = 1 @@ -99,6 +112,8 @@ flowlogic.balance_pressure = function(pos, node) for _, target in ipairs(connections) do target.set(average) end + + return average end diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 5ebae61..d195c63 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -36,7 +36,7 @@ register.simple = function(nodename) pipeworks.flowables.list.simple[nodename] = true table.insert(pipeworks.flowables.list.simple_nodenames, nodename) if pipeworks.toggles.pressure_logic then - abmregister.balance(nodename) + abmregister.flowlogic(nodename) end regwarning("simple", nodename) end From 65b3448796815718275ed3c16af4865e5e005454 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 17:55:14 +0100 Subject: [PATCH 52/75] new flow logic: abms.lua: refactor flowlogic.run_output() into a processing stage of flowlogic.run() --- new_flow_logic/abm_register.lua | 2 ++ new_flow_logic/abms.lua | 31 +++++++++++++------ .../flowable_node_registry_install.lua | 5 +-- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index db6233f..1c7eede 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -66,6 +66,7 @@ register.input = register_abm_input -- threshold determines the minimum pressure, over which outputfn is called. -- outputfn is then given the current pressure, and returns the pressure relieved by the output process. -- outputfn is expected to update environment, nearby world etc. as appropriate for the node. +--[[ local register_abm_output = function(nodename, threshold, outputfn) minetest.register_abm({ nodenames = { nodename }, @@ -77,6 +78,7 @@ local register_abm_output = function(nodename, threshold, outputfn) }) end register.output = register_abm_output +]] -- old spigot ABM code, not yet migrated --[[ diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 37b10bc..671a69d 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -68,6 +68,7 @@ end flowlogic.run = function(pos, node) + local nodename = node.name -- get the current pressure value. local nodepressure = get_pressure_access(pos) local currentpressure = nodepressure.get() @@ -75,6 +76,18 @@ flowlogic.run = function(pos, node) -- balance pressure with neighbours currentpressure = flowlogic.balance_pressure(pos, node, currentpressure) + -- if node is an output: run output phase + local output = pipeworks.flowables.outputs.list[nodename] + if output then + currentpressure = flowlogic.run_output( + pos, + node, + currentpressure, + output.upper, + output.lower, + output.outputfn) + end + -- set the new pressure nodepressure.set(currentpressure) end @@ -176,20 +189,18 @@ end -flowlogic.run_output = function(pos, node, threshold, outputfn) - -- callback for output devices. - -- takes care of checking a minimum pressure value and updating the node metadata. +flowlogic.run_output = function(pos, node, currentpressure, upper, lower, outputfn) + -- processing step for water output devices. + -- takes care of checking a minimum pressure value and updating the resulting pressure level -- the outputfn is provided the current pressure and returns the pressure "taken". -- as an example, using this with the above spigot function, -- the spigot function tries to output a water source if it will fit in the world. - local meta = minetest.get_meta(pos) - -- sometimes I wonder if meta:get_* returning default values would ever be problematic. - -- though here it doesn't matter, an uninit'd node returns 0, which is fine for a new, empty node. - local currentpressure = meta:get_float(label_pressure) - if currentpressure > threshold then + local result = currentpressure + if currentpressure > lower then local takenpressure = outputfn(pos, node, currentpressure) local newpressure = currentpressure - takenpressure - if newpressure < 0 then currentpressure = 0 end - meta:set_float(label_pressure, newpressure) + if newpressure < 0 then newpressure = 0 end + result = newpressure end + return result end diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index d195c63..aed6fbd 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -75,10 +75,7 @@ register.output = function(nodename, upper, lower, outputfn) error("pipeworks.flowables.outputs duplicate registration!") end checkbase(nodename) - pipeworks.flowables.outputs.list[nodename] = { threshold=threshold, outputfn=outputfn } - if pipeworks.toggles.pressure_logic then - abmregister.output(nodename, lower, outputfn) - end + pipeworks.flowables.outputs.list[nodename] = { upper=upper, lower=lower, outputfn=outputfn } -- output ABM now part of main flow logic ABM to preserve ordering. -- note that because outputs have to be a flowable first -- (and the installation of the flow logic ABM is conditional), From be1a6d53aa94f812dc661b4b08c5d0e2ebf97623 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 18:07:55 +0100 Subject: [PATCH 53/75] new flow logic: flowable_node_registry_install.lua: factor out register.intake_simple into generic registration and helper wrapper --- .../flowable_node_registry_install.lua | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index aed6fbd..35dbe97 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -45,21 +45,41 @@ local checkbase = function(nodename) if not checkexists(nodename) then error("pipeworks.flowables node doesn't exist as a flowable!") end end --- Register a node as a simple intake. +local duplicateerr = function(kind, nodename) error(kind.." duplicate registration for "..nodename) end + + + +-- Registers a node as a fluid intake. +-- intakefn is used to determine the water that can be taken in a node-specific way. -- Expects node to be registered as a flowable (is present in flowables.list.all), -- so that water can move out of it. --- maxpressure is the maximum pipeline pressure that this node can drive. +-- maxpressure is the maximum pipeline pressure that this node can drive; +-- if the input's node exceeds this the callback is not run. -- possible WISHME here: technic-driven high-pressure pumps -register.intake_simple = function(nodename, maxpressure) +register.intake = function(nodename, maxpressure, intakefn) + -- check for duplicate registration of this node + local list = pipeworks.flowables.inputs.list checkbase(nodename) - pipeworks.flowables.inputs.list[nodename] = { maxpressure=maxpressure } + if list[nodename] then duplicateerr("pipeworks.flowables.inputs", nodename) end + list[nodename] = { maxpressure=maxpressure, intakefn=intakefn } table.insert(pipeworks.flowables.inputs.nodenames, nodename) if pipeworks.toggles.pressure_logic then - abmregister.input(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) + abmregister.input(nodename, maxpressure, intakefn) end - regwarning("simple intake", nodename) + regwarning("intake", nodename) end + + +-- Register a node as a simple intake: +-- tries to absorb water source nodes from it's surroundings. +-- may exceed limit slightly due to needing to absorb whole nodes. +register.intake_simple = function(nodename, maxpressure) + register.intake(nodename, maxpressure, pipeworks.flowlogic.check_for_liquids_v2) +end + + + -- Register a node as an output. -- Expects node to already be a flowable. -- upper and lower thresholds have different meanings depending on whether finite liquid mode is in effect. From 9c770532e6e3cb1157e467015a97aef97a8a8893 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 19:19:09 +0100 Subject: [PATCH 54/75] new flow logic: abms.lua: refactor run_input to run as part of master run() ABM --- new_flow_logic/abm_register.lua | 2 ++ new_flow_logic/abms.lua | 31 ++++++++++++++----- .../flowable_node_registry_install.lua | 4 --- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index 1c7eede..dbd37e6 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -50,6 +50,7 @@ register.balance = register_abm_balance -- register a node for the input ABM. -- intakefn is run on the node to determine how much water can be taken (and update it's environment accordingly). -- maxpressure is the maximum pressure that this input can drive, beyond which pressure will not be raised. +--[[ local register_abm_input = function(nodename, maxpressure, intakefn) minetest.register_abm({ nodenames = { nodename }, @@ -61,6 +62,7 @@ local register_abm_input = function(nodename, maxpressure, intakefn) }) end register.input = register_abm_input +]] -- register a node for the output ABM. -- threshold determines the minimum pressure, over which outputfn is called. diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 671a69d..eb551d8 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -66,6 +66,14 @@ local get_pressure_access = function(pos) end +-- logging is unreliable when something is crashing... +local nilexplode = function(caller, label, value) + if value == nil then + error(caller..": "..label.." was nil") + end +end + + flowlogic.run = function(pos, node) local nodename = node.name @@ -73,6 +81,14 @@ flowlogic.run = function(pos, node) local nodepressure = get_pressure_access(pos) local currentpressure = nodepressure.get() + -- if node is an input: run intake phase + local inputdef = pipeworks.flowables.inputs.list[nodename] + if inputdef then + currentpressure = flowlogic.run_input(pos, node, currentpressure, inputdef) + --debuglog("post-intake currentpressure is "..currentpressure) + --nilexplode("run()", "currentpressure", currentpressure) + end + -- balance pressure with neighbours currentpressure = flowlogic.balance_pressure(pos, node, currentpressure) @@ -131,23 +147,22 @@ end -flowlogic.run_input = function(pos, node, maxpressure, intakefn) +flowlogic.run_input = function(pos, node, currentpressure, inputdef) -- intakefn allows a given input node to define it's own intake logic. -- this function will calculate the maximum amount of water that can be taken in; -- the intakefn will be given this and is expected to return the actual absorption amount. - local meta = minetest.get_meta(pos) - local currentpressure = meta:get_float(label_pressure) + local maxpressure = inputdef.maxpressure local intake_limit = maxpressure - currentpressure - if intake_limit <= 0 then return end + if intake_limit <= 0 then return currentpressure end - local actual_intake = intakefn(pos, intake_limit) + local actual_intake = inputdef.intakefn(pos, intake_limit) --pipeworks.logger("run_input@"..formatvec(pos).." oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake) - if actual_intake <= 0 then return end + if actual_intake <= 0 then return currentpressure end local newpressure = actual_intake + currentpressure - -- debuglog("oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake.." newpressure "..newpressure) - meta:set_float(label_pressure, newpressure) + --debuglog("run_input() end, oldpressure "..currentpressure.." intake_limit "..intake_limit.." actual_intake "..actual_intake.." newpressure "..newpressure) + return newpressure end diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 35dbe97..6da87dc 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -62,10 +62,6 @@ register.intake = function(nodename, maxpressure, intakefn) checkbase(nodename) if list[nodename] then duplicateerr("pipeworks.flowables.inputs", nodename) end list[nodename] = { maxpressure=maxpressure, intakefn=intakefn } - table.insert(pipeworks.flowables.inputs.nodenames, nodename) - if pipeworks.toggles.pressure_logic then - abmregister.input(nodename, maxpressure, intakefn) - end regwarning("intake", nodename) end From 91d057fcab8bf2caad295148201f1414e935def7 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 19:42:49 +0100 Subject: [PATCH 55/75] new flow logic: tear out old abm registration code --- new_flow_logic/abm_register.lua | 65 --------------------------------- todo/new_flow_logic.txt | 12 +++--- 2 files changed, 5 insertions(+), 72 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index dbd37e6..ac7b2e3 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -28,68 +28,3 @@ local register_flowlogic_abm = function(nodename) }) end register.flowlogic = register_flowlogic_abm - - - --- register a node name for the pressure balancing ABM. --- currently this only exists as a per-node function to allow nodes to be registered outside pipeworks. ---[[ -local register_abm_balance = function(nodename) - minetest.register_abm({ - nodenames = { nodename }, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - flowlogic.balance_pressure(pos, node) - end - }) -end -register.balance = register_abm_balance -]] - --- register a node for the input ABM. --- intakefn is run on the node to determine how much water can be taken (and update it's environment accordingly). --- maxpressure is the maximum pressure that this input can drive, beyond which pressure will not be raised. ---[[ -local register_abm_input = function(nodename, maxpressure, intakefn) - minetest.register_abm({ - nodenames = { nodename }, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - flowlogic.run_input(pos, node, maxpressure, intakefn) - end - }) -end -register.input = register_abm_input -]] - --- register a node for the output ABM. --- threshold determines the minimum pressure, over which outputfn is called. --- outputfn is then given the current pressure, and returns the pressure relieved by the output process. --- outputfn is expected to update environment, nearby world etc. as appropriate for the node. ---[[ -local register_abm_output = function(nodename, threshold, outputfn) - minetest.register_abm({ - nodenames = { nodename }, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - flowlogic.run_output(pos, node, threshold, outputfn) - end - }) -end -register.output = register_abm_output -]] - --- old spigot ABM code, not yet migrated ---[[ - minetest.register_abm({ - nodenames = { spigot_on, spigot_off }, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - pipeworks.run_spigot_output(pos, node) - end - }) -]] diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt index 5daa80d..3bc8a31 100644 --- a/todo/new_flow_logic.txt +++ b/todo/new_flow_logic.txt @@ -3,15 +3,13 @@ Currently, only "simple" flowable nodes exist, and they will always equalise pre A more sophisticated behaviour for this would be flowable node registration with some kind of custom callback, such that water can only flow into or out of these nodes in certain directions. This would enable devices such as the airtight panels, sensor tubes and valves to have correct flow behaviour. --- ABM ordering for event-driven "dropped below threshold" events -For the non-finite liquid mode, cleanup handlers are invoked continuously while pressure is below a certain amount. -This could potentially mean that a below-pressure output node such as a spigot could potentially keep deleting the water source node beneath it, even when one is placed there afterwards by a player say. -Furthermore, attempting to fix this with a "previous pressure" metadata variable is of little use, as the output code is current run in a separate ABM - so the correct sequencing of events cannot be guaranteed. -Therefore, the current code needs revising such that a node's output (or input) handlers are invoked from the main flow logic ABM, in order to ensure correct ordering. -This would also allow the code to compare old and new pressure, and invoke the cleanup handler *only once* if the pressure has dropped from above to below the threshold, and not continuously. +-- Implement clean-up functionality for output nodes in non-finite mode +register.output() needs to be equipped with an extra "cleanerfn" argument, which is saved into the node's output table entry. +When the pressure level falls below the lower level in non-finite mode, this function would be called by run_output() to e.g. remove a created water source. +Additionally, the outputfn needs to be equipped with a flag to convey the finite mode, so that in non-finite mode the outputfn will drain pressure continuously until the pressure falls below the threshold. -- Automated switching between node variants based on pressure thresholds -When the ABM ordering is complete, an additional callback which would be useful is a "node changer" callback, to switch between variations of a pipe depending on pressure level. +Within flowlogic.run(), an additional hook which would be useful is a "node changer" callback, to switch between variations of a pipe depending on pressure level. For regular pipes, this is mostly aesthetic, as the empty/loaded variants of the pipes have different texures. However, the flow sensor is currently a broken device under the new flow logic, as there is nothing to switch this device between the "on" and "off" state - in order to produce a mesecons output, separate nodes are required due to mesecon's API being limited to only on/off for a given node, with no facility for a callback function which could e.g. inspect pressure metadata. To make this work, a new registry table would be needed to check if a flowable node has this property. From ea92bfe4d321e11955c360fad527e08196fa5841 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 21:36:41 +0100 Subject: [PATCH 56/75] devices.lua: raise maximum pressure for pumps --- devices.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/devices.lua b/devices.lua index 26b9275..8ec3731 100644 --- a/devices.lua +++ b/devices.lua @@ -166,8 +166,9 @@ for s in ipairs(states) do }) -- FIXME: currently a simple flow device, but needs directionality checking new_flow_logic_register.simple(pumpname) + local pump_drive = 4 if states[s] ~= "off" then - new_flow_logic_register.intake_simple(pumpname, 2) + new_flow_logic_register.intake_simple(pumpname, pump_drive) end local nodename_valve_empty = "pipeworks:valve_"..states[s].."_empty" From 187e755aa5d7f4ddbc68cc2c4d8494051321a3cd Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 21:44:33 +0100 Subject: [PATCH 57/75] new flow logic: abms.lua: don't unpack outputdef variables in flowlogic.run(), leave to flowlogic.run_output() --- new_flow_logic/abms.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index eb551d8..6fee744 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -93,15 +93,13 @@ flowlogic.run = function(pos, node) currentpressure = flowlogic.balance_pressure(pos, node, currentpressure) -- if node is an output: run output phase - local output = pipeworks.flowables.outputs.list[nodename] - if output then + local outputdef = pipeworks.flowables.outputs.list[nodename] + if outputdef then currentpressure = flowlogic.run_output( pos, node, currentpressure, - output.upper, - output.lower, - output.outputfn) + outputdef) end -- set the new pressure @@ -204,15 +202,17 @@ end -flowlogic.run_output = function(pos, node, currentpressure, upper, lower, outputfn) +flowlogic.run_output = function(pos, node, currentpressure, outputdef) -- processing step for water output devices. -- takes care of checking a minimum pressure value and updating the resulting pressure level -- the outputfn is provided the current pressure and returns the pressure "taken". -- as an example, using this with the above spigot function, -- the spigot function tries to output a water source if it will fit in the world. + local upper = outputdef.upper + local lower = outputdef.lower local result = currentpressure if currentpressure > lower then - local takenpressure = outputfn(pos, node, currentpressure) + local takenpressure = outputdef.outputfn(pos, node, currentpressure) local newpressure = currentpressure - takenpressure if newpressure < 0 then newpressure = 0 end result = newpressure From 453a114cd022a4d7b0a028f9e4a9785e20e6e368 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 21:55:49 +0100 Subject: [PATCH 58/75] new flow logic: flowable_node_registry_install.lua: add cleanupfn argument to register.output() --- new_flow_logic/flowable_node_registry_install.lua | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 6da87dc..0be9fc0 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -86,12 +86,17 @@ end -- the upper and lower difference acts as a hysteresis to try and avoid "gaps" in the flow. -- if finite mode is on, upper is ignored and lower is used to determine whether to run outputfn; -- cleanupfn is ignored in this mode as finite mode assumes something causes water to move itself. -register.output = function(nodename, upper, lower, outputfn) +register.output = function(nodename, upper, lower, outputfn, cleanupfn) if pipeworks.flowables.outputs.list[nodename] then error("pipeworks.flowables.outputs duplicate registration!") end checkbase(nodename) - pipeworks.flowables.outputs.list[nodename] = { upper=upper, lower=lower, outputfn=outputfn } + pipeworks.flowables.outputs.list[nodename] = { + upper=upper, + lower=lower, + outputfn=outputfn, + cleanupfn=cleanupfn, + } -- output ABM now part of main flow logic ABM to preserve ordering. -- note that because outputs have to be a flowable first -- (and the installation of the flow logic ABM is conditional), @@ -112,5 +117,6 @@ end -- but only drains pressure when water source nodes are actually placed. register.output_simple = function(nodename, upper, lower, neighbours) local outputfn = pipeworks.flowlogic.helpers.make_neighbour_output_fixed(neighbours) - register.output(nodename, upper, lower, outputfn) + local cleanupfn = pipeworks.flowlogic.helpers.make_neighbour_cleanup_fixed(neighbours) + register.output(nodename, upper, lower, outputfn, cleanupfn) end From bd32b4fca2ee77da1b4b017d3e90a4013d4393a8 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 22:03:53 +0100 Subject: [PATCH 59/75] new flow logic: abms.lua: pass finite mode flag to run_output() --- new_flow_logic/abms.lua | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 6fee744..1605ea3 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -75,6 +75,7 @@ end +local finitemode = pipeworks.toggles.finite_water flowlogic.run = function(pos, node) local nodename = node.name -- get the current pressure value. @@ -99,7 +100,8 @@ flowlogic.run = function(pos, node) pos, node, currentpressure, - outputdef) + outputdef, + finitemode) end -- set the new pressure @@ -202,7 +204,7 @@ end -flowlogic.run_output = function(pos, node, currentpressure, outputdef) +flowlogic.run_output = function(pos, node, currentpressure, outputdef, finitemode) -- processing step for water output devices. -- takes care of checking a minimum pressure value and updating the resulting pressure level -- the outputfn is provided the current pressure and returns the pressure "taken". From 07e769d1b92661dc21bf85dee2f788f929fc444e Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 22:07:30 +0100 Subject: [PATCH 60/75] new flow logic: abms.lua: pass finite mod flag to output handler callbacks in flowlogic.run_output() --- new_flow_logic/abms.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 1605ea3..a4d5fc3 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -173,7 +173,7 @@ end -- this is a constructor function, returning another function which satisfies the output helper requirements. -- note that this does *not* take rotation into account. flowlogic.helpers.make_neighbour_output_fixed = function(neighbours) - return function(pos, node, currentpressure) + return function(pos, node, currentpressure, finitemode) local taken = 0 for _, offset in pairs(neighbours) do local npos = vector.add(pos, offset) @@ -214,7 +214,7 @@ flowlogic.run_output = function(pos, node, currentpressure, outputdef, finitemod local lower = outputdef.lower local result = currentpressure if currentpressure > lower then - local takenpressure = outputdef.outputfn(pos, node, currentpressure) + local takenpressure = outputdef.outputfn(pos, node, currentpressure, finitemode) local newpressure = currentpressure - takenpressure if newpressure < 0 then newpressure = 0 end result = newpressure From 9ab197af2f6e524be920857c0f152aef84546e37 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 22:21:54 +0100 Subject: [PATCH 61/75] new flow logic: abms.lua: implement non-finite mode behaviour for neighbour output helper --- new_flow_logic/abms.lua | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index a4d5fc3..99ccbc6 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -178,9 +178,18 @@ flowlogic.helpers.make_neighbour_output_fixed = function(neighbours) for _, offset in pairs(neighbours) do local npos = vector.add(pos, offset) local name = minetest.get_node(npos).name - if (name == "air") or (name == "default:water_flowing") then + if currentpressure < 1 then break end + -- take pressure anyway in non-finite mode, even if node is water source already. + -- in non-finite mode, pressure has to be sustained to keep the sources there. + -- so in non-finite mode, placing water is dependent on the target node; + -- draining pressure is not. + local canplace = (name == "air") or (name == "default:water_flowing") + if canplace then minetest.swap_node(npos, {name="default:water_source"}) + end + if (not finitemode) or canplace then taken = taken + 1 + currentpressure = currentpressure - 1 end end return taken From d4346919bcb4d2e0c692448bc0a652d55c0fa2a9 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 22:29:17 +0100 Subject: [PATCH 62/75] new flow logic: abms.lua: pass initial pressure to run_output() to allow falling-level event detection --- new_flow_logic/abms.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 99ccbc6..babd14e 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -81,6 +81,7 @@ flowlogic.run = function(pos, node) -- get the current pressure value. local nodepressure = get_pressure_access(pos) local currentpressure = nodepressure.get() + local oldpressure = currentpressure -- if node is an input: run intake phase local inputdef = pipeworks.flowables.inputs.list[nodename] @@ -100,6 +101,7 @@ flowlogic.run = function(pos, node) pos, node, currentpressure, + oldpressure, outputdef, finitemode) end @@ -213,7 +215,7 @@ end -flowlogic.run_output = function(pos, node, currentpressure, outputdef, finitemode) +flowlogic.run_output = function(pos, node, currentpressure, oldpressure, outputdef, finitemode) -- processing step for water output devices. -- takes care of checking a minimum pressure value and updating the resulting pressure level -- the outputfn is provided the current pressure and returns the pressure "taken". From f94c93bb59fa151ee90932f53afb82ac6f3aae15 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sat, 7 Oct 2017 22:35:08 +0100 Subject: [PATCH 63/75] new flow logic: abms.lua: implement non-finite mode cleanupfn invocation in run_output() --- new_flow_logic/abms.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index babd14e..9197d17 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -224,11 +224,16 @@ flowlogic.run_output = function(pos, node, currentpressure, oldpressure, outputd local upper = outputdef.upper local lower = outputdef.lower local result = currentpressure - if currentpressure > lower then + local threshold = nil + if finitemode then threshold = lower else threshold = upper end + if currentpressure > threshold then local takenpressure = outputdef.outputfn(pos, node, currentpressure, finitemode) local newpressure = currentpressure - takenpressure if newpressure < 0 then newpressure = 0 end result = newpressure end + if (not finitemode) and (currentpressure < lower) and (oldpressure > lower) then + outputdef.cleanupfn(pos, node, currentpressure) + end return result end From 6a25e56336f98be7f91d328d6a75674450aa46a4 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 11:32:08 +0100 Subject: [PATCH 64/75] new flow logic: algorithmic and value tuning for non-finite mode --- devices.lua | 4 ++-- new_flow_logic/abms.lua | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/devices.lua b/devices.lua index 8ec3731..44c9d5e 100644 --- a/devices.lua +++ b/devices.lua @@ -377,7 +377,7 @@ minetest.register_node(nodename_spigot_loaded, { -- register both so existing flowing spigots continue to work (even if the visual doesn't match the spigot's behaviour). new_flow_logic_register.simple(nodename_spigot_empty) new_flow_logic_register.simple(nodename_spigot_loaded) -local spigot_upper = 1.5 +local spigot_upper = 1.0 local spigot_lower = 1.0 local spigot_neighbours={{x=0, y=-1, z=0}} new_flow_logic_register.output_simple(nodename_spigot_empty, spigot_upper, spigot_lower, spigot_neighbours) @@ -671,7 +671,7 @@ minetest.register_node(nodename_fountain_loaded, { }) new_flow_logic_register.simple(nodename_fountain_empty) new_flow_logic_register.simple(nodename_fountain_loaded) -local fountain_upper = 1.5 +local fountain_upper = 1.0 local fountain_lower = 1.0 local fountain_neighbours={{x=0, y=1, z=0}} new_flow_logic_register.output_simple(nodename_fountain_empty, fountain_upper, fountain_lower, fountain_neighbours) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 9197d17..e83d50e 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -202,12 +202,13 @@ end -- removes water sources from neighbor positions when the output is "off" due to lack of pressure. flowlogic.helpers.make_neighbour_cleanup_fixed = function(neighbours) return function(pos, node, currentpressure) - -- FIXME - this would indiscriminately take blocks while under-pressure, not just one time? + --pipeworks.logger("neighbour_cleanup_fixed@"..formatvec(pos)) for _, offset in pairs(neighbours) do local npos = vector.add(pos, offset) local name = minetest.get_node(npos).name if (name == "default:water_source") then - minetest.remove_node(pos) + --pipeworks.logger("neighbour_cleanup_fixed removing "..formatvec(npos)) + minetest.remove_node(npos) end end end @@ -221,6 +222,7 @@ flowlogic.run_output = function(pos, node, currentpressure, oldpressure, outputd -- the outputfn is provided the current pressure and returns the pressure "taken". -- as an example, using this with the above spigot function, -- the spigot function tries to output a water source if it will fit in the world. + --pipeworks.logger("flowlogic.run_output() pos "..formatvec(pos).." old -> currentpressure "..tostring(oldpressure).." "..tostring(currentpressure).." finitemode "..tostring(finitemode)) local upper = outputdef.upper local lower = outputdef.lower local result = currentpressure @@ -232,7 +234,8 @@ flowlogic.run_output = function(pos, node, currentpressure, oldpressure, outputd if newpressure < 0 then newpressure = 0 end result = newpressure end - if (not finitemode) and (currentpressure < lower) and (oldpressure > lower) then + if (not finitemode) and (currentpressure < lower) and (oldpressure < lower) then + --pipeworks.logger("flowlogic.run_output() invoking cleanup currentpressure="..tostring(currentpressure)) outputdef.cleanupfn(pos, node, currentpressure) end return result From 7e09da50c2896e8a4bcfc6f666d5a63694e682bd Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 11:41:42 +0100 Subject: [PATCH 65/75] todo: update new flow logic items for cleanup handler work --- todo/new_flow_logic.txt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt index 3bc8a31..2cd15f1 100644 --- a/todo/new_flow_logic.txt +++ b/todo/new_flow_logic.txt @@ -3,10 +3,11 @@ Currently, only "simple" flowable nodes exist, and they will always equalise pre A more sophisticated behaviour for this would be flowable node registration with some kind of custom callback, such that water can only flow into or out of these nodes in certain directions. This would enable devices such as the airtight panels, sensor tubes and valves to have correct flow behaviour. --- Implement clean-up functionality for output nodes in non-finite mode -register.output() needs to be equipped with an extra "cleanerfn" argument, which is saved into the node's output table entry. -When the pressure level falls below the lower level in non-finite mode, this function would be called by run_output() to e.g. remove a created water source. -Additionally, the outputfn needs to be equipped with a flag to convey the finite mode, so that in non-finite mode the outputfn will drain pressure continuously until the pressure falls below the threshold. +-- (may not be possible) stop removing water nodes that were not placed by outputs when off +In non-finite mode, spigots and fountainheads will vanish water sources in their output positions, even if those output nodes did not place them there. +This is annoying though not game-breaking in non-finite mode, where water sources can at least be easily replenished. +Fixing this would require some kind of metadata marker on water nodes placed by spigots and fountains, such that only water sources placed while the device is "on" are removed when it is "off". +It is debateable whether existing water sources should be marked for removal when the device turns on again. -- Automated switching between node variants based on pressure thresholds Within flowlogic.run(), an additional hook which would be useful is a "node changer" callback, to switch between variations of a pipe depending on pressure level. From e98e4e268b5faf898a0b8f580d7da2b46ead05c4 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 14:27:40 +0100 Subject: [PATCH 66/75] new flow logic: flowable node registry: add initial support for transition triggers --- new_flow_logic/flowable_node_registry.lua | 6 +++ .../flowable_node_registry_install.lua | 50 +++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index b0634d0..7651928 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -27,6 +27,12 @@ pipeworks.flowables.outputs = {} pipeworks.flowables.outputs.list = {} -- not currently any nodenames arraylist for this one as it's not currently needed. +-- nodes with registered node transitions +-- nodes will be switched depending on pressure level +pipeworks.flowables.transitions = {} +pipeworks.flowables.transitions.list = {} -- master list +pipeworks.flowables.transitions.simple = {} -- nodes that change based purely on pressure + -- checks if a given node can flow in a given direction. diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 0be9fc0..63151f0 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -120,3 +120,53 @@ register.output_simple = function(nodename, upper, lower, neighbours) local cleanupfn = pipeworks.flowlogic.helpers.make_neighbour_cleanup_fixed(neighbours) register.output(nodename, upper, lower, outputfn, cleanupfn) end + + + +-- common base checking for transition nodes +-- ensures the node has only been registered once as a transition. +local transition_list = pipeworks.flowables.transitions.list +local insert_transition_base = function(nodename) + checkbase(nodename) + if transition_list[nodename] then duplicateerr("base transition", nodename) end + transition_list[nodename] = true +end + + + +-- register a simple transition set. +-- expects a table with nodenames as keys and threshold pressures as values. +-- internally, the table is sorted by value, and when one of these nodes needs to transition, +-- the table is searched starting from the lowest (even if it's value is non-zero), +-- until a value is found which is higher than or equal to the current node pressure. +-- ex. nodeset = { ["mod:level_0"] = 0, ["mod:level_1"] = 1, --[[ ... ]] } +local simpleseterror = function(msg) + error("register.transition_simple_set(): "..msg) +end +local simple_transitions = pipeworks.flowables.transitions.simple + +register.transition_simple_set = function(nodeset) + local set = {} + for nodename, value in pairs(nodeset) do + if type(nodename) ~= "string" then simpleseterror("nodename key "..tostring(nodename).."was not a string!") end + if type(value) ~= "number" then simpleseterror("pressure value "..tostring(value).."was not a number!") end + insert_transition_base(nodename) + if simple_transitions[nodename] then duplicateerr("simple transition set", nodename) end + -- assigning set to table is done separately below + + table.insert(set, { nodename=nodename, threshold=value }) + end + + -- sort pressure values, smallest first + local smallest_first = function(a, b) + return a.value < b.value + end + table.sort(set, smallest_first) + + -- individual registration of each node, all sharing this set, + -- so each node in the set will transition to the correct target node. + for _, element in ipairs(set) do + --pipeworks.logger("register.transition_simple_set() after sort: nodename "..element.nodename.." value "..tostring(element.threshold)) + simple_transitions[element.nodename] = set + end +end From 32a24730f1ab8cd596ed2f4cf6eda1a58c877ecb Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 15:07:12 +0100 Subject: [PATCH 67/75] new flow logic: change simple transition set logic to take list of key-value pairs, add set registration for flow sensor pipe --- devices.lua | 3 +++ new_flow_logic/flowable_node_registry_install.lua | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/devices.lua b/devices.lua index 44c9d5e..196d660 100644 --- a/devices.lua +++ b/devices.lua @@ -524,6 +524,9 @@ minetest.register_node(nodename_sensor_loaded, { -- FIXME requires-directionality new_flow_logic_register.simple(nodename_sensor_empty) new_flow_logic_register.simple(nodename_sensor_loaded) +-- activate flow sensor at roughly half the pressure pumps drive pipes +local sensor_pressure_set = { { nodename_sensor_empty, 0.0 }, { nodename_sensor_loaded, 2.0 } } +new_flow_logic_register.transition_simple_set(sensor_pressure_set) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index 63151f0..f019dc3 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -147,8 +147,11 @@ local simple_transitions = pipeworks.flowables.transitions.simple register.transition_simple_set = function(nodeset) local set = {} - for nodename, value in pairs(nodeset) do - if type(nodename) ~= "string" then simpleseterror("nodename key "..tostring(nodename).."was not a string!") end + for index, element in ipairs(nodeset) do + if type(element) ~= "table" then simpleseterror("element "..tostring(index).." in nodeset was not table!") end + local nodename = element[1] + local value = element[2] + if type(nodename) ~= "string" then simpleseterror("nodename "..tostring(nodename).."was not a string!") end if type(value) ~= "number" then simpleseterror("pressure value "..tostring(value).."was not a number!") end insert_transition_base(nodename) if simple_transitions[nodename] then duplicateerr("simple transition set", nodename) end @@ -159,7 +162,7 @@ register.transition_simple_set = function(nodeset) -- sort pressure values, smallest first local smallest_first = function(a, b) - return a.value < b.value + return a.threshold < b.threshold end table.sort(set, smallest_first) From eaf6c33bae0912e15ac190df203b9b250545052b Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 16:19:51 +0100 Subject: [PATCH 68/75] new flow logic: abms.lua: implement node transitions --- new_flow_logic/abms.lua | 51 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index e83d50e..6abdd42 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -29,7 +29,7 @@ end ---local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..tostring(vec.y)..sep..tostring(vec.z)..")" end +local formatvec = function(vec) local sep="," return "("..tostring(vec.x)..sep..tostring(vec.y)..sep..tostring(vec.z)..")" end -- new version of liquid check -- accepts a limit parameter to only delete water blocks that the receptacle can accept, @@ -106,6 +106,13 @@ flowlogic.run = function(pos, node) finitemode) end + -- if node has pressure transitions: determine new node + if pipeworks.flowables.transitions.list[nodename] then + local newnode = flowlogic.run_transition(node, currentpressure) + --pipeworks.logger("flowlogic.run()@"..formatvec(pos).." transition, new node name = "..dump(newnode).." pressure "..tostring(currentpressure)) + minetest.swap_node(pos, newnode) + end + -- set the new pressure nodepressure.set(currentpressure) end @@ -240,3 +247,45 @@ flowlogic.run_output = function(pos, node, currentpressure, oldpressure, outputd end return result end + + + +-- determine which node to switch to based on current pressure +flowlogic.run_transition = function(node, currentpressure) + local simplesetdef = pipeworks.flowables.transitions.simple[node.name] + local result = node + local found = false + + -- simple transition sets: assumes all nodes in the set share param values. + if simplesetdef then + -- assumes that the set has been checked to contain at least one element... + local nodename_prev = simplesetdef[1].nodename + local result_nodename = node.name + + for index, element in ipairs(simplesetdef) do + -- find the highest element that is below the current pressure. + local threshold = element.threshold + if threshold > currentpressure then + result_nodename = nodename_prev + found = true + break + end + nodename_prev = element.nodename + end + + -- use last element if no threshold is greater than current pressure + if not found then + result_nodename = nodename_prev + found = true + end + + -- preserve param1/param2 values + result = { name=result_nodename, param1=node.param1, param2=node.param2 } + end + + if not found then + pipeworks.logger("flowlogic.run_transition() BUG no transition definitions found! nodename="..nodename.." currentpressure="..tostring(currentpressure)) + end + + return result +end From c2553928f2e1063ca8011b0f9b024b819995cab5 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 16:20:30 +0100 Subject: [PATCH 69/75] new flow logic: flowable_node_registry_install.lua: add set size checking guard --- new_flow_logic/flowable_node_registry_install.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index f019dc3..e4a5744 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -147,6 +147,9 @@ local simple_transitions = pipeworks.flowables.transitions.simple register.transition_simple_set = function(nodeset) local set = {} + + local length = #nodeset + if length < 2 then simpleseterror("nodeset needs at least two elements!") end for index, element in ipairs(nodeset) do if type(element) ~= "table" then simpleseterror("element "..tostring(index).." in nodeset was not table!") end local nodename = element[1] From ce0983d239c4c855b7f6fd9d96d352c03c5d88b0 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 16:41:00 +0100 Subject: [PATCH 70/75] devices.lua: adjust flow sensor threshold to more closely model classic mode --- devices.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devices.lua b/devices.lua index 196d660..2a7afc9 100644 --- a/devices.lua +++ b/devices.lua @@ -525,7 +525,7 @@ minetest.register_node(nodename_sensor_loaded, { new_flow_logic_register.simple(nodename_sensor_empty) new_flow_logic_register.simple(nodename_sensor_loaded) -- activate flow sensor at roughly half the pressure pumps drive pipes -local sensor_pressure_set = { { nodename_sensor_empty, 0.0 }, { nodename_sensor_loaded, 2.0 } } +local sensor_pressure_set = { { nodename_sensor_empty, 0.0 }, { nodename_sensor_loaded, 1.0 } } new_flow_logic_register.transition_simple_set(sensor_pressure_set) From d5e3f1cf68a15d7e14cc44eb8e58e49dbb6aa087 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 17:38:28 +0100 Subject: [PATCH 71/75] new flow logic: implement post-transition hook with mesecons support, add mesecons transition rules for flow sensor --- devices.lua | 2 +- new_flow_logic/abms.lua | 24 +++++++++++++++++++ new_flow_logic/flowable_node_registry.lua | 1 + .../flowable_node_registry_install.lua | 12 +++++++++- 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/devices.lua b/devices.lua index 2a7afc9..5203bf3 100644 --- a/devices.lua +++ b/devices.lua @@ -526,7 +526,7 @@ new_flow_logic_register.simple(nodename_sensor_empty) new_flow_logic_register.simple(nodename_sensor_loaded) -- activate flow sensor at roughly half the pressure pumps drive pipes local sensor_pressure_set = { { nodename_sensor_empty, 0.0 }, { nodename_sensor_loaded, 1.0 } } -new_flow_logic_register.transition_simple_set(sensor_pressure_set) +new_flow_logic_register.transition_simple_set(sensor_pressure_set, { mesecons=pipeworks.mesecons_rules }) diff --git a/new_flow_logic/abms.lua b/new_flow_logic/abms.lua index 6abdd42..38ae4b6 100644 --- a/new_flow_logic/abms.lua +++ b/new_flow_logic/abms.lua @@ -111,6 +111,7 @@ flowlogic.run = function(pos, node) local newnode = flowlogic.run_transition(node, currentpressure) --pipeworks.logger("flowlogic.run()@"..formatvec(pos).." transition, new node name = "..dump(newnode).." pressure "..tostring(currentpressure)) minetest.swap_node(pos, newnode) + flowlogic.run_transition_post(pos, newnode) end -- set the new pressure @@ -289,3 +290,26 @@ flowlogic.run_transition = function(node, currentpressure) return result end + +-- post-update hook for run_transition +-- among other things, updates mesecons if present. +-- node here means the new node, returned from run_transition() above +flowlogic.run_transition_post = function(pos, node) + local mesecons_def = minetest.registered_nodes[node.name].mesecons + local mesecons_rules = pipeworks.flowables.transitions.mesecons[node.name] + if minetest.global_exists("mesecon") and (mesecons_def ~= nil) and mesecons_rules then + if type(mesecons_def) ~= "table" then + pipeworks.logger("flowlogic.run_transition_post() BUG mesecons def for "..node.name.."not a table: got "..tostring(mesecons_def)) + else + local receptor = mesecons_def.receptor + if receptor then + local state = receptor.state + if state == mesecon.state.on then + mesecon.receptor_on(pos, mesecons_rules) + elseif state == mesecon.state.off then + mesecon.receptor_off(pos, mesecons_rules) + end + end + end + end +end diff --git a/new_flow_logic/flowable_node_registry.lua b/new_flow_logic/flowable_node_registry.lua index 7651928..2523803 100644 --- a/new_flow_logic/flowable_node_registry.lua +++ b/new_flow_logic/flowable_node_registry.lua @@ -32,6 +32,7 @@ pipeworks.flowables.outputs.list = {} pipeworks.flowables.transitions = {} pipeworks.flowables.transitions.list = {} -- master list pipeworks.flowables.transitions.simple = {} -- nodes that change based purely on pressure +pipeworks.flowables.transitions.mesecons = {} -- table of mesecons rules to apply on transition diff --git a/new_flow_logic/flowable_node_registry_install.lua b/new_flow_logic/flowable_node_registry_install.lua index e4a5744..c8f6889 100644 --- a/new_flow_logic/flowable_node_registry_install.lua +++ b/new_flow_logic/flowable_node_registry_install.lua @@ -145,8 +145,9 @@ local simpleseterror = function(msg) end local simple_transitions = pipeworks.flowables.transitions.simple -register.transition_simple_set = function(nodeset) +register.transition_simple_set = function(nodeset, extras) local set = {} + if extras == nil then extras = {} end local length = #nodeset if length < 2 then simpleseterror("nodeset needs at least two elements!") end @@ -175,4 +176,13 @@ register.transition_simple_set = function(nodeset) --pipeworks.logger("register.transition_simple_set() after sort: nodename "..element.nodename.." value "..tostring(element.threshold)) simple_transitions[element.nodename] = set end + + -- handle extra options + -- if mesecons rules table was passed, set for each node + if extras.mesecons then + local mesecons_rules = pipeworks.flowables.transitions.mesecons + for _, element in ipairs(set) do + mesecons_rules[element.nodename] = extras.mesecons + end + end end From 084174123df3264744743072c315be80f1f36d4d Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 18:21:17 +0100 Subject: [PATCH 72/75] default_settings.lua: remove old default for new_flow_logic left over from transition to pipeworks.toggles.pressure_logic --- default_settings.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/default_settings.lua b/default_settings.lua index 9aa4835..91e511c 100644 --- a/default_settings.lua +++ b/default_settings.lua @@ -27,8 +27,6 @@ local settings = { drop_on_routing_fail = false, delete_item_on_clearobject = true, - - enable_new_flow_logic = false, } for name, value in pairs(settings) do From 72f793e2b3a7de1ed2946424eedc3fb2b0d3a1b4 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 19:11:58 +0100 Subject: [PATCH 73/75] new flow logic: abm_register.lua: add extra safeguarding for conditional activation of new flow logic --- new_flow_logic/abm_register.lua | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/new_flow_logic/abm_register.lua b/new_flow_logic/abm_register.lua index ac7b2e3..1d038d6 100644 --- a/new_flow_logic/abm_register.lua +++ b/new_flow_logic/abm_register.lua @@ -1,30 +1,26 @@ -- register new flow logic ABMs -- written 2017 by thetaepsilon - - local register = {} pipeworks.flowlogic.abmregister = register local flowlogic = pipeworks.flowlogic --- A possible DRY violation here... --- DISCUSS: should it be possible later on to raise the the rate of ABMs, or lower the chance? --- Currently all the intervals and chances are hardcoded below. - - - -- register node list for the main logic function. -- see flowlogic.run() in abms.lua. local register_flowlogic_abm = function(nodename) - minetest.register_abm({ - nodenames = { nodename }, - interval = 1, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - flowlogic.run(pos, node) - end - }) + if pipeworks.toggles.pressure_logic then + minetest.register_abm({ + nodenames = { nodename }, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + flowlogic.run(pos, node) + end + }) + else + minetest.log("warning", "pipeworks pressure_logic not enabled but register.flowlogic() requested") + end end register.flowlogic = register_flowlogic_abm From 085ee7b497489564a0539069ebe781a00d4665e7 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 19:13:52 +0100 Subject: [PATCH 74/75] todo: remove new flow logic item about node variant switching --- todo/new_flow_logic.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/todo/new_flow_logic.txt b/todo/new_flow_logic.txt index 2cd15f1..5d83c55 100644 --- a/todo/new_flow_logic.txt +++ b/todo/new_flow_logic.txt @@ -8,10 +8,3 @@ In non-finite mode, spigots and fountainheads will vanish water sources in their This is annoying though not game-breaking in non-finite mode, where water sources can at least be easily replenished. Fixing this would require some kind of metadata marker on water nodes placed by spigots and fountains, such that only water sources placed while the device is "on" are removed when it is "off". It is debateable whether existing water sources should be marked for removal when the device turns on again. - --- Automated switching between node variants based on pressure thresholds -Within flowlogic.run(), an additional hook which would be useful is a "node changer" callback, to switch between variations of a pipe depending on pressure level. -For regular pipes, this is mostly aesthetic, as the empty/loaded variants of the pipes have different texures. -However, the flow sensor is currently a broken device under the new flow logic, as there is nothing to switch this device between the "on" and "off" state - in order to produce a mesecons output, separate nodes are required due to mesecon's API being limited to only on/off for a given node, with no facility for a callback function which could e.g. inspect pressure metadata. -To make this work, a new registry table would be needed to check if a flowable node has this property. -In terms of ordering, this callback should be run after outputs have been processed. From 467907602bec6f3a7adfa3058257732a8b903214 Mon Sep 17 00:00:00 2001 From: thetaepsilon-gamedev Date: Sun, 8 Oct 2017 19:22:07 +0100 Subject: [PATCH 75/75] changelog.txt: back entries for pressure_logic work --- changelog.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/changelog.txt b/changelog.txt index d766fc0..5efe201 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,18 @@ Changelog --------- +2017-10-08 (thetaepsilon) +A lot more of the new flow logic work. +There are two sub-modes of this now, non-finite and finite mode. +Non-finite mode most closely resembles "classic mode", whereas finite mode is more intended for use with mods such as dynamic_liquids which enable water sources to move themselves. +Everything that was functional in classic mode more or less works correctly now. +Still TODO: ++ Flow directionality - things like flow sensors and airtight panels will flow in directions that don't make sense from their visuals. +Possible feature requests: ++ Making tanks and gratings do something useful. + + + 2017-09-27 (thetaepsilon) Start of new flow logic re-implementation. This mode is current *very* incomplete, and requires a per-world setting to enable.