328 lines
9.8 KiB
Lua
328 lines
9.8 KiB
Lua
-- initial settings, before loading them
|
|
local display_mode = "alerts-list-display-mode-icon-only"
|
|
local show_percentage = false
|
|
local columns_for_compact_mode = 4
|
|
|
|
-- constants
|
|
local ZOOM_LEVEL = 0.1
|
|
|
|
function format_guielement_name(prefix, surface, pos)
|
|
return prefix .. surface.index .. "_" .. pos.x .. "_" .. pos.y
|
|
end
|
|
|
|
function starts_with(str, start)
|
|
return str:sub(1, #start) == start
|
|
end
|
|
|
|
function signalid_to_spritepath(signalid)
|
|
local type = signalid.type
|
|
if type == "virtual" then
|
|
type = "virtual-signal"
|
|
end
|
|
return type .. "/" .. signalid.name
|
|
end
|
|
|
|
function refresh_speakers()
|
|
if global["speaker_cache"] then
|
|
for k, _ in pairs(global["speaker_cache"]) do
|
|
global["speaker_cache"][k] = nil
|
|
end
|
|
|
|
for k, v in pairs(game.surfaces) do
|
|
for sid, speaker in pairs(v.find_entities_filtered {type = "programmable-speaker"}) do
|
|
table.insert(global["speaker_cache"], speaker)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function remove_speaker(speaker)
|
|
if global["speaker_cache"] then
|
|
for k, v in pairs(global["speaker_cache"]) do
|
|
if v == speaker then
|
|
table.remove(global["speaker_cache"], k)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function compare_signals(s1, s2)
|
|
return s1 == s2 or (s1 and s2 and s1.type == s2.type and s1.name == s2.name)
|
|
end
|
|
|
|
function on_built(e)
|
|
if (e.created_entity.type == "programmable-speaker") then
|
|
if not global["speaker_cache"] then
|
|
global["speaker_cache"] = {}
|
|
end
|
|
|
|
table.insert(global["speaker_cache"], e.created_entity)
|
|
|
|
for k, player in pairs(game.players) do
|
|
draw_gui(player)
|
|
end
|
|
end
|
|
end
|
|
|
|
function on_destroyed(e)
|
|
if e.entity.type == "programmable-speaker" then
|
|
remove_speaker(e.entity)
|
|
for k, player in pairs(game.players) do
|
|
draw_gui(player)
|
|
end
|
|
end
|
|
end
|
|
|
|
function calculate_percentage(speaker, circuit)
|
|
local all_signals = speaker.get_merged_signals()
|
|
local left = 0
|
|
local right = circuit.condition["constant"]
|
|
if all_signals then
|
|
for k, v in pairs(all_signals) do
|
|
if compare_signals(v.signal, circuit.condition.first_signal) then
|
|
left = v.count
|
|
end
|
|
if compare_signals(v.signal, circuit.condition["second_signal"]) then
|
|
right = v.count
|
|
end
|
|
end
|
|
end
|
|
if right == 0 then
|
|
right = 1
|
|
end
|
|
percentage = left / right
|
|
return percentage
|
|
end
|
|
|
|
function get_signal_value(signals, signalid)
|
|
local value = 0
|
|
if signals then
|
|
for k, v in pairs(signals) do
|
|
if v.signal.type == signalid.type and v.signal.name == signalid.name then
|
|
value = v.count
|
|
break
|
|
end
|
|
end
|
|
end
|
|
return value
|
|
end
|
|
|
|
function left_column_for(tbl, speaker, circuit)
|
|
local elem_name = format_guielement_name("alerts_list_icons_", speaker.surface, speaker.position)
|
|
local element = tbl[elem_name]
|
|
if display_mode == "alerts-list-display-mode-icon-only" or display_mode == "alerts-list-display-mode-icon-and-text" then
|
|
if not element then
|
|
element =
|
|
tbl.add {
|
|
type = "sprite-button",
|
|
name = elem_name,
|
|
enabled = true,
|
|
mouse_button_filter = {"left"},
|
|
sprite = signalid_to_spritepath(speaker.alert_parameters.icon_signal_id),
|
|
show_percent_for_small_numbers = show_percentage
|
|
}
|
|
end
|
|
element.sprite = signalid_to_spritepath(speaker.alert_parameters.icon_signal_id)
|
|
if show_percentage then
|
|
element.number = calculate_percentage(speaker, circuit)
|
|
else
|
|
element.number = get_signal_value(speaker.get_merged_signals(), circuit.condition.first_signal)
|
|
end
|
|
element.tooltip = speaker.alert_parameters.alert_message
|
|
-- TODO: else for complex icon (full condition?)
|
|
end
|
|
-- update element data
|
|
end
|
|
|
|
function right_column_for(tbl, speaker, circuit)
|
|
if display_mode ~= "alerts-list-display-mode-icon-only" then
|
|
local elem_name = format_guielement_name("alerts_list_info_", speaker.surface, speaker.position)
|
|
local element = tbl[elem_name]
|
|
if not element then
|
|
element = tbl.add {type = "label", name = elem_name, caption = speaker.alert_parameters.alert_message}
|
|
end
|
|
element.caption = speaker.alert_parameters.alert_message
|
|
end
|
|
end
|
|
|
|
function on_click(element, player)
|
|
if element and player then
|
|
if starts_with(element.name, "alerts_list_icons_") then
|
|
for k, speaker in pairs(global["speaker_cache"]) do
|
|
if speaker then
|
|
if element.name == format_guielement_name("alerts_list_icons_", speaker.surface, speaker.position) then
|
|
player.open_map(speaker.position, ZOOM_LEVEL)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function fill_table_with_speakers(tbl, speakers, player)
|
|
if not speakers then
|
|
speakers = {}
|
|
end
|
|
|
|
local remove_list = {}
|
|
for k, v in pairs(tbl.children) do
|
|
remove_list[v.name] = v
|
|
end
|
|
|
|
local found_any = false
|
|
|
|
for i, speaker in pairs(speakers) do
|
|
-- here we do assume we always have a list of speakers that have global alert set
|
|
if speaker and speaker.valid and speaker.alert_parameters and speaker.alert_parameters.show_alert then
|
|
local behavior = speaker.get_control_behavior()
|
|
if behavior and behavior["circuit_condition"] then
|
|
if behavior.circuit_condition.fulfilled and speaker.alert_parameters.icon_signal_id then
|
|
found_any = true
|
|
left_column_for(tbl, speaker, behavior.circuit_condition)
|
|
right_column_for(tbl, speaker, behavior.circuit_condition)
|
|
remove_list[format_guielement_name("alerts_list_icons_", speaker.surface, speaker.position)] = nil
|
|
remove_list[format_guielement_name("alerts_list_info_", speaker.surface, speaker.position)] = nil
|
|
end
|
|
end
|
|
end
|
|
end
|
|
for k, v in pairs(remove_list) do
|
|
v.destroy()
|
|
end
|
|
|
|
if not found_any then
|
|
-- get rid of GUI if there's nothing to be shown
|
|
for k, player in pairs(game.players) do
|
|
if player.gui.left["alerts_list_frame_main"] then
|
|
player.gui.left["alerts_list_frame_main"].destroy()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- return GUI
|
|
function build_gui(player)
|
|
if not player.gui.left["alerts_list_frame_main"] then
|
|
-- TODO: make it transparent background?
|
|
local gui = player.gui.left.add {type = "frame", name = "alerts_list_frame_main", direction = "vertical"}
|
|
local columns = 2
|
|
if display_mode == "alerts-list-display-mode-icon-only" then
|
|
columns = columns_for_compact_mode
|
|
end
|
|
gui.add {
|
|
type = "label",
|
|
name = "alerts_list_label",
|
|
caption = {"gui-alerts-list.label-caption"},
|
|
tooltip = {"tooltip-alerts-list.label-caption"}
|
|
}
|
|
local tbl = gui.add {type = "table", name = "alerts_list_alert_table", column_count = columns}
|
|
return gui
|
|
else
|
|
return player.gui.left["alerts_list_frame_main"]
|
|
end
|
|
end
|
|
|
|
-- builds GUI and fills it with current speakers data
|
|
function draw_gui(player)
|
|
local gui = build_gui(player)
|
|
local tbl = gui.alerts_list_alert_table
|
|
fill_table_with_speakers(tbl, global["speaker_cache"], player)
|
|
end
|
|
|
|
function reload_settings(player)
|
|
display_mode = settings.get_player_settings(player)["alerts-list-display-mode"].value
|
|
show_percentage = settings.get_player_settings(player)["alerts-list-show-percentage"].value
|
|
columns_for_compact_mode = settings.get_player_settings(player)["alerts-list-columns-for-compact-mode"].value
|
|
|
|
if player.gui.left["alerts_list_frame_main"] then
|
|
player.gui.left["alerts_list_frame_main"].destroy()
|
|
end
|
|
|
|
draw_gui(player)
|
|
end
|
|
|
|
-- register events
|
|
|
|
script.on_init(
|
|
function()
|
|
for k, player in pairs(game.players) do
|
|
reload_settings(player)
|
|
end
|
|
|
|
if not global["speaker_cache"] then
|
|
global["speaker_cache"] = {}
|
|
end
|
|
refresh_speakers()
|
|
end
|
|
)
|
|
|
|
script.on_configuration_changed(
|
|
function()
|
|
for k, player in pairs(game.players) do
|
|
reload_settings(player)
|
|
end
|
|
|
|
if not global["speaker_cache"] then
|
|
global["speaker_cache"] = {}
|
|
end
|
|
refresh_speakers()
|
|
end
|
|
)
|
|
|
|
script.on_nth_tick(
|
|
settings.startup["alerts-list-refresh-rate"].value,
|
|
function(e)
|
|
for k, player in pairs(game.players) do
|
|
draw_gui(player)
|
|
end
|
|
end
|
|
)
|
|
|
|
script.on_event(
|
|
defines.events.on_player_joined_game,
|
|
function(e)
|
|
local player = game.players[e.player_index]
|
|
reload_settings(player)
|
|
|
|
if not global["speaker_cache"] then
|
|
global["speaker_cache"] = {}
|
|
end
|
|
refresh_speakers()
|
|
end
|
|
)
|
|
|
|
script.on_event(
|
|
defines.events.on_runtime_mod_setting_changed,
|
|
function(e)
|
|
if e.player_index ~= nil then
|
|
local player = game.players[e.player_index]
|
|
reload_settings(player)
|
|
end
|
|
end
|
|
)
|
|
|
|
script.on_event(
|
|
{defines.events.on_built_entity, defines.events.on_robot_built_entity},
|
|
function(e)
|
|
on_built(e)
|
|
end
|
|
)
|
|
|
|
script.on_event(
|
|
{defines.events.on_pre_player_mined_item, defines.events.on_robot_mined_entity, defines.events.on_entity_died},
|
|
function(e)
|
|
on_destroyed(e)
|
|
end
|
|
)
|
|
|
|
script.on_event(
|
|
{defines.events.on_gui_click},
|
|
function(e)
|
|
player = game.players[e.player_index]
|
|
if e.button == defines.mouse_button_type.left then
|
|
on_click(e.element, player)
|
|
end
|
|
end
|
|
)
|