Network handles timeouts, remove second switch ABM

This commit is contained in:
SX 2020-10-12 17:00:23 +03:00
parent 11fe7a7bf7
commit c6aa02897b
3 changed files with 34 additions and 67 deletions

View File

@ -4,7 +4,9 @@
local S = technic.getter local S = technic.getter
local switch_max_range = tonumber(minetest.settings:get("technic.switch_max_range") or "256") local switch_max_range = tonumber(minetest.settings:get("technic.switch_max_range") or "256")
local off_delay_seconds = tonumber(minetest.settings:get("technic.switch.off_delay_seconds") or "1800")
technic.active_networks = {}
technic.networks = {} technic.networks = {}
technic.cables = {} technic.cables = {}
@ -18,10 +20,12 @@ function technic.create_network(sw_pos)
end end
function technic.activate_network(network_id, timeout) function technic.activate_network(network_id, timeout)
assert(network_id) -- timeout is optional ttl for network in seconds, if not specified use default
local network = technic.networks[network_id] local network = technic.networks[network_id]
if network and (timeout or network.timeout < 4) then if network then
network.timeout = timeout or 4 -- timeout is absolute time in microseconds
network.timeout = minetest.get_us_time() + ((timeout or off_delay_seconds) * 1000 * 1000)
technic.active_networks[network_id] = network
end end
end end
@ -44,6 +48,7 @@ function technic.remove_network(network_id)
end end
end end
technic.networks[network_id] = nil technic.networks[network_id] = nil
technic.active_networks[network_id] = nil
--print(string.format("technic.remove_network(%.17g) at %s", network_id, minetest.pos_to_string(technic.network2pos(network_id)))) --print(string.format("technic.remove_network(%.17g) at %s", network_id, minetest.pos_to_string(technic.network2pos(network_id))))
end end
@ -285,9 +290,14 @@ function technic.build_network(network_id)
return return
end end
local network = { local network = {
-- Basic network data and lookup table for attached nodes (no switching stations)
id = network_id, tier = tier, all_nodes = {}, id = network_id, tier = tier, all_nodes = {},
-- Indexed arrays for iteration by machine type
SP_nodes = {}, PR_nodes = {}, RE_nodes = {}, BA_nodes = {}, SP_nodes = {}, PR_nodes = {}, RE_nodes = {}, BA_nodes = {},
supply = 0, demand = 0, timeout = 4, battery_charge = 0, battery_charge_max = 0, -- Power generation, usage and capacity related variables
supply = 0, demand = 0, battery_charge = 0, battery_charge_max = 0,
-- Network activation and excution control
timeout = 0, skip = 0,
} }
-- Add first cable (one that is holding network id) and build network -- Add first cable (one that is holding network id) and build network
local queue = {} local queue = {}

View File

@ -173,7 +173,7 @@ minetest.register_abm({
end end
technic.network_infotext(network_id, infotext) technic.network_infotext(network_id, infotext)
else else
-- Network exists and is not overloaded, reactivate for 4 seconds -- Network exists and is not overloaded, reactivate network
technic.activate_network(network_id) technic.activate_network(network_id)
infotext = technic.network_infotext(network_id) infotext = technic.network_infotext(network_id)
end end

View File

@ -1,22 +1,6 @@
local has_monitoring_mod = minetest.get_modpath("monitoring") local has_monitoring_mod = minetest.get_modpath("monitoring")
local switches = {} -- pos_hash -> { time = time_us }
local function get_switch_data(network_id)
local switch = switches[network_id]
if not switch then
switch = {
time = 0,
skip = 0
}
switches[network_id] = switch
end
return switch
end
local active_switching_stations_metric, switching_stations_usage_metric local active_switching_stations_metric, switching_stations_usage_metric
if has_monitoring_mod then if has_monitoring_mod then
@ -31,30 +15,10 @@ if has_monitoring_mod then
) )
end end
-- collect all active switching stations
minetest.register_abm({
nodenames = {"technic:switching_station"},
label = "Switching Station",
interval = 1,
chance = 1,
action = function(pos)
local network_id = technic.sw_pos2network(pos)
if network_id then
if technic.is_overloaded(network_id) then
switches[network_id] = nil
else
local switch = get_switch_data(network_id)
switch.time = minetest.get_us_time()
end
end
end
})
-- the interval between technic_run calls -- the interval between technic_run calls
local technic_run_interval = 1.0 local technic_run_interval = 1.0
-- iterate over all collected switching stations and execute the technic_run function -- iterate over all collected switching stations and execute the technic_run function
local off_delay_seconds = tonumber(minetest.settings:get("technic.switch.off_delay_seconds") or "1800")
local timer = 0 local timer = 0
minetest.register_globalstep(function(dtime) minetest.register_globalstep(function(dtime)
timer = timer + dtime timer = timer + dtime
@ -80,27 +44,24 @@ minetest.register_globalstep(function(dtime)
local now = minetest.get_us_time() local now = minetest.get_us_time()
local off_delay_micros = off_delay_seconds*1000*1000
local active_switches = 0 local active_switches = 0
for network_id, switch in pairs(switches) do for network_id, network in pairs(technic.active_networks) do
local pos = technic.network2sw_pos(network_id) local pos = technic.network2sw_pos(network_id)
local network = technic.networks[network_id]
local diff = now - switch.time
minetest.get_voxel_manip(pos, pos) local node = technic.get_or_load_node(pos) or minetest.get_node(pos)
local node = minetest.get_node(pos)
if network == nil or node.name ~= "technic:switching_station" then if node.name ~= "technic:switching_station" then
-- station vanished -- station vanished
switches[network_id] = nil technic.active_networks[network_id] = nil
elseif diff < off_delay_micros then elseif network.timeout > now then
-- station active -- station active
active_switches = active_switches + 1 active_switches = active_switches + 1
if switch.skip < 1 then if network.skip > 0 then
network.skip = network.skip - 1
else
local start = minetest.get_us_time() local start = minetest.get_us_time()
technic.network_run(network_id) technic.network_run(network_id)
@ -111,34 +72,30 @@ minetest.register_globalstep(function(dtime)
-- overload detection -- overload detection
if switch_diff > 250000 then if switch_diff > 250000 then
switch.skip = 30 network.skip = 30
elseif switch_diff > 150000 then elseif switch_diff > 150000 then
switch.skip = 20 network.skip = 20
elseif switch_diff > 75000 then elseif switch_diff > 75000 then
switch.skip = 10 network.skip = 10
elseif switch_diff > 50000 then elseif switch_diff > 50000 then
switch.skip = 2 network.skip = 2
end end
if switch.skip > 0 then if network.skip > 0 then
-- calculate efficiency in percent and display it -- calculate efficiency in percent and display it
local efficiency = math.floor(1/switch.skip*100) local efficiency = math.floor(1/network.skip*100)
technic.network_infotext(network_id, "Polyfuse triggered, current efficiency: " .. technic.network_infotext(network_id, "Polyfuse triggered, current efficiency: " ..
efficiency .. "% generated lag : " .. math.floor(switch_diff/1000) .. " ms") efficiency .. "% generated lag : " .. math.floor(switch_diff/1000) .. " ms")
-- remove laggy switching station from active index -- remove laggy network from active index
-- it will be reactivated when a player is near it -- it will be reactivated when a player is near it
-- laggy switching stations won't work well in unloaded areas this way technic.active_networks[network_id] = nil
switches[network_id] = nil
end end
else
switch.skip = math.max(switch.skip - 1, 0)
end end
else else
-- station timed out -- station timed out
switches[network_id] = nil technic.active_networks[network_id] = nil
end end
end end
@ -152,9 +109,9 @@ minetest.register_globalstep(function(dtime)
end) end)
minetest.register_chatcommand("technic_flush_switch_cache", { minetest.register_chatcommand("technic_flush_switch_cache", {
description = "removes all loaded switching stations from the cache", description = "removes all loaded networks from the cache",
privs = { server = true }, privs = { server = true },
func = function() func = function()
switches = {} technic.active_networks = {}
end end
}) })