asobi_match_server (asobi v0.84.0)
View SourcePer-match gen_statem driving the configured game module.
Trust boundary (F-32): asobi is single-tenant by design. The
configured game module (Mod:join/2, Mod:tick/1, Mod:handle_input/3,
phase / vote callbacks, etc.) is trusted code. We do not wrap
callbacks in try/catch — a crash in the game module is treated as a
bug worth surfacing, not a security boundary to harden against. The
match supervisor restarts the match server up to 10 times in 60s
(transient + intensity 10) before the entire asobi_match_sup falls
over, intentionally taking the lobby with it so an obviously broken
game cannot keep churning silently.
In multi-tenant or sandboxed contexts (asobi_lua) callbacks are run
through a Lua sandbox that has its own fault-isolation; that wrapper is
the place to put callback hardening.
Summary
Functions
Join carrying an opaque join context from the client. asobi does not
interpret it; it reaches the game module's join/3 if it exports one.
Projection of get_info/1 for callers who are not in the match.
Open or close the match to new joins.
Functions
-spec callback_mode() -> gen_statem:callback_mode_result().
-spec cancel(pid()) -> ok.
-spec finished(gen_statem:event_type() | enter, term(), map()) -> gen_statem:state_enter_result(atom()).
Join carrying an opaque join context from the client. asobi does not
interpret it; it reaches the game module's join/3 if it exports one.
Projection of get_info/1 for callers who are not in the match.
Mirrors asobi_world_server:listing_info/1. get_info/1 carries the full
players roster and the server-side listed flag; neither reaches a
browsing client. joinable does: a client browsing for a match to join has
to be able to tell a match that will take it from one that has closed, and
without it the only way to find out is to attempt the join and be refused.
-spec paused(gen_statem:event_type() | enter, term(), map()) -> gen_statem:state_enter_result(atom()).
-spec running(gen_statem:event_type() | enter, term(), map()) -> gen_statem:state_enter_result(atom()).
Open or close the match to new joins.
A closed match keeps running and keeps its roster; it answers every further
join with match_locked. This is the runtime half of joinability - listed
decides whether a match is advertised by asobi_match_lobby, and an
unlisted match is still joinable by id, so hiding a match is not closing it.
Asynchronous because the caller is usually the match's own Lua VM
(game.match.set_joinable), which runs inside this process. An Erlang game
module is in the same position - its callbacks run here too - so it closes
its own match with set_joinable(self(), false) from tick/1, join/2 or
any other callback.
-spec start_link(map()) -> gen_statem:start_ret().
-spec waiting(gen_statem:event_type() | enter, term(), map()) -> gen_statem:state_enter_result(atom()).