diff --git a/cybersyn/control.lua b/cybersyn/control.lua index a1bce50..7b5da94 100644 --- a/cybersyn/control.lua +++ b/cybersyn/control.lua @@ -2,9 +2,9 @@ require("scripts.constants") require("scripts.global") -require("scripts.combinator") +require("scripts.factorio-api") require("scripts.central-planning") require("scripts.layout") require("scripts.gui") -require("scripts.alerts") +require("scripts.migrations") require("scripts.main") diff --git a/cybersyn/scripts/alerts.lua b/cybersyn/scripts/alerts.lua deleted file mode 100644 index 81cca79..0000000 --- a/cybersyn/scripts/alerts.lua +++ /dev/null @@ -1,48 +0,0 @@ ---By Mami - -local send_missing_train_alert_for_stop_icon = {name = MISSING_TRAIN_NAME, type = "fluid"} ----@param r_stop LuaEntity ----@param p_stop LuaEntity -function send_missing_train_alert_for_stops(r_stop, p_stop) - for _, player in pairs(r_stop.force.players) do - player.add_custom_alert( - r_stop, - send_missing_train_alert_for_stop_icon, - {"cybersyn-messages.missing-trains", r_stop.backer_name, p_stop.backer_name}, - true - ) - end -end - -local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} ----@param train LuaTrain -function send_lost_train_alert(train) - local loco = train.front_stock or train.back_stock - if loco then - for _, player in pairs(loco.force.players) do - player.add_custom_alert( - loco, - send_lost_train_alert_icon, - {"cybersyn-messages.lost-train"}, - true - ) - end - end -end - - -local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"} ----@param train LuaTrain -function send_nonempty_train_in_depot_alert(train) - local loco = train.front_stock or train.back_stock - if loco then - for _, player in pairs(loco.force.players) do - player.add_custom_alert( - loco, - send_nonempty_train_in_depot_alert_icon, - {"cybersyn-messages.nonempty-train"}, - true - ) - end - end -end diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 1218afb..d28224e 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -11,80 +11,6 @@ local table_remove = table.remove local table_sort = table.sort local random = math.random -local create_loading_order_condition = {type = "inactivity", compare_type = "and", ticks = 120} ----@param stop LuaEntity ----@param manifest Manifest -function create_loading_order(stop, manifest) - local condition = {} - for _, item in ipairs(manifest) do - local cond_type - if item.type == "fluid" then - cond_type = "fluid_count" - else - cond_type = "item_count" - end - - condition[#condition + 1] = { - type = cond_type, - compare_type = "and", - condition = {comparator = "≥", first_signal = {type = item.type, name = item.name}, constant = item.count} - } - end - condition[#condition + 1] = create_loading_order_condition - return {station = stop.backer_name, wait_conditions = condition} -end - -local create_unloading_order_condition = {{type = "empty", compare_type = "and"}} ----@param stop LuaEntity -function create_unloading_order(stop) - return {station = stop.backer_name, wait_conditions = create_unloading_order_condition} -end - -local create_inactivity_order_condition = {{type = "inactivity", compare_type = "and", ticks = 120}} ----@param depot_name string -function create_inactivity_order(depot_name) - return {station = depot_name, wait_conditions = create_inactivity_order_condition} -end - ----@param stop LuaEntity -local function create_direct_to_station_order(stop) - return {rail = stop.connected_rail, rail_direction = stop.connected_rail_direction} -end - ----@param depot_name string -function create_depot_schedule(depot_name) - return {current = 1, records = {create_inactivity_order(depot_name)}} -end - ----@param depot_name string ----@param p_stop LuaEntity ----@param r_stop LuaEntity ----@param manifest Manifest -function create_manifest_schedule(depot_name, p_stop, r_stop, manifest) - return {current = 1, records = { - create_inactivity_order(depot_name), - create_direct_to_station_order(p_stop), - create_loading_order(p_stop, manifest), - create_direct_to_station_order(r_stop), - create_unloading_order(r_stop), - }} -end - ----@param map_data MapData ----@param station Station ----@param manifest Manifest -function remove_manifest(map_data, station, manifest, sign) - local deliveries = station.deliveries - for i, item in ipairs(manifest) do - deliveries[item.name] = deliveries[item.name] + sign*item.count - if deliveries[item.name] == 0 then - deliveries[item.name] = nil - end - end - set_comb2(map_data, station) - station.deliveries_total = station.deliveries_total - 1 -end - ---@param stop0 LuaEntity ---@param stop1 LuaEntity @@ -215,7 +141,7 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p keep_item = true end elseif total_slots_left > 0 then - local stack_size = game.item_prototypes[item.name].stack_size + local stack_size = get_stack_size(map_data, item.name) local slots = ceil(item.count/stack_size) if slots > total_slots_left then item.count = total_slots_left*stack_size @@ -488,7 +414,7 @@ local function tick_dispatch(map_data, mod_settings) local p_station = stations[p_station_id] if p_station.p_count_or_r_threshold_per_item[item_name] >= r_threshold then local prior = p_station.priority - local slot_threshold = item_type == "fluid" and r_threshold or ceil(r_threshold/game.item_prototypes[item_name].stack_size) + local slot_threshold = item_type == "fluid" and r_threshold or ceil(r_threshold/get_stack_size(map_data, item_name)) local depot, d = get_valid_train(map_data, r_station_id, p_station_id, item_type, slot_threshold) if prior > highest_prior or (prior == highest_prior and d < best_dist) then if depot then @@ -518,8 +444,8 @@ end ---@param map_data MapData ---@param mod_settings CybersynModSettings function tick(map_data, mod_settings) + map_data.total_ticks = map_data.total_ticks + 1 if map_data.tick_state == STATE_INIT then - map_data.total_ticks = map_data.total_ticks + 1 map_data.economy.all_p_stations = {} map_data.economy.all_r_stations = {} map_data.economy.all_names = {} diff --git a/cybersyn/scripts/combinator.lua b/cybersyn/scripts/combinator.lua deleted file mode 100644 index 265a194..0000000 --- a/cybersyn/scripts/combinator.lua +++ /dev/null @@ -1,100 +0,0 @@ ---By Mami -local abs = math.abs -local floor = math.floor - ----@param param ArithmeticCombinatorParameters -function get_comb_secondary_state(param) - local bits = param.second_constant or 0 - return bits%2 == 1, floor(bits/2)%3 -end ----@param depot Depot -function set_depot_from_comb_state(depot) - local param = depot.entity_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] - local signal = param.first_signal - depot.network_name = signal and signal.name or nil -end ----@param station Station -function set_station_from_comb_state(station) - --NOTE: this does nothing to update currently active deliveries - local param = station.entity_comb1.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] - local bits = param.second_constant or 0 - local is_pr_state = floor(bits/2)%3 - local signal = param.first_signal - station.network_name = signal and signal.name or nil - station.allows_all_trains = bits%2 == 1 - 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 control LuaArithmeticCombinatorControlBehavior -function set_comb_allows_all_trains(control, allows_all_trains) - local param = control.parameters - local bits = param.second_constant or 0 - param.second_constant = (bits - bits%2) + (allows_all_trains and 1 or 0) - control.parameters = param -end ----@param control LuaArithmeticCombinatorControlBehavior -function set_comb_is_pr_state(control, is_pr_state) - local param = control.parameters - local bits = param.second_constant or 0 - param.second_constant = (bits%2) + (2*is_pr_state) - control.parameters = param -end - - ----@param map_data MapData ----@param comb LuaEntity ----@param signals ConstantCombinatorParameters[]? -function set_combinator_output(map_data, comb, signals) - local out = map_data.to_output[comb.unit_number] - if out.valid then - out.get_or_create_control_behavior().parameters = signals - end -end ----@param comb LuaEntity ----@param op string -function set_combinator_operation(comb, op) - local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]] - local control = a.parameters - control.operation = op - a.parameters = control -end - - ----@param station Station -function get_signals(station) - local comb = station.entity_comb1 - if comb.valid and (comb.status == defines.entity_status.working or comb.status == defines.entity_status.low_power) then - return comb.get_merged_signals(defines.circuit_connector_id.combinator_input) - else - return nil - end -end - ----@param map_data MapData ----@param station Station -function set_comb2(map_data, station) - if station.entity_comb2 then - local deliveries = station.deliveries - local signals = {} - for item_name, count in pairs(deliveries) do - local i = #signals + 1 - local is_fluid = game.item_prototypes[item_name] == nil--NOTE: this is expensive - signals[i] = {index = i, signal = {type = is_fluid and "fluid" or "item", name = item_name}, count = -count} - end - set_combinator_output(map_data, station.entity_comb2, signals) - 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 and comb2.valid 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 diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua new file mode 100644 index 0000000..f6f33e8 --- /dev/null +++ b/cybersyn/scripts/factorio-api.lua @@ -0,0 +1,232 @@ +--By Mami +local abs = math.abs +local floor = math.floor + + +---@param map_data MapData +---@param item_name string +function get_stack_size(map_data, item_name) + return game.item_prototypes[item_name].stack_size +end + + +local create_loading_order_condition = {type = "inactivity", compare_type = "and", ticks = 120} +---@param stop LuaEntity +---@param manifest Manifest +function create_loading_order(stop, manifest) + local condition = {} + for _, item in ipairs(manifest) do + local cond_type + if item.type == "fluid" then + cond_type = "fluid_count" + else + cond_type = "item_count" + end + + condition[#condition + 1] = { + type = cond_type, + compare_type = "and", + condition = {comparator = "≥", first_signal = {type = item.type, name = item.name}, constant = item.count} + } + end + condition[#condition + 1] = create_loading_order_condition + return {station = stop.backer_name, wait_conditions = condition} +end + +local create_unloading_order_condition = {{type = "empty", compare_type = "and"}} +---@param stop LuaEntity +function create_unloading_order(stop) + return {station = stop.backer_name, wait_conditions = create_unloading_order_condition} +end + +local create_inactivity_order_condition = {{type = "inactivity", compare_type = "and", ticks = 120}} +---@param depot_name string +function create_inactivity_order(depot_name) + return {station = depot_name, wait_conditions = create_inactivity_order_condition} +end + +---@param stop LuaEntity +local function create_direct_to_station_order(stop) + return {rail = stop.connected_rail, rail_direction = stop.connected_rail_direction} +end + +---@param depot_name string +function create_depot_schedule(depot_name) + return {current = 1, records = {create_inactivity_order(depot_name)}} +end + +---@param depot_name string +---@param p_stop LuaEntity +---@param r_stop LuaEntity +---@param manifest Manifest +function create_manifest_schedule(depot_name, p_stop, r_stop, manifest) + return {current = 1, records = { + create_inactivity_order(depot_name), + create_direct_to_station_order(p_stop), + create_loading_order(p_stop, manifest), + create_direct_to_station_order(r_stop), + create_unloading_order(r_stop), + }} +end + +---@param map_data MapData +---@param station Station +---@param manifest Manifest +function remove_manifest(map_data, station, manifest, sign) + local deliveries = station.deliveries + for i, item in ipairs(manifest) do + deliveries[item.name] = deliveries[item.name] + sign*item.count + if deliveries[item.name] == 0 then + deliveries[item.name] = nil + end + end + set_comb2(map_data, station) + station.deliveries_total = station.deliveries_total - 1 +end + + + +---@param param ArithmeticCombinatorParameters +function get_comb_secondary_state(param) + local bits = param.second_constant or 0 + return bits%2 == 1, floor(bits/2)%3 +end +---@param depot Depot +function set_depot_from_comb_state(depot) + local param = depot.entity_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] + local signal = param.first_signal + depot.network_name = signal and signal.name or nil +end +---@param station Station +function set_station_from_comb_state(station) + --NOTE: this does nothing to update currently active deliveries + local param = station.entity_comb1.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] + local bits = param.second_constant or 0 + local is_pr_state = floor(bits/2)%3 + local signal = param.first_signal + station.network_name = signal and signal.name or nil + station.allows_all_trains = bits%2 == 1 + 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 control LuaArithmeticCombinatorControlBehavior +function set_comb_allows_all_trains(control, allows_all_trains) + local param = control.parameters + local bits = param.second_constant or 0 + param.second_constant = (bits - bits%2) + (allows_all_trains and 1 or 0) + control.parameters = param +end +---@param control LuaArithmeticCombinatorControlBehavior +function set_comb_is_pr_state(control, is_pr_state) + local param = control.parameters + local bits = param.second_constant or 0 + param.second_constant = (bits%2) + (2*is_pr_state) + control.parameters = param +end + + +---@param map_data MapData +---@param comb LuaEntity +---@param signals ConstantCombinatorParameters[]? +function set_combinator_output(map_data, comb, signals) + local out = map_data.to_output[comb.unit_number] + if out.valid then + out.get_or_create_control_behavior().parameters = signals + end +end +---@param comb LuaEntity +---@param op string +function set_combinator_operation(comb, op) + local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]] + local control = a.parameters + control.operation = op + a.parameters = control +end + + +---@param station Station +function get_signals(station) + local comb = station.entity_comb1 + if comb.valid and (comb.status == defines.entity_status.working or comb.status == defines.entity_status.low_power) then + return comb.get_merged_signals(defines.circuit_connector_id.combinator_input) + else + return nil + end +end + +---@param map_data MapData +---@param station Station +function set_comb2(map_data, station) + if station.entity_comb2 then + local deliveries = station.deliveries + local signals = {} + for item_name, count in pairs(deliveries) do + local i = #signals + 1 + local is_fluid = game.item_prototypes[item_name] == nil--NOTE: this is expensive + signals[i] = {index = i, signal = {type = is_fluid and "fluid" or "item", name = item_name}, count = -count} + end + set_combinator_output(map_data, station.entity_comb2, signals) + 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 and comb2.valid 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 + +local send_missing_train_alert_for_stop_icon = {name = MISSING_TRAIN_NAME, type = "fluid"} +---@param r_stop LuaEntity +---@param p_stop LuaEntity +function send_missing_train_alert_for_stops(r_stop, p_stop) + for _, player in pairs(r_stop.force.players) do + player.add_custom_alert( + r_stop, + send_missing_train_alert_for_stop_icon, + {"cybersyn-messages.missing-trains", r_stop.backer_name, p_stop.backer_name}, + true + ) + end +end + +local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"} +---@param train LuaTrain +function send_lost_train_alert(train) + local loco = train.front_stock or train.back_stock + if loco then + for _, player in pairs(loco.force.players) do + player.add_custom_alert( + loco, + send_lost_train_alert_icon, + {"cybersyn-messages.lost-train"}, + true + ) + end + end +end + + +local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"} +---@param train LuaTrain +function send_nonempty_train_in_depot_alert(train) + local loco = train.front_stock or train.back_stock + if loco then + for _, player in pairs(loco.force.players) do + player.add_custom_alert( + loco, + send_nonempty_train_in_depot_alert_icon, + {"cybersyn-messages.nonempty-train"}, + true + ) + end + end +end diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index a59f686..37abd59 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -802,6 +802,8 @@ local function main() register_gui_actions() flib_event.on_init(init_global) + + flib_event.on_configuration_changed(on_config_changed) end diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua new file mode 100644 index 0000000..33d20e3 --- /dev/null +++ b/cybersyn/scripts/migrations.lua @@ -0,0 +1,22 @@ +local flib_migration = require("__flib__.migration") + + +local migrations_table = { + ["0.0.1"] = function() + ---@type MapData + local map_data = global + for k, station in pairs(map_data.stations) do + station.p_count_or_r_threshold_per_item = {} + station.p_threshold = nil + station.is_all = nil + station.is_auto = nil + set_station_from_comb_state(station) + end + map_data.tick_state = STATE_INIT + end, +} + +---@param data ConfigurationChangedData +function on_config_changed(data) + flib_migration.on_config_changed(data, migrations_table) +end