diff --git a/.vscode/launch.json b/.vscode/launch.json index cb7c79b..ddec48b 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,6 +18,20 @@ }, "disableExtraMods": true }, + { + "type": "factoriomod", + "request": "launch", + "name": "Factorio Mod Debug (Modded)", + "modsPath": "C:\\Users\\mmoni\\AppData\\Roaming\\Factorio\\mods", + "manageMod": true, + "adjustMods": { + "debugadapter": true, + "flib": true, + "cybersyn": true, + "creative-mod": true, + }, + "disableExtraMods": false + }, { "type": "factoriomod", "request": "launch", diff --git a/TODO b/TODO index cc20c47..ec7f13b 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,6 @@ do hardcore testing models & art space elevator compat railloader compat +add missing items alert +lost train can be repurposed and rescheduled while alert is active +display when train is coming diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index 3b2c802..0bd6991 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -9,6 +9,7 @@ local btest = bit32.btest local band = bit32.band 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 @@ -99,8 +100,8 @@ local function set_comb2(map_data, station) local signals = {} for item_name, count in pairs(deliveries) do local i = #signals + 1 - local item_type = game.item_prototypes[item_name].type--NOTE: this is expensive - signals[i] = {index = i, signal = {type = item_type, name = item_name}, count = -count} + 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 @@ -481,23 +482,13 @@ local function tick_dispatch(map_data, mod_settings) local all_p_stations = map_data.economy.all_p_stations local all_names = map_data.economy.all_names local stations = map_data.stations - local size = #all_names local r_stations = tick_data.r_stations local p_stations = tick_data.p_stations if not (p_stations and #r_stations > 0 and #p_stations > 0) then - if size == 0 then - map_data.tick_state = STATE_INIT - return true - elseif tick_data.start_i == nil then - --semi-randomized starting item - tick_data.start_i = 2*(map_data.total_ticks%(size/2)) + 1 - tick_data.offset_i = 0 - end while true do - if tick_data.offset_i >= size then - tick_data.start_i = nil - tick_data.offset_i = nil + local size = #all_names + if size == 0 then tick_data.r_stations = nil tick_data.p_stations = nil tick_data.item_name = nil @@ -505,11 +496,16 @@ local function tick_dispatch(map_data, mod_settings) map_data.tick_state = STATE_INIT return true end - local name_i = tick_data.start_i + tick_data.offset_i - tick_data.offset_i = tick_data.offset_i + 2 - local item_network_name = all_names[(name_i - 1)%size + 1] - local signal = all_names[(name_i)%size + 1] + --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] + local signal = all_names[name_i] + --swap remove + all_names[name_i - 1] = all_names[size - 1] + all_names[name_i] = all_names[size] + all_names[size] = nil + all_names[size - 1] = nil r_stations = all_r_stations[item_network_name] p_stations = all_p_stations[item_network_name] diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index 4e15cdd..bdce530 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -15,6 +15,7 @@ COMBINATOR_CLOSE_SOUND = "entity-close/cybersyn-combinator" OPERATION_DEFAULT = "*" OPERATION_PRIMARY_IO = "/" +OPERATION_PRIMARY_IO_ACTIVE = "^" OPERATION_SECONDARY_IO = "%" OPERATION_DEPOT = "+" OPERATION_WAGON_MANIFEST = "-" diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 961980c..6f8ba23 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -53,6 +53,7 @@ ---@field public p_station_id uint ---@field public r_station_id uint ---@field public manifest Manifest +---@field public has_filtered_wagon boolean ---@alias Manifest {}[] ---@alias TrainClass {[uint]: boolean} diff --git a/cybersyn/scripts/layout.lua b/cybersyn/scripts/layout.lua index d9f3dba..543742e 100644 --- a/cybersyn/scripts/layout.lua +++ b/cybersyn/scripts/layout.lua @@ -2,6 +2,7 @@ local area = require("__flib__.area") local abs = math.abs local floor = math.floor +local ceil = math.ceil local function iterr(a, i) i = i + 1 @@ -123,6 +124,7 @@ function set_p_wagon_combs(map_data, station, train) local ivpairs = is_reversed and irpairs or ipairs for carriage_i, carriage in ivpairs(carriages) do + --NOTE: we are not checking valid ---@type LuaEntity? local comb = station.wagon_combs[carriage_i] if comb and not comb.valid then @@ -137,42 +139,53 @@ function set_p_wagon_combs(map_data, station, train) local signals = {} local inv = carriage.get_inventory(defines.inventory.cargo_wagon) - local item_slots_capacity = #inv - station.locked_slots - while item_slots_capacity > 0 do - local do_inc = false - if item.type == "item" then - local stack_size = game.item_prototypes[item.name].stack_size - local item_slots = math.ceil(item_count/stack_size) - local i = #signals + 1 - if item_slots > item_slots_capacity then - if comb then - signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = item_slots_capacity*stack_size} + if inv then + local inv_filter_i = 1 + local item_slots_capacity = #inv - station.locked_slots + while item_slots_capacity > 0 do + local do_inc = false + if item.type == "item" then + local stack_size = game.item_prototypes[item.name].stack_size + local item_slots = ceil(item_count/stack_size) + local i = #signals + 1 + local slots_to_filter + if item_slots > item_slots_capacity then + if comb then + signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = item_slots_capacity*stack_size} + end + item_slots_capacity = 0 + item_count = item_count - item_slots_capacity*stack_size + slots_to_filter = item_slots_capacity + else + if comb then + signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = item_count} + end + item_slots_capacity = item_slots_capacity - item_slots + do_inc = true + slots_to_filter = item_slots end - item_slots_capacity = 0 - item_count = item_count - item_slots_capacity*stack_size + for j = 1, slots_to_filter do + inv.set_filter(inv_filter_i, item.name) + inv_filter_i = inv_filter_i + 1 + end + train.has_filtered_wagon = true else - if comb then - signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = item_count} - end - item_slots_capacity = item_slots_capacity - item_slots do_inc = true end - else - do_inc = true - end - if do_inc then - item_i = item_i + 1 - if item_i <= #manifest then - item = manifest[item_i] - item_count = item.count - else - break + if do_inc then + item_i = item_i + 1 + if item_i <= #manifest then + item = manifest[item_i] + item_count = item.count + else + break + end end end - end - if comb then - set_combinator_output(map_data, comb, signals) + if comb then + set_combinator_output(map_data, comb, signals) + end end elseif carriage.type == "fluid-wagon" and fluid_i <= #manifest then local fluid_capacity = carriage.prototype.fluid_capacity diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index 0a0c9f8..d29050d 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -562,6 +562,20 @@ end local function on_train_leaves_station(map_data, train) if train.manifest then if train.status == STATUS_P then + if train.has_filtered_wagon then + train.has_filtered_wagon = false + for carriage_i, carriage in ipairs(train.entity.carriages) do + if carriage.type == "cargo-wagon" then + local inv = carriage.get_inventory(defines.inventory.cargo_wagon) + if inv and inv.is_filtered() then + ---@type uint + for i = 1, #inv do + inv.set_filter(i, nil) + end + end + end + end + end train.status = STATUS_P_TO_R local station = map_data.stations[train.p_station_id] remove_manifest(map_data, station, train.manifest, 1) @@ -663,21 +677,23 @@ end local function on_train_changed(event) local train_e = event.train local train = global.trains[train_e.id] - if train_e.state == defines.train_state.wait_station then - local stop = train_e.station - if stop and stop.valid and stop.name == "train-stop" then - if global.stations[stop.unit_number] then - on_train_arrives_buffer(global, stop, train) - else - local depot = global.depots[stop.unit_number] - if depot then - on_train_arrives_depot(global, depot, train_e) + if train_e.valid then + if train_e.state == defines.train_state.wait_station then + local stop = train_e.station + if stop and stop.valid and stop.name == "train-stop" then + if global.stations[stop.unit_number] then + on_train_arrives_buffer(global, stop, train) + else + local depot = global.depots[stop.unit_number] + if depot then + on_train_arrives_depot(global, depot, train_e) + end end end - end - elseif event.old_state == defines.train_state.wait_station then - if train then - on_train_leaves_station(global, train) + elseif event.old_state == defines.train_state.wait_station then + if train then + on_train_leaves_station(global, train) + end end end end @@ -739,7 +755,7 @@ local function main() mod_settings.p_threshold = settings.global["cybersyn-provide-threshold"].value--[[@as int]] mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]] - --NOTE: I have no idea if this correctly registers all events once in all situations + --NOTE: There is a concern that it is possible to build or destroy important entities without one of these events being triggered, in which case the mod will have undefined behavior flib_event.register(defines.events.on_built_entity, on_built, filter_built) flib_event.register(defines.events.on_robot_built_entity, on_built, filter_built) flib_event.register({defines.events.script_raised_built, defines.events.script_raised_revive, defines.events.on_entity_cloned}, on_built) @@ -754,7 +770,7 @@ local function main() flib_event.register(defines.events.on_entity_settings_pasted, on_paste) local nth_tick = math.ceil(60/mod_settings.tps); - flib_event.on_nth_tick(nth_tick, function(event) + flib_event.on_nth_tick(nth_tick, function() tick(global, mod_settings) end)