Skip to content

Commit b268e3d

Browse files
authored
Fix machines connected to multiple networks (#655)
Machines sometimes were be a part of multiple networks and generated power for each. This is fixed by checking if the machine is already part of an other network before assigning it to the current network.
1 parent 87e512f commit b268e3d

File tree

2 files changed

+111
-77
lines changed

2 files changed

+111
-77
lines changed

technic/machines/register/cables.lua

Lines changed: 88 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -43,84 +43,106 @@ local function check_connections(pos)
4343
return connections
4444
end
4545

46-
local function clear_networks(pos)
46+
local clear_networks
47+
48+
local function clear_network(network_id)
49+
if not network_id then
50+
return
51+
end
52+
53+
for _,v in pairs(technic.networks[network_id].all_nodes) do
54+
local pos1 = minetest.hash_node_position(v)
55+
technic.cables[pos1] = nil
56+
end
57+
local network_bckup = technic.networks[network_id]
58+
technic.networks[network_id] = nil
59+
60+
for _,n_pos in pairs(network_bckup.PR_nodes) do
61+
clear_networks(n_pos)
62+
end
63+
for _,n_pos in pairs(network_bckup.RE_nodes) do
64+
clear_networks(n_pos)
65+
end
66+
for _,n_pos in pairs(network_bckup.BA_nodes) do
67+
clear_networks(n_pos)
68+
end
69+
end
70+
71+
clear_networks = function(pos)
4772
local node = minetest.get_node(pos)
4873
local meta = minetest.get_meta(pos)
4974
local placed = node.name ~= "air"
5075
local positions = check_connections(pos)
76+
5177
if #positions < 1 then return end
52-
local dead_end = #positions == 1
53-
for _,connected_pos in pairs(positions) do
54-
local net = technic.cables[minetest.hash_node_position(connected_pos)]
55-
if net and technic.networks[net] then
56-
if dead_end and placed then
57-
-- Dead end placed, add it to the network
58-
-- Get the network
59-
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
60-
if not network_id then
61-
-- We're evidently not on a network, nothing to add ourselves to
62-
return
63-
end
64-
local sw_pos = minetest.get_position_from_hash(network_id)
65-
sw_pos.y = sw_pos.y + 1
66-
local network = technic.networks[network_id]
67-
local tier = network.tier
6878

69-
-- Actually add it to the (cached) network
70-
-- !! IMPORTANT: ../switching_station.lua -> check_node_subp() must be kept in sync
79+
if #positions == 1 then
80+
if placed then
81+
-- Dead end placed, add it to the network
82+
-- Get the network
83+
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
84+
if not network_id then
85+
-- We're evidently not on a network, nothing to add ourselves to
86+
return
87+
end
88+
local network = technic.networks[network_id]
89+
local tier = network.tier
90+
91+
-- Actually add it to the (cached) network
92+
-- !! IMPORTANT: ../switching_station.lua -> check_node_subp() must be kept in sync
93+
if technic.is_tier_cable(node.name, tier) then
7194
technic.cables[minetest.hash_node_position(pos)] = network_id
72-
pos.visited = 1
73-
if technic.is_tier_cable(node.name, tier) then
74-
-- Found a cable
75-
table.insert(network.all_nodes,pos)
76-
elseif technic.machines[tier][node.name] then
77-
-- Found a machine
78-
local eu_type = technic.machines[tier][node.name]
79-
meta:set_string(tier.."_network", string.format("%.20g", network_id))
80-
if eu_type == technic.producer then
81-
table.insert(network.PR_nodes, pos)
82-
elseif eu_type == technic.receiver then
83-
table.insert(network.RE_nodes, pos)
84-
elseif eu_type == technic.producer_receiver then
85-
table.insert(network.PR_nodes, pos)
86-
table.insert(network.RE_nodes, pos)
87-
elseif eu_type == technic.battery then
88-
table.insert(network.BA_nodes, pos)
89-
end
90-
-- Note: SPECIAL (i.e. switching station) is not traversed!
95+
table.insert(network.all_nodes,pos)
96+
elseif technic.machines[tier][node.name] then
97+
-- Found a machine
98+
local eu_type = technic.machines[tier][node.name]
99+
meta:set_string(tier.."_network", string.format("%.20g", network_id))
100+
meta:set_int(tier.."_EU_timeout", 2)
101+
if eu_type == technic.producer then
102+
table.insert(network.PR_nodes, pos)
103+
elseif eu_type == technic.receiver then
104+
table.insert(network.RE_nodes, pos)
105+
elseif eu_type == technic.producer_receiver then
106+
table.insert(network.PR_nodes, pos)
107+
table.insert(network.RE_nodes, pos)
108+
elseif eu_type == technic.battery then
109+
table.insert(network.BA_nodes, pos)
91110
end
92-
elseif dead_end and not placed then
93-
-- Dead end removed, remove it from the network
94-
-- Get the network
95-
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
96-
if not network_id then
97-
-- We're evidently not on a network, nothing to add ourselves to
98-
return
99-
end
100-
local network = technic.networks[network_id]
111+
-- Note: SPECIAL (i.e. switching station) is not traversed!
112+
end
113+
else
114+
-- Dead end removed, remove it from the network
115+
-- Get the network
116+
local network_id = technic.cables[minetest.hash_node_position(positions[1])]
117+
if not network_id then
118+
-- We're evidently not on a network, nothing to add ourselves to
119+
return
120+
end
121+
local network = technic.networks[network_id]
101122

102-
-- Search for and remove machine
103-
technic.cables[minetest.hash_node_position(pos)] = nil
104-
for tblname,table in pairs(network) do
105-
if tblname ~= "tier" then
106-
for machinenum,machine in pairs(table) do
107-
if machine.x == pos.x
108-
and machine.y == pos.y
109-
and machine.z == pos.z then
110-
table[machinenum] = nil
111-
end
123+
-- Search for and remove machine
124+
technic.cables[minetest.hash_node_position(pos)] = nil
125+
for tblname,table in pairs(network) do
126+
if tblname ~= "tier" then
127+
for machinenum,machine in pairs(table) do
128+
if machine.x == pos.x
129+
and machine.y == pos.y
130+
and machine.z == pos.z then
131+
table[machinenum] = nil
112132
end
113133
end
114134
end
115-
else
116-
-- Not a dead end, so the whole network needs to be recalculated
117-
for _,v in pairs(technic.networks[net].all_nodes) do
118-
local pos1 = minetest.hash_node_position(v)
119-
technic.cables[pos1] = nil
120-
end
121-
technic.networks[net] = nil
122135
end
123136
end
137+
return
138+
end
139+
140+
clear_network(technic.cables[minetest.hash_node_position(pos)])
141+
142+
for _,connected_pos in pairs(positions) do
143+
local network_id = technic.cables[minetest.hash_node_position(connected_pos)]
144+
-- Not a dead end, so the whole network needs to be recalculated
145+
clear_network(network_id)
124146
end
125147
end
126148

@@ -170,7 +192,7 @@ function technic.register_cable(tier, size)
170192
connects_to = {"group:technic_"..ltier.."_cable",
171193
"group:technic_"..ltier, "group:technic_all_tiers"},
172194
on_construct = clear_networks,
173-
on_destruct = clear_networks,
195+
after_destruct = clear_networks,
174196
})
175197

176198
local xyz = {
@@ -210,7 +232,7 @@ function technic.register_cable(tier, size)
210232
connects_to = {"group:technic_"..ltier.."_cable",
211233
"group:technic_"..ltier, "group:technic_all_tiers"},
212234
on_construct = clear_networks,
213-
on_destruct = clear_networks,
235+
after_destruct = clear_networks,
214236
}
215237
def.node_box.fixed = {
216238
{-size, -size, -size, size, size, size},

technic/machines/switching_station.lua

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,14 @@ local function flatten(map)
9797
return list
9898
end
9999

100-
-- Add a wire node to the LV/MV/HV network
101-
-- Returns: indicator whether the cable is new in the network
100+
-- Add a node to the LV/MV/HV network
101+
-- Returns: indicator whether the node is new in the network
102102
local hash_node_position = minetest.hash_node_position
103103
local function add_network_node(nodes, pos, network_id)
104104
local node_id = hash_node_position(pos)
105-
technic.cables[node_id] = network_id
105+
if network_id then
106+
technic.cables[node_id] = network_id
107+
end
106108
if nodes[node_id] then
107109
return false
108110
end
@@ -136,21 +138,31 @@ local check_node_subp = function(network, pos, machines, sw_pos, from_below, net
136138
local meta = minetest.get_meta(pos)
137139
-- Normal tostring() does not have enough precision, neither does meta:set_int()
138140
-- Lua 5.1 bug: Cannot use hexadecimal notation for compression (see LuaJIT #911)
139-
meta:set_string(network.tier.."_network", string.format("%.20g", network_id))
141+
local network_str = string.format("%.20g", network_id)
142+
local network_key = network.tier.."_network"
143+
local m_network_str = meta:get_string(network_key)
144+
145+
if m_network_str == "" then
146+
meta:set_string(network_key, network_str)
147+
else
148+
if m_network_str ~= network_str then
149+
return
150+
end
151+
end
140152

141153
if eu_type == technic.producer then
142-
add_network_node(network.PR_nodes, pos, network_id)
154+
add_network_node(network.PR_nodes, pos)
143155
elseif eu_type == technic.receiver then
144-
add_network_node(network.RE_nodes, pos, network_id)
156+
add_network_node(network.RE_nodes, pos)
145157
elseif eu_type == technic.producer_receiver then
146-
add_network_node(network.PR_nodes, pos, network_id)
147-
add_network_node(network.RE_nodes, pos, network_id)
158+
add_network_node(network.PR_nodes, pos)
159+
add_network_node(network.RE_nodes, pos)
148160
elseif eu_type == technic.battery then
149-
add_network_node(network.BA_nodes, pos, network_id)
161+
add_network_node(network.BA_nodes, pos)
150162
elseif eu_type == "SPECIAL" and from_below and
151163
not vector.equals(pos, sw_pos) then
152164
-- Another switching station -> disable it
153-
add_network_node(network.SP_nodes, pos, network_id)
165+
add_network_node(network.SP_nodes, pos)
154166
meta:set_int("active", 0)
155167
end
156168

@@ -193,7 +205,6 @@ local get_network = function(sw_pos, cable_pos, tier)
193205
end
194206
return cached.PR_nodes, cached.BA_nodes, cached.RE_nodes
195207
end
196-
197208
local machines = technic.machines[tier]
198209
local network = {
199210
tier = tier,
@@ -455,6 +466,7 @@ local function switching_station_timeout_count(pos, tier)
455466
local meta = minetest.get_meta(pos)
456467
local timeout = meta:get_int(tier.."_EU_timeout")
457468
if timeout <= 0 then
469+
meta:set_string(tier.."_network", "")
458470
meta:set_int(tier.."_EU_input", 0) -- Not needed anymore <-- actually, it is for supply converter
459471
return true
460472
else

0 commit comments

Comments
 (0)