RitnLibGui¶
Base class to build event-driven Factorio GUIs. It inherits from RitnLibPlayer (so all player fields are available), parses clicked element names by convention, and dispatches the action to a remote interface of the consumer mod.
RitnLibGui is abstract: you don't use it as-is, you derive a subclass that fills a few fields the base leaves empty. See the extension contract below.
| Source | classes/LuaClass/RitnGui.lua |
| Stage | control (runtime) |
| Access | global — injected into _G by core/setup-classes.lua. No require. |
| Inherits from | RitnLibPlayer |
| Extended by | the mod's GUI classes, e.g. RitnGuiMenuButton, RitnLobbyGuiLobby |
object_name |
"RitnLibGui" |
Constructor¶
RitnLibGui(event, mod_name, main_gui?) → RitnLibGui¶
Extracts the player from the event (via RitnLibEvent), initializes the RitnLibPlayer part, and leaves gui, gui_name, gui_action, content empty — to be filled by the subclass.
Parameters
- event :: EventData — the GUI event (or any event carrying a player_index).
- mod_name :: string — consumer mod name; used to target the remote interface.
- main_gui :: string? — suffix of the root element's name.
Return value → RitnLibGui. No-op if mod_name is nil.
Extension contract¶
The base class leaves four fields empty on purpose; your subclass fills them in its constructor, and the mod registers the dispatch interface:
RitnGuiMenuButton = ritnlib.classFactory.newclass(RitnLibGui, function(self, event)
RitnLibGui.init(self, event, ritnlib.defines.menu.name, "button-menu")
self.object_name = "RitnGuiMenuButton"
self.gui_name = "ritn" -- (1) logical slug
self.gui = { modGui.get_button_flow(self.player) } -- (2) root at [1]
self.content = flib.getContent() -- (3) element tree
self.gui_action = { -- (4) accepted actions
[self.gui_name] = { ["button-menu"] = true },
}
end)
-- on the mod side: register the remote dispatcher
remote.add_interface("MyMod", {
gui_action_ritn = function(action, event, ...) --[[ … ]] end,
})
| To provide | Role |
|---|---|
self.gui = { <root LuaGuiElement> } |
:getElement / :on_gui_click walk self.gui[1]. |
self.gui_name |
element-name prefix + remote interface suffix (gui_action_<gui_name>). |
self.gui_action[gui_name] = { [action] = true } |
the actions this GUI accepts. |
self.content |
path table used by :getElement. |
remote.add_interface(mod_name, { gui_action_<gui_name> = … }) |
receives the dispatched action. |
Design details in ADR-0001.
Attributes¶
In addition to the fields inherited from RitnLibPlayer:
mod_name :: string [Read]¶
Consumer mod name — target of remote.call.
event :: EventData [Read]¶
The original GUI event payload.
element :: LuaGuiElement? [Read]¶
The clicked/changed element (event.element).
gui :: table [Read]¶
Filled by the subclass: gui[1] must be the root LuaGuiElement (extension contract).
gui_name :: string [Read]¶
Logical GUI slug (e.g. "lobby"), filled by the subclass.
gui_action :: table<string, table<string, true>> [Read]¶
[gui_name][action] = true map of accepted actions, filled by the subclass.
content :: table [Read]¶
Element-path table used by :getElement, filled by the subclass.
main_gui :: string? [Read]¶
Suffix of the root element's name.
list_valid :: table<string, true> [Read]¶
Element types accepted by :on_gui_selection_state_changed (listbox, dropdown).
pattern :: string [Read]¶
Regex splitting element names into the ui/element/name triplet.
Methods¶
:getEvent() → RitnLibEvent¶
Returns a fresh RitnLibEvent wrapping the original payload.
:setMainGui(main_gui) → RitnLibGui¶
Sets the main_gui root element name. No-op if the argument isn't a string. Chainable.
:getElement(element_type, element_name?) → LuaGuiElement?¶
Retrieves an element by walking self.content[element_type][element_name] as a path of suffixes prefixed by gui_name, starting from self.gui[1].
Parameters
- element_type :: string — element category in content.
- element_name :: string? — specific name; if omitted, targets content[element_type].
Note — Relies on the extension contract:
self.gui[1]andself.contentmust have been filled by the subclass. Returnsnilif the path doesn't resolve.
:getListSelectedItem(element_type, element_name) → string?¶
Returns the selected item of a list-box / drop-down identified by (element_type, element_name). Validates the type and selection; nil if nothing is selected.
:actionGui(action, ...) → RitnLibGui¶
Dispatches an action via remote.call(self.mod_name, "gui_action_"..self.gui_name, action, self.event, ...). No-op if the action isn't declared in self.gui_action[self.gui_name].
Warning — The consumer mod must have registered
remote.add_interface(mod_name, { gui_action_<gui_name> = … }), otherwise theremote.callraises.
:on_gui_click(...)¶
Click handler: parses self.element.name via pattern into (ui, element, name) and dispatches action = "<element>-<name>" via :actionGui. Call it from the mod's on_gui_click event. Returns early and harmlessly when the click isn't for this GUI.
:on_gui_selection_state_changed(...)¶
Like :on_gui_click, for list-box / drop-down; dispatches action = "<element>-<name>-selection_state_changed". Call it from the matching event.
Usage examples¶
Wire the Factorio handler to the subclass (RitnLobbyGame/modules/lobby.lua):
local function on_gui_click(e)
RitnLobbyGuiLobby(e):on_gui_click()
end
module.events[defines.events.on_gui_click] = on_gui_click
Receive the dispatched action (RitnLobbyGame/modules/storage.lua):
local lobby_interface = {
["gui_action_lobby"] = function(action, event)
if action == "open" then RitnLobbyGuiLobby(event):action_open()
elseif action == "close" then RitnLobbyGuiLobby(event):action_close()
elseif action == "request" then RitnLobbyGuiLobby(event):action_request()
end
end,
}
remote.add_interface("RitnLobbyGame", lobby_interface)
Read a list selection (RitnLobbyGame/classes/RitnGuiLobby.lua):
Remarks¶
- Temporary wrapper — never store the instance in
storage; rebuild it in each GUI handler. See Temporary wrappers. - Abstract by design — without a subclass fulfilling the extension contract,
:getElement/:on_gui_clickhave nogui[1]root to walk. - Naming convention — element names follow
gui_name-element-namesopatterncan split them back and route the action.