Merge pull request #1 from mamoniot/combinator
switching to combinator architecture
@@ -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
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
--By Mami
|
||||
|
||||
require("scripts.constants")
|
||||
require("scripts.global")
|
||||
require("scripts.controller")
|
||||
require("scripts.layout")
|
||||
require("scripts.gui")
|
||||
require("scripts.main")
|
||||
|
||||
@@ -6,20 +6,20 @@ require('prototypes.item')
|
||||
require('prototypes.tech')
|
||||
require('prototypes.entity')
|
||||
require('prototypes.signal')
|
||||
require('prototypes.misc')
|
||||
|
||||
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,
|
||||
missing_train_icon,
|
||||
lost_train_icon,
|
||||
nonempty_train_icon,
|
||||
})
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 505 B |
@@ -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,19 @@ 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
|
||||
|
||||
[cybersyn-messages]
|
||||
missing-trains=No trains available to make a delivery from station __2__ to station __1__
|
||||
lost-train=A train has become lost
|
||||
nonempty-train=A train has parked in a depot while still containing items; it cannot be dispatched until it is empty
|
||||
|
||||
[cybersyn-gui]
|
||||
operation=Choose combinator type
|
||||
comb1=Primary controller
|
||||
comb2=Secondary station control
|
||||
depot=Depot
|
||||
wagon-manifest=Wagon
|
||||
combinator-title=Cybernetic combinator
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
missing_train_icon = flib.copy_prototype(data.raw["fluid"]["water"], MISSING_TRAIN_NAME)
|
||||
missing_train_icon.icon = "__cybersyn__/graphics/icons/missing-train.png"
|
||||
missing_train_icon.icon_size = 64
|
||||
missing_train_icon.icon_mipmaps = 0
|
||||
missing_train_icon.hidden = true
|
||||
missing_train_icon.auto_barrel = false
|
||||
missing_train_icon.subgroup = "cybersyn-signal"
|
||||
|
||||
lost_train_icon = flib.copy_prototype(data.raw["fluid"]["water"], LOST_TRAIN_NAME)
|
||||
lost_train_icon.icon = "__cybersyn__/graphics/icons/lost-train.png"
|
||||
lost_train_icon.icon_size = 64
|
||||
lost_train_icon.icon_mipmaps = 0
|
||||
lost_train_icon.hidden = true
|
||||
lost_train_icon.auto_barrel = false
|
||||
lost_train_icon.subgroup = "cybersyn-signal"
|
||||
|
||||
nonempty_train_icon = flib.copy_prototype(data.raw["fluid"]["water"], NONEMPTY_TRAIN_NAME)
|
||||
nonempty_train_icon.icon = "__cybersyn__/graphics/icons/nonempty-train.png"
|
||||
nonempty_train_icon.icon_size = 64
|
||||
nonempty_train_icon.icon_mipmaps = 0
|
||||
nonempty_train_icon.hidden = true
|
||||
nonempty_train_icon.auto_barrel = false
|
||||
nonempty_train_icon.subgroup = "cybersyn-signal"
|
||||
@@ -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,26 +13,26 @@ 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",
|
||||
icon = "__cybersyn__/graphics/icons/locked-slots.png",
|
||||
icon_size = 64,
|
||||
subgroup = "cybersyn-signal",
|
||||
order = "a-d"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
--By Mami
|
||||
|
||||
local send_missing_train_alert_for_stop_icon = {name = MISSING_TRAIN_NAME, type = "fluid"}
|
||||
---@param r_stop LuaEntity
|
||||
---@param p_stop LuaEntity
|
||||
function send_missing_train_alert_for_stops(r_stop, p_stop)
|
||||
for _, player in pairs(r_stop.force.players) do
|
||||
player.add_custom_alert(
|
||||
r_stop,
|
||||
send_missing_train_alert_for_stop_icon,
|
||||
{"cybersyn-messages.missing-trains", r_stop.backer_name, p_stop.backer_name},
|
||||
true
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"}
|
||||
---@param train LuaTrain
|
||||
function send_lost_train_alert(train)
|
||||
local loco = train.front_stock or train.back_stock
|
||||
if loco then
|
||||
for _, player in pairs(loco.force.players) do
|
||||
player.add_custom_alert(
|
||||
loco,
|
||||
send_lost_train_alert_icon,
|
||||
{"cybersyn-messages.lost-train"},
|
||||
true
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"}
|
||||
---@param train LuaTrain
|
||||
function send_nonempty_train_in_depot_alert(train)
|
||||
local loco = train.front_stock or train.back_stock
|
||||
if loco then
|
||||
for _, player in pairs(loco.force.players) do
|
||||
player.add_custom_alert(
|
||||
loco,
|
||||
send_nonempty_train_in_depot_alert_icon,
|
||||
{"cybersyn-messages.nonempty-train"},
|
||||
true
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,14 +1,21 @@
|
||||
--By Mami
|
||||
|
||||
MISSING_TRAIN_NAME = "cybersyn-missing-train"
|
||||
LOST_TRAIN_NAME = "cybersyn-lost-train"
|
||||
NONEMPTY_TRAIN_NAME = "cybersyn-nonempty-train"
|
||||
|
||||
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
|
||||
|
||||
@@ -23,13 +30,12 @@ TRAIN_LAYOUT_NA = "N"
|
||||
TRAIN_LAYOUT_CARGO = "C"
|
||||
TRAIN_LAYOUT_FLUID = "F"
|
||||
--TRAIN_LAYOUT_ARTILLERY = "A"
|
||||
|
||||
STATION_LAYOUT_NA = "N"
|
||||
STATION_LAYOUT_CARGO = "C"
|
||||
STATION_LAYOUT_FLUID = "F"
|
||||
STATION_LAYOUT_BOTH = "."
|
||||
STATION_LAYOUT_ALL = "."
|
||||
STATION_LAYOUT_NOT_FLUID = "[NC]"
|
||||
STATION_LAYOUT_NOT_CARGO = "[NF]"
|
||||
|
||||
LONGEST_INSERTER_REACH = 2
|
||||
|
||||
TRAIN_CLASS_ALL = "all"
|
||||
TRAIN_CLASS_AUTO = "auto"
|
||||
TRAIN_CLASS_ALL = {name = "all", type = "virtual"}
|
||||
TRAIN_CLASS_AUTO = {name = "auto", type = "virtual"}
|
||||
|
||||
@@ -4,6 +4,8 @@ local math = math
|
||||
local INF = math.huge
|
||||
|
||||
local create_loading_order_condition = {type = "inactivity", compare_type = "and", ticks = 120}
|
||||
---@param stop LuaEntity
|
||||
---@param manifest Manifest
|
||||
function create_loading_order(stop, manifest)
|
||||
local condition = {}
|
||||
for _, item in ipairs(manifest) do
|
||||
@@ -25,24 +27,31 @@ function create_loading_order(stop, manifest)
|
||||
end
|
||||
|
||||
local create_unloading_order_condition = {{type = "empty", compare_type = "and"}}
|
||||
---@param stop LuaEntity
|
||||
function create_unloading_order(stop)
|
||||
return {station = stop.backer_name, wait_conditions = create_unloading_order_condition}
|
||||
end
|
||||
|
||||
local create_inactivity_order_condition = {{type = "inactivity", compare_type = "and", ticks = 120}}
|
||||
---@param depot_name string
|
||||
function create_inactivity_order(depot_name)
|
||||
return {station = depot_name, wait_conditions = create_inactivity_order_condition}
|
||||
end
|
||||
|
||||
local create_direct_to_station_order_condition = {{type = "time", compare_type = "and", ticks = 0}}
|
||||
---@param stop LuaEntity
|
||||
local function create_direct_to_station_order(stop)
|
||||
return {rail = stop.connected_rail, rail_direction = stop.connected_rail_direction}
|
||||
end
|
||||
|
||||
---@param depot_name string
|
||||
function create_depot_schedule(depot_name)
|
||||
return {current = 1, records = {create_inactivity_order(depot_name)}}
|
||||
end
|
||||
|
||||
---@param depot_name string
|
||||
---@param p_stop LuaEntity
|
||||
---@param r_stop LuaEntity
|
||||
---@param manifest Manifest
|
||||
function create_manifest_schedule(depot_name, p_stop, r_stop, manifest)
|
||||
return {current = 1, records = {
|
||||
create_inactivity_order(depot_name),
|
||||
@@ -53,27 +62,103 @@ function create_manifest_schedule(depot_name, p_stop, r_stop, manifest)
|
||||
}}
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param station Station
|
||||
local function get_signals(station)
|
||||
local signals = station.entity_in.get_merged_signals()
|
||||
return signals
|
||||
if station.entity_comb1.valid then
|
||||
local signals = station.entity_comb1.get_merged_signals(defines.circuit_connector_id.combinator_input)
|
||||
return signals
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param comb LuaEntity
|
||||
---@param signals ConstantCombinatorParameters[]?
|
||||
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
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
local function set_comb2(map_data, station)
|
||||
if station.entity_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.entity_comb2, signals)
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param manifest Manifest
|
||||
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
|
||||
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param signal SignalID
|
||||
local function get_thresholds(map_data, station, signal)
|
||||
local comb2 = station.entity_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
|
||||
|
||||
---@param stop0 LuaEntity
|
||||
---@param stop1 LuaEntity
|
||||
local function get_stop_dist(stop0, stop1)
|
||||
return get_distance(stop0.position, stop1.position)
|
||||
end
|
||||
|
||||
|
||||
---@param station Station
|
||||
---@param layout_id uint
|
||||
local function station_accepts_layout(station, layout_id)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param r_station_id uint
|
||||
---@param p_station_id uint
|
||||
---@param item_type string
|
||||
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]
|
||||
local p_station = map_data.stations[p_station_id]
|
||||
|
||||
local p_to_r_dist = get_stop_dist(p_station.entity, r_station.entity)
|
||||
local p_to_r_dist = get_stop_dist(p_station.entity_stop, r_station.entity_stop)
|
||||
if p_to_r_dist == INF then
|
||||
return nil, INF
|
||||
end
|
||||
@@ -96,7 +181,7 @@ local function get_valid_train(map_data, r_station_id, p_station_id, item_type)
|
||||
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.station, p_station.entity)
|
||||
local d_to_p_dist = get_stop_dist(train.entity.station, p_station.entity_stop)
|
||||
|
||||
local dist = d_to_p_dist
|
||||
if dist < best_dist then
|
||||
@@ -113,6 +198,13 @@ local function get_valid_train(map_data, r_station_id, p_station_id, item_type)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param r_station_id uint
|
||||
---@param p_station_id uint
|
||||
---@param train Train
|
||||
---@param primary_item_name string
|
||||
---@param economy Economy
|
||||
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 +220,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.signal)
|
||||
if -effective_item_count >= r_threshold then
|
||||
requests[item_name] = -effective_item_count
|
||||
end
|
||||
end
|
||||
@@ -143,7 +236,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.signal)
|
||||
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}
|
||||
@@ -229,10 +323,12 @@ 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
|
||||
|
||||
train.entity.schedule = create_manifest_schedule(train.depot_name, p_station.entity, r_station.entity, manifest)
|
||||
train.entity.schedule = create_manifest_schedule(train.depot_name, p_station.entity_stop, r_station.entity_stop, manifest)
|
||||
set_comb2(map_data, p_station)
|
||||
set_comb2(map_data, r_station)
|
||||
end
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
function tick(map_data, mod_settings)
|
||||
local total_ticks = map_data.total_ticks
|
||||
local stations = map_data.stations
|
||||
@@ -247,7 +343,7 @@ function tick(map_data, mod_settings)
|
||||
local all_items = economy.all_items
|
||||
|
||||
for station_id, station in pairs(stations) do
|
||||
if station.deliveries_total < station.entity.trains_limit then
|
||||
if station.deliveries_total < station.entity_stop.trains_limit then
|
||||
station.r_threshold = mod_settings.r_threshold
|
||||
station.p_threshold = mod_settings.p_threshold
|
||||
station.priority = 0
|
||||
@@ -279,30 +375,33 @@ 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.signal)
|
||||
|
||||
if -effective_item_count >= station.r_threshold then
|
||||
if r_stations_all[item_name] == nil then
|
||||
r_stations_all[item_name] = {}
|
||||
p_stations_all[item_name] = {}
|
||||
all_items[#all_items + 1] = item_name
|
||||
all_items[#all_items + 1] = v.signal.type
|
||||
if item_name 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] = {}
|
||||
all_items[#all_items + 1] = item_name
|
||||
all_items[#all_items + 1] = v.signal.type
|
||||
end
|
||||
table.insert(r_stations_all[item_name], station_id)
|
||||
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] = {}
|
||||
all_items[#all_items + 1] = item_name
|
||||
all_items[#all_items + 1] = v.signal.type
|
||||
end
|
||||
table.insert(p_stations_all[item_name], station_id)
|
||||
end
|
||||
table.insert(r_stations_all[item_name], station_id)
|
||||
elseif effective_item_count >= station.p_threshold then
|
||||
if r_stations_all[item_name] == nil then
|
||||
r_stations_all[item_name] = {}
|
||||
p_stations_all[item_name] = {}
|
||||
all_items[#all_items + 1] = item_name
|
||||
all_items[#all_items + 1] = v.signal.type
|
||||
end
|
||||
table.insert(p_stations_all[item_name], station_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local failed_because_missing_trains_total = 0
|
||||
local failed_because_missing_trains = {}
|
||||
--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
|
||||
local start_i = 2*(total_ticks%(#all_items/2)) + 1
|
||||
@@ -336,13 +435,14 @@ function tick(map_data, mod_settings)
|
||||
highest_prior = prior
|
||||
elseif d < INF then
|
||||
could_have_been_serviced = true
|
||||
best = j
|
||||
end
|
||||
end
|
||||
end
|
||||
if best > 0 then
|
||||
if best_train then
|
||||
send_train_between(map_data, r_station_id, p_stations[best], best_train, item_name, economy)
|
||||
elseif could_have_been_serviced then
|
||||
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
||||
send_missing_train_alert_for_stops(stations[r_station_id].entity_stop, p_stations[best].entity_stop)
|
||||
end
|
||||
until #r_stations == 0
|
||||
else
|
||||
@@ -368,17 +468,17 @@ function tick(map_data, mod_settings)
|
||||
highest_prior = prior
|
||||
elseif d < INF then
|
||||
could_have_been_serviced = true
|
||||
best = i
|
||||
end
|
||||
end
|
||||
end
|
||||
if best > 0 then
|
||||
if best_train then
|
||||
send_train_between(map_data, r_stations[best], p_station_id, best_train, item_name, economy)
|
||||
elseif could_have_been_serviced then
|
||||
failed_because_missing_trains_total = failed_because_missing_trains_total + 1
|
||||
send_missing_train_alert_for_stops(stations[best].entity_stop, p_stations[p_station_id].entity_stop)
|
||||
end
|
||||
until #p_stations == 0
|
||||
end
|
||||
end
|
||||
end
|
||||
--TODO: add alert for missing trains
|
||||
end
|
||||
|
||||
@@ -1,61 +1,65 @@
|
||||
--By Mami
|
||||
---@class MapData
|
||||
---@field public total_ticks uint
|
||||
---@field public layout_top_id uint
|
||||
---@field public to_output {[uint]: LuaEntity}
|
||||
---@field public to_stop {[uint]: LuaEntity}
|
||||
---@field public stations {[uint]: Station}
|
||||
---@field public depots {[uint]: LuaEntity}
|
||||
---@field public trains {[uint]: Train}
|
||||
---@field public trains_available {[uint]: boolean}
|
||||
---@field public layouts {[uint]: string}
|
||||
---@field public layout_train_count {[uint]: int}
|
||||
---@field public train_classes {[string]: TrainClass}
|
||||
|
||||
---@class Station
|
||||
---@field public deliveries_total int
|
||||
---@field public priority int
|
||||
---@field public last_delivery_tick int
|
||||
---@field public r_threshold int >= 0
|
||||
---@field public p_threshold int >= 0
|
||||
---@field public locked_slots int >= 0
|
||||
---@field public entity_stop LuaEntity
|
||||
---@field public entity_comb1 LuaEntity
|
||||
---@field public entity_comb2 LuaEntity?
|
||||
---@field public wagon_combs {[int]: LuaEntity}?--NOTE: allowed to be invalid entities or combinators with the wrong operation, these must be checked and lazy deleted when found
|
||||
---@field public deliveries {[string]: int}
|
||||
---@field public train_class SignalID?
|
||||
---@field public accepted_layouts TrainClass
|
||||
---@field public layout_pattern string?
|
||||
|
||||
---@class Train
|
||||
---@field public entity LuaTrain
|
||||
---@field public layout_id uint
|
||||
---@field public item_slot_capacity int
|
||||
---@field public fluid_capacity int
|
||||
---@field public depot_name string
|
||||
---@field public status int
|
||||
---@field public p_station_id uint
|
||||
---@field public r_station_id uint
|
||||
---@field public manifest Manifest
|
||||
|
||||
---@alias Manifest {}[]
|
||||
---@alias TrainClass {[uint]: boolean}
|
||||
---@alias cybersyn.global MapData
|
||||
|
||||
---@class Economy
|
||||
---@field public r_stations_all {[string]: uint[]}
|
||||
---@field public p_stations_all {[string]: uint[]}
|
||||
---@field public all_items string[]
|
||||
---@field public total_ticks uint
|
||||
|
||||
--[[
|
||||
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}
|
||||
train_classes: {[string]: TrainClass}
|
||||
}
|
||||
Station: {
|
||||
deliveries_total: int
|
||||
priority: int
|
||||
last_delivery_tick: int
|
||||
r_threshold: int >= 0
|
||||
p_threshold: int >= 0
|
||||
locked_slots: int >= 0
|
||||
entity: LuaEntity
|
||||
entity_in: LuaEntity
|
||||
entity_out: LuaEntity
|
||||
deliveries: {
|
||||
[item_name]: int
|
||||
}
|
||||
train_class: string
|
||||
accepted_layouts: TrainClass
|
||||
layout_pattern: string|nil
|
||||
}
|
||||
Train: {
|
||||
entity: LuaEntity
|
||||
layout_id: int
|
||||
item_slot_capacity: int
|
||||
fluid_capacity: int
|
||||
depot_name: string
|
||||
status: int
|
||||
p_station_id: stop_id
|
||||
r_station_id: stop_id
|
||||
manifest: [{
|
||||
name: string
|
||||
type: string
|
||||
count: int
|
||||
}]
|
||||
}
|
||||
TrainClass: {
|
||||
[layout_id]: bool
|
||||
}
|
||||
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.to_stop = {}
|
||||
global.stations = {}
|
||||
global.depots = {}
|
||||
global.trains = {}
|
||||
global.trains_available = {}
|
||||
global.layouts = {}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
--By Mami
|
||||
local gui = require("__flib__.gui")
|
||||
|
||||
local RED = "utility/status_not_working"
|
||||
local GREEN = "utility/status_working"
|
||||
local YELLOW = "utility/status_yellow"
|
||||
|
||||
local STATUS_SPRITES = {}
|
||||
STATUS_SPRITES[defines.entity_status.working] = GREEN
|
||||
STATUS_SPRITES[defines.entity_status.normal] = GREEN
|
||||
STATUS_SPRITES[defines.entity_status.no_power] = RED
|
||||
STATUS_SPRITES[defines.entity_status.low_power] = YELLOW
|
||||
STATUS_SPRITES[defines.entity_status.disabled_by_control_behavior] = RED
|
||||
STATUS_SPRITES[defines.entity_status.disabled_by_script] = RED
|
||||
STATUS_SPRITES[defines.entity_status.marked_for_deconstruction] = RED
|
||||
local STATUS_SPRITES_DEFAULT = RED
|
||||
|
||||
local STATUS_NAMES = {}
|
||||
STATUS_NAMES[defines.entity_status.working] = "entity-status.working"
|
||||
STATUS_NAMES[defines.entity_status.normal] = "entity-status.normal"
|
||||
STATUS_NAMES[defines.entity_status.no_power] = "entity-status.no-power"
|
||||
STATUS_NAMES[defines.entity_status.low_power] = "entity-status.low-power"
|
||||
STATUS_NAMES[defines.entity_status.disabled_by_control_behavior] = "entity-status.disabled"
|
||||
STATUS_NAMES[defines.entity_status.disabled_by_script] = "entity-status.disabled-by-script"
|
||||
STATUS_NAMES[defines.entity_status.marked_for_deconstruction] = "entity-status.marked-for-deconstruction"
|
||||
STATUS_NAMES_DEFAULT = "entity-status.disabled"
|
||||
|
||||
---@param entity LuaEntity
|
||||
function gui_opened(entity, player)
|
||||
local rootgui = player.gui.screen
|
||||
local window = gui.build(rootgui, {
|
||||
{type="frame", direction="vertical", ref={"main_window"}, name=COMBINATOR_NAME, tags={unit_number=entity.unit_number}, actions={
|
||||
on_close = {"test"}
|
||||
}, children={
|
||||
--title bar
|
||||
{type="flow", ref={"titlebar"}, children={
|
||||
{type="label", style="frame_title", caption={"cybersyn-gui.combinator-title"}, elem_mods={ignored_by_interaction=true}},
|
||||
{type="empty-widget", style="flib_titlebar_drag_handle", elem_mods={ignored_by_interaction=true}},
|
||||
{type="sprite-button", style="frame_action_button", mouse_button_filter={"left"}, sprite="utility/close_white", hovered_sprite="utility/close_black", name=COMBINATOR_NAME, actions={
|
||||
on_click = {"test"}
|
||||
}}
|
||||
}},
|
||||
{type="frame", style="inside_shallow_frame_with_padding", style_mods={padding=8}, children={
|
||||
{type="flow", direction="vertical", style_mods={horizontal_align="left"}, children={
|
||||
--status
|
||||
{type="flow", style = "status_flow", direction = "horizontal", style_mods={vertical_align="center", horizontally_stretchable=true}, children={
|
||||
{type="sprite", sprite=STATUS_SPRITES[entity.status] or STATUS_SPRITES_DEFAULT, style="status_image", ref={"status_icon"}, style_mods={stretch_image_to_widget_size=true}},
|
||||
{type="label", caption={STATUS_NAMES[entity.status] or STATUS_NAMES_DEFAULT}, ref={"status_label"}}
|
||||
}},
|
||||
--preview
|
||||
{type="frame", style="deep_frame_in_shallow_frame", style_mods={minimal_width=0, horizontally_stretchable=true, padding=0}, children={
|
||||
{type="entity-preview", style="wide_entity_button", ref={"preview"}},
|
||||
}},
|
||||
{type="label", caption={"cybersyn-gui.operation"}, style_mods={top_padding=8}},
|
||||
{type="drop-down", ref={"operation"}, actions={
|
||||
on_selection_state_changed = {"test"}
|
||||
}, items={
|
||||
{"cybersyn-gui.comb1"},
|
||||
{"cybersyn-gui.comb2"},
|
||||
{"cybersyn-gui.depot"},
|
||||
{"cybersyn-gui.wagon-manifest"},
|
||||
}},
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
})
|
||||
|
||||
window.preview.entity = entity
|
||||
window.titlebar.drag_target = window.main_window
|
||||
window.main_window.force_auto_center()
|
||||
|
||||
player.opened = window.main_window
|
||||
end
|
||||
|
||||
local function o(event)
|
||||
local entity = event.entity
|
||||
if not entity or not entity.valid then return end
|
||||
local player = game.get_player(event.player_index)
|
||||
if not player then return end
|
||||
local rootgui = player.gui.screen
|
||||
|
||||
if rootgui[COMBINATOR_NAME] then
|
||||
--rootgui[COMBINATOR_NAME].destroy()
|
||||
else
|
||||
gui_opened(entity, player)
|
||||
end
|
||||
end
|
||||
|
||||
function register_gui_actions()
|
||||
gui.hook_events(function(event)
|
||||
local msg = gui.read_action(event)
|
||||
if msg then
|
||||
-- read the action to determine what to do
|
||||
local hi = 2
|
||||
end
|
||||
end)
|
||||
script.on_event(defines.events.on_gui_opened, o)
|
||||
end
|
||||
@@ -1,6 +1,9 @@
|
||||
--By Mami
|
||||
local area = require("__flib__.area")
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train Train
|
||||
---@param train_id uint
|
||||
function remove_train(map_data, train, train_id)
|
||||
map_data.trains[train_id] = nil
|
||||
map_data.trains_available[train_id] = nil
|
||||
@@ -18,6 +21,8 @@ function remove_train(map_data, train, train_id)
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train Train
|
||||
function update_train_layout(map_data, train)
|
||||
local carriages = train.entity.carriages
|
||||
local layout = ""
|
||||
@@ -68,54 +73,72 @@ function update_train_layout(map_data, train)
|
||||
train.fluid_capacity = fluid_capacity
|
||||
end
|
||||
|
||||
local function reset_station_layout(map_data, station)
|
||||
--station.entity
|
||||
local station_rail = station.entity.connected_rail
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param forbidden_entity LuaEntity?
|
||||
local function reset_station_layout(map_data, station, forbidden_entity)
|
||||
--NOTE: station must be in auto mode
|
||||
local station_rail = station.entity_stop.connected_rail
|
||||
if station_rail == nil then
|
||||
--cannot accept deliveries
|
||||
station.layout_pattern = "X"
|
||||
station.accepted_layouts = {}
|
||||
return
|
||||
end
|
||||
local rail_direction_from_station
|
||||
if station.entity.connected_rail_direction == defines.rail_direction.front then
|
||||
if station.entity_stop.connected_rail_direction == defines.rail_direction.front then
|
||||
rail_direction_from_station = defines.rail_direction.back
|
||||
else
|
||||
rail_direction_from_station = defines.rail_direction.front
|
||||
end
|
||||
local station_direction = station.entity.direction
|
||||
local surface = station.entity.surface
|
||||
local station_direction = station.entity_stop.direction
|
||||
local surface = station.entity_stop.surface
|
||||
local middle_x = station_rail.position.x
|
||||
local middle_y = station_rail.position.y
|
||||
local reach = LONGEST_INSERTER_REACH + 1 - DELTA
|
||||
local reach = LONGEST_INSERTER_REACH + 1
|
||||
local search_area
|
||||
local area_delta
|
||||
local direction_filter
|
||||
local is_ver
|
||||
--local center_line
|
||||
if station_direction == defines.direction.north then
|
||||
search_area = {left_top = {x = middle_x - reach, y = middle_y}, right_bottom = {x = middle_x + reach, y = middle_y - 6}}
|
||||
area_delta = {x = 0, y = -7}
|
||||
direction_filter = {defines.direction.east, defines.direction.west}
|
||||
elseif station_direction == defines.direction.east then
|
||||
search_area = {left_top = {y = middle_y - reach, x = middle_x}, right_bottom = {y = middle_y + reach, x = middle_x - 6}}
|
||||
area_delta = {y = 0, x = -7}
|
||||
direction_filter = {defines.direction.north, defines.direction.south}
|
||||
elseif station_direction == defines.direction.south then
|
||||
search_area = {left_top = {x = middle_x - reach, y = middle_y + 6}, right_bottom = {x = middle_x + reach, y = middle_y}}
|
||||
search_area = {left_top = {x = middle_x - reach, y = middle_y}, right_bottom = {x = middle_x + reach, y = middle_y + 6}}
|
||||
area_delta = {x = 0, y = 7}
|
||||
direction_filter = {defines.direction.east, defines.direction.west}
|
||||
is_ver = true
|
||||
elseif station_direction == defines.direction.east then
|
||||
search_area = {left_top = {y = middle_y - reach, x = middle_x}, right_bottom = {y = middle_y + reach, x = middle_x - 6}}
|
||||
area_delta = {x = -7, y = 0}
|
||||
direction_filter = {defines.direction.north, defines.direction.south}
|
||||
is_ver = false
|
||||
elseif station_direction == defines.direction.south then
|
||||
search_area = {left_top = {x = middle_x - reach, y = middle_y - 6}, right_bottom = {x = middle_x + reach, y = middle_y}}
|
||||
area_delta = {x = 0, y = -7}
|
||||
direction_filter = {defines.direction.east, defines.direction.west}
|
||||
is_ver = true
|
||||
elseif station_direction == defines.direction.west then
|
||||
search_area = {left_top = {y = middle_y - reach, x = middle_x + 6}, right_bottom = {y = middle_y + reach, x = middle_x}}
|
||||
area_delta = {y = 0, x = 7}
|
||||
area_delta = {x = 7, y = 0}
|
||||
direction_filter = {defines.direction.north, defines.direction.south}
|
||||
is_ver = false
|
||||
else
|
||||
assert(false, "cybersyn: invalid station direction")
|
||||
end
|
||||
local length = 2
|
||||
local pre_rail = station_rail
|
||||
local layout_pattern = "^"
|
||||
local layout_min_size = 10000
|
||||
local type_filter = {"inserter", "pump"}
|
||||
local type_filter = {"inserter", "pump", "arithmetic-combinator"}
|
||||
local wagon_number = 0
|
||||
local pattern_length = 1
|
||||
for i = 1, 100 do
|
||||
local rail, rail_direction, rail_connection_direction = pre_rail.get_connected_rail({rail_direction = rail_direction_from_station, rail_connection_direction = defines.rail_connection_direction.straight})
|
||||
if rail_connection_direction ~= defines.rail_connection_direction.straight or not rail.valid then
|
||||
if not rail or rail_connection_direction ~= defines.rail_connection_direction.straight or not rail.valid then
|
||||
break
|
||||
end
|
||||
pre_rail = rail
|
||||
length = length + 2
|
||||
if length%7 <= 1 then
|
||||
wagon_number = wagon_number + 1
|
||||
local supports_cargo = false
|
||||
local supports_fluid = false
|
||||
local entities = surface.find_entities_filtered({
|
||||
@@ -124,38 +147,73 @@ local function reset_station_layout(map_data, station)
|
||||
direction = direction_filter,
|
||||
})
|
||||
for _, entity in pairs(entities) do
|
||||
if entity.type == "inserter" then
|
||||
--local pickup_pos = entity.prototype.inserter_pickup_position + entity.position
|
||||
--local drop_pos = entity.prototype.inserter_drop_position + entity.position
|
||||
--TODO: add further checks
|
||||
supports_cargo = true
|
||||
elseif entity.type == "pump" then
|
||||
if entity.pump_rail_target then
|
||||
supports_fluid = true
|
||||
if entity.valid and entity ~= forbidden_entity then
|
||||
if entity.type == "inserter" then
|
||||
if not supports_cargo then
|
||||
local pos = entity.pickup_position
|
||||
local is_there
|
||||
if is_ver then
|
||||
is_there = middle_x - 1 <= pos.x and pos.x <= middle_x + 1
|
||||
else
|
||||
is_there = middle_y - 1 <= pos.y and pos.y <= middle_y + 1
|
||||
end
|
||||
if is_there then
|
||||
supports_cargo = true
|
||||
else
|
||||
pos = entity.drop_position
|
||||
if is_ver then
|
||||
is_there = middle_x - 1 <= pos.x and pos.x <= middle_x + 1
|
||||
else
|
||||
is_there = middle_y - 1 <= pos.y and pos.y <= middle_y + 1
|
||||
end
|
||||
if is_there then
|
||||
supports_cargo = true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif entity.type == "pump" then
|
||||
if not supports_fluid and entity.pump_rail_target then
|
||||
supports_fluid = true
|
||||
end
|
||||
elseif entity.name == COMBINATOR_NAME then
|
||||
local control = entity.get_or_create_control_behavior().parameters
|
||||
if control.operation == OPERATION_WAGON_MANIFEST then
|
||||
local pos = entity.position
|
||||
local is_there
|
||||
if is_ver then
|
||||
is_there = middle_x - 2.1 <= pos.x and pos.x <= middle_x + 2.1
|
||||
else
|
||||
is_there = middle_y - 2.1 <= pos.y and pos.y <= middle_y + 2.1
|
||||
end
|
||||
if is_there then
|
||||
if not station.wagon_combs then
|
||||
station.wagon_combs = {}
|
||||
end
|
||||
station.wagon_combs[wagon_number] = entity
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if supports_cargo then
|
||||
if supports_fluid then
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_BOTH
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_ALL
|
||||
else
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_CARGO
|
||||
--TODO: needs to allow misc wagons as well
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_NOT_FLUID
|
||||
end
|
||||
pattern_length = #layout_pattern
|
||||
elseif supports_fluid then
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_FLUID
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_NOT_CARGO
|
||||
pattern_length = #layout_pattern
|
||||
else
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_NA
|
||||
end
|
||||
if layout_min_size <= 0 then
|
||||
layout_pattern = layout_pattern.."?"
|
||||
else
|
||||
layout_min_size = layout_min_size - 1
|
||||
end
|
||||
search_area = area.move(search_area, area_delta)
|
||||
end
|
||||
end
|
||||
layout_pattern = layout_pattern..STATION_LAYOUT_NA.."*$"
|
||||
layout_pattern = string.sub(layout_pattern, 1, pattern_length)..STATION_LAYOUT_NA.."*$"
|
||||
station.layout_pattern = layout_pattern
|
||||
local accepted_layouts = station.accepted_layouts
|
||||
for id, layout in pairs(map_data.layouts) do
|
||||
@@ -167,52 +225,75 @@ local function reset_station_layout(map_data, station)
|
||||
end
|
||||
end
|
||||
|
||||
function set_station_train_class(map_data, station, train_class_name)
|
||||
if train_class_name == TRAIN_CLASS_AUTO then
|
||||
if station.train_class ~= TRAIN_CLASS_AUTO then
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param train_class SignalID
|
||||
function set_station_train_class(map_data, station, train_class)
|
||||
if train_class.name == TRAIN_CLASS_AUTO.name then
|
||||
if station.train_class.name ~= TRAIN_CLASS_AUTO.name then
|
||||
station.train_class = TRAIN_CLASS_AUTO
|
||||
station.accepted_layouts = {}
|
||||
end
|
||||
reset_station_layout(map_data, station)
|
||||
reset_station_layout(map_data, station, nil)
|
||||
else
|
||||
station.train_class = train_class_name
|
||||
station.accepted_layouts = map_data.train_classes[train_class_name]
|
||||
station.train_class = train_class
|
||||
station.accepted_layouts = map_data.train_classes[train_class.name]
|
||||
assert(station.accepted_layouts ~= nil)
|
||||
station.layout_pattern = nil
|
||||
end
|
||||
end
|
||||
|
||||
function update_station_if_auto(map_data, station)
|
||||
if station.train_class == TRAIN_CLASS_AUTO then
|
||||
reset_station_layout(map_data, station)
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function update_station_if_auto(map_data, station, forbidden_entity)
|
||||
if station.train_class.name == TRAIN_CLASS_AUTO.name then
|
||||
reset_station_layout(map_data, station, forbidden_entity)
|
||||
end
|
||||
end
|
||||
|
||||
function update_station_from_rail(map_data, rail)
|
||||
--TODO: search further?
|
||||
local entity = rail.get_rail_segment_entity(nil, false)
|
||||
if entity.name == BUFFER_STATION_NAME then
|
||||
update_station_if_auto(map_data, map_data.stations[entity.unit_number])
|
||||
---@param map_data MapData
|
||||
---@param rail LuaEntity
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function update_station_from_rail(map_data, rail, forbidden_entity)
|
||||
--TODO: search further or better?
|
||||
local entity = rail.get_rail_segment_entity(defines.rail_direction.back, false)
|
||||
if entity and entity.valid and entity.name == "train-stop" then
|
||||
local station = map_data.stations[entity.unit_number]
|
||||
if station then
|
||||
update_station_if_auto(map_data, station, forbidden_entity)
|
||||
end
|
||||
else
|
||||
entity = rail.get_rail_segment_entity(defines.rail_direction.front, false)
|
||||
if entity and entity.valid and entity.name == "train-stop" then
|
||||
local station = map_data.stations[entity.unit_number]
|
||||
if station then
|
||||
update_station_if_auto(map_data, station, forbidden_entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function update_station_from_pump(map_data, pump)
|
||||
---@param map_data MapData
|
||||
---@param pump LuaEntity
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function update_station_from_pump(map_data, pump, forbidden_entity)
|
||||
if pump.pump_rail_target then
|
||||
update_station_from_rail(map_data, pump.pump_rail_target)
|
||||
update_station_from_rail(map_data, pump.pump_rail_target, forbidden_entity)
|
||||
end
|
||||
end
|
||||
function update_station_from_inserter(map_data, inserter)
|
||||
---@param map_data MapData
|
||||
---@param inserter LuaEntity
|
||||
---@param forbidden_entity LuaEntity?
|
||||
function update_station_from_inserter(map_data, inserter, forbidden_entity)
|
||||
--TODO: check if correct
|
||||
local surface = inserter.surface
|
||||
local pos = inserter.position
|
||||
local pickup_pos = inserter.prototype.inserter_pickup_position
|
||||
local drop_pos = inserter.prototype.inserter_drop_position
|
||||
|
||||
local rail = surface.find_entity("straight-rail", {pos.x + pickup_pos.x, pos.y + pickup_pos.y})
|
||||
local rail = surface.find_entity("straight-rail", inserter.pickup_position)
|
||||
if rail then
|
||||
update_station_from_rail(map_data, rail)
|
||||
update_station_from_rail(map_data, rail, forbidden_entity)
|
||||
end
|
||||
rail = surface.find_entity("straight-rail", {pos.x + drop_pos.x, pos.y + drop_pos.y})
|
||||
rail = surface.find_entity("straight-rail", inserter.drop_position)
|
||||
if rail then
|
||||
update_station_from_rail(map_data, rail)
|
||||
update_station_from_rail(map_data, rail, forbidden_entity)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,38 +1,23 @@
|
||||
--By Mami
|
||||
|
||||
local function set_station_output_empty(station)
|
||||
--change circuit outputs
|
||||
station.entity_out.get_control_behavior().parameters = nil
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train Train
|
||||
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.entity_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.entity_comb1, nil)
|
||||
end
|
||||
end
|
||||
train.r_station_id = 0
|
||||
@@ -40,91 +25,16 @@ 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
|
||||
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param comb1 LuaEntity
|
||||
---@param comb2 LuaEntity
|
||||
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,
|
||||
@@ -138,13 +48,14 @@ local function on_station_built(map_data, stop)
|
||||
}
|
||||
map_data.stations[stop.unit_number] = station
|
||||
|
||||
update_station_if_auto(map_data, station)
|
||||
update_station_if_auto(map_data, station, nil)
|
||||
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]
|
||||
---@param map_data MapData
|
||||
---@param station_id uint
|
||||
---@param station Station
|
||||
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
|
||||
@@ -156,18 +67,239 @@ local function on_station_broken(map_data, stop)
|
||||
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
|
||||
send_lost_train_alert(train.entity)
|
||||
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
|
||||
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param comb_operation string
|
||||
---@param comb_forbidden LuaEntity?
|
||||
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 - 2, pos_y - 2},
|
||||
{pos_x + 2, pos_y + 2}
|
||||
}
|
||||
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
|
||||
|
||||
---@param map_data MapData
|
||||
---@param comb LuaEntity
|
||||
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
|
||||
if comb.direction == defines.direction.north or comb.direction == defines.direction.south then
|
||||
search_area = {
|
||||
{pos_x - 1.5, pos_y - 2},
|
||||
{pos_x + 1.5, pos_y + 2}
|
||||
}
|
||||
else
|
||||
search_area = {
|
||||
{pos_x - 2, pos_y - 1.5},
|
||||
{pos_x + 2, pos_y + 1.5}
|
||||
}
|
||||
end
|
||||
local stop = nil
|
||||
local rail = nil
|
||||
local entities = comb.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 == "straight-rail" then
|
||||
rail = cur_entity
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local out = comb.surface.create_entity({
|
||||
name = COMBINATOR_OUT_NAME,
|
||||
position = comb.position,
|
||||
force = comb.force
|
||||
})
|
||||
assert(out, "cybersyn: could not spawn combinator controller")
|
||||
comb.connect_neighbour({
|
||||
target_entity = out,
|
||||
source_circuit_id = defines.circuit_connector_id.combinator_output,
|
||||
wire = defines.wire_type.green,
|
||||
})
|
||||
comb.connect_neighbour({
|
||||
target_entity = out,
|
||||
source_circuit_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, nil)
|
||||
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, comb)
|
||||
|
||||
on_station_built(map_data, stop, comb, comb2)
|
||||
end
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param comb LuaEntity
|
||||
local function on_combinator_broken(map_data, comb)
|
||||
--NOTE: we do not check for wagon manifest combinators and update their stations, it is assumed they will be lazy deleted later
|
||||
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.entity_comb1 == comb then
|
||||
local comb1 = search_for_station_combinator(map_data, stop, OPERATION_PRIMARY_IO, comb)
|
||||
if comb1 then
|
||||
station.entity_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.entity_comb2 == comb then
|
||||
station.entity_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
|
||||
---@param map_data MapData
|
||||
---@param comb LuaEntity
|
||||
local function on_combinator_updated(map_data, comb)
|
||||
--NOTE: this is the lazy way to implement updates and puts strong restrictions on data validity on on_combinator_broken
|
||||
on_combinator_broken(map_data, comb)
|
||||
on_combinator_built(map_data, comb)
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
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 - 2, pos_y - 2},
|
||||
{pos_x + 2, pos_y + 2}
|
||||
}
|
||||
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
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
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 - 2, pos_y - 2},
|
||||
{pos_x + 2, pos_y + 2}
|
||||
}
|
||||
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
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
local function on_station_rename(map_data, stop)
|
||||
--search for trains coming to the renamed station
|
||||
local station_id = stop.unit_number
|
||||
@@ -183,7 +315,7 @@ local function on_station_rename(map_data, stop)
|
||||
--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)
|
||||
local schedule = create_manifest_schedule(train.depot_name, p_station.entity_stop, r_station.entity_stop, train.manifest)
|
||||
schedule.current = train.entity.schedule.current
|
||||
train.entity.schedule = schedule
|
||||
end
|
||||
@@ -193,53 +325,51 @@ local function on_station_rename(map_data, stop)
|
||||
end
|
||||
|
||||
|
||||
local function find_and_add_all_stations(map_data)
|
||||
---@param map_data MapData
|
||||
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
|
||||
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train_entity LuaTrain
|
||||
local function on_train_arrives_depot(map_data, train_entity)
|
||||
local contents = train_entity.get_contents()
|
||||
local train = map_data.trains[train_entity.id]
|
||||
if train then
|
||||
if train.manifest then
|
||||
if train.status == STATUS_R_TO_D then
|
||||
--succeeded delivery
|
||||
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 = create_depot_schedule(train.depot_name)
|
||||
map_data.trains_available[train_entity.id] = true
|
||||
else
|
||||
if train.manifest and train.status == STATUS_R_TO_D then
|
||||
--succeeded delivery
|
||||
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
|
||||
map_data.trains_available[train_entity.id] = true
|
||||
else
|
||||
if train.manifest then
|
||||
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
|
||||
train.entity.schedule = create_depot_schedule(train.depot_name)
|
||||
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
|
||||
send_lost_train_alert(train.entity)
|
||||
end
|
||||
train.depot_name = train_entity.station.backer_name
|
||||
train.status = STATUS_D
|
||||
map_data.trains_available[train_entity.id] = true
|
||||
end
|
||||
else
|
||||
if next(contents) ~= nil then
|
||||
--train still has cargo
|
||||
train_entity.schedule = nil
|
||||
remove_train(map_data, train, train_entity.id)
|
||||
send_nonempty_train_in_depot_alert(train_entity)
|
||||
else
|
||||
train_entity.schedule = create_depot_schedule(train.depot_name)
|
||||
end
|
||||
elseif next(contents) == nil then
|
||||
train = {
|
||||
depot_name = train_entity.station.backer_name,
|
||||
status = STATUS_D,
|
||||
@@ -251,15 +381,20 @@ 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
|
||||
else
|
||||
send_nonempty_train_in_depot_alert(train_entity)
|
||||
end
|
||||
end
|
||||
|
||||
local function on_train_arrives_buffer(map_data, station_id, train)
|
||||
---@param map_data MapData
|
||||
---@param stop LuaEntity
|
||||
---@param train 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 +405,12 @@ 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)
|
||||
if station.wagon_combs then
|
||||
for i, entity in ipairs(station.wagon_combs) do
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif train.status == STATUS_P_TO_R then
|
||||
if train.r_station_id == station_id then
|
||||
@@ -281,47 +421,40 @@ 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)
|
||||
remove_train(map_data, train, train.entity.id)
|
||||
train.entity.schedule = nil
|
||||
send_lost_train_alert(train.entity)
|
||||
end
|
||||
else
|
||||
--train is lost somehow, probably from player intervention
|
||||
remove_train(map_data, train, train.entity.id)
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train 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
|
||||
set_station_output_empty(station)
|
||||
remove_manifest(map_data, station, train.manifest, 1)
|
||||
set_combinator_output(map_data, station.entity_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.entity_comb1, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param train Train
|
||||
local function on_train_broken(map_data, train)
|
||||
if train.manifest then
|
||||
on_failed_delivery(map_data, train)
|
||||
@@ -331,7 +464,9 @@ local function on_train_broken(map_data, train)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---@param map_data MapData
|
||||
---@param pre_train_id uint
|
||||
---@param train_entity LuaEntity
|
||||
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 +482,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 +491,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,33 +512,21 @@ 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)
|
||||
update_station_from_inserter(global, entity, entity)
|
||||
elseif entity.type == "pump" then
|
||||
update_station_from_pump(global, entity)
|
||||
update_station_from_pump(global, entity, entity)
|
||||
elseif entity.type == "straight-rail" then
|
||||
update_station_from_rail(global, entity)
|
||||
update_station_from_rail(global, entity, nil)
|
||||
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 +539,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
|
||||
on_station_broken(global, entity)
|
||||
if entity.name == "train-stop" then
|
||||
on_stop_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"},
|
||||
@@ -469,6 +607,8 @@ local function register_events()
|
||||
script.on_event(defines.events.on_train_changed_state, on_train_changed)
|
||||
|
||||
script.on_event(defines.events.on_entity_renamed, on_rename)
|
||||
|
||||
register_gui_actions()
|
||||
end
|
||||
|
||||
script.on_load(function()
|
||||
@@ -477,12 +617,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)
|
||||
|
||||
@@ -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,
|
||||
|
||||