diff --git a/LICENSE b/LICENSE index aeb0e16..0c08310 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 Monica Moniot +Copyright (c) 2022 Mami Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/cybersyn/control.lua b/cybersyn/control.lua index 9ef9749..6b7facc 100644 --- a/cybersyn/control.lua +++ b/cybersyn/control.lua @@ -1,4 +1,4 @@ - +--By Mami require("scripts.constants") require("scripts.global") diff --git a/cybersyn/data.lua b/cybersyn/data.lua index 78fc92c..3cc2b38 100644 --- a/cybersyn/data.lua +++ b/cybersyn/data.lua @@ -8,18 +8,14 @@ require('prototypes.entity') require('prototypes.signal') data:extend({ - cybersyn_depot_item, - cybersyn_station_item, - cybersyn_depot_recipe, - cybersyn_station_recipe, + combinator_entity, + combinator_out_entity, + combinator_item, + combinator_recipe, cybersyn_tech, - cybersyn_depot_entity, - cybersyn_station_entity, - cybersyn_station_in, - cybersyn_station_out, - cybersyn_subgroup, - cybersyn_priority, - cybersyn_p_threshold, - cybersyn_r_threshold, - cybersyn_locked_slots, + subgroup_signal, + priority_signal, + p_threshold_signal, + r_threshold_signal, + locked_slots_signal, }) diff --git a/cybersyn/graphics/icons/depot.png b/cybersyn/graphics/icons/combinator.png similarity index 100% rename from cybersyn/graphics/icons/depot.png rename to cybersyn/graphics/icons/combinator.png diff --git a/cybersyn/graphics/icons/p_threshold.png b/cybersyn/graphics/icons/provide-threshold.png similarity index 100% rename from cybersyn/graphics/icons/p_threshold.png rename to cybersyn/graphics/icons/provide-threshold.png diff --git a/cybersyn/graphics/icons/r_threshold.png b/cybersyn/graphics/icons/request-threshold.png similarity index 100% rename from cybersyn/graphics/icons/r_threshold.png rename to cybersyn/graphics/icons/request-threshold.png diff --git a/cybersyn/graphics/icons/station.png b/cybersyn/graphics/icons/station.png deleted file mode 100644 index 3f42332..0000000 Binary files a/cybersyn/graphics/icons/station.png and /dev/null differ diff --git a/cybersyn/graphics/invisible.png b/cybersyn/graphics/invisible.png new file mode 100644 index 0000000..b04843b Binary files /dev/null and b/cybersyn/graphics/invisible.png differ diff --git a/cybersyn/locale/en/base.cfg b/cybersyn/locale/en/base.cfg index 9c42495..27d1aff 100644 --- a/cybersyn/locale/en/base.cfg +++ b/cybersyn/locale/en/base.cfg @@ -1,32 +1,26 @@ [mod-setting-name] cybersyn-ticks-per-second=Dispatcher ticks per second -cybersyn-requester-threshold=Default requester threshold -cybersyn-provider-threshold=Default provider threshold +cybersyn-request-threshold=Default requester threshold +cybersyn-provide-threshold=Default provider threshold [mod-setting-description] cybersyn-ticks-per-second=How many times per second to check all stations for possible deliveries. This value will be rounded up to a divisor of 60. -cybersyn-requester-threshold=When a requester threshold signal is not recieved by a station it will default to this value. -cybersyn-provider-threshold=When a provider threshold signal is not recieved by a station it will default to this value. +cybersyn-request-threshold=When a requester threshold signal is not recieved by a station it will default to this value. +cybersyn-provide-threshold=When a provider threshold signal is not recieved by a station it will default to this value. [item-name] -cybersyn-depot=Cybersyn depot -cybersyn-station=Cybersyn station +cybersyn-combinator=Cybernetic combinator [item-description] -cybersyn-depot=Cybersyn depot -cybersyn-station=Cybersyn station +cybersyn-combinator=Cybernetic combinator [entity-name] -cybersyn-depot=Cybersyn depot -cybersyn-station=Cybersyn station -cybersyn-station-out=Cybersyn station output -cybersyn-station-in=Cybersyn station input +cybersyn-combinator=Cybernetic combinator +cybersyn-combinator-output=NA [entity-description] -cybersyn-depot=Cybersyn depot -cybersyn-station=Cybersyn station -cybersyn-station-out=Cybersyn station output -cybersyn-station-in=Cybersyn station input +cybersyn-combinator=Cybersyn depot +cybersyn-combinator-output=NA [technology-name] cybersyn-train-network=Cybernetic train network @@ -36,6 +30,6 @@ cybersyn-train-network=Cybernetic train network [virtual-signal-name] cybersyn-priority=Station priority -cybersyn-p_threshold=Provide threshold -cybersyn-r_threshold=Request threshold +cybersyn-provide-threshold=Provide threshold +cybersyn-request-threshold=Request threshold cybersyn-locked-slots=Locked slots per cargo wagon diff --git a/cybersyn/prototypes/entity.lua b/cybersyn/prototypes/entity.lua index fc9fb6a..e9d08e4 100644 --- a/cybersyn/prototypes/entity.lua +++ b/cybersyn/prototypes/entity.lua @@ -1,39 +1,47 @@ --By Mami -cybersyn_station_entity = flib.copy_prototype(data.raw["train-stop"]["train-stop"], BUFFER_STATION_NAME) -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} +combinator_entity = flib.copy_prototype(data.raw["arithmetic-combinator"]["arithmetic-combinator"], COMBINATOR_NAME) +combinator_entity.icon = "__cybersyn__/graphics/icons/combinator.png" +combinator_entity.radius_visualisation_specification = { + sprite = { + filename = "__cybersyn__/graphics/icons/combinator.png", + tint = {r = 1, g = 1, b = .25, a = 1}, + height = 64, + width = 64, + }, + distance = 1, +} -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} +combinator_out_entity = flib.copy_prototype(data.raw["constant-combinator"]["constant-combinator"], COMBINATOR_OUT_NAME) +combinator_out_entity.icon = nil +combinator_out_entity.icon_size = nil +combinator_out_entity.icon_mipmaps = nil +combinator_out_entity.next_upgrade = nil +combinator_out_entity.minable = nil +combinator_out_entity.selection_box = nil +combinator_out_entity.collision_box = nil +combinator_out_entity.collision_mask = {} +combinator_out_entity.item_slot_count = 500 +combinator_out_entity.circuit_wire_max_distance = 3 +combinator_out_entity.flags = {"not-blueprintable", "not-deconstructable", "placeable-off-grid"} -cybersyn_station_in = flib.copy_prototype(data.raw["lamp"]["small-lamp"], STATION_IN_NAME) -cybersyn_station_in.icon = "__cybersyn__/graphics/icons/station.png" -cybersyn_station_in.icon_size = 64 -cybersyn_station_in.icon_mipmaps = 4 -cybersyn_station_in.next_upgrade = nil -cybersyn_station_in.minable = nil -cybersyn_station_in.selection_box = {{-0.5, -0.5}, {0.5, 0.5}} -cybersyn_station_in.selection_priority = 60 -cybersyn_station_in.collision_box = {{-0.15, -0.15}, {0.15, 0.15}} -cybersyn_station_in.collision_mask = {"rail-layer"} -cybersyn_station_in.energy_usage_per_tick = "10W" -cybersyn_station_in.light = {intensity = 1, size = 6} -cybersyn_station_in.energy_source = {type="void"} - -cybersyn_station_out = flib.copy_prototype(data.raw["constant-combinator"]["constant-combinator"],STATION_OUT_NAME) -cybersyn_station_out.icon = "__cybersyn__/graphics/icons/station.png" -cybersyn_station_out.icon_size = 64 -cybersyn_station_out.icon_mipmaps = 4 -cybersyn_station_out.next_upgrade = nil -cybersyn_station_out.minable = nil -cybersyn_station_out.selection_box = {{-0.5, -0.5}, {0.5, 0.5}} -cybersyn_station_out.selection_priority = 60 -cybersyn_station_out.collision_box = {{-0.15, -0.15}, {0.15, 0.15}} -cybersyn_station_out.collision_mask = {"rail-layer"} +local origin = {0.0, 0.0} +local invisible_sprite = {filename = "__cybersyn__/graphics/invisible.png", width = 1, height = 1} +local wire_con1 = { + red = origin, + green = origin +} +local wire_con0 = {wire = wire_con1, shadow = wire_con1} +combinator_out_entity.sprites = invisible_sprite +combinator_out_entity.activity_led_sprites = invisible_sprite +combinator_out_entity.activity_led_light = { + intensity = 0, + size = 0, +} +combinator_out_entity.activity_led_light_offsets = {origin, origin, origin, origin} +combinator_out_entity.draw_circuit_wires = false +combinator_out_entity.circuit_wire_connection_points = { + wire_con0, + wire_con0, + wire_con0, + wire_con0 +} diff --git a/cybersyn/prototypes/item.lua b/cybersyn/prototypes/item.lua index cbe919e..428db83 100644 --- a/cybersyn/prototypes/item.lua +++ b/cybersyn/prototypes/item.lua @@ -1,12 +1,6 @@ --By Mami -cybersyn_station_item = flib.copy_prototype(data.raw["item"]["train-stop"], BUFFER_STATION_NAME) -cybersyn_station_item.icon = "__cybersyn__/graphics/icons/station.png" -cybersyn_station_item.icon_size = 64 -cybersyn_station_item.icon_mipmaps = 4 -cybersyn_station_item.order = cybersyn_station_item.order.."-c" - -cybersyn_depot_item = flib.copy_prototype(data.raw["item"]["train-stop"], DEPOT_STATION_NAME) -cybersyn_depot_item.icon = "__cybersyn__/graphics/icons/depot.png" -cybersyn_depot_item.icon_size = 64 -cybersyn_depot_item.icon_mipmaps = 4 -cybersyn_depot_item.order = cybersyn_depot_item.order.."-d" +combinator_item = flib.copy_prototype(data.raw["item"]["arithmetic-combinator"], COMBINATOR_NAME) +combinator_item.icon = "__cybersyn__/graphics/icons/combinator.png" +combinator_item.icon_size = 64 +combinator_item.icon_mipmaps = 4 +combinator_item.order = combinator_item.order.."-c" diff --git a/cybersyn/prototypes/signal.lua b/cybersyn/prototypes/signal.lua index cc5a5e8..cbc8fff 100644 --- a/cybersyn/prototypes/signal.lua +++ b/cybersyn/prototypes/signal.lua @@ -1,11 +1,11 @@ --By Mami -cybersyn_subgroup = { +subgroup_signal = { type = "item-subgroup", name = "cybersyn-signal", group = "signals", order = "cybersyn0[cybersyn-signal]" } -cybersyn_priority = { +priority_signal = { type = "virtual-signal", name = SIGNAL_PRIORITY, icon = "__cybersyn__/graphics/icons/priority.png", @@ -13,23 +13,23 @@ cybersyn_priority = { subgroup = "cybersyn-signal", order = "a-a" } -cybersyn_p_threshold = { +p_threshold_signal = { type = "virtual-signal", name = PROVIDE_THRESHOLD, - icon = "__cybersyn__/graphics/icons/p_threshold.png", + icon = "__cybersyn__/graphics/icons/provide-threshold.png", icon_size = 64, subgroup = "cybersyn-signal", order = "a-b" } -cybersyn_r_threshold = { +r_threshold_signal = { type = "virtual-signal", name = REQUEST_THRESHOLD, - icon = "__cybersyn__/graphics/icons/r_threshold.png", + icon = "__cybersyn__/graphics/icons/request-threshold.png", icon_size = 64, subgroup = "cybersyn-signal", order = "a-c" } -cybersyn_locked_slots = { +locked_slots_signal = { type = "virtual-signal", name = LOCKED_SLOTS, icon = "__cybersyn__/graphics/icons/locked_slots.png", diff --git a/cybersyn/prototypes/tech.lua b/cybersyn/prototypes/tech.lua index fa7c661..e787109 100644 --- a/cybersyn/prototypes/tech.lua +++ b/cybersyn/prototypes/tech.lua @@ -1,17 +1,10 @@ --By Mami -cybersyn_station_recipe = flib.copy_prototype(data.raw["recipe"]["train-stop"], BUFFER_STATION_NAME) -cybersyn_station_recipe.ingredients = { - {"train-stop", 1}, +combinator_recipe = flib.copy_prototype(data.raw["recipe"]["train-stop"], COMBINATOR_NAME) +combinator_recipe.ingredients = { + {"copper-cable", 5}, {"advanced-circuit", 5}, } -cybersyn_station_recipe.enabled = false - -cybersyn_depot_recipe = flib.copy_prototype(data.raw["recipe"]["train-stop"], DEPOT_STATION_NAME) -cybersyn_depot_recipe.ingredients = { - {"train-stop", 1}, - {"electronic-circuit", 5}, -} -cybersyn_depot_recipe.enabled = false +combinator_recipe.enabled = false cybersyn_tech = { type = "technology", @@ -27,11 +20,7 @@ cybersyn_tech = { effects = { { type = "unlock-recipe", - recipe = BUFFER_STATION_NAME - }, - { - type = "unlock-recipe", - recipe = DEPOT_STATION_NAME + recipe = COMBINATOR_NAME }, }, unit = { @@ -39,7 +28,7 @@ cybersyn_tech = { {"automation-science-pack", 1}, {"logistic-science-pack", 1} }, - count = 300, + count = 400, time = 30 }, order = "c-g-c" diff --git a/cybersyn/scripts/constants.lua b/cybersyn/scripts/constants.lua index ca80e9e..86cd4e2 100644 --- a/cybersyn/scripts/constants.lua +++ b/cybersyn/scripts/constants.lua @@ -1,14 +1,17 @@ --By Mami SIGNAL_PRIORITY = "cybersyn-priority" -REQUEST_THRESHOLD = "cybersyn-r_threshold" -PROVIDE_THRESHOLD = "cybersyn-p_threshold" +REQUEST_THRESHOLD = "cybersyn-request-threshold" +PROVIDE_THRESHOLD = "cybersyn-provide-threshold" LOCKED_SLOTS = "cybersyn-locked-slots" -STATION_IN_NAME = "cybersyn-station-in" -STATION_OUT_NAME = "cybersyn-station-out" -BUFFER_STATION_NAME = "cybersyn-station" -DEPOT_STATION_NAME = "cybersyn-depot" +COMBINATOR_NAME = "cybersyn-combinator" +COMBINATOR_OUT_NAME = "cybersyn-combinator-output" + +OPERATION_PRIMARY_IO = "*" +OPERATION_SECONDARY_IO = "/" +OPERATION_DEPOT = "+" +OPERATION_WAGON_MANIFEST = "-" DELTA = 1/2048 diff --git a/cybersyn/scripts/controller.lua b/cybersyn/scripts/controller.lua index 045f40f..cc8fbe9 100644 --- a/cybersyn/scripts/controller.lua +++ b/cybersyn/scripts/controller.lua @@ -54,20 +54,76 @@ function create_manifest_schedule(depot_name, p_stop, r_stop, manifest) end - local function get_signals(station) - local signals = station.entity_in.get_merged_signals() - return signals + if station.comb1.valid then + local signals = station.comb1.get_merged_signals(defines.circuit_connector_id.combinator_input) + return signals + else + return nil + end +end + +function set_combinator_output(map_data, comb, signals) + if comb.valid then + local out = map_data.to_output[comb.unit_number] + if out.valid then + out.get_or_create_control_behavior().parameters = signals + else + --TODO: error logging? + end + else + --TODO: error logging? + end +end + +local function set_comb2(map_data, station) + if station.comb2 then + local deliveries = station.deliveries + local signals = {} + for item_name, count in pairs(deliveries) do + local i = #signals + 1 + local item_type = game.item_prototypes[item_name].type + signals[i] = {index = i, signal = {type = item_type, name = item_name}, count = count} + end + set_combinator_output(map_data, station.comb2, signals) + end +end + +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 + +local function get_thresholds(map_data, station, signal) + local comb2 = station.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 station.r_threshold, count + elseif count < 0 then + return -count, station.p_threshold + end + end + return station.r_threshold, station.p_threshold end local function get_stop_dist(stop0, stop1) return get_distance(stop0.position, stop1.position) end + local function station_accepts_layout(station, layout_id) return true end + local function get_valid_train(map_data, r_station_id, p_station_id, item_type) --NOTE: this code is the critical section for run-time optimization local r_station = map_data.stations[r_station_id] @@ -113,6 +169,7 @@ local function get_valid_train(map_data, r_station_id, p_station_id, item_type) end end + local function send_train_between(map_data, r_station_id, p_station_id, train, primary_item_name, economy) local r_station = map_data.stations[r_station_id] local p_station = map_data.stations[p_station_id] @@ -128,7 +185,8 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p 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] or 0) - if -effective_item_count >= r_station.r_threshold then + local r_threshold, p_threshold = get_thresholds(map_data, r_station, v) + if -effective_item_count >= r_threshold then requests[item_name] = -effective_item_count end end @@ -143,7 +201,8 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p 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] or 0) - if effective_item_count >= p_station.p_threshold then + local r_threshold, p_threshold = get_thresholds(map_data, r_station, v) + if effective_item_count >= p_threshold then local r = requests[item_name] if r then local item = {name = item_name, count = math.min(r, effective_item_count), type = item_type} @@ -230,6 +289,8 @@ local function send_train_between(map_data, r_station_id, p_station_id, train, p train.manifest = manifest train.entity.schedule = create_manifest_schedule(train.depot_name, p_station.entity, r_station.entity, manifest) + set_comb2(map_data, p_station) + set_comb2(map_data, r_station) end @@ -279,8 +340,9 @@ function tick(map_data, mod_settings) local item_name = v.signal.name local item_count = v.count local effective_item_count = item_count + (station.deliveries[item_name] or 0) + local r_threshold, p_threshold = get_thresholds(map_data, station, v) - if -effective_item_count >= station.r_threshold then + if -effective_item_count >= r_threshold then if r_stations_all[item_name] == nil then r_stations_all[item_name] = {} p_stations_all[item_name] = {} @@ -288,7 +350,7 @@ function tick(map_data, mod_settings) all_items[#all_items + 1] = v.signal.type end table.insert(r_stations_all[item_name], station_id) - elseif effective_item_count >= station.p_threshold then + elseif effective_item_count >= p_threshold then if r_stations_all[item_name] == nil then r_stations_all[item_name] = {} p_stations_all[item_name] = {} diff --git a/cybersyn/scripts/global.lua b/cybersyn/scripts/global.lua index d5d8dae..5404611 100644 --- a/cybersyn/scripts/global.lua +++ b/cybersyn/scripts/global.lua @@ -4,7 +4,10 @@ global: { total_ticks: int layout_top_id: int + to_output: {[comb_unit_number]: LuaEntity} + to_stop: {[comb_unit_number]: LuaEntity} stations: {[stop_id]: Station} + depots: {[stop_id]: LuaEntity} trains: {[train_id]: Train} trains_available: {[train_id]: bool} layouts: {[layout_id]: Layout} @@ -18,12 +21,16 @@ Station: { r_threshold: int >= 0 p_threshold: int >= 0 locked_slots: int >= 0 - entity: LuaEntity - entity_in: LuaEntity - entity_out: LuaEntity + entity_stop: LuaEntity + entity_comb1: LuaEntity + entity_comb2: LuaEntity? + wagon_combs: {[int]: LuaEntity}--allowed to be invalid entities deliveries: { [item_name]: int } + deliveries: { + [item_name]: item-type + } train_class: string accepted_layouts: TrainClass layout_pattern: string|nil @@ -51,11 +58,13 @@ Layout: string --TODO: only init once mod_settings = {} mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value -mod_settings.r_threshold = settings.global["cybersyn-requester-threshold"].value -mod_settings.p_threshold = settings.global["cybersyn-provider-threshold"].value +mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value +mod_settings.p_threshold = settings.global["cybersyn-provide-threshold"].value global.total_ticks = 0 +global.to_output = {} global.stations = {} +global.depots = {} global.trains = {} global.trains_available = {} global.layouts = {} diff --git a/cybersyn/scripts/main.lua b/cybersyn/scripts/main.lua index e428922..a1b1315 100644 --- a/cybersyn/scripts/main.lua +++ b/cybersyn/scripts/main.lua @@ -1,38 +1,21 @@ --By Mami -local function set_station_output_empty(station) - --change circuit outputs - station.entity_out.get_control_behavior().parameters = nil -end - local function on_failed_delivery(map_data, train) --NOTE: must change train status to STATUS_D or remove it from tracked trains after this call 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 + remove_manifest(map_data, station, train.manifest, 1) if train.status == STATUS_P then - set_station_output_empty(station) + set_combinator_output(map_data, station.comb1, nil) end 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 + remove_manifest(map_data, station, train.manifest, -1) if train.status == STATUS_R then - set_station_output_empty(station) + set_combinator_output(map_data, station.comb1, nil) end end train.r_station_id = 0 @@ -40,91 +23,12 @@ local function on_failed_delivery(map_data, train) train.manifest = nil end -local function on_station_built(map_data, stop) - local pos_x = stop.position.x - local pos_y = stop.position.y - - local in_pos - local out_pos - local search_area - if stop.direction == 0 then - in_pos = {pos_x, pos_y - 1} - out_pos = {pos_x - 1, pos_y - 1} - search_area = { - {pos_x + DELTA - 1, pos_y + DELTA - 1}, - {pos_x - DELTA + 1, pos_y - DELTA} - } - elseif stop.direction == 2 then - in_pos = {pos_x, pos_y} - out_pos = {pos_x, pos_y - 1} - search_area = { - {pos_x + DELTA, pos_y + DELTA - 1}, - {pos_x - DELTA + 1, pos_y - DELTA + 1} - } - elseif stop.direction == 4 then - in_pos = {pos_x - 1, pos_y} - out_pos = {pos_x, pos_y} - search_area = { - {pos_x + DELTA - 1, pos_y + DELTA}, - {pos_x - DELTA + 1, pos_y - DELTA + 1} - } - elseif stop.direction == 6 then - in_pos = {pos_x - 1, pos_y - 1} - out_pos = {pos_x - 1, pos_y} - search_area = { - {pos_x + DELTA - 1, pos_y + DELTA - 1}, - {pos_x - DELTA, pos_y - DELTA + 1} - } - else - assert(false, "cybersyn: invalid direction of train stop") - end - - local entity_in = nil - local entity_out = nil - local entities = stop.surface.find_entities(search_area) - for _, cur_entity in pairs(entities) do - if cur_entity.valid then - if cur_entity.name == "entity-ghost" then - if cur_entity.ghost_name == STATION_IN_NAME then - _, entity_in = cur_entity.silent_revive() - elseif cur_entity.ghost_name == STATION_OUT_NAME then - _, entity_out = cur_entity.silent_revive() - end - elseif cur_entity.name == STATION_IN_NAME then - entity_in = cur_entity - elseif cur_entity.name == STATION_OUT_NAME then - entity_out = cur_entity - end - end - end - - if entity_in == nil then - entity_in = stop.surface.create_entity({ - name = STATION_IN_NAME, - position = in_pos, - force = stop.force - }) - end - entity_in.operable = false - entity_in.minable = false - entity_in.destructible = false - - if entity_out == nil then - entity_out = stop.surface.create_entity({ - name = STATION_OUT_NAME, - position = out_pos, - direction = stop.direction, - force = stop.force - }) - end - entity_out.operable = false - entity_out.minable = false - entity_out.destructible = false - +local function on_station_built(map_data, stop, comb1, comb2) local station = { - entity = stop, - entity_in = entity_in, - entity_out = entity_out, + entity_stop = stop, + entity_comb1 = comb1, + entity_comb2 = comb2, + wagon_combs = nil, deliveries_total = 0, last_delivery_tick = 0, priority = 0, @@ -140,11 +44,9 @@ local function on_station_built(map_data, stop) update_station_if_auto(map_data, 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] +local function on_station_broken(map_data, station_id, station) if station.deliveries_total > 0 then + --search for trains coming to the destroyed station for train_id, train in pairs(map_data.trains) do local is_r = train.r_station_id == station_id local is_p = train.p_station_id == station_id @@ -161,13 +63,226 @@ local function on_station_broken(map_data, stop) 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 +local function search_for_station_combinator(map_data, stop, comb_operation, comb_forbidden) + local pos_x = stop.position.x + local pos_y = stop.position.y + --TODO: fix search area + local search_area = { + {pos_x + DELTA - 1, pos_y + DELTA - 1}, + {pos_x - DELTA + 1, pos_y - DELTA + 1} + } + local entities = stop.surface.find_entities(search_area) + for _, entity in pairs(entities) do + if + entity.valid and entity.name == COMBINATOR_NAME and + entity ~= comb_forbidden and map_data.to_stop[entity.unit_number] == stop + then + local control = entity.get_or_create_control_behavior().parameters + if control.operation == comb_operation then + return entity + end + end + end +end + +local function on_combinator_built(map_data, comb) + local pos_x = comb.position.x + local pos_y = comb.position.y + + --TODO: fix search area + local search_area = { + {pos_x + DELTA - 1, pos_y + DELTA - 1}, + {pos_x - DELTA + 1, pos_y - DELTA + 1} + } + local stop = nil + local rail = nil + local entities = stop.surface.find_entities(search_area) + for _, cur_entity in pairs(entities) do + if cur_entity.valid then + if cur_entity.name == "train-stop" then + --NOTE: if there are multiple stops we take the later one + stop = cur_entity + elseif cur_entity.name == "rail-straight" then + rail = cur_entity + end + end + end + + local out = comb.surface.create_entity({ + name = COMBINATOR_OUT_NAME, + position = comb.position, + force = comb.force + }) + comb.connect_neighbour({ + target_entity = out, + source_wire_id = defines.circuit_connector_id.combinator_output, + wire = defines.wire_type.green, + }) + comb.connect_neighbour({ + target_entity = out, + source_wire_id = defines.circuit_connector_id.combinator_output, + wire = defines.wire_type.red, + }) + + map_data.to_output[comb.unit_number] = out + map_data.to_stop[comb.unit_number] = stop + + local control = comb.get_or_create_control_behavior().parameters + if control.operation == OPERATION_WAGON_MANIFEST then + if rail then + update_station_from_rail(map_data, rail) + end + elseif control.operation == OPERATION_DEPOT then + if stop then + local station = map_data.stations[stop.unit_number] + local depot_comb = map_data.depots[stop.unit_number] + if depot_comb or station then + --NOTE: repeated combinators are ignored + else + map_data.depots[stop.unit_number] = comb + end + end + elseif control.operation == OPERATION_SECONDARY_IO then + if stop then + local station = map_data.stations[stop.unit_number] + if station and not station.entity_comb2 then + station.entity_comb2 = comb + end + end + elseif stop then + control.operation = OPERATION_PRIMARY_IO + local station = map_data.stations[stop.unit_number] + local depot_comb = map_data.depots[stop.unit_number] + if station then + --NOTE: repeated combinators are ignored + else + if depot_comb then + --NOTE: this will disrupt deliveries in progress that where dispatched from this station in a minor way + map_data.depots[stop.unit_number] = nil + end + --no station or depot + --add station + + local comb2 = search_for_station_combinator(map_data, stop, OPERATION_SECONDARY_IO, nil) + + station = { + entity_stop = stop, + entity_comb1 = comb, + entity_comb2 = comb2, + wagon_combs = nil, + deliveries_total = 0, + last_delivery_tick = 0, + priority = 0, + r_threshold = 0, + p_threshold = 0, + locked_slots = 0, + deliveries = {}, + train_class = TRAIN_CLASS_AUTO, + accepted_layouts = {}, + layout_pattern = nil, + } + map_data.stations[stop.unit_number] = station + + update_station_if_auto(map_data, station) + end + end +end +local function on_combinator_broken(map_data, comb) + local out = map_data.to_output[comb.unit_number] + local stop = map_data.to_stop[comb.unit_number] + + if stop and stop.valid then + local station = map_data.stations[stop.unit_number] + if station then + if station.comb1 == comb then + local comb1 = search_for_station_combinator(map_data, stop, OPERATION_PRIMARY_IO, comb) + if comb1 then + station.comb1 = comb1 + else + on_station_broken(map_data, stop.unit_number, station) + map_data.depots[stop.unit_number] = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, nil) + end + elseif station.comb2 == comb then + station.comb2 = search_for_station_combinator(map_data, stop, OPERATION_SECONDARY_IO, comb) + end + else + local depot_comb = map_data.depots[stop.unit_number] + if depot_comb == comb then + --NOTE: this will disrupt deliveries in progress that where dispatched from this station in a minor way + map_data.depots[stop.unit_number] = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb) + end + end + end + + if out and out.valid then + out.destroy() + end + map_data.to_output[comb.unit_number] = nil + map_data.to_stop[comb.unit_number] = nil +end +local function on_combinator_updated(map_data, comb) + --NOTE: this is the lazy way to implement updates and is not robust + on_combinator_broken(map_data, comb) + on_combinator_built(map_data, comb) +end + +local function on_stop_built(map_data, stop) + local pos_x = stop.position.x + local pos_y = stop.position.y + + --TODO: fix search area + local search_area = { + {pos_x + DELTA - 1, pos_y + DELTA - 1}, + {pos_x - DELTA + 1, pos_y - DELTA + 1} + } + local comb2 = nil + local comb1 = nil + local depot_comb = nil + local entities = stop.surface.find_entities(search_area) + for _, entity in pairs(entities) do + if entity.valid and entity.name == COMBINATOR_NAME and map_data.to_stop[entity.unit_number] == nil then + map_data.to_stop[entity.unit_number] = stop + local control = entity.get_or_create_control_behavior().parameters + if control.operation == OPERATION_PRIMARY_IO then + comb1 = entity + elseif control.operation == OPERATION_SECONDARY_IO then + comb2 = entity + elseif control.operation == OPERATION_DEPOT then + depot_comb = entity + end + end + end + if comb1 then + on_station_built(map_data, stop, comb1, comb2) + elseif depot_comb then + map_data.depots[stop.unit_number] = depot_comb + end +end +local function on_stop_broken(map_data, stop) + local pos_x = stop.position.x + local pos_y = stop.position.y + + --TODO: fix search area + local search_area = { + {pos_x + DELTA - 1, pos_y + DELTA - 1}, + {pos_x - DELTA + 1, pos_y - DELTA + 1} + } + local entities = stop.surface.find_entities(search_area) + for _, entity in pairs(entities) do + if map_data.to_stop[entity.unit_number] == stop then + map_data.to_stop[entity.unit_number] = nil + end + end + + local station = map_data.stations[stop.unit_number] + if station then + on_station_broken(map_data, stop.unit_number, station) + end + map_data.depots[stop.unit_number] = nil +end local function on_station_rename(map_data, stop) --search for trains coming to the renamed station local station_id = stop.unit_number @@ -193,24 +308,18 @@ local function on_station_rename(map_data, stop) end -local function find_and_add_all_stations(map_data) +local function find_and_add_all_stations_from_nothing(map_data) for _, surface in pairs(game.surfaces) do - local stops = surface.find_entities_filtered({type="train-stop"}) - if stops then - for k, stop in pairs(stops) do - if stop.name == BUFFER_STATION_NAME then - local station = map_data.stations[stop.unit_number] - if not station then - on_station_built(map_data, stop) - end - end + local entities = surface.find_entities_filtered({name = COMBINATOR_NAME}) + for k, comb in pairs(entities) do + if comb.valid then + on_combinator_built(map_data, comb) end end end end - local function on_train_arrives_depot(map_data, train_entity) local train = map_data.trains[train_entity.id] if train then @@ -251,15 +360,15 @@ local function on_train_arrives_depot(map_data, train_entity) r_station_id = 0, manifest = nil, } - update_train_layout(global, train) + update_train_layout(map_data, 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 - -local function on_train_arrives_buffer(map_data, station_id, train) +local function on_train_arrives_buffer(map_data, stop, train) + local station_id = stop.unit_number if train.manifest then if train.status == STATUS_D_TO_P then if train.p_station_id == station_id then @@ -270,7 +379,7 @@ local function on_train_arrives_buffer(map_data, station_id, train) for i, item in ipairs(train.manifest) do signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = item.count} end - station.entity_out.get_control_behavior().parameters = signals + set_combinator_output(map_data, station.comb1, signals) end elseif train.status == STATUS_P_TO_R then if train.r_station_id == station_id then @@ -281,7 +390,7 @@ local function on_train_arrives_buffer(map_data, station_id, train) for i, item in ipairs(train.manifest) do signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = -1} end - station.entity_out.get_control_behavior().parameters = signals + set_combinator_output(map_data, station.comb1, signals) end else on_failed_delivery(map_data, train) @@ -293,31 +402,18 @@ local function on_train_arrives_buffer(map_data, station_id, train) remove_train(map_data, train, train.entity.id) end end - 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 - set_station_output_empty(station) + remove_manifest(map_data, station, train.manifest, 1) + set_combinator_output(map_data, station.comb1, nil) 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 - set_station_output_empty(station) + remove_manifest(map_data, station, train.manifest, -1) + set_combinator_output(map_data, station.comb1, nil) end end end @@ -331,7 +427,6 @@ local function on_train_broken(map_data, train) end 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 @@ -347,8 +442,6 @@ local function on_train_modified(map_data, pre_train_id, train_entity) end - - local function on_tick(event) tick(global, mod_settings) global.total_ticks = global.total_ticks + 1 @@ -358,8 +451,10 @@ local function on_built(event) local entity = event.entity or event.created_entity or event.destination if not entity or not entity.valid then return end - if entity.name == BUFFER_STATION_NAME then - on_station_built(global, entity) + if entity.name == "train-stop" then + on_stop_built(global, entity) + elseif entity.name == COMBINATOR_NAME then + on_combinator_built(global, entity) elseif entity.type == "inserter" then update_station_from_inserter(global, entity) elseif entity.type == "pump" then @@ -377,10 +472,11 @@ local function on_broken(event) if train then on_train_broken(global, train) end - elseif entity.name == BUFFER_STATION_NAME then - on_station_broken(global, entity) + elseif entity.name == "train-stop" then + on_stop_broken(global, entity) + elseif entity.name == COMBINATOR_NAME then + on_combinator_broken(global, entity) elseif entity.type == "inserter" then - --NOTE: check if this works or if it needs to be delayed update_station_from_inserter(global, entity) elseif entity.type == "pump" then update_station_from_pump(global, entity) @@ -388,22 +484,9 @@ local function on_broken(event) update_station_from_rail(global, entity) end 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 and train_e.station ~= nil then - if train_e.station.name == DEPOT_STATION_NAME then - on_train_arrives_depot(global, train_e) - elseif train_e.station.name == BUFFER_STATION_NAME then - if train then - on_train_arrives_buffer(global, train_e.station.unit_number, train) - end - end - elseif event.old_state == defines.train_state.wait_station then - if train then - on_train_leaves_station(global, train) - end +local function on_rename(event) + if event.entity.name == "train-stop" then + on_station_rename(global, event.entity) end end @@ -416,33 +499,48 @@ local function on_train_built(event) on_train_modified(global, event.old_train_id_2, train_e) end 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.name == "train-stop" then + if global.stations[stop.unit_number] then + on_train_arrives_buffer(global, stop, train) + elseif global.depots[stop.unit_number] then + on_train_arrives_depot(global, train_e) + end + end + elseif event.old_state == defines.train_state.wait_station then + if train then + on_train_leaves_station(global, train) + end + 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 + if entity.name == "train-stop" then on_station_broken(global, entity) end end end end -local function on_rename(event) - if event.entity.name == BUFFER_STATION_NAME then - on_station_rename(global, event.entity) - end -end local filter_built = { {filter = "type", type = "train-stop"}, + {filter = "type", type = "arithmetic-combinator"}, {filter = "type", type = "inserter"}, {filter = "type", type = "pump"}, {filter = "type", type = "straight-rail"}, } local filter_broken = { {filter = "type", type = "train-stop"}, + {filter = "type", type = "arithmetic-combinator"}, {filter = "type", type = "inserter"}, {filter = "type", type = "pump"}, {filter = "type", type = "straight-rail"}, @@ -477,12 +575,12 @@ end) script.on_init(function() --TODO: we are not checking changed cargo capacities - find_and_add_all_stations(global) + --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) + --find_and_add_all_stations(global) register_events() end) diff --git a/cybersyn/settings.lua b/cybersyn/settings.lua index 8de42a3..be2a1c9 100644 --- a/cybersyn/settings.lua +++ b/cybersyn/settings.lua @@ -1,4 +1,4 @@ ---By cybersyn +--By Mami data:extend({ { type = "int-setting", @@ -11,7 +11,7 @@ data:extend({ }, { type = "int-setting", - name = "cybersyn-requester-threshold", + name = "cybersyn-request-threshold", order = "ab", setting_type = "runtime-global", default_value = 1000000000, @@ -20,7 +20,7 @@ data:extend({ }, { type = "int-setting", - name = "cybersyn-provider-threshold", + name = "cybersyn-provide-threshold", order = "ac", setting_type = "runtime-global", default_value = 1000000000,