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 Date: 2022-11-04
Features: Features:
- Pre-Alpha release - 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.constants")
require("scripts.global") require("scripts.global")
require("scripts.combinator")
require("scripts.central-planning") require("scripts.central-planning")
require("scripts.layout") require("scripts.layout")
require("scripts.gui") require("scripts.gui")

View File

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

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,20 +1,18 @@
[mod-setting-name] [mod-setting-name]
cybersyn-ticks-per-second=Dispatcher updates per second cybersyn-ticks-per-second=Dispatcher updates per second
cybersyn-request-threshold=Default requester threshold cybersyn-request-threshold=Default requester threshold
cybersyn-provide-threshold=Default provider threshold
cybersyn-network-flag=Default network flags cybersyn-network-flag=Default network flags
[mod-setting-description] [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-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-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. 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] [item-name]
cybersyn-combinator=Cybernetic combinator cybersyn-combinator=Cybernetic combinator
[item-description] [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] [entity-name]
cybersyn-combinator=Cybernetic combinator cybersyn-combinator=Cybernetic combinator
@@ -32,7 +30,6 @@ cybersyn-train-network=Train stop controllers capable of coordinating the inputs
[virtual-signal-name] [virtual-signal-name]
cybersyn-priority=Station priority cybersyn-priority=Station priority
cybersyn-provide-threshold=Provide threshold
cybersyn-request-threshold=Request threshold cybersyn-request-threshold=Request threshold
cybersyn-locked-slots=Locked slots per cargo wagon cybersyn-locked-slots=Locked slots per cargo wagon
@@ -49,4 +46,10 @@ comb2=Optional station control
depot=Depot control depot=Depot control
wagon-manifest=Wagon control wagon-manifest=Wagon control
network=Network 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", subgroup = "cybersyn-signal",
order = "a" 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 = { r_threshold_signal = {
type = "virtual-signal", type = "virtual-signal",
name = REQUEST_THRESHOLD, name = REQUEST_THRESHOLD,

View File

@@ -70,49 +70,6 @@ function create_manifest_schedule(depot_name, p_stop, r_stop, manifest)
}} }}
end 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 map_data MapData
---@param station Station ---@param station Station
---@param manifest Manifest ---@param manifest Manifest
@@ -128,20 +85,6 @@ function remove_manifest(map_data, station, manifest, sign)
station.deliveries_total = station.deliveries_total - 1 station.deliveries_total = station.deliveries_total - 1
end 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 stop0 LuaEntity
---@param stop1 LuaEntity ---@param stop1 LuaEntity
@@ -150,12 +93,12 @@ local function get_stop_dist(stop0, stop1)
end end
---@param map_data MapData ---@param map_data MapData
---@param r_station_id uint ---@param r_station_id uint
---@param p_station_id uint ---@param p_station_id uint
---@param item_type string ---@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 --NOTE: this code is the critical section for run-time optimization
local r_station = map_data.stations[r_station_id] local r_station = map_data.stations[r_station_id]
local p_station = map_data.stations[p_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 --check layout validity for both stations
local capacity = (is_fluid and train.fluid_capacity) or train.item_slot_capacity local capacity = (is_fluid and train.fluid_capacity) or train.item_slot_capacity
if if
capacity > 0 and capacity > min_amount_to_move and
btest(netand, depot.network_flag) and btest(netand, depot.network_flag) and
(r_station.is_all or r_station.accepted_layouts[layout_id]) and (r_station.allows_all_trains or r_station.accepted_layouts[layout_id]) and
(p_station.is_all or p_station.accepted_layouts[layout_id]) (p_station.allows_all_trains or p_station.accepted_layouts[layout_id])
then then
valid_train_exists = true valid_train_exists = true
--check if exists valid path --check if exists valid path
@@ -227,33 +170,19 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p
---@type string ---@type string
local network_name = depot.network_name local network_name = depot.network_name
local requests = {}
local manifest = {} local manifest = {}
local r_signals = r_station.tick_signals for k, v in pairs(r_station.tick_signals) do
if r_signals then
for k, v in pairs(r_signals) do
---@type string ---@type string
local item_name = v.signal.name 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 item_type = v.signal.type
local effective_item_count = item_count + (p_station.deliveries[item_name] or 0) local r_item_count = v.count
if effective_item_count > 0 and item_count > 0 then local r_effective_item_count = r_item_count + (r_station.deliveries[item_name] or 0)
local r = requests[item_name] if r_effective_item_count < 0 and r_item_count < 0 then
if r then local r_threshold = r_station.p_count_or_r_threshold_per_item[item_name]
local item = {name = item_name, type = item_type, count = min(r, effective_item_count)} 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 if item_name == primary_item_name then
manifest[#manifest + 1] = manifest[1] manifest[#manifest + 1] = manifest[1]
manifest[1] = item manifest[1] = item
@@ -263,12 +192,13 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p
end end
end 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 local total_slots_left = train.item_slot_capacity
if locked_slots > 0 then 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 end
local total_liquid_left = train.fluid_capacity 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 r_station.deliveries_total = r_station.deliveries_total + 1
p_station.deliveries_total = p_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 for item_i, item in ipairs(manifest) do
assert(item.count > 0, "main.lua error, transfer amount was not positive") 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 if station.network_name and station.deliveries_total < station.entity_stop.trains_limit then
station.r_threshold = mod_settings.r_threshold station.r_threshold = mod_settings.r_threshold
station.p_threshold = mod_settings.p_threshold
station.priority = 0 station.priority = 0
station.locked_slots = 0 station.locked_slots = 0
station.network_flag = mod_settings.network_flag station.network_flag = mod_settings.network_flag
local signals = get_signals(station) local signals = get_signals(station)
station.tick_signals = signals station.tick_signals = signals
table_clear(station.p_count_or_r_threshold_per_item)
if signals then if signals then
for k, v in pairs(signals) do for k, v in pairs(signals) do
local item_name = v.signal.name 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 if item_name == SIGNAL_PRIORITY then
station.priority = item_count station.priority = item_count
elseif item_name == REQUEST_THRESHOLD and item_count ~= 0 then 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) 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 elseif item_name == LOCKED_SLOTS then
station.locked_slots = max(item_count, 0) station.locked_slots = max(item_count, 0)
end end
@@ -453,12 +380,13 @@ local function tick_poll_station(map_data, mod_settings)
end end
end end
for k, v in pairs(signals) do for k, v in pairs(signals) do
---@type string
local item_name = v.signal.name local item_name = v.signal.name
local item_count = v.count local item_count = v.count
local effective_item_count = item_count + (station.deliveries[item_name] or 0) 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 item_network_name = station.network_name..":"..item_name
local stations = all_r_stations[item_network_name] local stations = all_r_stations[item_network_name]
if stations == nil then if stations == nil then
@@ -468,7 +396,8 @@ local function tick_poll_station(map_data, mod_settings)
all_names[#all_names + 1] = v.signal all_names[#all_names + 1] = v.signal
end end
stations[#stations + 1] = station_id 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 item_network_name = station.network_name..":"..item_name
local stations = all_p_stations[item_network_name] local stations = all_p_stations[item_network_name]
if stations == nil then if stations == nil then
@@ -476,6 +405,7 @@ local function tick_poll_station(map_data, mod_settings)
all_p_stations[item_network_name] = stations all_p_stations[item_network_name] = stations
end end
stations[#stations + 1] = station_id stations[#stations + 1] = station_id
station.p_count_or_r_threshold_per_item[item_name] = effective_item_count
else else
signals[k] = nil signals[k] = nil
end end
@@ -544,6 +474,10 @@ local function tick_dispatch(map_data, mod_settings)
end end
local r_station_id = table_remove(r_stations--[[@as uint[] ]]) 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 = 0
local best_depot = nil local best_depot = nil
@@ -551,8 +485,10 @@ local function tick_dispatch(map_data, mod_settings)
local highest_prior = -INF local highest_prior = -INF
local could_have_been_serviced = false local could_have_been_serviced = false
for j, p_station_id in ipairs(p_stations) do 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 p_station = stations[p_station_id]
local prior = stations[p_station_id].priority 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 prior > highest_prior or (prior == highest_prior and d < best_dist) then
if depot then if depot then
best = j best = j
@@ -565,10 +501,11 @@ local function tick_dispatch(map_data, mod_settings)
end end
end end
end end
end
if best_depot then 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 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 end
return false return false
end 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" SIGNAL_PRIORITY = "cybersyn-priority"
REQUEST_THRESHOLD = "cybersyn-request-threshold" REQUEST_THRESHOLD = "cybersyn-request-threshold"
PROVIDE_THRESHOLD = "cybersyn-provide-threshold"
LOCKED_SLOTS = "cybersyn-locked-slots" LOCKED_SLOTS = "cybersyn-locked-slots"
COMBINATOR_NAME = "cybersyn-combinator" COMBINATOR_NAME = "cybersyn-combinator"
@@ -16,6 +15,7 @@ COMBINATOR_CLOSE_SOUND = "entity-close/cybersyn-combinator"
OPERATION_DEFAULT = "*" OPERATION_DEFAULT = "*"
OPERATION_PRIMARY_IO = "/" OPERATION_PRIMARY_IO = "/"
OPERATION_PRIMARY_IO_ACTIVE = "^" OPERATION_PRIMARY_IO_ACTIVE = "^"
OPERATION_PRIMARY_IO_NOT_FOUND = "<<"
OPERATION_SECONDARY_IO = "%" OPERATION_SECONDARY_IO = "%"
OPERATION_DEPOT = "+" OPERATION_DEPOT = "+"
OPERATION_WAGON_MANIFEST = "-" OPERATION_WAGON_MANIFEST = "-"

View File

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

View File

@@ -30,10 +30,21 @@ STATUS_NAMES_DEFAULT = "entity-status.disabled"
---@param player LuaPlayer ---@param player LuaPlayer
function gui_opened(comb, player) function gui_opened(comb, player)
local rootgui = player.gui.screen local rootgui = player.gui.screen
local selected_index = 0
local control = comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] local control = comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local op = control.operation 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 selected_index = 1
elseif op == OPERATION_SECONDARY_IO then elseif op == OPERATION_SECONDARY_IO then
selected_index = 2 selected_index = 2
@@ -66,7 +77,8 @@ local window = flib_gui.build(rootgui, {
}}, }},
--drop down --drop down
{type="label", style="heading_3_label", caption={"cybersyn-gui.operation"}, style_mods={top_padding=8}}, {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={ {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} on_selection_state_changed={"drop-down", comb.unit_number}
}, selected_index=selected_index, items={ }, selected_index=selected_index, items={
{"cybersyn-gui.comb1"}, {"cybersyn-gui.comb1"},
@@ -74,17 +86,21 @@ local window = flib_gui.build(rootgui, {
{"cybersyn-gui.depot"}, {"cybersyn-gui.depot"},
{"cybersyn-gui.wagon-manifest"}, {"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 ---choose-elem-button
{type="line", style_mods={top_padding=10}}, {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="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", children={ {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", signal=control.first_signal, style_mods={bottom_margin=2, right_margin=6}, actions={ {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} on_elem_changed={"choose-elem-button", comb.unit_number}
}}, }},
{type="checkbox", name="radiobutton", ref={"radiobutton"}, state=control.second_constant ~= 1, style_mods={top_margin=4}, actions={ {type="checkbox", name="radio_button", ref={"radio_button"}, state=not allows_all_trains, tooltip={"cybersyn-gui.auto-tooltip"}, actions={
on_checked_state_changed={"radiobutton", comb.unit_number} on_checked_state_changed={"radio_button", comb.unit_number}
}}, }},
{type="label", name="radiolabel", style_mods={single_line=false, maximal_width=330, left_padding=3}, ref={"radiolabel"}, caption={"cybersyn-gui.auto-description"}}, {type="label", name="radio_label", style_mods={left_padding=3}, ref={"radio_label"}, caption={"cybersyn-gui.auto-description"}},
}} }}
}} }}
}} }}
@@ -96,8 +112,9 @@ local window = flib_gui.build(rootgui, {
window.main_window.force_auto_center() window.main_window.force_auto_center()
window.network.visible = selected_index == 1 or selected_index == 3 window.network.visible = selected_index == 1 or selected_index == 3
window.network_label.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.radio_button.visible = selected_index == 1
window.radiolabel.visible = selected_index == 1 window.radio_label.visible = selected_index == 1
window.switch.visible = selected_index == 1
player.opened = window.main_window player.opened = window.main_window
end end
@@ -142,31 +159,37 @@ function register_gui_actions()
local comb = global.to_comb[msg[2]] local comb = global.to_comb[msg[2]]
if not comb or not comb.valid then return end 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 if element.selected_index == 1 then
set_combinator_operation(comb, OPERATION_PRIMARY_IO) set_combinator_operation(comb, OPERATION_PRIMARY_IO)
element.parent["network_label"].visible = true top_flow["switch"].visible = true
parent["network"].visible = true all_flow["network_label"].visible = true
parent["radiobutton"].visible = true bottom_flow["network"].visible = true
parent["radiolabel"].visible = true bottom_flow["radio_button"].visible = true
bottom_flow["radio_label"].visible = true
elseif element.selected_index == 2 then elseif element.selected_index == 2 then
set_combinator_operation(comb, OPERATION_SECONDARY_IO) set_combinator_operation(comb, OPERATION_SECONDARY_IO)
element.parent["network_label"].visible = false top_flow["switch"].visible = false
parent["network"].visible = false all_flow["network_label"].visible = false
parent["radiobutton"].visible = false bottom_flow["network"].visible = false
parent["radiolabel"].visible = false bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
elseif element.selected_index == 3 then elseif element.selected_index == 3 then
set_combinator_operation(comb, OPERATION_DEPOT) set_combinator_operation(comb, OPERATION_DEPOT)
element.parent["network_label"].visible = true top_flow["switch"].visible = false
parent["network"].visible = true all_flow["network_label"].visible = true
parent["radiobutton"].visible = false bottom_flow["network"].visible = true
parent["radiolabel"].visible = false bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
elseif element.selected_index == 4 then elseif element.selected_index == 4 then
set_combinator_operation(comb, OPERATION_WAGON_MANIFEST) set_combinator_operation(comb, OPERATION_WAGON_MANIFEST)
element.parent["network_label"].visible = false top_flow["switch"].visible = false
parent["network"].visible = false all_flow["network_label"].visible = false
parent["radiobutton"].visible = false bottom_flow["network"].visible = false
parent["radiolabel"].visible = false bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
else else
return return
end end
@@ -188,28 +211,43 @@ function register_gui_actions()
else else
control.first_signal = signal control.first_signal = signal
end end
a.parameters = control a.parameters = control
on_combinator_network_updated(global, comb, signal and signal.name or nil) 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 local element = event.element
if not element then return end if not element then return end
local comb = global.to_comb[msg[2]] local comb = global.to_comb[msg[2]]
if not comb or not comb.valid then return end if not comb or not comb.valid then return end
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]] local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
local is_auto = element.state local allows_all_trains = element.state
control.second_constant = is_auto and 0 or 1 set_comb_allows_all_trains(a, allows_all_trains)
a.parameters = control
local stop = global.to_stop[comb.unit_number] local stop = global.to_stop[comb.unit_number]
if stop then if stop then
local station = global.stations[stop.unit_number] local station = global.stations[stop.unit_number]
if station then 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 end
end end

View File

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

View File

@@ -91,15 +91,16 @@ end
---@param map_data MapData ---@param map_data MapData
---@param stop LuaEntity ---@param stop LuaEntity
---@param comb 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 = { local depot = {
entity_stop = stop, entity_stop = stop,
entity_comb = comb, entity_comb = comb,
network_name = control.first_signal and control.first_signal.name or nil, --network_name = nil,
priority = 0, priority = 0,
network_flag = 0, network_flag = 0,
} }
map_data.depots[stop.unit_number] = depot map_data.depots[stop.unit_number] = depot
set_depot_from_comb_state(depot)
end end
local function on_depot_broken(map_data, depot) local function on_depot_broken(map_data, depot)
@@ -117,8 +118,7 @@ end
---@param stop LuaEntity ---@param stop LuaEntity
---@param comb1 LuaEntity ---@param comb1 LuaEntity
---@param comb2 LuaEntity ---@param comb2 LuaEntity
---@param control ArithmeticCombinatorParameters local function on_station_built(map_data, stop, comb1, comb2)
local function on_station_built(map_data, stop, comb1, comb2, control)
local station = { local station = {
entity_stop = stop, entity_stop = stop,
entity_comb1 = comb1, entity_comb1 = comb1,
@@ -130,13 +130,14 @@ local function on_station_built(map_data, stop, comb1, comb2, control)
r_threshold = 0, r_threshold = 0,
p_threshold = 0, p_threshold = 0,
locked_slots = 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, network_flag = 0,
deliveries = {}, deliveries = {},
is_all = control.second_constant == 1, --allows_all_trains = param.second_constant == 1,
accepted_layouts = {}, accepted_layouts = {},
layout_pattern = nil, layout_pattern = nil,
} }
set_station_from_comb_state(station)
map_data.stations[stop.unit_number] = station map_data.stations[stop.unit_number] = station
update_station_if_auto(map_data, station, nil) 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_output[comb.unit_number] = out
map_data.to_stop[comb.unit_number] = stop map_data.to_stop[comb.unit_number] = stop
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]] local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters local param = control.parameters
local op = control.operation local op = param.operation
if op == OPERATION_DEFAULT then if op == OPERATION_DEFAULT then
op = OPERATION_PRIMARY_IO op = OPERATION_PRIMARY_IO
control.operation = op param.operation = op
control.first_signal = NETWORK_SIGNAL_DEFAULT param.first_signal = NETWORK_SIGNAL_DEFAULT
a.parameters = control control.parameters = param
elseif op == OPERATION_PRIMARY_IO_ACTIVE then elseif op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_NOT_FOUND then
op = OPERATION_PRIMARY_IO op = OPERATION_PRIMARY_IO
control.operation = op param.operation = op
a.parameters = control control.parameters = param
end end
if op == OPERATION_WAGON_MANIFEST then if op == OPERATION_WAGON_MANIFEST then
if rail then if rail then
@@ -269,7 +270,7 @@ local function on_combinator_built(map_data, comb)
if depot or station then if depot or station then
--NOTE: repeated combinators are ignored --NOTE: repeated combinators are ignored
else else
on_depot_built(map_data, stop, comb, control) on_depot_built(map_data, stop, comb)
end end
end end
elseif op == OPERATION_SECONDARY_IO then elseif op == OPERATION_SECONDARY_IO then
@@ -279,23 +280,23 @@ local function on_combinator_built(map_data, comb)
station.entity_comb2 = comb station.entity_comb2 = comb
end end
end end
elseif stop then elseif op == OPERATION_PRIMARY_IO then
control.operation = OPERATION_PRIMARY_IO if stop then
local station = map_data.stations[stop.unit_number] local station = map_data.stations[stop.unit_number]
local depot = map_data.depots[stop.unit_number]
if station then if station then
--NOTE: repeated combinators are ignored --NOTE: repeated combinators are ignored
else else
local depot = map_data.depots[stop.unit_number]
if depot then if depot then
--NOTE: this will disrupt deliveries in progress that where dispatched from this station in a minor way on_depot_broken(map_data, depot)
map_data.depots[stop.unit_number] = nil
end end
--no station or depot --no station or depot
--add station --add station
local comb2 = search_for_station_combinator(map_data, stop, OPERATION_SECONDARY_IO, comb) local comb2 = search_for_station_combinator(map_data, stop, OPERATION_SECONDARY_IO, comb)
on_station_built(map_data, stop, comb, comb2, control) on_station_built(map_data, stop, comb, comb2)
end
end end
end 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) local comb1 = search_for_station_combinator(map_data, stop, OPERATION_PRIMARY_IO, comb)
if comb1 then if comb1 then
station.entity_comb1 = comb1 station.entity_comb1 = comb1
local control = comb1.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] set_station_from_comb_state(station)
station.network_name = control.first_signal and control.first_signal.name
else else
on_station_broken(map_data, stop.unit_number, station) on_station_broken(map_data, stop.unit_number, station)
local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb) local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb)
if depot_comb then if depot_comb then
local control = depot_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] on_depot_built(map_data, stop, depot_comb)
on_depot_built(map_data, stop, depot_comb, control.first_signal)
end end
end end
elseif station.entity_comb2 == comb then 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 --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) local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb)
if depot_comb then if depot_comb then
local control = depot_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
depot.entity_comb = depot_comb depot.entity_comb = depot_comb
depot.network_name = control.first_signal and control.first_signal.name set_depot_from_comb_state(depot)
else else
on_depot_broken(map_data, depot) on_depot_broken(map_data, depot)
end end
@@ -404,7 +402,7 @@ local function on_stop_built(map_data, stop)
map_data.to_stop[entity.unit_number] = stop map_data.to_stop[entity.unit_number] = stop
local control = entity.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]] local control = entity.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local op = control.operation 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 comb1 = entity
elseif op == OPERATION_SECONDARY_IO then elseif op == OPERATION_SECONDARY_IO then
comb2 = entity comb2 = entity
@@ -414,9 +412,9 @@ local function on_stop_built(map_data, stop)
end end
end end
if comb1 then 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 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
end end
---@param map_data MapData ---@param map_data MapData
@@ -743,7 +741,6 @@ end
local function on_settings_changed(event) local function on_settings_changed(event)
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as int]] 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.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]] mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]]
if event.setting == "cybersyn-ticks-per-second" then if event.setting == "cybersyn-ticks-per-second" then
local nth_tick = math.ceil(60/mod_settings.tps); local nth_tick = math.ceil(60/mod_settings.tps);
@@ -773,7 +770,6 @@ local filter_broken = {
local function main() local function main()
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as int]] 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.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]] 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 --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", name = "cybersyn-request-threshold",
order = "ab", order = "ab",
setting_type = "runtime-global", setting_type = "runtime-global",
default_value = 2000000000, default_value = 2000,
minimum_value = 1,
maximum_value = 2147483647,
},
{
type = "int-setting",
name = "cybersyn-provide-threshold",
order = "ac",
setting_type = "runtime-global",
default_value = 2000000000,
minimum_value = 1, minimum_value = 1,
maximum_value = 2147483647, maximum_value = 2147483647,
}, },