diff --git a/cybersyn/data.lua b/cybersyn/data.lua index 549ee77..fd6ea3c 100644 --- a/cybersyn/data.lua +++ b/cybersyn/data.lua @@ -5,6 +5,7 @@ require('scripts.constants') require('prototypes.item') require('prototypes.tech') require('prototypes.entity') +require('prototypes.signal') data:extend({ cybersyn_depot_item, @@ -16,4 +17,8 @@ data:extend({ cybersyn_station_entity, cybersyn_station_in, cybersyn_station_out, + cybersyn_subgroup, + cybersyn_priority, + cybersyn_p_threshold, + cybersyn_r_threshold, }) diff --git a/cybersyn/graphics/icons/p_threshold.png b/cybersyn/graphics/icons/p_threshold.png new file mode 100644 index 0000000..3f42332 Binary files /dev/null and b/cybersyn/graphics/icons/p_threshold.png differ diff --git a/cybersyn/graphics/icons/priority.png b/cybersyn/graphics/icons/priority.png new file mode 100644 index 0000000..3f42332 Binary files /dev/null and b/cybersyn/graphics/icons/priority.png differ diff --git a/cybersyn/graphics/icons/r_threshold.png b/cybersyn/graphics/icons/r_threshold.png new file mode 100644 index 0000000..3f42332 Binary files /dev/null and b/cybersyn/graphics/icons/r_threshold.png differ diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index 2a729c1..474ea37 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -33,3 +33,8 @@ cybersyn-train-network=Cybernetic train network [technology-description] cybersyn-train-network=Cybernetic train network + +[virtual-signal-name] +cybersyn-priority=Station priority +cybersyn-p_threshold=Provide threshold +cybersyn-r_threshold=Request threshold diff --git a/cybersyn/prototypes/entity.lua b/cybersyn/prototypes/entity.lua index 9aa1dce..fc9fb6a 100644 --- a/cybersyn/prototypes/entity.lua +++ b/cybersyn/prototypes/entity.lua @@ -4,12 +4,14 @@ cybersyn_station_entity.icon = "__cybersyn__/graphics/icons/station.png" cybersyn_station_entity.icon_size = 64 cybersyn_station_entity.icon_mipmaps = 4 cybersyn_station_entity.next_upgrade = nil +cybersyn_station_entity.color = {.5, .1, .9} cybersyn_depot_entity = flib.copy_prototype(data.raw["train-stop"]["train-stop"], DEPOT_STATION_NAME) cybersyn_depot_entity.icon = "__cybersyn__/graphics/icons/depot.png" cybersyn_depot_entity.icon_size = 64 cybersyn_depot_entity.icon_mipmaps = 4 cybersyn_depot_entity.next_upgrade = nil +cybersyn_depot_entity.color = {1, .9, .9} cybersyn_station_in = flib.copy_prototype(data.raw["lamp"]["small-lamp"], STATION_IN_NAME) cybersyn_station_in.icon = "__cybersyn__/graphics/icons/station.png" diff --git a/cybersyn/prototypes/signal.lua b/cybersyn/prototypes/signal.lua new file mode 100644 index 0000000..72770ba --- /dev/null +++ b/cybersyn/prototypes/signal.lua @@ -0,0 +1,31 @@ +--By Mami +cybersyn_subgroup = { + type = "item-subgroup", + name = "cybersyn-signal", + group = "signals", + order = "cybersyn0[cybersyn-signal]" +} +cybersyn_priority = { + type = "virtual-signal", + name = SIGNAL_PRIORITY, + icon = "__cybersyn__/graphics/icons/priority.png", + icon_size = 64, + subgroup = "cybersyn-signal", + order = "a-a" +} +cybersyn_p_threshold = { + type = "virtual-signal", + name = PROVIDE_THRESHOLD, + icon = "__cybersyn__/graphics/icons/p_threshold.png", + icon_size = 64, + subgroup = "cybersyn-signal", + order = "a-b" +} +cybersyn_r_threshold = { + type = "virtual-signal", + name = REQUEST_THRESHOLD, + icon = "__cybersyn__/graphics/icons/r_threshold.png", + icon_size = 64, + subgroup = "cybersyn-signal", + order = "a-b" +} diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index 0fffac8..9987f2a 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -1,8 +1,8 @@ --By Mami SIGNAL_PRIORITY = "cybersyn-priority" -REQUEST_THRESHOLD = "cybersyn-request-threshold" -PROVIDE_THRESHOLD = "cybersyn-provide-threshold" +REQUEST_THRESHOLD = "cybersyn-r_threshold" +PROVIDE_THRESHOLD = "cybersyn-p_threshold" STATION_IN_NAME = "cybersyn-station-in" STATION_OUT_NAME = "cybersyn-station-out" diff --git a/cybersyn/scripts/controller.lua b/cybersyn/scripts/controller.lua index 2518522..548806f 100644 --- a/cybersyn/scripts/controller.lua +++ b/cybersyn/scripts/controller.lua @@ -33,22 +33,22 @@ function create_loading_order(stop, manifest) cond_type = "item_count" end - condition[1] = { + condition[#condition + 1] = { type = cond_type, compare_type = "and", condition = {comparator = "≥", first_signal = {type = item.type, name = item.name}, constant = item.count} } - condition[2] = create_loading_order_condition 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"} +local create_unloading_order_condition = {{type = "empty", compare_type = "and"}} function create_unloading_order(stop) return {station = stop.backer_name, wait_conditions = create_unloading_order_condition} end -local create_inactivity_order_condition = create_loading_order_condition +local create_inactivity_order_condition = {{type = "inactivity", compare_type = "and", ticks = 120}} function create_inactivity_order(depot_name) return {station = depot_name, wait_conditions = create_inactivity_order_condition} end @@ -58,6 +58,20 @@ local function create_direct_to_station_order(stop) return {wait_conditions = create_direct_to_station_order_condition, rail = stop.connected_rail, rail_direction = stop.connected_rail_direction} end +function create_depot_schedule(depot_name) + return {current = 1, records = {create_inactivity_order(depot_name)}} +end + +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 + local function get_signals(station) @@ -132,7 +146,7 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p local item_count = v.count local item_type = v.signal.type if item_name and item_type and item_type ~= "virtual" then - local effective_item_count = item_count + r_station.deliveries[item_name] + local effective_item_count = item_count + (r_station.deliveries[item_name] or 0) if -effective_item_count >= r_station.r_threshold then requests[item_name] = -effective_item_count end @@ -140,14 +154,14 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p end end - local p_signals = get_signals(r_station) + local p_signals = get_signals(p_station) if p_signals then for k, v in pairs(p_signals) do local item_name = v.signal.name local item_count = v.count local item_type = v.signal.type if item_name and item_type and item_type ~= "virtual" then - local effective_item_count = item_count + p_station.deliveries[item_name] + local effective_item_count = item_count + (p_station.deliveries[item_name] or 0) if effective_item_count >= p_station.p_threshold then local r = requests[item_name] if r then @@ -196,8 +210,8 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p end end - r_station.last_delivery_tick = economy.ticks_total - p_station.last_delivery_tick = economy.ticks_total + r_station.last_delivery_tick = economy.total_ticks + p_station.last_delivery_tick = economy.total_ticks r_station.deliveries_total = r_station.deliveries_total + 1 p_station.deliveries_total = p_station.deliveries_total + 1 @@ -230,36 +244,25 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p train.r_station_id = r_station_id train.manifest = manifest - do - local records = { - create_inactivity_order(train.depot_name), - create_direct_to_station_order(p_station.entity), - create_loading_order(p_station.entity, manifest), - create_direct_to_station_order(r_station.entity), - create_unloading_order(r_station.entity), - } - local schedule = {current = 1, records = records} - - train.entity.schedule = schedule - end + train.entity.schedule = create_manifest_schedule(train.depot_name, p_station.entity, r_station.entity, manifest) end function tick(map_data, mod_settings) - local ticks_total = map_data.ticks_total + local total_ticks = map_data.total_ticks local stations = map_data.stations local economy = { r_stations_all = {}, p_stations_all = {}, all_items = {}, - ticks_total = ticks_total, + total_ticks = total_ticks, } local r_stations_all = economy.r_stations_all local p_stations_all = economy.p_stations_all local all_items = economy.all_items for station_id, station in pairs(stations) do - if station.deliveries_total < station.train_limit then + if station.deliveries_total < station.entity.trains_limit then station.r_threshold = mod_settings.r_threshold station.p_threshold = mod_settings.p_threshold station.priority = 0 @@ -287,7 +290,7 @@ function tick(map_data, mod_settings) for k, v in pairs(signals) do local item_name = v.signal.name local item_count = v.count - local effective_item_count = item_count + station.deliveries[item_name] + local effective_item_count = item_count + (station.deliveries[item_name] or 0) if -effective_item_count >= station.r_threshold then if r_stations_all[item_name] == nil then @@ -312,7 +315,7 @@ function tick(map_data, mod_settings) local failed_because_missing_trains_total = 0 --we do not dispatch more than one train per station per tick --psuedo-randomize what item (and what station) to check first so if trains available is low they choose orders psuedo-randomly - for _, item_name in icpairs(all_items, ticks_total) do + for _, item_name in icpairs(all_items, total_ticks) do local r_stations = r_stations_all[item_name] local p_stations = p_stations_all[item_name] @@ -321,7 +324,7 @@ function tick(map_data, mod_settings) if #r_stations <= #p_stations then --probably backpressure, prioritize locality repeat - local i = ticks_total%#r_stations + 1 + local i = total_ticks%#r_stations + 1 local r_station_id = table.remove(r_stations, i) local best = 0 @@ -352,7 +355,7 @@ function tick(map_data, mod_settings) else --prioritize round robin repeat - local j = ticks_total%#p_stations + 1 + local j = total_ticks%#p_stations + 1 local p_station_id = table.remove(p_stations, j) local best = 0 diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index d982ed4..acebe8a 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -12,12 +12,13 @@ global: { } Station: { deliveries_total: int - train_limit: int priority: int last_delivery_tick: int r_threshold: int >= 0 p_threshold: int >= 0 entity: LuaEntity + entity_in: LuaEntity + entity_out: LuaEntity deliveries: { [item_name]: int } @@ -28,8 +29,6 @@ Station: { } Train: { entity: LuaEntity - entity_in: LuaEntity - entity_out: LuaEntity layout_id: int item_slot_capacity: int fluid_capacity: int diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index b712c6c..39365ed 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -129,7 +129,6 @@ local function on_station_built(map_data, stop) entity_in.operable = false entity_in.minable = false entity_in.destructible = false - entity_in.health = 0 if entity_out == nil then entity_out = stop.surface.create_entity({ @@ -142,18 +141,17 @@ local function on_station_built(map_data, stop) entity_out.operable = false entity_out.minable = false entity_out.destructible = false - entity_out.health = 0 local station = { entity = stop, entity_in = entity_in, entity_out = entity_out, deliveries_total = 0, - train_limit = 100, priority = 0, last_delivery_tick = 0, r_threshold = 0, p_threshold = 0, + deliveries = {}, accepted_layouts = {} } @@ -163,24 +161,26 @@ 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 + if station.deliveries_total > 0 then + for train_id, train in pairs(map_data.trains) do + 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 end + + if station.entity_in.valid then station.entity_in.destroy() end + if station.entity_out.valid then station.entity_out.destroy() end + map_data.stations[station_id] = nil end @@ -188,23 +188,20 @@ local function on_station_rename(map_data, stop) --search for trains coming to the renamed 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 renamed - --TODO: test to make sure this code actually works - local record = train.entity.schedule.records - if is_p then - record[3] = create_loading_order(station.entity, train.manifest) - else - record[5] = create_unloading_order(station.entity) + if station.deliveries_total > 0 then + for train_id, train in pairs(map_data.trains) do + 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 renamed + local p_station = map_data.stations[train.p_station_id] + local r_station = map_data.stations[train.r_station_id] + local schedule = create_manifest_schedule(train.depot_name, p_station.entity, r_station.entity, train.manifest) + schedule.current = train.entity.schedule.current + train.entity.schedule = schedule end end end @@ -237,7 +234,8 @@ local function update_train_layout(map_data, train) 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 + local inv = carriage.get_inventory(defines.inventory.cargo_wagon) + item_slot_capacity = item_slot_capacity + #inv elseif carriage.type == "fluid-wagon" then layout = layout.."F" fluid_capacity = fluid_capacity + carriage.prototype.capacity @@ -309,7 +307,7 @@ local function on_train_arrives_depot(map_data, train_entity) 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)}} + train.entity.schedule = create_depot_schedule(train.depot_name) map_data.trains_available[train_entity.id] = true else on_failed_delivery(map_data, train) @@ -333,13 +331,15 @@ local function on_train_arrives_depot(map_data, train_entity) layout_id = 0, item_slot_capacity = 0, fluid_capacity = 0, - p_station = 0, - r_station = 0, + p_station_id = 0, + r_station_id = 0, manifest = nil, } - update_train_layout(train) + update_train_layout(global, train) map_data.trains[train_entity.id] = train map_data.trains_available[train_entity.id] = true + local schedule = create_depot_schedule(train.depot_name) + train_entity.schedule = schedule end end @@ -456,9 +456,9 @@ local function on_broken(event) if not entity or not entity.valid then return end if entity.train then - local train = global.trains[entity.id] + local train = global.trains[entity.train.id] if train then - on_train_broken(global, entity.train) + on_train_broken(global, train) end elseif entity.name == BUFFER_STATION_NAME then on_station_broken(global, entity)