291 lines
9.9 KiB
Lua

require "value_sensors.day_time"
require "value_sensors.evolution_factor"
require "value_sensors.kill_count"
require "value_sensors.play_time"
require "value_sensors.player_locations"
require "value_sensors.pollution_around_player"
require "value_sensors.remote_sensor"
require "settingsGUI"
require "remote"
if not evogui then evogui = {} end
function evogui.mod_init()
if not global.settings then global.settings = {} end
if not global.settings.update_delay then global.settings.update_delay = 60 end
for _, player in pairs(game.players) do
evogui.create_player_globals(player)
evogui.create_sensor_display(player)
end
end
local function mod_update_0_4_205()
-- 0.4.204 to 0.4.205: Factorio 0.15.22 introduced a bug wherein a
-- GUI element with more than 4 characters in its name, which was
-- shorter than the_mod_name + 4 characters, would get deleted on
-- load. At this time, the EvoGUI root element switched from
-- gui.top.evoGUI to gui.top.evogui_root.
--
-- We need to clean up the leftovers for people updating EvoGUI
-- from any other version of Factorio now.
for _, player in pairs(game.players) do
if player.gui.top.evoGUI then
player.gui.top.evoGUI.destroy()
end
end
end
function evogui.mod_update(data)
if data.mod_changes then
if data.mod_changes["EvoGUI"] then
-- TODO: If a more major migration ever needs doing, do that here.
-- Otherwise, just falling back to mod_init should work fine.
evogui.mod_init()
mod_update_0_4_205()
end
evogui.validate_sensors(data.mod_changes)
end
end
function evogui.on_gui_click(event)
if string.starts_with(event.element.name, "evogui_settings_gui_") then
evogui.on_settings_click(event)
elseif event.element.name == "evoGUI_toggle_popup" then
evogui.evoGUI_toggle_popup(event)
elseif string.starts_with(event.element.name, "evogui_sensor_") then
for _, sensor in pairs(evogui.value_sensors) do
-- if the gui element name matches 'evogui_sensor_' + sensor_name, send it the on_click event.
if string.starts_with(event.element.name, "evogui_sensor_" .. sensor.name) then
sensor:on_click(event)
break
end
end
end
end
-- Iterate through all value_sensors, if any are associated with a mod_name that
-- has been removed, remove the sensor from the list of value_sensors.
function evogui.validate_sensors(mod_changes)
for i = #evogui.value_sensors, 1, -1 do
local sensor = evogui.value_sensors[i]
if sensor.mod_name and mod_changes[sensor.mod_name] then
-- mod removed, remove sensor from ui
if mod_changes[sensor.mod_name].new_version == nil then
evogui.hide_sensor(sensor)
table.remove(evogui.value_sensors, i)
end
end
end
end
function evogui.hide_sensor(sensor)
for player_name, data in pairs(global.evogui) do
if data.always_visible then
data.always_visible[sensor["name"]] = false
end
end
for _, player in pairs(game.players) do
local player_settings = global.evogui[player.name]
local sensor_flow = player.gui.top.evogui_root.sensor_flow
evogui.update_av(player, sensor_flow.always_visible)
end
end
function evogui.new_player(event)
local player = game.players[event.player_index]
evogui.create_player_globals(player)
evogui.create_sensor_display(player)
end
function evogui.update_gui(event)
if (event.tick % global.settings.update_delay) ~= 0 then return end
for player_index, player in pairs(game.players) do
local player_settings = global.evogui[player.name]
-- saves converted from SP with no username to MP won't raise evogui.new_player
-- so we have to check here, as well.
if not player_settings then
evogui.new_player({player_index = player_index})
player_settings = global.evogui[player.name]
elseif not player.gui.top.evogui_root then
evogui.create_sensor_display(player)
end
local sensor_flow = player.gui.top.evogui_root.sensor_flow
evogui.update_av(player, sensor_flow.always_visible)
if player_settings.popup_open then
evogui.update_ip(player, sensor_flow.in_popup)
end
end
end
function evogui.create_player_globals(player)
if not global.evogui then global.evogui = {} end
if not global.evogui[player.name] then global.evogui[player.name] = {} end
local player_settings = global.evogui[player.name]
if not player_settings.version then player_settings.version = "" end
if not player_settings.always_visible then
player_settings.always_visible = {
["evolution_factor"] = true,
["play_time"] = true,
}
end
if not player_settings.in_popup then
player_settings.in_popup = {
["day_time"] = true,
}
end
if not player_settings.popup_open then player_settings.popup_open = false end
if not player_settings.sensor_settings then
player_settings.sensor_settings = {}
end
if not player_settings.sensor_settings['player_locations'] then
player_settings.sensor_settings['player_locations'] = {
['show_player_index'] = false,
['show_position'] = false,
['show_surface'] = false,
['show_direction'] = true,
['show_offline'] = false,
}
elseif player_settings.sensor_settings['player_locations'].show_offline == nil then
-- 0.4.3 new feature (783e3d68)
player_settings.sensor_settings['player_locations'].show_offline = false
end
if not player_settings.sensor_settings['day_time'] then
player_settings.sensor_settings['day_time'] = {
['show_day_number'] = false,
['minute_rounding'] = true,
}
end
if not player_settings.sensor_settings['evolution_factor'] then
player_settings.sensor_settings['evolution_factor'] = {
['extra_precision'] = false,
}
end
if not player_settings.sensor_settings['play_time'] then
player_settings.sensor_settings['play_time'] = {
['show_days'] = true,
['show_seconds'] = true,
}
end
end
function evogui.create_sensor_display(player)
local root = player.gui.top.evogui_root
local destroyed = false
if root then
player.gui.top.evogui_root.destroy()
destroyed = true
end
if not root or destroyed then
local root = player.gui.top.add{type="frame",
name="evogui_root",
direction="horizontal",
style="EvoGUI_outer_frame_no_border"}
local action_buttons = root.add{type="flow",
name="action_buttons",
direction="vertical",
style="EvoGUI_cramped_flow_v"}
action_buttons.add{type="button",
name="evoGUI_toggle_popup",
style="EvoGUI_expando_closed"}
if global.evogui[player.name].popup_open then
action_buttons.evoGUI_toggle_popup.style = "EvoGUI_expando_open"
end
action_buttons.add{type="button",
name="evogui_settings_gui_settings_open",
style="EvoGUI_settings"}
local sensor_flow = root.add{type="flow",
name="sensor_flow",
direction="vertical",
style="EvoGUI_cramped_flow_v"}
sensor_flow.add{type="flow",
name="always_visible",
direction="vertical",
style="EvoGUI_cramped_flow_v"}
sensor_flow.add{type="flow",
name="in_popup",
direction="vertical",
style="EvoGUI_cramped_flow_v"}
end
end
local function update_sensors(element, sensor_list, active_sensors)
for _, sensor in ipairs(sensor_list) do
if active_sensors[sensor.name] then
local status, err = pcall(sensor.create_ui, sensor, element)
if err then error({"err_specific", sensor.name, "create_ui", err}) end
status, err = pcall(sensor.update_ui, sensor, element)
if err then error({"err_specific", sensor.name, "update_ui", err}) end
else
local status, err = pcall(sensor.delete_ui, sensor, element)
if err then error({"err_specific", sensor.name, "delete_ui", err}) end
end
end
end
function evogui.update_av(player, element)
local always_visible = global.evogui[player.name].always_visible
update_sensors(element, evogui.value_sensors, always_visible)
end
function evogui.update_ip(player, element)
if not global.evogui[player.name].popup_open then return end
local in_popup = global.evogui[player.name].in_popup
update_sensors(element, evogui.value_sensors, in_popup)
end
function evogui.evoGUI_toggle_popup(event)
local player = game.players[event.player_index]
local player_settings = global.evogui[player.name]
local root = player.gui.top.evogui_root
if player_settings.popup_open then
-- close it
player_settings.popup_open = false
for _, childname in ipairs(root.sensor_flow.in_popup.children_names) do
root.sensor_flow.in_popup[childname].destroy()
end
root.action_buttons.evoGUI_toggle_popup.style = "EvoGUI_expando_closed"
else
-- open it
player_settings.popup_open = true
evogui.update_ip(player, root.sensor_flow.in_popup)
root.action_buttons.evoGUI_toggle_popup.style = "EvoGUI_expando_open"
end
end