-
Notifications
You must be signed in to change notification settings - Fork 0
Builder Commands
Audience: Builder Status: ✅ Ready
The in-game command surface, with emphasis on how commands are resolved and on the staff/builder
verbs an elevated session gains over an ordinary player. This page explains the dispatch model
(so you understand why n means north and why a verb you lack simply "doesn't exist"), then
itemizes the everyday command surface and the staff verbs. For who gets staff rank and how it's
applied, see Trust Tier Model; for the deeper parser/targeting internals see
Command Parser & Targeting.
Every line a player types enters one dispatcher running on the zone's single goroutine, so a command handler mutates zone state without locking. The pipeline is: trim the line (a blank line just re-prompts), split into a verb and the rest, lowercase the verb, clear AFK as a side effect, resolve the verb, gate it, and run it.
A character can define Unix-style aliases — alias bc burn corpse makes bc expand to burn corpse, and bc altar to burn corpse altar (trailing input is appended). Expansion runs at the
split step, before verb resolution — the phase the parser reserves for it — which has two
consequences worth understanding: an alias can target any verb the resolver handles (built-in,
ability, custom, channel, or a named exit), and it grants no privilege, because the MinRank
gate always runs on the resolved verb, not the typed alias. Expansion is cycle- and
depth-bounded (a visited-set plus a cap), and the reconstructed line is re-clamped to the ingress
byte cap so a chained alias can't amplify one keystroke past it. alias lists, alias <name>
queries, unalias removes. (This is distinct from a built-in command alias like n→north,
which is engine-defined; see the abbreviation rule below.)
A verb is looked up across four namespaces in a fixed order; a later namespace can never shadow an earlier one:
- Built-in verbs — the engine's core commands (movement, look, inventory, combat, …). Abbreviation-aware (below).
- Ability invocations — abilities whose invocation is a command verb (e.g. a spell word). Exact match only, so an ability can never shadow or abbreviate a core verb.
-
Custom Lua commands (
command_defs) — verbs a pack defines in Lua. Exact match only; a custom verb that collides with a built-in is rejected at load with a warning, so content can never override a core verb. -
Content channel verbs (
channel_defs, e.g.gossip) — exact match only.
If none of those match, a final named-exit fall-through tries the current room's exit keys: an
unknown verb that exactly matches an exit key traverses it, so a content exit like grove or
warded is typeable as a movement verb. It is consulted last, so it can never shadow or
abbreviate a core verb, and it checks the exits map only — never entrances, which is the
instance-entry security path. Only then, if nothing at all matched, is the reply
Huh? and a fresh prompt.
Within the built-in table, resolution is: (1) an exact match on a canonical name or an alias
always wins; (2) otherwise the first command, in registration/priority order, whose canonical
name has the typed verb as a prefix. Aliases do not participate in prefix matching — only
canonical names abbreviate. Movement is registered first (highest priority), which is why n
abbreviates to north and cl abbreviates to close (the low-priority clear never wins the
abbreviation). A verb longer than any candidate name is a Huh?.
Staff verbs carry a minimum rank. If your session's rank is below a verb's minimum, the resolver forces the verb to not found before the fall-through — so an insufficient-rank staff verb is indistinguishable from a nonexistent one. This is the classic wizard posture: the existence of staff tooling never leaks to a mortal. (Rank is your session tier's rank vs. the command's minimum — see Trust Tier Model.)
Shape-only surface (honest caveats). The command struct also declares
MinPos,Level, andFlags(CmdHidden,CmdNoWhileFighting), but dispatch enforces onlyMinRank. Position/combat gating is done ad hoc inside individual handlers (movement refuses while fighting;restchecks position) rather than by the dispatcher.CmdHiddenmarks staff verbs and is now consumed by thehelpcommand's index (a hidden or over-MinRankverb is filtered from a mortal's help, exactly as dispatch hides it);CmdNoWhileFightingis enforced nowhere. Player alias expansion is not implemented (it's deferred to a later phase). Treat those fields as declared-but-inert.
All of these are ungated (rank 0). Aliases are shown in parentheses.
Movement (highest priority): north (n), south (s), east (e), west (w), up (u),
down (d) — walk an exit, whether that's a local move, an intra-shard transfer, or a cross-shard
handoff. Refused while fighting ("flee first"). The named-exit verbs enter / exit / out
walk a content-authored non-cardinal exit (a city gate, a portal) through the same move()
chokepoint; they're registered low-priority so o still abbreviates to open. The built-in
Exits: line lists these too, in the order exit, enter, out, n, e, s, w, u, d (so a gate
room reads e.g. Exits: exit, south). A pack may also register its own toggle verbs
(toggle_defs) the same low-priority way — the demo's overworld verb
flips the minimap.
Look & common:
-
look(l) — bare shows the room;look <target>examines an item, occupant, or container's contents. -
help/help <topic>— the content-defined help index and topics (help_defs), with the registered command set auto-included; the listing honorsCmdHidden+MinRank, so it doubles as the tier-appropriate command reference. -
say(') — room speech (fires Luaspeechtriggers on scripted mobs present). -
score(sc) — your character sheet; renders the contentscoredisplay template if the pack defines one, else a built-in. -
who— the cross-shard online roster, filtered by visibility/holylight, with a per-session cooldown (falls back to a zone-local list if presence is disabled). -
tell/reply— directed, durable player-to-player messages. -
tells(replay) — your recent private-message history, sent + received interleaved chronologically. A transient, session-scoped ring: pair-privacy is structural (an A↔B exchange lives only in A's and B's own session rings — no shared store to leak from, no access check needed), it skips an ignored author so it matches what actually reached your screen, and it resets on relog/handoff. A sent tell is recorded at the confirmed-echo point (past both the resolve-miss and publish-failure returns), never optimistically at enqueue — so a tell to a nonexistent name leaves no phantom entry, keeping "history == what you actually saw." -
audit— your own permanent-record trail (creation, deaths, tier/attribute/track grants), scoped by your stable character id;audit <name>is a staff-only lookup of another character. See Persistence & Durability → the audit trail. -
quit— clean disconnect.
Carrying capacity (encumbrance) is pure content: carry_capacity is a derived attribute (5e's Str×15 authored as a base formula), and the engine only enforces aggregate carried weight ≤ carry_capacity at acquisition — get/get from refuse an over-weight pickup, and get all takes what fits and leaves the rest. Worn gear stays in contents, so one weight pass covers carried + worn with no double-count; a pack that sets carry_capacity ≤ 0 models no encumbrance (a clean no-op).
Inventory, equipment & containers: inventory (i, inv), equipment (eq), get (take),
drop, put, wear, wield, hold, remove, open, close, split (split a material
stack), keep / unkeep (protect an item from drop/sacrifice). inventory and equipment
render content display templates if defined.
Combat: kill (k) — engage melee and arm the zone's round driver; flee — a sanctioned
mid-fight exit; assist (as) — join an ally's fight; consider (con) — size up a target.
Rest & position: rest (sit) — enter a faster-regen resting position; stand. rest/rest short/sit is a short rest and rest long/rest full a long rest — the engine fires OnRest plus the specific OnShortRest/OnLongRest, and what each restores is content (5e: short spends Hit Dice, long restores all).
Credits: credits (aliases license, copyright) — show the loaded packs' declared license/attribution notices (a pack's required CC-BY-style credit, surfaced in-game). A world whose packs declare none reports a clean "no content credits."
Vitals: vitals — toggle live resource pools in your prompt (vitals on|off).
Comms toggles: channels — list/toggle channels (channels on|off <ref>); ignore — manage
a per-player ignore list; afk — set/clear AFK. history <channel> replays that channel's recent
scrollback — but only to a viewer the channel's live hear predicate still admits at fetch time
(a since-demoted or flag-dropped player replays nothing), while a member who merely toggled the
channel off can still read it. Shard-local, so on a multi-shard fleet the backlog is a partial view — and it says so, appending an in-band "shard-local view; may be incomplete" footer whenever the shard has peers (a single-shard run, the common case, shows no footer).
Mail: mail — mail (list) / mail read <n> / mail delete <n> /
mail send <name> <subj> | <body>; degrades to "Mail is unavailable" on a shard with no store.
Screen: clear (cls) — wipe the terminal. This is universal, not rank-gated: it emits an
engine-constant ANSI clear (never player-controlled bytes), so there is nothing untrusted to gate.
It's registered at low priority so cl still abbreviates to close.
Aliases: alias — list your aliases; alias <name> — show one; alias <name> <expansion> —
define one (alias bc burn corpse); unalias <name> — remove one. Per-character, durable across
logout and a cross-shard walk. See how aliases expand.
All staff verbs are world verbs, registered last (lowest priority, so they never win an
abbreviation), hidden (CmdHidden), and gated at MinRank = 1 — "any tier above baseline." Below
that rank they are treated as unknown (see above). The account-tier side of granting staff rank is
in First Admin Setup and Trust Tier Model.
| Verb | Side | MinRank | Effect |
|---|---|---|---|
stat [<target>] |
world | 1 | Inspect an entity's internals: runtime id, prototype ("vnum"), flyweight bit, component set, live flags (reserved trust flags marked *), serialized state. Bare = current room; me/self = you; else keyword-resolve over room/inventory/equipment. Read-only. Cannot inspect a target of higher tier than you.
|
reload [<pack>] |
world | 1 | Trigger a director-coordinated content hot-reload across the fleet. |
pull <version> [force] |
world | 1 (force: admin) |
Request a director-coordinated install of a published content version from the external store. force downgrades the live-zone prune veto to a report — it still runs and still reports what it blocked — and needs admin on top of the builder flag, since it strips content the fleet may be hosting. See Content Pack Operations. |
holylight on|off |
world | 1 | See-all toggle (reserved holylight flag). Turning it on is capped: only a tier that grants holylight may enable it (no self-elevation); off is always allowed. Session-scoped (relog re-derives from tier). |
wizinvis on|off |
world | 1 | Staff invisibility (reserved wizinvis flag): hides you from anyone of strictly lower trust rank. No grant cap — reach is bounded by your own rank. Republishes presence. Session-scoped (cleared at login). |
rolls on|off |
world | 1 | Surface your own hidden check-roll math. |
debug on|off |
world | 1 | Subscribe your session to live zone diagnostics (first consumer: Lua script errors). Session-scoped, and rank is re-checked per line, so a mid-session demote stops delivery before relog. |
Notes:
-
reloadandpullare content operations, coordinated by the director across all shards. The operational side (external store, versions, CI) is in Content Pack Operations. -
The
screen.*Lua capability is not a per-tier unlock. The sandboxed full-screen ANSI builder (screen.frame()→clear/home/at/color/write/show) is available to content regardless of the player's tier; its trust boundary is content-authorship (a builder wrote the Lua), not a per-call rank check, and it's bounded by per-frame caps. A builder does not "unlock" it by tier. See Pack Lua Scripting. -
There is no world-side
promote/demoteverb. Tier changes are account/edge-side (promote/demoteon the gate →SetAccountTier), and the world applies the new tier on the target's next login. The gate verbs also carry the wiz-command posture: a non-staff actor who typespromote/demotegets a plainHuh?— no usage hint, no authorization refusal, and no account-service round-trip — so the verbs' existence never leaks (and can't be used to probe the account service). The gate resolves amanage_tiersvisibility bit once at login and only uses it to decide whether to intercept; the account service stays authoritative. See First Admin Setup, Trust Tier Model, and Accounts & Auth Internals.
TelosMUD — Wiki under construction.
- Builder Reference
- Builder Commands
- Trust Tier Model
- Pack Authoring
- Pack MUD Settings
- Pack Lua Scripting
- Pack Lua Hooks
- Pack Entity Reference
- Building Instanced Zones
- Engine Developer Reference
- Architecture Overview
- Entity Component Model
- Zone Runtime & Actor Model
- Instanced Zones
- Command Parser & Targeting
- Edge & Protocol
- GMCP Reference
- Persistence & Durability
- Content Loading & Hot Reload
- Abilities & Effects
- Combat System
- Loot, Spawns & Crafting
- Accounts & Auth Internals
- Orchestration & Directors
- Scoped Event Bus
- Cross-Shard Handoff
- Lua Sandbox Internals
- Distributed Systems Model
- RPC & Protobuf