asobi_presence (asobi v0.75.1)
View SourceWho is reachable, and who counts as online.
Those are two different facts and this module keeps them apart:
- addressable - the process is a delivery target for
send/2, keyed by player id. Player sessions and bots are both addressable. - online - a connected human player. Only
track/2records that, andonline_count/0counts exactly those.
Bots (asobi_bot) are addressable but never online. track_bot/2 joins the
delivery group and nothing else: a bot does not count toward
online_count/0 and does not emit player_online / player_offline
presence broadcasts. online_count/0 is the operator-facing concurrency
number, and bot fill is itself driven by how few humans are queued, so
counting server-spawned bots would both inflate the figure and feed it back
into its own input.
Message contract
Everything send/2 delivers arrives at the target process as
{asobi_message, message()}. message/0 is the contract between the core
servers that produce those terms (asobi_match_server, asobi_world_server,
asobi_zone, asobi_matchmaker, the Lua runtime) and the processes that
pattern-match them (asobi_ws_handler, asobi_player_session, asobi_bot).
Shared match state is the one shape whose form depends on the recipient:
send_match_state/3 hands a session the pre-encoded frame and a bot the
same payload as a term. Both are message/0 shapes; see that function.
It is a public type on purpose. send/2 is spec'd with it, so a producer
that invents a shape fails dialyzer instead of quietly emitting a term no
consumer handles, and a consumer (asobi_bot does this) can spec its own
clauses against the same named type rather than an ad-hoc guess.
Summary
Functions
Deliver one tick of shared match state to a roster entry.
Track a connected player session: addressable by send/2 and counted by
online_count/0.
Track a bot process: addressable by send/2, deliberately not online.
Types
-type message() :: {match_joined, pid()} | {match_state, map()} | {match_state_raw, binary()} | {match_event, event_name(), map()} | {world_joined, pid(), pid() | undefined} | {world_zone_changed, pid()} | {world_event, event_name(), map()} | {zone_delta, non_neg_integer(), [map()]} | {zone_delta_raw, binary()} | {terrain_chunk, {integer(), integer()}, binary()} | {dm_message, map()} | {notification, map()} | {game_message, term()} | {script_error, map()}.
Functions
-spec get_status(binary()) -> online | offline.
-spec handle_call(term(), gen_server:from(), map()) -> {reply, term(), map()}.
-spec init([]) -> {ok, #{}}.
-spec online_count() -> non_neg_integer().
Deliver one tick of shared match state to a roster entry.
Sessions get PreEncoded, the wire frame the caller encoded once for the
whole match (ADR 0001). Bots get SharedState, the same payload as a term,
because a bot reads the state in Erlang and has no use for a JSON binary:
routing it here keeps the one encode per tick and costs a bot no decode.
-spec start_link() -> gen_server:start_ret().
Track a connected player session: addressable by send/2 and counted by
online_count/0.
Track a bot process: addressable by send/2, deliberately not online.
A bot never counts toward online_count/0 and never emits a presence
broadcast. See the module docs for why.
-spec untrack(binary()) -> ok.