diff --git a/control.lua b/control.lua index dc1f4be..14179e3 100644 --- a/control.lua +++ b/control.lua @@ -68,9 +68,14 @@ end) -------------------------------------------------------------------------------- -- oarc_new_spawn_created = script.generate_event_name() --- script.on_configuration_changed(function(data) --- -- Regenerate event ID: --- end) +script.on_configuration_changed(function(data) + -- Regenerate event ID: + + -- Reset the players GUI + for _,player in pairs(game.players) do + RecreateOarcGui(player) + end +end) script.on_event(defines.events.on_runtime_mod_setting_changed, function(event) if (not StringStartsWith(event.setting, "oarc-mod")) then return end @@ -96,6 +101,7 @@ script.on_event(defines.events.on_player_changed_surface, function(event) SeparateSpawnsPlayerChangedSurface(event) end) + ---------------------------------------- -- Shared chat, so you don't have to type /s -- But you do lose your player colors across forces. @@ -253,10 +259,7 @@ script.on_event(defines.events.on_gui_click, function(event) SeparateSpawnsGuiClick(event) ClickOarcGuiButton(event) - ServerInfoGuiClick(event) - SpawnCtrlGuiClick(event) - SettingsControlsTabGuiClick(event) - SettingsSurfaceControlsTabGuiClick(event) + OarcGuiTabsClick(event) end) --- Called when LuaGuiElement checked state is changed (related to checkboxes and radio buttons). diff --git a/lib/gui_tabs/player_list.lua b/lib/gui_tabs/player_list.lua new file mode 100644 index 0000000..9337c3b --- /dev/null +++ b/lib/gui_tabs/player_list.lua @@ -0,0 +1,127 @@ +-- Contains the GUI for the player list tab. + +---Used by AddOarcGuiTab +---@param tab_container LuaGuiElement +---@param player LuaPlayer +---@return nil +function CreatePlayerListTab(tab_container, player) + + local scroll_pane = tab_container.add { + type = "scroll-pane", + direction = "vertical", + vertical_scroll_policy = "always", + } + + + -- Make a table: player name, force name, home surface, time played, gps button + local player_table = scroll_pane.add { + type = "table", + column_count = 6, + style = "bordered_table", + } + + --- Add the header rows + AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-player"}, "caption_label") + AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-force"}, "caption_label") + AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-surface"}, "caption_label") + AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-time-player"}, "caption_label") + AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-location"}, "caption_label") + AddLabel(player_table, nil, {"oarc-player-list-tab-column-header-status"}, "caption_label") + + -- List online players first + for _,online_player in pairs(game.connected_players) do + AddPlayerRow(player_table, online_player.name, true) + end + + -- List offline players later + for _,player in pairs(game.players) do + if (not player.connected) then + AddPlayerRow(player_table, player.name, false) + end + end + +end + + +---Add a row to the table for a player +---@param table LuaGuiElement +---@param player_name string +---@param online boolean +---@return nil +function AddPlayerRow(table, player_name, online) + local player = game.players[player_name] + if (player) then + if player.admin then + local label = AddLabel(table, nil, player.name, my_player_list_admin_style) + label.tooltip = "Admin" + else + AddLabel(table, nil, player.name, my_label_style) + end + AddLabel(table, nil, player.force.name, my_label_style) + + -- List home surface name or holding pen + if (player.surface.name == HOLDING_PEN_SURFACE_NAME) then + AddLabel(table, nil, {"oarc-player-waiting-to-spawn"}, my_label_style) + else + local spawn = FindPlayerHomeSpawn(player.name) + if (spawn) then + AddLabel(table, nil, spawn.surface_name, my_label_style) + else + AddLabel(table, nil, "Unknown?", my_label_style) -- Shouldn't happen + end + end + + AddLabel(table, nil, FormatTimeHoursSecs(player.online_time), my_label_style) + + CreatePlayerGPSButton(table, player.name) + + if online then + local label = AddLabel(table, nil, {"oarc-player-online"}, my_player_list_style) + label.style.font_color = {r=0.1, g=1, b=0.1} + else + AddLabel(table, nil, {"oarc-player-offline"}, my_player_list_offline_style) + end + end +end + + +---Display a GPS button for a specific location. (For the player list) +---@param container LuaGuiElement +---@param player_name string +---@return nil +function CreatePlayerGPSButton(container, player_name) + local gps_button = container.add { + type = "sprite-button", + sprite = "utility/gps_map_icon", + tags = { + action = "oarc_player_list_tab", + setting = "show_location", + player_name = player_name, + }, + style = "slot_button", + tooltip = {"", {"oarc-player-list-tab-location-button-tooltip"}, " (", game.players[player_name].surface.name, ")"}, + } + gps_button.style.width = 28 + gps_button.style.height = 28 +end + +---Handle the gui click of the player list tab in the Oarc GUI. +---@param event EventData.on_gui_click +---@return nil +function PlayerListGuiClick(event) + if not event.element.valid then return end + local player = game.players[event.player_index] + local tags = event.element.tags + + if (tags.action ~= "oarc_player_list_tab") then + return + end + + -- Shows the player's current location on the map + if (tags.setting == "show_location") then + local player_name = tags.player_name --[[@as string]] + local target_player = game.players[player_name] + + player.open_map(target_player.position, 0.05) -- TODO: Update this for spage age! + end +end \ No newline at end of file diff --git a/lib/gui_tabs/spawn_controls.lua b/lib/gui_tabs/spawn_controls.lua index 2d034c1..a2243c8 100644 --- a/lib/gui_tabs/spawn_controls.lua +++ b/lib/gui_tabs/spawn_controls.lua @@ -301,7 +301,7 @@ function SpawnCtrlGuiClick(event) elseif (tags.setting == "show_location") then local surface_name = tags.surface --[[@as string]] local position = tags.position --[[@as MapPosition]] - player.open_map(position, 0.05) + player.open_map(position, 0.05) -- TODO: Update this for spage age! player.print({"", { "oarc-spawn-gps-location" }, GetGPStext(surface_name, position)}) -- Accept or reject pending player join requests to a shared base diff --git a/lib/oarc_gui_tabs.lua b/lib/oarc_gui_tabs.lua index 4703383..a743280 100644 --- a/lib/oarc_gui_tabs.lua +++ b/lib/oarc_gui_tabs.lua @@ -5,6 +5,7 @@ require("lib/gui_tabs/server_info") require("lib/gui_tabs/spawn_controls") require("lib/gui_tabs/settings_controls") require("lib/gui_tabs/mod_info_faq") +require("lib/gui_tabs/player_list") -------------------------------------------------------------------------------- -- GUI Tab Handler @@ -18,17 +19,20 @@ OARC_SERVER_INFO_TAB_NAME = "server_info" OARC_SPAWN_CTRL_TAB_NAME = "spawn_controls" OARC_CONFIG_CTRL_TAB_NAME = "settings" OARC_MOD_INFO_CTRL_TAB_NAME = "mod_info" +OARC_MOD_PLAYER_LIST_TAB_NAME = "player_list" OARC_SERVER_INFO_TAB_LOCALIZED = {"oarc-server-info-tab-title"} OARC_SPAWN_CTRL_TAB_LOCALIZED = {"oarc-spawn-ctrls-tab-title"} OARC_CONFIG_CTRL_TAB_LOCALIZED = {"oarc-settings-tab-title"} OARC_MOD_INFO_CTRL_TAB_LOCALIZED = {"oarc-mod-info-tab-title"} +OARC_PLAYER_LIST_TAB_LOCALIZED = {"oarc-player-list-tab-title"} local OARC_GUI_TAB_CONTENT_FUNCTIONS = { [OARC_SERVER_INFO_TAB_NAME] = CreateServerInfoTab, [OARC_SPAWN_CTRL_TAB_NAME] = CreateSpawnControlsTab, [OARC_MOD_INFO_CTRL_TAB_NAME] = CreateModInfoTab, [OARC_CONFIG_CTRL_TAB_NAME] = CreateSettingsControlsTab, + [OARC_MOD_PLAYER_LIST_TAB_NAME] = CreatePlayerListTab } ---@param player LuaPlayer @@ -57,6 +61,10 @@ function InitOarcGuiTabs(player) AddOarcGuiTab(player, OARC_CONFIG_CTRL_TAB_NAME, OARC_CONFIG_CTRL_TAB_LOCALIZED) SetOarcGuiTabEnabled(player, OARC_CONFIG_CTRL_TAB_NAME, true) + -- Player list tab + AddOarcGuiTab(player, OARC_MOD_PLAYER_LIST_TAB_NAME, OARC_PLAYER_LIST_TAB_LOCALIZED) + SetOarcGuiTabEnabled(player, OARC_MOD_PLAYER_LIST_TAB_NAME, true) + HideOarcGui(player) end @@ -298,9 +306,39 @@ function SwitchOarcGuiTab(player, tab_name) end end ---@param event EventData.on_gui_closed +---Handles the closing of the OARC GUI. +---@param event EventData.on_gui_closed +---@return nil function OarcGuiClosed(event) if (event.element and (event.element.name == "oarc_gui")) then HideOarcGui(game.players[event.player_index]) end end + +---Completely destroys and recreates the OARC GUI for a player. +---@param player LuaPlayer +---@return nil +function RecreateOarcGui(player) + if (mod_gui.get_button_flow(player).oarc_button ~= nil) then + mod_gui.get_button_flow(player).oarc_button.destroy() + end + + if (mod_gui.get_frame_flow(player)[OARC_GUI] ~= nil) then + mod_gui.get_frame_flow(player)[OARC_GUI].destroy() + end + + InitOarcGuiTabs(player) +end + + +---Server info gui click event handler +---@param event EventData.on_gui_click +---@return nil +function OarcGuiTabsClick(event) + if not event.element.valid then return end + ServerInfoGuiClick(event) + SpawnCtrlGuiClick(event) + SettingsControlsTabGuiClick(event) + SettingsSurfaceControlsTabGuiClick(event) + PlayerListGuiClick(event) +end \ No newline at end of file diff --git a/lib/oarc_gui_utils.lua b/lib/oarc_gui_utils.lua index 4bef959..b5ea3cd 100644 --- a/lib/oarc_gui_utils.lua +++ b/lib/oarc_gui_utils.lua @@ -99,8 +99,8 @@ my_shared_item_list_fixed_width_style = { ---@diagnostic disable-next-line: missing-fields my_player_list_admin_style = { font = "default-semibold", - font_color = {r=1,g=0.5,b=0.5}, - minimal_width = 200, + font_color = { r=0.9, g=0.7, b=0.3 }, + -- minimal_width = 200, top_padding = 0, bottom_padding = 0, single_line = false, @@ -109,7 +109,7 @@ my_player_list_admin_style = { ---@diagnostic disable-next-line: missing-fields my_player_list_style = { font = "default-semibold", - minimal_width = 200, + -- minimal_width = 200, top_padding = 0, bottom_padding = 0, single_line = false, @@ -119,7 +119,7 @@ my_player_list_style = { my_player_list_offline_style = { -- font = "default-semibold", font_color = {r=0.5,g=0.5,b=0.5}, - minimal_width = 200, + -- minimal_width = 200, top_padding = 0, bottom_padding = 0, single_line = false, diff --git a/lib/oarc_tests.lua b/lib/oarc_tests.lua index a81351c..a3092a9 100644 --- a/lib/oarc_tests.lua +++ b/lib/oarc_tests.lua @@ -162,18 +162,6 @@ function ClearTestButtons(player) end end -function RecreateOarcGui(player) - if (mod_gui.get_button_flow(player).oarc_button ~= nil) then - mod_gui.get_button_flow(player).oarc_button.destroy() - end - - if (mod_gui.get_frame_flow(player)[OARC_GUI] ~= nil) then - mod_gui.get_frame_flow(player)[OARC_GUI].destroy() - end - - InitOarcGuiTabs(player) -end - function SetNauvisChunksGenerated() local nauvis = game.surfaces["nauvis"] diff --git a/lib/oarc_utils.lua b/lib/oarc_utils.lua index c495512..200684f 100644 --- a/lib/oarc_utils.lua +++ b/lib/oarc_utils.lua @@ -208,12 +208,13 @@ end ---@return string function FormatTimeHoursSecs(ticks) local seconds = ticks / 60 - local minutes = math.floor((seconds)/60) - local hours = math.floor((minutes)/60) - local minutes = math.floor(minutes - 60*hours) + local total_minutes = math.floor((seconds)/60) + local hours = math.floor((total_minutes)/60) + local minutes = math.floor(total_minutes - 60*hours) return string.format("%dh:%02dm", hours, minutes) end + -- -- Simple math clamp -- function clamp(val, min, max) -- if (val > max) then diff --git a/lib/separate_spawns.lua b/lib/separate_spawns.lua index b7d7447..29a4d9a 100644 --- a/lib/separate_spawns.lua +++ b/lib/separate_spawns.lua @@ -737,7 +737,7 @@ function RemoveOrResetPlayer(player, remove_player) end end ----Searches all unique spawns for the primary one for a player. +---Searches all unique spawns for the primary one for a player. This will return null if they joined someeone else's spawn. ---@param player_name string ---@return OarcUniqueSpawn? function FindPrimaryUniqueSpawn(player_name) @@ -748,6 +748,19 @@ function FindPrimaryUniqueSpawn(player_name) end end +---Find the primary home spawn of a player, if one exists. It could be they joined a shared spawn. +---@param player_name string +---@return OarcUniqueSpawn? +function FindPlayerHomeSpawn(player_name) + for _,spawns in pairs(global.unique_spawns) do + for _,spawn in pairs(spawns) do + if (spawn.primary) and ((spawn.host_name == player_name) or TableContains(spawn.joiners, player_name)) then + return spawn + end + end + end +end + ---Searches all unique spawns for a list of secondary ones for a player. ---@param player_name string ---@return table -- Indexed by surface name! diff --git a/locale/en/locale.cfg b/locale/en/locale.cfg index 0335831..2fe68e5 100644 --- a/locale/en/locale.cfg +++ b/locale/en/locale.cfg @@ -181,6 +181,7 @@ oarc-server-info-tab-title=Server Info oarc-spawn-ctrls-tab-title=Spawn Controls oarc-settings-tab-title=Settings oarc-mod-info-tab-title=Mod Info +oarc-player-list-tab-title=Player List oarc-server-info-tab-welcome-msg-title=Welcome Message oarc-server-info-tab-discord-invite=Discord Invite: @@ -197,6 +198,19 @@ oarc-player-not-found=Player __1__ is not found? oarc-player-about-to-spawn=Player __1__ is about to spawn, try again later. oarc-player-none-selected=No player selected! +oarc-player-list-tab-column-header-player=Player +oarc-player-list-tab-column-header-force=Team (Force) +oarc-player-list-tab-column-header-surface=Home Surface +oarc-player-list-tab-column-header-time-player=Time Played +oarc-player-list-tab-column-header-location=Location +oarc-player-list-tab-column-header-status=Status + +oarc-player-online=Online +oarc-player-offline=Offline +oarc-player-waiting-to-spawn=Not Spawned Yet + +oarc-player-list-tab-location-button-tooltip=Click to view map location. + oarc-settings-tab-title-mod-settings=Mod Settings oarc-settings-tab-admin-warning=You are an admin. Changing these settings late in the game may cause issues!\nChanging settings will not modify existing spawns. BE CAREFUL!