A game-agnostic framework for connecting Luanti games to Archipelago multiworld randomizer servers. Each game will need its own game-specific mod and corresponding apworld to define its randomization logic and overrides. This library provides realtime connectivity to the multiworld server for that mod.
Features 🔗
arclib provides the foundational client-side components for Archipelago integration, including:
- Robust Connection Management: Automatic reconnection, ping/pong keepalive, and timeout handling
- WebSocket Connections: HTTP proxy support to work around Luanti's WebSocket limitations
- Message Persistence: Reliable message delivery using Luanti's mod storage with queuing across restarts
- Protocol Abstraction: Flexible Archipelago protocol implementation with proper JSON serialization
- Event System: Emitter pattern for handling server events and state changes
- Configuration UI: Built-in formspec interface for server connection settings
- Cross-Platform: Works on all Luanti platforms via HTTP-to-WebSocket proxy
Requirements 🔗
WebSocket Proxy Required: arclib is packaged with websockproxy, which allows Luanti to connect to websockets, as required by Archipelago but unsupported by Luanti's HTTP API. An instance of this must be running and accessible to arclib.
Ideally, players (singleplayer) or server operators (multiplayer) should run their own instance of the websockproxy. One instance of websockproxy is sufficient for any/all running game instances.
The proxy defaults to http://localhost:9839 and can be configured in the connection settings.
Users who have the Go language tools installed can run make proxy in arclib to run the proxy directly from source. Pre-built versions may be available as websockproxy/websockproxy-* binaries for selected platforms.
HTTP Access Required: arclib must be added to the Luanti secure.http_mods setting in order to load. Players or server operators must do this manually, by editing the config file or using Luanti's settings interface.
Quick Start 🔗
Installation 🔗
Add arclib to your mod's dependencies in mod.conf:
depends = arclib
Basic Usage 🔗
-- Create a manager instance
local manager = arclib.manager({
url_target = "wss://archipelago.gg:38281",
login_slotname = "PlayerName",
login_gamename = "Your Game Name",
modstore = core.get_mod_storage() -- For persistence
})
-- Set up event handlers
manager.on("update", function()
-- Handle state updates (items received, locations checked, etc.)
local state = manager.state
if state.items_received then
-- Process received items
end
end)
manager.on("printtext", function(text)
-- Display chat messages from Archipelago
core.chat_send_all(text)
end)
core.register_on_chat_message(function(_, msg)
-- Relay local chat to archipelago
manager:say(msg)
end)
-- Load saved connection configuration
arclib.ux.configure({
modstore = modstore,
manager = manager
})
-- Chat command to access config UI
core.register_chatcommand("ap", {
description = "Show Archipelago config form",
func = function(name)
arclib.ux.configure({
modstore = modstore,
player = name,
manager = manager,
})
end
})
API Reference 🔗
Manager (arclib.manager) 🔗
The main interface for Archipelago connections.
Handles automatic reconnects and message resends, including persisting queued reliable messages across restarts. Maintains a cached replicated state from the server, including across disconnects.
Constructor 🔗
local manager = arclib.manager(options)
Options 🔗
modstore: Luanti mod storage for persistencestoreprefix: Optional prefix for storage keysurl_target: Archipelago WebSocket URLurl_proxy: HTTP proxy URL (default:http://localhost:9839)login_slotname: Player slot namelogin_gamename: Game namelogin_password: Optional room password
Methods 🔗
manager:open()- Start connectionmanager:close()- Stop connectionmanager:check_location(locations)- Check location(s) by name or ID (reliable)manager:goal_complete()- Send goal completion (reliable)manager:say(text)- Send chat messagemanager:flush_send_queue()- Manually flush pending messages
Events 🔗
update- State updated from server (any data update received, including partial state during startup)printtext- Chat message received (from PrintJSON) and parseddisconnect- Connection lostrejected- Connection rejected by servercmd:*- Specific Archipelago commands, following Archipelago protocol's TitleCase naming
Connection (arclib.connection) 🔗
Low-level protocol handler (used internally by manager). Not intended for downstream use, exported as-is.
WebSocket (arclib.websocket) 🔗
HTTP-to-WebSocket bridge client. Not intended for downstream use, exported as-is.
Utilities (arclib.util) 🔗
create_emitter()- Create event emitter functionsdeepcopy(src)- Deep copy tables with cycle supportgenerate_uuid()- Generate UUID v4log(level, ...)- Structured loggingprint_json_convert(state, data)- Convert PrintJSON to textstructstore(modstore, prefix)- Persistent structured storage
UX (arclib.ux) 🔗
configure(options)- Load stored configuration / show configuration UI
Architecture 🔗
Your Mod
↕
arclib.manager
arclib.connection
arclib.websocket
↕ (HTTP)
External websockproxy
↕ (WebSocket)
Archipelago Server
Persistence 🔗
arclib can automatically persist:
- Connection configuration
- Reliable message queue (location checks, goal completion)
- Cached server state
Data is stored using Luanti's mod storage system, in the consumer mod's own mod storage. Persistence is controlled by downstream mods, which must provide a mod storage object to arclib components to enable it.
AI Disclosure 🔗
This project was developed jointly by human developer(s) and AI coding agent(s). AI models used may include members of the following model families: OpenCode Zen Big Pickle (based on GLM-4.x), and Copilot Anthropic Claude 4.x. Agent access to the project was managed by SST's OpenCode tool.