summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVanessa Ezekowitz <vanessaezekowitz@gmail.com>2014-01-01 15:57:51 -0500
committerVanessa Ezekowitz <vanessaezekowitz@gmail.com>2015-06-18 12:42:19 -0400
commit24ff13d7db9fab896c8d2e79574c3647823d7b35 (patch)
tree94e73f5f5895f22ad3650615c827dc6292fd79bd
parent5822f60ba9cbebe45c1f82fa06dc93b747ba71a6 (diff)
complete rewrite of water flowing logic
also implements leak-down in "off" pumps fixes failure to remove water source when digging active spigot/fountain
-rw-r--r--devices.lua75
-rw-r--r--flowing_logic.lua281
-rw-r--r--init.lua2
-rw-r--r--pipes.lua54
4 files changed, 201 insertions, 211 deletions
diff --git a/devices.lua b/devices.lua
index 52f3002..81a5ca6 100644
--- a/devices.lua
+++ b/devices.lua
@@ -241,6 +241,11 @@ minetest.register_node("pipeworks:spigot_pouring", {
end,
after_dig_node = function(pos)
pipeworks.scan_for_pipe_objects(pos)
+ local pos_below = {x = pos.x, y = pos.y-1, z = pos.z}
+ local below_node = minetest.get_node(pos_below)
+ if below_node.name == "default:water_source" then
+ minetest.set_node(pos_below, { name = "air" })
+ end
end,
selection_box = {
type = "fixed",
@@ -264,7 +269,7 @@ local panel_cbox = {
}
}
-minetest.register_node("pipeworks:entry_panel_empty", {
+minetest.register_node("pipeworks:entry_panel", {
description = "Airtight Pipe entry/exit",
drawtype = "mesh",
mesh = "pipeworks_entry_panel.obj",
@@ -321,7 +326,7 @@ minetest.register_node("pipeworks:entry_panel_empty", {
if not minetest.registered_nodes[minetest.get_node(pos1).name]["buildable_to"] then return end
- minetest.add_node(pos1, {name = "pipeworks:entry_panel_empty", param2 = fdir })
+ minetest.add_node(pos1, {name = "pipeworks:entry_panel", param2 = fdir })
pipeworks.scan_for_pipe_objects(pos1)
if not pipeworks.expect_infinite_stacks then
@@ -336,26 +341,10 @@ minetest.register_node("pipeworks:entry_panel_empty", {
end
})
-minetest.register_node("pipeworks:entry_panel_loaded", {
- description = "Airtight Pipe entry/exit",
- drawtype = "mesh",
- mesh = "pipeworks_entry_panel.obj",
- tiles = { "pipeworks_entry_panel.png" },
- paramtype = "light",
- paramtype2 = "facedir",
- groups = {snappy=3, pipe=1, not_in_creative_inventory=1},
- sounds = default.node_sound_wood_defaults(),
- walkable = true,
- after_place_node = function(pos)
- pipeworks.scan_for_pipe_objects(pos)
- end,
- after_dig_node = function(pos)
- pipeworks.scan_for_pipe_objects(pos)
- end,
- selection_box = panel_cbox,
- collision_box = panel_cbox,
- drop = "pipeworks:entry_panel_empty"
-})
+local sensorboxes = {}
+pipeworks.add_node_box(sensorboxes, pipeworks.pipe_leftstub)
+pipeworks.add_node_box(sensorboxes, pipeworks.pipe_sensorbody)
+pipeworks.add_node_box(sensorboxes, pipeworks.pipe_rightstub)
minetest.register_node("pipeworks:flow_sensor_empty", {
description = "Flow Sensor",
@@ -519,38 +508,12 @@ minetest.register_node("pipeworks:fountainhead", {
end,
after_dig_node = function(pos)
pipeworks.scan_for_pipe_objects(pos)
- end,
- on_construct = function(pos)
- if mesecon then
- mesecon.receptor_on(pos, rules)
+ local pos_above = {x = pos.x, y = pos.y+1, z = pos.z}
+ local node_above = minetest.get_node(pos_above)
+ if node_above.name == "default:water_source" then
+ minetest.set_node(pos_above, { name = "air" })
end
end,
- selection_box = {
- type = "fixed",
- fixed = { -2/16, -8/16, -2/16, 2/16, 8/16, 2/16 }
- },
- collision_box = {
- type = "fixed",
- fixed = { -2/16, -8/16, -2/16, 2/16, 8/16, 2/16 }
- },
-})
-
-minetest.register_node("pipeworks:fountainhead_pouring", {
- description = "Fountainhead",
- drawtype = "mesh",
- mesh = "pipeworks_fountainhead.obj",
- tiles = { "pipeworks_fountainhead.png" },
- sunlight_propagates = true,
- paramtype = "light",
- groups = {snappy=3, pipe=1, not_in_creative_inventory=1},
- sounds = default.node_sound_wood_defaults(),
- walkable = true,
- after_place_node = function(pos)
- pipeworks.scan_for_pipe_objects(pos)
- end,
- after_dig_node = function(pos)
- pipeworks.scan_for_pipe_objects(pos)
- end,
on_construct = function(pos)
if mesecon then
mesecon.receptor_on(pos, rules)
@@ -564,9 +527,13 @@ minetest.register_node("pipeworks:fountainhead_pouring", {
type = "fixed",
fixed = { -2/16, -8/16, -2/16, 2/16, 8/16, 2/16 }
},
- drop = "pipeworks:fountainhead"
})
+-- compatibility
+
minetest.register_alias("pipeworks:valve_off_loaded", "pipeworks:valve_off_empty")
-minetest.register_alias("pipeworks:entry_panel", "pipeworks:entry_panel_empty")
+minetest.register_alias("pipeworks:fountainhead_pouring", "pipeworks:fountainhead")
+minetest.register_alias("pipeworks:entry_panel", "pipeworks:entry_panel_empty")
+minetest.register_alias("pipeworks:entry_panel_empty", "pipeworks:entry_panel")
+minetest.register_alias("pipeworks:entry_panel_loaded", "pipeworks:entry_panel")
diff --git a/flowing_logic.lua b/flowing_logic.lua
index e0a6236..7dbfa08 100644
--- a/flowing_logic.lua
+++ b/flowing_logic.lua
@@ -1,121 +1,192 @@
--- This file provides the actual flow and pathfinding logic that makes water
+-- This file provides the actual flow logic that makes liquids
-- move through the pipes.
---
--- Contributed by mauvebic, 2013-01-03, rewritten a bit by Vanessa Ezekowitz
---
-
-local finitewater = minetest.setting_getbool("liquid_finite")
-
-pipeworks.check_for_liquids = function(pos)
- local coords = {
- {x=pos.x,y=pos.y-1,z=pos.z},
- {x=pos.x,y=pos.y+1,z=pos.z},
- {x=pos.x-1,y=pos.y,z=pos.z},
- {x=pos.x+1,y=pos.y,z=pos.z},
- {x=pos.x,y=pos.y,z=pos.z-1},
- {x=pos.x,y=pos.y,z=pos.z+1}, }
- for i =1,6 do
- local name = minetest.get_node(coords[i]).name
- if name and string.find(name,"water") then
- if finitewater then minetest.remove_node(coords[i]) end
- return true
+
+local finite_liquids = minetest.setting_getbool("liquid_finite")
+local pipe_liquid_max = 8
+local pipe_liquid_shows_loaded = 2
+
+-- Evaluate and balance liquid in all pipes
+
+minetest.register_abm({
+ nodenames = pipeworks.pipe_nodenames,
+ interval = 2,
+ chance = 1,
+ action = function(pos, node, active_object_count, active_object_count_wider)
+ local coords = {
+ {x = pos.x, y = pos.y, z = pos.z},
+ {x = pos.x, y = pos.y-1, z = pos.z},
+ {x = pos.x, y = pos.y+1, z = pos.z},
+ {x = pos.x-1, y = pos.y, z = pos.z},
+ {x = pos.x+1, y = pos.y, z = pos.z},
+ {x = pos.x, y = pos.y, z = pos.z-1},
+ {x = pos.x, y = pos.y, z = pos.z+1},
+ }
+
+ local num_connections = 0
+ local connection_list = {}
+ local total_level = 0
+
+ for _,adjacentpos in ipairs(coords) do
+ local adjacent_node = minetest.get_node(adjacentpos)
+ if adjacent_node and string.find(dump(pipeworks.pipe_nodenames), adjacent_node.name) then
+
+ local node_level = (minetest.get_meta(adjacentpos):get_float("liquid_level")) or 0
+ if node_level < 0 then node_level = 0 end
+
+ total_level = total_level + node_level
+ num_connections = num_connections + 1
+ table.insert(connection_list, adjacentpos)
+ end
end
- end
- return false
-end
-
-pipeworks.check_for_inflows = function(pos,node)
- local coords = {
- {x=pos.x,y=pos.y-1,z=pos.z},
- {x=pos.x,y=pos.y+1,z=pos.z},
- {x=pos.x-1,y=pos.y,z=pos.z},
- {x=pos.x+1,y=pos.y,z=pos.z},
- {x=pos.x,y=pos.y,z=pos.z-1},
- {x=pos.x,y=pos.y,z=pos.z+1}, }
- local newnode = false
- local source = false
- for i =1,6 do
- if newnode then break end
- local name = minetest.get_node(coords[i]).name
- if name and (name == "pipeworks:pump_on" and pipeworks.check_for_liquids(coords[i])) or string.find(name,"_loaded") then
- if string.find(name,"_loaded") then
- source = minetest.get_meta(coords[i]):get_string("source")
- if source == minetest.pos_to_string(pos) then break end
+
+ local average_level = total_level / num_connections
+
+ for _, connected_pipe_pos in ipairs(connection_list) do
+
+ local newnode
+ local connected_pipe = minetest.get_node(connected_pipe_pos)
+ local pipe_name = string.match(connected_pipe.name, "pipeworks:pipe_%d.*_")
+
+ if connected_pipe and pipe_name then
+ minetest.get_meta(connected_pipe_pos):set_float("liquid_level", average_level)
+
+ if average_level > pipe_liquid_shows_loaded then
+ newnode = pipe_name.."loaded"
+ else
+ newnode = pipe_name.."empty"
+ end
+ end
+
+ if newnode and connected_pipe.name ~= newnode then
+ minetest.swap_node(connected_pipe_pos, {name = newnode, param2 = connected_pipe.param2})
end
- newnode = string.gsub(node.name,"empty","loaded")
- source = {x=coords[i].x,y=coords[i].y,z=coords[i].z}
end
end
- if newnode then
- minetest.add_node(pos,{name=newnode, param2 = node.param2})
- minetest.get_meta(pos):set_string("source",minetest.pos_to_string(source))
- end
-end
-
-pipeworks.check_sources = function(pos,node)
- local sourcepos = minetest.string_to_pos(minetest.get_meta(pos):get_string("source"))
- if not sourcepos then return end
- local source = minetest.get_node(sourcepos).name
- local newnode = false
- if source and not ((source == "pipeworks:pump_on" and pipeworks.check_for_liquids(sourcepos)) or string.find(source,"_loaded") or source == "ignore" ) then
- newnode = string.gsub(node.name,"loaded","empty")
- end
+})
- if newnode then
- minetest.add_node(pos,{name=newnode, param2 = node.param2})
- minetest.get_meta(pos):set_string("source","")
- end
-end
-
-pipeworks.spigot_check = function(pos, node)
- local belowname = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z}).name
- if belowname and (belowname == "air" or belowname == "default:water_flowing" or belowname == "default:water_source") then
- local spigotname = minetest.get_node(pos).name
- local fdir=node.param2
- local check = {
- {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},
- {x=pos.x-1,y=pos.y,z=pos.z}
- }
- local near_node = minetest.get_node(check[fdir+1])
- if near_node and string.find(near_node.name, "_loaded") then
- if spigotname and spigotname == "pipeworks:spigot" then
- minetest.add_node(pos,{name = "pipeworks:spigot_pouring", param2 = fdir})
- if finitewater or belowname ~= "default:water_source" then
- minetest.add_node({x=pos.x,y=pos.y-1,z=pos.z},{name = "default:water_source"})
+-- Process all pumps in the area
+
+minetest.register_abm({
+ nodenames = {"pipeworks:pump_on", "pipeworks:pump_off"},
+ interval = 1,
+ chance = 1,
+ action = function(pos, node, active_object_count, active_object_count_wider)
+ local minp = {x = pos.x-1, y = pos.y-1, z = pos.z-1}
+ local maxp = {x = pos.x+1, y = pos.y, z = pos.z+1}
+ local pos_above = {x = pos.x, y = pos.y+1, z = pos.z}
+ local node_above = minetest.get_node(pos_above)
+ if not node_above then return end
+
+ local meta = minetest.get_meta(pos_above)
+ local node_level_above = meta:get_float("liquid_level")
+ if node_level_above == nil then node_level_above = 0 end
+ local pipe_name = string.match(node_above.name, "pipeworks:pipe_%d.*_")
+
+ if pipe_name then
+ if node.name == "pipeworks:pump_on" then
+ local water_nodes = minetest.find_nodes_in_area(minp, maxp,
+ {"default:water_source", "default:water_flowing"})
+ if (node_level_above < pipe_liquid_max) and #water_nodes > 1 then
+ meta:set_float("liquid_level", node_level_above + 4) -- add water to the pipe
end
- end
- else
- if spigotname == "pipeworks:spigot_pouring" then
- minetest.add_node({x=pos.x,y=pos.y,z=pos.z},{name = "pipeworks:spigot", param2 = fdir})
- if belowname == "default:water_source" and not finitewater then
- minetest.remove_node({x=pos.x,y=pos.y-1,z=pos.z})
+ else
+ if node_level_above > 0 then
+ meta:set_float("liquid_level", node_level_above - 1) -- leak the pipe down
end
end
end
end
-end
-
-pipeworks.fountainhead_check = function(pos, node)
- local abovename = minetest.get_node({x=pos.x,y=pos.y+1,z=pos.z}).name
- if abovename and (abovename == "air" or abovename == "default:water_flowing" or abovename == "default:water_source") then
- local fountainhead_name = minetest.get_node(pos).name
- local near_node = minetest.get_node({x=pos.x,y=pos.y-1,z=pos.z})
- if near_node and string.find(near_node.name, "_loaded") then
- if fountainhead_name and fountainhead_name == "pipeworks:fountainhead" then
- minetest.add_node(pos,{name = "pipeworks:fountainhead_pouring"})
- if finitewater or abovename ~= "default:water_source" then
- minetest.add_node({x=pos.x,y=pos.y+1,z=pos.z},{name = "default:water_source"})
- end
+})
+
+-- Process all fountainheads in the area
+
+minetest.register_abm({
+ nodenames = {"pipeworks:fountainhead"},
+ interval = 1,
+ chance = 1,
+ action = function(pos, node, active_object_count, active_object_count_wider)
+ local pos_above = {x = pos.x, y = pos.y+1, z = pos.z}
+ local node_above = minetest.get_node(pos_above)
+ if not node_above then return end
+
+ local pos_below = {x = pos.x, y = pos.y-1, z = pos.z}
+ local node_below = minetest.get_node(pos_below)
+ if not node_below then return end
+
+ local node_level_below = (minetest.get_meta(pos_below):get_float("liquid_level")) or 0
+ print(node_level_below)
+ print(dump(node_above.name))
+
+ if node_level_below > 2
+ and (node_above.name == "air" or node_above.name == "default:water_flowing") then
+ minetest.set_node(pos_above, {name = "default:water_source"})
+ elseif node_level_below < 1 and node_above.name == "default:water_source" then
+ minetest.set_node(pos_above, {name = "air"})
+ end
+
+ if node_level_below > 1
+ and (node_above.name == "air" or node_above.name == "default:water_source") then
+ minetest.get_meta(pos_below):set_float("liquid_level", node_level_below - 1)
+ end
+ end
+})
+
+-- Process all spigots in the area
+
+minetest.register_abm({
+ nodenames = {"pipeworks:spigot","pipeworks:spigot_pouring"},
+ interval = 1,
+ chance = 1,
+ action = function(pos, node, active_object_count, active_object_count_wider)
+ local pos_below = {x = pos.x, y = pos.y-1, z = pos.z}
+ local below_node = minetest.get_node(pos_below)
+ if not below_node then return end
+
+ if below_node.name == "air" or below_node.name == "default:water_flowing"
+ or below_node.name == "default:water_source" then
+ local fdir = node.param2
+ local fdir_to_pos = {
+ {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},
+ {x = pos.x-1, y = pos.y, z = pos.z }
+ }
+
+ local pos_adjacent = fdir_to_pos[fdir+1]
+ local adjacent_node = minetest.get_node(pos_adjacent)
+ 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.*_")
+
+ if pipe_name and adjacent_node_level > 2
+ and (below_node.name == "air" or below_node.name == "default:water_flowing") then
+ minetest.set_node(pos, {name = "pipeworks:spigot_pouring", param2 = fdir})
+ minetest.set_node(pos_below, {name = "default:water_source"})
end
- else
- if fountainhead_name == "pipeworks:fountainhead_pouring" then
- minetest.add_node({x=pos.x,y=pos.y,z=pos.z},{name = "pipeworks:fountainhead"})
- if abovename == "default:water_source" and not finitewater then
- minetest.remove_node({x=pos.x,y=pos.y+1,z=pos.z})
+
+ if (pipe_name and adjacent_node_level < 1)
+ or (node.name ~= "pipeworks:spigot" and not pipe_name) then
+ minetest.set_node(pos,{name = "pipeworks:spigot", param2 = fdir})
+ if below_node.name == "default:water_source" then
+ minetest.set_node(pos_below, {name = "air"})
end
end
+
+ if adjacent_node_level > 1
+ and (below_node.name == "air" or below_node.name == "default:water_source") then
+ minetest.get_meta(pos_adjacent):set_float("liquid_level", adjacent_node_level - 1)
+ end
end
end
-end
+})
+
+--[[
+other nodes that need processed separately:
+table.insert(pipeworks.pipe_nodenames,"pipeworks:valve_on_empty")
+table.insert(pipeworks.pipe_nodenames,"pipeworks:valve_off_empty")
+table.insert(pipeworks.pipe_nodenames,"pipeworks:entry_panel_empty")
+table.insert(pipeworks.pipe_nodenames,"pipeworks:flow_sensor_empty")
+table.insert(pipeworks.pipe_nodenames,"pipeworks:valve_on_loaded")
+table.insert(pipeworks.pipe_nodenames,"pipeworks:entry_panel_loaded")
+table.insert(pipeworks.pipe_nodenames,"pipeworks:flow_sensor_loaded")
+]]--
diff --git a/init.lua b/init.lua
index 92ce02c..7c7befa 100644
--- a/init.lua
+++ b/init.lua
@@ -39,6 +39,8 @@ pipeworks.mesecons_rules={{x=0,y=0,z=1},{x=0,y=0,z=-1},{x=1,y=0,z=0},{x=-1,y=0,z
pipeworks.liquid_texture = "default_water.png"
+pipeworks.pipe_nodenames = {}
+
-- Helper functions
function pipeworks.fix_image_names(table, replacement)
diff --git a/pipes.lua b/pipes.lua
index 2056fdf..79d6d58 100644
--- a/pipes.lua
+++ b/pipes.lua
@@ -2,9 +2,6 @@
local REGISTER_COMPATIBILITY = true
-local pipes_empty_nodenames = {}
-local pipes_full_nodenames = {}
-
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
@@ -113,12 +110,10 @@ for index, connects in ipairs(cconnects) do
end
})
- table.insert(pipes_empty_nodenames, "pipeworks:pipe_"..index.."_empty")
- table.insert(pipes_full_nodenames, "pipeworks:pipe_"..index.."_loaded")
+ table.insert(pipeworks.pipe_nodenames, "pipeworks:pipe_"..index.."_empty")
+ table.insert(pipeworks.pipe_nodenames, "pipeworks:pipe_"..index.."_loaded")
end
-
-
if REGISTER_COMPATIBILITY then
local cempty = "pipeworks:pipe_compatibility_empty"
local cloaded = "pipeworks:pipe_compatibility_loaded"
@@ -175,48 +170,3 @@ 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")
-
-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")
-
-minetest.register_abm({
- nodenames = pipes_empty_nodenames,
- interval = 1,
- chance = 1,
- action = function(pos, node, active_object_count, active_object_count_wider)
- pipeworks.check_for_inflows(pos,node)
- end
-})
-
-minetest.register_abm({
- nodenames = pipes_full_nodenames,
- interval = 1,
- chance = 1,
- action = function(pos, node, active_object_count, active_object_count_wider)
- pipeworks.check_sources(pos,node)
- end
-})
-
-minetest.register_abm({
- nodenames = {"pipeworks:spigot","pipeworks:spigot_pouring"},
- interval = 1,
- chance = 1,
- action = function(pos, node, active_object_count, active_object_count_wider)
- pipeworks.spigot_check(pos,node)
- end
-})
-
-minetest.register_abm({
- nodenames = {"pipeworks:fountainhead","pipeworks:fountainhead_pouring"},
- interval = 1,
- chance = 1,
- action = function(pos, node, active_object_count, active_object_count_wider)
- pipeworks.fountainhead_check(pos,node)
- end
-})
-