mirror of
https://github.com/Xevion/project-cybersyn.git
synced 2025-12-06 03:16:05 -06:00
Experimental 1.2.2 (#21)
---------------------------------------------------------------------------------------------------
Version: 1.2.2
Date: 2022-12-29
Features:
- Added a station combinator setting to enable or disable the inactivity condition in a train's orders, disabled by default (but not in <=1.2.1 worlds)
- Added a depot combinator setting to enable depot bypass, enabled by default
- Added a depot combinator setting to force trains to park at the same depot, enabled by default
- Added network "each" for depots
- Added a map setting to modify the default locked slots per cargo wagon value
- Added a map setting to modify the default priority value
- Added a map setting to allow trains with cargo at depots, disabled by default
Changes:
- Inverted the sign of combinator outputs, a map setting has been added to maintain backwards compatibility with <=1.2.1 worlds
- Overhauled the wagon control combinator algorithm to spread items out between cargo wagons
- Trains with cargo held in the depot now check if they have been emptied and reset when they have
- Cargo capacity is now prioritized over distance when choosing trains
- Increased the default request threshold to 2000
- Improved English localization
Bugfixes:
- Fixed a bug where trains with cargo sometimes weren't getting held at depots
- Fixed a crash caused by changing a station combinator to the "each" network during a bad tick
- Fixed a crash when changing a refueler away from network each
- Multiple rare bugs and crashes relating to wagon control combinators are fixed
- Fixed a bug with refueler direct orders not being applied after moving through a space elevator
- Fixed a bug where filtered slots sometimes weren't being removed
---------------------------------------------------------------------------------------------------
This commit is contained in:
20
README.md
20
README.md
@@ -6,6 +6,8 @@ Behold one of the most feature-rich and performant train logistics network mods
|
||||
|
||||
## Quick Start Guide
|
||||
|
||||
Copy the contents of [Project Cybersyn Official Example Blueprints](https://raw.githubusercontent.com/mamoniot/project-cybersyn/main/cybersyn_blueprints.txt) and paste them into the import blueprint text box to see examples of how to create a functional network. I highly recommend taking a look at these; the blueprint book showcases both the basics of the mod and highly advanced designs you can create.
|
||||
|
||||
Within Project Cybersyn, you can think of requester stations as requester chests, provider stations as passive provider chests, depots as roboports and trains as the logistics bots. There is a direct correspondence between the Cybersyn train network and Factorio's robot logistics network.
|
||||
|
||||
A bare minimum Cybersyn train network consists of 2 components: depots and stations. Both are created by placing a cybernetic combinator adjacent to a train stop. Select the "Mode" of the combinator to "Station" to create a station, and to "Depot" to create a depot. Create a basic train and order it to park at the depot you just created, it is now controlled by the Cybersyn network. Depots and stations can have any train stop name, names do not impact their function. The circuit network input of a station's cybernetic combinator determines what items that station will request or provide to the Cybersyn network. A positive item signal is interpreted as that station providing that item to the network; A negative item signal is interpreted as that station requesting that item from the network.
|
||||
@@ -15,7 +17,7 @@ A bare minimum Cybersyn train network consists of 2 components: depots and stati
|
||||
|
||||
To make a basic provider station, create an item buffer of chests or tanks adjacent to the station's tracks, and connect that buffer by wire to the input of the cybernetic combinator. To make a basic requester station, repeat the same, except reverse the direction of the inserters or pumps so they are *unloading* instead of loading; then connect a constant combinator to the same circuit network, set it to output the number of item you want this requester station to keep loaded in its item buffer, and flip the sign of each so the signal strength is negative. Once the provider station contains the item being requested, a train will automatically be sent to deliver that item from the provider station to the requester station. The requester station's buffer will automatically be topped up on the item being requested. Be sure that the requester station has the space to at minimum unload 2 fully loaded trains.
|
||||
|
||||
Follow the above directions and you have set up a bare minimum Cybersyn network! You may continue adding onto it with more stations and depots and Cybersyn will automatically manage all of them for you. At some point you may notice small hiccups within this network, like trains attempting to deliver a tiny amount of an item instead of a full cargo load, or you may want to extend your network with things like multi-item stations or centralized train refueling. In either case refer to **Mod Details** below for a in depth explanation of every feature within this mod.
|
||||
Follow the above directions and you have set up a bare minimum Cybersyn network! You may continue adding onto it with more stations and depots and Cybersyn will automatically manage all of them for you. There is one issue with this kind of network though; trains won't always deliver full loads of cargo, meaning trains will make deliveries more frequently than is necessary. To fix this issue you will need to start using "request thresholds". To get a full picture of how request thresholds work, either import the official example blueprints from above, or read the **Request thresholds** section below.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -37,7 +39,7 @@ These all combine to make it possible to **create "universal" stations**; statio
|
||||
|
||||
Stations can **automatically build allow-lists for trains** they can load or unload. Inserters or pumps adjacent to the station's tracks are auto-detected. No more deadlocks caused by trains mistakenly attempting to fulfill a delivery to a station that cannot unload it. This feature is compatible with miniloaders.
|
||||
|
||||
Trains can automatically visit **centralized fuel loaders**. It is not required that every single depot loads trains with fuel.
|
||||
Trains can automatically visit **centralized refuelers**. It is not required that every single depot loads trains with fuel.
|
||||
|
||||
Trains can **bypass visiting the depot** if they have enough fuel. Trains spend far more time productively making deliveries rather than travelling to and from their depot. Fewer reserve trains are needed as a result.
|
||||
|
||||
@@ -69,7 +71,7 @@ This mod adds a single new entity to the game, the cybernetic combinator. This c
|
||||
|
||||

|
||||
|
||||
When placed adjacent to a vanilla train stop, a Cybersyn station is created. This station can provide or request items to your train network. Connect the input of the combinator to a circuit network; When a positive item signal is received, this station will provide that item to the network, when a negative signal is received, this station will request that item from the network. When a station is providing an item that another station is requesting, a train order will automatically be generated to transfer those items from the providing station to the requesting station. When a train arrives to fulfill this order, the output of the combinator will give the full list of items expected to be loaded (positive) or unloaded (negative) from the train.
|
||||
When placed adjacent to a vanilla train stop, a Cybersyn station is created. This station can provide or request items to your train network. Connect the input of the combinator to a circuit network; When a positive item signal is received, this station will provide that item to the network, when a negative signal is received, this station will request that item from the network. When a station is providing an item that another station is requesting, a train order will automatically be generated to transfer those items from the providing station to the requesting station. When a train arrives to fulfill this order, the output of the combinator will give the full list of items expected to be loaded (negative) or unloaded (positive) from the train.
|
||||
|
||||
Stations can automatically build allow-lists. When this option is enabled, only trains that can be loaded or unloaded by this station will be allowed to make deliveries to it. Stations determine this based on what inserters or pumps are present at this station along its tracks. When disabled, all trains within the network are allowed.
|
||||
|
||||
@@ -81,11 +83,11 @@ Stations can be set to provide only or request only. By default stations can bot
|
||||
|
||||
When placed adjacent to a vanilla train stop, a Cybersyn depot is created. Any train which parks at this depot will automatically be added to the train network. Whenever a train order is generated, if this train has the cargo capacity to fulfill it, and is allow-listed by both stations, then it will automatically be dispatched to fulfill the order. When the order is completed, the train will return to any train stop with the same name as the depot it first parked in. This almost always means it returns to a Cybersyn depot where it will again await to fulfill a new order. To save on UPS the input of a depot combinator is only read when a train parks at the depot; this is only relevant for networks which make extensive use of network masks on depots.
|
||||
|
||||
### Fuel loader mode
|
||||
### Refueler mode
|
||||
|
||||
When placed adjacent to a vanilla train stop, a Cybersyn fuel loader is created. Whenever a train completes a delivery, if it is running low on fuel (configurable in mod settings), it will attempt to visit a fuel loader before returning to the depot. The train will search for a fuel loader within its network that has not exceeded its train limit and that it is allow-listed for. If one is found it will schedule a detour to it to stock back up on fuel.
|
||||
When placed adjacent to a vanilla train stop, a Cybersyn refueler is created. Whenever a train completes a delivery, if it is running low on fuel (configurable in mod settings), it will attempt to visit a refueler before returning to the depot. The train will search for a refueler within its network that has not exceeded its train limit and that it is allow-listed for. If one is found it will schedule a detour to it to stock back up on fuel.
|
||||
|
||||
Fuel loaders can automatically build allow-lists. When this option is enabled, trains will be prevented from parking at this station if one of their cargo wagons would be filled with fuel.
|
||||
Refuelers can automatically build allow-lists. When this option is enabled, trains will be prevented from parking at this station if one of their cargo wagons would be filled with fuel.
|
||||
|
||||
### Station control mode
|
||||
|
||||
@@ -107,11 +109,11 @@ When placed adjacent to the tracks of an already existing Cybersyn station, this
|
||||
|
||||

|
||||
|
||||
Stations, depots and fuel loaders can be set to belong to a particular network by setting that network on their combinator. By default all combinators belong to the "signal-A" network. By setting a different signal Id, the combinator will belong to that different network. Networks identified with different signal Ids do not share any trains or items; Orders will never be generated to transfer items between separate networks.
|
||||
Stations, depots and refuelers can be set to belong to a particular network by setting that network on their combinator. By default all combinators belong to the "signal-A" network. By setting a different signal Id, the combinator will belong to that different network. Networks identified with different signal Ids do not share any trains or items; Orders will never be generated to transfer items between separate networks.
|
||||
|
||||
In addition, if the combinator receives as input a signal of the same Id as its network signal Id, then the value of this signal will be interpreted as a bitmask to give 32 "sub-networks" to choose from. Each station can belong to any set of sub-networks based on its mask. A delivery will only be made between two stations if any two bits match between the two masks, i.e. if `mask1 & mask2 > 0`. When a network Id is an item, that item will be ignored by stations, its signal will only ever be interpreted as the network mask.
|
||||
|
||||
Stations and fuel loader combinators allow their network to be set to the "each" virtual signal. When in this mode, each virtual signal given to them as input is interpretted as a network mask for that network Id. The station or fuel loader is thus made a part of that network with the specified network mask. This allows you to union together as many different networks as you would like.
|
||||
A network can be set to the "each" virtual signal. When in this mode, each virtual signal given to them as input is interpretted as a network mask for that network Id. The stop is thus made a part of that network with the specified network mask. This allows you to union together as many different networks as you would like.
|
||||
|
||||
### Request threshold
|
||||
|
||||
@@ -127,7 +129,7 @@ After an order has been generated, enough items will be subtracted from that ord
|
||||
|
||||
### Priority
|
||||
|
||||
Orders will be generated first for stations, depots and fuel loaders which are receiving a higher priority signal than the others. If stations have the same priority, the least recently used requester station will be prioritized, and the provider station closest to the requester station will be prioritized. So in times of item shortage (front-pressure), round robin distribution will be used, and in times of item surplus (back-pressure), minimum travel distance distribution will be used. Provider stations will be prevented from providing items to lower priority requester stations until the highest priority requester station is satisfied.
|
||||
Orders will be generated first for stations, depots and refuelers which are receiving a higher priority signal than the others. If multiple depots or refuelers have the same priority, the closest one will be prioritized. Depots calculate distance based on the location of their train. If multiple stations have the same priority, the least recently used requester station will be prioritized, and the provider station closest to the requester station will be prioritized. So in times of item shortage (front-pressure), round robin distribution will be used, and in times of item surplus (back-pressure), minimum travel distance distribution will be used. Provider stations will be prevented from providing items to lower priority requester stations until the highest priority requester station is satisfied.
|
||||
|
||||
If a combinator set to station control mode receives a priority signal, for each item signal input to the combinator, items of that type will have its priority overridden in addition to its request threshold. This effectively allows you to choose one of two possible priorities for each item that a station processes.
|
||||
|
||||
|
||||
4
TODO
4
TODO
@@ -6,12 +6,12 @@ major:
|
||||
add in game guide
|
||||
move to an event based algorithm
|
||||
models & art
|
||||
train always returns to same depot setting
|
||||
make train inactivity condition a setting
|
||||
|
||||
minor:
|
||||
handle if signals are removed from the game during migration
|
||||
update wagon control combinators immediately upon placement
|
||||
railloader compat
|
||||
deadlocks signals compat
|
||||
close gui when the combinator is destroyed
|
||||
do not play close sound when a different gui is opened
|
||||
gui can desync if settings are changed outside of it while it is open
|
||||
|
||||
@@ -1,8 +1,33 @@
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 1.2.2
|
||||
Date: 2022-12-29
|
||||
Features:
|
||||
- Added a station combinator setting to enable or disable the inactivity condition in a train's orders, disabled by default (but not in <=1.2.1 worlds)
|
||||
- Added a depot combinator setting to enable depot bypass, enabled by default
|
||||
- Added a depot combinator setting to force trains to park at the same depot, enabled by default
|
||||
- Added network "each" for depots
|
||||
- Added a map setting to modify the default locked slots per cargo wagon value
|
||||
- Added a map setting to modify the default priority value
|
||||
- Added a map setting to allow trains with cargo at depots, disabled by default
|
||||
Changes:
|
||||
- Inverted the sign of combinator outputs, a map setting has been added to maintain backwards compatibility with <=1.2.1 worlds
|
||||
- Overhauled the wagon control combinator algorithm to spread items out between cargo wagons
|
||||
- Trains with cargo held in the depot now check if they have been emptied and reset when they have
|
||||
- Cargo capacity is now prioritized over distance when choosing trains
|
||||
- Increased the default request threshold to 2000
|
||||
- Improved English localization
|
||||
Bugfixes:
|
||||
- Fixed a bug where trains with cargo sometimes weren't getting held at depots
|
||||
- Fixed a crash caused by changing a station combinator to the "each" network during a bad tick
|
||||
- Fixed a crash when changing a refueler away from network each
|
||||
- Multiple rare bugs and crashes relating to wagon control combinators are fixed
|
||||
- Fixed a bug with refueler direct orders not being applied after moving through a space elevator
|
||||
- Fixed a bug where filtered slots sometimes weren't being removed
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 1.2.1
|
||||
Date: 2022-12-24
|
||||
Bugfixes:
|
||||
- Fixed an bug where sometimes refuelers would reject trains they should accept
|
||||
- Fixed a bug where sometimes refuelers would reject trains they should accept
|
||||
---------------------------------------------------------------------------------------------------
|
||||
Version: 1.2.0
|
||||
Date: 2022-12-23
|
||||
@@ -49,7 +74,7 @@ Date: 2022-12-9
|
||||
Version: 1.1.3
|
||||
Date: 2022-12-8
|
||||
Bugfixes:
|
||||
- Fixed a crash when removing a fuel loader
|
||||
- Fixed a crash when removing a refueler
|
||||
- Fixed a gui bug
|
||||
- Fixed a crash on newly generated worlds
|
||||
- Fixed a crash with breaking combinators
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
--<goto p_continue> at line 310 jumps into the scope of local 'p_flag'
|
||||
require("scripts.constants")
|
||||
require("scripts.global")
|
||||
require("scripts.lib")
|
||||
require("scripts.factorio-api")
|
||||
require("scripts.layout")
|
||||
require("scripts.central-planning")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cybersyn",
|
||||
"version": "1.2.1",
|
||||
"version": "1.2.2",
|
||||
"title": "Project Cybersyn",
|
||||
"author": "Mami",
|
||||
"factorio_version": "1.1",
|
||||
|
||||
@@ -2,21 +2,29 @@
|
||||
cybersyn-ticks-per-second=Central planning updates per second
|
||||
cybersyn-update-rate=Central planning update rate
|
||||
cybersyn-request-threshold=Default request threshold
|
||||
cybersyn-priority=Default priority
|
||||
cybersyn-locked-slots=Default locked slots per cargo wagon
|
||||
cybersyn-network-flag=Default network mask
|
||||
cybersyn-fuel-threshold=Fuel threshold
|
||||
cybersyn-depot-bypass-enabled=Depot bypass enabled
|
||||
cybersyn-warmup-time=Station warmup time (sec)
|
||||
cybersyn-stuck-train-time=Stuck train timeout (sec)
|
||||
cybersyn-allow-cargo-in-depot=Allow cargo in depots
|
||||
cybersyn-invert-sign=Invert combinator output (deprecated)
|
||||
|
||||
[mod-setting-description]
|
||||
cybersyn-ticks-per-second=How many times per second the central planner should update the state of the network and schedule deliveries. This value will be rounded up to a divisor of 60. Setting this to 0 will stop all dispatches.
|
||||
cybersyn-update-rate=How many stations per tick can be polled at once or can have deliveries scheduled at once. Larger number allow the central planner to keep more up to date on the current state of the network, but at the cost of performance.
|
||||
cybersyn-request-threshold=The default request threshold when a request threshold signal is not given to a station. When a station receives a negative item signal that surpasses its request threshold, so long as any station exists with a positive signal greater than the request threshold, a delivery of that item will be scheduled between the two stations.
|
||||
cybersyn-priority=The default priority when a priority signal is not given to a station, depot or refueler. Stations with higher priorities will receive deliveries before stations with lower priorities.
|
||||
cybersyn-locked-slots=The default number of locked slots per cargo wagon when a "locked slots per cargo wagon" signal is not given to a station. When a provider station has locked slots per cargo wagon of X, any train attempting to make a delivery from it will have its orders modified so every cargo wagon will have at least X item slots left empty. This is necessary to make multi-item provider stations function correctly.
|
||||
cybersyn-network-flag=The default set of sub-networks a station will service when no network signal is given to a station. This integer is interpretted bit-wise to give 32 possible sub-networks to choose from.
|
||||
cybersyn-fuel-threshold=What percentage of a train's fuel inventory must be full to skip refueling. If this is set to 1, trains will always visit a fuel loader after completing a delivery.
|
||||
cybersyn-fuel-threshold=What percentage of a train's fuel inventory must be full to skip refueling. If this is set to 1, trains will always visit a refueler after completing a delivery.
|
||||
cybersyn-depot-bypass-enabled=If checked, when a train completes a delivery and refueling, it may take a new order from the network before having to return to its depot.
|
||||
cybersyn-warmup-time=How many seconds a cybernetic combinator will wait before connecting to the Cybersyn network. This is a grace period to modify or correct the circuit network before trains start dispatching to a newly blueprinted station.
|
||||
cybersyn-stuck-train-time=After this many seconds from a train's dispatch, an alert will be sent to let you know a train is probably stuck and has not completed its delivery. The player will likely have to debug their network to get the train unstuck.
|
||||
cybersyn-allow-cargo-in-depot=If checked, trains will be allowed to have cargo in depots; no alerts will be generated and the train will not be held. In addition, trains with orders to visit requester stations with "Inactivity condition" checked will wait for inactivity instead of waiting for empty cargo. Useful for creating train systems where depots handle excess cargo. For advanced users only.
|
||||
cybersyn-invert-sign=Flip the sign of the output of cybernetic combinators to be the same as it is in LTN or in earlier versions of Project Cybersyn.
|
||||
|
||||
[item-name]
|
||||
cybersyn-combinator=Cybernetic combinator
|
||||
@@ -48,7 +56,7 @@ unexpected-train=A train has unexpectedly returned to the depot before completin
|
||||
stuck-train=A train is stuck
|
||||
cannot-path-between-surfaces=A train is attempting to make a delivery between two unconnected surfaces, perhaps put them on separate networks
|
||||
depot-broken=A train is lost because its depot was broken
|
||||
refueler-broken=A train is lost because its fuel loader was broken
|
||||
refueler-broken=A train is lost because its refueler was broken
|
||||
station-broken=A train is lost because one of its delivery stations was broken
|
||||
train-at-incorrect=A train parked at a station it was not scheduled to delivered to
|
||||
missing-train=Could not find any train on the correct network to make a delivery from __2__ to __1__
|
||||
@@ -61,16 +69,22 @@ combinator-title=Cybernetic combinator
|
||||
operation=Mode
|
||||
comb1=Station
|
||||
depot=Depot
|
||||
refueler=Fuel loader
|
||||
refueler=Refueler
|
||||
comb2=Station control
|
||||
wagon-manifest=Wagon control
|
||||
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.
|
||||
network=Network
|
||||
network-tooltip=A signal is used to identify which network this combinator is a member of. Trains will only be dispatched from depots to provider and requester stations if they are all identified with the same signal.
|
||||
allow-list-description=Automatic allow-list
|
||||
allow-list-tooltip=When checked trains in the network are automatically added to the allow-list if every wagon of the train is able to be loaded or unloaded by this station. When unchecked the allow-list is not used and all trains are allowed to park here.
|
||||
is-stack-description=Stack thresholds
|
||||
is-stack-tooltip=When checked all request thresholds for this station are interpretted as a count of item stacks rather than a count of total items. Thresholds for fluids are unaffected.
|
||||
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.
|
||||
enable-inactive-description=Inactivity condition
|
||||
enable-inactive-tooltip=When checked a train at a provider is required to wait for inactivity even if its order has been fulfilled. This is frequently useful for preventing inserters from getting items stuck in their hands.
|
||||
use-same-depot-description=Require same depot
|
||||
use-same-depot-tooltip=When checked trains from this depot always return to this depot. When unchecked the train is allowed to return to any depot with the same name as this one.
|
||||
depot-bypass-description=Depot bypass
|
||||
depot-bypass-tooltip=When checked trains from this depot do not have to be parked at this depot to receive new orders, they just have to have no current active orders. They will still return to this depot if they are low on fuel and no refuelers are available.
|
||||
|
||||
@@ -40,15 +40,13 @@ function create_delivery(map_data, r_station_id, p_station_id, train_id, manifes
|
||||
local r_station = map_data.stations[r_station_id]
|
||||
local p_station = map_data.stations[p_station_id]
|
||||
local train = map_data.trains[train_id]
|
||||
local depot = map_data.depots[train.depot_id]
|
||||
|
||||
local is_at_depot = remove_available_train(map_data, train_id, train)
|
||||
|
||||
remove_available_train(map_data, train_id, train)
|
||||
local depot_id = train.parked_at_depot_id
|
||||
if depot_id then
|
||||
map_data.depots[depot_id].available_train_id = nil
|
||||
train.parked_at_depot_id = nil
|
||||
end
|
||||
--NOTE: we assume that the train is not being teleported at this time
|
||||
if set_manifest_schedule(map_data, train.entity, train.depot_name, train.se_depot_surface_i, p_station.entity_stop, r_station.entity_stop, manifest, depot_id ~= nil) then
|
||||
--NOTE: set_manifest_schedule is allowed to cancel the delivery at the last second if applying the schedule to the train makes it lost
|
||||
if set_manifest_schedule(map_data, train.entity, depot.entity_stop, not train.use_any_depot, p_station.entity_stop, p_station.enable_inactive, r_station.entity_stop, mod_settings.allow_cargo_in_depot and r_station.enable_inactive--[[@as boolean]], manifest, is_at_depot) then
|
||||
local old_status = train.status
|
||||
train.status = STATUS_TO_P
|
||||
train.p_station_id = p_station_id
|
||||
@@ -155,10 +153,12 @@ function create_manifest(map_data, r_station_id, p_station_id, train_id, primary
|
||||
|
||||
--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_item_slots
|
||||
if locked_slots > 0 then
|
||||
local total_cw = #train.entity.cargo_wagons
|
||||
total_slots_left = min(total_slots_left, max(total_slots_left - total_cw*locked_slots, total_cw))
|
||||
local total_cargo_wagons = #train.entity.cargo_wagons
|
||||
total_item_slots = max(train.item_slot_capacity - total_cargo_wagons*locked_slots, 1)
|
||||
else
|
||||
total_item_slots = train.item_slot_capacity
|
||||
end
|
||||
local total_liquid_left = train.fluid_capacity
|
||||
|
||||
@@ -174,13 +174,13 @@ function create_manifest(map_data, r_station_id, p_station_id, train_id, primary
|
||||
total_liquid_left = 0--no liquid merging
|
||||
keep_item = true
|
||||
end
|
||||
elseif total_slots_left > 0 then
|
||||
elseif total_item_slots > 0 then
|
||||
local stack_size = get_stack_size(map_data, item.name)
|
||||
local slots = ceil(item.count/stack_size)
|
||||
if slots > total_slots_left then
|
||||
item.count = total_slots_left*stack_size
|
||||
if slots > total_item_slots then
|
||||
item.count = total_item_slots*stack_size
|
||||
end
|
||||
total_slots_left = total_slots_left - slots
|
||||
total_item_slots = total_item_slots - slots
|
||||
keep_item = true
|
||||
end
|
||||
if keep_item then
|
||||
@@ -329,7 +329,7 @@ local function tick_dispatch(map_data, mod_settings)
|
||||
---@type uint
|
||||
local j = 1
|
||||
while j <= #p_stations do
|
||||
local p_flag, r_flag, netand, best_p_train_id, best_t_prior, best_t_to_p_dist, effective_count, override_threshold, p_prior, best_p_dist
|
||||
local p_flag, r_flag, netand, best_p_train_id, best_t_prior, best_capacity, best_t_to_p_dist, effective_count, override_threshold, p_prior, best_p_dist
|
||||
|
||||
local p_station_id = p_stations[j]
|
||||
local p_station = stations[p_station_id]
|
||||
@@ -337,8 +337,8 @@ local function tick_dispatch(map_data, mod_settings)
|
||||
goto p_continue
|
||||
end
|
||||
|
||||
p_flag = p_station.network_name == NETWORK_EACH and (p_station.network_flag[network_name] or 0) or p_station.network_flag
|
||||
r_flag = r_station.network_name == NETWORK_EACH and (r_station.network_flag[network_name] or 0) or r_station.network_flag
|
||||
p_flag = get_network_flag(p_station, network_name)
|
||||
r_flag = get_network_flag(r_station, network_name)
|
||||
netand = band(p_flag, r_flag)
|
||||
if netand == 0 then
|
||||
goto p_continue
|
||||
@@ -353,11 +353,13 @@ local function tick_dispatch(map_data, mod_settings)
|
||||
---@type uint?
|
||||
best_p_train_id = nil
|
||||
best_t_prior = -INF
|
||||
best_capacity = 0
|
||||
best_t_to_p_dist = INF
|
||||
if trains then
|
||||
for train_id, _ in pairs(trains) do
|
||||
local train = map_data.trains[train_id]
|
||||
if not btest(netand, train.network_flag) or train.se_is_being_teleported then
|
||||
local train_flag = get_network_flag(train, network_name)
|
||||
if not btest(netand, train_flag) or train.se_is_being_teleported then
|
||||
goto train_continue
|
||||
end
|
||||
if correctness < 2 then
|
||||
@@ -397,14 +399,19 @@ local function tick_dispatch(map_data, mod_settings)
|
||||
if train.priority < best_t_prior then
|
||||
goto train_continue
|
||||
end
|
||||
|
||||
if train.priority == best_t_prior and capacity < best_capacity then
|
||||
goto train_continue
|
||||
end
|
||||
|
||||
--check if path is shortest so we prioritize locality
|
||||
local t_to_p_dist = get_stop_dist(train.entity.front_stock, p_station.entity_stop) - DEPOT_PRIORITY_MULT*train.priority
|
||||
|
||||
if train.priority == best_t_prior and t_to_p_dist > best_t_to_p_dist then
|
||||
if capacity == best_capacity and t_to_p_dist > best_t_to_p_dist then
|
||||
goto train_continue
|
||||
end
|
||||
|
||||
best_p_train_id = train_id
|
||||
best_capacity = capacity
|
||||
best_t_prior = train.priority
|
||||
best_t_to_p_dist = t_to_p_dist
|
||||
::train_continue::
|
||||
@@ -507,10 +514,11 @@ local function tick_poll_station(map_data, mod_settings)
|
||||
end
|
||||
end
|
||||
station.r_threshold = mod_settings.r_threshold
|
||||
station.priority = 0
|
||||
station.priority = mod_settings.priority
|
||||
station.item_priority = nil
|
||||
station.locked_slots = 0
|
||||
if station.network_name == NETWORK_EACH then
|
||||
station.locked_slots = mod_settings.locked_slots
|
||||
local is_each = station.network_name == NETWORK_EACH
|
||||
if is_each then
|
||||
station.network_flag = {}
|
||||
else
|
||||
station.network_flag = mod_settings.network_flag
|
||||
@@ -548,12 +556,12 @@ local function tick_poll_station(map_data, mod_settings)
|
||||
if item_type == "virtual" then
|
||||
if item_name == SIGNAL_PRIORITY then
|
||||
station.priority = item_count
|
||||
elseif item_name == REQUEST_THRESHOLD and item_count ~= 0 then
|
||||
elseif item_name == REQUEST_THRESHOLD then
|
||||
--NOTE: thresholds must be >0 or they can cause a crash
|
||||
station.r_threshold = abs(item_count)
|
||||
elseif item_name == LOCKED_SLOTS then
|
||||
station.locked_slots = max(item_count, 0)
|
||||
elseif station.network_name == NETWORK_EACH then
|
||||
elseif is_each then
|
||||
station.network_flag[item_name] = item_count
|
||||
end
|
||||
comb1_signals[k] = nil
|
||||
@@ -645,8 +653,38 @@ local function tick_poll_station(map_data, mod_settings)
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param mod_settings CybersynModSettings
|
||||
local function tick_poll_train(map_data, mod_settings)
|
||||
function tick_init(map_data, mod_settings)
|
||||
local tick_data = map_data.tick_data
|
||||
|
||||
map_data.economy.all_p_stations = {}
|
||||
map_data.economy.all_r_stations = {}
|
||||
map_data.economy.all_names = {}
|
||||
|
||||
for i, id in pairs(map_data.warmup_station_ids) do
|
||||
local station = map_data.stations[id]
|
||||
if station then
|
||||
if station.last_delivery_tick + mod_settings.warmup_time*mod_settings.tps < map_data.total_ticks then
|
||||
map_data.active_station_ids[#map_data.active_station_ids + 1] = id
|
||||
map_data.warmup_station_ids[i] = nil
|
||||
end
|
||||
else
|
||||
map_data.warmup_station_ids[i] = nil
|
||||
end
|
||||
end
|
||||
if map_data.queue_station_update then
|
||||
for id, _ in pairs(map_data.queue_station_update) do
|
||||
local station = map_data.stations[id]
|
||||
if station then
|
||||
local pre = station.allows_all_trains
|
||||
set_station_from_comb(station)
|
||||
if station.allows_all_trains ~= pre then
|
||||
update_stop_if_auto(map_data, station, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
map_data.queue_station_update = nil
|
||||
end
|
||||
|
||||
--NOTE: the following has undefined behavior if last_train is deleted, this should be ok since the following doesn't care how inconsistent our access pattern is
|
||||
local train_id, train = next(map_data.trains, tick_data.last_train)
|
||||
tick_data.last_train = train_id
|
||||
@@ -657,10 +695,7 @@ local function tick_poll_train(map_data, mod_settings)
|
||||
end
|
||||
interface_raise_train_stuck(train_id)
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
local function tick_poll_comb(map_data, mod_settings)
|
||||
local tick_data = map_data.tick_data
|
||||
|
||||
--NOTE: the following has undefined behavior if last_comb is deleted
|
||||
local comb_id, comb = next(map_data.to_comb, tick_data.last_comb)
|
||||
tick_data.last_comb = comb_id
|
||||
@@ -673,6 +708,9 @@ local function tick_poll_comb(map_data, mod_settings)
|
||||
if refueler_id then
|
||||
set_refueler_from_comb(map_data, mod_settings, refueler_id)
|
||||
end
|
||||
|
||||
map_data.tick_state = STATE_POLL_STATIONS
|
||||
interface_raise_tick_init()
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param mod_settings CybersynModSettings
|
||||
@@ -680,30 +718,13 @@ function tick(map_data, mod_settings)
|
||||
map_data.total_ticks = map_data.total_ticks + 1
|
||||
|
||||
if map_data.active_alerts then
|
||||
if map_data.total_ticks%(10*mod_settings.tps) < 1 then
|
||||
if map_data.total_ticks%(8*mod_settings.tps) < 1 then
|
||||
process_active_alerts(map_data)
|
||||
end
|
||||
end
|
||||
|
||||
if map_data.tick_state == STATE_INIT then
|
||||
map_data.economy.all_p_stations = {}
|
||||
map_data.economy.all_r_stations = {}
|
||||
map_data.economy.all_names = {}
|
||||
for i, id in pairs(map_data.warmup_station_ids) do
|
||||
local station = map_data.stations[id]
|
||||
if station then
|
||||
if station.last_delivery_tick + mod_settings.warmup_time*mod_settings.tps < map_data.total_ticks then
|
||||
map_data.active_station_ids[#map_data.active_station_ids + 1] = id
|
||||
map_data.warmup_station_ids[i] = nil
|
||||
end
|
||||
else
|
||||
map_data.warmup_station_ids[i] = nil
|
||||
end
|
||||
end
|
||||
map_data.tick_state = STATE_POLL_STATIONS
|
||||
interface_raise_tick_init()
|
||||
tick_poll_train(map_data, mod_settings)
|
||||
tick_poll_comb(map_data)
|
||||
tick_init(map_data, mod_settings)
|
||||
elseif map_data.tick_state == STATE_POLL_STATIONS then
|
||||
for i = 1, mod_settings.update_rate do
|
||||
if tick_poll_station(map_data, mod_settings) then break end
|
||||
|
||||
@@ -22,6 +22,12 @@ MODE_DEPOT = "+"
|
||||
MODE_WAGON = "-"
|
||||
MODE_REFUELER = ">>"
|
||||
|
||||
SETTING_DISABLE_ALLOW_LIST = 2
|
||||
SETTING_IS_STACK = 3
|
||||
SETTING_ENABLE_INACTIVE = 4
|
||||
SETTING_USE_ANY_DEPOT = 5
|
||||
SETTING_DISABLE_DEPOT_BYPASS = 6
|
||||
|
||||
NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"}
|
||||
NETWORK_EACH = "signal-each"
|
||||
INACTIVITY_TIME = 100
|
||||
|
||||
@@ -39,15 +39,32 @@ function se_get_space_elevator_name(surface)
|
||||
end
|
||||
|
||||
|
||||
---@param train LuaTrain
|
||||
function get_any_train_entity(train)
|
||||
return train.front_stock or train.back_stock or train.carriages[1]
|
||||
end
|
||||
|
||||
|
||||
---@param e Station|Refueler|Train
|
||||
---@param network_name string
|
||||
function get_network_flag(e, network_name)
|
||||
return e.network_name == NETWORK_EACH and (e.network_flag[network_name] or 0) or e.network_flag
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
--[[train schedules]]--
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
local create_loading_order_condition = {type = "inactivity", compare_type = "and", ticks = INACTIVITY_TIME}
|
||||
local condition_wait_inactive = {type = "inactivity", compare_type = "and", ticks = INACTIVITY_TIME}
|
||||
local condition_only_inactive = {condition_wait_inactive}
|
||||
local condition_unloading_order = {{type = "empty", compare_type = "and"}}
|
||||
local condition_direct_to_station = {{type = "time", compare_type = "and", ticks = 1}}
|
||||
---@param stop LuaEntity
|
||||
---@param manifest Manifest
|
||||
function create_loading_order(stop, manifest)
|
||||
---@param enable_inactive boolean
|
||||
function create_loading_order(stop, manifest, enable_inactive)
|
||||
local condition = {}
|
||||
for _, item in ipairs(manifest) do
|
||||
local cond_type
|
||||
@@ -63,26 +80,30 @@ function create_loading_order(stop, manifest)
|
||||
condition = {comparator = "≥", first_signal = {type = item.type, name = item.name}, constant = item.count}
|
||||
}
|
||||
end
|
||||
condition[#condition + 1] = create_loading_order_condition
|
||||
if enable_inactive then
|
||||
condition[#condition + 1] = condition_wait_inactive
|
||||
end
|
||||
return {station = stop.backer_name, wait_conditions = condition}
|
||||
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}
|
||||
---@param enable_inactive boolean
|
||||
function create_unloading_order(stop, enable_inactive)
|
||||
if enable_inactive then
|
||||
return {station = stop.backer_name, wait_conditions = condition_only_inactive}
|
||||
else
|
||||
return {station = stop.backer_name, wait_conditions = condition_unloading_order}
|
||||
end
|
||||
end
|
||||
|
||||
local create_inactivity_order_condition = {{type = "inactivity", compare_type = "and", ticks = INACTIVITY_TIME}}
|
||||
---@param depot_name string
|
||||
function create_inactivity_order(depot_name)
|
||||
return {station = depot_name, wait_conditions = create_inactivity_order_condition}
|
||||
return {station = depot_name, wait_conditions = condition_only_inactive}
|
||||
end
|
||||
|
||||
local create_direct_to_station_order_condition = {{type = "time", compare_type = "and", ticks = 1}}
|
||||
---@param stop LuaEntity
|
||||
function create_direct_to_station_order(stop)
|
||||
return {rail = stop.connected_rail, rail_direction = stop.connected_rail_direction, wait_conditions = create_direct_to_station_order_condition}
|
||||
return {rail = stop.connected_rail, rail_direction = stop.connected_rail_direction, wait_conditions = condition_direct_to_station}
|
||||
end
|
||||
|
||||
---@param train LuaTrain
|
||||
@@ -138,13 +159,15 @@ function se_create_elevator_order(elevator_name, is_train_in_orbit)
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param train LuaTrain
|
||||
---@param depot_name string
|
||||
---@param d_surface_i int
|
||||
---@param depot_stop LuaEntity
|
||||
---@param same_depot boolean
|
||||
---@param p_stop LuaEntity
|
||||
---@param p_enable_inactive boolean
|
||||
---@param r_stop LuaEntity
|
||||
---@param r_enable_inactive boolean
|
||||
---@param manifest Manifest
|
||||
---@param start_at_depot boolean?
|
||||
function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop, r_stop, manifest, start_at_depot)
|
||||
function set_manifest_schedule(map_data, train, depot_stop, same_depot, p_stop, p_enable_inactive, r_stop, r_enable_inactive, manifest, start_at_depot)
|
||||
--NOTE: can only return false if start_at_depot is false, it should be incredibly rare that this function returns false
|
||||
local old_schedule
|
||||
if not start_at_depot then
|
||||
@@ -153,6 +176,7 @@ function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop,
|
||||
local t_surface = train.front_stock.surface
|
||||
local p_surface = p_stop.surface
|
||||
local r_surface = r_stop.surface
|
||||
local d_surface_i = depot_stop.surface.index
|
||||
local t_surface_i = t_surface.index
|
||||
local p_surface_i = p_surface.index
|
||||
local r_surface_i = r_surface.index
|
||||
@@ -160,15 +184,19 @@ function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop,
|
||||
local is_r_on_t = t_surface_i == r_surface_i
|
||||
local is_d_on_t = t_surface_i == d_surface_i
|
||||
if is_p_on_t and is_r_on_t and is_d_on_t then
|
||||
local records = {
|
||||
create_inactivity_order(depot_stop.backer_name),
|
||||
create_direct_to_station_order(p_stop),
|
||||
create_loading_order(p_stop, manifest, p_enable_inactive),
|
||||
create_direct_to_station_order(r_stop),
|
||||
create_unloading_order(r_stop, r_enable_inactive),
|
||||
}
|
||||
if same_depot then
|
||||
records[6] = create_direct_to_station_order(depot_stop)
|
||||
end
|
||||
train.schedule = {
|
||||
current = start_at_depot and 1 or 2--[[@as uint]],
|
||||
records = {
|
||||
create_inactivity_order(depot_name),
|
||||
create_direct_to_station_order(p_stop),
|
||||
create_loading_order(p_stop, manifest),
|
||||
create_direct_to_station_order(r_stop),
|
||||
create_unloading_order(r_stop),
|
||||
}
|
||||
records = records
|
||||
}
|
||||
if old_schedule and not train.has_path then
|
||||
train.schedule = old_schedule
|
||||
@@ -186,14 +214,14 @@ function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop,
|
||||
if is_train_in_orbit or t_zone.orbit_index == other_zone.index then
|
||||
local elevator_name = se_get_space_elevator_name(t_surface)
|
||||
if elevator_name then
|
||||
local records = {create_inactivity_order(depot_name)}
|
||||
local records = {create_inactivity_order(depot_stop.backer_name)}
|
||||
if t_surface_i == p_surface_i then
|
||||
records[#records + 1] = create_direct_to_station_order(p_stop)
|
||||
else
|
||||
records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit)
|
||||
is_train_in_orbit = not is_train_in_orbit
|
||||
end
|
||||
records[#records + 1] = create_loading_order(p_stop, manifest)
|
||||
records[#records + 1] = create_loading_order(p_stop, manifest, p_enable_inactive)
|
||||
|
||||
if p_surface_i ~= r_surface_i then
|
||||
records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit)
|
||||
@@ -201,7 +229,7 @@ function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop,
|
||||
elseif t_surface_i == r_surface_i then
|
||||
records[#records + 1] = create_direct_to_station_order(r_stop)
|
||||
end
|
||||
records[#records + 1] = create_unloading_order(r_stop)
|
||||
records[#records + 1] = create_unloading_order(r_stop, r_enable_inactive)
|
||||
if r_surface_i ~= d_surface_i then
|
||||
records[#records + 1] = se_create_elevator_order(elevator_name, is_train_in_orbit)
|
||||
is_train_in_orbit = not is_train_in_orbit
|
||||
@@ -221,9 +249,9 @@ function set_manifest_schedule(map_data, train, depot_name, d_surface_i, p_stop,
|
||||
end
|
||||
--NOTE: create a schedule that cannot be fulfilled, the train will be stuck but it will give the player information what went wrong
|
||||
train.schedule = {current = 1, records = {
|
||||
create_inactivity_order(depot_name),
|
||||
create_loading_order(p_stop, manifest),
|
||||
create_unloading_order(r_stop),
|
||||
create_inactivity_order(depot_stop.backer_name),
|
||||
create_loading_order(p_stop, manifest, p_enable_inactive),
|
||||
create_unloading_order(r_stop, r_enable_inactive),
|
||||
}}
|
||||
lock_train(train)
|
||||
send_alert_cannot_path_between_surfaces(map_data, train)
|
||||
@@ -306,6 +334,78 @@ function get_comb_network_name(comb)
|
||||
|
||||
return signal and signal.name or nil
|
||||
end
|
||||
|
||||
---@param station Station
|
||||
function set_station_from_comb(station)
|
||||
--NOTE: this does nothing to update currently active deliveries
|
||||
--NOTE: this can only be called at the tick init boundary
|
||||
local params = get_comb_params(station.entity_comb1)
|
||||
local signal = params.first_signal
|
||||
|
||||
local bits = params.second_constant or 0
|
||||
local is_pr_state = bit_extract(bits, 0, 2)
|
||||
local allows_all_trains = bit_extract(bits, SETTING_DISABLE_ALLOW_LIST) > 0
|
||||
local is_stack = bit_extract(bits, SETTING_IS_STACK) > 0
|
||||
local enable_inactive = bit_extract(bits, SETTING_ENABLE_INACTIVE) > 0
|
||||
|
||||
station.network_name = signal and signal.name or nil
|
||||
station.allows_all_trains = allows_all_trains
|
||||
station.is_stack = is_stack
|
||||
station.enable_inactive = enable_inactive
|
||||
station.is_p = (is_pr_state == 0 or is_pr_state == 1) or nil
|
||||
station.is_r = (is_pr_state == 0 or is_pr_state == 2) or nil
|
||||
|
||||
if station.network_name == NETWORK_EACH then
|
||||
station.network_flag = {}
|
||||
end
|
||||
end
|
||||
---@param mod_settings CybersynModSettings
|
||||
---@param train Train
|
||||
---@param comb LuaEntity
|
||||
function set_train_from_comb(mod_settings, train, comb)
|
||||
--NOTE: this does nothing to update currently active deliveries
|
||||
local params = get_comb_params(comb)
|
||||
local signal = params.first_signal
|
||||
local network_name = signal and signal.name or nil
|
||||
|
||||
local bits = params.second_constant or 0
|
||||
local disable_bypass = bit_extract(bits, SETTING_DISABLE_DEPOT_BYPASS) > 0
|
||||
local use_any_depot = bit_extract(bits, SETTING_USE_ANY_DEPOT) > 0
|
||||
|
||||
train.network_name = network_name
|
||||
train.disable_bypass = disable_bypass
|
||||
train.use_any_depot = use_any_depot
|
||||
|
||||
local is_each = train.network_name == NETWORK_EACH
|
||||
if is_each then
|
||||
train.network_flag = {}
|
||||
else
|
||||
train.network_flag = mod_settings.network_flag
|
||||
end
|
||||
train.priority = mod_settings.priority
|
||||
local signals = comb.get_merged_signals(defines.circuit_connector_id.combinator_input)
|
||||
if signals then
|
||||
for k, v in pairs(signals) do
|
||||
local item_name = v.signal.name
|
||||
local item_type = v.signal.type
|
||||
local item_count = v.count
|
||||
if item_name then
|
||||
if item_type == "virtual" then
|
||||
if item_name == SIGNAL_PRIORITY then
|
||||
train.priority = item_count
|
||||
elseif is_each then
|
||||
if item_name ~= REQUEST_THRESHOLD and item_name ~= LOCKED_SLOTS then
|
||||
train.network_flag[item_name] = item_count
|
||||
end
|
||||
end
|
||||
end
|
||||
if item_name == network_name then
|
||||
train.network_flag = item_count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param mod_settings CybersynModSettings
|
||||
---@param id uint
|
||||
@@ -316,12 +416,14 @@ function set_refueler_from_comb(map_data, mod_settings, id)
|
||||
local bits = params.second_constant or 0
|
||||
local signal = params.first_signal
|
||||
local old_network = refueler.network_name
|
||||
local old_network_flag = refueler.network_flag
|
||||
|
||||
refueler.network_name = signal and signal.name or nil
|
||||
refueler.allows_all_trains = bit_extract(bits, 2) > 0
|
||||
refueler.priority = 0
|
||||
refueler.allows_all_trains = bit_extract(bits, SETTING_DISABLE_ALLOW_LIST) > 0
|
||||
refueler.priority = mod_settings.priority
|
||||
|
||||
if refueler.network_name == NETWORK_EACH then
|
||||
local is_each = refueler.network_name == NETWORK_EACH
|
||||
if is_each then
|
||||
map_data.each_refuelers[id] = true
|
||||
refueler.network_flag = {}
|
||||
else
|
||||
@@ -339,8 +441,10 @@ function set_refueler_from_comb(map_data, mod_settings, id)
|
||||
if item_type == "virtual" then
|
||||
if item_name == SIGNAL_PRIORITY then
|
||||
refueler.priority = item_count
|
||||
elseif refueler.network_name == NETWORK_EACH then
|
||||
refueler.network_flag[item_name] = item_count
|
||||
elseif is_each then
|
||||
if item_name ~= REQUEST_THRESHOLD and item_name ~= LOCKED_SLOTS then
|
||||
refueler.network_flag[item_name] = item_count
|
||||
end
|
||||
end
|
||||
end
|
||||
if item_name == refueler.network_name then
|
||||
@@ -352,7 +456,7 @@ function set_refueler_from_comb(map_data, mod_settings, id)
|
||||
|
||||
local f, a
|
||||
if old_network == NETWORK_EACH then
|
||||
f, a = pairs(refueler.network_flag--[[@as {[string]: int}]])
|
||||
f, a = pairs(old_network_flag--[[@as {[string]: int}]])
|
||||
elseif old_network ~= refueler.network_name then
|
||||
f, a = once, old_network
|
||||
else
|
||||
@@ -406,24 +510,6 @@ function update_display(map_data, station)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
---@param station Station
|
||||
function set_station_from_comb_state(station)
|
||||
--NOTE: this does nothing to update currently active deliveries
|
||||
local params = get_comb_params(station.entity_comb1)
|
||||
local signal = params.first_signal
|
||||
|
||||
local bits = params.second_constant or 0
|
||||
local is_pr_state = bit_extract(bits, 0, 2)
|
||||
local allows_all_trains = bit_extract(bits, 2) > 0
|
||||
local is_stack = bit_extract(bits, 3) > 0
|
||||
|
||||
station.network_name = signal and signal.name or nil
|
||||
station.allows_all_trains = allows_all_trains
|
||||
station.is_stack = is_stack
|
||||
station.is_p = (is_pr_state == 0 or is_pr_state == 1) or nil
|
||||
station.is_r = (is_pr_state == 0 or is_pr_state == 2) or nil
|
||||
end
|
||||
---@param comb LuaEntity
|
||||
function get_comb_gui_settings(comb)
|
||||
local params = get_comb_params(comb)
|
||||
@@ -433,8 +519,6 @@ function get_comb_gui_settings(comb)
|
||||
local switch_state = "none"
|
||||
local bits = params.second_constant or 0
|
||||
local is_pr_state = bit_extract(bits, 0, 2)
|
||||
local allows_all_trains = bit_extract(bits, 2) > 0
|
||||
local is_stack = bit_extract(bits, 3) > 0
|
||||
if is_pr_state == 0 then
|
||||
switch_state = "none"
|
||||
elseif is_pr_state == 1 then
|
||||
@@ -454,7 +538,7 @@ function get_comb_gui_settings(comb)
|
||||
elseif op == MODE_WAGON then
|
||||
selected_index = 5
|
||||
end
|
||||
return selected_index, params.first_signal, switch_state, not allows_all_trains, is_stack
|
||||
return selected_index, params.first_signal, switch_state, bits
|
||||
end
|
||||
---@param comb LuaEntity
|
||||
---@param is_pr_state 0|1|2
|
||||
@@ -467,23 +551,14 @@ function set_comb_is_pr_state(comb, is_pr_state)
|
||||
control.parameters = param
|
||||
end
|
||||
---@param comb LuaEntity
|
||||
---@param allows_all_trains boolean
|
||||
function set_comb_allows_all_trains(comb, allows_all_trains)
|
||||
---@param n int
|
||||
---@param bit boolean
|
||||
function set_comb_setting(comb, n, bit)
|
||||
local control = get_comb_control(comb)
|
||||
local param = control.parameters
|
||||
local bits = param.second_constant or 0
|
||||
|
||||
param.second_constant = bit_replace(bits, allows_all_trains and 1 or 0, 2)
|
||||
control.parameters = param
|
||||
end
|
||||
---@param comb LuaEntity
|
||||
---@param is_stack boolean
|
||||
function set_comb_is_stack(comb, is_stack)
|
||||
local control = get_comb_control(comb)
|
||||
local param = control.parameters
|
||||
local bits = param.second_constant or 0
|
||||
|
||||
param.second_constant = bit_replace(bits, is_stack and 1 or 0, 3)
|
||||
param.second_constant = bit_replace(bits, bit and 1 or 0, n)
|
||||
control.parameters = param
|
||||
end
|
||||
---@param comb LuaEntity
|
||||
@@ -540,22 +615,25 @@ end
|
||||
---@param map_data MapData
|
||||
---@param station Station
|
||||
function set_comb2(map_data, station)
|
||||
local sign = mod_settings.invert_sign and -1 or 1
|
||||
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}
|
||||
signals[i] = {index = i, signal = {type = is_fluid and "fluid" or "item", name = item_name}, count = sign*count}
|
||||
end
|
||||
set_combinator_output(map_data, station.entity_comb2, signals)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
--[[alerts]]--
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
---@param train LuaTrain
|
||||
---@param icon {}
|
||||
---@param message string
|
||||
@@ -694,7 +772,14 @@ function process_active_alerts(map_data)
|
||||
if id == 1 then
|
||||
send_alert_for_train(train, send_stuck_train_alert_icon, "cybersyn-messages.stuck-train")
|
||||
elseif id == 2 then
|
||||
send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train")
|
||||
--this is an alert that we have to actively check if we can clear
|
||||
local is_train_empty = next(train.get_contents()) == nil and next(train.get_fluid_contents()) == nil
|
||||
if is_train_empty then
|
||||
--NOTE: this function could get confused being called internally, be sure it can handle that
|
||||
on_train_changed({train = train})
|
||||
else
|
||||
send_alert_for_train(train, send_nonempty_train_in_depot_alert_icon, "cybersyn-messages.nonempty-train")
|
||||
end
|
||||
elseif id == 3 then
|
||||
send_alert_for_train(train, send_lost_train_alert_icon, "cybersyn-messages.depot-broken")
|
||||
elseif id == 4 then
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
---@field public stations {[uint]: Station}
|
||||
---@field public active_station_ids uint[]
|
||||
---@field public warmup_station_ids uint[]
|
||||
---@field public queue_station_update {[uint]: true?}?
|
||||
---@field public depots {[uint]: Depot}
|
||||
---@field public refuelers {[uint]: Refueler}
|
||||
---@field public trains {[uint]: Train}
|
||||
@@ -29,6 +30,7 @@
|
||||
---@field public is_p true?
|
||||
---@field public is_r true?
|
||||
---@field public is_stack true?
|
||||
---@field public enable_inactive true?
|
||||
---@field public allows_all_trains true?
|
||||
---@field public deliveries_total int
|
||||
---@field public last_delivery_tick int
|
||||
@@ -50,7 +52,7 @@
|
||||
---@class Depot
|
||||
---@field public entity_stop LuaEntity
|
||||
---@field public entity_comb LuaEntity
|
||||
---@field public available_train_id uint?--train_id
|
||||
---@field public available_train_id uint?--train_id, only present when a train is parked here
|
||||
|
||||
---@class Refueler
|
||||
---@field public entity_stop LuaEntity
|
||||
@@ -76,13 +78,13 @@
|
||||
---@field public last_manifest_tick int
|
||||
---@field public has_filtered_wagon true?
|
||||
---@field public is_available true?
|
||||
---@field public parked_at_depot_id uint?
|
||||
---@field public depot_name string
|
||||
---@field public depot_id uint
|
||||
---@field public use_any_depot true?
|
||||
---@field public disable_bypass true?
|
||||
---@field public network_name string? --can only be nil when the train is parked at a depot
|
||||
---@field public network_flag int
|
||||
---@field public priority int
|
||||
---@field public refueler_id uint?
|
||||
---@field public se_depot_surface_i uint --se only
|
||||
---@field public se_is_being_teleported true? --se only
|
||||
---@field public se_awaiting_removal any? --se only
|
||||
---@field public se_awaiting_rename any? --se only
|
||||
@@ -105,17 +107,21 @@
|
||||
---@field public tps double
|
||||
---@field public update_rate int
|
||||
---@field public r_threshold int
|
||||
---@field public priority int
|
||||
---@field public locked_slots int
|
||||
---@field public network_flag int
|
||||
---@field public warmup_time double
|
||||
---@field public stuck_train_time double
|
||||
---@field public fuel_threshold double
|
||||
---@field public depot_bypass_enabled boolean
|
||||
---@field public invert_sign boolean
|
||||
---@field public allow_cargo_in_depot boolean
|
||||
---@field public missing_train_alert_enabled boolean --interface setting
|
||||
---@field public stuck_train_alert_enabled boolean --interface setting
|
||||
---@field public react_to_nonempty_train_in_depot boolean --interface setting
|
||||
---@field public react_to_train_at_incorrect_station boolean --interface setting
|
||||
---@field public react_to_train_early_to_depot boolean --interface setting
|
||||
|
||||
--if this is uncommented it means there are migrations to write
|
||||
|
||||
---@alias cybersyn.global MapData
|
||||
---@type CybersynModSettings
|
||||
mod_settings = {}
|
||||
@@ -150,9 +156,3 @@ function init_global()
|
||||
|
||||
IS_SE_PRESENT = remote.interfaces["space-exploration"] ~= nil
|
||||
end
|
||||
|
||||
---@param v string
|
||||
---@param h string?
|
||||
function once(v, h)
|
||||
return not h and v or nil--[[@as string|nil]]
|
||||
end
|
||||
|
||||
@@ -26,25 +26,37 @@ STATUS_NAMES[defines.entity_status.disabled_by_script] = "entity-status.disabled
|
||||
STATUS_NAMES[defines.entity_status.marked_for_deconstruction] = "entity-status.marked-for-deconstruction"
|
||||
STATUS_NAMES_DEFAULT = "entity-status.disabled"
|
||||
|
||||
|
||||
local bit_extract = bit32.extract
|
||||
local function setting(bits, n)
|
||||
return bit_extract(bits, n) > 0
|
||||
end
|
||||
local function setting_flip(bits, n)
|
||||
return bit_extract(bits, n) == 0
|
||||
end
|
||||
|
||||
|
||||
---@param main_window LuaGuiElement
|
||||
---@param selected_index int
|
||||
local function set_visibility(main_window, selected_index)
|
||||
local uses_network = selected_index == 1 or selected_index == 2 or selected_index == 3
|
||||
local uses_allow_list = selected_index == 1 or selected_index == 3
|
||||
local is_station = selected_index == 1
|
||||
local is_depot = selected_index == 2
|
||||
local uses_network = is_station or is_depot or selected_index == 3
|
||||
local uses_allow_list = is_station or selected_index == 3
|
||||
|
||||
local vflow = main_window.frame.vflow--[[@as LuaGuiElement]]
|
||||
local top_flow = vflow.top--[[@as LuaGuiElement]]
|
||||
local bottom_flow = vflow.bottom--[[@as LuaGuiElement]]
|
||||
local right_flow = bottom_flow.right--[[@as LuaGuiElement]]
|
||||
local first_settings = bottom_flow.first--[[@as LuaGuiElement]]
|
||||
local depot_settings = bottom_flow.depot--[[@as LuaGuiElement]]
|
||||
|
||||
top_flow.is_pr_switch.visible = is_station
|
||||
vflow.network_label.visible = uses_network
|
||||
bottom_flow.network.visible = uses_network
|
||||
right_flow.allow_list.visible = uses_allow_list
|
||||
--right_flow.allow_list_label.visible = uses_allow_list
|
||||
right_flow.is_stack.visible = is_station
|
||||
--right_flow.is_stack_label.visible = is_station
|
||||
first_settings.allow_list.visible = uses_allow_list
|
||||
first_settings.is_stack.visible = is_station
|
||||
bottom_flow.enable_inactive.visible = is_station
|
||||
depot_settings.visible = is_depot
|
||||
end
|
||||
|
||||
---@param comb LuaEntity
|
||||
@@ -53,7 +65,7 @@ function gui_opened(comb, player)
|
||||
combinator_update(global, comb, true)
|
||||
|
||||
local rootgui = player.gui.screen
|
||||
local selected_index, signal, switch_state, allow_list, is_stack = get_comb_gui_settings(comb)
|
||||
local selected_index, signal, switch_state, bits = get_comb_gui_settings(comb)
|
||||
|
||||
local window = flib_gui.build(rootgui, {
|
||||
{type="frame", direction="vertical", ref={"main_window"}, name=COMBINATOR_NAME, children={
|
||||
@@ -69,8 +81,8 @@ function gui_opened(comb, player)
|
||||
{type="flow", name="vflow", 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="sprite", sprite=STATUS_SPRITES[comb.status] or STATUS_SPRITES_DEFAULT, style="status_image", style_mods={stretch_image_to_widget_size=true}},
|
||||
{type="label", caption={STATUS_NAMES[comb.status] or STATUS_NAMES_DEFAULT}}
|
||||
}},
|
||||
--preview
|
||||
{type="frame", style="deep_frame_in_shallow_frame", style_mods={minimal_width=0, horizontally_stretchable=true, padding=0}, children={
|
||||
@@ -94,25 +106,45 @@ function gui_opened(comb, player)
|
||||
}},
|
||||
---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=signal, style_mods={bottom_margin=1, right_margin=6, top_margin=2}, actions={
|
||||
{type="label", name="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="top"}, children={
|
||||
{type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=signal, style_mods={bottom_margin=1, right_margin=6, top_margin=2}, actions={
|
||||
on_elem_changed={"choose-elem-button", comb.unit_number}
|
||||
}},
|
||||
{type="flow", name="right", direction="vertical", style_mods={horizontal_align="left"}, children={
|
||||
{type="flow", name="allow_list", direction="horizontal", style_mods={vertical_align="center"}, children={
|
||||
{type="checkbox", name="allow_list", ref={"allow_list"}, state=allow_list, tooltip={"cybersyn-gui.allow-list-tooltip"}, actions={
|
||||
on_checked_state_changed={"allow_list", comb.unit_number}
|
||||
{type="flow", name="depot", direction="vertical", style_mods={horizontal_align="left"}, children={
|
||||
{type="flow", name="use_any_depot", direction="horizontal", style_mods={vertical_align="center"}, children={
|
||||
{type="checkbox", name="use_same_depot", state=setting_flip(bits, SETTING_USE_ANY_DEPOT), tooltip={"cybersyn-gui.use-same-depot-tooltip"}, actions={
|
||||
on_checked_state_changed={"setting-flip", comb.unit_number, SETTING_USE_ANY_DEPOT}
|
||||
}},
|
||||
{type="label", name="allow_list_label", style_mods={left_padding=3}, ref={"allow_list_label"}, caption={"cybersyn-gui.allow-list-description"}},
|
||||
{type="label", name="use_same_depot_label", style_mods={left_padding=3}, caption={"cybersyn-gui.use-same-depot-description"}},
|
||||
}},
|
||||
{type="flow", name="depot_bypass", direction="horizontal", style_mods={vertical_align="center"}, children={
|
||||
{type="checkbox", name="depot_bypass", state=setting_flip(bits, SETTING_DISABLE_DEPOT_BYPASS), tooltip={"cybersyn-gui.depot-bypass-tooltip"}, actions={
|
||||
on_checked_state_changed={"setting-flip", comb.unit_number, SETTING_DISABLE_DEPOT_BYPASS}
|
||||
}},
|
||||
{type="label", name="depot_bypass_label", style_mods={left_padding=3}, caption={"cybersyn-gui.depot-bypass-description"}},
|
||||
}},
|
||||
}},
|
||||
{type="flow", name="first", direction="vertical", style_mods={horizontal_align="left", right_margin=8}, children={
|
||||
{type="flow", name="allow_list", direction="horizontal", style_mods={vertical_align="center"}, children={
|
||||
{type="checkbox", name="allow_list", state=setting_flip(bits, SETTING_DISABLE_ALLOW_LIST), tooltip={"cybersyn-gui.allow-list-tooltip"}, actions={
|
||||
on_checked_state_changed={"setting-flip", comb.unit_number, SETTING_DISABLE_ALLOW_LIST}
|
||||
}},
|
||||
{type="label", name="allow_list_label", style_mods={left_padding=3}, caption={"cybersyn-gui.allow-list-description"}},
|
||||
}},
|
||||
{type="flow", name="is_stack", direction="horizontal", style_mods={vertical_align="center"}, children={
|
||||
{type="checkbox", name="is_stack", ref={"is_stack"}, state=is_stack, tooltip={"cybersyn-gui.is-stack-tooltip"}, actions={
|
||||
on_checked_state_changed={"is_stack", comb.unit_number}
|
||||
{type="checkbox", name="is_stack", state=setting(bits, SETTING_IS_STACK), tooltip={"cybersyn-gui.is-stack-tooltip"}, actions={
|
||||
on_checked_state_changed={"setting", comb.unit_number, SETTING_IS_STACK}
|
||||
}},
|
||||
{type="label", name="is_stack_label", style_mods={left_padding=3}, ref={"is_stack_label"}, caption={"cybersyn-gui.is-stack-description"}},
|
||||
{type="label", name="is_stack_label", style_mods={left_padding=3}, caption={"cybersyn-gui.is-stack-description"}},
|
||||
}},
|
||||
}}
|
||||
}},
|
||||
{type="flow", name="enable_inactive", direction="horizontal", style_mods={vertical_align="center"}, children={
|
||||
{type="checkbox", name="enable_inactive", state=setting(bits, SETTING_ENABLE_INACTIVE), tooltip={"cybersyn-gui.enable-inactive-tooltip"}, actions={
|
||||
on_checked_state_changed={"setting", comb.unit_number, SETTING_ENABLE_INACTIVE}
|
||||
}},
|
||||
{type="label", name="enable_inactive_label", style_mods={left_padding=3}, caption={"cybersyn-gui.enable-inactive-description"}},
|
||||
}},
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
@@ -197,38 +229,30 @@ function register_gui_actions()
|
||||
local comb = global.to_comb[msg[2]]
|
||||
if not comb or not comb.valid then return end
|
||||
|
||||
local param = get_comb_params(comb)
|
||||
|
||||
local signal = element.elem_value
|
||||
if signal and (signal.name == "signal-everything" or signal.name == "signal-anything" or signal.name == "signal-each") then
|
||||
if param.operation == MODE_PRIMARY_IO or param.operation == MODE_PRIMARY_IO_ACTIVE or param.operation == MODE_PRIMARY_IO_FAILED_REQUEST or param.operation == MODE_REFUELER then
|
||||
signal.name = NETWORK_EACH
|
||||
else
|
||||
signal = nil
|
||||
end
|
||||
signal.name = NETWORK_EACH
|
||||
element.elem_value = signal
|
||||
end
|
||||
set_comb_network_name(comb, signal)
|
||||
|
||||
combinator_update(global, comb)
|
||||
elseif msg[1] == "allow_list" then
|
||||
elseif msg[1] == "setting" 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 allows_all_trains = not element.state
|
||||
set_comb_allows_all_trains(comb, allows_all_trains)
|
||||
set_comb_setting(comb, msg[3], element.state)
|
||||
|
||||
combinator_update(global, comb)
|
||||
elseif msg[1] == "is_stack" then
|
||||
elseif msg[1] == "setting-flip" 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_stack = element.state
|
||||
set_comb_is_stack(comb, is_stack)
|
||||
set_comb_setting(comb, msg[3], not element.state)
|
||||
|
||||
combinator_update(global, comb)
|
||||
elseif msg[1] == "is_pr_switch" then
|
||||
|
||||
@@ -3,37 +3,10 @@ local area = require("__flib__.area")
|
||||
local abs = math.abs
|
||||
local floor = math.floor
|
||||
local ceil = math.ceil
|
||||
local min = math.min
|
||||
local max = math.max
|
||||
|
||||
|
||||
local function table_compare(t0, t1)
|
||||
if #t0 ~= #t1 then
|
||||
return false
|
||||
end
|
||||
for i = 0, #t0 do
|
||||
if t0[i] ~= t1[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
---@param a any[]
|
||||
---@param i uint
|
||||
local function iterr(a, i)
|
||||
i = i + 1
|
||||
if i <= #a then
|
||||
local r = a[#a - i + 1]
|
||||
return i, r
|
||||
else
|
||||
return nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
---@param a any[]
|
||||
local function irpairs(a)
|
||||
return iterr, a, 0
|
||||
end
|
||||
|
||||
---@param layout_pattern (0|1|2|3)[]
|
||||
---@param layout (0|1|2)[]
|
||||
function is_refuel_layout_accepted(layout_pattern, layout)
|
||||
@@ -81,11 +54,6 @@ end
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function remove_train(map_data, train_id, train)
|
||||
local parked_at_depot_id = train.parked_at_depot_id
|
||||
if parked_at_depot_id then
|
||||
local depot = map_data.depots[parked_at_depot_id]
|
||||
depot.available_train_id = nil
|
||||
end
|
||||
remove_available_train(map_data, train_id, train)
|
||||
|
||||
local layout_id = train.layout_id
|
||||
@@ -191,9 +159,31 @@ function set_p_wagon_combs(map_data, station, train)
|
||||
if not station.wagon_combs or not next(station.wagon_combs) then return end
|
||||
local carriages = train.entity.carriages
|
||||
local manifest = train.manifest--[[@as Manifest]]
|
||||
if not manifest[1] then return end
|
||||
local sign = mod_settings.invert_sign and 1 or -1
|
||||
|
||||
local is_reversed = get_train_direction(station.entity_stop, train.entity)
|
||||
|
||||
local locked_slots = station.locked_slots
|
||||
local percent_slots_to_use_per_wagon = 1.0
|
||||
if train.item_slot_capacity > 0 then
|
||||
local total_item_slots
|
||||
if locked_slots > 0 then
|
||||
local total_cargo_wagons = #train.entity.cargo_wagons
|
||||
total_item_slots = max(train.item_slot_capacity - total_cargo_wagons*locked_slots, 1)
|
||||
else
|
||||
total_item_slots = train.item_slot_capacity
|
||||
end
|
||||
|
||||
local to_be_used_item_slots = 0
|
||||
for i, item in ipairs(train.manifest) do
|
||||
if item.type == "item" then
|
||||
to_be_used_item_slots = to_be_used_item_slots + ceil(item.count/get_stack_size(map_data, item.name))
|
||||
end
|
||||
end
|
||||
percent_slots_to_use_per_wagon = min(to_be_used_item_slots/total_item_slots, 1.0)
|
||||
end
|
||||
|
||||
local item_i = 1
|
||||
local item = manifest[item_i]
|
||||
local item_count = item.count
|
||||
@@ -215,39 +205,29 @@ function set_p_wagon_combs(map_data, station, train)
|
||||
end
|
||||
end
|
||||
if carriage.type == "cargo-wagon" and item_i <= #manifest then
|
||||
local signals = {}
|
||||
|
||||
local inv = carriage.get_inventory(defines.inventory.cargo_wagon)
|
||||
if inv then
|
||||
local signals = {}
|
||||
|
||||
local inv_filter_i = 1
|
||||
local item_slots_capacity = #inv - station.locked_slots
|
||||
local item_slots_capacity = max(ceil((#inv - locked_slots)*percent_slots_to_use_per_wagon), 1)
|
||||
while item_slots_capacity > 0 do
|
||||
local do_inc = false
|
||||
local do_inc
|
||||
if item.type == "item" then
|
||||
local stack_size = get_stack_size(map_data, item.name)
|
||||
local item_slots = ceil(item_count/stack_size)
|
||||
local i = #signals + 1
|
||||
local slots_to_filter
|
||||
if item_slots > item_slots_capacity then
|
||||
if comb then
|
||||
signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = item_slots_capacity*stack_size}
|
||||
end
|
||||
item_slots_capacity = 0
|
||||
item_count = item_count - item_slots_capacity*stack_size
|
||||
slots_to_filter = item_slots_capacity
|
||||
else
|
||||
if comb then
|
||||
signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = item_count}
|
||||
end
|
||||
item_slots_capacity = item_slots_capacity - item_slots
|
||||
do_inc = true
|
||||
slots_to_filter = item_slots
|
||||
end
|
||||
for j = 1, slots_to_filter do
|
||||
local count_to_fill = min(item_slots_capacity*stack_size, item_count)
|
||||
local slots_to_fill = ceil(count_to_fill/stack_size)
|
||||
|
||||
signals[i] = {index = i, signal = {type = item.type, name = item.name}, count = sign*count_to_fill}
|
||||
item_count = item_count - count_to_fill
|
||||
item_slots_capacity = item_slots_capacity - slots_to_fill
|
||||
for j = 1, slots_to_fill do
|
||||
inv.set_filter(inv_filter_i, item.name)
|
||||
inv_filter_i = inv_filter_i + 1
|
||||
end
|
||||
train.has_filtered_wagon = true
|
||||
do_inc = item_count == 0
|
||||
else
|
||||
do_inc = true
|
||||
end
|
||||
@@ -271,27 +251,18 @@ function set_p_wagon_combs(map_data, station, train)
|
||||
local signals = {}
|
||||
|
||||
while fluid_capacity > 0 do
|
||||
local do_inc = false
|
||||
local do_inc
|
||||
if fluid.type == "fluid" then
|
||||
if fluid_count > fluid_capacity then
|
||||
if comb then
|
||||
signals[1] = {index = 1, signal = {type = fluid.type, name = fluid.name}, count = fluid_capacity}
|
||||
end
|
||||
fluid_capacity = 0
|
||||
fluid_count = fluid_count - fluid_capacity
|
||||
else
|
||||
if comb then
|
||||
signals[1] = {index = 1, signal = {type = fluid.type, name = fluid.name}, count = item_count}
|
||||
end
|
||||
fluid_capacity = fluid_capacity - fluid_count
|
||||
fluid_i = fluid_i + 1
|
||||
if fluid_i <= #manifest then
|
||||
fluid = manifest[fluid_i]
|
||||
fluid_count = fluid.count
|
||||
end
|
||||
end
|
||||
break
|
||||
local count_to_fill = min(fluid_count, fluid_capacity)
|
||||
|
||||
signals[1] = {index = 1, signal = {type = fluid.type, name = fluid.name}, count = sign*count_to_fill}
|
||||
fluid_count = fluid_count - count_to_fill
|
||||
fluid_capacity = 0
|
||||
do_inc = fluid_count == 0
|
||||
else
|
||||
do_inc = true
|
||||
end
|
||||
if do_inc then
|
||||
fluid_i = fluid_i + 1
|
||||
if fluid_i <= #manifest then
|
||||
fluid = manifest[fluid_i]
|
||||
@@ -315,6 +286,7 @@ function set_r_wagon_combs(map_data, station, train)
|
||||
local carriages = train.entity.carriages
|
||||
|
||||
local is_reversed = get_train_direction(station.entity_stop, train.entity)
|
||||
local sign = mod_settings.invert_sign and -1 or 1
|
||||
|
||||
local ivpairs = is_reversed and irpairs or ipairs
|
||||
for carriage_i, carriage in ivpairs(carriages) do
|
||||
@@ -336,7 +308,7 @@ function set_r_wagon_combs(map_data, station, train)
|
||||
local stack = inv[stack_i]
|
||||
if stack.valid_for_read then
|
||||
local i = #signals + 1
|
||||
signals[i] = {index = i, signal = {type = "item", name = stack.name}, count = -stack.count}
|
||||
signals[i] = {index = i, signal = {type = "item", name = stack.name}, count = sign*stack.count}
|
||||
end
|
||||
end
|
||||
set_combinator_output(map_data, comb, signals)
|
||||
@@ -347,7 +319,7 @@ function set_r_wagon_combs(map_data, station, train)
|
||||
local inv = carriage.get_fluid_contents()
|
||||
for fluid_name, count in pairs(inv) do
|
||||
local i = #signals + 1
|
||||
signals[i] = {index = i, signal = {type = "fluid", name = fluid_name}, count = -floor(count)}
|
||||
signals[i] = {index = i, signal = {type = "fluid", name = fluid_name}, count = sign*floor(count)}
|
||||
end
|
||||
set_combinator_output(map_data, comb, signals)
|
||||
end
|
||||
|
||||
51
cybersyn/scripts/lib.lua
Normal file
51
cybersyn/scripts/lib.lua
Normal file
@@ -0,0 +1,51 @@
|
||||
--By Mami
|
||||
---@param v string
|
||||
---@param h string?
|
||||
function once(v, h)
|
||||
return not h and v or nil--[[@as string|nil]]
|
||||
end
|
||||
---@param t any[]
|
||||
---@return any
|
||||
function rnext_consume(t)
|
||||
local len = #t
|
||||
if len > 1 then
|
||||
local i = math.random(1, len)
|
||||
local v = t[i]
|
||||
t[i] = t[len]
|
||||
t[len] = nil
|
||||
return v
|
||||
else
|
||||
local v = t[1]
|
||||
t[1] = nil
|
||||
return v
|
||||
end
|
||||
end
|
||||
|
||||
function table_compare(t0, t1)
|
||||
if #t0 ~= #t1 then
|
||||
return false
|
||||
end
|
||||
for i = 0, #t0 do
|
||||
if t0[i] ~= t1[i] then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
---@param a any[]
|
||||
---@param i uint
|
||||
function irnext(a, i)
|
||||
i = i + 1
|
||||
if i <= #a then
|
||||
local r = a[#a - i + 1]
|
||||
return i, r
|
||||
else
|
||||
return nil, nil
|
||||
end
|
||||
end
|
||||
|
||||
---@param a any[]
|
||||
function irpairs(a)
|
||||
return irnext, a, 0
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
|
||||
|
||||
|
||||
function log_dispatch(network_name, r_stop, p_stop)
|
||||
end
|
||||
|
||||
function log_refuel(network_name, refuel_stop)
|
||||
end
|
||||
@@ -1,5 +1,4 @@
|
||||
--By Mami
|
||||
local floor = math.floor
|
||||
local ceil = math.ceil
|
||||
local table_insert = table.insert
|
||||
|
||||
@@ -23,12 +22,24 @@ end
|
||||
---@param depot_id uint
|
||||
---@param depot Depot
|
||||
local function on_depot_broken(map_data, depot_id, depot)
|
||||
local train_id = depot.available_train_id
|
||||
if train_id then
|
||||
local train = map_data.trains[train_id]
|
||||
lock_train(train.entity)
|
||||
send_alert_depot_of_train_broken(map_data, train.entity)
|
||||
remove_train(map_data, train_id, train)
|
||||
for train_id, train in pairs(map_data.trains) do
|
||||
if train.depot_id == depot_id then
|
||||
if train.use_any_depot then
|
||||
local e = get_any_train_entity(train.entity)
|
||||
local stops = e.force.get_train_stops({name = depot.entity_stop.backer_name, surface = e.surface})
|
||||
for stop in rnext_consume, stops do
|
||||
local new_depot_id = stop.unit_number
|
||||
if map_data.depots[new_depot_id] then
|
||||
train.depot_id = new_depot_id--[[@as uint]]
|
||||
goto continue
|
||||
end
|
||||
end
|
||||
end
|
||||
lock_train(train.entity)
|
||||
send_alert_depot_of_train_broken(map_data, train.entity)
|
||||
remove_train(map_data, train_id, train)
|
||||
end
|
||||
::continue::
|
||||
end
|
||||
map_data.depots[depot_id] = nil
|
||||
interface_raise_depot_removed(depot_id, depot)
|
||||
@@ -105,17 +116,17 @@ local function on_station_built(map_data, stop, comb1, comb2)
|
||||
entity_stop = stop,
|
||||
entity_comb1 = comb1,
|
||||
entity_comb2 = comb2,
|
||||
--is_p = set_station_from_comb_state,
|
||||
--is_r = set_station_from_comb_state,
|
||||
--allows_all_trains = set_station_from_comb_state,
|
||||
--is_p = set_station_from_comb,
|
||||
--is_r = set_station_from_comb,
|
||||
--allows_all_trains = set_station_from_comb,
|
||||
deliveries_total = 0,
|
||||
last_delivery_tick = map_data.total_ticks,
|
||||
priority = 0,
|
||||
item_priotity = nil,
|
||||
r_threshold = 0,
|
||||
locked_slots = 0,
|
||||
--network_name = set_station_from_comb_state,
|
||||
network_flag = 0,
|
||||
--network_name = set_station_from_comb,
|
||||
--network_flag = set_station_from_comb,
|
||||
wagon_combs = nil,
|
||||
deliveries = {},
|
||||
accepted_layouts = {},
|
||||
@@ -125,7 +136,6 @@ local function on_station_built(map_data, stop, comb1, comb2)
|
||||
item_thresholds = nil,
|
||||
display_state = 0,
|
||||
}
|
||||
set_station_from_comb_state(station)
|
||||
local id = stop.unit_number--[[@as uint]]
|
||||
map_data.stations[id] = station
|
||||
map_data.warmup_station_ids[#map_data.warmup_station_ids + 1] = id
|
||||
@@ -350,8 +360,8 @@ function combinator_update(map_data, comb, reset_display)
|
||||
local params = control.parameters
|
||||
local old_params = map_data.to_comb_params[unit_number]
|
||||
local has_changed = false
|
||||
local station
|
||||
local id
|
||||
local station = nil
|
||||
local id = nil
|
||||
|
||||
|
||||
if params.operation == MODE_PRIMARY_IO_ACTIVE or params.operation == MODE_PRIMARY_IO_FAILED_REQUEST or params.operation == MODE_PRIMARY_IO then
|
||||
@@ -361,7 +371,10 @@ function combinator_update(map_data, comb, reset_display)
|
||||
if stop then
|
||||
id = stop.unit_number--[[@as uint]]
|
||||
station = map_data.stations[id]
|
||||
if should_reset and station and station.entity_comb1 == comb then
|
||||
if station.entity_comb1 ~= comb then
|
||||
station = nil
|
||||
end
|
||||
if should_reset and station then
|
||||
--make sure only MODE_PRIMARY_IO gets stored on map_data.to_comb_params
|
||||
if station.display_state == 0 then
|
||||
params.operation = MODE_PRIMARY_IO
|
||||
@@ -396,12 +409,12 @@ function combinator_update(map_data, comb, reset_display)
|
||||
|
||||
local stop = map_data.to_stop[comb.unit_number]
|
||||
if stop and stop.valid then
|
||||
id = stop.unit_number
|
||||
station = map_data.stations[id]
|
||||
if station then
|
||||
if station.entity_comb1 == comb then
|
||||
station.network_name = new_network
|
||||
--NOTE: these updates have to be queued to occur at tick init since central planning is expecting them not to change between ticks
|
||||
if not map_data.queue_station_update then
|
||||
map_data.queue_station_update = {}
|
||||
end
|
||||
map_data.queue_station_update[id] = true
|
||||
else
|
||||
local depot = map_data.depots[id]
|
||||
if depot then
|
||||
@@ -426,11 +439,11 @@ function combinator_update(map_data, comb, reset_display)
|
||||
if params.second_constant ~= old_params.second_constant then
|
||||
has_changed = true
|
||||
if station then
|
||||
local pre = station.allows_all_trains
|
||||
set_station_from_comb_state(station)
|
||||
if station.allows_all_trains ~= pre then
|
||||
update_stop_if_auto(map_data, station, true)
|
||||
--NOTE: these updates have to be queued to occur at tick init since central planning is expecting them not to change between ticks
|
||||
if not map_data.queue_station_update then
|
||||
map_data.queue_station_update = {}
|
||||
end
|
||||
map_data.queue_station_update[id] = true
|
||||
else
|
||||
local refueler = map_data.refuelers[id]
|
||||
if refueler then
|
||||
@@ -553,13 +566,6 @@ local function on_stop_rename(map_data, stop, old_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local depot = map_data.depots[station_id]
|
||||
if depot and depot.available_train_id then
|
||||
local train = map_data.trains[depot.available_train_id--[[@as uint]]]
|
||||
train.depot_name = stop.backer_name
|
||||
--train.se_depot_surface_i = stop.surface.index
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -653,28 +659,28 @@ local function on_rename(event)
|
||||
end
|
||||
|
||||
|
||||
local function on_settings_changed(event)
|
||||
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as double]]
|
||||
mod_settings.update_rate = settings.global["cybersyn-update-rate"].value --[[@as int]]
|
||||
mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]]
|
||||
mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]]
|
||||
mod_settings.fuel_threshold = settings.global["cybersyn-fuel-threshold"].value--[[@as double]]
|
||||
mod_settings.depot_bypass_enabled = settings.global["cybersyn-depot-bypass-enabled"].value--[[@as boolean]]
|
||||
mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as double]]
|
||||
mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as double]]
|
||||
if event.setting == "cybersyn-ticks-per-second" then
|
||||
if mod_settings.tps > DELTA then
|
||||
local nth_tick = ceil(60/mod_settings.tps)--[[@as uint]];
|
||||
script.on_nth_tick(nth_tick, function()
|
||||
tick(global, mod_settings)
|
||||
end)
|
||||
else
|
||||
script.on_nth_tick(nil)
|
||||
---@param schedule TrainSchedule
|
||||
---@param stop LuaEntity
|
||||
---@param old_surface_index uint
|
||||
local function se_add_direct_to_station_order(schedule, stop, old_surface_index)
|
||||
local surface_i = stop.surface.index
|
||||
if surface_i ~= old_surface_index then
|
||||
local name = stop.backer_name
|
||||
local records = schedule.records
|
||||
for i = schedule.current, #records do
|
||||
if records[i].station == name then
|
||||
if i == 1 then
|
||||
--we are assuming this is the depot order
|
||||
records[#records + 1] = create_direct_to_station_order(stop)
|
||||
schedule.current = #records--[[@as uint]]
|
||||
else
|
||||
table_insert(records, i, create_direct_to_station_order(stop))
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
interface_raise_on_mod_settings_changed(event)
|
||||
end
|
||||
|
||||
local function setup_se_compat()
|
||||
IS_SE_PRESENT = remote.interfaces["space-exploration"] ~= nil
|
||||
if not IS_SE_PRESENT then return end
|
||||
@@ -687,9 +693,6 @@ local function setup_se_compat()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
local old_id = event.old_train_id_1
|
||||
--NOTE: this is not guaranteed to be unique, it should be fine since the window of time for another train to mistakenly steal this train's event data is miniscule
|
||||
--NOTE: please SE dev if you read this fix the issue where se_on_train_teleport_finished_event is returning the wrong old train id
|
||||
local train_unique_identifier = event.train.front_stock.backer_name
|
||||
|
||||
local train = map_data.trains[old_id]
|
||||
if not train then return end
|
||||
@@ -706,19 +709,27 @@ local function setup_se_compat()
|
||||
---@type uint
|
||||
local new_id = train_entity.id
|
||||
local old_surface_index = event.old_surface_index
|
||||
local train_unique_identifier = event.train.front_stock.backer_name
|
||||
|
||||
--NOTE: event.old_train_id_1 from this event is useless, it's for one of the many transient trains SE spawns while teleporting the old train, only se_on_train_teleport_started_event returns the correct old train id
|
||||
--NOTE: please SE dev if you read this fix the issue where se_on_train_teleport_finished_event is returning the wrong old train id
|
||||
local old_id = event.old_train_id_1
|
||||
local train = map_data.trains[old_id]
|
||||
if not train then return end
|
||||
|
||||
if train.is_available then
|
||||
local network = map_data.available_trains[train.network_name--[[@as string]]]
|
||||
if network then
|
||||
network[new_id] = true
|
||||
network[old_id] = nil
|
||||
local f, a
|
||||
if train.network_name == NETWORK_EACH then
|
||||
f, a = next, train.network_flag
|
||||
else
|
||||
f, a = once, train.network_name
|
||||
end
|
||||
for network_name in f, a do
|
||||
local network = map_data.available_trains[network_name]
|
||||
if network then
|
||||
network[new_id] = true
|
||||
network[old_id] = nil
|
||||
if next(network) == nil then
|
||||
map_data.available_trains[network_name] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -737,51 +748,60 @@ local function setup_se_compat()
|
||||
train.se_awaiting_rename = nil
|
||||
end
|
||||
|
||||
if not (train.status == STATUS_TO_P or train.status == STATUS_TO_R) then return end
|
||||
|
||||
local schedule = train_entity.schedule
|
||||
if schedule then
|
||||
if train.status == STATUS_TO_P or train.status == STATUS_TO_R then
|
||||
local p_station = map_data.stations[train.p_station_id]
|
||||
local p_name = p_station.entity_stop.backer_name
|
||||
local p_surface_i = p_station.entity_stop.surface.index
|
||||
local r_station = map_data.stations[train.r_station_id]
|
||||
local r_name = r_station.entity_stop.backer_name
|
||||
local r_surface_i = r_station.entity_stop.surface.index
|
||||
local records = schedule.records
|
||||
local i = schedule.current
|
||||
while i <= #records do
|
||||
if records[i].station == p_name and p_surface_i ~= old_surface_index then
|
||||
table_insert(records, i, create_direct_to_station_order(p_station.entity_stop))
|
||||
i = i + 1
|
||||
elseif records[i].station == r_name and r_surface_i ~= old_surface_index then
|
||||
table_insert(records, i, create_direct_to_station_order(r_station.entity_stop))
|
||||
i = i + 1
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
train_entity.schedule = schedule
|
||||
elseif train.status == STATUS_TO_F then
|
||||
local refueler = map_data.refuelers[train.refueler_id]
|
||||
local f_name = refueler.entity_stop.backer_name
|
||||
local f_surface_i = refueler.entity_stop.surface.index
|
||||
local records = schedule.records
|
||||
local i = schedule.current
|
||||
while i <= #records do
|
||||
if records[i].station == f_name and f_surface_i ~= old_surface_index then
|
||||
table_insert(records, i, create_direct_to_station_order(refueler.entity_stop))
|
||||
i = i + 1
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
train_entity.schedule = schedule
|
||||
if train.status == STATUS_TO_P then
|
||||
local stop = map_data.stations[train.p_station_id].entity_stop
|
||||
se_add_direct_to_station_order(schedule, stop, old_surface_index)
|
||||
end
|
||||
if train.status == STATUS_TO_P or train.status == STATUS_TO_R then
|
||||
local stop = map_data.stations[train.r_station_id].entity_stop
|
||||
se_add_direct_to_station_order(schedule, stop, old_surface_index)
|
||||
end
|
||||
if train.status == STATUS_TO_F then
|
||||
local stop = map_data.refuelers[train.refueler_id].entity_stop
|
||||
se_add_direct_to_station_order(schedule, stop, old_surface_index)
|
||||
end
|
||||
if not train.use_any_depot then
|
||||
local depot = map_data.depots[train.depot_id]
|
||||
se_add_direct_to_station_order(schedule, depot.entity_stop, old_surface_index)
|
||||
end
|
||||
train_entity.schedule = schedule
|
||||
end
|
||||
interface_raise_train_teleported(new_id, old_id)
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local function grab_all_settings()
|
||||
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as double]]
|
||||
mod_settings.update_rate = settings.global["cybersyn-update-rate"].value --[[@as int]]
|
||||
mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]]
|
||||
mod_settings.priority = settings.global["cybersyn-priority"].value--[[@as int]]
|
||||
mod_settings.locked_slots = settings.global["cybersyn-locked-slots"].value--[[@as int]]
|
||||
mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]]
|
||||
mod_settings.fuel_threshold = settings.global["cybersyn-fuel-threshold"].value--[[@as double]]
|
||||
mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as double]]
|
||||
mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as double]]
|
||||
mod_settings.allow_cargo_in_depot = settings.global["cybersyn-allow-cargo-in-depot"].value--[[@as boolean]]
|
||||
mod_settings.invert_sign = settings.global["cybersyn-invert-sign"].value--[[@as boolean]]
|
||||
end
|
||||
local function on_settings_changed(event)
|
||||
grab_all_settings()
|
||||
if event.setting == "cybersyn-ticks-per-second" then
|
||||
if mod_settings.tps > DELTA then
|
||||
local nth_tick = ceil(60/mod_settings.tps)--[[@as uint]];
|
||||
script.on_nth_tick(nth_tick, function()
|
||||
tick(global, mod_settings)
|
||||
end)
|
||||
else
|
||||
script.on_nth_tick(nil)
|
||||
end
|
||||
end
|
||||
interface_raise_on_mod_settings_changed(event)
|
||||
end
|
||||
|
||||
|
||||
local filter_built = {
|
||||
{filter = "name", name = "train-stop"},
|
||||
{filter = "name", name = COMBINATOR_NAME},
|
||||
@@ -798,18 +818,10 @@ local filter_broken = {
|
||||
{filter = "rolling-stock"},
|
||||
}
|
||||
local function main()
|
||||
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as double]]
|
||||
mod_settings.update_rate = settings.global["cybersyn-update-rate"].value --[[@as int]]
|
||||
mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]]
|
||||
mod_settings.network_flag = settings.global["cybersyn-network-flag"].value--[[@as int]]
|
||||
mod_settings.fuel_threshold = settings.global["cybersyn-fuel-threshold"].value--[[@as double]]
|
||||
mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as double]]
|
||||
mod_settings.stuck_train_time = settings.global["cybersyn-stuck-train-time"].value--[[@as double]]
|
||||
mod_settings.depot_bypass_enabled = settings.global["cybersyn-depot-bypass-enabled"].value--[[@as boolean]]
|
||||
grab_all_settings()
|
||||
|
||||
mod_settings.missing_train_alert_enabled = true
|
||||
mod_settings.stuck_train_alert_enabled = true
|
||||
mod_settings.react_to_nonempty_train_in_depot = true
|
||||
mod_settings.react_to_train_at_incorrect_station = true
|
||||
mod_settings.react_to_train_early_to_depot = true
|
||||
|
||||
@@ -848,6 +860,10 @@ local function main()
|
||||
register_gui_actions()
|
||||
|
||||
script.on_init(function()
|
||||
local setting = settings.global["cybersyn-invert-sign"]
|
||||
setting.value = false
|
||||
settings.global["cybersyn-invert-sign"] = setting
|
||||
mod_settings.invert_sign = false
|
||||
init_global()
|
||||
setup_se_compat()
|
||||
end)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
--By Mami
|
||||
local flib_migration = require("__flib__.migration")
|
||||
|
||||
|
||||
@@ -103,23 +104,40 @@ local migrations_table = {
|
||||
map_data.each_refuelers = {}
|
||||
map_data.se_tele_old_id = nil
|
||||
|
||||
for k, comb in pairs(map_data.to_comb) do
|
||||
for id, comb in pairs(map_data.to_comb) do
|
||||
local control = get_comb_control(comb)
|
||||
local params = control.parameters
|
||||
local params_old = map_data.to_comb_params[id]
|
||||
local bits = params.second_constant or 0
|
||||
local bits_old = params_old.second_constant or 0
|
||||
|
||||
local allows_all_trains = bits%2
|
||||
local is_pr_state = math.floor(bits/2)%3
|
||||
local allows_all_trains_old = bits_old%2
|
||||
local is_pr_state_old = math.floor(bits_old/2)%3
|
||||
|
||||
local new_bits = bit32.bor(is_pr_state, allows_all_trains*4)
|
||||
params.second_constant = new_bits
|
||||
bits = bit32.bor(is_pr_state, allows_all_trains*4)
|
||||
bits_old = bit32.bor(is_pr_state_old, allows_all_trains_old*4)
|
||||
params.second_constant = bits
|
||||
params_old.second_constant = bits_old
|
||||
|
||||
control.parameters = params
|
||||
map_data.to_comb_params[id] = params_old
|
||||
end
|
||||
for id, station in pairs(map_data.stations) do
|
||||
station.display_state = (station.display_state >= 2 and 1 or 0) + (station.display_state%2)*2
|
||||
|
||||
set_station_from_comb_state(station)
|
||||
update_stop_if_auto(map_data, station, true)
|
||||
local params = get_comb_params(station.entity_comb1)
|
||||
|
||||
local bits = params.second_constant or 0
|
||||
local is_pr_state = bit32.extract(bits, 0, 2)
|
||||
local allows_all_trains = bit32.extract(bits, SETTING_DISABLE_ALLOW_LIST) > 0
|
||||
local is_stack = bit32.extract(bits, SETTING_IS_STACK) > 0
|
||||
|
||||
station.allows_all_trains = allows_all_trains
|
||||
station.is_stack = is_stack
|
||||
station.is_p = (is_pr_state == 0 or is_pr_state == 1) or nil
|
||||
station.is_r = (is_pr_state == 0 or is_pr_state == 2) or nil
|
||||
end
|
||||
|
||||
map_data.layout_train_count = {}
|
||||
@@ -135,6 +153,77 @@ local migrations_table = {
|
||||
end
|
||||
end
|
||||
end,
|
||||
["1.2.2"] = function()
|
||||
---@type MapData
|
||||
local map_data = global
|
||||
local setting = settings.global["cybersyn-invert-sign"]
|
||||
setting.value = true
|
||||
settings.global["cybersyn-invert-sign"] = setting
|
||||
|
||||
for id, comb in pairs(map_data.to_comb) do
|
||||
local control = get_comb_control(comb)
|
||||
local params = control.parameters
|
||||
local params_old = map_data.to_comb_params[id]
|
||||
local bits = params.second_constant or 0
|
||||
local bits_old = params_old.second_constant or 0
|
||||
|
||||
bits = bit32.replace(bits, 1, SETTING_ENABLE_INACTIVE)--[[@as int]]
|
||||
bits = bit32.replace(bits, 1, SETTING_ENABLE_INACTIVE)--[[@as int]]
|
||||
bits_old = bit32.replace(bits_old, 1, SETTING_USE_ANY_DEPOT)--[[@as int]]
|
||||
bits_old = bit32.replace(bits_old, 1, SETTING_USE_ANY_DEPOT)--[[@as int]]
|
||||
params.second_constant = bits
|
||||
params_old.second_constant = bits_old
|
||||
|
||||
control.parameters = params
|
||||
map_data.to_comb_params[id] = params_old
|
||||
end
|
||||
for _, station in pairs(map_data.stations) do
|
||||
station.enable_inactive = true
|
||||
end
|
||||
for train_id, train in pairs(map_data.trains) do
|
||||
train.depot_id = train.parked_at_depot_id
|
||||
if not train.depot_id then
|
||||
local e = get_any_train_entity(train.entity)
|
||||
local stops = e.force.get_train_stops({name = train.depot_name, surface = e.surface})
|
||||
for stop in rnext_consume, stops do
|
||||
local new_depot_id = stop.unit_number
|
||||
if map_data.depots[new_depot_id] then
|
||||
train.depot_id = new_depot_id--[[@as uint]]
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if not train.depot_id then
|
||||
train.depot_id = next(map_data.depots)
|
||||
end
|
||||
if not train.depot_id then
|
||||
train.entity.manual_mode = true
|
||||
send_alert_depot_of_train_broken(map_data, train.entity)
|
||||
local layout_id = train.layout_id
|
||||
local count = global.layout_train_count[layout_id]
|
||||
if count <= 1 then
|
||||
global.layout_train_count[layout_id] = nil
|
||||
global.layouts[layout_id] = nil
|
||||
for _, stop in pairs(global.stations) do
|
||||
stop.accepted_layouts[layout_id] = nil
|
||||
end
|
||||
for _, stop in pairs(global.refuelers) do
|
||||
stop.accepted_layouts[layout_id] = nil
|
||||
end
|
||||
else
|
||||
global.layout_train_count[layout_id] = count - 1
|
||||
end
|
||||
map_data.trains[train_id] = nil
|
||||
end
|
||||
|
||||
train.use_any_depot = true
|
||||
train.disable_bypass = nil
|
||||
|
||||
train.depot_name = nil
|
||||
train.se_depot_surface_i = nil
|
||||
train.parked_at_depot_id = nil
|
||||
end
|
||||
end
|
||||
}
|
||||
--STATUS_R_TO_D = 5
|
||||
|
||||
|
||||
@@ -48,6 +48,18 @@ function on_failed_delivery(map_data, train_id, train)
|
||||
unset_wagon_combs(map_data, station)
|
||||
end
|
||||
end
|
||||
if train.has_filtered_wagon then
|
||||
train.has_filtered_wagon = nil
|
||||
for carriage_i, carriage in ipairs(train.entity.cargo_wagons) do
|
||||
local inv = carriage.get_inventory(defines.inventory.cargo_wagon)
|
||||
if inv and inv.is_filtered() then
|
||||
---@type uint
|
||||
for i = 1, #inv do
|
||||
inv.set_filter(i, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
train.r_station_id = nil
|
||||
train.p_station_id = nil
|
||||
train.manifest = nil
|
||||
@@ -60,14 +72,21 @@ end
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function add_available_train(map_data, train_id, train)
|
||||
local network_name = train.network_name
|
||||
if network_name then
|
||||
local network = map_data.available_trains[network_name]
|
||||
if not network then
|
||||
network = {}
|
||||
map_data.available_trains[network_name] = network
|
||||
if train.network_name then
|
||||
local f, a
|
||||
if train.network_name == NETWORK_EACH then
|
||||
f, a = next, train.network_flag
|
||||
else
|
||||
f, a = once, train.network_name
|
||||
end
|
||||
for network_name in f, a do
|
||||
local network = map_data.available_trains[network_name]
|
||||
if not network then
|
||||
network = {}
|
||||
map_data.available_trains[network_name] = network
|
||||
end
|
||||
network[train_id] = true
|
||||
end
|
||||
network[train_id] = true
|
||||
train.is_available = true
|
||||
interface_raise_train_available(train_id)
|
||||
end
|
||||
@@ -80,77 +99,56 @@ end
|
||||
---@param train Train
|
||||
function add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
|
||||
local comb = depot.entity_comb
|
||||
local network_name = get_comb_network_name(comb)
|
||||
if network_name then
|
||||
local network = map_data.available_trains[network_name]
|
||||
if not network then
|
||||
network = {}
|
||||
map_data.available_trains[network_name] = network
|
||||
end
|
||||
network[train_id] = true
|
||||
train.is_available = true
|
||||
end
|
||||
set_train_from_comb(mod_settings, train, comb)
|
||||
depot.available_train_id = train_id
|
||||
train.depot_id = depot_id
|
||||
train.status = STATUS_D
|
||||
train.parked_at_depot_id = depot_id
|
||||
train.depot_name = depot.entity_stop.backer_name
|
||||
train.se_depot_surface_i = depot.entity_stop.surface.index
|
||||
train.network_name = network_name
|
||||
train.network_flag = mod_settings.network_flag
|
||||
train.priority = 0
|
||||
if network_name then
|
||||
local signals = comb.get_merged_signals(defines.circuit_connector_id.combinator_input)
|
||||
if signals then
|
||||
for k, v in pairs(signals) do
|
||||
local item_name = v.signal.name
|
||||
local item_count = v.count
|
||||
if item_name then
|
||||
if item_name == SIGNAL_PRIORITY then
|
||||
train.priority = item_count
|
||||
end
|
||||
if item_name == network_name then
|
||||
train.network_flag = item_count
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
interface_raise_train_available(train_id)
|
||||
end
|
||||
|
||||
add_available_train(map_data, train_id, train)
|
||||
end
|
||||
---@param map_data MapData
|
||||
---@param train_id uint
|
||||
---@param train Train
|
||||
function remove_available_train(map_data, train_id, train)
|
||||
---@type uint
|
||||
if train.is_available and train.network_name then
|
||||
local network = map_data.available_trains[train.network_name--[[@as string]]]
|
||||
if network then
|
||||
network[train_id] = nil
|
||||
if next(network) == nil then
|
||||
map_data.available_trains[train.network_name] = nil
|
||||
if train.is_available then
|
||||
train.is_available = nil
|
||||
local f, a
|
||||
if train.network_name == NETWORK_EACH then
|
||||
f, a = next, train.network_flag
|
||||
else
|
||||
f, a = once, train.network_name
|
||||
end
|
||||
for network_name in f, a do
|
||||
local network = map_data.available_trains[network_name]
|
||||
if network then
|
||||
network[train_id] = nil
|
||||
if next(network) == nil then
|
||||
map_data.available_trains[network_name] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
train.is_available = nil
|
||||
local depot = map_data.depots[train.depot_id]
|
||||
if depot.available_train_id == train_id then
|
||||
depot.available_train_id = nil
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
---@param map_data MapData
|
||||
---@param depot_id uint
|
||||
---@param train_entity LuaTrain
|
||||
local function on_train_arrives_depot(map_data, depot_id, train_entity)
|
||||
local contents = train_entity.get_contents()
|
||||
local fluid_contents = train_entity.get_fluid_contents()
|
||||
local is_train_empty = next(contents) == nil and next(fluid_contents) == nil
|
||||
local is_train_empty = next(train_entity.get_contents()) == nil and next(train_entity.get_fluid_contents()) == nil
|
||||
local train_id = train_entity.id
|
||||
local train = map_data.trains[train_id]
|
||||
if train then
|
||||
if train.status == STATUS_TO_D then
|
||||
elseif train.status == STATUS_TO_D_BYPASS or train.status == STATUS_D then
|
||||
--shouldn't be possible to get train.status == STATUS_D
|
||||
elseif train.status == STATUS_TO_D_BYPASS or train.status == STATUS_D then
|
||||
remove_available_train(map_data, train_id, train)
|
||||
elseif mod_settings.react_to_train_early_to_depot then
|
||||
if train.manifest then
|
||||
@@ -160,21 +158,19 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
|
||||
else
|
||||
return
|
||||
end
|
||||
if is_train_empty then
|
||||
if is_train_empty or mod_settings.allow_cargo_in_depot then
|
||||
local old_status = train.status
|
||||
add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, map_data.depots[depot_id])
|
||||
set_depot_schedule(train_entity, train.depot_name)
|
||||
local depot = map_data.depots[depot_id]
|
||||
add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
|
||||
set_depot_schedule(train_entity, depot.entity_stop.backer_name)
|
||||
interface_raise_train_status_changed(train_id, old_status, STATUS_D)
|
||||
else
|
||||
--train still has cargo
|
||||
if mod_settings.react_to_nonempty_train_in_depot then
|
||||
lock_train_to_depot(train_entity)
|
||||
remove_train(map_data, train_id, train)
|
||||
send_alert_nonempty_train_in_depot(map_data, train_entity)
|
||||
end
|
||||
interface_raise_train_nonempty_in_depot(depot_id, train_entity, train_id)
|
||||
lock_train_to_depot(train_entity)
|
||||
remove_train(map_data, train_id, train)
|
||||
send_alert_nonempty_train_in_depot(map_data, train_entity)
|
||||
end
|
||||
elseif is_train_empty then
|
||||
elseif is_train_empty or mod_settings.allow_cargo_in_depot then
|
||||
--NOTE: only place where new Train
|
||||
train = {
|
||||
entity = train_entity,
|
||||
@@ -188,22 +184,25 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
|
||||
last_manifest_tick = map_data.total_ticks,
|
||||
has_filtered_wagon = nil,
|
||||
--is_available = add_available_train_to_depot,
|
||||
--parked_at_depot_id = add_available_train_to_depot,
|
||||
--depot_name = add_available_train_to_depot,
|
||||
--depot_id = add_available_train_to_depot,
|
||||
--use_any_depot = add_available_train_to_depot,
|
||||
--disable_bypass = add_available_train_to_depot,
|
||||
--network_name = add_available_train_to_depot,
|
||||
--network_flag = add_available_train_to_depot,
|
||||
--priority = add_available_train_to_depot,
|
||||
}
|
||||
}--[[@as Train]]
|
||||
set_train_layout(map_data, train)
|
||||
map_data.trains[train_id] = train
|
||||
add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, map_data.depots[depot_id])
|
||||
local depot = map_data.depots[depot_id]
|
||||
add_available_train_to_depot(map_data, mod_settings, train_id, train, depot_id, depot)
|
||||
|
||||
set_depot_schedule(train_entity, train.depot_name)
|
||||
set_depot_schedule(train_entity, depot.entity_stop.backer_name)
|
||||
interface_raise_train_created(train_id, depot_id)
|
||||
else
|
||||
if mod_settings.react_to_nonempty_train_in_depot then
|
||||
send_alert_nonempty_train_in_depot(map_data, train_entity)
|
||||
end
|
||||
lock_train_to_depot(train_entity)
|
||||
send_alert_nonempty_train_in_depot(map_data, train_entity)
|
||||
end
|
||||
if not is_train_empty then
|
||||
interface_raise_train_nonempty_in_depot(depot_id, train_entity)
|
||||
end
|
||||
end
|
||||
@@ -218,7 +217,7 @@ local function on_train_arrives_station(map_data, station_id, train_id, train)
|
||||
if train.p_station_id == station_id then
|
||||
train.status = STATUS_P
|
||||
local station = map_data.stations[station_id]
|
||||
set_comb1(map_data, station, train.manifest, 1)
|
||||
set_comb1(map_data, station, train.manifest, mod_settings.invert_sign and 1 or -1)
|
||||
set_p_wagon_combs(map_data, station, train)
|
||||
interface_raise_train_status_changed(train_id, STATUS_TO_P, STATUS_P)
|
||||
end
|
||||
@@ -226,7 +225,7 @@ local function on_train_arrives_station(map_data, station_id, train_id, train)
|
||||
if train.r_station_id == station_id then
|
||||
train.status = STATUS_R
|
||||
local station = map_data.stations[station_id]
|
||||
set_comb1(map_data, station, train.manifest, -1)
|
||||
set_comb1(map_data, station, train.manifest, mod_settings.invert_sign and -1 or 1)
|
||||
set_r_wagon_combs(map_data, station, train)
|
||||
interface_raise_train_status_changed(train_id, STATUS_TO_R, STATUS_R)
|
||||
end
|
||||
@@ -316,45 +315,54 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
|
||||
end
|
||||
if fuel_fill > mod_settings.fuel_threshold then
|
||||
--if fuel_fill == INF, it's probably a modded electric train
|
||||
if mod_settings.depot_bypass_enabled then
|
||||
if not train.disable_bypass then
|
||||
train.status = STATUS_TO_D_BYPASS
|
||||
add_available_train(map_data, train_id, train)
|
||||
interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_D_BYPASS)
|
||||
return
|
||||
end
|
||||
else
|
||||
local refuelers = map_data.to_refuelers[train.network_name]
|
||||
if refuelers then
|
||||
local best_refueler_id = nil
|
||||
local best_dist = INF
|
||||
local best_prior = -INF
|
||||
for id, _ in pairs(refuelers) do
|
||||
local refueler = map_data.refuelers[id]
|
||||
set_refueler_from_comb(map_data, mod_settings, id)
|
||||
local f, a
|
||||
if train.network_name == NETWORK_EACH then
|
||||
f, a = next, train.network_flag
|
||||
else
|
||||
f, a = once, train.network_name
|
||||
end
|
||||
for network_name in f, a do
|
||||
local refuelers = map_data.to_refuelers[network_name]
|
||||
if refuelers then
|
||||
local best_refueler_id = nil
|
||||
local best_dist = INF
|
||||
local best_prior = -INF
|
||||
for id, _ in pairs(refuelers) do
|
||||
local refueler = map_data.refuelers[id]
|
||||
set_refueler_from_comb(map_data, mod_settings, id)
|
||||
|
||||
local refueler_network_flag = refueler.network_name == NETWORK_EACH and (refueler.network_flag[train.network_name] or 0) or refueler.network_flag
|
||||
if btest(train.network_flag, refueler_network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then
|
||||
local accepted = false
|
||||
local dist = nil
|
||||
if refueler.priority == best_prior then
|
||||
dist = get_stop_dist(train.entity.front_stock, refueler.entity_stop)
|
||||
accepted = dist < best_dist
|
||||
end
|
||||
if accepted or refueler.priority > best_prior then
|
||||
best_refueler_id = id
|
||||
best_dist = dist or get_stop_dist(train.entity.front_stock, refueler.entity_stop)
|
||||
best_prior = refueler.priority
|
||||
local refueler_network_flag = get_network_flag(refueler, network_name)
|
||||
local train_network_flag = get_network_flag(train, network_name)
|
||||
if btest(train_network_flag, refueler_network_flag) and (refueler.allows_all_trains or refueler.accepted_layouts[train.layout_id]) and refueler.trains_total < refueler.entity_stop.trains_limit then
|
||||
local accepted = false
|
||||
local dist = nil
|
||||
if refueler.priority == best_prior then
|
||||
dist = get_stop_dist(train.entity.front_stock, refueler.entity_stop)
|
||||
accepted = dist < best_dist
|
||||
end
|
||||
if accepted or refueler.priority > best_prior then
|
||||
best_refueler_id = id
|
||||
best_dist = dist or get_stop_dist(train.entity.front_stock, refueler.entity_stop)
|
||||
best_prior = refueler.priority
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if best_refueler_id then
|
||||
train.status = STATUS_TO_F
|
||||
train.refueler_id = best_refueler_id
|
||||
local refueler = map_data.refuelers[best_refueler_id]
|
||||
refueler.trains_total = refueler.trains_total + 1
|
||||
add_refueler_schedule(map_data, train.entity, refueler.entity_stop)
|
||||
interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_F)
|
||||
return
|
||||
if best_refueler_id then
|
||||
train.status = STATUS_TO_F
|
||||
train.refueler_id = best_refueler_id
|
||||
local refueler = map_data.refuelers[best_refueler_id]
|
||||
refueler.trains_total = refueler.trains_total + 1
|
||||
add_refueler_schedule(map_data, train.entity, refueler.entity_stop)
|
||||
interface_raise_train_status_changed(train_id, STATUS_R, STATUS_TO_F)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -367,7 +375,7 @@ local function on_train_leaves_stop(map_data, mod_settings, train_id, train)
|
||||
refueler.trains_total = refueler.trains_total - 1
|
||||
unset_wagon_combs(map_data, refueler)
|
||||
set_combinator_output(map_data, refueler.entity_comb, nil)
|
||||
if mod_settings.depot_bypass_enabled then
|
||||
if not train.disable_bypass then
|
||||
train.status = STATUS_TO_D_BYPASS
|
||||
add_available_train(map_data, train_id, train)
|
||||
else
|
||||
|
||||
@@ -18,28 +18,37 @@ data:extend({
|
||||
minimum_value = 1,
|
||||
maximum_value = 2147483647,
|
||||
},
|
||||
--{
|
||||
-- type = "int-setting",
|
||||
-- name = "cybersyn-wait-time",
|
||||
-- order = "ab",
|
||||
-- setting_type = "runtime-global",
|
||||
-- default_value = 2000,
|
||||
-- minimum_value = 1,
|
||||
-- maximum_value = 2147483647,
|
||||
--},
|
||||
{
|
||||
type = "double-setting",
|
||||
type = "int-setting",
|
||||
name = "cybersyn-request-threshold",
|
||||
order = "ac",
|
||||
order = "ba",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 1,
|
||||
minimum_value = 0,
|
||||
default_value = 2000,
|
||||
minimum_value = 1,
|
||||
maximum_value = 2147483647,
|
||||
},
|
||||
{
|
||||
type = "int-setting",
|
||||
name = "cybersyn-priority",
|
||||
order = "bb",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 0,
|
||||
minimum_value = -2147483648,
|
||||
maximum_value = 2147483647,
|
||||
},
|
||||
{
|
||||
type = "int-setting",
|
||||
name = "cybersyn-locked-slots",
|
||||
order = "bc",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 0,
|
||||
minimum_value = 0,
|
||||
maximum_value = 1000,
|
||||
},
|
||||
{
|
||||
type = "int-setting",
|
||||
name = "cybersyn-network-flag",
|
||||
order = "ad",
|
||||
order = "bd",
|
||||
setting_type = "runtime-global",
|
||||
default_value = -1,
|
||||
minimum_value = -2147483648,
|
||||
@@ -48,23 +57,16 @@ data:extend({
|
||||
{
|
||||
type = "double-setting",
|
||||
name = "cybersyn-fuel-threshold",
|
||||
order = "ae",
|
||||
order = "be",
|
||||
setting_type = "runtime-global",
|
||||
default_value = .5,
|
||||
minimum_value = 0,
|
||||
maximum_value = 1,
|
||||
},
|
||||
{
|
||||
type = "bool-setting",
|
||||
name = "cybersyn-depot-bypass-enabled",
|
||||
order = "af",
|
||||
setting_type = "runtime-global",
|
||||
default_value = true,
|
||||
},
|
||||
{
|
||||
type = "double-setting",
|
||||
name = "cybersyn-warmup-time",
|
||||
order = "ag",
|
||||
order = "ca",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 20,
|
||||
minimum_value = 0,
|
||||
@@ -73,10 +75,24 @@ data:extend({
|
||||
{
|
||||
type = "double-setting",
|
||||
name = "cybersyn-stuck-train-time",
|
||||
order = "ah",
|
||||
order = "cb",
|
||||
setting_type = "runtime-global",
|
||||
default_value = 600,
|
||||
minimum_value = 0,
|
||||
maximum_value = 2147483647,
|
||||
},
|
||||
{
|
||||
type = "bool-setting",
|
||||
name = "cybersyn-allow-cargo-in-depot",
|
||||
order = "cc",
|
||||
setting_type = "runtime-global",
|
||||
default_value = false,
|
||||
},
|
||||
{
|
||||
type = "bool-setting",
|
||||
name = "cybersyn-invert-sign",
|
||||
order = "da",
|
||||
setting_type = "runtime-global",
|
||||
default_value = false,
|
||||
},
|
||||
})
|
||||
|
||||
1
cybersyn_blueprints.txt
Normal file
1
cybersyn_blueprints.txt
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user