readded copy-paste

This commit is contained in:
Monica Moniot
2022-11-25 22:57:12 -05:00
parent be3f2f1d07
commit c4d8d3d21b
11 changed files with 346 additions and 284 deletions

14
TODO
View File

@@ -1,9 +1,13 @@
bugs:
major:
do hardcore testing
models & art
railloader compat
minor:
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
do hardcore testing
models & art
space elevator compat
railloader compat
major bug with copy-paste when the operation is changed by blueprint but it gets copied to the old settings before it's checked for update
go over init and make it agree with type info

View File

@@ -52,3 +52,10 @@ Version: 0.5.0
Date: 2022-11-25
Features:
- Added SE space elevator compat
---------------------------------------------------------------------------------------------------
Version: 0.5.1
Date: 2022-11-25
Features:
- Re-added combinator copy-paste
- Fixed bugs within train blacklist logic
- Fixed a crash

View File

@@ -1,6 +1,6 @@
{
"name": "cybersyn",
"version": "0.5.0",
"version": "0.5.1",
"title": "Project Cybersyn",
"author": "Mami",
"factorio_version": "1.1",

View File

@@ -12,7 +12,7 @@ combinator_entity.radius_visualisation_specification = {
distance = 1.5,
}
combinator_entity.active_energy_usage = "10KW"
combinator_entity.allow_copy_paste = false
--combinator_entity.allow_copy_paste = false

View File

@@ -26,7 +26,7 @@ function remove_manifest(map_data, station, manifest, sign)
set_comb2(map_data, station)
station.deliveries_total = station.deliveries_total - 1
if station.deliveries_total == 0 and station.entity_comb1.valid then
map_data.to_comb_params[station.entity_comb1.unit_number] = set_combinator_operation(station.entity_comb1, OPERATION_PRIMARY_IO)
set_comb_operation_with_check(map_data, station.entity_comb1, OPERATION_PRIMARY_IO)
end
end
@@ -214,10 +214,10 @@ local function send_train_between(map_data, r_station_id, p_station_id, depot, p
set_comb2(map_data, p_station)
set_comb2(map_data, r_station)
if p_station.entity_comb1.valid then
map_data.to_comb_params[p_station.entity_comb1.unit_number] = set_combinator_operation(p_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE)
set_comb_operation_with_check(map_data, p_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE)
end
if r_station.entity_comb1.valid then
map_data.to_comb_params[r_station.entity_comb1.unit_number] = set_combinator_operation(r_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE)
set_comb_operation_with_check(map_data, r_station.entity_comb1, OPERATION_PRIMARY_IO_ACTIVE)
end
end
@@ -229,11 +229,22 @@ local function tick_poll_train(map_data, mod_settings)
local train_id, train = next(map_data.trains, tick_data.last_train)
tick_data.last_train = train_id
if train and train.manifest and train.last_manifest_tick + mod_settings.stuck_train_time*mod_settings.tps < map_data.total_ticks then
if train and train.manifest and train.entity and train.last_manifest_tick + mod_settings.stuck_train_time*mod_settings.tps < map_data.total_ticks then
send_stuck_train_alert(train.entity, train.depot_name)
end
end
---@param map_data MapData
local function tick_poll_comb(map_data)
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
if comb and comb.valid then
combinator_update(map_data, comb)
end
end
---@param map_data MapData
---@param mod_settings CybersynModSettings
local function tick_poll_station(map_data, mod_settings)
local tick_data = map_data.tick_data
@@ -254,7 +265,7 @@ local function tick_poll_station(map_data, mod_settings)
station = map_data.stations[station_id]
if station then
if station.display_update then
map_data.to_comb_params[station.entity_comb1.unit_number] = update_combinator_display(station.entity_comb1, station.display_failed_request)
update_combinator_display(map_data, station.entity_comb1, station.display_failed_request)
station.display_update = station.display_failed_request
station.display_failed_request = nil
end
@@ -373,6 +384,7 @@ local function tick_dispatch(map_data, mod_settings)
local name_i = size <= 2 and 2 or 2*random(size/2)
local item_network_name = all_names[name_i - 1]
local signal = all_names[name_i]
--swap remove
all_names[name_i - 1] = all_names[size - 1]
all_names[name_i] = all_names[size]
@@ -384,7 +396,7 @@ local function tick_dispatch(map_data, mod_settings)
if p_stations then
tick_data.r_stations = r_stations
tick_data.p_stations = p_stations
tick_data.item_name = signal.name
tick_data.item_name = signal.name--[[@as string]]
tick_data.item_type = signal.type
table_sort(r_stations, function(a_id, b_id)
local a = stations[a_id]
@@ -417,6 +429,7 @@ local function tick_dispatch(map_data, mod_settings)
if r_station and r_station.deliveries_total < r_station.entity_stop.trains_limit then
local item_name = tick_data.item_name
local item_type = tick_data.item_type
--NOTE: the station at r_station_id could have been deleted and reregistered since last poll, this check here prevents it from being processed for a delivery in that case
local r_threshold = r_station.p_count_or_r_threshold_per_item[item_name]
if r_threshold then
@@ -483,6 +496,7 @@ function tick(map_data, mod_settings)
end
end
tick_poll_train(map_data, mod_settings)
tick_poll_comb(map_data)
end
if map_data.tick_state == STATE_POLL_STATIONS then

View File

@@ -14,10 +14,31 @@ end
---@param stop0 LuaEntity
---@param stop1 LuaEntity
function get_stop_dist(stop0, stop1)
return get_distance(stop0.position, stop1.position)
local surface0 = stop0.surface.index
local surface1 = stop1.surface.index
return (surface0 == surface1 and get_distance(stop0.position, stop1.position) or DIFFERENT_SURFACE_DISTANCE)
end
---@param surface LuaSurface
local function se_get_space_elevator_name(surface)
--TODO: check how expensive the following is and potentially cache it's results
local entity = surface.find_entities_filtered({
name = SE_ELEVATOR_STOP_PROTO_NAME,
type = "train-stop",
limit = 1,
})[1]
if entity and entity.valid then
return string.sub(entity.backer_name, 1, string.len(entity.backer_name) - SE_ELEVATOR_SUFFIX_LENGTH)
end
end
------------------------------------------------------------------------------
--[[train schedules]]--
------------------------------------------------------------------------------
local create_loading_order_condition = {type = "inactivity", compare_type = "and", ticks = 120}
---@param stop LuaEntity
---@param manifest Manifest
@@ -69,22 +90,7 @@ end
function lock_train(train)
train.manual_mode = true
end
--[[
---@param train LuaTrain
---@param depot_stop LuaEntity
---@param p_stop LuaEntity
---@param r_stop LuaEntity
---@param manifest Manifest
function set_manifest_schedule(train, depot_stop, p_stop, r_stop, manifest)
train.schedule = {current = 1, records = {
create_inactivity_order(depot_stop.backer_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),
}}
end
]]
---@param train LuaTrain
---@param stop LuaEntity
---@param old_name string
@@ -99,64 +105,230 @@ function rename_manifest_schedule(train, stop, old_name)
end
train.schedule = schedule
end
---@param train LuaTrain
---@param depot_stop LuaEntity
---@param p_stop LuaEntity
---@param r_stop LuaEntity
---@param manifest Manifest
function set_manifest_schedule(train, depot_stop, p_stop, r_stop, manifest)
--NOTE: train must be on same surface as depot_stop
local d_surface = depot_stop.surface
local p_surface = p_stop.surface
local r_surface = r_stop.surface
local d_surface_i = d_surface.index
local p_surface_i = p_surface.index
local r_surface_i = r_surface.index
if d_surface_i == p_surface_i and p_surface_i == r_surface_i then
train.schedule = {current = 1, records = {
create_inactivity_order(depot_stop.backer_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),
}}
return
elseif IS_SE_PRESENT and (d_surface_i == p_surface_i or p_surface_i == r_surface_i or r_surface_i == d_surface_i) then
local d_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = d_surface_i})
local other_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = (d_surface_i == p_surface_i) and r_surface_i or p_surface_i})
local is_train_in_orbit = other_zone.orbit_index == d_zone.index
if is_train_in_orbit or d_zone.orbit_index == other_zone.index then
local elevator_name = se_get_space_elevator_name(d_surface)
if elevator_name then
local records = {create_inactivity_order(depot_stop.backer_name)}
if d_surface_i == p_surface_i then
records[#records + 1] = create_direct_to_station_order(p_stop)
else
records[#records + 1] = {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)}
is_train_in_orbit = not is_train_in_orbit
end
records[#records + 1] = create_loading_order(p_stop, manifest)
if p_surface_i ~= r_surface_i then
records[#records + 1] = {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)}
is_train_in_orbit = not is_train_in_orbit
end
records[#records + 1] = create_unloading_order(r_stop)
if r_surface_i ~= d_surface_i then
records[#records + 1] = {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)}
is_train_in_orbit = not is_train_in_orbit
end
train.schedule = {current = 1, records = records}
return
end
end
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_stop.backer_name),
create_loading_order(p_stop, manifest),
create_unloading_order(r_stop),
}}
lock_train(train)
send_lost_train_alert(train, depot_stop.backer_name)
end
------------------------------------------------------------------------------
--[[combinators]]--
------------------------------------------------------------------------------
---@param comb LuaEntity
function get_comb_control(comb)
--NOTE: using this as opposed to get_comb_params gives you R/W access
return comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
end
---@param comb LuaEntity
function get_comb_params(comb)
return comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
end
---@param param ArithmeticCombinatorParameters
function get_comb_secondary_state(param)
local bits = param.second_constant or 0
return bits%2 == 1, floor(bits/2)%3
---@param comb LuaEntity
function get_comb_gui_settings(comb)
local params = get_comb_params(comb)
local op = params.operation
local selected_index = 0
local switch_state = "none"
local bits = params.second_constant or 0
local allows_all_trains = bits%2 == 1
local is_pr_state = floor(bits/2)%3
if is_pr_state == 0 then
switch_state = "none"
elseif is_pr_state == 1 then
switch_state = "left"
elseif is_pr_state == 2 then
switch_state = "right"
end
if op == OPERATION_PRIMARY_IO or op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_FAILED_REQUEST then
selected_index = 1
elseif op == OPERATION_SECONDARY_IO then
selected_index = 2
elseif op == OPERATION_DEPOT then
selected_index = 3
elseif op == OPERATION_WAGON_MANIFEST then
selected_index = 4
end
return selected_index, params.first_signal, not allows_all_trains, switch_state
end
---@param comb LuaEntity
function get_comb_network_name(comb)
local params = get_comb_params(comb)
local signal = params.first_signal
return signal and signal.name or nil
end
---@param station Station
function set_station_from_comb_state(station)
--NOTE: this does nothing to update currently active deliveries
local param = get_comb_params(station.entity_comb1)
local bits = param.second_constant or 0
local params = get_comb_params(station.entity_comb1)
local bits = params.second_constant or 0
local is_pr_state = floor(bits/2)%3
local signal = param.first_signal
local signal = params.first_signal
station.network_name = signal and signal.name or nil
station.allows_all_trains = bits%2 == 1
station.is_p = is_pr_state == 0 or is_pr_state == 1
station.is_r = is_pr_state == 0 or is_pr_state == 2
end
---@param map_data MapData
---@param unit_number uint
---@param params ArithmeticCombinatorParameters
function has_comb_params_changed(map_data, unit_number, params)
local old_params = map_data.to_comb_params[unit_number]
if params.operation ~= old_params.operation then
if (old_params.operation == OPERATION_PRIMARY_IO) and (params.operation == OPERATION_PRIMARY_IO_ACTIVE or params.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST) then
else
return true
end
end
local new_signal = params.first_signal
local old_signal = old_params.first_signal
local new_network = new_signal and new_signal.name or nil
local old_network = old_signal and old_signal.name or nil
if new_network ~= old_network then
return true
end
if params.second_constant ~= old_params.second_constant then
return true
end
return false
end
---@param map_data MapData
---@param comb LuaEntity
---@param op string
function set_comb_operation_with_check(map_data, comb, op)
---@type uint
local unit_number = comb.unit_number
local control = get_comb_control(comb)
local params = control.parameters
if not has_comb_params_changed(map_data, unit_number, params) then
params.operation = op
control.parameters = params
if (op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_FAILED_REQUEST) then
params.operation = OPERATION_PRIMARY_IO
end
map_data.to_comb_params[unit_number] = params
end
end
---@param map_data MapData
---@param comb LuaEntity
---@param is_failed boolean
function update_combinator_display(map_data, comb, is_failed)
---@type uint
local unit_number = comb.unit_number
local control = get_comb_control(comb)
local params = control.parameters
if not has_comb_params_changed(map_data, unit_number, params) then
if is_failed then
if params.operation == OPERATION_PRIMARY_IO then
params.operation = OPERATION_PRIMARY_IO_FAILED_REQUEST
control.parameters = params
params.operation = OPERATION_PRIMARY_IO
map_data.to_comb_params[unit_number] = params
end
elseif params.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST then
params.operation = OPERATION_PRIMARY_IO
control.parameters = params
map_data.to_comb_params[unit_number] = params
end
end
end
---@param comb LuaEntity
---@param allows_all_trains boolean
function set_comb_allows_all_trains(comb, allows_all_trains)
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = get_comb_control(comb)
local param = control.parameters
local bits = param.second_constant or 0
param.second_constant = (bits - bits%2) + (allows_all_trains and 1 or 0)
control.parameters = param
return param
end
---@param comb LuaEntity
---@param is_pr_state 0|1|2
function set_comb_is_pr_state(comb, is_pr_state)
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = get_comb_control(comb)
local param = control.parameters
local bits = param.second_constant or 0
param.second_constant = (bits%2) + (2*is_pr_state)
control.parameters = param
return param
end
---@param comb LuaEntity
function get_comb_network_name(comb)
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local signal = control.parameters.first_signal
return signal and signal.name
end
---@param comb LuaEntity
---@param signal SignalID?
function set_comb_network_name(comb, signal)
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = get_comb_control(comb)
local param = control.parameters
param.first_signal = signal
control.parameters = param
return param
end
---@param comb LuaEntity
---@param op string
function set_comb_operation(comb, op)
local control = get_comb_control(comb)
local params = control.parameters
params.operation = op
control.parameters = params
end
@@ -169,32 +341,6 @@ function set_combinator_output(map_data, comb, signals)
out.get_or_create_control_behavior().parameters = signals
end
end
---@param comb LuaEntity
---@param op string
function set_combinator_operation(comb, op)
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local param = control.parameters
param.operation = op
control.parameters = param
return param
end
---@param comb LuaEntity
---@param is_failed boolean
function update_combinator_display(comb, is_failed)
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local param = control.parameters
if is_failed then
if param.operation == OPERATION_PRIMARY_IO then
param.operation = OPERATION_PRIMARY_IO_FAILED_REQUEST
control.parameters = param
end
elseif param.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST then
param.operation = OPERATION_PRIMARY_IO
control.parameters = param
end
return param
end
---@param station Station
function get_signals(station)
@@ -236,6 +382,12 @@ function get_threshold(map_data, station, signal)
return station.r_threshold
end
------------------------------------------------------------------------------
--[[alerts]]--
------------------------------------------------------------------------------
local send_missing_train_alert_for_stop_icon = {name = MISSING_TRAIN_NAME, type = "fluid"}
---@param r_stop LuaEntity
---@param p_stop LuaEntity
@@ -312,89 +464,3 @@ function send_stuck_train_alert(train, depot_name)
end
end
end
--function se_create_placeholder_order()
--end
---@param surface LuaSurface
local function se_get_space_elevator_name(surface)
--TODO: check how expensive the following is and potentially cache it's results
local entity = surface.find_entities_filtered({
name = SE_ELEVATOR_STOP_PROTO_NAME,
type = "train-stop",
limit = 1,
})[1]
if entity and entity.valid then
return string.sub(entity.backer_name, 1, string.len(entity.backer_name) - SE_ELEVATOR_SUFFIX_LENGTH)
end
end
---@param train LuaTrain
---@param depot_stop LuaEntity
---@param p_stop LuaEntity
---@param r_stop LuaEntity
---@param manifest Manifest
function set_manifest_schedule(train, depot_stop, p_stop, r_stop, manifest)
--NOTE: train must be on same surface as depot_stop
local d_surface = depot_stop.surface
local p_surface = p_stop.surface
local r_surface = r_stop.surface
local d_surface_i = d_surface.index
local p_surface_i = p_surface.index
local r_surface_i = r_surface.index
if d_surface_i == p_surface_i and p_surface_i == r_surface_i then
train.schedule = {current = 1, records = {
create_inactivity_order(depot_stop.backer_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),
}}
return
elseif IS_SE_PRESENT and (d_surface_i == p_surface_i or p_surface_i == r_surface_i or r_surface_i == d_surface_i) then
local d_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = d_surface_i})
local other_zone = remote.call("space-exploration", "get_zone_from_surface_index", {surface_index = (d_surface_i == p_surface_i) and r_surface_i or p_surface_i})
local is_train_in_orbit = other_zone.orbit_index == d_zone.index
if is_train_in_orbit or d_zone.orbit_index == other_zone.index then
local elevator_name = se_get_space_elevator_name(d_surface)
if elevator_name then
local records = {create_inactivity_order(depot_stop.backer_name)}
if d_surface_i == p_surface_i then
records[#records + 1] = create_direct_to_station_order(p_stop)
else
records[#records + 1] = {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)}
is_train_in_orbit = not is_train_in_orbit
end
records[#records + 1] = create_loading_order(p_stop, manifest)
if p_surface_i ~= r_surface_i then
records[#records + 1] = {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)}
is_train_in_orbit = not is_train_in_orbit
end
records[#records + 1] = create_unloading_order(r_stop)
if r_surface_i ~= d_surface_i then
records[#records + 1] = {station = elevator_name..(is_train_in_orbit and SE_ELEVATOR_ORBIT_SUFFIX or SE_ELEVATOR_PLANET_SUFFIX)}
is_train_in_orbit = not is_train_in_orbit
end
train.schedule = {current = 1, records = records}
return
end
end
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_stop.backer_name),
create_loading_order(p_stop, manifest),
create_unloading_order(r_stop),
}}
lock_train(train)
send_lost_train_alert(train, depot_stop.backer_name)
end
---@param stop0 LuaEntity
---@param stop1 LuaEntity
function se_get_stop_dist(stop0, stop1)
local surface0 = stop0.surface.index
local surface1 = stop1.surface.index
return (surface0 == surface1 and get_distance(stop0.position, stop1.position) or DIFFERENT_SURFACE_DISTANCE)
end

View File

@@ -2,7 +2,6 @@
---@class MapData
---@field public total_ticks uint
---@field public layout_top_id uint
---@field public is_player_cursor_blueprint {[uint]: true|nil}
---@field public to_comb {[uint]: LuaEntity}
---@field public to_comb_params {[uint]: ArithmeticCombinatorParameters}
---@field public to_output {[uint]: LuaEntity}
@@ -36,7 +35,7 @@
---@field public deliveries {[string]: int}
---@field public network_name string?
---@field public network_flag int --transient
---@field public accepted_layouts TrainClass
---@field public accepted_layouts {[uint]: true?}
---@field public layout_pattern {[uint]: int}
---@field public tick_signals {[uint]: Signal}? --transient
---@field public p_count_or_r_threshold_per_item {[string]: int} --transient
@@ -61,21 +60,20 @@
---@field public has_filtered_wagon boolean
---@field public depot_id uint?
---@field public depot_name string
---@field public network_name string
---@field public network_name string?
---@field public network_flag int
---@field public priority int
---@field public se_awaiting_removal any?
---@field public se_awaiting_rename any?
---@alias Manifest {}[]
---@alias TrainClass {[uint]: true}
---@alias cybersyn.global MapData
---@class Economy
---could contain invalid stations
---@field public all_r_stations {[string]: uint[]} --{[network_name:item_name]: count}
---@field public all_p_stations {[string]: uint[]} --{[network_name:item_name]: count}
---@field public all_names {[string]: uint[]} --{[network_name:item_name]: count}
---@field public all_r_stations {[string]: uint[]} --{[network_name:item_name]: station_id}
---@field public all_p_stations {[string]: uint[]} --{[network_name:item_name]: station_id}
---@field public all_names (string|SignalID)[]
---@class CybersynModSettings
---@field public tps int
@@ -111,7 +109,6 @@ function init_global()
global.layouts = {}
global.layout_train_count = {}
global.layout_top_id = 1
global.is_player_cursor_blueprint = {}
if IS_SE_PRESENT then
global.se_tele_old_id = {}

View File

@@ -30,29 +30,7 @@ STATUS_NAMES_DEFAULT = "entity-status.disabled"
---@param player LuaPlayer
function gui_opened(comb, player)
local rootgui = player.gui.screen
local param = get_comb_params(comb)
local op = param.operation
local selected_index = 0
local switch_state = "none"
local allows_all_trains, is_pr_state = get_comb_secondary_state(param)
if is_pr_state == 0 then
switch_state = "none"
elseif is_pr_state == 1 then
switch_state = "left"
elseif is_pr_state == 2 then
switch_state = "right"
end
if op == OPERATION_PRIMARY_IO or op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_FAILED_REQUEST then
selected_index = 1
elseif op == OPERATION_SECONDARY_IO then
selected_index = 2
elseif op == OPERATION_DEPOT then
selected_index = 3
elseif op == OPERATION_WAGON_MANIFEST then
selected_index = 4
end
local selected_index, signal, check, switch_state = get_comb_gui_settings(comb)
local window = flib_gui.build(rootgui, {
{type="frame", direction="vertical", ref={"main_window"}, name=COMBINATOR_NAME, children={
@@ -94,10 +72,10 @@ function gui_opened(comb, player)
{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=param.first_signal, style_mods={bottom_margin=1, right_margin=6}, actions={
{type="choose-elem-button", name="network", style="slot_button_in_shallow_frame", ref={"network"}, elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, signal=signal, style_mods={bottom_margin=1, right_margin=6}, actions={
on_elem_changed={"choose-elem-button", comb.unit_number}
}},
{type="checkbox", name="radio_button", ref={"radio_button"}, state=not allows_all_trains, tooltip={"cybersyn-gui.auto-tooltip"}, actions={
{type="checkbox", name="radio_button", ref={"radio_button"}, state=check, tooltip={"cybersyn-gui.auto-tooltip"}, actions={
on_checked_state_changed={"radio_button", comb.unit_number}
}},
{type="label", name="radio_label", style_mods={left_padding=3}, ref={"radio_label"}, caption={"cybersyn-gui.auto-description"}},
@@ -164,28 +142,28 @@ function register_gui_actions()
local bottom_flow = all_flow.bottom
local param
if element.selected_index == 1 then
param = set_combinator_operation(comb, OPERATION_PRIMARY_IO)
set_comb_operation(comb, OPERATION_PRIMARY_IO)
top_flow["switch"].visible = true
all_flow["network_label"].visible = true
bottom_flow["network"].visible = true
bottom_flow["radio_button"].visible = true
bottom_flow["radio_label"].visible = true
elseif element.selected_index == 2 then
param = set_combinator_operation(comb, OPERATION_SECONDARY_IO)
set_comb_operation(comb, OPERATION_SECONDARY_IO)
top_flow["switch"].visible = false
all_flow["network_label"].visible = false
bottom_flow["network"].visible = false
bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
elseif element.selected_index == 3 then
param = set_combinator_operation(comb, OPERATION_DEPOT)
set_comb_operation(comb, OPERATION_DEPOT)
top_flow["switch"].visible = false
all_flow["network_label"].visible = true
bottom_flow["network"].visible = true
bottom_flow["radio_button"].visible = false
bottom_flow["radio_label"].visible = false
elseif element.selected_index == 4 then
param = set_combinator_operation(comb, OPERATION_WAGON_MANIFEST)
set_comb_operation(comb, OPERATION_WAGON_MANIFEST)
top_flow["switch"].visible = false
all_flow["network_label"].visible = false
bottom_flow["network"].visible = false
@@ -195,7 +173,7 @@ function register_gui_actions()
return
end
on_combinator_updated(global, comb, param)
combinator_update(global, comb)
elseif msg[1] == "choose-elem-button" then
local element = event.element
if not element then return end
@@ -207,9 +185,9 @@ function register_gui_actions()
signal = nil
element.elem_value = nil
end
local param = set_comb_network_name(comb, signal)
set_comb_network_name(comb, signal)
on_combinator_updated(global, comb, param)
combinator_update(global, comb)
elseif msg[1] == "radio_button" then
local element = event.element
if not element then return end
@@ -217,9 +195,9 @@ function register_gui_actions()
if not comb or not comb.valid then return end
local allows_all_trains = not element.state
local param = set_comb_allows_all_trains(comb, allows_all_trains)
set_comb_allows_all_trains(comb, allows_all_trains)
on_combinator_updated(global, comb, param)
combinator_update(global, comb)
elseif msg[1] == "switch" then
local element = event.element
if not element then return end
@@ -227,9 +205,9 @@ function register_gui_actions()
if not comb or not comb.valid then return end
local is_pr_state = (element.switch_state == "none" and 0) or (element.switch_state == "left" and 1) or 2
local param = set_comb_is_pr_state(comb, is_pr_state)
set_comb_is_pr_state(comb, is_pr_state)
on_combinator_updated(global, comb, param)
combinator_update(global, comb)
end
end
end)

View File

@@ -5,7 +5,19 @@ local floor = math.floor
local ceil = math.ceil
local string_find = string.find
local string_sub = string.sub
local table_compare = table.compare
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
local function iterr(a, i)
i = i + 1
@@ -447,10 +459,10 @@ function reset_station_layout(map_data, station, forbidden_entity)
if supports_fluid then
layout_pattern[wagon_number] = 3
else
layout_pattern[wagon_number] = 2
layout_pattern[wagon_number] = 1
end
elseif supports_fluid then
layout_pattern[wagon_number] = 1
layout_pattern[wagon_number] = 2
else
--layout_pattern[wagon_number] = nil
end

View File

@@ -152,10 +152,8 @@ local function on_station_built(map_data, stop, comb1, comb2)
priority = 0,
r_threshold = 0,
locked_slots = 0,
--network_name = param.first_signal and param.first_signal.name or nil,
network_flag = 0,
deliveries = {},
--allows_all_trains = param.second_constant == 1,
accepted_layouts = {},
layout_pattern = nil,
p_count_or_r_threshold_per_item = {},
@@ -270,25 +268,25 @@ local function on_combinator_built(map_data, comb)
wire = defines.wire_type.red,
})
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local param = control.parameters
local op = param.operation
local control = get_comb_control(comb)
local params = control.parameters
local op = params.operation
if op == OPERATION_DEFAULT then
op = OPERATION_PRIMARY_IO
param.operation = op
param.first_signal = NETWORK_SIGNAL_DEFAULT
control.parameters = param
elseif op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_FAILED_REQUEST then
params.operation = op
params.first_signal = NETWORK_SIGNAL_DEFAULT
control.parameters = params
elseif op ~= OPERATION_PRIMARY_IO and op ~= OPERATION_SECONDARY_IO and op ~= OPERATION_DEPOT and op ~= OPERATION_WAGON_MANIFEST then
op = OPERATION_PRIMARY_IO
param.operation = op
control.parameters = param
params.operation = op
control.parameters = params
end
map_data.to_comb[comb.unit_number] = comb
map_data.to_comb_params[comb.unit_number] = params
map_data.to_output[comb.unit_number] = out
map_data.to_stop[comb.unit_number] = stop
map_data.to_comb_params[comb.unit_number] = param
if op == OPERATION_WAGON_MANIFEST then
if rail then
@@ -360,7 +358,7 @@ function on_combinator_network_updated(map_data, comb, network_name)
end
---@param map_data MapData
---@param comb LuaEntity
local function on_combinator_broken(map_data, comb)
function on_combinator_broken(map_data, comb)
--NOTE: we do not check for wagon manifest combinators and update their stations, it is assumed they will be lazy deleted later
---@type uint
local comb_id = comb.unit_number
@@ -411,13 +409,17 @@ end
---@param map_data MapData
---@param comb LuaEntity
---@param new_params ArithmeticCombinatorParameters
function on_combinator_updated(map_data, comb, new_params)
local old_params = map_data.to_comb_params[comb.unit_number]
if new_params.operation ~= old_params.operation then
if (new_params.operation == OPERATION_PRIMARY_IO_ACTIVE or new_params.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST or new_params.operation == OPERATION_PRIMARY_IO) and (old_params.operation == OPERATION_PRIMARY_IO_ACTIVE or old_params.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST or old_params.operation == OPERATION_PRIMARY_IO) then
set_combinator_operation(comb, old_params.operation)
new_params.operation = old_params.operation
function combinator_update(map_data, comb)
---@type uint
local unit_number = comb.unit_number
local control = get_comb_control(comb)
local params = control.parameters
local old_params = map_data.to_comb_params[unit_number]
if params.operation ~= old_params.operation then
if (old_params.operation == OPERATION_PRIMARY_IO) and (params.operation == OPERATION_PRIMARY_IO_ACTIVE or params.operation == OPERATION_PRIMARY_IO_FAILED_REQUEST) then
--make sure only OPERATION_PRIMARY_IO gets stored on map_data.to_comb_params
params.operation = OPERATION_PRIMARY_IO
else
--NOTE: This is rather dangerous, we may need to actually implement operation changing
on_combinator_broken(map_data, comb)
@@ -425,19 +427,20 @@ function on_combinator_updated(map_data, comb, new_params)
return
end
end
local new_signal = new_params.first_signal
local new_signal = params.first_signal
local old_signal = old_params.first_signal
local new_network = new_signal and new_signal.name or nil
local old_network = old_signal and old_signal.name or nil
if new_network ~= old_network then
on_combinator_network_updated(map_data, comb, new_network)
map_data.to_comb_params[unit_number] = params
end
if new_params.second_constant ~= old_params.second_constant then
if params.second_constant ~= old_params.second_constant then
local stop = global.to_stop[comb.unit_number]
if stop then
local station = global.stations[stop.unit_number]
if station then
local bits = new_params.second_constant
local bits = params.second_constant
local is_pr_state = floor(bits/2)%3
station.is_p = is_pr_state == 0 or is_pr_state == 1
station.is_r = is_pr_state == 0 or is_pr_state == 2
@@ -448,8 +451,8 @@ function on_combinator_updated(map_data, comb, new_params)
end
end
end
map_data.to_comb_params[unit_number] = params
end
map_data.to_comb_params[comb.unit_number] = new_params
end
---@param map_data MapData
@@ -594,7 +597,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
set_depot_schedule(train_entity, train.depot_name)
else
--train still has cargo
lock_train(train.entity)
lock_train(train_entity)
remove_train(map_data, train, train_id)
send_nonempty_train_in_depot_alert(train_entity)
end
@@ -616,7 +619,7 @@ local function on_train_arrives_depot(map_data, depot_id, train_entity)
set_depot_schedule(train_entity, train.depot_name)
else
lock_train(train.entity)
lock_train(train_entity)
send_nonempty_train_in_depot_alert(train_entity)
end
end
@@ -825,35 +828,10 @@ local function on_paste(event)
if not entity or not entity.valid then return end
if entity.name == COMBINATOR_NAME then
on_combinator_updated(global, entity, get_comb_params(entity))
combinator_update(global, entity)
end
end
local function on_cursor_stack_changed(event)
local i = event.player_index
local player = game.get_player(i)
if not player then return end
local cursor = player.cursor_stack
if global.is_player_cursor_blueprint[i] then
--TODO: check if we can limit this search somehow?
for id, comb in pairs(global.to_comb) do
on_combinator_updated(global, comb, get_comb_params(comb))
end
end
local contains_comb = nil
if cursor and cursor.valid_for_read and cursor.type == "blueprint" then
local cost_to_build = cursor.cost_to_build
for k, v in pairs(cost_to_build) do
if k == COMBINATOR_NAME then
contains_comb = true
break
end
end
end
global.is_player_cursor_blueprint[i] = contains_comb
end
local function on_settings_changed(event)
mod_settings.tps = settings.global["cybersyn-ticks-per-second"].value --[[@as int]]
@@ -907,8 +885,7 @@ local function main()
flib_event.register({defines.events.on_pre_surface_deleted, defines.events.on_pre_surface_cleared}, on_surface_removed)
--flib_event.register(defines.events.on_entity_settings_pasted, on_paste)
--flib_event.register(defines.events.on_player_cursor_stack_changed, on_cursor_stack_changed)
flib_event.register(defines.events.on_entity_settings_pasted, on_paste)
local nth_tick = math.ceil(60/mod_settings.tps);
flib_event.on_nth_tick(nth_tick, function()
@@ -939,7 +916,6 @@ local function main()
---@type MapData
local map_data = global
local old_id = event.old_train_id_1
local old_surface_index = event.old_surface_index
--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

View File

@@ -2,20 +2,6 @@ local flib_migration = require("__flib__.migration")
local migrations_table = {
["0.2.0"] = function()
---@type MapData
local map_data = global
map_data.tick_state = STATE_INIT
map_data.all_station_ids = {}
for id, station in pairs(map_data.stations) do
station.p_count_or_r_threshold_per_item = {}
station.p_threshold = nil
station.is_all = nil
set_station_from_comb_state(station)
set_combinator_operation(station.entity_comb1, OPERATION_PRIMARY_IO)
map_data.all_station_ids[#map_data.all_station_ids + 1] = id
end
end,
["0.2.1"] = function()
---@type MapData
local map_data = global
@@ -106,6 +92,28 @@ local migrations_table = {
end
map_data.layouts[id] = new_layout
end
end,
["0.5.1"] = function()
---@type MapData
local map_data = global
map_data.tick_state = STATE_INIT
map_data.is_player_cursor_blueprint = nil
for id, layout in pairs(map_data.layouts) do
local new_layout = {}
local max_i = 0
for i, v in pairs(layout) do
new_layout[i] = v
if i > max_i then
max_i = i
end
end
for i = 1, max_i do
if new_layout[i] == nil then
new_layout[i] = 0
end
end
map_data.layouts[id] = new_layout
end
for id, station in pairs(map_data.stations) do
reset_station_layout(map_data, station)
end