Merge branch 'experimental' of github.com:mamoniot/project-cybersyn into experimental

This commit is contained in:
mamoniot
2023-03-13 17:37:49 -04:00
23 changed files with 784 additions and 212 deletions

View File

@@ -85,14 +85,14 @@ constants.gui_content_frame_height = 744
constants.gui_inventory_table_height = 40 * 18
constants.gui_translations = {
delivering_to = { "gui.ltnm-delivering-to" },
fetching_from = { "gui.ltnm-fetching-from" },
loading_at = { "gui.ltnm-loading-at" },
not_available = { "gui.ltnm-not-available" },
parked_at_depot_with_residue = { "gui.ltnm-parked-at-depot-with-residue" },
parked_at_depot = { "gui.ltnm-parked-at-depot" },
returning_to_depot = { "gui.ltnm-returning-to-depot" },
unloading_at = { "gui.ltnm-unloading-at" },
delivering_to = { "cybersyn-gui.delivering-to" },
fetching_from = { "cybersyn-gui.fetching-from" },
loading_at = { "cybersyn-gui.loading-at" },
not_available = { "cybersyn-gui.not-available" },
parked_at_depot_with_residue = { "cybersyn-gui.parked-at-depot-with-residue" },
parked_at_depot = { "cybersyn-gui.parked-at-depot" },
returning_to_depot = { "cybersyn-gui.returning-to-depot" },
unloading_at = { "cybersyn-gui.unloading-at" },
}
constants.input_sanitizers = {
@@ -144,8 +144,8 @@ constants.ltn_event_names = {
if script then
constants.open_station_gui_tooltip = {
"",
{ "gui.ltnm-open-station-gui" },
remote.interfaces["ltn-combinator"] and { "", "\n", { "gui.ltnm-open-ltn-combinator-gui" } } or nil,
{ "cybersyn-gui.open-station-gui" },
remote.interfaces["ltn-combinator"] and { "", "\n", { "cybersyn-gui.open-ltn-combinator-gui" } } or nil,
}
end

View File

@@ -26,14 +26,14 @@ data:extend({
--{
-- type = "shortcut",
-- name = "ltnm-toggle-gui",
-- name = "cybersyn-toggle-gui",
-- icon = data_util.build_sprite(nil, { 0, 0 }, util.paths.shortcut_icons, 32, 2),
-- disabled_icon = data_util.build_sprite(nil, { 48, 0 }, util.paths.shortcut_icons, 32, 2),
-- small_icon = data_util.build_sprite(nil, { 0, 32 }, util.paths.shortcut_icons, 24, 2),
-- disabled_small_icon = data_util.build_sprite(nil, { 36, 32 }, util.paths.shortcut_icons, 24, 2),
-- toggleable = true,
-- action = "lua",
-- associated_control_input = "ltnm-toggle-gui",
-- associated_control_input = "cybersyn-toggle-gui",
-- technology_to_unlock = "logistic-train-network",
--},
})

View File

@@ -11,6 +11,7 @@
"? space-exploration >= 0.6.94",
"? miniloader",
"? nullius",
"? pypostprocessing"
"? pypostprocessing",
"! LtnManager"
]
}

View File

@@ -12,6 +12,9 @@ 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)
cybersyn-manager-enabled=Enable the Cybersyn GUI.
cybersyn-manager-update-rate=Manager refresh tick interval
cybersyn-manager-result-limit=Max entities displayed on GUI pages.
[mod-setting-description]
cybersyn-enable-planner=Enable or disable the central planning algorithm. If disabled no new trains will be dispatched.
@@ -27,6 +30,7 @@ cybersyn-warmup-time=How many seconds a cybernetic combinator will wait before c
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.
cybersyn-manager-result-limit=Caps the number of matching enitities (e.g. stations, trains) to limit the amount of update time consumed when the list is refreshed.\n-1 means return all results.
[item-name]
cybersyn-combinator=Cybernetic combinator

View File

@@ -1,5 +1,8 @@
[mod-name]
cybersyn=Project Cybersyn
[controls]
cybersyn-toggle-gui=Toggle LTN Manager
cybersyn-toggle-gui=Toggle Cybersyn Manager
[cybersyn-gui]
alert-delivery-failed=Delivery failed
@@ -33,6 +36,7 @@ inventory=Inventory
keep-open=Keep open
loading-at=Loading at
name=Name
network-name-label=Network Filter:
network-id-label=Network ID:
network-id=Network ID
no-alerts=[img=warning-white] No alerts
@@ -41,8 +45,7 @@ no-history=[img=warning-white] No history
no-stations=[img=warning-white] No stations
not-available=Not available
no-trains=[img=warning-white] No trains
open-ltn-combinator-gui=[font=default-semibold][color=128,206,240]Control:[/color][/font] Open LTN Combinator GUI
open-station-gui=Open station GUI\n[font=default-semibold][color=128,206,240]Shift:[/color][/font] Open station on map
open-station-gui=Open station GUI\n[font=default-semibold][color=128,206,240]Shift:[/color][/font] Open station on map\n[font=default-semibold][color=128,206,240]Control:[/color][/font] Open Station Cybernetic Combinator\n[font=default-semibold][color=128,206,240]Alt:[/color][/font] Open Station Control Cybernetic Combinator
open-train-gui=Open train GUI
parked-at-depot=Parked at depot
parked-at-depot-with-residue=Parked at depot with residue
@@ -54,13 +57,14 @@ requested=Requested
returning-to-depot=Returning to depot
route=Route
runtime=Runtime
search-label=Search:
search-label=Station Name:
search-item-label=Item Filter:
shipments-description=Green = Inbound\nBlue = Outbound
shipment=Shipment
shipments=Shipments
stations=Stations
status-description=[img=flib_indicator_green]1 = normal status\n[img=flib_indicator_blue]n = LTN Controlled Train parked at stop, n = number of trains\n[img=flib_indicator_yellow]n = Stop is part of a scheduled delivery, n = number of trains\n[img=flib_indicator_white]1 = Error - not initialized\n[img=flib_indicator_red]1 = Error - short circuit\n[img=flib_indicator_red]2 = Error - deactivated stop
status=Status
status=Network Signal
surface-label=Surface:
time=Time
train-id=Train ID
@@ -69,9 +73,11 @@ type=Type
unloading-at=Unloading at
[cybersyn-message]
error-ltn-combinator-not-found=Could not find an LTN Combinator for this station.
error-cybernetic-combinator-not-found=Could not find a cybernetic combinator for this station.
error-station-control-combinator-not-found=Could not find a station control cybernetic combinator for this station.
error-station-is-invalid=Station is invalid, please refresh the GUI.
error-train-is-invalid=Train is invalid, please refresh the GUI.
error-cross-surface-camera-invalid=Cannot move the camera to an entity on a different surface!
[cybersyn-mod-setting-description]
iterations-per-tick=Decrease this number if you're having performance issues.
@@ -81,4 +87,4 @@ history-length=History length
iterations-per-tick=Iterations per tick [img=info]
[shortcut-name]
cybersyn-toggle-gui=Toggle LTN Manager
cybersyn-toggle-gui=Toggle Cybersyn Manager

View File

@@ -364,7 +364,7 @@ data:extend({
-- custom inputs
--{
-- type = "custom-input",
-- name = "ltnm-toggle-gui",
-- name = "cybersyn-toggle-gui",
-- key_sequence = "CONTROL + T",
--},
--{
@@ -376,14 +376,14 @@ data:extend({
-- shortcuts
{
type = "shortcut",
name = "ltnm-toggle-gui",
name = "cybersyn-toggle-gui",
icon = data_util.build_sprite(nil, { 0, 0 }, util.paths.shortcut_icons, 32, 2),
disabled_icon = data_util.build_sprite(nil, { 48, 0 }, util.paths.shortcut_icons, 32, 2),
small_icon = data_util.build_sprite(nil, { 0, 32 }, util.paths.shortcut_icons, 24, 2),
disabled_small_icon = data_util.build_sprite(nil, { 36, 32 }, util.paths.shortcut_icons, 24, 2),
toggleable = true,
action = "lua",
--associated_control_input = "ltnm-toggle-gui",
--associated_control_input = "cybersyn-toggle-gui",
technology_to_unlock = "cybersyn-train-network",
},
})

View File

@@ -30,6 +30,8 @@ SETTING_DISABLE_DEPOT_BYPASS = 6
SETTING_ENABLE_SLOT_BARRING = 7
NETWORK_SIGNAL_DEFAULT = {name="signal-A", type="virtual"}
NETWORK_SIGNAL_GUI_DEFAULT = {name="signal-each", type="virtual"}
NETWORK_ANYTHING = "signal-anything"
NETWORK_EACH = "signal-each"
INACTIVITY_TIME = 100
LOCK_TRAIN_TIME = 60*60*60*24*7

View File

@@ -124,6 +124,8 @@
---@field public stuck_train_alert_enabled 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
---@field public enable_manager boolean
---@field public manager_update_rate int
--if this is uncommented it means there are migrations to write

View File

@@ -12,7 +12,7 @@ function alerts_tab.build(widths)
return {
tab = {
type = "tab",
caption = { "gui.ltnm-alerts" },
caption = { "cybersyn-gui.alerts" },
ref = { "alerts", "tab" },
actions = {
on_click = { gui = "main", action = "change_tab", tab = "alerts" },
@@ -36,7 +36,7 @@ function alerts_tab.build(widths)
type = "sprite-button",
style = "tool_button_red",
sprite = "utility/trash",
tooltip = { "gui.ltnm-delete-all-alerts" },
tooltip = { "cybersyn-gui.delete-all-alerts" },
ref = { "alerts", "delete_all_button" },
actions = {
on_click = { gui = "main", action = "delete_all_alerts" },
@@ -52,7 +52,7 @@ function alerts_tab.build(widths)
{
type = "label",
style = "ltnm_semibold_label",
caption = { "gui.ltnm-no-alerts" },
caption = { "cybersyn-gui.no-alerts" },
ref = { "alerts", "warning_label" },
},
},
@@ -121,7 +121,7 @@ function alerts_tab.update(self)
type = "label",
style = "ltnm_clickable_semibold_label",
style_mods = { width = widths.alerts.train_id, horizontal_align = "center" },
tooltip = { "gui.ltnm-open-train-gui" },
tooltip = { "cybersyn-gui.open-train-gui" },
},
{
type = "flow",
@@ -153,7 +153,7 @@ function alerts_tab.update(self)
type = "sprite-button",
style = "tool_button_red",
sprite = "utility/trash",
tooltip = { "gui.ltnm-delete-alert" },
tooltip = { "cybersyn-gui.delete-alert" },
},
})
end
@@ -185,8 +185,8 @@ function alerts_tab.update(self)
{ elem_mods = { caption = util.signed_int32(alerts_entry.train.network_id) } },
{
elem_mods = {
caption = { "gui.ltnm-alert-" .. string.gsub(alerts_entry.type, "_", "-") },
tooltip = { "gui.ltnm-alert-" .. string.gsub(alerts_entry.type, "_", "-") .. "-description" },
caption = { "cybersyn-gui.alert-" .. string.gsub(alerts_entry.type, "_", "-") },
tooltip = { "cybersyn-gui.alert-" .. string.gsub(alerts_entry.type, "_", "-") .. "-description" },
},
},
{},

View File

@@ -85,14 +85,14 @@ constants.gui_content_frame_height = 744
constants.gui_inventory_table_height = 40 * 18
constants.gui_translations = {
delivering_to = { "gui.ltnm-delivering-to" },
fetching_from = { "gui.ltnm-fetching-from" },
loading_at = { "gui.ltnm-loading-at" },
not_available = { "gui.ltnm-not-available" },
parked_at_depot_with_residue = { "gui.ltnm-parked-at-depot-with-residue" },
parked_at_depot = { "gui.ltnm-parked-at-depot" },
returning_to_depot = { "gui.ltnm-returning-to-depot" },
unloading_at = { "gui.ltnm-unloading-at" },
delivering_to = { "cybersyn-gui.delivering-to" },
fetching_from = { "cybersyn-gui.fetching-from" },
loading_at = { "cybersyn-gui.loading-at" },
not_available = { "cybersyn-gui.not-available" },
parked_at_depot_with_residue = { "cybersyn-gui.parked-at-depot-with-residue" },
parked_at_depot = { "cybersyn-gui.parked-at-depot" },
returning_to_depot = { "cybersyn-gui.returning-to-depot" },
unloading_at = { "cybersyn-gui.unloading-at" },
}
constants.input_sanitizers = {
@@ -144,8 +144,7 @@ constants.ltn_event_names = {
if script then
constants.open_station_gui_tooltip = {
"",
{ "gui.ltnm-open-station-gui" },
remote.interfaces["ltn-combinator"] and { "", "\n", { "gui.ltnm-open-ltn-combinator-gui" } } or nil,
{ "cybersyn-gui.open-station-gui" },
}
end

View File

@@ -8,7 +8,7 @@ function depots_tab.build(widths)
return {
tab = {
type = "tab",
caption = { "gui.ltnm-depots" },
caption = { "cybersyn-gui.depots" },
ref = { "depots", "tab" },
actions = {
on_click = { gui = "main", action = "change_tab", tab = "depots" },
@@ -25,7 +25,7 @@ function depots_tab.build(widths)
style_mods = { right_padding = 4 },
templates.sort_checkbox(widths, "depots", "name", true, nil, true),
templates.sort_checkbox(widths, "depots", "network_id", false),
templates.sort_checkbox(widths, "depots", "status", false, { "gui.ltnm-status-description" }),
templates.sort_checkbox(widths, "depots", "status", false, { "cybersyn-gui.status-description" }),
templates.sort_checkbox(widths, "depots", "trains", false),
},
{ type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "depots", "scroll_pane" } },
@@ -37,7 +37,7 @@ function depots_tab.build(widths)
{
type = "label",
style = "ltnm_semibold_label",
caption = { "gui.ltnm-no-depots" },
caption = { "cybersyn-gui.no-depots" },
ref = { "depots", "warning_label" },
},
},

View File

@@ -12,7 +12,7 @@ function history_tab.build(widths)
return {
tab = {
type = "tab",
caption = { "gui.ltnm-history" },
caption = { "cybersyn-gui.history" },
ref = { "history", "tab" },
actions = {
on_click = { gui = "main", action = "change_tab", tab = "history" },
@@ -38,7 +38,7 @@ function history_tab.build(widths)
type = "sprite-button",
style = "tool_button_red",
sprite = "utility/trash",
tooltip = { "gui.ltnm-clear-history" },
tooltip = { "cybersyn-gui.clear-history" },
ref = { "history", "clear_button" },
actions = {
on_click = { gui = "main", action = "clear_history" },
@@ -54,7 +54,7 @@ function history_tab.build(widths)
{
type = "label",
style = "ltnm_semibold_label",
caption = { "gui.ltnm-no-history" },
caption = { "cybersyn-gui.no-history" },
ref = { "history", "warning_label" },
},
},

View File

@@ -1,20 +1,22 @@
local misc = require("__flib__.misc")
local gui = require("__flib__.gui-lite")
local templates = require("templates")
local util = require("scripts.gui.util")
local templates = require("scripts.gui.templates")
local format = require("__flib__.format")
local inventory_tab = {}
function inventory_tab.build()
function inventory_tab.create()
return {
tab = {
name = "manager_inventory_tab",
type = "tab",
caption = { "gui.ltnm-inventory" },
caption = { "cybersyn-gui.inventory" },
ref = { "inventory", "tab" },
actions = {
on_click = { gui = "main", action = "change_tab", tab = "inventory" },
},
handler = inventory_tab.handle.on_inventory_tab_selected
},
content = {
name = "manager_inventory_content_frame",
type = "flow",
style_mods = { horizontal_spacing = 12 },
direction = "horizontal",
@@ -26,62 +28,245 @@ function inventory_tab.build()
}
end
local function update_table(self, name, color)
local translations = self.player_table.dictionaries.materials
---@param map_data MapData
---@param player_data PlayerData
function inventory_tab.build(map_data, player_data)
local state = self.state
local refs = self.refs.inventory
local refs = player_data.refs
local search_query = state.search_query
local search_network_id = state.network_id
local search_surface = state.surface
local search_query = player_data.search_query
local search_item = player_data.search_item
local search_network_name = player_data.search_network_name
local search_network_mask = player_data.search_network_mask
local search_surface_idx = player_data.search_surface_idx
local inventory_provided = {}
local inventory_in_transit = {}
local inventory_requested = {}
local ltn_inventory = state.ltn_data.inventory[name][search_surface]
local stations_sorted = {}
local i = 0
local table = refs[name].table
local children = table.children
for id, station in pairs(map_data.stations) do
local entity = station.entity_stop
if not entity.valid then
goto continue
end
for name, count_by_network_id in pairs(ltn_inventory or {}) do
if
bit32.btest(count_by_network_id.combined_id, search_network_id)
and string.find(string.lower(translations[name]), string.lower(search_query))
then
local running_count = 0
for network_id, count in pairs(count_by_network_id) do
if network_id ~= "combined_id" and bit32.btest(network_id, search_network_id) then
running_count = running_count + count
if search_query then
if not string.match(entity.backer_name, search_query) then
goto continue
end
end
-- move surface comparison up higher in query to short circuit query earlier if surface doesn't match
if search_surface_idx then
if search_surface_idx == -1 then
goto has_match
elseif entity.surface.index ~= search_surface_idx then
goto continue
end
::has_match::
end
if search_network_name then
if search_network_name == (NETWORK_EACH or NETWORK_ANYTHING) then
goto has_match
end
if search_network_name ~= station.network_name then
goto continue
end
::has_match::
local train_flag = get_network_flag(station, station.network_name)
if not bit32.btest(search_network_mask, train_flag) then
goto continue
end
elseif search_network_mask ~= -1 then
if station.network_name == NETWORK_EACH then
local masks = station.network_flag--[[@as {}]]
for _, network_flag in pairs(masks) do
if bit32.btest(search_network_mask, network_flag) then
goto has_match
end
end
goto continue
::has_match::
elseif not bit32.btest(search_network_mask, station.network_flag) then
goto continue
end
end
if search_item then
if station.deliveries then
for item_name, _ in pairs(station.deliveries) do
if item_name == search_item then
goto has_match
end
end
end
local comb1_signals, _ = get_signals(station)
if comb1_signals then
for _, signal_ID in pairs(comb1_signals) do
local item = signal_ID.signal.name
if item then
if item == search_item then
goto has_match
end
end
end
end
goto continue
::has_match::
end
stations_sorted[#stations_sorted + 1] = id
::continue::
end
for i, station_id in pairs(stations_sorted) do
--- @class Station
local station = map_data.stations[station_id]
local comb1_signals, _ = get_signals(station)
if comb1_signals then
for _, v in pairs(comb1_signals) do
local item = v.signal
local count = v.count
if item.type ~= "virtual" then
if count > 0 then
if inventory_provided[item.name] == nil then
inventory_provided[item.name] = count
else
inventory_provided[item.name] = inventory_provided[item.name] + count
end
else
if inventory_requested[item.name] == nil then
inventory_requested[item.name] = count
else
inventory_requested[item.name] = inventory_requested[item.name] + count
end
end
end
end
end
if running_count > 0 then
i = i + 1
local button = children[i]
if not button then
button = table.add({ type = "sprite-button", style = "flib_slot_button_" .. color, enabled = false })
local deliveries = station.deliveries
if deliveries then
for item, count in pairs(deliveries) do
if count > 0 then
if inventory_in_transit[item] == nil then
inventory_in_transit[item] = 0
inventory_in_transit[item] = inventory_in_transit[item] + count
else
inventory_in_transit[item] = inventory_in_transit[item] + count
end
end
button.sprite = string.gsub(name, ",", "/")
button.number = running_count
button.tooltip = "[img="
.. string.gsub(name, ",", "/")
.. "] [font=default-semibold]"
.. translations[name]
.. "[/font]\n"
.. misc.delineate_number(running_count)
end
end
end
for j = i + 1, #children do
children[j].destroy()
local inventory_provided_table = refs.inventory_provided_table
local provided_children = {}
local i = 0
for item, count in pairs(inventory_provided) do
i = i + 1
local sprite, img_path, item_string = util.generate_item_references(item)
if game.is_valid_sprite_path(sprite) then
provided_children[#provided_children+1] = {
type = "sprite-button",
style = "flib_slot_button_green",
enabled = false,
sprite = sprite,
number = count,
tooltip = { "",
img_path,
" [font=default-semibold]",
{ item_string },
"[/font]\n"..format.number(count),
},
}
end
end
local inventory_requested_table = refs.inventory_requested_table
local requested_children = {}
local i = 0
for item, count in pairs(inventory_requested) do
i = i + 1
local sprite, img_path, item_string = util.generate_item_references(item)
if game.is_valid_sprite_path(sprite) then
requested_children[#requested_children+1] = {
type = "sprite-button",
style = "flib_slot_button_red",
enabled = false,
sprite = sprite,
number = count,
tooltip = { "",
img_path,
" [font=default-semibold]",
{ item_string },
"[/font]\n"..format.number(count),
},
}
end
end
local inventory_in_transit_table = refs.inventory_in_transit_table
local in_transit_children = {}
local i = 0
for item, count in pairs(inventory_in_transit) do
i = i + 1
local sprite, img_path, item_string = util.generate_item_references(item)
if game.is_valid_sprite_path(sprite) then
in_transit_children[#in_transit_children+1] = {
type = "sprite-button",
style = "flib_slot_button_blue",
enabled = false,
sprite = sprite,
number = count,
tooltip = { "",
img_path,
" [font=default-semibold]",
{ item_string },
"[/font]\n"..format.number(count),
},
}
end
end
if next(inventory_provided_table.children) ~= nil then
refs.inventory_provided_table.clear()
end
if next(inventory_requested_table.children) ~= nil then
refs.inventory_requested_table.clear()
end
if next(inventory_in_transit_table.children) ~= nil then
refs.inventory_in_transit_table.clear()
end
gui.add(refs.inventory_provided_table, provided_children)
gui.add(refs.inventory_requested_table, requested_children)
gui.add(refs.inventory_in_transit_table, in_transit_children)
end
function inventory_tab.update(self)
update_table(self, "provided", "green")
update_table(self, "in_transit", "blue")
update_table(self, "requested", "red")
inventory_tab.handle = {}
--- @param e {player_index: uint}
function inventory_tab.wrapper(e, handler)
local player = game.get_player(e.player_index)
if not player then return end
local player_data = global.manager.players[e.player_index]
handler(player, player_data, player_data.refs, e)
end
---@param player LuaPlayer
---@param player_data PlayerData
function inventory_tab.handle.on_inventory_tab_selected(player, player_data)
player_data.selected_tab = "inventory_tab"
end
gui.add_handlers(inventory_tab.handle, inventory_tab.wrapper)
return inventory_tab

View File

@@ -4,7 +4,7 @@ local mod_gui = require("__core__.lualib.mod-gui")
local manager = require("scripts.gui.manager")
--- @class Manager
--- @field players table<int, PlayerData>
--- @field players table<uint, PlayerData>
--- @field item_order table<string, int>
--- @class PlayerData
@@ -18,6 +18,7 @@ local manager = require("scripts.gui.manager")
--- @field trains_orderings uint[]
--- @field trains_orderings_invert boolean[]
--- @field pinning boolean
--- @field selected_tab string?
@@ -46,7 +47,7 @@ end
local manager_gui = {}
function manager_gui.on_lua_shortcut(e)
if e.prototype_name == "ltnm-toggle-gui" then
if e.prototype_name == "cybersyn-toggle-gui" then
manager.wrapper(e, manager.handle.manager_toggle)
end
end
@@ -65,7 +66,7 @@ function manager_gui.on_player_created(e)
}
global.manager.players[e.player_index] = player_data
manager.update(global, player, player_data)
--manager.update(global, player, player_data)
--top_left_button_update(player, player_data)
end
@@ -91,6 +92,21 @@ function manager_gui.on_runtime_mod_setting_changed(e)
end
end
commands.add_command("cybersyn_rebuild_manager_windows", nil, function(command)
local manager_data = global.manager
if manager_data then
---@param v PlayerData
for i, v in pairs(manager_data.players) do
local player = game.get_player(i)
if player ~= nil then
v.refs.manager_window.destroy()
v.refs = manager.create(player)
end
end
end
end)
--- @param manager Manager
local function init_items(manager)
@@ -135,4 +151,17 @@ function manager_gui.on_init()
end
--gui.handle_events()
---@param global cybersyn.global
function manager_gui.tick(global)
local manager_data = global.manager
if manager_data then
for i, v in pairs(manager_data.players) do
if v.is_manager_open then
local query_limit = settings.get_player_settings(i)["cybersyn-manager-result-limit"].value
manager.update(global, v, query_limit)
end
end
end
end
return manager_gui

View File

@@ -8,9 +8,10 @@ local templates = require("scripts.gui.templates")
local stations_tab = require("scripts.gui.stations")
--local trains_tab = require("scripts.gui.trains")
--local depots_tab = require("scripts.gui.depots")
--local inventory_tab = require("scripts.gui.inventory")
local inventory_tab = require("scripts.gui.inventory")
--local history_tab = require("scripts.gui.history")
--local alerts_tab = require("scripts.gui.alerts")
local util = require("scripts.gui.util")
local manager = {}
@@ -36,19 +37,19 @@ function manager.create(player)
style = "flib_titlebar_flow",
handler = manager.handle.manager_titlebar_click,
children = {
{ type = "label", style = "frame_title", caption = { "mod-name.LtnManager" }, ignored_by_interaction = true },
{ type = "label", style = "frame_title", caption = { "mod-name.cybersyn" }, ignored_by_interaction = true },
{ type = "empty-widget", style = "flib_titlebar_drag_handle", ignored_by_interaction = true },
{
name = "manager_dispatcher_status_label",
type = "label",
style = "bold_label",
style_mods = { font_color = constants.colors.red.tbl, left_margin = -4, top_margin = 1 },
caption = { "gui.ltnm-dispatcher-disabled" },
tooltip = { "gui.ltnm-dispatcher-disabled-description" },
caption = { "cybersyn-gui.dispatcher-disabled" },
tooltip = { "cybersyn-gui.dispatcher-disabled-description" },
visible = not settings.global["cybersyn-enable-planner"].value,
},
templates.frame_action_button("manager_pin_button", "ltnm_pin", { "gui.ltnm-keep-open" }, manager.handle.manager_pin),--on_gui_clicked
templates.frame_action_button("manager_refresh_button", "ltnm_refresh", { "gui.ltnm-refresh-tooltip" }, manager.handle.manager_refresh_click),--on_gui_clicked
templates.frame_action_button("manager_pin_button", "ltnm_pin", { "cybersyn-gui.keep-open" }, manager.handle.manager_pin),--on_gui_clicked
templates.frame_action_button("manager_refresh_button", "ltnm_refresh", { "cybersyn-gui.refresh-tooltip" }, manager.handle.manager_refresh_click),--on_gui_clicked
templates.frame_action_button(nil, "utility/close", { "gui.close-instruction" }, manager.handle.manager_close),--on_gui_clicked
},
},
@@ -61,15 +62,20 @@ function manager.create(player)
type = "frame",
style = "ltnm_main_toolbar_frame",
children = {
{ type = "label", style = "subheader_caption_label", caption = { "gui.ltnm-search-label" } },
{ type = "label", style = "subheader_caption_label", caption = { "cybersyn-gui.search-label" } },
{
name = "manager_text_search_field",
type = "textfield",
clear_and_focus_on_right_click = true,
handler = manager.handle.manager_update_text_search, --on_gui_text_changed
},
--item search box commented out. It *works*, but, the filtering logic only checks delivieres, so I'm not sure what Mami intended it for, so I'm leaving it off for now...
{ type = "label", style = "subheader_caption_label", caption = { "cybersyn-gui.search-item-label" } },
{ type= "choose-elem-button", name="manager_item_filter", style="slot_button_in_shallow_frame", elem_type="signal", handler=manager.handle.manager_update_item_search, },
{ type = "empty-widget", style = "flib_horizontal_pusher" },
{ type = "label", style = "caption_label", caption = { "gui.ltnm-network-id-label" } },
{ type = "label", style = "caption_label", caption = { "cybersyn-gui.network-name-label" } },
{ type= "choose-elem-button", name="network", style="slot_button_in_shallow_frame", elem_type="signal", tooltip={"cybersyn-gui.network-tooltip"}, handler=manager.handle.manager_update_network_name, },
{ type = "label", style = "caption_label", caption = { "cybersyn-gui.network-id-label" } },
{
name = "manager_network_mask_field",
type = "textfield",
@@ -80,7 +86,7 @@ function manager.create(player)
text = "-1",
handler = manager.handle.manager_update_network_mask, --on_gui_text_changed
},
{ type = "label", style = "caption_label", caption = { "gui.ltnm-surface-label" } },
{ type = "label", style = "caption_label", caption = { "cybersyn-gui.surface-label" } },
{
name = "manager_surface_dropdown",
type = "drop-down",
@@ -92,10 +98,9 @@ function manager.create(player)
name = "manager_tabbed_pane",
type = "tabbed-pane",
style = "ltnm_tabbed_pane",
stations_tab.create(widths),
inventory_tab.create(),
selected_tab_index = 1,
tabs = {
stations_tab.create(widths)
}
},
},
},
@@ -111,12 +116,53 @@ function manager.create(player)
return refs
end
function manager.build(player_data)
local refs = player_data.refs
-- Surface dropdown
--- @type LuaGuiElement
local surface_dropdown = refs.manager_surface_dropdown
local surfaces = game.surfaces
local selected_surface_id = player_data.search_surface_idx
local currently_selected_index = surface_dropdown.selected_index
local currently_selected_surface = nil
if currently_selected_index ~= (nil or 0) then
currently_selected_surface = surface_dropdown.get_item(currently_selected_index)
end
surface_dropdown.clear_items()
surface_dropdown.add_item("all", 1)
i = 1
for name, _ in pairs(surfaces) do
i = i + 1
surface_dropdown.add_item(name, i)
--reselect same surface
if name == currently_selected_surface then
refs.manager_surface_dropdown.selected_index = i
end
end
-- Validate that the selected index still exist
if selected_surface_id then
local selected_surface = game.get_surface(selected_surface_id)
-- If the surface was invalidated since last update, reset to all
if not selected_surface then
player_data.search_surface_idx = -1
end
else
player_data.search_surface_idx = -1
end
end
--- @param map_data MapData
--- @param player LuaPlayer
--- @param player_data PlayerData
function manager.update(map_data, player, player_data)
--local tab = trains_tab.build(map_data, player_data)
--gui.add(_, tab, player_data.refs)
function manager.update(map_data, player_data, query_limit)
if player_data.selected_tab ~= nil then
manager.build(player_data)
end
if player_data.selected_tab == "stations_tab" then
stations_tab.build(map_data, player_data, query_limit)
elseif player_data.selected_tab == "inventory_tab" then
inventory_tab.build(map_data, player_data)
end
end
@@ -157,7 +203,7 @@ function manager.handle.manager_open(player, player_data, refs)
end
player_data.is_manager_open = true
player.set_shortcut_toggled("ltnm-toggle-gui", true)
player.set_shortcut_toggled("cybersyn-toggle-gui", true)
end
@@ -165,23 +211,7 @@ end
--- @param player_data PlayerData
--- @param refs table<string, LuaGuiElement>
function manager.handle.manager_close(player, player_data, refs)
if player_data.pinning then
return
end
refs.manager_window.visible = false
player_data.visible = false
if player.opened == refs.manager_window then
player.opened = nil
end
player_data.is_manager_open = false
player.set_shortcut_toggled("ltnm-toggle-gui", false)
player_data.refs.manager_window.destroy()
player_data.refs = manager.create(player)
util.close_manager_window(player, player_data, refs)
end
--- @param player LuaPlayer
@@ -233,12 +263,27 @@ function manager.handle.manager_update_text_search(player, player_data, refs, e)
player_data.search_query = query
end
--- @param player LuaPlayer
--- @param player_data PlayerData
--- @param refs table<string, LuaGuiElement>
--- @param e GuiEventData
function manager.handle.manager_update_item_search(player, player_data, refs, e)
local element = e.element
local signal = element.elem_value
if signal then
player_data.search_item = signal.name
else
player_data.search_item = nil
end
end
--- @param player LuaPlayer
--- @param player_data PlayerData
--- @param refs table<string, LuaGuiElement>
function manager.handle.manager_update_network_name(player, player_data, refs)
local signal = refs.manager_network_name.elem_value
function manager.handle.manager_update_network_name(player, player_data, refs, e)
local element = e.element
local signal = element.elem_value
if signal then
player_data.search_network_name = signal.name
else
@@ -248,18 +293,30 @@ end
--- @param player LuaPlayer
--- @param player_data PlayerData
--- @param refs table<string, LuaGuiElement>
function manager.handle.manager_update_network_mask(player, player_data, refs)
player_data.search_network_mask = tonumber(refs.manager_network_mask_field.text) or -1
function manager.handle.manager_update_network_mask(player, player_data, refs, e)
player_data.search_network_mask = tonumber(e.text) or -1
end
--- @param player LuaPlayer
--- @param player_data PlayerData
--- @param refs table<string, LuaGuiElement>
function manager.handle.manager_update_surface(player, player_data, refs)
local i = refs.manager_surface_dropdown.selected_index
player_data.search_surface_idx = i--TODO: fix this
function manager.handle.manager_update_surface(player, player_data, refs, e)
--- @type LuaGuiElement
local element = e.element
local i = element.selected_index
local refs = player_data.refs
local surface_id = -1
--all surfaces should always be the first entry with an index of 1
if i > 1 then
local surface_name = refs.manager_surface_dropdown.get_item(i)
local surface = game.get_surface(surface_name)
surface_id = surface.index
end
player_data.search_surface_idx = surface_id
end
gui.add_handlers(manager.handle, manager.wrapper)
return manager

View File

@@ -9,14 +9,14 @@ local stations_tab = {}
function stations_tab.create(widths)
return {
tab = {
name = "manager_stations_tab",
type = "tab",
caption = { "gui.ltnm-stations" },
caption = { "cybersyn-gui.stations" },
ref = { "stations", "tab" },
actions = {
on_click = { gui = "main", action = "change_tab", tab = "stations" },
},
handler = stations_tab.handle.on_stations_tab_selected
},
content = {
name = "manager_stations_content_frame",
type = "frame",
style = "ltnm_main_content_frame",
direction = "vertical",
@@ -25,19 +25,19 @@ function stations_tab.create(widths)
type = "frame",
style = "ltnm_table_toolbar_frame",
templates.sort_checkbox(widths, "stations", "name", true),
templates.sort_checkbox(widths, "stations", "status", false, { "gui.ltnm-status-description" }),
templates.sort_checkbox(widths, "stations", "status", false), --repurposed status column, description no longer necessary
templates.sort_checkbox(widths, "stations", "network_id", false),
templates.sort_checkbox(
widths,
"stations",
"provided_requested",
false,
{ "gui.ltnm-provided-requested-description" }
{ "cybersyn-gui-provided-requested-description" }
),
templates.sort_checkbox(widths, "stations", "shipments", false, { "gui.ltnm-shipments-description" }),
templates.sort_checkbox(widths, "stations", "shipments", false, { "cybersyn-gui-shipments-description" }),
templates.sort_checkbox(widths, "stations", "control_signals", false),
},
{ type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "stations", "scroll_pane" } },
{ name = "manager_stations_tab_scroll_pane", type = "scroll-pane", style = "ltnm_table_scroll_pane", ref = { "stations", "scroll_pane" } },
{
type = "flow",
style = "ltnm_warning_flow",
@@ -46,7 +46,7 @@ function stations_tab.create(widths)
{
type = "label",
style = "ltnm_semibold_label",
caption = { "gui.ltnm-no-stations" },
caption = { "cybersyn-gui-no-stations" },
ref = { "stations", "warning_label" },
},
},
@@ -57,29 +57,52 @@ end
--- @param map_data MapData
--- @param player_data PlayerData
--- @return GuiElemDef
function stations_tab.build(map_data, player_data)
function stations_tab.build(map_data, player_data, query_limit)
local widths = constants.gui["en"]
local refs = player_data.refs
local search_query = player_data.search_query
local search_item = player_data.search_item
local search_network_name = player_data.search_network_name
local search_network_mask = player_data.search_network_mask
local search_surface_idx = player_data.search_surface_idx
local stations = map_data.stations
local stations_sorted = {}
local to_sorted_manifest = {}
for id, station in pairs(map_data.stations) do
local i = 0
for id, station in pairs(stations) do
local entity = station.entity_stop
if not entity.valid then
goto continue
end
if search_query then
if not string.match(entity.backer_name, search_query) then
goto continue
end
end
-- move surface comparison up higher in query to short circuit query earlier if surface doesn't match; this can exclude hundreds of stations instantly in SE
if search_surface_idx then
if search_surface_idx == -1 then
goto has_match
elseif entity.surface.index ~= search_surface_idx then
goto continue
end
::has_match::
end
if search_network_name then
if search_network_name ~= station.network_name then
goto continue
end
local train_flag = get_network_flag(station, search_network_name)
local train_flag = get_network_flag(station, station.network_name)
if not bit32.btest(search_network_mask, train_flag) then
goto continue
end
@@ -98,19 +121,24 @@ function stations_tab.build(map_data, player_data)
end
end
if search_surface_idx then
if entity.surface.index ~= search_surface_idx then
goto continue
end
end
if search_item then
if not station.deliveries then
goto continue
if station.deliveries then
for item_name, _ in pairs(station.deliveries) do
if item_name == search_item then
goto has_match
end
end
end
for item_name, _ in pairs(station.deliveries) do
if item_name == search_item then
goto has_match
local comb1_signals, _ = get_signals(station)
if comb1_signals then
for _, signal_ID in pairs(comb1_signals) do
local item = signal_ID.signal.name
if item then
if item == search_item then
goto has_match
end
end
end
end
goto continue
@@ -118,6 +146,10 @@ function stations_tab.build(map_data, player_data)
end
stations_sorted[#stations_sorted + 1] = id
i = i + 1
if query_limit ~= -1 and i >= query_limit then
break
end
::continue::
end
@@ -182,72 +214,127 @@ function stations_tab.build(map_data, player_data)
return (not player_data.trains_orderings_invert[#player_data.trains_orderings_invert]) == (a < b)
end)
local scroll_pane = refs.scroll_pane
local scroll_pane = refs.manager_stations_tab_scroll_pane
if next(scroll_pane.children) ~= nil then
refs.manager_stations_tab_scroll_pane.clear()
end
for i, station_id in pairs(stations_sorted) do
local station = map_data.stations[station_id]
--- @type Station
local station = stations[station_id]
local network_sprite = "utility/close_black"
local network_name = station.network_name
local network_flag = get_network_flag(station, network_name)
if network_name ~= nil then
network_sprite, _, _ = util.generate_item_references(network_name)
end
local color = i % 2 == 0 and "dark" or "light"
local row = gui.add(scroll_pane, {
gui.add(scroll_pane, {
type = "frame",
style = "ltnm_table_row_frame_" .. color,
{
type = "label",
style = "ltnm_clickable_semibold_label",
style_mods = { width = widths.name },
style_mods = { width = widths.stations.name },
tooltip = constants.open_station_gui_tooltip,
caption = station.entity_stop.backer_name,
handler = stations_tab.handle.open_station_gui,
tags = { station_id = station_id }
},
templates.status_indicator(widths.status, true),
{ type = "label", style_mods = { width = widths.network_id, horizontal_align = "center" } },
templates.small_slot_table(widths, color, "provided_requested"),
templates.small_slot_table(widths, color, "shipments"),
templates.small_slot_table(widths, color, "control_signals"),
})
--templates.status_indicator(widths.stations.status, true), --repurposing status column for network name
{ type = "sprite-button", style = "ltnm_small_slot_button_default", enabled = false, sprite = network_sprite, },
{ type = "label", style_mods = { width = widths.stations.network_id, horizontal_align = "center" }, caption = network_flag },
templates.small_slot_table(widths.stations, color, "provided_requested"),
templates.small_slot_table(widths.stations, color, "shipments"),
templates.small_slot_table(widths.stations, color, "control_signals"),
}, refs)
gui.add(row, {
{
elem_mods = { caption = station.entity_stop.name },
handler = stations_tab.hande.open_station_gui,
tags = station_id,
},
{ elem_mods = { caption = station.network_name } },
{ elem_mods = { caption = station.network_flag } },
})
gui.add(refs.provided_requested_table, util.slot_table_build_from_station(station))
gui.add(refs.shipments_table, util.slot_table_build_from_deliveries(station))
gui.add(refs.control_signals_table, util.slot_table_build_from_control_signals(station))
util.slot_table_update(row.provided_requested_frame.provided_requested_table, {
{ color = "green", entries = station.provided, translations = dictionaries.materials },
{ color = "red", entries = station.requested, translations = dictionaries.materials },
})
util.slot_table_update(row.shipments_frame.shipments_table, {
{ color = "green", entries = station.inbound, translations = dictionaries.materials },
{ color = "blue", entries = station.outbound, translations = dictionaries.materials },
})
util.slot_table_update(row.control_signals_frame.control_signals_table, {
{
color = "default",
entries = station.control_signals,
translations = dictionaries.virtual_signals,
type = "virtual-signal",
},
})
end
if #stations_sorted == 0 then
refs.warning_flow.visible = true
--refs.warning_flow.visible = true
scroll_pane.visible = false
refs.content_frame.style = "ltnm_main_warning_frame"
--refs.content_frame.style = "ltnm_main_warning_frame"
else
refs.warning_flow.visible = false
--refs.warning_flow.visible = false
scroll_pane.visible = true
refs.content_frame.style = "ltnm_main_content_frame"
--refs.content_frame.style = "ltnm_main_content_frame"
end
end
stations_tab.hande = {}
stations_tab.handle = {}
function stations_tab.hande.open_station_gui()
--- @param e {player_index: uint}
function stations_tab.wrapper(e, handler)
local player = game.get_player(e.player_index)
if not player then return end
local player_data = global.manager.players[e.player_index]
handler(player, player_data, player_data.refs, e)
end
--- @param e GuiEventData
--- @param player LuaPlayer
--- @param player_data PlayerData
function stations_tab.handle.open_station_gui(player, player_data, refs, e)
local station_id = e.element.tags.station_id
--- @type Station
local station = global.stations[station_id]
local station_entity = station.entity_stop
local station_comb1 = station.entity_comb1
local station_comb2 = station.entity_comb2
if not station_entity or not station_entity.valid then
util.error_flying_text(player, { "message.ltnm-error-station-is-invalid" })
return
end
if e.shift then
if station_entity.surface ~= player.surface then
util.error_flying_text(player, { "cybersyn-message.error-cross-surface-camera-invalid" })
else
player.zoom_to_world(station_entity.position, 1, station_entity)
rendering.draw_circle({
color = constants.colors.red.tbl,
target = station_entity.position,
surface = station_entity.surface,
radius = 0.5,
filled = false,
width = 5,
time_to_live = 60 * 3,
players = { player },
})
if not player_data.pinning then util.close_manager_window(player, player_data, refs) end
end
elseif e.control then
if station_comb1 ~= nil and station_comb1.valid then
player.opened = station_comb1
else
util.error_flying_text(player, { "cybersyn-message.error-cybernetic-combinator-not-found" })
end
elseif e.alt then
if station_comb2 ~= nil and station_comb2.valid then
player.opened = station_comb2
else
util.error_flying_text(player, { "cybersyn-message.error-station-control-combinator-not-found" })
end
else
player.opened = station_entity
end
end
---@param player LuaPlayer
---@param player_data PlayerData
function stations_tab.handle.on_stations_tab_selected(player, player_data)
player_data.selected_tab = "stations_tab"
end
gui.add_handlers(stations_tab.handle, stations_tab.wrapper)
return stations_tab

View File

@@ -30,7 +30,7 @@ function templates.inventory_slot_table(name, columns)
return {
type = "flow",
direction = "vertical",
{ type = "label", style = "bold_label", caption = { "gui.ltnm-" .. string.gsub(name, "_", "-") } },
{ type = "label", style = "bold_label", caption = { "cybersyn-gui." .. string.gsub(name, "_", "-") } },
{
type = "frame",
style = "deep_frame_in_shallow_frame",
@@ -43,7 +43,7 @@ function templates.inventory_slot_table(name, columns)
vertical_scroll_policy = "auto-and-reserve-space",
-- vertical_scroll_policy = "always",
ref = { "inventory", name, "scroll_pane" },
{ type = "table", style = "slot_table", column_count = columns, ref = { "inventory", name, "table" } },
{ type = "table", name = "inventory_" .. name .. "_table", style = "slot_table", column_count = columns, ref = { "inventory", name, "table" } },
},
},
}
@@ -77,7 +77,7 @@ function templates.sort_checkbox(widths, tab, column, selected, tooltip, state)
type = "checkbox",
style = selected and "ltnm_selected_sort_checkbox" or "ltnm_sort_checkbox",
style_mods = { width = widths and widths[tab][column] or nil, horizontally_stretchable = not widths },
caption = { "gui.ltnm-" .. string.gsub(column, "_", "-") },
caption = { "cybersyn-gui." .. string.gsub(column, "_", "-") },
tooltip = tooltip,
state = state,
ref = { tab, "toolbar", column .. "_checkbox" },

View File

@@ -12,7 +12,7 @@ local trains_tab = {}
--- @param map_data MapData
--- @param player_data PlayerData
--- @return GuiElemDef
function trains_tab.build(map_data, player_data)
function trains_tab.build(map_data, player_data, query_limit)
local widths = constants.gui["en"]
local search_item = player_data.search_item
@@ -22,6 +22,8 @@ function trains_tab.build(map_data, player_data)
local trains_sorted = {}
local i = 0
for id, train in pairs(map_data.trains) do
if search_network_name then
if search_network_name ~= train.network_name then
@@ -70,6 +72,10 @@ function trains_tab.build(map_data, player_data)
end
trains_sorted[#trains_sorted + 1] = id
i = i + 1
if query_limit ~= -1 and i >= query_limit then
break
end
::continue::
end
@@ -133,7 +139,7 @@ function trains_tab.build(map_data, player_data)
train_list[1] = {
type = "label",
style = "ltnm_semibold_label",
caption = { "gui.ltnm-no-trains" },
caption = { "cybersyn-gui.no-trains" },
}
else
for idx, train_id in ipairs(trains_sorted) do
@@ -156,7 +162,7 @@ function trains_tab.build(map_data, player_data)
{
type = "button",
style = "ltnm_train_minimap_button",
tooltip = { "gui.ltnm-open-train-gui" },
tooltip = { "cybersyn-gui.open-train-gui" },
elem_mods = { entity = get_any_train_entity(train.entity) },
handler = trains_tab.handle.open_train_gui, --on_click
tags = { train_id = train_id },
@@ -197,7 +203,7 @@ function trains_tab.build(map_data, player_data)
tab = {
name = "trains_tab",
type = "tab",
caption = #trains_sorted == 0 and { "gui.ltnm-trains" } or { "gui.ltnm-trains", #train_list },
caption = #trains_sorted == 0 and { "cybersyn-gui.trains" } or { "cybersyn-gui.trains", #train_list },
--badge_text = format.number(#ltn_data.sorted_trains.composition),
handler = trains_tab.handle.change_tab, --on_click
tags = { tab = "trains_tab" },
@@ -212,7 +218,7 @@ function trains_tab.build(map_data, player_data)
type = "frame",
style = "ltnm_table_toolbar_frame",
templates.sort_checkbox(widths, "trains", "status", false),
templates.sort_checkbox(widths, "trains", "layout", false, { "gui.ltnm-composition-description" }),
templates.sort_checkbox(widths, "trains", "layout", false, { "cybersyn-gui.composition-description" }),
templates.sort_checkbox(widths, "trains", "depot", false),
templates.sort_checkbox(widths, "trains", "shipment", false),
},

View File

@@ -33,11 +33,35 @@ function util.gui_list(parent, iterator, test, build, update, ...)
end
end
--- Builds a valid sprite path or returns nil
--- @param item string
--- @return string, string, string
function util.generate_item_references(item)
local sprite = nil
local image_path = ""
local item_name = ""
if game.is_valid_sprite_path("item/" .. item) then
sprite = "item/" .. item
image_path = "[img=item." .. item .. "]"
item_name = "item-name." .. item
elseif game.is_valid_sprite_path("fluid/" .. item) then
sprite = "fluid/" .. item
image_path = "[img=fluid." .. item .. "]"
item_name = "fluid-name." .. item
elseif game.is_valid_sprite_path("virtual-signal/" .. item) then
sprite = "virtual-signal/" .. item
image_path = "[img=virtual-signal." .. item .. "]"
item_name = "virtual-signal." .. item
end
return sprite, image_path, item_name
end
--- Updates a slot table based on the passed criteria.
--- @param manifest Manifest
--- @param color string
--- @return GuiElemDef[]
function util.slot_table_build(manifest, color)
function util.slot_table_build_from_manifest(manifest, color)
---@type GuiElemDef[]
local children = {}
for _, item in pairs(manifest) do
@@ -66,6 +90,125 @@ function util.slot_table_build(manifest, color)
return children
end
--- @param station Station
--- @param color string
--- @return GuiElemDef[]
function util.slot_table_build_from_station(station)
---@type GuiElemDef[]
local children = {}
local comb1_signals, comb2_signals = get_signals(station)
if comb1_signals then
for _, v in pairs(comb1_signals) do
local item = v.signal
if item.type == "virtual" then
goto continue
end
local count = v.count
local name = item.name
local sprite, img_path, item_string = util.generate_item_references(name)
if sprite ~= nil then
local color
if count > 0 then
color = "green"
else
color = "red"
end
if game.is_valid_sprite_path(sprite) then
children[#children + 1] = {
type = "sprite-button",
enabled = false,
style = "ltnm_small_slot_button_" .. color,
sprite = sprite,
tooltip = {
"",
img_path,
{ item_string },
"\n"..format.number(count),
},
number = count
}
end
end
::continue::
end
end
return children
end
function util.slot_table_build_from_deliveries(station)
---@type GuiElemDef[]
local children = {}
local deliveries = station.deliveries
for item, count in pairs(deliveries) do
local sprite, img_path, item_string = util.generate_item_references(item)
if sprite ~= nil then
local color
if count > 0 then
color = "green"
else
color = "blue"
end
if game.is_valid_sprite_path(sprite) then
children[#children + 1] = {
type = "sprite-button",
enabled = false,
style = "ltnm_small_slot_button_" .. color,
sprite = sprite,
tooltip = {
"",
img_path,
{ item_string },
"\n"..format.number(count),
},
number = count
}
end
end
end
return children
end
--- @param station Station
--- @return GuiElemDef[]
function util.slot_table_build_from_control_signals(station)
---@type GuiElemDef[]
local children = {}
local comb1_signals, comb2_signals = get_signals(station)
if comb1_signals then
for _, v in pairs(comb1_signals) do
local item = v.signal
local count = v.count
local name = item.name
local sprite = ""
local color = "default"
if item.type ~= "virtual" then
goto continue
else
sprite = "virtual-signal" .. "/" .. name
end
if game.is_valid_sprite_path(sprite) then
children[#children + 1] = {
type = "sprite-button",
enabled = false,
style = "ltnm_small_slot_button_" .. color,
sprite = sprite,
tooltip = {
"",
"[img=virtual-signal." .. name .. "]",
{ "virtual-signal-name." .. name },
"\n"..format.number(count),
},
number = count
}
end
::continue::
end
end
return children
end
function util.sorted_iterator(arr, src_tbl, sort_state)
local step = sort_state and 1 or -1
local i = sort_state and 1 or #arr
@@ -86,4 +229,21 @@ function util.signed_int32(val)
return (val >= MAX_INT and val - (2 * MAX_INT)) or val
end
function util.close_manager_window(player, player_data, refs)
if player_data.pinning then
return
end
refs.manager_window.visible = false
player_data.visible = false
if player.opened == refs.manager_window then
player.opened = nil
end
player_data.is_manager_open = false
player.set_shortcut_toggled("cybersyn-toggle-gui", false)
end
return util

View File

@@ -835,6 +835,8 @@ local function grab_all_settings()
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]]
mod_settings.manager_enabled = settings.startup["cybersyn-manager-enabled"].value--[[@as boolean]]
mod_settings.manager_update_rate = settings.startup["cybersyn-manager-update-rate"].value--[[@as int]]
end
local function on_settings_changed(event)
grab_all_settings()
@@ -913,7 +915,7 @@ local function main()
end
local MANAGER_ENABLED = true
local MANAGER_ENABLED = mod_settings.manager_enabled
script.on_init(function()
local setting = settings.global["cybersyn-invert-sign"]
@@ -943,6 +945,10 @@ local function main()
script.on_event(defines.events.on_player_removed, manager.on_player_removed)
script.on_event(defines.events.on_player_created, manager.on_player_created)
script.on_event(defines.events.on_lua_shortcut, manager.on_lua_shortcut)
-- TODO: rework this to work as a per-player runtime setting
script.on_nth_tick(mod_settings.manager_update_rate, function()
manager.tick(global)
end)
end
end

View File

@@ -243,6 +243,7 @@ function interface.update_stop_from_rail(rail, forbidden_entity, force_update)
update_stop_from_rail(global, rail, forbidden_entity, force_update)
end
------------------------------------------------------------------
--[[unsafe API]]
------------------------------------------------------------------

View File

@@ -102,6 +102,31 @@ data:extend({
setting_type = "runtime-global",
default_value = false,
},
{
type = "int-setting",
name = "cybersyn-manager-update-rate",
order = "ad",
setting_type = "startup",
default_value = 60,
minimum_value = 1,
maximum_value = 2147483647,
},
{
type = "bool-setting",
name = "cybersyn-manager-enabled",
order = "aa",
setting_type = "startup",
default_value = true,
},
{
type = "int-setting",
name = "cybersyn-manager-result-limit",
order = "aa",
setting_type = "runtime-per-user",
default_value = -1,
minimum_value = -1,
maximum_value = 2147483647,
}
--{
-- type = "bool-setting",
-- name = "cybersyn-disable-top-left-button",