removed provide threshold

This commit is contained in:
Monica Moniot
2022-11-10 19:20:29 -05:00
parent e6a8d72f85
commit 0b370407fa
14 changed files with 335 additions and 265 deletions

View File

@@ -3,3 +3,9 @@ Version: 0.1.0
Date: 2022-11-04
Features:
- Pre-Alpha release
---------------------------------------------------------------------------------------------------
Version: 0.2.0
Date: 2022-11-04
Features:
- Removed provide-threshold
- Added ability to specify station type on a cybernetic combinator

View File

@@ -2,6 +2,7 @@
require("scripts.constants")
require("scripts.global")
require("scripts.combinator")
require("scripts.central-planning")
require("scripts.layout")
require("scripts.gui")

View File

@@ -16,7 +16,6 @@ data:extend({
cybersyn_tech,
subgroup_signal,
priority_signal,
p_threshold_signal,
r_threshold_signal,
locked_slots_signal,
missing_train_icon,

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,20 +1,18 @@
[mod-setting-name]
cybersyn-ticks-per-second=Dispatcher updates per second
cybersyn-request-threshold=Default requester threshold
cybersyn-provide-threshold=Default provider threshold
cybersyn-network-flag=Default network flags
[mod-setting-description]
cybersyn-ticks-per-second=How many times per second the dispather should check for new deliveries. Deliveries are made one at a time per update. This value will be rounded up to a divisor of 60.
cybersyn-request-threshold=The default request threshold when a request threshold signal is not given to a station. Huge values will prevent stations from taking requests from the network unless an explicit threshold is set.
cybersyn-provide-threshold=The default provide threshold when a provide threshold signal is not given to a station. Huge values will prevent stations from providing to the network unless an explicit threshold is set.
cybersyn-network-flag=The default set of networks a station will service when no network signal is given to a station. This integer is interpretted bit-wise to give 32 possible network flags to choose from.
[item-name]
cybersyn-combinator=Cybernetic combinator
[item-description]
cybersyn-combinator=Place next to a train stop to add it to the cybersyn train network. This stop can now request or provide items using the circuit network. Be sure to set a threshold signal.
cybersyn-combinator=Place next to a train stop to add it to the cybersyn train network. This stop can now request or provide items that are reported to it by the circuit network.
[entity-name]
cybersyn-combinator=Cybernetic combinator
@@ -32,7 +30,6 @@ cybersyn-train-network=Train stop controllers capable of coordinating the inputs
[virtual-signal-name]
cybersyn-priority=Station priority
cybersyn-provide-threshold=Provide threshold
cybersyn-request-threshold=Request threshold
cybersyn-locked-slots=Locked slots per cargo wagon
@@ -49,4 +46,10 @@ comb2=Optional station control
depot=Depot control
wagon-manifest=Wagon control
network=Network
auto-description=Station automatically decides which trains in the network it can service (all trains are allowed by default)
network-tooltip=A signal is used to identify which network this combinator is a member of. Trains will only be dispatched from depots to provide and request stations if they are all identified with the same signal.
auto-tooltip=When checked trains in the network are automatically blacklisted if they are not able to interact with all of the loading and unloading machines present along the station. When unchecked the blacklist is empty and all trains are allowed.
auto-description=Allow automatic train blacklist
switch-provide=Provide only
switch-request=Request only
switch-provide-tooltip=Lock this station to only provide items to the network. By default it both requests and provides.
switch-request-tooltip=Lock this station to only request items from the network. By default it both requests and provides.

View File

@@ -14,15 +14,6 @@ priority_signal = {
subgroup = "cybersyn-signal",
order = "a"
}
p_threshold_signal = {
type = "virtual-signal",
name = PROVIDE_THRESHOLD,
icon = "__cybersyn__/graphics/icons/provide-threshold.png",
icon_size = 64,
icon_mipmaps = 4,
subgroup = "cybersyn-signal",
order = "b"
}
r_threshold_signal = {
type = "virtual-signal",
name = REQUEST_THRESHOLD,

View File

@@ -70,49 +70,6 @@ function create_manifest_schedule(depot_name, p_stop, r_stop, manifest)
}}
end
---@param station Station
local function get_signals(station)
local comb = station.entity_comb1
if comb.valid and (comb.status == defines.entity_status.working or comb.status == defines.entity_status.low_power) then
return comb.get_merged_signals(defines.circuit_connector_id.combinator_input)
else
return nil
end
end
---@param map_data MapData
---@param comb LuaEntity
---@param signals ConstantCombinatorParameters[]?
function set_combinator_output(map_data, comb, signals)
local out = map_data.to_output[comb.unit_number]
if out.valid then
out.get_or_create_control_behavior().parameters = signals
end
end
---@param comb LuaEntity
---@param op string
function set_combinator_operation(comb, op)
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
control.operation = op
a.parameters = control
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 is_fluid = game.item_prototypes[item_name] == nil--NOTE: this is expensive
signals[i] = {index = i, signal = {type = is_fluid and "fluid" or "item", 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
@@ -128,20 +85,6 @@ function remove_manifest(map_data, station, manifest, sign)
station.deliveries_total = station.deliveries_total - 1
end
---@param map_data MapData
---@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
@@ -150,12 +93,12 @@ local function get_stop_dist(stop0, stop1)
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)
---@param min_amount_to_move int
local function get_valid_train(map_data, r_station_id, p_station_id, item_type, min_amount_to_move)
--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]
@@ -185,10 +128,10 @@ local function get_valid_train(map_data, r_station_id, p_station_id, item_type)
--check layout validity for both stations
local capacity = (is_fluid and train.fluid_capacity) or train.item_slot_capacity
if
capacity > 0 and
capacity > min_amount_to_move and
btest(netand, depot.network_flag) and
(r_station.is_all or r_station.accepted_layouts[layout_id]) and
(p_station.is_all or p_station.accepted_layouts[layout_id])
(r_station.allows_all_trains or r_station.accepted_layouts[layout_id]) and
(p_station.allows_all_trains or p_station.accepted_layouts[layout_id])
then
valid_train_exists = true
--check if exists valid path
@@ -227,48 +170,35 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p
---@type string
local network_name = depot.network_name
local requests = {}
local manifest = {}
local r_signals = r_station.tick_signals
if r_signals then
for k, v in pairs(r_signals) do
---@type string
local item_name = v.signal.name
local item_count = v.count
local effective_item_count = item_count + (r_station.deliveries[item_name] or 0)
if effective_item_count < 0 and item_count < 0 then
requests[item_name] = -effective_item_count
end
end
end
local p_signals = p_station.tick_signals
if p_signals then
for k, v in pairs(p_signals) do
local item_name = v.signal.name
local item_count = v.count
local item_type = v.signal.type
local effective_item_count = item_count + (p_station.deliveries[item_name] or 0)
if effective_item_count > 0 and item_count > 0 then
local r = requests[item_name]
if r then
local item = {name = item_name, type = item_type, count = min(r, effective_item_count)}
if item_name == primary_item_name then
manifest[#manifest + 1] = manifest[1]
manifest[1] = item
else
manifest[#manifest + 1] = item
end
for k, v in pairs(r_station.tick_signals) do
---@type string
local item_name = v.signal.name
local item_type = v.signal.type
local r_item_count = v.count
local r_effective_item_count = r_item_count + (r_station.deliveries[item_name] or 0)
if r_effective_item_count < 0 and r_item_count < 0 then
local r_threshold = r_station.p_count_or_r_threshold_per_item[item_name]
local p_effective_item_count = p_station.p_count_or_r_threshold_per_item[item_name]
if p_effective_item_count and p_effective_item_count >= r_threshold then
local item = {name = item_name, type = item_type, count = min(-r_effective_item_count, p_effective_item_count)}
if item_name == primary_item_name then
manifest[#manifest + 1] = manifest[1]
manifest[1] = item
else
manifest[#manifest + 1] = item
end
end
end
end
local locked_slots = max(p_station.locked_slots, r_station.locked_slots)
--locked slots is only taken into account after the train is already approved for dispatch
local locked_slots = p_station.locked_slots
local total_slots_left = train.item_slot_capacity
if locked_slots > 0 then
total_slots_left = max(total_slots_left - #train.entity.cargo_wagons*locked_slots, min(total_slots_left, #train.entity.cargo_wagons))
local total_cw = #train.entity.cargo_wagons
total_slots_left = min(total_slots_left, max(total_slots_left - total_cw*locked_slots, total_cw))
end
local total_liquid_left = train.fluid_capacity
@@ -307,7 +237,6 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p
r_station.deliveries_total = r_station.deliveries_total + 1
p_station.deliveries_total = p_station.deliveries_total + 1
assert(manifest[1].name == primary_item_name)
for item_i, item in ipairs(manifest) do
assert(item.count > 0, "main.lua error, transfer amount was not positive")
@@ -420,12 +349,12 @@ local function tick_poll_station(map_data, mod_settings)
if station.network_name and 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
station.locked_slots = 0
station.network_flag = mod_settings.network_flag
local signals = get_signals(station)
station.tick_signals = signals
table_clear(station.p_count_or_r_threshold_per_item)
if signals then
for k, v in pairs(signals) do
local item_name = v.signal.name
@@ -436,10 +365,8 @@ local function tick_poll_station(map_data, mod_settings)
if item_name == SIGNAL_PRIORITY then
station.priority = item_count
elseif item_name == REQUEST_THRESHOLD and item_count ~= 0 then
--NOTE: thresholds must be >0 or they will cause a crash
--NOTE: thresholds must be >0 or they can cause a crash
station.r_threshold = abs(item_count)
elseif item_name == PROVIDE_THRESHOLD and item_count ~= 0 then
station.p_threshold = abs(item_count)
elseif item_name == LOCKED_SLOTS then
station.locked_slots = max(item_count, 0)
end
@@ -453,12 +380,13 @@ local function tick_poll_station(map_data, mod_settings)
end
end
for k, v in pairs(signals) do
---@type string
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)
local r_threshold = get_threshold(map_data, station, v.signal)
if -effective_item_count >= r_threshold and -item_count >= r_threshold then
if station.is_r and -effective_item_count >= r_threshold and -item_count >= r_threshold then
local item_network_name = station.network_name..":"..item_name
local stations = all_r_stations[item_network_name]
if stations == nil then
@@ -468,7 +396,8 @@ local function tick_poll_station(map_data, mod_settings)
all_names[#all_names + 1] = v.signal
end
stations[#stations + 1] = station_id
elseif effective_item_count >= p_threshold and item_count >= p_threshold then
station.p_count_or_r_threshold_per_item[item_name] = r_threshold
elseif station.is_p and effective_item_count > 0 and item_count > 0 then
local item_network_name = station.network_name..":"..item_name
local stations = all_p_stations[item_network_name]
if stations == nil then
@@ -476,6 +405,7 @@ local function tick_poll_station(map_data, mod_settings)
all_p_stations[item_network_name] = stations
end
stations[#stations + 1] = station_id
station.p_count_or_r_threshold_per_item[item_name] = effective_item_count
else
signals[k] = nil
end
@@ -544,6 +474,10 @@ local function tick_dispatch(map_data, mod_settings)
end
local r_station_id = table_remove(r_stations--[[@as uint[] ]])
local r_station = stations[r_station_id]
local item_name = tick_data.item_name
local item_type = tick_data.item_type
local r_threshold = r_station.p_count_or_r_threshold_per_item[item_name]
local best = 0
local best_depot = nil
@@ -551,24 +485,27 @@ local function tick_dispatch(map_data, mod_settings)
local highest_prior = -INF
local could_have_been_serviced = false
for j, p_station_id in ipairs(p_stations) do
local depot, d = get_valid_train(map_data, r_station_id, p_station_id, tick_data.item_type)
local prior = stations[p_station_id].priority
if prior > highest_prior or (prior == highest_prior and d < best_dist) then
if depot then
best = j
best_dist = d
best_depot = depot
highest_prior = prior
elseif d < INF then
could_have_been_serviced = true
best = j
local p_station = stations[p_station_id]
if p_station.p_count_or_r_threshold_per_item[item_name] >= r_threshold then
local prior = p_station.priority
local depot, d = get_valid_train(map_data, r_station_id, p_station_id, item_type, r_threshold)
if prior > highest_prior or (prior == highest_prior and d < best_dist) then
if depot then
best = j
best_dist = d
best_depot = depot
highest_prior = prior
elseif d < INF then
could_have_been_serviced = true
best = j
end
end
end
end
if best_depot then
send_train_between(map_data, r_station_id, table_remove(p_stations, best), best_depot, tick_data.item_name)
send_train_between(map_data, r_station_id, table_remove(p_stations, best), best_depot, item_name)
elseif could_have_been_serviced then
send_missing_train_alert_for_stops(stations[r_station_id].entity_stop, stations[p_stations[best]].entity_stop)
send_missing_train_alert_for_stops(r_station.entity_stop, stations[p_stations[best]].entity_stop)
end
return false
end

View File

@@ -0,0 +1,100 @@
--By Mami
local abs = math.abs
local floor = math.floor
---@param param ArithmeticCombinatorParameters
function get_comb_secondary_state(param)
local bits = param.second_constant or 0
return bits%2 == 1, floor(bits/2)%3
end
---@param depot Depot
function set_depot_from_comb_state(depot)
local param = depot.entity_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local signal = param.first_signal
depot.network_name = signal and signal.name or nil
end
---@param station Station
function set_station_from_comb_state(station)
--NOTE: this does nothing to update currently active deliveries
local param = station.entity_comb1.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local bits = param.second_constant or 0
local is_pr_state = floor(bits/2)%3
local signal = param.first_signal
station.network_name = signal and signal.name or nil
station.allows_all_trains = bits%2 == 1
station.is_p = is_pr_state == 0 or is_pr_state == 1
station.is_r = is_pr_state == 0 or is_pr_state == 2
end
---@param control LuaArithmeticCombinatorControlBehavior
function set_comb_allows_all_trains(control, allows_all_trains)
local param = control.parameters
local bits = param.second_constant or 0
param.second_constant = (bits - bits%2) + (allows_all_trains and 1 or 0)
control.parameters = param
end
---@param control LuaArithmeticCombinatorControlBehavior
function set_comb_is_pr_state(control, is_pr_state)
local param = control.parameters
local bits = param.second_constant or 0
param.second_constant = (bits%2) + (2*is_pr_state)
control.parameters = param
end
---@param map_data MapData
---@param comb LuaEntity
---@param signals ConstantCombinatorParameters[]?
function set_combinator_output(map_data, comb, signals)
local out = map_data.to_output[comb.unit_number]
if out.valid then
out.get_or_create_control_behavior().parameters = signals
end
end
---@param comb LuaEntity
---@param op string
function set_combinator_operation(comb, op)
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
control.operation = op
a.parameters = control
end
---@param station Station
function get_signals(station)
local comb = station.entity_comb1
if comb.valid and (comb.status == defines.entity_status.working or comb.status == defines.entity_status.low_power) then
return comb.get_merged_signals(defines.circuit_connector_id.combinator_input)
else
return nil
end
end
---@param map_data MapData
---@param station Station
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 is_fluid = game.item_prototypes[item_name] == nil--NOTE: this is expensive
signals[i] = {index = i, signal = {type = is_fluid and "fluid" or "item", 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 signal SignalID
function get_threshold(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 abs(count)
end
end
return station.r_threshold
end

View File

@@ -6,7 +6,6 @@ NONEMPTY_TRAIN_NAME = "cybersyn-nonempty-train"
SIGNAL_PRIORITY = "cybersyn-priority"
REQUEST_THRESHOLD = "cybersyn-request-threshold"
PROVIDE_THRESHOLD = "cybersyn-provide-threshold"
LOCKED_SLOTS = "cybersyn-locked-slots"
COMBINATOR_NAME = "cybersyn-combinator"
@@ -16,6 +15,7 @@ COMBINATOR_CLOSE_SOUND = "entity-close/cybersyn-combinator"
OPERATION_DEFAULT = "*"
OPERATION_PRIMARY_IO = "/"
OPERATION_PRIMARY_IO_ACTIVE = "^"
OPERATION_PRIMARY_IO_NOT_FOUND = "<<"
OPERATION_SECONDARY_IO = "%"
OPERATION_DEPOT = "+"
OPERATION_WAGON_MANIFEST = "-"

View File

@@ -16,11 +16,12 @@
---@field public economy Economy
---@class Station
---@field public is_p boolean
---@field public is_r boolean
---@field public deliveries_total int
---@field public last_delivery_tick int
---@field public priority int --transient
---@field public r_threshold int >= 0 --transient
---@field public p_threshold int >= 0 --transient
---@field public locked_slots int >= 0 --transient
---@field public entity_stop LuaEntity
---@field public entity_comb1 LuaEntity
@@ -29,10 +30,11 @@
---@field public deliveries {[string]: int}
---@field public network_name string?
---@field public network_flag int --transient
---@field public is_all boolean
---@field public allows_all_trains boolean
---@field public accepted_layouts TrainClass
---@field public layout_pattern string?
---@field public tick_signals {[uint]: Signal}? --transient
---@field public p_count_or_r_threshold_per_item {[string]: int}? --transient
---@class Depot
---@field public priority int --transient
@@ -67,12 +69,18 @@
---@class CybersynModSettings
---@field public tps int
---@field public r_threshold int
---@field public p_threshold int
---@field public network_flag int
---@type CybersynModSettings
mod_settings = {}
local pairs = pairs
function table_clear(tab)
for k, _ in pairs(tab) do
tab[k] = nil
end
end
function init_global()
global.total_ticks = 0
global.tick_state = STATE_INIT

View File

@@ -30,10 +30,21 @@ STATUS_NAMES_DEFAULT = "entity-status.disabled"
---@param player LuaPlayer
function gui_opened(comb, player)
local rootgui = player.gui.screen
local selected_index = 0
local control = comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local op = control.operation
if op == OPERATION_PRIMARY_IO or op == OPERATION_PRIMARY_IO_ACTIVE then
local selected_index = 0
local switch_state = "none"
local allows_all_trains, is_pr_state = get_comb_secondary_state(control)
if is_pr_state == 0 then
switch_state = "none"
elseif is_pr_state == 1 then
switch_state = "left"
elseif is_pr_state == 2 then
switch_state = "right"
end
if op == OPERATION_PRIMARY_IO or op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_NOT_FOUND then
selected_index = 1
elseif op == OPERATION_SECONDARY_IO then
selected_index = 2
@@ -43,61 +54,67 @@ function gui_opened(comb, player)
selected_index = 4
end
local window = flib_gui.build(rootgui, {
{type="frame", direction="vertical", ref={"main_window"}, name=COMBINATOR_NAME, 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 = {"close", comb.unit_number}
}}
}},
{type="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12}, 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, bottom_padding=4}, children={
{type="sprite", sprite=STATUS_SPRITES[comb.status] or STATUS_SPRITES_DEFAULT, style="status_image", ref={"status_icon"}, style_mods={stretch_image_to_widget_size=true}},
{type="label", caption={STATUS_NAMES[comb.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"}},
}},
--drop down
{type="label", style="heading_3_label", caption={"cybersyn-gui.operation"}, style_mods={top_padding=8}},
{type="drop-down", style_mods={top_padding=3}, ref={"operation"}, actions={
on_selection_state_changed={"drop-down", comb.unit_number}
}, selected_index=selected_index, items={
{"cybersyn-gui.comb1"},
{"cybersyn-gui.comb2"},
{"cybersyn-gui.depot"},
{"cybersyn-gui.wagon-manifest"},
}},
---choose-elem-button
{type="line", style_mods={top_padding=10}},
{type="label", name="network_label", ref={"network_label"}, style="heading_3_label", caption={"cybersyn-gui.network"}, style_mods={top_padding=7}},
{type="flow", name="bottom", direction="horizontal", children={
{type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", signal=control.first_signal, style_mods={bottom_margin=2, right_margin=6}, actions={
on_elem_changed={"choose-elem-button", comb.unit_number}
local window = flib_gui.build(rootgui, {
{type="frame", direction="vertical", ref={"main_window"}, name=COMBINATOR_NAME, 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 = {"close", comb.unit_number}
}}
}},
{type="frame", style="inside_shallow_frame_with_padding", style_mods={padding=12}, 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, bottom_padding=4}, children={
{type="sprite", sprite=STATUS_SPRITES[comb.status] or STATUS_SPRITES_DEFAULT, style="status_image", ref={"status_icon"}, style_mods={stretch_image_to_widget_size=true}},
{type="label", caption={STATUS_NAMES[comb.status] or STATUS_NAMES_DEFAULT}, ref={"status_label"}}
}},
{type="checkbox", name="radiobutton", ref={"radiobutton"}, state=control.second_constant ~= 1, style_mods={top_margin=4}, actions={
on_checked_state_changed={"radiobutton", comb.unit_number}
--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", name="radiolabel", style_mods={single_line=false, maximal_width=330, left_padding=3}, ref={"radiolabel"}, caption={"cybersyn-gui.auto-description"}},
--drop down
{type="label", style="heading_3_label", caption={"cybersyn-gui.operation"}, style_mods={top_padding=8}},
{type="flow", name="top", direction="horizontal", style_mods={vertical_align="center"}, children={
{type="drop-down", style_mods={top_padding=3, right_margin=8}, ref={"operation"}, actions={
on_selection_state_changed={"drop-down", comb.unit_number}
}, selected_index=selected_index, items={
{"cybersyn-gui.comb1"},
{"cybersyn-gui.comb2"},
{"cybersyn-gui.depot"},
{"cybersyn-gui.wagon-manifest"},
}},
{type="switch", name="switch", ref={"switch"}, allow_none_state=true, switch_state=switch_state, left_label_caption={"cybersyn-gui.switch-provide"}, right_label_caption={"cybersyn-gui.switch-request"}, left_label_tooltip={"cybersyn-gui.switch-provide-tooltip"}, right_label_tooltip={"cybersyn-gui.switch-request-tooltip"}, actions={
on_switch_state_changed={"switch", comb.unit_number}
}}
}},
---choose-elem-button
{type="line", style_mods={top_padding=10}},
{type="label", name="network_label", ref={"network_label"}, style="heading_3_label", caption={"cybersyn-gui.network"}, style_mods={top_padding=8}},
{type="flow", name="bottom", direction="horizontal", style_mods={vertical_align="center"}, children={
{type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=control.first_signal, style_mods={bottom_margin=1, right_margin=6}, actions={
on_elem_changed={"choose-elem-button", comb.unit_number}
}},
{type="checkbox", name="radio_button", ref={"radio_button"}, state=not allows_all_trains, tooltip={"cybersyn-gui.auto-tooltip"}, actions={
on_checked_state_changed={"radio_button", comb.unit_number}
}},
{type="label", name="radio_label", style_mods={left_padding=3}, ref={"radio_label"}, caption={"cybersyn-gui.auto-description"}},
}}
}}
}}
}}
}}
})
})
window.preview.entity = comb
window.titlebar.drag_target = window.main_window
window.main_window.force_auto_center()
window.network.visible = selected_index == 1 or selected_index == 3
window.network_label.visible = selected_index == 1 or selected_index == 3
window.radiobutton.visible = selected_index == 1
window.radiolabel.visible = selected_index == 1
window.radio_button.visible = selected_index == 1
window.radio_label.visible = selected_index == 1
window.switch.visible = selected_index == 1
player.opened = window.main_window
end
@@ -142,31 +159,37 @@ function register_gui_actions()
local comb = global.to_comb[msg[2]]
if not comb or not comb.valid then return end
local parent = element.parent.bottom
local top_flow = element.parent
local all_flow = top_flow.parent
local bottom_flow = all_flow.bottom
if element.selected_index == 1 then
set_combinator_operation(comb, OPERATION_PRIMARY_IO)
element.parent["network_label"].visible = true
parent["network"].visible = true
parent["radiobutton"].visible = true
parent["radiolabel"].visible = true
top_flow["switch"].visible = true
all_flow["network_label"].visible = true
bottom_flow["network"].visible = true
bottom_flow["radio_button"].visible = true
bottom_flow["radio_label"].visible = true
elseif element.selected_index == 2 then
set_combinator_operation(comb, OPERATION_SECONDARY_IO)
element.parent["network_label"].visible = false
parent["network"].visible = false
parent["radiobutton"].visible = false
parent["radiolabel"].visible = false
top_flow["switch"].visible = false
all_flow["network_label"].visible = false
bottom_flow["network"].visible = false
bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
elseif element.selected_index == 3 then
set_combinator_operation(comb, OPERATION_DEPOT)
element.parent["network_label"].visible = true
parent["network"].visible = true
parent["radiobutton"].visible = false
parent["radiolabel"].visible = false
top_flow["switch"].visible = false
all_flow["network_label"].visible = true
bottom_flow["network"].visible = true
bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
elseif element.selected_index == 4 then
set_combinator_operation(comb, OPERATION_WAGON_MANIFEST)
element.parent["network_label"].visible = false
parent["network"].visible = false
parent["radiobutton"].visible = false
parent["radiolabel"].visible = false
top_flow["switch"].visible = false
all_flow["network_label"].visible = false
bottom_flow["network"].visible = false
bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
else
return
end
@@ -188,28 +211,43 @@ function register_gui_actions()
else
control.first_signal = signal
end
a.parameters = control
on_combinator_network_updated(global, comb, signal and signal.name or nil)
elseif msg[1] == "radiobutton" then
elseif msg[1] == "radio_button" then
local element = event.element
if not element then return end
local comb = global.to_comb[msg[2]]
if not comb or not comb.valid then return end
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
local is_auto = element.state
control.second_constant = is_auto and 0 or 1
a.parameters = control
local allows_all_trains = element.state
set_comb_allows_all_trains(a, allows_all_trains)
local stop = global.to_stop[comb.unit_number]
if stop then
local station = global.stations[stop.unit_number]
if station then
set_station_train_class(global, station, not is_auto)
set_station_train_class(global, station, allows_all_trains)
end
end
elseif msg[1] == "switch" then
local element = event.element
if not element then return end
local comb = global.to_comb[msg[2]]
if not comb or not comb.valid then return end
local is_pr_state = (element.switch_state == "none" and 0) or (element.switch_state == "left" and 1) or 2
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
set_comb_is_pr_state(a, is_pr_state)
local stop = global.to_stop[comb.unit_number]
if stop then
local station = global.stations[stop.unit_number]
if station then
station.is_p = is_pr_state == 0 or is_pr_state == 1
station.is_r = is_pr_state == 0 or is_pr_state == 2
end
end
end

View File

@@ -447,11 +447,11 @@ end
---@param map_data MapData
---@param station Station
---@param is_all boolean
function set_station_train_class(map_data, station, is_all)
if station.is_all ~= is_all then
station.is_all = is_all
if not is_all then
---@param allows_all_trains boolean
function set_station_train_class(map_data, station, allows_all_trains)
if station.allows_all_trains ~= allows_all_trains then
station.allows_all_trains = allows_all_trains
if not allows_all_trains then
reset_station_layout(map_data, station, nil)
end
end
@@ -461,7 +461,7 @@ end
---@param station Station
---@param forbidden_entity LuaEntity?
function update_station_if_auto(map_data, station, forbidden_entity)
if not station.is_all then
if not station.allows_all_trains then
reset_station_layout(map_data, station, forbidden_entity)
end
end

View File

@@ -91,15 +91,16 @@ end
---@param map_data MapData
---@param stop LuaEntity
---@param comb LuaEntity
local function on_depot_built(map_data, stop, comb, control)
local function on_depot_built(map_data, stop, comb)
local depot = {
entity_stop = stop,
entity_comb = comb,
network_name = control.first_signal and control.first_signal.name or nil,
--network_name = nil,
priority = 0,
network_flag = 0,
}
map_data.depots[stop.unit_number] = depot
set_depot_from_comb_state(depot)
end
local function on_depot_broken(map_data, depot)
@@ -117,8 +118,7 @@ end
---@param stop LuaEntity
---@param comb1 LuaEntity
---@param comb2 LuaEntity
---@param control ArithmeticCombinatorParameters
local function on_station_built(map_data, stop, comb1, comb2, control)
local function on_station_built(map_data, stop, comb1, comb2)
local station = {
entity_stop = stop,
entity_comb1 = comb1,
@@ -130,13 +130,14 @@ local function on_station_built(map_data, stop, comb1, comb2, control)
r_threshold = 0,
p_threshold = 0,
locked_slots = 0,
network_name = control.first_signal and control.first_signal.name or nil,
--network_name = param.first_signal and param.first_signal.name or nil,
network_flag = 0,
deliveries = {},
is_all = control.second_constant == 1,
--allows_all_trains = param.second_constant == 1,
accepted_layouts = {},
layout_pattern = nil,
}
set_station_from_comb_state(station)
map_data.stations[stop.unit_number] = station
update_station_if_auto(map_data, station, nil)
@@ -244,18 +245,18 @@ local function on_combinator_built(map_data, comb)
map_data.to_output[comb.unit_number] = out
map_data.to_stop[comb.unit_number] = stop
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
local op = control.operation
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local param = control.parameters
local op = param.operation
if op == OPERATION_DEFAULT then
op = OPERATION_PRIMARY_IO
control.operation = op
control.first_signal = NETWORK_SIGNAL_DEFAULT
a.parameters = control
elseif op == OPERATION_PRIMARY_IO_ACTIVE then
param.operation = op
param.first_signal = NETWORK_SIGNAL_DEFAULT
control.parameters = param
elseif op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_NOT_FOUND then
op = OPERATION_PRIMARY_IO
control.operation = op
a.parameters = control
param.operation = op
control.parameters = param
end
if op == OPERATION_WAGON_MANIFEST then
if rail then
@@ -269,7 +270,7 @@ local function on_combinator_built(map_data, comb)
if depot or station then
--NOTE: repeated combinators are ignored
else
on_depot_built(map_data, stop, comb, control)
on_depot_built(map_data, stop, comb)
end
end
elseif op == OPERATION_SECONDARY_IO then
@@ -279,23 +280,23 @@ local function on_combinator_built(map_data, comb)
station.entity_comb2 = comb
end
end
elseif stop then
control.operation = OPERATION_PRIMARY_IO
local station = map_data.stations[stop.unit_number]
local depot = map_data.depots[stop.unit_number]
if station then
--NOTE: repeated combinators are ignored
else
if depot 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
elseif op == OPERATION_PRIMARY_IO then
if stop then
local station = map_data.stations[stop.unit_number]
if station then
--NOTE: repeated combinators are ignored
else
local depot = map_data.depots[stop.unit_number]
if depot then
on_depot_broken(map_data, depot)
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
--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, control)
end
end
end
@@ -341,14 +342,12 @@ local function on_combinator_broken(map_data, comb)
local comb1 = search_for_station_combinator(map_data, stop, OPERATION_PRIMARY_IO, comb)
if comb1 then
station.entity_comb1 = comb1
local control = comb1.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
station.network_name = control.first_signal and control.first_signal.name
set_station_from_comb_state(station)
else
on_station_broken(map_data, stop.unit_number, station)
local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb)
if depot_comb then
local control = depot_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
on_depot_built(map_data, stop, depot_comb, control.first_signal)
on_depot_built(map_data, stop, depot_comb)
end
end
elseif station.entity_comb2 == comb then
@@ -360,9 +359,8 @@ local function on_combinator_broken(map_data, comb)
--NOTE: this will disrupt deliveries in progress that where dispatched from this station in a minor way
local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb)
if depot_comb then
local control = depot_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
depot.entity_comb = depot_comb
depot.network_name = control.first_signal and control.first_signal.name
set_depot_from_comb_state(depot)
else
on_depot_broken(map_data, depot)
end
@@ -404,7 +402,7 @@ local function on_stop_built(map_data, stop)
map_data.to_stop[entity.unit_number] = stop
local control = entity.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local op = control.operation
if op == OPERATION_PRIMARY_IO then
if op == OPERATION_PRIMARY_IO or op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_NOT_FOUND then
comb1 = entity
elseif op == OPERATION_SECONDARY_IO then
comb2 = entity
@@ -414,9 +412,9 @@ local function on_stop_built(map_data, stop)
end
end
if comb1 then
on_station_built(map_data, stop, comb1, comb2, comb1.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]])
on_station_built(map_data, stop, comb1, comb2)
elseif depot_comb then
on_depot_built(map_data, stop, depot_comb, depot_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]])
on_depot_built(map_data, stop, depot_comb)
end
end
---@param map_data MapData
@@ -743,7 +741,6 @@ end
local function on_settings_changed(event)
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as int]]
mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]]
mod_settings.p_threshold = settings.global["cybersyn-provide-threshold"].value--[[@as int]]
mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]]
if event.setting == "cybersyn-ticks-per-second" then
local nth_tick = math.ceil(60/mod_settings.tps);
@@ -773,7 +770,6 @@ local filter_broken = {
local function main()
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as int]]
mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]]
mod_settings.p_threshold = settings.global["cybersyn-provide-threshold"].value--[[@as int]]
mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]]
--NOTE: There is a concern that it is possible to build or destroy important entities without one of these events being triggered, in which case the mod will have undefined behavior

View File

@@ -14,16 +14,7 @@ data:extend({
name = "cybersyn-request-threshold",
order = "ab",
setting_type = "runtime-global",
default_value = 2000000000,
minimum_value = 1,
maximum_value = 2147483647,
},
{
type = "int-setting",
name = "cybersyn-provide-threshold",
order = "ac",
setting_type = "runtime-global",
default_value = 2000000000,
default_value = 2000,
minimum_value = 1,
maximum_value = 2147483647,
},