From 260ab8c0fde82584a5652f278326ed4bd0449556 Mon Sep 17 00:00:00 2001 From: SX Date: Sat, 5 Sep 2020 11:26:33 +0300 Subject: [PATCH 1/8] Reduce meta, fix network id #76 #77 --- technic/machines/register/cables.lua | 2 -- technic/machines/switching_station.lua | 39 +++++++++++++++----------- 2 files changed, 23 insertions(+), 18 deletions(-) diff --git a/technic/machines/register/cables.lua b/technic/machines/register/cables.lua index a8a746e..4b82631 100644 --- a/technic/machines/register/cables.lua +++ b/technic/machines/register/cables.lua @@ -38,7 +38,6 @@ 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 @@ -66,7 +65,6 @@ local function clear_networks(pos) 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 diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index 41300bb..6479fcc 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -135,36 +135,37 @@ local function add_cable_node(nodes, pos, network_id, queue) end -- Generic function to add found connected nodes to the right classification array -local check_node_subp = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, from_below, network_id, queue) +local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, from_below, network_id, queue) local distance_to_switch = vector.distance(pos, sw_pos) if distance_to_switch > switch_max_range then -- max range exceeded - return + return true end technic.get_or_load_node(pos) local name = minetest.get_node(pos).name if technic.is_tier_cable(name, tier) then - add_cable_node(all_nodes, pos,network_id, queue) + add_cable_node(all_nodes, pos, network_id, queue) elseif machines[name] then --dprint(name.." is a "..machines[name]) local meta = minetest.get_meta(pos) - local net_id_key = tier.."_network" + local pos_hash = minetest.hash_node_position(pos) local net_id_new = network_id - local net_id_old = meta:get_string(net_id_key) - if net_id_old == "" then - meta:set_string(net_id_key, net_id_new) + local net_id_old = technic.cables[pos_hash] + if net_id_old == nil then + technic.cables[pos_hash] = net_id_new elseif net_id_old ~= net_id_new then -- do not allow running pos from multiple networks, also disable switch overloaded_networks[net_id_old] = minetest.get_us_time() + (overload_reset_time * 1000 * 1000) overloaded_networks[net_id_new] = overloaded_networks[net_id_old] -- delete caches for conflicting network technic.networks[net_id_old] = nil - meta:set_string(net_id_key, net_id_new) + technic.cables[pos] = net_id_new meta:set_string("infotext",S("Network Overloaded")) + return false end if machines[name] == technic.producer then @@ -186,10 +187,11 @@ local check_node_subp = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nod meta:set_int(tier.."_EU_timeout", 2) -- Touch node end + return true end -- Traverse a network given a list of machines and a cable type name -local traverse_network = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, network_id, queue) +local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, pos, machines, tier, sw_pos, network_id, queue) local positions = { {x=pos.x+1, y=pos.y, z=pos.z}, {x=pos.x-1, y=pos.y, z=pos.z}, @@ -198,18 +200,21 @@ local traverse_network = function(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_no {x=pos.x, y=pos.y, z=pos.z+1}, {x=pos.x, y=pos.y, z=pos.z-1}} for i, cur_pos in pairs(positions) do - check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3, network_id, queue) + if not check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3, network_id, queue) then + return false + end end + return true end -local touch_nodes = function(list, tier) +local function touch_nodes(list, tier) for _, pos in ipairs(list) do local meta = minetest.get_meta(pos) meta:set_int(tier.."_EU_timeout", 2) -- Touch node end end -local get_network = function(network_id, sw_pos, pos1, tier) +local function get_network(network_id, sw_pos, pos1, tier) local cached = technic.networks[network_id] if cached and cached.tier == tier then touch_nodes(cached.PR_nodes, tier) @@ -233,8 +238,10 @@ local get_network = function(network_id, sw_pos, pos1, tier) while next(queue) do local to_visit = {} for _, pos in ipairs(queue) do - traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, - pos, technic.machines[tier], tier, sw_pos, network_id, to_visit) + if not traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, + pos, technic.machines[tier], tier, sw_pos, network_id, to_visit) then + return false + end end queue = to_visit end @@ -312,7 +319,7 @@ technic.switching_station_run = function(pos) end local name = minetest.get_node(pos1).name - local network_id = tostring(minetest.hash_node_position(pos1)) + local network_id = minetest.hash_node_position(pos1) -- Check if network is overloaded / conflicts with another network if overloaded_networks[network_id] then local remaining = reset_overloaded(network_id) @@ -327,7 +334,7 @@ technic.switching_station_run = function(pos) local tier = technic.get_cable_tier(name) if tier then PR_nodes, BA_nodes, RE_nodes = get_network(network_id, pos, pos1, tier) - if overloaded_networks[network_id] then return end + if overloaded_networks[network_id] or PR_nodes == false then return end else --dprint("Not connected to a network") meta:set_string("infotext", S("%s Has No Network"):format(machine_name)) From 081d5534834af974a9b81576aba705130df0bf9d Mon Sep 17 00:00:00 2001 From: SX Date: Sat, 5 Sep 2020 15:09:32 +0300 Subject: [PATCH 2/8] Reduce meta usage, clean cable cache on overload #76 #77 --- technic/machines/HV/nuclear_reactor.lua | 5 ++- technic/machines/power_monitor.lua | 2 +- technic/machines/register/generator.lua | 6 ++-- technic/machines/switching_station.lua | 45 ++++++++++++++++++++----- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/technic/machines/HV/nuclear_reactor.lua b/technic/machines/HV/nuclear_reactor.lua index c221c7e..ac42037 100644 --- a/technic/machines/HV/nuclear_reactor.lua +++ b/technic/machines/HV/nuclear_reactor.lua @@ -490,11 +490,10 @@ minetest.register_node("technic:hv_nuclear_reactor_core_active", { timer:start(1) end, on_timer = function(pos, node) - local meta = minetest.get_meta(pos) - -- Connected back? - if meta:get_int("HV_EU_timeout") > 0 then return false end + if technic.get_timeout("HV", pos) > 0 then return false end + local meta = minetest.get_meta(pos) local burn_time = meta:get_int("burn_time") or 0 if burn_time >= burn_ticks or burn_time == 0 then diff --git a/technic/machines/power_monitor.lua b/technic/machines/power_monitor.lua index f25e8f7..51eeeee 100644 --- a/technic/machines/power_monitor.lua +++ b/technic/machines/power_monitor.lua @@ -101,7 +101,7 @@ minetest.register_abm({ local sw_pos = get_swpos(pos) local timeout = 0 for tier in pairs(technic.machines) do - timeout = math.max(meta:get_int(tier.."_EU_timeout"),timeout) + timeout = math.max(technic.get_timeout(tier, pos),timeout) end if timeout > 0 and sw_pos then local sw_meta = minetest.get_meta(sw_pos) diff --git a/technic/machines/register/generator.lua b/technic/machines/register/generator.lua index 9120e29..91a942e 100644 --- a/technic/machines/register/generator.lua +++ b/technic/machines/register/generator.lua @@ -206,12 +206,12 @@ function technic.register_generator(data) timer:start(1) end, on_timer = function(pos, node) + -- Connected back? + if technic.get_timeout(tier, pos) > 0 then return false end + local meta = minetest.get_meta(pos) local node = minetest.get_node(pos) - -- Connected back? - if meta:get_int(tier.."_EU_timeout") > 0 then return false end - local burn_time = meta:get_int("burn_time") or 0 if burn_time <= 0 then diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index 6479fcc..6dacfec 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -10,6 +10,12 @@ local reset_overloaded = function(network_id) local remaining = math.max(0, overloaded_networks[network_id] - minetest.get_us_time()) if remaining == 0 then -- Clear cache, remove overload and restart network + local cables = technic.cables + for pos_hash,cable_net_id in pairs(cables) do + if cable_net_id == network_id then + cables[pos_hash] = nil + end + end overloaded_networks[network_id] = nil technic.networks[network_id] = nil end @@ -163,7 +169,8 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes overloaded_networks[net_id_new] = overloaded_networks[net_id_old] -- delete caches for conflicting network technic.networks[net_id_old] = nil - technic.cables[pos] = net_id_new + technic.networks[net_id_new] = nil + technic.cables[pos_hash] = net_id_new meta:set_string("infotext",S("Network Overloaded")) return false end @@ -185,7 +192,7 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes add_network_node(BA_nodes, pos, network_id) end - meta:set_int(tier.."_EU_timeout", 2) -- Touch node + technic.touch_node(tier, pos, 2) -- Touch node end return true end @@ -207,10 +214,32 @@ local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_node return true end +technic.node_timeout = {} + +technic.pos2network = function(pos) + return technic.cables[minetest.hash_node_position(pos)] +end + +technic.get_timeout = function(tier, pos) + if technic.node_timeout[tier] == nil then + -- it is normal that some multi tier nodes always drop here when checking all LV, MV and HV tiers + return 0 + end + return technic.node_timeout[tier][minetest.hash_node_position(pos)] or 0 +end + +technic.touch_node = function(tier, pos, timeout) + if technic.node_timeout[tier] == nil then + -- this should get built up during registration + technic.node_timeout[tier] = {} + end + technic.node_timeout[tier][minetest.hash_node_position(pos)] = timeout or 2 +end + local function touch_nodes(list, tier) + local touch_node = technic.touch_node for _, pos in ipairs(list) do - local meta = minetest.get_meta(pos) - meta:set_int(tier.."_EU_timeout", 2) -- Touch node + touch_node(tier, pos, 2) -- Touch node end end @@ -224,7 +253,7 @@ local function get_network(network_id, sw_pos, pos1, tier) local meta = minetest.get_meta(pos) meta:set_int("active", 0) meta:set_string("active_pos", minetest.serialize(sw_pos)) - meta:set_int(tier.."_EU_timeout", 2) -- Touch node + technic.touch_node(tier, pos, 2) -- Touch node end return cached.PR_nodes, cached.BA_nodes, cached.RE_nodes end @@ -524,13 +553,13 @@ end -- Timeout for a node in case it was disconnected from the network -- A node must be touched by the station continuously in order to function local function switching_station_timeout_count(pos, tier) - local meta = minetest.get_meta(pos) - local timeout = meta:get_int(tier.."_EU_timeout") + local timeout = technic.get_timeout(tier, pos) if timeout <= 0 then + local meta = minetest.get_meta(pos) meta:set_int(tier.."_EU_input", 0) -- Not needed anymore <-- actually, it is for supply converter return true else - meta:set_int(tier.."_EU_timeout", timeout - 1) + technic.touch_node(tier, pos, timeout - 1) return false end end From 74b000aaad59d8353d688c45d9bf0a4173b9c1f8 Mon Sep 17 00:00:00 2001 From: SX Date: Sat, 5 Sep 2020 15:14:54 +0300 Subject: [PATCH 3/8] Make node_timeout local --- technic/machines/switching_station.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index 6dacfec..328e606 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -214,26 +214,26 @@ local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_node return true end -technic.node_timeout = {} +local node_timeout = {} technic.pos2network = function(pos) return technic.cables[minetest.hash_node_position(pos)] end technic.get_timeout = function(tier, pos) - if technic.node_timeout[tier] == nil then + if node_timeout[tier] == nil then -- it is normal that some multi tier nodes always drop here when checking all LV, MV and HV tiers return 0 end - return technic.node_timeout[tier][minetest.hash_node_position(pos)] or 0 + return node_timeout[tier][minetest.hash_node_position(pos)] or 0 end technic.touch_node = function(tier, pos, timeout) - if technic.node_timeout[tier] == nil then + if node_timeout[tier] == nil then -- this should get built up during registration - technic.node_timeout[tier] = {} + node_timeout[tier] = {} end - technic.node_timeout[tier][minetest.hash_node_position(pos)] = timeout or 2 + node_timeout[tier][minetest.hash_node_position(pos)] = timeout or 2 end local function touch_nodes(list, tier) From eb20854c30c52abc6e6b67d31cb91294260d81b3 Mon Sep 17 00:00:00 2001 From: SX Date: Sat, 19 Sep 2020 22:34:20 +0300 Subject: [PATCH 4/8] Remove Power monitor from network #76 not actual machine anymore --- technic/machines/power_monitor.lua | 45 +++++++++++++++++--------- technic/machines/register/cables.lua | 5 +-- technic/machines/switching_station.lua | 25 ++++++++++---- 3 files changed, 51 insertions(+), 24 deletions(-) diff --git a/technic/machines/power_monitor.lua b/technic/machines/power_monitor.lua index 51eeeee..e17a790 100644 --- a/technic/machines/power_monitor.lua +++ b/technic/machines/power_monitor.lua @@ -6,13 +6,38 @@ local S = technic.getter local cable_entry = "^technic_cable_connection_overlay.png" +-- Get registered cable or nil, returns nil if area is not loaded +local function get_cable(pos) + local node = minetest.get_node_or_nil(pos) + return (node and technic.get_cable_tier(node.name)) and node +end + +-- return the position of connected cable or nil +local function get_connected_cable_network(pos) + local param2 = minetest.get_node(pos).param2 + -- should probably also work sideways or upside down but for now it wont + if param2 > 3 then return end + -- Below? + local checkpos = {x=pos.x,y=pos.y-1,z=pos.z} + local network_id = get_cable(checkpos) and technic.pos2network(checkpos) + if network_id then + return network_id + end + -- Behind? + checkpos = vector.add(minetest.facedir_to_dir(param2),pos) + network_id = get_cable(checkpos) and technic.pos2network(checkpos) + if network_id then + return network_id + end +end + -- return the position of the associated switching station or nil local function get_swpos(pos) - local network_hash = technic.cables[minetest.hash_node_position(pos)] - local network = network_hash and minetest.get_position_from_hash(network_hash) - local swpos = network and {x=network.x,y=network.y+1,z=network.z} + local network_id = get_connected_cable_network(pos) + local network = network_id and technic.networks[network_id] + local swpos = network and technic.network2sw_pos(network_id) local is_powermonitor = swpos and minetest.get_node(swpos).name == "technic:switching_station" - return is_powermonitor and swpos or nil + return (is_powermonitor and network.all_nodes[network_id]) and swpos end minetest.register_craft({ @@ -99,11 +124,7 @@ minetest.register_abm({ action = function(pos, node, active_object_count, active_object_count_wider) local meta = minetest.get_meta(pos) local sw_pos = get_swpos(pos) - local timeout = 0 - for tier in pairs(technic.machines) do - timeout = math.max(technic.get_timeout(tier, pos),timeout) - end - if timeout > 0 and sw_pos then + if sw_pos then local sw_meta = minetest.get_meta(sw_pos) local supply = sw_meta:get_int("supply") local demand = sw_meta:get_int("demand") @@ -115,9 +136,3 @@ minetest.register_abm({ end end, }) - -for tier in pairs(technic.machines) do - -- RE in order to use the "timeout" functions, although it consumes 0 power - technic.register_machine(tier, "technic:power_monitor", "RE") -end - diff --git a/technic/machines/register/cables.lua b/technic/machines/register/cables.lua index 4b82631..7b57f47 100644 --- a/technic/machines/register/cables.lua +++ b/technic/machines/register/cables.lua @@ -60,10 +60,11 @@ local function clear_networks(pos) -- Actually add it to the (cached) network -- This is similar to check_node_subp - technic.cables[minetest.hash_node_position(pos)] = network_id + local pos_hash = minetest.hash_node_position(pos) + technic.cables[pos_hash] = network_id pos.visited = 1 if technic.is_tier_cable(name, tier) then - table.insert(network.all_nodes,pos) + network.all_nodes[pos_hash] = pos elseif technic.machines[tier][node.name] then if technic.machines[tier][node.name] == technic.producer then table.insert(network.PR_nodes,pos) diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index 328e606..18a80ed 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -6,7 +6,7 @@ technic.redundant_warn = {} local overload_reset_time = tonumber(minetest.settings:get("technic.overload_reset_time") or "20") local overloaded_networks = {} -local reset_overloaded = function(network_id) +local function reset_overloaded(network_id) local remaining = math.max(0, overloaded_networks[network_id] - minetest.get_us_time()) if remaining == 0 then -- Clear cache, remove overload and restart network @@ -216,11 +216,23 @@ end local node_timeout = {} -technic.pos2network = function(pos) - return technic.cables[minetest.hash_node_position(pos)] +function technic.pos2network(pos) + return pos and technic.cables[minetest.hash_node_position(pos)] end -technic.get_timeout = function(tier, pos) +function technic.network2pos(network_id) + return network_id and minetest.get_position_from_hash(network_id) +end + +function technic.network2sw_pos(network_id) + -- Return switching station position for network. + -- It is not guaranteed that position actually contains switching station. + local sw_pos = minetest.get_position_from_hash(network_id) + sw_pos.y = sw_pos.y + 1 + return sw_pos +end + +function technic.get_timeout(tier, pos) if node_timeout[tier] == nil then -- it is normal that some multi tier nodes always drop here when checking all LV, MV and HV tiers return 0 @@ -228,7 +240,7 @@ technic.get_timeout = function(tier, pos) return node_timeout[tier][minetest.hash_node_position(pos)] or 0 end -technic.touch_node = function(tier, pos, timeout) +function technic.touch_node(tier, pos, timeout) if node_timeout[tier] == nil then -- this should get built up during registration node_timeout[tier] = {} @@ -278,7 +290,6 @@ local function get_network(network_id, sw_pos, pos1, tier) BA_nodes = flatten(BA_nodes) RE_nodes = flatten(RE_nodes) SP_nodes = flatten(SP_nodes) - all_nodes = flatten(all_nodes) technic.networks[network_id] = {tier = tier, all_nodes = all_nodes, SP_nodes = SP_nodes, PR_nodes = PR_nodes, RE_nodes = RE_nodes, BA_nodes = BA_nodes} return PR_nodes, BA_nodes, RE_nodes @@ -317,7 +328,7 @@ local function run_nodes(list, run_stage) end end -technic.switching_station_run = function(pos) +function technic.switching_station_run(pos) if not technic.powerctrl_state then return end local t0 = minetest.get_us_time() From 219f772e1d19692d45d7458c31823454f4228f4d Mon Sep 17 00:00:00 2001 From: SX Date: Sun, 20 Sep 2020 02:01:52 +0300 Subject: [PATCH 5/8] #77 Revert early exit on overload, update overload --- technic/machines/switching_station.lua | 33 ++++++++++---------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index 18a80ed..df613e9 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -6,6 +6,9 @@ technic.redundant_warn = {} local overload_reset_time = tonumber(minetest.settings:get("technic.overload_reset_time") or "20") local overloaded_networks = {} +local function overload_network(network_id) + overloaded_networks[network_id] = minetest.get_us_time() + (overload_reset_time * 1000 * 1000) +end local function reset_overloaded(network_id) local remaining = math.max(0, overloaded_networks[network_id] - minetest.get_us_time()) if remaining == 0 then @@ -146,7 +149,7 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes local distance_to_switch = vector.distance(pos, sw_pos) if distance_to_switch > switch_max_range then -- max range exceeded - return true + return end technic.get_or_load_node(pos) @@ -165,14 +168,10 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes technic.cables[pos_hash] = net_id_new elseif net_id_old ~= net_id_new then -- do not allow running pos from multiple networks, also disable switch - overloaded_networks[net_id_old] = minetest.get_us_time() + (overload_reset_time * 1000 * 1000) - overloaded_networks[net_id_new] = overloaded_networks[net_id_old] - -- delete caches for conflicting network - technic.networks[net_id_old] = nil - technic.networks[net_id_new] = nil + overload_network(net_id_new, pos) + overload_network(net_id_old, pos) technic.cables[pos_hash] = net_id_new meta:set_string("infotext",S("Network Overloaded")) - return false end if machines[name] == technic.producer then @@ -194,7 +193,6 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes technic.touch_node(tier, pos, 2) -- Touch node end - return true end -- Traverse a network given a list of machines and a cable type name @@ -207,15 +205,10 @@ local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_node {x=pos.x, y=pos.y, z=pos.z+1}, {x=pos.x, y=pos.y, z=pos.z-1}} for i, cur_pos in pairs(positions) do - if not check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3, network_id, queue) then - return false - end + check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, cur_pos, machines, tier, sw_pos, i == 3, network_id, queue) end - return true end -local node_timeout = {} - function technic.pos2network(pos) return pos and technic.cables[minetest.hash_node_position(pos)] end @@ -232,6 +225,8 @@ function technic.network2sw_pos(network_id) return sw_pos end +local node_timeout = {} + function technic.get_timeout(tier, pos) if node_timeout[tier] == nil then -- it is normal that some multi tier nodes always drop here when checking all LV, MV and HV tiers @@ -279,10 +274,8 @@ local function get_network(network_id, sw_pos, pos1, tier) while next(queue) do local to_visit = {} for _, pos in ipairs(queue) do - if not traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, - pos, technic.machines[tier], tier, sw_pos, network_id, to_visit) then - return false - end + traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes, + pos, technic.machines[tier], tier, sw_pos, network_id, to_visit) end queue = to_visit end @@ -358,7 +351,6 @@ function technic.switching_station_run(pos) return end - local name = minetest.get_node(pos1).name local network_id = minetest.hash_node_position(pos1) -- Check if network is overloaded / conflicts with another network if overloaded_networks[network_id] then @@ -371,10 +363,11 @@ function technic.switching_station_run(pos) return end + local name = minetest.get_node(pos1).name local tier = technic.get_cable_tier(name) if tier then PR_nodes, BA_nodes, RE_nodes = get_network(network_id, pos, pos1, tier) - if overloaded_networks[network_id] or PR_nodes == false then return end + if overloaded_networks[network_id] then return end else --dprint("Not connected to a network") meta:set_string("infotext", S("%s Has No Network"):format(machine_name)) From 8741cc615410a69c44ffdead1b30d26a297401f8 Mon Sep 17 00:00:00 2001 From: SX Date: Sun, 20 Sep 2020 13:00:17 +0300 Subject: [PATCH 6/8] Overload skip PR+RE nodes --- technic/machines/switching_station.lua | 37 ++++++++++++++++---------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index df613e9..afe5fd6 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -126,6 +126,21 @@ local function flatten(map) return list end +local function attach_network_machine(network_id, pos) + local pos_hash = minetest.hash_node_position(pos) + local net_id_old = technic.cables[pos_hash] + if net_id_old == nil then + technic.cables[pos_hash] = network_id + elseif net_id_old ~= network_id then + -- do not allow running pos from multiple networks, also disable switch + overload_network(network_id, pos) + overload_network(net_id_old, pos) + technic.cables[pos_hash] = network_id + local meta = minetest.get_meta(pos) + meta:set_string("infotext",S("Network Overloaded")) + end +end + -- Add a wire node to the LV/MV/HV network local function add_network_node(nodes, pos, network_id) local node_id = minetest.hash_node_position(pos) @@ -160,34 +175,26 @@ local function check_node_subp(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_nodes elseif machines[name] then --dprint(name.." is a "..machines[name]) - local meta = minetest.get_meta(pos) - local pos_hash = minetest.hash_node_position(pos) - local net_id_new = network_id - local net_id_old = technic.cables[pos_hash] - if net_id_old == nil then - technic.cables[pos_hash] = net_id_new - elseif net_id_old ~= net_id_new then - -- do not allow running pos from multiple networks, also disable switch - overload_network(net_id_new, pos) - overload_network(net_id_old, pos) - technic.cables[pos_hash] = net_id_new - meta:set_string("infotext",S("Network Overloaded")) - end - if machines[name] == technic.producer then + attach_network_machine(network_id, pos) add_network_node(PR_nodes, pos, network_id) elseif machines[name] == technic.receiver then + attach_network_machine(network_id, pos) add_network_node(RE_nodes, pos, network_id) elseif machines[name] == technic.producer_receiver then + --attach_network_machine(network_id, pos) add_network_node(PR_nodes, pos, network_id) add_network_node(RE_nodes, pos, network_id) elseif machines[name] == "SPECIAL" and (pos.x ~= sw_pos.x or pos.y ~= sw_pos.y or pos.z ~= sw_pos.z) and from_below then -- Another switching station -> disable it + attach_network_machine(network_id, pos) add_network_node(SP_nodes, pos, network_id) + local meta = minetest.get_meta(pos) meta:set_int("active", 0) elseif machines[name] == technic.battery then + attach_network_machine(network_id, pos) add_network_node(BA_nodes, pos, network_id) end @@ -357,6 +364,8 @@ function technic.switching_station_run(pos) local remaining = reset_overloaded(network_id) if remaining > 0 then meta:set_string("infotext",S("%s Network Overloaded, Restart in %dms"):format(machine_name, remaining / 1000)) + -- Set switching station supply value to zero to clean up power monitor supply info + meta:set_int("supply",0) return end meta:set_string("infotext",S("%s Restarting Network"):format(machine_name)) From b131e3f3439ad0f3c3cb2ca3ebd05cd4ca127ca6 Mon Sep 17 00:00:00 2001 From: SX Date: Sun, 20 Sep 2020 16:01:47 +0300 Subject: [PATCH 7/8] Do not activate new switch if another is active already --- technic/machines/switching_station.lua | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index afe5fd6..d54274b 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -66,7 +66,17 @@ minetest.register_node("technic:switching_station",{ on_construct = function(pos) local meta = minetest.get_meta(pos) meta:set_string("infotext", S("Switching Station")) - meta:set_string("active", 1) + local network_id = technic.sw_pos2network(pos) + local net_sw_pos = network_id and technic.network2sw_pos(network_id) + local net_sw_node = net_sw_pos and minetest.get_node(net_sw_pos) + if net_sw_node and net_sw_node.name == "technic:switching_station" then + -- There's already network with same id, check if it already has active switching station + -- set active to 0 for this switch if there's already another active + local net_sw_meta = minetest.get_meta(net_sw_pos) + meta:set_string("active", net_sw_meta:get_int("active") == 1 and 0 or 1) + else + meta:set_string("active", 1) + end meta:set_string("channel", "switching_station"..minetest.pos_to_string(pos)) meta:set_string("formspec", "field[channel;Channel;${channel}]") local poshash = minetest.hash_node_position(pos) @@ -216,6 +226,10 @@ local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_node end end +function technic.sw_pos2network(pos) + return pos and technic.cables[minetest.hash_node_position({x=pos.x,y=pos.y-1,z=pos.z})] +end + function technic.pos2network(pos) return pos and technic.cables[minetest.hash_node_position(pos)] end From adc0b332be47b2da97a2cfd0b0a536a3a425f7d0 Mon Sep 17 00:00:00 2001 From: SX Date: Sun, 20 Sep 2020 18:21:34 +0300 Subject: [PATCH 8/8] Cleanup caches immediately when new switching station placed --- technic/machines/switching_station.lua | 35 +++++++++++++++++--------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/technic/machines/switching_station.lua b/technic/machines/switching_station.lua index d54274b..b97a5d7 100644 --- a/technic/machines/switching_station.lua +++ b/technic/machines/switching_station.lua @@ -13,14 +13,8 @@ local function reset_overloaded(network_id) local remaining = math.max(0, overloaded_networks[network_id] - minetest.get_us_time()) if remaining == 0 then -- Clear cache, remove overload and restart network - local cables = technic.cables - for pos_hash,cable_net_id in pairs(cables) do - if cable_net_id == network_id then - cables[pos_hash] = nil - end - end + technic.remove_network(network_id) overloaded_networks[network_id] = nil - technic.networks[network_id] = nil end -- Returns 0 when network reset or remaining time if reset timer has not expired yet return remaining @@ -68,13 +62,20 @@ minetest.register_node("technic:switching_station",{ meta:set_string("infotext", S("Switching Station")) local network_id = technic.sw_pos2network(pos) local net_sw_pos = network_id and technic.network2sw_pos(network_id) - local net_sw_node = net_sw_pos and minetest.get_node(net_sw_pos) - if net_sw_node and net_sw_node.name == "technic:switching_station" then + local net_sw_node = net_sw_pos and minetest.get_node_or_nil(net_sw_pos) + if net_sw_node then -- There's already network with same id, check if it already has active switching station - -- set active to 0 for this switch if there's already another active - local net_sw_meta = minetest.get_meta(net_sw_pos) - meta:set_string("active", net_sw_meta:get_int("active") == 1 and 0 or 1) + if net_sw_node.name == "technic:switching_station" then + -- Another switch found set active to 0 for this switch if another is already active + local net_sw_meta = minetest.get_meta(net_sw_pos) + meta:set_string("active", net_sw_meta:get_int("active") == 1 and 0 or 1) + else + -- Network switching station disappeared, cleanup caches and start new network + technic.remove_network(network_id) + meta:set_string("active", 1) + end else + -- Clean start, not previous networks, no other switching stations meta:set_string("active", 1) end meta:set_string("channel", "switching_station"..minetest.pos_to_string(pos)) @@ -226,6 +227,16 @@ local function traverse_network(PR_nodes, RE_nodes, BA_nodes, SP_nodes, all_node end end +function technic.remove_network(network_id) + local cables = technic.cables + for pos_hash,cable_net_id in pairs(cables) do + if cable_net_id == network_id then + cables[pos_hash] = nil + end + end + technic.networks[network_id] = nil +end + function technic.sw_pos2network(pos) return pos and technic.cables[minetest.hash_node_position({x=pos.x,y=pos.y-1,z=pos.z})] end