1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
-- reimplementation of new_flow_logic branch: processing functions
-- written 2017 by thetaepsilon
local flowlogic = {}
flowlogic.helpers = {}
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 = {
{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},
}
if include_base then table.insert(coords, pos) end
return coords
end
-- local debuglog = function(msg) print("## "..msg) 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.
local check_for_liquids_v2 = function(pos, limit)
local coords = make_coords_offsets(pos, false)
local total = 0
for index, tpos in ipairs(coords) do
if total >= limit then break end
local name = minetest.get_node(tpos).name
if name == "default:water_source" then
minetest.remove_node(tpos)
total = total + 1
end
end
return total
end
flowlogic.check_for_liquids_v2 = check_for_liquids_v2
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.
-- 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 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 neighbour = minetest.get_meta(npos)
local haspressure = (neighbour:get_int(label_haspressure) ~= 0)
if haspressure then
local n = neighbour:get_float(label_pressure)
table.insert(connections, neighbour)
totalv = totalv + n
totalc = totalc + 1
end
end
local average = totalv / totalc
for _, targetmeta in ipairs(connections) do
targetmeta:set_float(label_pressure, average)
end
end
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
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)
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)
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
|