diff --git a/exp_scenario/module/gui/elements.lua b/exp_scenario/module/gui/elements.lua index e1cd1113..66cfc99d 100644 --- a/exp_scenario/module/gui/elements.lua +++ b/exp_scenario/module/gui/elements.lua @@ -7,34 +7,57 @@ local Gui = require("modules/exp_gui") --- @class ExpGui_Elements local Elements = {} ---- To help with caching and avoid context changes the player list from the previous update is remembered ---- @type (string?)[] -local _player_names = {} - --- Dropdown which allows selecting an online player --- @class ExpGui_Elements.online_player_dropdown: ExpElement --- @overload fun(parent: LuaGuiElement): LuaGuiElement Elements.online_player_dropdown = Gui.define("player_dropdown") :track_all_elements() :draw(function(def, parent) + local player_names = Elements.online_player_dropdown._access_player_names() return parent.add{ type = "drop-down", - items = _player_names, - selected_index = #_player_names > 0 and 1 or nil, + items = player_names, + selected_index = 1, } end) :style{ height = 24, } --[[ @as any ]] +--- To help with caching and avoid context changes the player list from the previous update is remembered +--- @type (string?)[] +do local _player_names = {} + --- Updates the player name list after a join or leave + --- @return (string?)[] + function Elements.online_player_dropdown._update_player_names() + _player_names[#_player_names] = nil -- Nil last element to account for player leave + for i, player in pairs(game.connected_players) do + _player_names[i] = player.name + end + return _player_names + end + + --- Safely access the player name list + --- @return (string?)[] + function Elements.online_player_dropdown._access_player_names() + if not _player_names[1] then + for i, player in pairs(game.connected_players) do + _player_names[i] = player.name + end + end + return _player_names + end +end + --- Get the selected player name from a online player dropdown --- @param online_player_dropdown LuaGuiElement --- @return string function Elements.online_player_dropdown.get_selected_name(online_player_dropdown) - local name = _player_names[online_player_dropdown.selected_index] + local player_names = Elements.online_player_dropdown._access_player_names() + local name = player_names[online_player_dropdown.selected_index] if not name then online_player_dropdown.selected_index = 1 - name = _player_names[1] --- @cast name -nil + name = player_names[1] --- @cast name -nil end return name end @@ -43,10 +66,11 @@ end --- @param online_player_dropdown LuaGuiElement --- @return LuaPlayer function Elements.online_player_dropdown.get_selected(online_player_dropdown) - local name = _player_names[online_player_dropdown.selected_index] + local player_names = Elements.online_player_dropdown._access_player_names() + local name = player_names[online_player_dropdown.selected_index] if not name then online_player_dropdown.selected_index = 1 - name = _player_names[1] --- @cast name -nil + name = player_names[1] --- @cast name -nil end return assert(game.get_player(name)) end @@ -55,20 +79,15 @@ end --- Get the number of players in the dropdown --- @return number function Elements.online_player_dropdown.get_player_count() - return #_player_names + return #Elements.online_player_dropdown._access_player_names() end --- Update all player dropdowns to match the currently online players --- We don't split join and leave because the order would be inconsistent between players and cause desyncs function Elements.online_player_dropdown.refresh_online() - _player_names[#_player_names] = nil -- Nil last element to account for player leave - - for i, player in pairs(game.connected_players) do - _player_names[i] = player.name - end - + local player_names = Elements.online_player_dropdown._update_player_names() for _, online_player_dropdown in Elements.online_player_dropdown:online_elements() do - online_player_dropdown.items = _player_names + online_player_dropdown.items = player_names end end