From be849acb437b8b056e0af4cbb4357f641dc60f3b Mon Sep 17 00:00:00 2001 From: mamoniot Date: Fri, 23 Dec 2022 08:52:55 -0500 Subject: [PATCH] added an "everything" network --- TODO | 1 - cybersyn/changelog.txt | 1 + cybersyn/scripts/central-planning.lua | 77 ++++++++++++----- cybersyn/scripts/constants.lua | 1 + cybersyn/scripts/factorio-api.lua | 52 ++++++++++-- cybersyn/scripts/global.lua | 8 +- cybersyn/scripts/gui.lua | 11 ++- cybersyn/scripts/log.lua | 9 ++ cybersyn/scripts/main.lua | 117 +++++++++++--------------- cybersyn/scripts/train-events.lua | 7 +- 10 files changed, 181 insertions(+), 103 deletions(-) create mode 100644 cybersyn/scripts/log.lua diff --git a/TODO b/TODO index 5e2b603..186f80e 100644 --- a/TODO +++ b/TODO @@ -9,7 +9,6 @@ major: move to an event based algorithm models & art add stack threshold setting - allow "any" signal for network unions minor: railloader compat diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index f43521b..06db779 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -9,6 +9,7 @@ Date: 2022-12-22 - Provide stations now override request thresholds with the per-item thresholds set by their station info combinator - Nonempty trains in depot are no longer put in manual mode, instead they are forced to park at the depot - Made several alerts persistent + - Allowed station and fuel combinators to be set to network id "everything", for each virtual signal they recieve as input, the stop is added to that network and its signal strength is used as the network mask --------------------------------------------------------------------------------------------------- Version: 1.1.7 Date: 2022-12-17 diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index d640a6e..09da855 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -9,6 +9,7 @@ local band = bit32.band local table_remove = table.remove local random = math.random + ---@param map_data MapData ---@param station Station ---@param manifest Manifest @@ -188,6 +189,7 @@ local function tick_dispatch(map_data, mod_settings) local p_stations local item_name local item_type + local item_network_name while true do local size = #all_names if size == 0 then @@ -198,7 +200,7 @@ local function tick_dispatch(map_data, mod_settings) --randomizing the ordering should only matter if we run out of available trains local name_i = size <= 2 and 2 or 2*random(size/2) - local item_network_name = all_names[name_i - 1]--[[@as string]] + item_network_name = all_names[name_i - 1]--[[@as string]] local signal = all_names[name_i]--[[@as SignalID]] --swap remove @@ -274,7 +276,13 @@ local function tick_dispatch(map_data, mod_settings) local r_station_id = r_stations[r_station_i] local r_station = stations[r_station_id] ---@type string - local network_name = r_station.network_name + local network_name + if r_station.network_name == NETWORK_ANY then + --TODO: here + _, _, network_name = string.find(item_network_name, "(^.*):") + else + network_name = r_station.network_name + end local trains = map_data.available_trains[network_name] local is_fluid = item_type == "fluid" --no train exists with layout accepted by both provide and request stations @@ -296,7 +304,9 @@ local function tick_dispatch(map_data, mod_settings) goto p_continue end - local netand = band(p_station.network_flag, r_station.network_flag) + local p_flag = p_station.network_name == NETWORK_ANY and (p_station.network_flag[item_name] or 0) or p_station.network_flag + local r_flag = r_station.network_name == NETWORK_ANY and (r_station.network_flag[item_name] or 0) or r_station.network_flag + local netand = band(p_flag, r_flag) if netand == 0 then goto p_continue end @@ -462,7 +472,11 @@ local function tick_poll_station(map_data, mod_settings) station.priority = 0 station.item_priority = nil station.locked_slots = 0 - station.network_flag = mod_settings.network_flag + if station.network_name == NETWORK_ANY then + station.network_flag = {} + else + station.network_flag = mod_settings.network_flag + end local comb1_signals, comb2_signals = get_signals(station) station.tick_signals = comb1_signals station.item_p_counts = {} @@ -500,6 +514,8 @@ local function tick_poll_station(map_data, mod_settings) station.r_threshold = abs(item_count) elseif item_name == LOCKED_SLOTS then station.locked_slots = max(item_count, 0) + elseif station.network_name == NETWORK_ANY then + station.network_flag[item_name] = item_count end comb1_signals[k] = nil end @@ -524,27 +540,43 @@ local function tick_poll_station(map_data, mod_settings) if -effective_item_count >= r_threshold and -item_count >= r_threshold then is_not_requesting = false is_requesting_nothing = false - local item_network_name = station.network_name..":"..item_name - local stations = all_r_stations[item_network_name] - if stations == nil then - stations = {} - all_r_stations[item_network_name] = stations - all_names[#all_names + 1] = item_network_name - all_names[#all_names + 1] = v.signal + local f, a + if station.network_name == NETWORK_ANY then + f, a = pairs(station.network_flag--[[@as {[string]: int}]]) + else + f, a = once, station.network_name + end + for network_name, _ in f, a do + local item_network_name = network_name..":"..item_name + local stations = all_r_stations[item_network_name] + if stations == nil then + stations = {} + all_r_stations[item_network_name] = stations + all_names[#all_names + 1] = item_network_name + all_names[#all_names + 1] = v.signal + end + stations[#stations + 1] = station_id end - stations[#stations + 1] = station_id end end if is_not_requesting then if station.is_p and effective_item_count > 0 and item_count > 0 then - local item_network_name = station.network_name..":"..item_name - local stations = all_p_stations[item_network_name] - if stations == nil then - stations = {} - all_p_stations[item_network_name] = stations + local f, a + if station.network_name == NETWORK_ANY then + f, a = pairs(station.network_flag--[[@as {[string]: int}]]) + else + f, a = once, station.network_name + end + for network_name, _ in f, a do + local item_network_name = network_name..":"..item_name + local stations = all_p_stations[item_network_name] + if stations == nil then + stations = {} + all_p_stations[item_network_name] = stations + end + stations[#stations + 1] = station_id + station.item_p_counts[item_name] = effective_item_count end - stations[#stations + 1] = station_id - station.item_p_counts[item_name] = effective_item_count else comb1_signals[k] = nil end @@ -589,7 +621,7 @@ function tick(map_data, mod_settings) map_data.total_ticks = map_data.total_ticks + 1 if map_data.active_alerts then - if map_data.total_ticks%(10*mod_settings.tps) < 1 then + if map_data.total_ticks%(9*mod_settings.tps) < 1 then process_active_alerts(map_data) end end @@ -613,9 +645,8 @@ function tick(map_data, mod_settings) interface_raise_tick_init() tick_poll_train(map_data, mod_settings) tick_poll_comb(map_data) - end - - if map_data.tick_state == STATE_POLL_STATIONS then + return + elseif map_data.tick_state == STATE_POLL_STATIONS then for i = 1, mod_settings.update_rate do if tick_poll_station(map_data, mod_settings) then break end end diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index 2d15ffd..ee51318 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -23,6 +23,7 @@ MODE_WAGON_MANIFEST = "-" MODE_REFUELER = ">>" NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"} +NETWORK_ANY = "signal-everything" INACTIVITY_TIME = 100 LOCK_TRAIN_TIME = 60*60*60*24*7 diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 8fb9a1c..b79c5ad 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -345,32 +345,74 @@ function set_station_from_comb_state(station) station.is_p = is_pr_state == 0 or is_pr_state == 1 station.is_r = is_pr_state == 0 or is_pr_state == 2 end +---@param map_data MapData ---@param mod_settings CybersynModSettings ----@param refueler Refueler -function set_refueler_from_comb(mod_settings, refueler) +---@param id uint +function set_refueler_from_comb(map_data, mod_settings, id) --NOTE: this does nothing to update currently active deliveries + local refueler = map_data.refuelers[id] local params = get_comb_params(refueler.entity_comb) local bits = params.second_constant or 0 local signal = params.first_signal + + local f, a + if refueler.network_name == NETWORK_ANY then + f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) + else + f, a = once, refueler.network_name + end + for network_name, _ in f, a do + local network = map_data.to_refuelers[network_name] + if network then + network[id] = nil + if next(network) == nil then + map_data.to_refuelers[network_name] = nil + end + end + end + refueler.network_name = signal and signal.name or nil refueler.allows_all_trains = bits%2 == 1 local signals = refueler.entity_comb.get_merged_signals(DEFINES_COMBINATOR_INPUT) refueler.priority = 0 - refueler.network_flag = mod_settings.network_flag + if refueler.network_name == NETWORK_ANY then + refueler.network_flag = {} + else + refueler.network_flag = mod_settings.network_flag + end if not signals then return end for k, v in pairs(signals) do local item_name = v.signal.name + local item_type = v.signal.type local item_count = v.count if item_name then - if item_name == SIGNAL_PRIORITY then - refueler.priority = item_count + if item_type == "virtual" then + if item_name == SIGNAL_PRIORITY then + refueler.priority = item_count + elseif refueler.network_name == NETWORK_ANY then + refueler.network_flag[item_name] = item_count + end end if item_name == refueler.network_name then refueler.network_flag = item_count end end end + + if refueler.network_name == NETWORK_ANY then + f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) + else + f, a = once, refueler.network_name + end + for network_name, _ in f, a do + local network = map_data.to_refuelers[network_name] + if not network then + network = {} + map_data.to_refuelers[network_name] = network + end + network[id] = true + end end ---@param map_data MapData diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 2acf3c7..843c2db 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -36,7 +36,7 @@ ---@field public r_threshold int >= 0 --transient ---@field public locked_slots int >= 0 --transient ---@field public network_name string? ----@field public network_flag int --transient +---@field public network_flag int|{[string]: int} --transient ---@field public wagon_combs {[int]: LuaEntity}?--NOTE: allowed to be invalid entities or combinators with the wrong operation, these must be checked and lazy deleted when found ---@field public deliveries {[string]: int} ---@field public accepted_layouts {[uint]: true?} @@ -151,3 +151,9 @@ function init_global() global.se_tele_old_id = {} end end + +---@param v string +---@param h string? +function once(v, h) + return not h and v or nil--[[@as string|nil]] +end diff --git a/cybersyn/scripts/gui.lua b/cybersyn/scripts/gui.lua index 58607b8..60fe7dc 100644 --- a/cybersyn/scripts/gui.lua +++ b/cybersyn/scripts/gui.lua @@ -192,10 +192,17 @@ function register_gui_actions() local comb = global.to_comb[msg[2]] if not comb or not comb.valid then return end + local param = get_comb_params(comb) + local signal = element.elem_value if signal and (signal.name == "signal-everything" or signal.name == "signal-anything" or signal.name == "signal-each") then - signal = nil - element.elem_value = nil + if param.operation == MODE_PRIMARY_IO or param.operation == MODE_PRIMARY_IO_ACTIVE or param.operation == MODE_PRIMARY_IO_FAILED_REQUEST or param.operation == MODE_REFUELER then + signal.name = NETWORK_ANY + element.elem_value.name = NETWORK_ANY + else + signal = nil + element.elem_value = nil + end end set_comb_network_name(comb, signal) diff --git a/cybersyn/scripts/log.lua b/cybersyn/scripts/log.lua new file mode 100644 index 0000000..36acc00 --- /dev/null +++ b/cybersyn/scripts/log.lua @@ -0,0 +1,9 @@ + + + + +function log_dispatch(network_name, r_stop, p_stop) +end + +function log_refuel(network_name, refuel_stop) +end diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index f996204..fcb211d 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -27,7 +27,7 @@ local function on_depot_broken(map_data, depot_id, depot) if train_id then local train = map_data.trains[train_id] lock_train(train.entity) - send_alert_depot_of_train_broken(train.entity, depot.entity_stop.backer_name) + send_alert_depot_of_train_broken(map_data, train.entity) remove_train(map_data, train_id, train) end map_data.depots[depot_id] = nil @@ -50,18 +50,10 @@ local function on_refueler_built(map_data, stop, comb) --network_name = set_refueler_from_comb, --network_flag = set_refueler_from_comb, } - set_refueler_from_comb(mod_settings, refueler) local id = stop.unit_number--[[@as uint]] map_data.refuelers[id] = refueler + set_refueler_from_comb(map_data, mod_settings, id) update_stop_if_auto(map_data, refueler, false) - if refueler.network_name then - local network = map_data.to_refuelers[refueler.network_name] - if not network then - network = {} - map_data.to_refuelers[refueler.network_name] = network - end - network[id] = true - end interface_raise_refueler_created(id) end ---@param map_data MapData @@ -76,18 +68,26 @@ local function on_refueler_broken(map_data, refueler_id, refueler) if not train.se_is_being_teleported then remove_train(map_data, train_id, train) lock_train(train.entity) - send_alert_refueler_of_train_broken(train.entity, train.depot_name) + send_alert_refueler_of_train_broken(map_data, train.entity) else train.se_awaiting_removal = train_id end end end end - if refueler.network_name then - local network = map_data.to_refuelers[refueler.network_name] - network[refueler_id] = nil - if next(network) == nil then - map_data.to_refuelers[refueler.network_name] = nil + local f, a + if refueler.network_name == NETWORK_ANY then + f, a = pairs(refueler.network_flag--[[@as {[string]: int}]]) + else + f, a = once, refueler.network_name + end + for network_name, _ in f, a do + local network = map_data.to_refuelers[network_name] + if network then + network[refueler_id] = nil + if next(network) == nil then + map_data.to_refuelers[network_name] = nil + end end end map_data.refuelers[refueler_id] = nil @@ -151,7 +151,7 @@ local function on_station_broken(map_data, station_id, station) if not train.se_is_being_teleported then remove_train(map_data, train_id, train) lock_train(train.entity) - send_alert_station_of_train_broken(train.entity, train.depot_name) + send_alert_station_of_train_broken(map_data, train.entity) else train.se_awaiting_removal = train_id end @@ -297,55 +297,6 @@ local function on_combinator_built(map_data, comb) end ---@param map_data MapData ---@param comb LuaEntity ----@param network_name string? -function on_combinator_network_updated(map_data, comb, network_name) - local stop = map_data.to_stop[comb.unit_number] - - if stop and stop.valid then - local id = stop.unit_number - local station = map_data.stations[id] - if station then - if station.entity_comb1 == comb then - station.network_name = network_name - end - else - local depot = map_data.depots[id] - if depot then - if depot.entity_comb == comb then - local train_id = depot.available_train_id - if train_id then - local train = map_data.trains[train_id] - remove_available_train(map_data, train_id, train) - add_available_train_to_depot(map_data, mod_settings, train_id, train, id, depot) - interface_raise_train_status_changed(train_id, STATUS_D, STATUS_D) - end - end - else - local refueler = map_data.refuelers[id] - if refueler and refueler.entity_comb == comb then - if refueler.network_name then - local network = map_data.to_refuelers[refueler.network_name] - network[id] = nil - if next(network) == nil then - map_data.to_refuelers[refueler.network_name] = nil - end - end - refueler.network_name = network_name - if network_name then - local network = map_data.to_refuelers[network_name] - if not network then - network = {} - map_data.to_refuelers[network_name] = network - end - network[id] = true - end - end - end - end - end -end ----@param map_data MapData ----@param comb LuaEntity function on_combinator_broken(map_data, comb) --NOTE: we do not check for wagon manifest combinators and update their stations, it is assumed they will be lazy deleted later ---@type uint @@ -441,7 +392,35 @@ function combinator_update(map_data, comb, reset_display) local old_network = old_signal and old_signal.name or nil if new_network ~= old_network then has_changed = true - on_combinator_network_updated(map_data, comb, new_network) + + local stop = map_data.to_stop[comb.unit_number] + if stop and stop.valid then + id = stop.unit_number + station = map_data.stations[id] + if station then + if station.entity_comb1 == comb then + station.network_name = new_network + end + else + local depot = map_data.depots[id] + if depot then + if depot.entity_comb == comb then + local train_id = depot.available_train_id + if train_id then + local train = map_data.trains[train_id] + remove_available_train(map_data, train_id, train) + add_available_train_to_depot(map_data, mod_settings, train_id, train, id, depot) + interface_raise_train_status_changed(train_id, STATUS_D, STATUS_D) + end + end + else + local refueler = map_data.refuelers[id] + if refueler and refueler.entity_comb == comb then + set_refueler_from_comb(map_data, mod_settings, id) + end + end + end + end end if params.second_constant ~= old_params.second_constant then has_changed = true @@ -455,7 +434,7 @@ function combinator_update(map_data, comb, reset_display) local refueler = map_data.refuelers[id] if refueler then local pre = refueler.allows_all_trains - set_refueler_from_comb(mod_settings, refueler) + set_refueler_from_comb(map_data, mod_settings, id) if refueler.allows_all_trains ~= pre then update_stop_if_auto(map_data, refueler, false) end @@ -752,7 +731,7 @@ local function setup_se_compat() if train.se_awaiting_removal then remove_train(map_data, train.se_awaiting_removal, train) lock_train(train.entity) - send_alert_station_of_train_broken(train.entity, train.depot_name) + send_alert_station_of_train_broken(map_data, train.entity) return elseif train.se_awaiting_rename then rename_manifest_schedule(train.entity, train.se_awaiting_rename[1], train.se_awaiting_rename[2]) diff --git a/cybersyn/scripts/train-events.lua b/cybersyn/scripts/train-events.lua index a4141a3..c2da022 100644 --- a/cybersyn/scripts/train-events.lua +++ b/cybersyn/scripts/train-events.lua @@ -1,6 +1,7 @@ --By Mami local min = math.min local INF = math.huge +local btest = bit32.btest ---@param map_data MapData ---@param station Station @@ -329,8 +330,10 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train) local best_prior = -INF for id, _ in pairs(refuelers) do local refueler = map_data.refuelers[id] - set_refueler_from_comb(mod_settings, refueler) - if bit32.btest(train.network_flag, refueler.network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then + set_refueler_from_comb(map_data, mod_settings, id) + + local refueler_network_flag = refueler.network_name == NETWORK_ANY and refueler.network_flag[train.network_name] or refueler.network_flag + if btest(train.network_flag, refueler_network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then local accepted = false local dist = nil if refueler.priority == best_prior then