asobi_lua_config (asobi v0.75.1)
View SourceLoads game configuration from Lua files in the game directory.
Supports two modes:
Single mode — a
match.luain the game directory. The script declares its config as globals (match_size,max_players,strategy,bots). The mode name defaults to"default".Multi-mode — a
config.luathat returns a table mapping mode names to script paths:return { arena = "arena/match.lua", ctf = "ctf/match.lua" }Each match script declares its own config as globals.
If neither file exists, the loader is a no-op (Erlang OTP projects that
configure via sys.config are unaffected).
Match script globals
match_size = 4 -- required, positive integer
max_players = 10 -- optional, defaults to match_size
strategy = "fill" -- optional, "fill" | "skill_based"
bots = { script = "bots/ai.lua", min_players = 4 } -- optional; min_players defaults to match_size, enabled defaults to true
game_type = "world" -- optional, "match" (default) or "world"
listed = true -- optional, browsable via match.list / world.list (matches default false, worlds true)
quick_play = true -- optional, reachable via world.find_or_create (default true)
state_strategy = "shared" -- optional, "shared" picks asobi_lua_match_shared (encode-once broadcast)
guest_auth = true -- optional, offer anonymous no-account play (needs an operator pepper; ADR 0004)
registration = "closed" -- optional, "open" | "oauth_only" | "closed" (operator sys.config wins)
-- World mode config (large session games, game_type = "world"):
tick_rate = 50 -- optional, ms per world tick (default 50 = 20 Hz)
grid_size = 1 -- optional, zones per dimension (default 10)
zone_size = 1200 -- optional, world units per zone (default 200)
view_radius = 0 -- optional, zone radius a player subscribes to (default 1)
persistent = false -- optional, snapshot zones to DB across restarts
lazy_zones = true -- optional, on-demand zone loading
zone_idle_timeout = 30000 -- optional, ms before idle zone is reaped
max_active_zones = 10000 -- optional, cap on concurrent zones
spatial_grid_cell_size = 64 -- optional, cell size for spatial grid indexing
cold_tick_divisor = 10 -- optional, tick rate divisor for cold (unoccupied) zones
empty_grace_ms = 60000 -- optional, ms to keep an empty world alive before finishing
player_ttl_ms = 0 -- optional, 0=remove on disconnect, -1=keep forever, N=grace msSetting game_type = "world" routes the script through the asobi_lua_world
bridge (zone_tick/2 + handle_input/3 returning entities). Defaults to "match",
which uses the asobi_lua_match bridge (tick/1 + wrapped-state callbacks).
guest_auth and registration are read from match.lua in single-mode and
from config.lua (the manifest) in multi-mode. guest_auth only declares
intent; guest auth is on iff the operator also supplies a >= 32-byte pepper
(ADR 0004). registration declares a signup posture for a deployment that
states none: it lands in the script layer asobi_registration reads only when
the operator's sys.config leaves registration unset, and an unrecognised
value is logged and dropped rather than downgrading the posture.
This module reads Lua and nothing else: it hands the config term it derived to
asobi_game_config:apply_config/1, which owns the merge with operator config
and the order the app-env keys are written in (ADR 0006).
Bot scripts can export a names list that the platform reads after loading:
names = {"Spark", "Blitz", "Volt"}