From 49e08af7edfdaf26b141b991f05b5823c137c754 Mon Sep 17 00:00:00 2001 From: Cooldude2606 <25043174+Cooldude2606@users.noreply.github.com> Date: Thu, 2 Jan 2025 03:24:00 +0000 Subject: [PATCH] Add ExpGui_GuiIter --- exp_gui/module/iter.lua | 215 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 exp_gui/module/iter.lua diff --git a/exp_gui/module/iter.lua b/exp_gui/module/iter.lua new file mode 100644 index 00000000..3fba2f38 --- /dev/null +++ b/exp_gui/module/iter.lua @@ -0,0 +1,215 @@ + +local ExpUtil = require("modules/exp_util") +local Storage = require("modules/exp_util/storage") + +--- @type table>> +local script_data = {} +Storage.register(script_data, function(tbl) + script_data = tbl +end) + +--- @class ExpGui_GuiIter +local GuiIter = { + _elements = script_data, +} + +local function nop() return nil, nil end + +--- Get the next valid element +--- @param elements table +--- @param prev_index uint? +--- @return uint?, LuaGuiElement? +local function next_valid_element(elements, prev_index) + local element_index, element = next(elements, prev_index) + while element and not element.valid do + elements[element_index] = nil + element_index, element = next(elements, element_index) + end + return element_index, element +end + +--- Get the next valid player with elements +--- @param define_elements table> +--- @param players LuaPlayer[] +--- @param prev_index uint? +--- @param online boolean? +--- @return uint?, LuaPlayer?, table? +local function next_valid_player(define_elements, players, prev_index, online) + local index, player = nil, nil + while true do + index, player = next(players, prev_index) + while player and not player.valid do + define_elements[player.index] = nil + index, player = next(players, index) + end + + if index == nil then + return nil, nil, nil + end + + if online == nil or player.connected == online then + local player_elements = define_elements[player.index] + if player_elements and #player_elements > 0 then + return index, player, player_elements + end + end + end +end + +--- Iterate over all valid elements for a player +--- @param define_name string +--- @param player LuaPlayer +--- @return fun(): LuaPlayer?, LuaGuiElement? +function GuiIter.player_elements(define_name, player) + if not player.valid then return nop end + + local define_elements = script_data[define_name] + if not define_elements then return nop end + + local player_elements = define_elements[player.index] + if not player_elements then return nop end + + local element_index, element = nil, nil + return function() + element_index, element = next_valid_element(player_elements, element_index) + if element_index == nil then return nil, nil end + return player, element + end +end + +--- Iterate over all valid elements for a player +--- @param define_name string +--- @param players LuaPlayer[] +--- @param online boolean? +--- @return fun(): LuaPlayer?, LuaGuiElement? +function GuiIter.filtered_elements(define_name, players, online) + local define_elements = script_data[define_name] + if not define_elements then return nop end + + local index, player, player_elements = nil, nil, nil + local element_index, element = nil, nil + return function() + while true do + -- Get the next valid player elements if needed + if element_index == nil then + index, player, player_elements = next_valid_player(define_elements, players, index, online) + if index == nil then return nil, nil end + --- @cast player_elements -nil + end + + -- Get the next element + element_index, element = next_valid_element(player_elements, element_index) + if element_index then + return player, element + end + end + end +end + +--- Iterate over all valid elements +--- @param define_name string +--- @return fun(): LuaPlayer?, LuaGuiElement? +function GuiIter.all_elements(define_name) + local define_elements = script_data[define_name] + if not define_elements then return nop end + + local player_index, player_elements, player = nil, nil, nil + local element_index, element = nil, nil + return function() + while true do + if element_index == nil then + -- Get the next player + player_index, player_elements = next(define_elements, player_index) + if player_index == nil then return nil, nil end + player = game.get_player(player_index) + + -- Ensure next player is valid + while player and not player.valid do + define_elements[player_index] = nil + player_index, player_elements = next(define_elements, player_index) + if player_index == nil then return nil, nil end + player = game.get_player(player_index) + end + --- @cast player_elements -nil + end + + -- Get the next element + element_index, element = next_valid_element(player_elements, element_index) + if element_index then + return player, element + end + end + end +end + +--- @alias FilterType LuaPlayer | LuaForce | LuaPlayer[] | nil + +--- Iterate over all valid gui elements for all players +--- @param define_name string +--- @param filter FilterType +--- @return fun(): LuaPlayer?, LuaGuiElement? +function GuiIter.get_elements(define_name, filter) + local class_name = ExpUtil.get_class_name(filter) + if class_name == "nil" then + --- @cast filter nil + return GuiIter.all_elements(define_name) + elseif class_name == "LuaPlayer" then + --- @cast filter LuaPlayer + return GuiIter.player_elements(define_name, filter) + elseif class_name == "LuaForce" then + --- @cast filter LuaForce + return GuiIter.filtered_elements(define_name, filter.players) + elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then + --- @cast filter LuaPlayer[] + return GuiIter.filtered_elements(define_name, filter) + else + error("Unknown filter type: " .. class_name) + end +end + +--- Iterate over all valid gui elements for all online players +--- @param define_name string +--- @param filter FilterType +--- @return fun(): LuaPlayer?, LuaGuiElement? +function GuiIter.get_online_elements(define_name, filter) + local class_name = ExpUtil.get_class_name(filter) + if class_name == "nil" then + --- @cast filter nil + return GuiIter.filtered_elements(define_name, game.connected_players) + elseif class_name == "LuaPlayer" then + --- @cast filter LuaPlayer + if not filter.connected then return nop end + return GuiIter.player_elements(define_name, filter) + elseif class_name == "LuaForce" then + --- @cast filter LuaForce + return GuiIter.filtered_elements(define_name, filter.connected_players) + elseif type(filter) == "table" and ExpUtil.get_class_name(filter[1]) == "LuaPlayer" then + --- @cast filter LuaPlayer[] + return GuiIter.filtered_elements(define_name, filter, true) + else + error("Unknown filter type: " .. class_name) + end +end + +--- Add a new element to the global iter +--- @param define_name string +--- @param element LuaGuiElement +function GuiIter.add_element(define_name, element) + if not element.valid then return end + + local define_elements = script_data[define_name] + if not define_elements then + define_elements = {} + script_data[define_name] = define_elements + end + + local player_elements = script_data[element.player_index] + if not player_elements then + player_elements = {} + script_data[element.player_index] = player_elements + end + + player_elements[element.index] = element +end + +return GuiIter