summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorroot <root@linuxworks.belug.de>2017-10-19 14:21:27 +0200
committerroot <root@linuxworks.belug.de>2017-10-19 14:21:27 +0200
commit277154cf2daf870044c6f5bac90f338552fb75df (patch)
tree9cc6bb59a684df55155d69fc1b1ec2c8c181e22c
parent848741a294363431a2a6e9c32ddf693951951fec (diff)
parent9df0ec7edb55ba443acc68df9ed63fdd53c66bfa (diff)
Merge branch 'master' of https://github.com/minetest-mods/pipeworks
-rw-r--r--devices.lua27
-rw-r--r--filter-injector.lua4
-rw-r--r--init.lua2
-rw-r--r--pressure_logic/abm_register.lua (renamed from new_flow_logic/abm_register.lua)1
-rw-r--r--pressure_logic/abms.lua (renamed from new_flow_logic/abms.lua)92
-rw-r--r--pressure_logic/flowable_node_registry.lua (renamed from new_flow_logic/flowable_node_registry.lua)31
-rw-r--r--pressure_logic/flowable_node_registry_install.lua (renamed from new_flow_logic/flowable_node_registry_install.lua)70
-rw-r--r--todo/pressure_logic.txt (renamed from todo/new_flow_logic.txt)26
8 files changed, 192 insertions, 61 deletions
diff --git a/devices.lua b/devices.lua
index 5203bf3..093137e 100644
--- a/devices.lua
+++ b/devices.lua
@@ -161,16 +161,18 @@ for s in ipairs(states) do
local fdir = node.param2
minetest.swap_node(pos, { name = "pipeworks:pump_"..states[3-s], param2 = fdir })
end,
- -- 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)
+
+ -- FIXME: this currently assumes that pumps can only rotate around the fixed axis pointing Y+.
+ new_flow_logic_register.directional_vertical_fixed(pumpname, true)
local pump_drive = 4
if states[s] ~= "off" then
new_flow_logic_register.intake_simple(pumpname, pump_drive)
end
+
+
local nodename_valve_empty = "pipeworks:valve_"..states[s].."_empty"
minetest.register_node(nodename_valve_empty, {
description = "Valve",
@@ -213,8 +215,7 @@ for s in ipairs(states) do
-- 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)
+ new_flow_logic_register.directional_horizonal_rotate(nodename_valve_empty)
end
end
@@ -262,7 +263,7 @@ minetest.register_node(nodename_valve_loaded, {
-- 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)
+new_flow_logic_register.directional_horizonal_rotate(nodename_valve_loaded)
-- grating
@@ -436,10 +437,9 @@ 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)
+new_flow_logic_register.directional_horizonal_rotate(nodename_panel_empty)
+new_flow_logic_register.directional_horizonal_rotate(nodename_panel_loaded)
@@ -521,9 +521,8 @@ 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)
+new_flow_logic_register.directional_horizonal_rotate(nodename_sensor_empty)
+new_flow_logic_register.directional_horizonal_rotate(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, { mesecons=pipeworks.mesecons_rules })
@@ -672,8 +671,8 @@ 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)
+new_flow_logic_register.directional_vertical_fixed(nodename_fountain_empty, false)
+new_flow_logic_register.directional_vertical_fixed(nodename_fountain_loaded, false)
local fountain_upper = 1.0
local fountain_lower = 1.0
local fountain_neighbours={{x=0, y=1, z=0}}
diff --git a/filter-injector.lua b/filter-injector.lua
index c9d132f..0f651fb 100644
--- a/filter-injector.lua
+++ b/filter-injector.lua
@@ -115,7 +115,7 @@ local function grabAndFire(data,slotseq_mode,exmatch_mode,filtmeta,frominv,fromi
local stack = frominv:get_stack(frominvname, spos)
local doRemove = stack:get_count()
if fromtube.can_remove then
- doRemove = fromtube.can_remove(frompos, fromnode, stack, dir)
+ doRemove = fromtube.can_remove(frompos, fromnode, stack, dir, frominvname, spos)
elseif fromdef.allow_metadata_inventory_take then
doRemove = fromdef.allow_metadata_inventory_take(frompos, frominvname,spos, stack, fakePlayer)
end
@@ -146,7 +146,7 @@ local function grabAndFire(data,slotseq_mode,exmatch_mode,filtmeta,frominv,fromi
end
if fromtube.remove_items then
-- it could be the entire stack...
- item = fromtube.remove_items(frompos, fromnode, stack, dir, count)
+ item = fromtube.remove_items(frompos, fromnode, stack, dir, count, frominvname, spos)
else
item = stack:take_item(count)
frominv:set_stack(frominvname, spos, stack)
diff --git a/init.lua b/init.lua
index 8974005..f4276f8 100644
--- a/init.lua
+++ b/init.lua
@@ -126,7 +126,7 @@ dofile(pipeworks.modpath.."/filter-injector.lua")
dofile(pipeworks.modpath.."/trashcan.lua")
dofile(pipeworks.modpath.."/wielder.lua")
-local logicdir = "/new_flow_logic/"
+local logicdir = "/pressure_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,
diff --git a/new_flow_logic/abm_register.lua b/pressure_logic/abm_register.lua
index 1d038d6..a8e3abc 100644
--- a/new_flow_logic/abm_register.lua
+++ b/pressure_logic/abm_register.lua
@@ -12,6 +12,7 @@ local flowlogic = pipeworks.flowlogic
local register_flowlogic_abm = function(nodename)
if pipeworks.toggles.pressure_logic then
minetest.register_abm({
+ label = "pipeworks new_flow_logic run",
nodenames = { nodename },
interval = 1,
chance = 1,
diff --git a/new_flow_logic/abms.lua b/pressure_logic/abms.lua
index 0b0b799..083d8c3 100644
--- a/new_flow_logic/abms.lua
+++ b/pressure_logic/abms.lua
@@ -31,6 +31,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.
@@ -120,8 +122,67 @@ end
+local simple_neighbour_offsets = {
+ {x=0, y=-1,z= 0},
+ {x=0, y= 1,z= 0},
+ {x=-1,y= 0,z= 0},
+ {x= 1,y= 0,z= 0},
+ {x= 0,y= 0,z=-1},
+ {x= 0,y= 0,z= 1},
+}
+local get_neighbour_positions = function(pos, node)
+ -- local dname = "get_neighbour_positions@"..formatvec(pos).." "
+ -- get list of node neighbours.
+ -- if this node is directional and only flows on certain sides,
+ -- invoke the callback to retrieve the set.
+ -- for simple flowables this is just an auto-gen'd list of all six possible neighbours.
+ local candidates = {}
+ if pipeworks.flowables.list.simple[node.name] then
+ candidates = simple_neighbour_offsets
+ else
+ -- directional flowables: call the callback to get the list
+ local directional = pipeworks.flowables.list.directional[node.name]
+ if directional then
+ --pipeworks.logger(dname.."invoking neighbourfn")
+ local offsets = directional.neighbourfn(node)
+ candidates = offsets
+ end
+ end
+
+ -- then, check each possible neighbour to see if they can be reached from this node.
+ local connections = {}
+ for index, offset in ipairs(candidates) do
+ local npos = vector.add(pos, offset)
+ local neighbour = minetest.get_node(npos)
+ local nodename = neighbour.name
+ local is_simple = (pipeworks.flowables.list.simple[nodename])
+ if is_simple then
+ local n = get_pressure_access(npos)
+ table.insert(connections, n)
+ else
+ -- if target node is also directional, check if it agrees it can flow in that direction
+ local directional = pipeworks.flowables.list.directional[nodename]
+ if directional then
+ --pipeworks.logger(dname.."directionality test for offset "..formatvec(offset))
+ local towards_origin = vector.multiply(offset, -1)
+ --pipeworks.logger(dname.."vector passed to directionfn: "..formatvec(towards_origin))
+ local result = directional.directionfn(neighbour, towards_origin)
+ --pipeworks.logger(dname.."result: "..tostring(result))
+ if result then
+ local n = get_pressure_access(npos)
+ table.insert(connections, n)
+ end
+ end
+ end
+ end
+
+ return connections
+end
+
+
+
flowlogic.balance_pressure = function(pos, node, currentpressure)
- -- debuglog("balance_pressure() "..node.name.." at "..pos.x.." "..pos.y.." "..pos.z)
+ -- local dname = "flowlogic.balance_pressure()@"..formatvec(pos).." "
-- check the pressure of all nearby flowable nodes, and average it out.
-- pressure handles to average over
@@ -131,31 +192,14 @@ flowlogic.balance_pressure = function(pos, node, currentpressure)
local totalv = currentpressure
local totalc = 1
- -- get list of node neighbours.
- -- if this node is directional and only flows on certain sides,
- -- invoke the callback to retrieve the set.
- -- for simple flowables this is just an auto-gen'd list of all six possible neighbours.
- local candidates = {}
- if pipeworks.flowables.list.simple[node.name] then
- candidates = make_coords_offsets(pos, false)
- end
+ local connections = get_neighbour_positions(pos, node)
- -- then handle neighbours, but if not a pressure node don't consider them at all
- for _, npos in ipairs(candidates) do
- local nodename = minetest.get_node(npos).name
- -- 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()
- table.insert(connections, neighbour)
- totalv = totalv + n
- totalc = totalc + 1
- end
+ -- for each neighbour, add neighbour's pressure to the total to balance out
+ for _, neighbour in ipairs(connections) do
+ local n = neighbour.get()
+ totalv = totalv + n
+ totalc = totalc + 1
end
-
local average = totalv / totalc
for _, target in ipairs(connections) do
target.set(average)
diff --git a/new_flow_logic/flowable_node_registry.lua b/pressure_logic/flowable_node_registry.lua
index 2523803..6d7bf17 100644
--- a/new_flow_logic/flowable_node_registry.lua
+++ b/pressure_logic/flowable_node_registry.lua
@@ -17,6 +17,24 @@ pipeworks.flowables.list.all = {}
pipeworks.flowables.list.simple = {}
pipeworks.flowables.list.simple_nodenames = {}
+-- directional flowables - can only flow on certain sides
+-- format per entry is a table with the following fields:
+-- neighbourfn: function(node),
+-- called to determine which nodes to consider as neighbours.
+-- can be used to e.g. inspect the node's param values for facedir etc.
+-- returns: array of vector offsets to look for possible neighbours in
+-- directionfn: function(node, vector):
+-- can this node flow in this direction?
+-- called in the context of another node to check the matching entry returned by neighbourfn.
+-- for every offset vector returned by neighbourfn,
+-- the node at that absolute position is checked.
+-- if that node is also a directional flowable,
+-- then that node's vector is passed to that node's directionfn
+-- (inverted, so that directionfn sees a vector pointing out from it back to the origin node).
+-- if directionfn agrees that the neighbour node can currently flow in that direction,
+-- the neighbour is to participate in pressure balancing.
+pipeworks.flowables.list.directional = {}
+
-- simple intakes - try to absorb any adjacent water nodes
pipeworks.flowables.inputs = {}
pipeworks.flowables.inputs.list = {}
@@ -33,16 +51,3 @@ 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
-
-
-
--- 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
diff --git a/new_flow_logic/flowable_node_registry_install.lua b/pressure_logic/flowable_node_registry_install.lua
index c8f6889..7b14fd3 100644
--- a/new_flow_logic/flowable_node_registry_install.lua
+++ b/pressure_logic/flowable_node_registry_install.lua
@@ -20,6 +20,9 @@ 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)
+ if pipeworks.toggles.pressure_logic then
+ abmregister.flowlogic(nodename)
+ end
end
local regwarning = function(kind, nodename)
@@ -35,12 +38,73 @@ register.simple = function(nodename)
insertbase(nodename)
pipeworks.flowables.list.simple[nodename] = true
table.insert(pipeworks.flowables.list.simple_nodenames, nodename)
- if pipeworks.toggles.pressure_logic then
- abmregister.flowlogic(nodename)
- end
regwarning("simple", nodename)
end
+-- Register a node as a directional flowable:
+-- has a helper function which determines which nodes to consider valid neighbours.
+register.directional = function(nodename, neighbourfn, directionfn)
+ insertbase(nodename)
+ pipeworks.flowables.list.directional[nodename] = {
+ neighbourfn = neighbourfn,
+ directionfn = directionfn
+ }
+ regwarning("directional", nodename)
+end
+
+-- register a node as a directional flowable that can only flow through either the top or bottom side.
+-- used for fountainheads (bottom side) and pumps (top side).
+-- this is in world terms, not facedir relative!
+register.directional_vertical_fixed = function(nodename, topside)
+ local y
+ if topside then y = 1 else y = -1 end
+ local side = { x=0, y=y, z=0 }
+ local neighbourfn = function(node) return { side } end
+ local directionfn = function(node, direction)
+ return vector.equals(direction, side)
+ end
+ register.directional(nodename, neighbourfn, directionfn)
+end
+
+-- register a node as a directional flowable whose accepting sides depends upon param2 rotation.
+-- used for entry panels, valves, flow sensors and spigots,
+-- whose facing axis is always upwards and can only rotate horizontally.
+local iseastwest = function(node)
+ local data = node.param2
+ local rotation = data % 4
+ -- rotation 0 and 2 is the same axis, as is 1 and 3.
+ -- 0-3 starts at north and proceeds clockwise.
+ local axis = rotation % 2
+ --pipeworks.logger("iseastwest() rotation="..tostring(rotation).." axis="..tostring(axis))
+ return (axis == 1)
+end
+register.directional_horizonal_rotate = function(nodename)
+ local north = {x= 0,y= 0,z= 1}
+ local south = {x= 0,y= 0,z=-1}
+ local east = {x= 1,y= 0,z= 0}
+ local west = {x=-1,y= 0,z= 0}
+ local neighbourfn = function(node)
+ if iseastwest(node) then
+ return { east, west }
+ else
+ return { north, south }
+ end
+ end
+ local directionfn = function(node, direction)
+ local result = false
+ if iseastwest(node) then
+ --pipeworks.logger("horizontal rotate directionfn() eastwest=true")
+ result = vector.equals(direction, east) or vector.equals(direction, west)
+ else
+ result = vector.equals(direction, north) or vector.equals(direction, south)
+ end
+ return result
+ end
+ register.directional(nodename, neighbourfn, directionfn)
+end
+
+
+
local checkbase = function(nodename)
if not checkexists(nodename) then error("pipeworks.flowables node doesn't exist as a flowable!") end
end
diff --git a/todo/new_flow_logic.txt b/todo/pressure_logic.txt
index b6787e9..41ce2f8 100644
--- a/todo/new_flow_logic.txt
+++ b/todo/pressure_logic.txt
@@ -1,7 +1,9 @@
--- 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.
+-- Directionality code (in progress)
+The flowable node class for directional nodes now exists and is hooked up in the code for determining valid neighbours in the flowable node ABM routines.
+Pumps have been converted to this as part of the testing.
+However, currently only the "raw" registration for this is available, and the pump definition registers it's own callback routines.
+Helpers need to be added to flowable_node_registry_install.lua to abstract away the expression of which nodes can flow which ways - valves, flow sensors, spigots and entry panels, for instance, all currently rotate the same way using an upwards facedir, so a helper for these nodes would prevent code duplication.
+
-- (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.
@@ -20,3 +22,19 @@ VanessaE would like this to function as an output with the following properties:
* While on, tries to randomly place a water source in an adjacent node every ABM interval, preferring to place it downwards first.
* Even with multiple water source nodes placed, only drains 1 unit pressure per ABM interval in non-finite mode. Finite mode will cause it to drain 1 unit per water source node placed and simply stop placing sources when below threshold pressure, like spigots and fountainheads already do.
* When turning off in non-finite mode, for all neighbour nodes, replace the water sources with flowing water as discussed above, but *only* if those neighbouring sources do not have any water source neighbours of their own in turn - this will prevent the block from creating a "hole" in a uniform pool of water sources.
+
+
+
+-- Support for other fluids in pipes (Feature request/wish list)
+Various sources from IRC and github issues have indicated that the ability to carry amounts of substance other than water through pipes would see uses appear for it if it were implemented (there does not appear to be anything trying to do so right now).
+Extending the pressure mechanism to handle new fluids would be simple enough, it would just have to deal with more variables.
+However, this feature raises the question of how to handle mixtures of fluids in pipes.
+
+Two possible solutions appear evident:
++ Don't mix at all. For each flowable registered, either a variant would be created for each supported liquid, or each node would declare which fluid it carries explicitly. Flowable nodes for different fluids would not interact with each other at all.
+
++ Equalise "pressure" of multiple fluid variables in a similar manner to how the single water pressure value is currently balanced out, however this raises the issue of how to deal with mixtures - for instance, how is a spigot to function with a mixed liquid? does it simply refuse to function if it doesn't know how to deal with a certain mixture (as it can only output whole nodes)? likewise for certain mixtures in pipes, should it be allowed for lava and water for instance to mix like they don't interact at all?
+
+This mechanism also hints at a weakness of the pressure logic mechanism as it currently stands - namely that liquids are handled like gases and assumed to be compressible.
+
+