diff --git a/technic/machines/register/cables.lua b/technic/machines/register/cables.lua index 70da6d6..a87a3a8 100644 --- a/technic/machines/register/cables.lua +++ b/technic/machines/register/cables.lua @@ -43,84 +43,106 @@ local function check_connections(pos) return connections end -local function clear_networks(pos) +local clear_networks + +local function clear_network(network_id) + if not network_id then + return + end + + for _,v in pairs(technic.networks[network_id].all_nodes) do + local pos1 = minetest.hash_node_position(v) + technic.cables[pos1] = nil + end + local network_bckup = technic.networks[network_id] + technic.networks[network_id] = nil + + for _,n_pos in pairs(network_bckup.PR_nodes) do + clear_networks(n_pos) + end + for _,n_pos in pairs(network_bckup.RE_nodes) do + clear_networks(n_pos) + end + for _,n_pos in pairs(network_bckup.BA_nodes) do + clear_networks(n_pos) + end +end + +clear_networks = function(pos) local node = minetest.get_node(pos) local meta = minetest.get_meta(pos) local placed = node.name ~= "air" local positions = check_connections(pos) + if #positions < 1 then return end - local dead_end = #positions == 1 - for _,connected_pos in pairs(positions) do - local net = technic.cables[minetest.hash_node_position(connected_pos)] - if net and technic.networks[net] then - if dead_end and placed then - -- Dead end placed, add it to the network - -- Get the network - local network_id = technic.cables[minetest.hash_node_position(positions[1])] - if not network_id then - -- We're evidently not on a network, nothing to add ourselves to - return - end - local sw_pos = minetest.get_position_from_hash(network_id) - sw_pos.y = sw_pos.y + 1 - local network = technic.networks[network_id] - local tier = network.tier - -- Actually add it to the (cached) network - -- !! IMPORTANT: ../switching_station.lua -> check_node_subp() must be kept in sync + if #positions == 1 then + if placed then + -- Dead end placed, add it to the network + -- Get the network + local network_id = technic.cables[minetest.hash_node_position(positions[1])] + if not network_id then + -- We're evidently not on a network, nothing to add ourselves to + return + end + local network = technic.networks[network_id] + local tier = network.tier + + -- Actually add it to the (cached) network + -- !! IMPORTANT: ../switching_station.lua -> check_node_subp() must be kept in sync + if technic.is_tier_cable(node.name, tier) then technic.cables[minetest.hash_node_position(pos)] = network_id - pos.visited = 1 - if technic.is_tier_cable(node.name, tier) then - -- Found a cable - table.insert(network.all_nodes,pos) - elseif technic.machines[tier][node.name] then - -- Found a machine - local eu_type = technic.machines[tier][node.name] - meta:set_string(tier.."_network", string.format("%.20g", network_id)) - if eu_type == technic.producer then - table.insert(network.PR_nodes, pos) - elseif eu_type == technic.receiver then - table.insert(network.RE_nodes, pos) - elseif eu_type == technic.producer_receiver then - table.insert(network.PR_nodes, pos) - table.insert(network.RE_nodes, pos) - elseif eu_type == technic.battery then - table.insert(network.BA_nodes, pos) - end - -- Note: SPECIAL (i.e. switching station) is not traversed! + table.insert(network.all_nodes,pos) + elseif technic.machines[tier][node.name] then + -- Found a machine + local eu_type = technic.machines[tier][node.name] + meta:set_string(tier.."_network", string.format("%.20g", network_id)) + meta:set_int(tier.."_EU_timeout", 2) + if eu_type == technic.producer then + table.insert(network.PR_nodes, pos) + elseif eu_type == technic.receiver then + table.insert(network.RE_nodes, pos) + elseif eu_type == technic.producer_receiver then + table.insert(network.PR_nodes, pos) + table.insert(network.RE_nodes, pos) + elseif eu_type == technic.battery then + table.insert(network.BA_nodes, pos) end - elseif dead_end and not placed then - -- Dead end removed, remove it from the network - -- Get the network - local network_id = technic.cables[minetest.hash_node_position(positions[1])] - if not network_id then - -- We're evidently not on a network, nothing to add ourselves to - return - end - local network = technic.networks[network_id] + -- Note: SPECIAL (i.e. switching station) is not traversed! + end + else + -- Dead end removed, remove it from the network + -- Get the network + local network_id = technic.cables[minetest.hash_node_position(positions[1])] + if not network_id then + -- We're evidently not on a network, nothing to add ourselves to + return + end + local network = technic.networks[network_id] - -- Search for and remove machine - technic.cables[minetest.hash_node_position(pos)] = nil - for tblname,table in pairs(network) do - if tblname ~= "tier" then - for machinenum,machine in pairs(table) do - if machine.x == pos.x - and machine.y == pos.y - and machine.z == pos.z then - table[machinenum] = nil - end + -- Search for and remove machine + technic.cables[minetest.hash_node_position(pos)] = nil + for tblname,table in pairs(network) do + if tblname ~= "tier" then + for machinenum,machine in pairs(table) do + if machine.x == pos.x + and machine.y == pos.y + and machine.z == pos.z then + table[machinenum] = nil end end end - else - -- Not a dead end, so the whole network needs to be recalculated - for _,v in pairs(technic.networks[net].all_nodes) do - local pos1 = minetest.hash_node_position(v) - technic.cables[pos1] = nil - end - technic.networks[net] = nil end end + return + end + + clear_network(technic.cables[minetest.hash_node_position(pos)]) + + for _,connected_pos in pairs(positions) do + local network_id = technic.cables[minetest.hash_node_position(connected_pos)] + -- Not a dead end, so the whole network needs to be recalculated + clear_network(network_id) end end @@ -170,7 +192,7 @@ function technic.register_cable(tier, size) connects_to = {"group:technic_"..ltier.."_cable", "group:technic_"..ltier, "group:technic_all_tiers"}, on_construct = clear_networks, - on_destruct = clear_networks, + after_destruct = clear_networks, }) local xyz = { @@ -210,7 +232,7 @@ function technic.register_cable(tier, size) connects_to = {"group:technic_"..ltier.."_cable", "group:technic_"..ltier, "group:technic_all_tiers"}, on_construct = clear_networks, - on_destruct = clear_networks, + after_destruct = clear_networks, } def.node_box.fixed = { {-size, -size, -size, size, size, size}, diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index d1cabf0..b671585 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -97,12 +97,14 @@ local function flatten(map) return list end --- Add a wire node to the LV/MV/HV network --- Returns: indicator whether the cable is new in the network +-- Add a node to the LV/MV/HV network +-- Returns: indicator whether the node is new in the network local hash_node_position = minetest.hash_node_position local function add_network_node(nodes, pos, network_id) local node_id = hash_node_position(pos) - technic.cables[node_id] = network_id + if network_id then + technic.cables[node_id] = network_id + end if nodes[node_id] then return false end @@ -136,21 +138,31 @@ local check_node_subp = function(network, pos, machines, sw_pos, from_below, net local meta = minetest.get_meta(pos) -- Normal tostring() does not have enough precision, neither does meta:set_int() -- Lua 5.1 bug: Cannot use hexadecimal notation for compression (see LuaJIT #911) - meta:set_string(network.tier.."_network", string.format("%.20g", network_id)) + local network_str = string.format("%.20g", network_id) + local network_key = network.tier.."_network" + local m_network_str = meta:get_string(network_key) + + if m_network_str == "" then + meta:set_string(network_key, network_str) + else + if m_network_str ~= network_str then + return + end + end if eu_type == technic.producer then - add_network_node(network.PR_nodes, pos, network_id) + add_network_node(network.PR_nodes, pos) elseif eu_type == technic.receiver then - add_network_node(network.RE_nodes, pos, network_id) + add_network_node(network.RE_nodes, pos) elseif eu_type == technic.producer_receiver then - add_network_node(network.PR_nodes, pos, network_id) - add_network_node(network.RE_nodes, pos, network_id) + add_network_node(network.PR_nodes, pos) + add_network_node(network.RE_nodes, pos) elseif eu_type == technic.battery then - add_network_node(network.BA_nodes, pos, network_id) + add_network_node(network.BA_nodes, pos) elseif eu_type == "SPECIAL" and from_below and not vector.equals(pos, sw_pos) then -- Another switching station -> disable it - add_network_node(network.SP_nodes, pos, network_id) + add_network_node(network.SP_nodes, pos) meta:set_int("active", 0) end @@ -193,7 +205,6 @@ local get_network = function(sw_pos, cable_pos, tier) end return cached.PR_nodes, cached.BA_nodes, cached.RE_nodes end - local machines = technic.machines[tier] local network = { tier = tier, @@ -455,6 +466,7 @@ local function switching_station_timeout_count(pos, tier) local meta = minetest.get_meta(pos) local timeout = meta:get_int(tier.."_EU_timeout") if timeout <= 0 then + meta:set_string(tier.."_network", "") meta:set_int(tier.."_EU_input", 0) -- Not needed anymore <-- actually, it is for supply converter return true else