feat(bridge): console commands as event steps — command.run (PLAN_REDESIGNS §16)

A `command.run` frame (protocol 14, PROTOCOL.md §20.11) runs the console
commands a step's author typed: once, or once per online recipient with
{steamid} and {name} filled in (the name quoted the way the game's own
BuildCommand quotes an argument). D382-D384: no allowlist; offline
recipients are skipped and named.

- At most once per key: the key is written to commands-run.json before
  anything runs; a repeat answers from the record, a repeat while running
  joins the running job, a record a reload interrupted answers
  `interrupted`. Kept 7 days, at most 500 records.
- Spread over frames: whole recipients per frame, up to 30 commands or 8 ms.
- unknown-command: ConsoleSystem.Run returns null both for an unknown command
  and for one that replies nothing, so the run listens to Unity's log for the
  game's own "Command '...' not found" line while each command runs (spiked
  on Oxide 2.0.7830 and Carbon 2.0.262, Rust 25902425). The same capture is
  the reply when Run returns nothing.
- rg.world shows commandKeys and commandsRunning.

Compiled on both rigs and driven through a throwaway plugin (repeat key,
unknown command, offline recipients, malformed requests); rigs restored to
the protocol-13 bridge.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
This commit is contained in:
2026-10-16 02:30:59 -05:00
parent 9c99aceb65
commit b52b8a8f80
2 changed files with 602 additions and 1 deletions

View File

@@ -138,6 +138,15 @@ nivex's `ZLevels Remastered` is optional, and the bridge only says whether it is
never read or sent. Its XP boosts are its own permissions (`zlevelsremastered.vip1` to `vip3`), so an
event lends one as it lends any other permission, and it takes effect at once.
An event can also run console commands an admin typed (`command.run`): once, as a step, or once for each
recipient of a reward who is online, with `{steamid}` and `{name}` filled in (the name as one quoted
argument). That is how a plugin with no support of its own here is used from an event, for example
RaidableBases' `rbe`. There is no allowlist: the site's switchboard is the switch, and `EventsEnabled`
here is the server's. Each request runs at most once: its key is written to
`data/RunicGateway/commands-run.json` before anything runs, and is kept for seven days. A command the
server does not know stops the request there as `unknown-command`. On a framework with
`consolePlugins=False`, that is every plugin's command.
Rust's own world events need no plugin at all. The patrol helicopter, Bradley, the cargo ship, the
Chinook, airdrops, locked crates, the Travelling Vendor, the satellite and the Deep Sea reach the
site's feed and its event triggers on every server, and an event can call one of them (`world.call`).