Remote interfaces¶
This guide covers the remote.add_interface patterns used in RitnLib mods: GUI dispatch, cross-mod communication, and naming conventions.
Why remote¶
Factorio uses remote.add_interface / remote.call for communication between mods. It's the only clean way for mod A to call a function from mod B without tight coupling.
In RitnLib, remote interfaces are primarily used for GUI dispatch: RitnLibGui calls remote.call(mod_name, "gui_action_<gui_name>", ...) to route clicks.
Interface structure¶
-- my-mod/control.lua
remote.add_interface("my-mod", {
my_function = function(arg1, arg2)
-- logic
return result
end,
another_function = function()
-- ...
end
})
remote.add_interface takes a name (the interface name, typically the mod name) and a table of functions. It registers at the moment the file runs.
GUI interface — click dispatch¶
The gui_action_<gui_name> pattern is a RitnLib convention. RitnLibGui looks for exactly this name:
remote.add_interface("my-mod", {
-- gui_name = "my-gui" → gui_action_my_gui (hyphens → underscores)
gui_action_my_gui = function(player_index, element_name)
local player = game.get_player(player_index)
if element_name == "btn-ok" then
-- OK button clicked
elseif element_name == "btn-close" then
if player and player.gui.center["my-gui-root"] then
player.gui.center["my-gui-root"].destroy()
end
end
end,
})
element_name is the name of the clicked element without the "gui_name-" prefix.
Multiple GUIs in the same mod¶
You can have multiple GUI interfaces in the same remote.add_interface table:
remote.add_interface("my-mod", {
gui_action_inventory = function(player_index, element_name)
-- dispatch for the "inventory" GUI
end,
gui_action_options = function(player_index, element_name)
-- dispatch for the "options" GUI
end,
-- utility functions for other mods
get_version = function()
return "1.0.0"
end,
})
Calling another mod's interface¶
-- Check the interface exists before calling
if remote.interfaces["other-mod"] and remote.interfaces["other-mod"]["get_version"] then
local version = remote.call("other-mod", "get_version")
log("other-mod version: " .. version)
end
Always check remote.interfaces["mod-name"] before calling — the mod may be absent or disabled.
Naming rule¶
| Case | Function name |
|---|---|
GUI dispatch for gui_name = "my-panel" |
gui_action_my_panel |
GUI dispatch for gui_name = "lobby-main" |
gui_action_lobby_main |
| Public API for other mods | any descriptive name |
The rule: replace hyphens with underscores in gui_name to get the function name.
One interface per mod¶
remote.add_interface can only be called once per name. Calling it twice with the same name raises a Factorio error. Group all your functions in a single call.
-- ✅ One call with all functions
remote.add_interface("my-mod", {
gui_action_panel = function(...) ... end,
gui_action_options = function(...) ... end,
get_data = function() ... end,
})
-- ❌ Two separate calls → Factorio error
remote.add_interface("my-mod", { gui_action_panel = ... })
remote.add_interface("my-mod", { gui_action_options = ... }) -- ERROR