From d4cc8481c4a0655dda4dc5163888e78c1c310543 Mon Sep 17 00:00:00 2001 From: Monica Moniot Date: Wed, 7 Dec 2022 19:53:12 -0500 Subject: [PATCH] added optional priority --- cybersyn/changelog.txt | 7 +++ cybersyn/info.json | 2 +- cybersyn/scripts/central-planning.lua | 70 +++++++++++++++++++-------- cybersyn/scripts/factorio-api.lua | 65 +++++++------------------ cybersyn/scripts/main.lua | 10 ++-- cybersyn/scripts/migrations.lua | 9 ++++ 6 files changed, 93 insertions(+), 70 deletions(-) diff --git a/cybersyn/changelog.txt b/cybersyn/changelog.txt index 2ecbabd..62ca7b0 100644 --- a/cybersyn/changelog.txt +++ b/cybersyn/changelog.txt @@ -111,3 +111,10 @@ Version: 1.0.9 Date: 2022-12-3 Features: - Fixed a bug with SE compat preventing players from joining multiplayer games +--------------------------------------------------------------------------------------------------- +Version: 1.0.10 +Date: 2022-12-5 + Features: + - Added the ability to use the priority signal as input to optional station control so one can override priority on items with optional station control thresholds + - Added refueler stations + - Fixed a crash relating to wagon control combinators on request stations diff --git a/cybersyn/info.json b/cybersyn/info.json index 1c35137..3744a23 100644 --- a/cybersyn/info.json +++ b/cybersyn/info.json @@ -1,6 +1,6 @@ { "name": "cybersyn", - "version": "1.0.9", + "version": "1.0.10", "title": "Project Cybersyn", "author": "Mami", "factorio_version": "1.1", diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index ab3f8bf..48f4373 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -114,8 +114,8 @@ function send_train_between(map_data, r_station_id, p_station_id, train_id, prim local r_item_count = v.count local r_effective_item_count = r_item_count + (r_station.deliveries[item_name] or 0) if r_effective_item_count < 0 and r_item_count < 0 then - local r_threshold = r_station.p_count_or_r_threshold_per_item[item_name] - local p_effective_item_count = p_station.p_count_or_r_threshold_per_item[item_name] + local r_threshold = r_station.item_thresholds and r_station.item_thresholds[item_name] or r_station.r_threshold + local p_effective_item_count = p_station.item_p_counts[item_name] --could be an item that is not present at the station if p_effective_item_count and p_effective_item_count >= r_threshold then local item = {name = item_name, type = item_type, count = min(-r_effective_item_count, p_effective_item_count)} @@ -282,11 +282,19 @@ local function tick_dispatch(map_data, mod_settings) local station = stations[id] --NOTE: the station at r_station_id could have been deleted and reregistered since last poll, this check here prevents it from being processed for a delivery in that case if station and station.deliveries_total < station.entity_stop.trains_limit then - local threshold = station.p_count_or_r_threshold_per_item[item_name] - if threshold <= max_threshold and (station.priority > best_prior or (station.priority == best_prior and station.last_delivery_tick < best_lru)) then + local item_threshold = station.item_thresholds and station.item_thresholds[item_name] or nil + local threshold = station.r_threshold + local prior = station.priority + if item_threshold then + threshold = item_threshold + if station.item_priority then + prior = station.item_priority--[[@as int]] + end + end + if threshold <= max_threshold and (prior > best_prior or (prior == best_prior and station.last_delivery_tick < best_lru)) then r_station_i = i r_threshold = threshold - best_prior = station.priority + best_prior = prior best_lru = station.last_delivery_tick end end @@ -314,9 +322,13 @@ local function tick_dispatch(map_data, mod_settings) for j, p_station_id in ipairs(p_stations) do local p_station = stations[p_station_id] if p_station and p_station.deliveries_total < p_station.entity_stop.trains_limit then - local effective_count = p_station.p_count_or_r_threshold_per_item[item_name] + local effective_count = p_station.item_p_counts[item_name] if effective_count >= r_threshold then + local item_threshold = p_station.item_thresholds and p_station.item_thresholds[item_name] or nil local prior = p_station.priority + if item_threshold then + prior = p_station.item_priority--[[@as int]] + end local slot_threshold = item_type == "fluid" and r_threshold or ceil(r_threshold/get_stack_size(map_data, item_name)) local train, d = get_valid_train(map_data, r_station_id, p_station_id, item_type, slot_threshold) if prior > best_prior or (prior == best_prior and d < best_dist) then @@ -385,13 +397,34 @@ local function tick_poll_station(map_data, mod_settings) end station.r_threshold = mod_settings.r_threshold station.priority = 0 + station.item_priority = nil station.locked_slots = 0 station.network_flag = mod_settings.network_flag - local signals = get_signals(station) - station.tick_signals = signals - station.p_count_or_r_threshold_per_item = {} - if signals then - for k, v in pairs(signals) do + local comb1_signals, comb2_signals = get_signals(station) + station.tick_signals = comb1_signals + station.item_p_counts = {} + + if comb1_signals then + if comb2_signals then + station.item_thresholds = {} + for k, v in pairs(comb2_signals) do + local item_name = v.signal.name + local item_count = v.count + local item_type = v.signal.type + if item_name then + if item_type == "virtual" then + if item_name == SIGNAL_PRIORITY then + station.item_priority = item_count + end + else + station.item_thresholds[item_name] = abs(item_count) + end + end + end + else + station.item_thresholds = nil + end + for k, v in pairs(comb1_signals) do local item_name = v.signal.name local item_count = v.count local item_type = v.signal.type @@ -405,18 +438,18 @@ local function tick_poll_station(map_data, mod_settings) elseif item_name == LOCKED_SLOTS then station.locked_slots = max(item_count, 0) end - signals[k] = nil + comb1_signals[k] = nil end if item_name == station.network_name then station.network_flag = item_count - signals[k] = nil + comb1_signals[k] = nil end else - signals[k] = nil + comb1_signals[k] = nil end end local is_requesting_nothing = true - for k, v in pairs(signals) do + for k, v in pairs(comb1_signals) do ---@type string local item_name = v.signal.name local item_count = v.count @@ -424,7 +457,7 @@ local function tick_poll_station(map_data, mod_settings) local is_not_requesting = true if station.is_r then - local r_threshold = get_threshold(map_data, station, v.signal) + local r_threshold = station.item_thresholds and station.item_thresholds[item_name] or station.r_threshold if -effective_item_count >= r_threshold and -item_count >= r_threshold then is_not_requesting = false is_requesting_nothing = false @@ -437,7 +470,6 @@ local function tick_poll_station(map_data, mod_settings) all_names[#all_names + 1] = v.signal end stations[#stations + 1] = station_id - station.p_count_or_r_threshold_per_item[item_name] = r_threshold end end if is_not_requesting then @@ -449,9 +481,9 @@ local function tick_poll_station(map_data, mod_settings) all_p_stations[item_network_name] = stations end stations[#stations + 1] = station_id - station.p_count_or_r_threshold_per_item[item_name] = effective_item_count + station.item_p_counts[item_name] = effective_item_count else - signals[k] = nil + comb1_signals[k] = nil end end end diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 2396d08..88bd349 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -254,38 +254,14 @@ function set_station_from_comb_state(station) station.is_r = is_pr_state == 0 or is_pr_state == 2 end ---@param map_data MapData ----@param unit_number uint ----@param params ArithmeticCombinatorParameters -local function has_comb_params_changed(map_data, unit_number, params) - local old_params = map_data.to_comb_params[unit_number] - - if params.operation ~= old_params.operation then - if (old_params.operation == OPERATION_PRIMARY_IO) and (params.operation == OPERATION_PRIMARY_IO_ACTIVE or params.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST) then - else - return true - end - end - local new_signal = params.first_signal - local old_signal = old_params.first_signal - local new_network = new_signal and new_signal.name or nil - local old_network = old_signal and old_signal.name or nil - if new_network ~= old_network then - return true - end - if params.second_constant ~= old_params.second_constant then - return true - end - return false -end ----@param map_data MapData ---@param station Station function update_display(map_data, station) local comb = station.entity_comb1 if comb.valid then - local unit_number = comb.unit_number--[[@as uint]] local control = get_comb_control(comb) local params = control.parameters - if not has_comb_params_changed(map_data, unit_number, params) then + --NOTE: the following check can cause a bug where the display desyncs if the player changes the operation of the combinator and then changes it back before the mod can notice, however removing it causes a bug where the user's change is overwritten and ignored. Everything's bad we need an event to catch copy-paste by blueprint. + if params.operation == OPERATION_PRIMARY_IO or params.operation == OPERATION_PRIMARY_IO_ACTIVE or params.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST then if station.display_state >= 2 then params.operation = OPERATION_PRIMARY_IO_ACTIVE elseif station.display_state == 1 then @@ -350,12 +326,23 @@ local DEFINES_COMBINATOR_INPUT = defines.circuit_connector_id.combinator_input ---@param station Station function get_signals(station) --NOTE: the combinator must be valid, but checking for valid every time is too slow - local comb = station.entity_comb1 - local status = comb.status - if status == DEFINES_WORKING or status == DEFINES_LOW_POWER then - return comb.get_merged_signals(DEFINES_COMBINATOR_INPUT) + local comb1 = station.entity_comb1 + local status1 = comb1.status + ---@type Signal[]? + local comb1_signals = nil + ---@type Signal[]? + local comb2_signals = nil + if status1 == DEFINES_WORKING or status1 == DEFINES_LOW_POWER then + comb1_signals = comb1.get_merged_signals(DEFINES_COMBINATOR_INPUT) end - return nil + local comb2 = station.entity_comb2 + if comb2 then + local status2 = comb2.status + if status2 == DEFINES_WORKING or status2 == DEFINES_LOW_POWER then + comb2_signals = comb2.get_merged_signals(DEFINES_COMBINATOR_INPUT) + end + end + return comb1_signals, comb2_signals end ---@param map_data MapData @@ -373,22 +360,6 @@ function set_comb2(map_data, station) end end - ----@param map_data MapData ----@param station Station ----@param signal SignalID -function get_threshold(map_data, station, signal) - local comb2 = station.entity_comb2 - if comb2 then - local count = comb2.get_merged_signal(signal, defines.circuit_connector_id.combinator_input) - if count ~= 0 then - return abs(count) - end - end - return station.r_threshold -end - - ------------------------------------------------------------------------------ --[[alerts]]-- ------------------------------------------------------------------------------ diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index ec434d0..c92213c 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -182,6 +182,7 @@ local function on_station_built(map_data, stop, comb1, comb2) deliveries_total = 0, last_delivery_tick = map_data.total_ticks, priority = 0, + item_priotity = nil, r_threshold = 0, locked_slots = 0, --network_name = set_station_from_comb_state, @@ -191,7 +192,8 @@ local function on_station_built(map_data, stop, comb1, comb2) accepted_layouts = {}, layout_pattern = nil, tick_signals = nil, - p_count_or_r_threshold_per_item = {}, + item_p_counts = {}, + item_thresholds = nil, display_state = 0, } set_station_from_comb_state(station) @@ -473,9 +475,11 @@ function combinator_update(map_data, comb) local new_network = new_signal and new_signal.name or nil 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) end if params.second_constant ~= old_params.second_constant then + has_changed = true local stop = global.to_stop[comb.unit_number] if stop then local station = global.stations[stop.unit_number] @@ -708,9 +712,9 @@ local function on_train_arrives_buffer(map_data, stop, train_id, train) set_r_wagon_combs(map_data, station, train) end elseif train.status == STATUS_P and train.p_station_id == station_id then - --this player intervention that is considered valid + --this is player intervention that is considered valid elseif (train.status == STATUS_R or train.status == STATUS_R_TO_D) and train.r_station_id == station_id then - --this player intervention that is considered valid + --this is player intervention that is considered valid elseif mod_settings.react_to_train_at_incorrect_station then on_failed_delivery(map_data, train_id, train) remove_train(map_data, train_id, train) diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index df7365b..f866716 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -184,6 +184,15 @@ local migrations_table = { station.update_display = nil end end, + ["1.0.10"] = function() + ---@type MapData + local map_data = global + map_data.tick_state = STATE_INIT + map_data.tick_data = {} + for id, station in pairs(map_data.stations) do + station.p_count_or_r_threshold_per_item = nil + end + end, } ---@param data ConfigurationChangedData