Generated reference. This page mirrors
Code/Commands/README.md, this module's source-of-truth documentation (Standards/02_DOCUMENTATION_STANDARDS.md §1). Edit it there, not here -- this file is regenerated on every docs build and any local edit is silently overwritten.
Commands¶
Purpose. One registration point for every chat-typed player action: registry, access- gated dispatch, a global veto hook, and help generated from the same registration a command lives on. See 15_COMMANDS_FRAMEWORK.md.
Responsibilities.
- CommandDefinition / CommandContext — a code-registered command: name, required
permission, minimum argument count, usage/category/help text, and its Execute delegate.
Execute is Func<CommandContext, Task<Result>> — async because a real command's body
typically needs persistence I/O (fixed once /team, Jobs' own first real command, needed
to actually await one; /help's synchronous body never exercised this). A synchronous
body wraps its result in Task.FromResult. /give (Code/Inventories/InventoryModule.cs,
Milestone 10) is this framework's first command with a non-null RequiredPermission --
the gating itself is CommandDispatchComponent.RequestExecuteCommand's job, untested here
for the same reason that whole component is (thin, engine-facing -- see
OfflineTests/OfflineTests.csproj's exclusion list).
- ICommandRegistry / CommandRegistry — register once at module boot, read many times;
case-insensitive name lookup; a duplicate name is a thrown exception at boot, never a
silent overwrite.
- CommandExecuting — the global veto hook, a CancellableEvent published before a
command's Execute runs, replacing legacy's PlayerCanUseCommand.
- CommandDispatchComponent — the one [Rpc.Host] entry point per character:
RequestExecuteCommand(string name, string[] arguments). Identity, existence, state,
access, and argument-count checks; publishes CommandExecuting; logs every attempt
(refused or not) with its full argument text; replies to the caller's own connection with
the outcome via ReceiveCommandReply (Rpc.FilterInclude(Connection)) — see
15_COMMANDS_FRAMEWORK.md §4.
- CommandsModule — registers ICommandRegistry and /help, the framework's own proof
that registration → dispatch → help all agree. Also registers HelpTab
(Code/Commands/Ui/HelpTab.razor, Milestone 11) against IMenuRegistry — the player
menu's Help tab, which groups ICommandRegistry.All by Category rather than duplicating
/help's own text
(24_PLAYER_MENU.md §8).
Not responsible for.
- Turning a typed /command arg1 arg2 chat line into the (name, string[])
RequestExecuteCommand expects. That's Code/Chat/Ui/ChatPanel.razor's job — this module
only defines what it expects to receive and how to reply to it.
- Typed-parameter binding. CommandContext.Arguments is raw IReadOnlyList<string>;
each command parses what it needs. Reflection- or source-gen-based binding is a real
feature on the scale of its own design pass, not built here — see
15_COMMANDS_FRAMEWORK.md §4.
- The other 65 legacy commands. Almost every one acts on a system that doesn't exist yet
(Jobs, Crime, Property beyond doors, Chat channels, admin player-targeting) — see
15_COMMANDS_FRAMEWORK.md §7.
They land alongside whichever milestone item builds each one's dependency.
- Filtering /help's output by the caller's own permissions. Shows every registered
command regardless of who's asking — a minor information leak (an admin-only command's
existence is visible), not a security one (RequiredPermission still gates running it).
Dependencies. Core (IServiceRegistry, IServiceResolver, IEventBus, IGameLog,
Result), Character (Character, PermissionSet.Has via HasPermission, for access checks
and dispatch identity), Ui (IMenuRegistry, for HelpTab's registration).
Public API.
- ICommandRegistry — Register(CommandDefinition), Find(string), All.
- CommandDefinition, CommandContext, CommandExecuting.
- CommandDispatchComponent.RequestExecuteCommand(string, string[]), .ReceiveCommandReply
(server-called, client-received), .CommandReplyReceived (the static event a UI panel
subscribes to).
- HelpTab — the player menu tab; not called directly by anything outside IMenuRegistry's
own instantiation.
Events published. CommandExecuting (cancellable), before every command's Execute.
Persistence. None — commands are code, not saved state.
Future improvements.
- Typed-parameter binding, once a second or third real command needs more than raw strings.
- /help filtered by the caller's own permissions.
- The remaining legacy commands, one per milestone item that builds their dependency.