diff options
-rw-r--r-- | flowing_logic.lua | 212 |
1 files changed, 89 insertions, 123 deletions
diff --git a/flowing_logic.lua b/flowing_logic.lua index 2d5af3e..f654078 100644 --- a/flowing_logic.lua +++ b/flowing_logic.lua @@ -20,6 +20,53 @@ if mesecon then } end +-- check if a valve, sensor, or other X-oriented device +-- has something connected at each end. + +function pipeworks.is_device_connected(pos, node, axisdir, fdir_mod4, rotation) + local fdir = node.param2 + local fdir_mod4_p2 = (fdir+2) % 4 + + if rotation == "z" then + fdir_mod4 = (fdir+1) % 4 + fdir_mod4_p2 = (fdir+3) % 4 + end + + local fdir_to_pos = { + {x = pos.x+1, y = pos.y, z = pos.z }, + {x = pos.x, y = pos.y, z = pos.z-1}, + {x = pos.x-1, y = pos.y, z = pos.z }, + {x = pos.x, y = pos.y, z = pos.z+1}, + } + + local pos_adjacent1 = fdir_to_pos[fdir_mod4 + 1] + local pos_adjacent2 = fdir_to_pos[fdir_mod4_p2 + 1] + + if rotation == "y" then + pos_adjacent1 = { x=pos.x, y=pos.y+1, z=pos.z } + pos_adjacent2 = { x=pos.x, y=pos.y-1, z=pos.z } + end + + local adjacent_node1 = minetest.get_node(pos_adjacent1) + local adjacent_node2 = minetest.get_node(pos_adjacent2) + + local set1 + local set2 + + if string.find(dump(pipeworks.pipe_nodenames), adjacent_node1.name) or + (string.find(dump(pipeworks.device_nodenames), adjacent_node1.name) and + (adjacent_node1.param2 == fdir_mod4 or adjacent_node1.param2 == fdir_mod4_p2)) then + set1 = true + end + + if string.find(dump(pipeworks.pipe_nodenames), adjacent_node2.name) or + (string.find(dump(pipeworks.device_nodenames), adjacent_node2.name) and + (adjacent_node2.param2 == fdir_mod4 or adjacent_node2.param2 == fdir_mod4_p2)) then + set2 = true + end + return {set1=set1, set2=set2, pos_adjacent1=pos_adjacent1, pos_adjacent2=pos_adjacent2} +end + -- Evaluate and balance liquid in all pipes minetest.register_abm({ @@ -171,6 +218,10 @@ minetest.register_abm({ if not adjacent_node then return end local adjacent_node_level = (minetest.get_meta(pos_adjacent):get_float("liquid_level")) or 0 local pipe_name = string.match(adjacent_node.name, "pipeworks:pipe_%d.*_") + local device_name = string.match(adjacent_node.name, "pipeworks:valve_on.*") + or string.match(adjacent_node.name, "pipeworks:flow_sensor.*") + or string.match(adjacent_node.name, "pipeworks:entry_panel") + if pipe_name and adjacent_node_level > 0.9 and (below_node.name == "air" or below_node.name == "default:water_flowing") then @@ -201,74 +252,71 @@ table.insert(pipeworks.device_nodenames,"pipeworks:valve_off_empty") table.insert(pipeworks.device_nodenames,"pipeworks:valve_on_loaded") table.insert(pipeworks.device_nodenames,"pipeworks:flow_sensor_empty") table.insert(pipeworks.device_nodenames,"pipeworks:flow_sensor_loaded") +table.insert(pipeworks.device_nodenames,"pipeworks:entry_panel") minetest.register_abm({ nodenames = pipeworks.device_nodenames, interval = 2, chance = 1, action = function(pos, node, active_object_count, active_object_count_wider) - local fdir = node.param2 - local axisdir = math.floor(fdir/4) - local fdir_mod4 = fdir % 4 - local fdir_mod4_p2 = (fdir+2) % 4 - - if axisdir ~= 0 and axisdir ~= 5 then -- if it isn't horizontal, force it. - minetest.swap_node(pos, {name = node.name, param2 = fdir_mod4}) - return - end - local fdir_to_pos = { - {x = pos.x+1, y = pos.y, z = pos.z }, - {x = pos.x, y = pos.y, z = pos.z-1}, - {x = pos.x-1, y = pos.y, z = pos.z }, - {x = pos.x, y = pos.y, z = pos.z+1}, - } + local fdir = node.param2 + local axisdir = math.floor(fdir/4) + local fdir_mod4 = fdir % 4 + local rotation - local pos_adjacent1 = fdir_to_pos[fdir_mod4 + 1] - local pos_adjacent2 = fdir_to_pos[fdir_mod4_p2 + 1] + if not string.match(node.name, "pipeworks:valve_off") then - local adjacent_node1 = minetest.get_node(pos_adjacent1) - local adjacent_node2 = minetest.get_node(pos_adjacent2) + if node.name == "pipeworks:entry_panel" then + rotation = "z" + fdir_mod4 = (fdir+1) % 4 - if not adjacent_node1 or not adjacent_node2 then return end + -- reset the panel's facedir to predictable values, if needed - local my_level = (minetest.get_meta(pos):get_float("liquid_level")) or 0 - local adjacent_node_level1 = (minetest.get_meta(pos_adjacent1):get_float("liquid_level")) or 0 - local adjacent_node_level2 = (minetest.get_meta(pos_adjacent2):get_float("liquid_level")) or 0 + if axisdir == 5 then + minetest.swap_node(pos, {name = node.name, param2 = fdir_mod4 }) + return + elseif axisdir ~= 0 and axisdir ~= 3 then + minetest.swap_node(pos, {name = node.name, param2 = 13 }) + return + end - if not string.match(node.name, "pipeworks:valve_off") then + if node.param2 == 13 then + rotation = "y" + end + elseif axisdir ~= 0 and axisdir ~= 5 then -- if the device isn't horizontal, force it. + minetest.swap_node(pos, {name = node.name, param2 = fdir_mod4}) + return + end + + local connections = pipeworks.is_device_connected(pos, node, axisdir, fdir_mod4, rotation) local num_connections = 1 - local set1 - local set2 + local my_level = (minetest.get_meta(pos):get_float("liquid_level")) or 0 local total_level = my_level - if string.find(dump(pipeworks.pipe_nodenames), adjacent_node1.name) or - (string.find(dump(pipeworks.device_nodenames), adjacent_node1.name) and - (adjacent_node1.param2 == fdir_mod4 or adjacent_node1.param2 == fdir_mod4_p2)) then + if not connections.set1 and not connections.set2 then return end + + if connections.set1 then num_connections = num_connections + 1 - total_level = total_level + adjacent_node_level1 - set1 = true + total_level = total_level + (minetest.get_meta(connections.pos_adjacent1):get_float("liquid_level")) or 0 end - if string.find(dump(pipeworks.pipe_nodenames), adjacent_node2.name) or - (string.find(dump(pipeworks.device_nodenames), adjacent_node2.name) and - (adjacent_node2.param2 == fdir_mod4 or adjacent_node2.param2 == fdir_mod4_p2)) then + if connections.set2 then num_connections = num_connections + 1 - total_level = total_level + adjacent_node_level2 - set2 = true + total_level = total_level + (minetest.get_meta(connections.pos_adjacent2):get_float("liquid_level")) or 0 end local average_level = total_level / num_connections minetest.get_meta(pos):set_float("liquid_level", average_level) - if set1 then - minetest.get_meta(pos_adjacent1):set_float("liquid_level", average_level) + if connections.set1 then + minetest.get_meta(connections.pos_adjacent1):set_float("liquid_level", average_level) end - if set2 then - minetest.get_meta(pos_adjacent2):set_float("liquid_level", average_level) + if connections.set2 then + minetest.get_meta(connections.pos_adjacent2):set_float("liquid_level", average_level) end if node.name == "pipeworks:flow_sensor_empty" or @@ -276,7 +324,7 @@ minetest.register_abm({ local sensor = string.match(node.name, "pipeworks:flow_sensor_") local newnode = nil - if my_level > 1 and (set1 or set2) then + if my_level > 1 and (connections.set1 or connections.set2) then newnode = sensor.."loaded" else newnode = sensor.."empty" @@ -297,85 +345,3 @@ minetest.register_abm({ end }) -minetest.register_abm({ - nodenames = { "pipeworks:entry_panel" }, - interval = 2, - chance = 1, - action = function(pos, node, active_object_count, active_object_count_wider) - local fdir = node.param2 - local axisdir = math.floor(fdir/4) - local fdir_mod4 = (fdir+1) % 4 - local fdir_mod4_p2 = (fdir+3) % 4 - - -- reset the panel's facedir to predictable values, if needed - - if axisdir == 5 then - minetest.swap_node(pos, {name = node.name, param2 = fdir_mod4 }) - return - elseif axisdir ~= 0 and axisdir ~= 3 then - minetest.swap_node(pos, {name = node.name, param2 = 13 }) - return - end - - local pos_adjacent1 - local pos_adjacent2 - - if axisdir == 0 then - local fdir_to_pos = { - {x = pos.x+1, y = pos.y, z = pos.z }, - {x = pos.x, y = pos.y, z = pos.z-1}, - {x = pos.x-1, y = pos.y, z = pos.z }, - {x = pos.x, y = pos.y, z = pos.z+1}, - } - - pos_adjacent1 = fdir_to_pos[fdir_mod4 + 1] - pos_adjacent2 = fdir_to_pos[fdir_mod4_p2 + 1] - else - pos_adjacent1 = { x=pos.x, y=pos.y+1, z=pos.z } - pos_adjacent2 = { x=pos.x, y=pos.y-1, z=pos.z } - end - - local adjacent_node1 = minetest.get_node(pos_adjacent1) - local adjacent_node2 = minetest.get_node(pos_adjacent2) - - if not adjacent_node1 or not adjacent_node2 then return end - - local my_level = (minetest.get_meta(pos):get_float("liquid_level")) or 0 - local adjacent_node_level1 = (minetest.get_meta(pos_adjacent1):get_float("liquid_level")) or 0 - local adjacent_node_level2 = (minetest.get_meta(pos_adjacent2):get_float("liquid_level")) or 0 - - local num_connections = 1 - local set1 - local set2 - local total_level = my_level - - if string.find(dump(pipeworks.pipe_nodenames), adjacent_node1.name) or - (axisdir == 3 and string.find(dump(pipeworks.device_nodenames), adjacent_node1.name) and - (adjacent_node1.param2 == fdir_mod4 or adjacent_node1.param2 == fdir_mod4_p2)) then - num_connections = num_connections + 1 - total_level = total_level + adjacent_node_level1 - set1 = true - end - - if string.find(dump(pipeworks.pipe_nodenames), adjacent_node2.name) or - (axisdir == 3 and string.find(dump(pipeworks.device_nodenames), adjacent_node2.name) and - (adjacent_node2.param2 == fdir_mod4 or adjacent_node2.param2 == fdir_mod4_p2)) then - num_connections = num_connections + 1 - total_level = total_level + adjacent_node_level2 - set2 = true - end - - local average_level = total_level / num_connections - - minetest.get_meta(pos):set_float("liquid_level", average_level) - - if set1 then - minetest.get_meta(pos_adjacent1):set_float("liquid_level", average_level) - end - - if set2 then - minetest.get_meta(pos_adjacent2):set_float("liquid_level", average_level) - end - end -}) - |