fixed copy-paste and added alert sounds

This commit is contained in:
Monica Moniot
2022-11-15 18:28:46 -05:00
parent 4198adedec
commit 43b210efbe
11 changed files with 187 additions and 99 deletions

View File

@@ -19,3 +19,9 @@ Version: 0.3.0
Date: 2022-11-13
Features:
- Added warmup period on just built stations
---------------------------------------------------------------------------------------------------
Version: 0.3.0
Date: 2022-11-13
Features:
- Fixed copy-paste
- Added alert sounds

View File

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

View File

@@ -39,6 +39,7 @@ cybersyn-locked-slots=Locked slots per cargo wagon
missing-trains=No trains available to make a delivery from __2__ to __1__
lost-train=A train has become lost
nonempty-train=A train has parked in a depot while still containing items; it cannot be dispatched until it is empty
unexpected-train=A train has returned to the depot before completing it's delivery
[cybersyn-gui]
combinator-title=Cybernetic combinator

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 = true

View File

@@ -11,6 +11,7 @@ LOCKED_SLOTS = "cybersyn-locked-slots"
COMBINATOR_NAME = "cybersyn-combinator"
COMBINATOR_OUT_NAME = "cybersyn-combinator-output"
COMBINATOR_CLOSE_SOUND = "entity-close/cybersyn-combinator"
ALERT_SOUND = "utility/console_message"
OPERATION_DEFAULT = "*"
OPERATION_PRIMARY_IO = "/"

View File

@@ -70,7 +70,9 @@ function create_manifest_schedule(depot_name, p_stop, r_stop, manifest)
}}
end
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
@@ -78,14 +80,14 @@ function get_comb_secondary_state(param)
end
---@param depot Depot
function set_depot_from_comb_state(depot)
local param = depot.entity_comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local param = get_comb_params(depot.entity_comb)
local signal = param.first_signal
depot.network_name = signal and signal.name or nil
end
---@param station Station
function set_station_from_comb_state(station)
--NOTE: this does nothing to update currently active deliveries
local param = station.entity_comb1.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local param = get_comb_params(station.entity_comb1)
local bits = param.second_constant or 0
local is_pr_state = floor(bits/2)%3
local signal = param.first_signal
@@ -94,19 +96,36 @@ function set_station_from_comb_state(station)
station.is_p = is_pr_state == 0 or is_pr_state == 1
station.is_r = is_pr_state == 0 or is_pr_state == 2
end
---@param control LuaArithmeticCombinatorControlBehavior
function set_comb_allows_all_trains(control, allows_all_trains)
---@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 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 control LuaArithmeticCombinatorControlBehavior
function set_comb_is_pr_state(control, is_pr_state)
---@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 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
---@param signal SignalID?
function set_comb_network_name(comb, signal)
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local param = control.parameters
param.first_signal = signal
control.parameters = param
return param
end
@@ -122,24 +141,25 @@ end
---@param comb LuaEntity
---@param op string
function set_combinator_operation(comb, op)
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
control.operation = op
a.parameters = control
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 a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local param = control.parameters
if is_failed then
if control.operation == OPERATION_PRIMARY_IO then
control.operation = OPERATION_PRIMARY_IO_REQUEST_FAILED
a.parameters = control
if param.operation == OPERATION_PRIMARY_IO then
param.operation = OPERATION_PRIMARY_IO_REQUEST_FAILED
control.parameters = param
end
elseif control.operation == OPERATION_PRIMARY_IO_REQUEST_FAILED then
control.operation = OPERATION_PRIMARY_IO
a.parameters = control
elseif param.operation == OPERATION_PRIMARY_IO_REQUEST_FAILED then
param.operation = OPERATION_PRIMARY_IO
control.parameters = param
end
end
@@ -193,9 +213,8 @@ function send_missing_train_alert_for_stops(r_stop, p_stop)
r_stop,
send_missing_train_alert_for_stop_icon,
{"cybersyn-messages.missing-trains", r_stop.backer_name, p_stop.backer_name},
true
)
end
true)
end
end
local send_lost_train_alert_icon = {name = LOST_TRAIN_NAME, type = "fluid"}
@@ -208,12 +227,26 @@ function send_lost_train_alert(train)
loco,
send_lost_train_alert_icon,
{"cybersyn-messages.lost-train"},
true
)
true)
player.play_sound({path = ALERT_SOUND})
end
end
end
---@param train LuaTrain
function send_unexpected_train_alert(train)
local loco = train.front_stock or train.back_stock
if loco then
for _, player in pairs(loco.force.players) do
player.add_custom_alert(
loco,
send_lost_train_alert_icon,
{"cybersyn-messages.unexpected-train"},
true)
end
end
end
local send_nonempty_train_in_depot_alert_icon = {name = NONEMPTY_TRAIN_NAME, type = "fluid"}
---@param train LuaTrain
function send_nonempty_train_in_depot_alert(train)
@@ -224,8 +257,8 @@ function send_nonempty_train_in_depot_alert(train)
loco,
send_nonempty_train_in_depot_alert_icon,
{"cybersyn-messages.nonempty-train"},
true
)
true)
player.play_sound({path = ALERT_SOUND})
end
end
end
end

View File

@@ -2,7 +2,9 @@
---@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}
---@field public to_stop {[uint]: LuaEntity}
---@field public stations {[uint]: Station}
@@ -90,6 +92,7 @@ function init_global()
all_names = {},
}
global.to_comb = {}
global.to_comb_params = {}
global.to_output = {}
global.to_stop = {}
global.stations = {}
@@ -101,4 +104,5 @@ function init_global()
global.layouts = {}
global.layout_train_count = {}
global.layout_top_id = 1
global.is_player_cursor_blueprint = {}
end

View File

@@ -30,12 +30,12 @@ STATUS_NAMES_DEFAULT = "entity-status.disabled"
---@param player LuaPlayer
function gui_opened(comb, player)
local rootgui = player.gui.screen
local control = comb.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local op = control.operation
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(control)
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
@@ -94,7 +94,7 @@ 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=control.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=param.first_signal, style_mods={bottom_margin=1, right_margin=6}, actions={
on_elem_changed={"choose-elem-button", comb.unit_number}
}},
{type="checkbox", name="radio_button", ref={"radio_button"}, state=not allows_all_trains, tooltip={"cybersyn-gui.auto-tooltip"}, actions={
@@ -162,29 +162,30 @@ function register_gui_actions()
local top_flow = element.parent
local all_flow = top_flow.parent
local bottom_flow = all_flow.bottom
local param
if element.selected_index == 1 then
set_combinator_operation(comb, OPERATION_PRIMARY_IO)
param = set_combinator_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
set_combinator_operation(comb, OPERATION_SECONDARY_IO)
param = set_combinator_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
set_combinator_operation(comb, OPERATION_DEPOT)
param = set_combinator_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
set_combinator_operation(comb, OPERATION_WAGON_MANIFEST)
param = set_combinator_operation(comb, OPERATION_WAGON_MANIFEST)
top_flow["switch"].visible = false
all_flow["network_label"].visible = false
bottom_flow["network"].visible = false
@@ -194,44 +195,31 @@ function register_gui_actions()
return
end
on_combinator_updated(global, comb)
on_combinator_updated(global, comb, param)
elseif msg[1] == "choose-elem-button" then
local element = event.element
if not element then return end
local comb = global.to_comb[msg[2]]
if not comb or not comb.valid then return end
local a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local control = a.parameters
local signal = element.elem_value
if signal and (signal.name == "signal-everything" or signal.name == "signal-anything" or signal.name == "signal-each") then
control.first_signal = nil
signal = nil
element.elem_value = nil
else
control.first_signal = signal
end
a.parameters = control
local param = set_comb_network_name(comb, signal)
on_combinator_network_updated(global, comb, signal and signal.name or nil)
on_combinator_updated(global, comb, param)
elseif msg[1] == "radio_button" then
local element = event.element
if not element then return end
local comb = global.to_comb[msg[2]]
if not comb or not comb.valid then return end
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local allows_all_trains = not element.state
set_comb_allows_all_trains(control, allows_all_trains)
local param = set_comb_allows_all_trains(comb, allows_all_trains)
local stop = global.to_stop[comb.unit_number]
if stop then
local station = global.stations[stop.unit_number]
if station then
set_station_train_class(global, station, allows_all_trains)
end
end
on_combinator_updated(global, comb, param)
elseif msg[1] == "switch" then
local element = event.element
if not element then return end
@@ -239,17 +227,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 a = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
set_comb_is_pr_state(a, is_pr_state)
local param = set_comb_is_pr_state(comb, is_pr_state)
local stop = global.to_stop[comb.unit_number]
if stop then
local station = global.stations[stop.unit_number]
if station then
station.is_p = is_pr_state == 0 or is_pr_state == 1
station.is_r = is_pr_state == 0 or is_pr_state == 2
end
end
on_combinator_updated(global, comb, param)
end
end
end)

View File

@@ -397,8 +397,8 @@ local function reset_station_layout(map_data, station, forbidden_entity)
supports_fluid = true
end
elseif entity.name == COMBINATOR_NAME then
local control = entity.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
if control.operation == OPERATION_WAGON_MANIFEST then
local param = map_data.to_comb_params[entity.unit_number]
if param.operation == OPERATION_WAGON_MANIFEST then
local pos = entity.position
local is_there
if is_ver then
@@ -445,18 +445,6 @@ local function reset_station_layout(map_data, station, forbidden_entity)
end
end
---@param map_data MapData
---@param station Station
---@param allows_all_trains boolean
function set_station_train_class(map_data, station, allows_all_trains)
if station.allows_all_trains ~= allows_all_trains then
station.allows_all_trains = allows_all_trains
if not allows_all_trains then
reset_station_layout(map_data, station, nil)
end
end
end
---@param map_data MapData
---@param station Station
---@param forbidden_entity LuaEntity?

View File

@@ -1,5 +1,6 @@
--By Mami
local flib_event = require("__flib__.event")
local floor = math.floor
---@param map_data MapData
@@ -186,8 +187,8 @@ local function search_for_station_combinator(map_data, stop, comb_operation, com
entity.valid and entity.name == COMBINATOR_NAME and
entity ~= comb_forbidden and map_data.to_stop[entity.unit_number] == stop
then
local control = entity.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
if control.operation == comb_operation then
local param = get_comb_params(entity)
if param.operation == comb_operation then
return entity
end
end
@@ -243,13 +244,15 @@ local function on_combinator_built(map_data, comb)
wire = defines.wire_type.red,
})
map_data.to_comb[comb.unit_number] = comb
map_data.to_output[comb.unit_number] = out
map_data.to_stop[comb.unit_number] = stop
local control = comb.get_or_create_control_behavior()--[[@as LuaArithmeticCombinatorControlBehavior]]
local param = control.parameters
local op = param.operation
map_data.to_comb[comb.unit_number] = comb
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_DEFAULT then
op = OPERATION_PRIMARY_IO
param.operation = op
@@ -334,8 +337,10 @@ end
---@param comb LuaEntity
local function on_combinator_broken(map_data, comb)
--NOTE: we do not check for wagon manifest combinators and update their stations, it is assumed they will be lazy deleted later
local out = map_data.to_output[comb.unit_number]
local stop = map_data.to_stop[comb.unit_number]
---@type uint
local comb_id = comb.unit_number
local out = map_data.to_output[comb_id]
local stop = map_data.to_stop[comb_id]
if stop and stop.valid then
local station = map_data.stations[stop.unit_number]
@@ -345,6 +350,7 @@ local function on_combinator_broken(map_data, comb)
if comb1 then
station.entity_comb1 = comb1
set_station_from_comb_state(station)
update_station_if_auto(map_data, station)
else
on_station_broken(map_data, stop.unit_number, station)
local depot_comb = search_for_station_combinator(map_data, stop, OPERATION_DEPOT, comb)
@@ -374,16 +380,47 @@ local function on_combinator_broken(map_data, comb)
if out and out.valid then
out.destroy()
end
map_data.to_comb[comb.unit_number] = nil
map_data.to_output[comb.unit_number] = nil
map_data.to_stop[comb.unit_number] = nil
map_data.to_comb[comb_id] = nil
map_data.to_output[comb_id] = nil
map_data.to_stop[comb_id] = nil
map_data.to_comb_params[comb_id] = nil
end
---@param map_data MapData
---@param comb LuaEntity
function on_combinator_updated(map_data, comb)
--NOTE: this is the lazy way to implement updates and puts strong restrictions on data validity on on_combinator_broken
on_combinator_broken(map_data, comb)
on_combinator_built(map_data, comb)
---@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
on_combinator_broken(map_data, comb)
on_combinator_built(map_data, comb)
else
local new_signal = new_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)
end
if new_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 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
local allow_all_trains = bits%2 == 1
if station.allow_all_trains ~= allow_all_trains then
station.allow_all_trains = allow_all_trains
update_station_if_auto(map_data, station)
end
end
end
end
map_data.to_comb_params[comb.unit_number] = new_params
end
end
---@param map_data MapData
@@ -403,8 +440,8 @@ local function on_stop_built(map_data, stop)
for _, entity in pairs(entities) do
if entity.valid and entity.name == COMBINATOR_NAME and map_data.to_stop[entity.unit_number] == nil then
map_data.to_stop[entity.unit_number] = stop
local control = entity.get_or_create_control_behavior().parameters--[[@as ArithmeticCombinatorParameters]]
local op = control.operation
local param = get_comb_params(entity)
local op = param.operation
if op == OPERATION_PRIMARY_IO or op == OPERATION_PRIMARY_IO_ACTIVE or op == OPERATION_PRIMARY_IO_REQUEST_FAILED then
comb1 = entity
elseif op == OPERATION_SECONDARY_IO then
@@ -510,7 +547,7 @@ local function on_train_arrives_depot(map_data, depot, train_entity)
else
if train.manifest then
on_failed_delivery(map_data, train)
send_lost_train_alert(train.entity)
send_unexpected_train_alert(train.entity)
end
train.status = STATUS_D
add_available_train(map_data, depot, train_id)
@@ -734,15 +771,43 @@ local function on_surface_removed(event)
end
end
local function on_paste(event)
local entity = event.destination
if not entity or not entity.valid then return end
if entity.name == COMBINATOR_NAME then
on_combinator_updated(global, entity)
on_combinator_updated(global, entity, get_comb_params(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
player.play_sound({path = ALERT_SOUND})
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]]
mod_settings.r_threshold = settings.global["cybersyn-request-threshold"].value--[[@as int]]
@@ -792,6 +857,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)
local nth_tick = math.ceil(60/mod_settings.tps);
flib_event.on_nth_tick(nth_tick, function()

View File

@@ -31,6 +31,15 @@ local migrations_table = {
map_data.all_station_ids = nil
mod_settings.warmup_time = settings.global["cybersyn-warmup-time"].value--[[@as int]]
end,
["0.4.0"] = function()
---@type MapData
local map_data = global
map_data.is_player_cursor_blueprint = {}
map_data.to_comb_params = {}
for id, comb in pairs(map_data.to_comb) do
map_data.to_comb_params[id] = get_comb_params(comb)
end
end,
}
---@param data ConfigurationChangedData