Source layout

The MUX server is organized by responsibility beneath src/mux.

  • server contains platform definitions, configuration parsing, server state, lifecycle, logging, timers, signals, and file caches.
  • support contains reusable containers, buffer helpers, and string utilities.
  • objects owns game objects, exact-name Lua storage, flags, and powers.
  • world owns player, object, matching, movement, and presentation behavior.
  • commands owns native command dispatch, queues, literal parsing, and macros.
  • communication owns channels and speech.
  • network owns client descriptors, Telnet, sockets, and event scheduling.
  • persistence owns SQLite-backed MUX data.
  • lua owns the Lua runtime integration.
  • help owns indexing, rendering, and command handlers for the markdown help system (see Help system).

Project code includes MUX interfaces through paths rooted at mux/; it does not depend on the include-directory search order. Types exposed by MUX use descriptive PascalCase names. Functions use snake_case, and implementation details remain private to their owning module unless another translation unit needs them.

Large subsystems use several translation units instead of collecting unrelated operations in one source file. Command registration, dispatch, configuration, listing, builder operations, state inspection, and examination are separate; channels separate delivery, aliases, management, presence, and administration; networking separates timing, output, connection lifecycle, commands, and site access; and SQLite and Lua code separate their schemas or runtimes from loading, storage, callbacks, scheduling, flows, and bindings. Headers ending in _internal.h are private contracts between translation units in one subsystem and must not be included by other subsystems.

Object flags and powers are represented by individual boolean fields in memory and matching SQLite columns. Flags use has_*_flag names and powers use has_*_power names; command names omit those storage-oriented affixes (for example, idle maps to has_idle_power).

Mutable resources should be owned by a named subsystem or by the operation that uses them. For example, each help article index is an independently created HelpIndex, while wildcard captures and lock parser/serializer state are scoped to a single call. New code should pass these owners or operation contexts explicitly instead of adding mutable file-scope state. Immutable lookup tables may remain static const.

MuxServer is the process composition root. It creates and destroys the long-lived resources in dependency order:

OwnerContains or depends onPassed to
MuxServerConfiguration, BtechContext, and all owners belowStartup and shutdown
GameDatabaseObject array, cached names, native subsystem state, exact-name Lua storage, allocation bounds, freelist, and mark bufferDatabase, persistence, world, and command code
PersistenceContextBorrowed configuration, database, channels, macros, snapshot counters, and an owned bounded SQLite extension registrySnapshot loading and writing
MacroRegistryPlayer macro sets and their capacityMacro commands and commac persistence
ChannelRegistryChannel-name index and channel countComsys commands and commac persistence
CommandRegistryBuilt-in commands, prefixes, and player macrosCommand dispatch and configuration aliases
WorldIndexesFlag, power, and player indexesObject, world, and command modules
AccessControlStoreAllowed, forbidden, and suspect sites plus disallowed player namesConfiguration, connection, and player creation paths
WorldContextBorrowed database, configuration, world indexes, access-control store, and descriptor registryObject, matching, lock, and world-facing command operations
ObjectListResults for one search or wildcard-attribute operationCreated and destroyed by the calling operation
MapTextOne rendered tactical-map buffer and its line viewCreated and destroyed by the map or navigation command
MuxEventSchedulerTimed BTech event lists, type index, recycled events, and tickBTech event producers and lifecycle shutdown
RuntimeClockCurrent time, maintenance deadlines, event cadence, and memory-usage samplesTimers, queues, descriptors, and status commands
ConfigurationContextBorrowed configuration, database, log, command and world registries, world context, and administrative notification contextStartup configuration parsing and runtime configuration commands
ServerControlBorrowed configuration, database, log, descriptors, player cache, persistence, lifecycle, and diagnostic command contextDatabase dumps, shutdown, and signal handling
ConnectionRuntimeBorrowed configuration, clock, descriptor registry, log, access control, and file-cache owner slotTelnet listeners and accepted connections
MaintenanceContextBorrowed server control, connection runtime, configuration, clock, descriptors, queues, player cache, background command, Lua services, and Lua owner slotServerLifecycle and ServerTimer
ServerLifecyclelibuv loop, service timers, signals, sockets, and one borrowed MaintenanceContextTimers, sockets, and event producers
DescriptorRegistryActive client descriptorsNetwork, Lua, cache delivery, and connection commands
CommandQueuePer-object and timed-wait queues plus a narrow borrowed CommandQueueDependencies service viewLifecycle ticks and command producers
CommandContextPlayer, enactor, descriptor, matching state, borrowed world/log/BTech services, and one EvaluationContextInteractive and queued command dispatch
CommandRuntimeBorrowed command-facing services, configuration and server-control capabilities, reloadable Lua owner slot, and process status valuesCommandContext and EvaluationContext without exposing MuxServer
CommandInvocationParsed command identity, arguments, vectors, and current CommandContextUniform typed command handlers
EvaluationContextNotification depth and borrowed world/log/BTech servicesNative commands and notifications
LuaServicesBorrowed configuration, database, descriptors, command queue, clock, background notification context, log, and process countersLuaRuntime without exposing CommandRuntime or MuxServer
LuaRuntimeLua state, loaded modules, schedules, sandbox package, and one borrowed LuaServices viewLua commands, events, flows, and maintenance ticks
ServerLogLogging configuration, recursion depth, timestamp scratch space, and arbitrary-file cacheProcess-wide logging entry points
LoginThrottleRecent failed-login windowsConnection flow
PlayerCachePer-player queue accountingQueue and player operations
FileCacheConnect, reject, quit, and rotating connection textNetwork and file-list commands
HelpIndexParsed article metadata rooted at one help directoryHelp rendering and commands

Core MUX and BTech source files no longer access the old mudstate or mudconf aliases. Context headers mark non-owning members as borrowed; their destroy functions must never release those dependencies. Compact concrete owner types with public layouts are embedded in MuxServer; opaque owners and the large heap-resident ServerConfiguration are held through pointers and use paired *_create/*_destroy functions. LuaOwner provides a stable, explicitly typed owner slot: reload replaces its runtime while queued flows retain a stable reference to the wrapper.

Only composition and startup functions accept MuxServer *. Runtime modules receive the narrow borrowed context they need: configuration code cannot reach network ownership, socket acceptance cannot reach persistence, and command control paths cannot recover the composition root. Source files include these context interfaces directly instead of using mux_server.h as an aggregate dependency header.

MuxServer owns a narrow BtechContext for BTech runtime services and legacy callback objects. In addition to borrowing core MUX services, this context owns the BTech special-object registry, special command indexes, map-coding cache, part-name registry, lazily populated template filename registry, combat overrides, advanced-economy part costs, heartbeat timer state, random-generator state and roll statistics, startup-resolved missile cluster indexes, wizard-adjustable weapon recycle/BV settings, and update timestamps. Those resources are released explicitly before the event scheduler during server teardown. Canonical weapon definitions remain immutable; runtime overrides are isolated in the context-owned settings array. Interactive and queued dispatch push a checked BtechCommandScope while invoking BTech code; nested command execution restores the previous scope in LIFO order instead of manually swapping one mutable command pointer. Persistence extensions retain their subsystem-specific borrowed context explicitly, so BTech snapshot code does not use the unthreaded accessor. The command table itself dispatches through typed CommandInvocation handlers, so it no longer stores incompatible function pointers. BTech notification, lock, menu, and guard helpers now take their BtechContext or EvaluationContext explicitly; the process-global unthreaded accessor and ambient evaluation macro have been removed. Linting rejects either compatibility seam if it returns. New and converted APIs take the narrow owner or operation context they require. Callback and traversal APIs likewise carry an explicit operation context, so path scoring, radio relay searches, status menus, neighboring-hex visits, debug-memory walks, and persistence event visits keep their scratch state on the initiating call rather than at file scope. BTech status, armor, weapon, target, and scan-report renderers receive their EvaluationContext explicitly; only legacy command and notification entry points resolve the checked current command scope.

Long-lived mutable process ownership is now concentrated at the POSIX signal-handler dispatch bridge. Compiled BTech formatting paths no longer use function-local static result buffers: formatters either return small values or write into storage owned by the enclosing operation. This includes xcode value callbacks, status renderers, menu callbacks, generated part names, attribute reads, mech identifiers, and unit-parts summaries. Random-generator state and its roll statistics, startup-resolved missile cluster indexes, map coding, and generated part-name indexes are explicit BtechContext owners, while artillery and map-object recycler lists have been replaced by direct scheduler or allocation ownership. Player map colors are caller-owned render state, and the LOS tracer writes into an operation-owned LosTrace instead of sharing a process-static coordinate array. Template filename and reference-mech caching have explicit BtechContext lifetimes. Tactical map rendering returns an owned MapText instead of reusing static sketch and colorization buffers. Advanced-economy prices are also owned by that context; persistence receives only a short-lived read view of their canonical part ranges. Repair-job tables and map-link update counters are caller-owned command scratch. Turret, weapon-recycle, and physical-XP overrides are grouped under BtechContext instead of shared by the process. Keeping that distinction explicit prevents unavoidable boundary state from becoming a justification for new ambient state.