From fc050f39c1069797b329a69226e0dca80b76792e Mon Sep 17 00:00:00 2001 From: Monica Moniot Date: Wed, 12 Oct 2022 12:37:12 -0400 Subject: [PATCH] added layout counting --- mtc/scripts/global.lua | 14 ++- mtc/scripts/main.lua | 265 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 241 insertions(+), 38 deletions(-) diff --git a/mtc/scripts/global.lua b/mtc/scripts/global.lua index acac881..ee9fcda 100644 --- a/mtc/scripts/global.lua +++ b/mtc/scripts/global.lua @@ -3,9 +3,12 @@ --[[ global: { total_ticks: int + layout_top_id: int stations: {[stop_id]: Station} trains: {[train_id]: Train} trains_available: {[train_id]: bool} + layouts: {[layout_id]: Layout} + layout_train_count: {[layout_id]: int} } Station: { deliveries_total: int @@ -18,9 +21,7 @@ Station: { deliveries: { [item_name]: int } - train_layout: [ [ { - [car_type]: bool - } ] ] + train_layout: [char] accepted_layouts: { [layout_id]: bool } @@ -30,7 +31,6 @@ Train: { layout_id: int item_slot_capacity: int fluid_capacity: int - depot_id: int depot_name: string status: int p_station_id: stop_id @@ -41,12 +41,16 @@ Train: { count: int }] } +Layout: string ]] - +--TODO: only init once global.total_ticks = 0 global.stations = {} global.trains = {} global.trains_available = {} +global.layouts = {} +global.layout_train_count = {} +global.layout_top_id = 1 STATUS_D = 0 STATUS_D_TO_P = 1 diff --git a/mtc/scripts/main.lua b/mtc/scripts/main.lua index 7849ab9..ae945aa 100644 --- a/mtc/scripts/main.lua +++ b/mtc/scripts/main.lua @@ -1,5 +1,55 @@ --By Monica Moniot + + + +local function on_failed_delivery(map_data, train) + local is_p_delivery_made = train.status ~= STATUS_D_TO_P and train.status ~= STATUS_P + if not is_p_delivery_made then + local station = map_data.stations[train.p_station_id] + for i, item in ipairs(train.manifest) do + station.deliveries[item.name] = station.deliveries[item.name] + item.count + if station.deliveries[item.name] == 0 then + station.deliveries[item.name] = nil + end + end + station.deliveries_total = station.deliveries_total - 1 + end + local is_r_delivery_made = train.status == STATUS_R_TO_D + if not is_r_delivery_made then + local station = map_data.stations[train.r_station_id] + for i, item in ipairs(train.manifest) do + station.deliveries[item.name] = station.deliveries[item.name] - item.count + if station.deliveries[item.name] == 0 then + station.deliveries[item.name] = nil + end + end + station.deliveries_total = station.deliveries_total - 1 + end + --TODO: change circuit outputs + train.r_station_id = 0 + train.p_station_id = 0 + train.manifest = nil + --NOTE: must change train status to STATUS_D or remove it from tracked trains after call +end + +local function remove_train(map_data, train, train_id) + map_data.trains[train_id] = nil + map_data.trains_available[train_id] = nil + local layout_id = train.layout_id + local count = map_data.layout_train_count[layout_id] + if count <= 1 then + map_data.layout_train_count[layout_id] = nil + map_data.layouts[layout_id] = nil + for station_id, station in pairs(map_data.stations) do + station.accepted_layouts[layout_id] = nil + end + else + map_data.layout_train_count[layout_id] = count - 1 + end +end + local function on_station_built(map_data, stop) + --TODO: update station stats local station = { deliveries_total = 0, train_limit = 100, @@ -18,6 +68,28 @@ local function on_station_built(map_data, stop) map_data.stations[stop.unit_number] = station end local function on_station_broken(map_data, stop) + --search for trains coming to the destroyed station + local station_id = stop.unit_number + local station = map_data.stations[station_id] + for train_id, train in pairs(map_data.trains) do + if station.deliveries_total <= 0 then + break + end + local is_p = train.r_station_id == station_id + local is_r = train.p_station_id == station_id + if is_p or is_r then + local is_p_delivery_made = train.status ~= STATUS_D_TO_P and train.status ~= STATUS_P + local is_r_delivery_made = train.status == STATUS_R_TO_D + 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) + train.entity.schedule = nil + remove_train(map_data, train, train_id) + --TODO: mark train as lost in the alerts system + end + end + end + map_data.stations[station_id] = nil end @@ -37,24 +109,73 @@ local function find_and_add_all_stations(map_data) end end -local function on_failed_delivery(map_data, train) - if train.status == STATUS_D or train.status == STATUS_D_TO_P or train.status == STATUS_P then - local station = map_data.stations[train.p_station_id] - for i, item in ipairs(train.manifest) do - station.deliveries[item.name] = station.deliveries[item.name] + item.count +local function update_train_layout(map_data, train) + local carriages = train.entity.carriages + local layout = "" + local i = 1 + local item_slot_capacity = 0 + local fluid_capacity = 0 + for _, carriage in pairs(carriages) do + if carriage.type == "cargo-wagon" then + layout = layout.."C" + item_slot_capacity = item_slot_capacity + carriage.prototype.inventory_size + elseif carriage.type == "fluid-wagon" then + layout = layout.."F" + fluid_capacity = fluid_capacity + carriage.prototype.capacity + else + layout = layout.."?" + end + i = i + 1 + end + local layout_id = 0 + for id, cur_layout in pairs(map_data.layouts) do + if layout == cur_layout then + layout_id = id + break end end - if train.status ~= STATUS_R_TO_D then - local station = map_data.stations[train.r_station_id] - for i, item in ipairs(train.manifest) do - station.deliveries[item.name] = station.deliveries[item.name] - item.count + if layout_id == 0 then + --define new layout + layout_id = map_data.layout_top_id + map_data.layout_top_id = map_data.layout_top_id + 1 + + map_data.layouts[layout_id] = layout + map_data.layout_train_count[layout_id] = 1 + for station_id, station in pairs(map_data.stations) do + if #layout >= #station.train_layout then + local is_approved = true + for i, v in ipairs(station.train_layout) do + local c = string.sub(layout, i, i) + if v == "C" then + if c ~= "C" and c ~= "?" then + is_approved = false + break + end + elseif v == "F" then + if c ~= "F" then + is_approved = false + break + end + end + end + for i = #station.train_layout, #layout do + local c = string.sub(layout, i, i) + if c ~= "?" then + is_approved = false + break + end + end + if is_approved then + station.accepted_layouts[layout_id] = true + end + end end + else + map_data.layout_train_count[layout_id] = map_data.layout_train_count[layout_id] + 1 end - --TODO: change circuit outputs - train.r_station_id = 0 - train.p_station_id = 0 - train.manifest = nil - --NOTE: must change train status after call or remove it from tracked trains + train.layout_id = layout_id + train.item_slot_capacity = item_slot_capacity + train.fluid_capacity = fluid_capacity end @@ -67,17 +188,26 @@ local function on_train_arrives_depot(map_data, train_entity) train.p_station_id = 0 train.r_station_id = 0 train.manifest = nil + train.depot_name = train_entity.station.backer_name + train.status = STATUS_D + train.entity.schedule = {current = 1, records = {create_inactivity_order(train.depot_name)}} + map_data.trains_available[train_entity.id] = true else on_failed_delivery(map_data, train) + local contents = train.entity.get_contents() + if next(contents) == nil then + train.depot_name = train_entity.station.backer_name + train.status = STATUS_D + map_data.trains_available[train_entity.id] = true + else--train still has cargo + train.entity.schedule = nil + remove_train(map_data, train, train_entity.id) + --TODO: mark train as lost in the alerts system + end end end - train.depot_id = train_entity.station.unit_number - train.depot_name = train_entity.station.backer_name - train.status = STATUS_D - map_data.trains_available[train_entity.id] = true else - map_data.trains[train_entity.id] = { - depot_id = train_entity.station.unit_number, + train = { depot_name = train_entity.station.backer_name, status = STATUS_D, entity = train_entity, @@ -88,8 +218,10 @@ local function on_train_arrives_depot(map_data, train_entity) r_station = 0, manifest = nil, } + update_train_layout(train) + map_data.trains[train_entity.id] = train + map_data.trains_available[train_entity.id] = true end - map_data.trains_available[train_entity.id] = true end local function on_train_arrives_buffer(map_data, station_id, train) @@ -106,29 +238,37 @@ local function on_train_arrives_buffer(map_data, station_id, train) end else on_failed_delivery(map_data, train) - map_data.trains[train.entity.id] = nil + remove_train(map_data, train, train.entity.id) end else --train is lost somehow, probably from player intervention - map_data.trains[train.entity.id] = nil + remove_train(map_data, train, train.entity.id) end end -local function on_train_leaves_buffer(map_data, train) +local function on_train_leaves_station(map_data, train) if train.manifest then if train.status == STATUS_P then train.status = STATUS_P_TO_R local station = map_data.stations[train.p_station_id] for i, item in ipairs(train.manifest) do station.deliveries[item.name] = station.deliveries[item.name] + item.count + if station.deliveries[item.name] == 0 then + station.deliveries[item.name] = nil + end end + station.deliveries_total = station.deliveries_total - 1 --TODO: change circuit outputs elseif train.status == STATUS_R then train.status = STATUS_R_TO_D local station = map_data.stations[train.r_station_id] for i, item in ipairs(train.manifest) do station.deliveries[item.name] = station.deliveries[item.name] - item.count + if station.deliveries[item.name] == 0 then + station.deliveries[item.name] = nil + end end + station.deliveries_total = station.deliveries_total - 1 --TODO: change circuit outputs end end @@ -137,7 +277,26 @@ end local function on_train_broken(map_data, train) if train.manifest then on_failed_delivery(map_data, train) - map_data.trains[train.entity.id] = nil + remove_train(map_data, train, train.entity.id) + end +end + +local function on_train_modified(map_data, pre_train_id, train_entity) + local train = map_data.trains[pre_train_id] + if train then + + if train.manifest then + on_failed_delivery(map_data, train) + remove_train(map_data, train, pre_train_id) + else--train is in depot + remove_train(map_data, train, pre_train_id) + train.entity = train_entity + update_train_layout(map_data, train) + --TODO: update train stats + + map_data.trains[train_entity.id] = train + map_data.trains_available[train_entity.id] = true + end end end @@ -146,11 +305,15 @@ local function on_tick(event) tick(global.stations, global.trains_available, global.total_ticks) global.total_ticks = global.total_ticks + 1 end + local function on_built(event) local entity = event.entity or event.created_entity or event.destination - if not entity or not entity.valid or entity.name ~= BUFFER_STATION_NAME then return end - - on_station_built(global, entity) + if not entity or not entity.valid then return end + if entity.name == BUFFER_STATION_NAME then + on_station_built(global, entity) + elseif entity.type == "inserter" then + elseif entity.type == "pump" then + end end local function on_broken(event) local entity = event.entity @@ -163,6 +326,8 @@ local function on_broken(event) end elseif entity.name == BUFFER_STATION_NAME then on_station_broken(entity.unit_number) + elseif entity.type == "inserter" then + elseif entity.type == "pump" then end end @@ -178,16 +343,46 @@ local function on_train_changed(event) end end elseif event.old_state == defines.train_state.wait_station then - if train and train.is_at_buffer then - on_train_leaves_buffer(global, train) + if train then + on_train_leaves_station(global, train) end end end -local filter_built = {{filter = "type", type = "train-stop"}} -local filter_broken = {{filter = "type", type = "train-stop"}, {filter = "rolling-stock"}} -local function register_events() +local function on_train_built(event) + local train_e = event.train + if event.old_train_id_1 then + on_train_modified(global, event.old_train_id_1, train_e) + end + if event.old_train_id_2 then + on_train_modified(global, event.old_train_id_2, train_e) + end +end +local function on_surface_removed(event) + local surface = game.surfaces[event.surface_index] + if surface then + local train_stops = surface.find_entities_filtered({type = "train-stop"}) + for _, entity in pairs(train_stops) do + if entity.name == BUFFER_STATION_NAME then + on_station_broken(entity.unit_number) + end + end + end +end + +local filter_built = { + {filter = "type", type = "train-stop"}, + {filter = "type", type = "inserter"}, + {filter = "type", type = "pump"}, +} +local filter_broken = { + {filter = "type", type = "train-stop"}, + {filter = "type", type = "inserter"}, + {filter = "type", type = "pump"}, + {filter = "rolling-stock"}, +} +local function register_events() script.on_event(defines.events.on_built_entity, on_built, filter_built) script.on_event(defines.events.on_robot_built_entity, on_built, filter_built) script.on_event({defines.events.script_raised_built, defines.events.script_raised_revive, defines.events.on_entity_cloned}, on_built) @@ -211,9 +406,13 @@ script.on_load(function() end) script.on_init(function() + --TODO: we are not checking changed cargo capacities + find_and_add_all_stations(global) register_events() end) script.on_configuration_changed(function(data) + --TODO: we are not checking changed cargo capacities + find_and_add_all_stations(global) register_events() end)