From c4acb7225a059b9eb40c1149ba043a55016eab16 Mon Sep 17 00:00:00 2001 From: Carter Kolwey Date: Sat, 11 Mar 2017 00:57:52 -0600 Subject: [PATCH] Don't require a full network recalculation to add or remove a dead end A dead end (node with only one connection) can be simply added or removed from the network without needing to traverse the whole thing. --- technic/machines/register/cables.lua | 96 ++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 5 deletions(-) diff --git a/technic/machines/register/cables.lua b/technic/machines/register/cables.lua index 04c6096..165db98 100644 --- a/technic/machines/register/cables.lua +++ b/technic/machines/register/cables.lua @@ -11,7 +11,15 @@ function technic.get_cable_tier(name) return cable_tier[name] end -local function clear_networks(pos) +local function check_connections(pos) + -- Build a table of all machines + local machines = {} + for tier,list in pairs(technic.machines) do + for k,v in pairs(list) do + machines[k] = v + end + end + local connections = {} local positions = { {x=pos.x+1, y=pos.y, z=pos.z}, {x=pos.x-1, y=pos.y, z=pos.z}, @@ -19,14 +27,92 @@ local function clear_networks(pos) {x=pos.x, y=pos.y-1, z=pos.z}, {x=pos.x, y=pos.y, z=pos.z+1}, {x=pos.x, y=pos.y, z=pos.z-1}} + for _,connected_pos in pairs(positions) do + local name = minetest.get_node(connected_pos).name + if machines[name] or technic.get_cable_tier(name) then + table.insert(connections,connected_pos) + end + end + return connections +end + +local function clear_networks(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 - for _,v in pairs(technic.networks[net].all_nodes) do - local pos1 = minetest.hash_node_position(v) - technic.cables[pos1] = nil + 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 + -- This is similar to check_node_subp + technic.cables[minetest.hash_node_position(pos)] = network_id + pos.visited = 1 + if technic.is_tier_cable(name, tier) then + table.insert(network.all_nodes,pos) + elseif technic.machines[tier][node.name] then + meta:set_string(tier.."_network",minetest.pos_to_string(sw_pos)) + if technic.machines[tier][node.name] == technic.producer then + table.insert(network.PR_nodes,pos) + elseif technic.machines[tier][node.name] == technic.receiver then + table.insert(network.RE_nodes,pos) + elseif technic.machines[tier][node.name] == technic.producer_receiver then + table.insert(network.PR_nodes,pos) + table.insert(network.RE_nodes,pos) + elseif technic.machines[tier][node.name] == "SPECIAL" and + (pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and + from_below then + table.insert(network.SP_nodes,pos) + elseif technic.machines[tier][node.name] == technic.battery then + table.insert(network.BA_nodes,pos) + end + 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] + + -- 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 + 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 - technic.networks[net] = nil end end end