diff --git a/cybersyn/scripts/central-planning.lua b/cybersyn/scripts/central-planning.lua index ffd6a2c..bf47478 100644 --- a/cybersyn/scripts/central-planning.lua +++ b/cybersyn/scripts/central-planning.lua @@ -66,17 +66,17 @@ local function get_valid_train(map_data, r_station_id, p_station_id, item_type, capacity >= min_slots_to_move and btest(netand, train.network_flag) and (r_station.allows_all_trains or r_station.accepted_layouts[layout_id]) and - (p_station.allows_all_trains or p_station.accepted_layouts[layout_id]) + (p_station.allows_all_trains or p_station.accepted_layouts[layout_id]) and + not train.se_is_being_teleported then valid_train_exists = true --check if exists valid path --check if path is shortest so we prioritize locality - local d_to_p_dist = get_stop_dist(train.entity.front_stock, p_station.entity_stop) - DEPOT_PRIORITY_MULT*train.priority + local t_to_p_dist = get_stop_dist(train.entity.front_stock, p_station.entity_stop) - DEPOT_PRIORITY_MULT*train.priority - local dist = d_to_p_dist - if capacity > best_capacity or (capacity == best_capacity and dist < best_dist) then + if capacity > best_capacity or (capacity == best_capacity and t_to_p_dist < best_dist) then best_capacity = capacity - best_dist = dist + best_dist = t_to_p_dist best_train = train_id end end @@ -170,47 +170,48 @@ local function send_train_between(map_data, r_station_id, p_station_id, train_id end end - r_station.last_delivery_tick = map_data.total_ticks - p_station.last_delivery_tick = map_data.total_ticks - - r_station.deliveries_total = r_station.deliveries_total + 1 - p_station.deliveries_total = p_station.deliveries_total + 1 - - for item_i, item in ipairs(manifest) do - assert(item.count > 0, "main.lua error, transfer amount was not positive") - - r_station.deliveries[item.name] = (r_station.deliveries[item.name] or 0) + item.count - p_station.deliveries[item.name] = (p_station.deliveries[item.name] or 0) - item.count - - if item_i > 1 then - --prevent deliveries from being processed for these items until their stations are re-polled - local item_network_name = network_name..":"..item.name - economy.all_r_stations[item_network_name] = nil - economy.all_p_stations[item_network_name] = nil - end - end - remove_available_train(map_data, train_id, train) - local depot_id = train.depot_id + local depot_id = train.parked_at_depot_id if depot_id then map_data.depots[depot_id].available_train_id = nil - train.depot_id = nil + train.parked_at_depot_id = nil end + --NOTE: we assume that the train is not being teleported at this time + if set_manifest_schedule(train.entity, train.depot_name, train.se_depot_surface_i, p_station.entity_stop, r_station.entity_stop, manifest, depot_id ~= nil) then + train.status = STATUS_D_TO_P + train.p_station_id = p_station_id + train.r_station_id = r_station_id + train.manifest = manifest + train.last_manifest_tick = map_data.total_ticks - train.status = STATUS_D_TO_P - train.p_station_id = p_station_id - train.r_station_id = r_station_id - train.manifest = manifest - train.last_manifest_tick = map_data.total_ticks + r_station.last_delivery_tick = map_data.total_ticks + p_station.last_delivery_tick = map_data.total_ticks - set_manifest_schedule(train.entity, train.depot_name, train.se_depot_surface_i, p_station.entity_stop, r_station.entity_stop, manifest, depot_id ~= nil) - set_comb2(map_data, p_station) - set_comb2(map_data, r_station) - if p_station.entity_comb1.valid then - set_comb_operation_with_check(map_data, p_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE) - end - if r_station.entity_comb1.valid then - set_comb_operation_with_check(map_data, r_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE) + r_station.deliveries_total = r_station.deliveries_total + 1 + p_station.deliveries_total = p_station.deliveries_total + 1 + + for item_i, item in ipairs(manifest) do + assert(item.count > 0, "main.lua error, transfer amount was not positive") + + r_station.deliveries[item.name] = (r_station.deliveries[item.name] or 0) + item.count + p_station.deliveries[item.name] = (p_station.deliveries[item.name] or 0) - item.count + + if item_i > 1 then + --prevent deliveries from being processed for these items until their stations are re-polled + local item_network_name = network_name..":"..item.name + economy.all_r_stations[item_network_name] = nil + economy.all_p_stations[item_network_name] = nil + end + end + + set_comb2(map_data, p_station) + set_comb2(map_data, r_station) + if p_station.entity_comb1.valid then + set_comb_operation_with_check(map_data, p_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE) + end + if r_station.entity_comb1.valid then + set_comb_operation_with_check(map_data, r_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE) + end end end @@ -222,7 +223,7 @@ local function tick_poll_train(map_data, mod_settings) local train_id, train = next(map_data.trains, tick_data.last_train) tick_data.last_train = train_id - if train and train.manifest and train.entity and train.last_manifest_tick + mod_settings.stuck_train_time*mod_settings.tps < map_data.total_ticks then + if train and train.manifest and not train.se_is_being_teleported and train.last_manifest_tick + mod_settings.stuck_train_time*mod_settings.tps < map_data.total_ticks then send_stuck_train_alert(train.entity, train.depot_name) end end diff --git a/cybersyn/scripts/factorio-api.lua b/cybersyn/scripts/factorio-api.lua index 9b9a3a8..6253647 100644 --- a/cybersyn/scripts/factorio-api.lua +++ b/cybersyn/scripts/factorio-api.lua @@ -119,7 +119,11 @@ end ---@param manifest Manifest ---@param start_at_depot boolean? function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, manifest, start_at_depot) - --NOTE: train must be on same surface as depot_stop + --NOTE: can only return false if start_at_depot is false, it should be incredibly rare that this function returns false + local old_schedule + if not start_at_depot then + old_schedule = train.schedule + end local t_surface = train.front_stock.surface local p_surface = p_stop.surface local r_surface = r_stop.surface @@ -134,7 +138,12 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m create_direct_to_station_order(r_stop), create_unloading_order(r_stop), }} - return + if old_schedule and not train.has_path then + train.schedule = old_schedule + return false + else + return true + end elseif IS_SE_PRESENT and (t_surface_i == p_surface_i or p_surface_i == r_surface_i or r_surface_i == t_surface_i) then local t_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = t_surface_i}) local other_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = (t_surface_i == p_surface_i) and r_surface_i or p_surface_i}) @@ -161,7 +170,12 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m end train.schedule = {current = start_at_depot and 1 or 2, records = records} - return + if old_schedule and not train.has_path then + train.schedule = old_schedule + return false + else + return true + end end end end @@ -173,6 +187,7 @@ function set_manifest_schedule(train, depot_name, d_surface_i, p_stop, r_stop, m }} lock_train(train) send_lost_train_alert(train, depot_name) + return true end diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index 58de442..4c0a07a 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -59,12 +59,13 @@ ---@field public last_manifest_tick int ---@field public has_filtered_wagon boolean ---@field public is_available true? ----@field public depot_id uint? +---@field public parked_at_depot_id uint? ---@field public depot_name string ----@field public se_depot_surface_i uint --se only ----@field public network_name string? +---@field public network_name string ---@field public network_flag int ---@field public priority int +---@field public se_depot_surface_i uint --se only +---@field public se_is_being_teleported true? --se only ---@field public se_awaiting_removal any? --se only ---@field public se_awaiting_rename any? --se only diff --git a/cybersyn/scripts/layout.lua b/cybersyn/scripts/layout.lua index fcdd3a4..410fd5a 100644 --- a/cybersyn/scripts/layout.lua +++ b/cybersyn/scripts/layout.lua @@ -55,7 +55,7 @@ end ---@param train_id uint ---@param train Train function remove_train(map_data, train_id, train) - local parked_at_depot_id = train.depot_id + local parked_at_depot_id = train.parked_at_depot_id if parked_at_depot_id then local depot = map_data.depots[parked_at_depot_id] depot.available_train_id = nil diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index dac7148..bd31550 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -87,7 +87,7 @@ local function add_available_train_to_depot(map_data, train_id, train, depot_id, end depot.available_train_id = train_id train.status = STATUS_D - train.depot_id = depot_id + train.parked_at_depot_id = depot_id train.depot_name = depot.entity_stop.backer_name train.se_depot_surface_i = depot.entity_stop.surface.index train.network_name = network_name @@ -124,6 +124,7 @@ function remove_available_train(map_data, train_id, train) map_data.available_trains[train.network_name] = nil end end + train.is_available = nil end end @@ -196,7 +197,7 @@ local function on_station_broken(map_data, station_id, station) if (is_r and not is_r_delivery_made) or (is_p and not is_p_delivery_made) then --train is attempting delivery to a stop that was destroyed, stop it on_failed_delivery(map_data, train) - if train.entity then + if not train.se_is_being_teleported then remove_train(map_data, train_id, train) lock_train(train.entity) send_lost_train_alert(train.entity, train.depot_name) @@ -548,17 +549,17 @@ local function on_station_rename(map_data, stop, old_name) local is_r_delivery_made = train.status == STATUS_R_TO_D if is_r and not is_r_delivery_made then local r_station = map_data.stations[train.r_station_id] - if train.entity then + if not train.se_is_being_teleported then rename_manifest_schedule(train.entity, r_station.entity_stop, old_name) - elseif IS_SE_PRESENT then + else train.se_awaiting_rename = {r_station.entity_stop, old_name} end elseif is_p and not is_p_delivery_made then --train is attempting delivery to a stop that was renamed local p_station = map_data.stations[train.p_station_id] - if train.entity then + if not train.se_is_being_teleported then rename_manifest_schedule(train.entity, p_station.entity_stop, old_name) - elseif IS_SE_PRESENT then + else train.se_awaiting_rename = {p_station.entity_stop, old_name} end end @@ -737,7 +738,7 @@ local function on_train_leaves_station(map_data, mod_settings, train_id, train) end elseif train.status == STATUS_D then --The train is leaving the depot without a manifest, the player likely intervened - local depot = map_data.depots[train.depot_id--[[@as uint]]] + local depot = map_data.depots[train.parked_at_depot_id--[[@as uint]]] send_lost_train_alert(train.entity, depot.entity_stop.backer_name) remove_train(map_data, train_id, train) end @@ -749,7 +750,7 @@ end ---@param train Train local function on_train_broken(map_data, train_id, train) --NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0 - if train.entity then + if not train.se_is_being_teleported then if train.manifest then on_failed_delivery(map_data, train) end @@ -761,7 +762,7 @@ end local function on_train_modified(map_data, pre_train_id) local train = map_data.trains[pre_train_id] --NOTE: train.entity is only absent if the train is climbing a space elevator as of 0.5.0 - if train and train.entity then + if train and not train.se_is_being_teleported then if train.manifest then on_failed_delivery(map_data, train) end @@ -980,7 +981,7 @@ local function main() local train = map_data.trains[old_id] if not train then return end --NOTE: IMPORTANT, until se_on_train_teleport_finished_event is called map_data.trains[old_id] will reference an invalid train entity; very few of our events care about this and the ones that do should be impossible to trigger until teleportation is finished - train.entity = nil + train.se_is_being_teleported = true map_data.se_tele_old_id[train_unique_identifier] = old_id end) flib_event.register(se_on_train_teleport_finished_event, function(event) @@ -1010,6 +1011,7 @@ local function main() map_data.trains[new_id] = train map_data.trains[old_id] = nil + train.se_is_being_teleported = nil train.entity = train_entity if train.se_awaiting_removal then diff --git a/cybersyn/scripts/migrations.lua b/cybersyn/scripts/migrations.lua index 00dfcf3..ebc8b7d 100644 --- a/cybersyn/scripts/migrations.lua +++ b/cybersyn/scripts/migrations.lua @@ -43,7 +43,7 @@ local migrations_table = { for id, train in pairs(map_data.trains) do local depot = train.depot if depot then - train.depot_id = depot.entity_comb.unit_number + train.parked_at_depot_id = depot.entity_comb.unit_number train.network_name = depot.network_name train.network_flag = depot.network_flag train.priority = depot.priority @@ -138,7 +138,7 @@ local migrations_table = { for k, v in pairs(map_data.trains) do v.depot = nil if not v.is_available then - v.depot_id = nil + v.parked_at_depot_id = nil end end end, @@ -147,21 +147,23 @@ local migrations_table = { local map_data = global map_data.tick_state = STATE_INIT map_data.tick_data = {} - if IS_SE_PRESENT then - for k, v in pairs(map_data.available_trains) do - for id, _ in pairs(v) do - local train = map_data.trains[id] - if not train then - v[id] = nil - end + map_data.available_trains = {} + for id, v in pairs(map_data.trains) do + v.parked_at_depot_id = v.depot_id + v.depot_id = nil + v.se_is_being_teleported = not v.entity and true or nil + --NOTE: we are guessing here because this information was never saved + v.se_depot_surface_i = v.entity.front_stock.surface.index + if v.parked_at_depot_id then + v.is_available = true + local network = map_data.available_trains[v.network_name--[[@as string]]] + if not network then + network = {} + map_data.available_trains[v.network_name--[[@as string]]] = network end - end - for id, v in pairs(map_data.trains) do - if v.is_available then - map_data.available_trains[v.network_name--[[@as string]]][id] = true - end - --NOTE: we are guessing here because this information was never saved - v.se_depot_surface_i = v.entity.front_stock.surface.index + network[id] = true + else + v.is_available = nil end end end,