docs(modules): mirror the uMod/Oxide ecosystem for module-rust #248

Merged
whitlocktech merged 2 commits from docs/rust-oxide-api into main 2026-09-15 15:21:01 +00:00
Member

What

A new docs/modules/rust/ holding a verbatim mirror of the uMod/Oxide documentation — the Rust
game API and the game-independent plugin framework around it — captured 2026-09-15, so the
upcoming module-rust can be designed and built without a round trip to umod.org on every question.

File Contents
modules/rust/README.md Orientation — why it exists, how Oxide hooks bind, provenance, capture procedure
modules/rust/HOOKS.md What Rust tells you — 477 hooks, 20 categories, 34 marked universal
modules/rust/OXIDE_API.md How a plugin is built — the 19 developer pages
modules/rust/DEFINITIONS.md What things are called — 678 items, 2,590 skins
modules/rust/OPERATING.md How it gets run — the 6 operator pages
modules/rust/agent/ The same facts in machine shape — TSV/JSONL at ~46% of the tokens

25 prose pages, 477 hooks, 678 items, 2,590 skins, 150 code examples.

Why both halves

rust-dryrun.md's central structural fact drives the
shape: a ServUO shard is source the operator compiles, but a Rust server is a binary nobody
outside Facepunch patches.
Two consequences, and they are the two halves of the directory:

  1. We can only emit what Oxide hands us. HOOKS.md is the hard ceiling on what a Rust module
    can ever know about a live server — the input to the Rust sidecar's event catalogue.
  2. We are a guest in someone else's plugin framework. Our plugin is compiled, loaded,
    permissioned and configured by Oxide, on Oxide's terms. OXIDE_API.md is that rulebook;
    OPERATING.md is what the server owner has to do, which is the surface our deployment story has
    to sit on.

The universal-hook split

34 of the 477 are not Rust's — they are uMod's own Covalence hooks (Init, Loaded, Unload,
OnUserConnected, the OnGroup*/OnUserPermission* families), raised identically on every game
uMod supports. Verified against /documentation/games/universal in the same capture: all 34 are in
the Rust set and the Rust page adds none of its own, so the overlap is exact.

The distinction is architectural, not trivia — a universal hook is the portable part of the
surface.
Marked in HOOKS.md, flagged 1 in agent/hooks.tsv.

agent/ — the token-efficient copy

Same facts, generated in the same pass so it cannot drift from the markdown.

File Rows ~tokens vs. markdown
hooks.tsv 477 ~19.6k 31%
items.tsv 678 ~6.9k 80%
skins.tsv 104 (2,590 skins) ~17.9k 77%
api.jsonl 150 ~7.8k 47%
Total ~52k 46%

hooks.tsv normalises the return contract to five codes (none / nonnull / bool / data /
?) so an agent can filter on it. api.jsonl is every code example uMod publishes, addressed by
page and heading.

Where the win is, honestly. Large for hooks (3.2×) and API prose (2.1×), because both are mostly
explanation. Only ~1.25× for the item and skin tables, because DEFINITIONS.md was already dense.
agent/README.md says exactly that rather than quoting a flat number.

Two things worth recording from building it

  • The first skins.tsv was 11% larger than the markdown it replaces. One row per skin means
    repeating the item shortname 2,590 times, which costs more than the markdown's grouped headings.
    Regrouping to one row per item is what made it a saving at all. Measured, not assumed.
  • Signature extraction by brace depth silently captured body lines. A nested } inside
    OnUserConnected's example ended the block early, so a Puts(...) line was recorded as a hook
    signature. It now matches on the hook's own name; all 477 rows verified to carry a real signature
    and none to contain a body line.

Faithfulness

  • OnShopCompleteTrade is two records upstream. Both kept; second anchored #onshopcompletetrade-1.
  • Three hooks state no return behaviour upstream at all — marked (not stated upstream) / ?
    rather than guessed.
  • Twelve hooks document more than one overload; every block reproduced.
  • All internal links and anchors across all six markdown files validated: 0 broken. No leftover
    raw HTML or unescaped entities in the converted pages.

Capture procedure

Recorded in the README because none of it was obvious. Cloudflare gates uMod's HTML pages but not
its JSON endpoints, so it took three different routes: a plain curl for hooks
(/documentation/hooks/rust.json, one request, no paging), a rendered browser DOM for the
definitions tables, and throttled same-origin fetches for the prose pages — uMod returns
429 Too Many Requests on a tight loop, and a 429 is easy to mistake for a real page
because it
still returns 200-shaped HTML with a title.

Rust wipes monthly and the hook list moves with it, so every file carries its capture date.

Scope

Docs only — no code, no contract changes. The mirror is reference, not authority: uMod stays
upstream and normative, and nothing here may be cited as a Runic Gateway contract.

Deliberately not mirrored, and the README says why: the other games uMod supports (not our
ecosystem), the community/process pages, and the /documentation/umod/* alias paths.

docs/README.md gains one row in the modules/ table. One pre-existing broken link in that README
(android/TRUSTED_DEVICES_APP_HANDOFF.md) was left alone as out of scope.


  • AI-assisted: written with Claude Code (Claude Opus 5)

🤖 Generated with Claude Code

https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4

## What A new `docs/modules/rust/` holding a **verbatim mirror of the uMod/Oxide documentation** — the Rust game API *and* the game-independent plugin framework around it — captured 2026-09-15, so the upcoming `module-rust` can be designed and built without a round trip to umod.org on every question. | File | Contents | |---|---| | `modules/rust/README.md` | Orientation — why it exists, how Oxide hooks bind, provenance, capture procedure | | `modules/rust/HOOKS.md` | **What Rust tells you** — 477 hooks, 20 categories, 34 marked universal | | `modules/rust/OXIDE_API.md` | **How a plugin is built** — the 19 developer pages | | `modules/rust/DEFINITIONS.md` | **What things are called** — 678 items, 2,590 skins | | `modules/rust/OPERATING.md` | **How it gets run** — the 6 operator pages | | `modules/rust/agent/` | The same facts in **machine shape** — TSV/JSONL at ~46% of the tokens | 25 prose pages, 477 hooks, 678 items, 2,590 skins, 150 code examples. ## Why both halves [`rust-dryrun.md`](../src/branch/main/modules/rust-dryrun.md)'s central structural fact drives the shape: a ServUO shard is source the operator compiles, but **a Rust server is a binary nobody outside Facepunch patches.** Two consequences, and they are the two halves of the directory: 1. **We can only emit what Oxide hands us.** `HOOKS.md` is the hard ceiling on what a Rust module can ever know about a live server — the input to the Rust sidecar's event catalogue. 2. **We are a guest in someone else's plugin framework.** Our plugin is compiled, loaded, permissioned and configured by Oxide, on Oxide's terms. `OXIDE_API.md` is that rulebook; `OPERATING.md` is what the server owner has to do, which is the surface our deployment story has to sit on. ## The universal-hook split **34 of the 477 are not Rust's** — they are uMod's own Covalence hooks (`Init`, `Loaded`, `Unload`, `OnUserConnected`, the `OnGroup*`/`OnUserPermission*` families), raised identically on every game uMod supports. Verified against `/documentation/games/universal` in the same capture: all 34 are in the Rust set and the Rust page adds none of its own, so the overlap is exact. The distinction is architectural, not trivia — **a universal hook is the portable part of the surface.** Marked in `HOOKS.md`, flagged `1` in `agent/hooks.tsv`. ## `agent/` — the token-efficient copy Same facts, generated in the same pass so it cannot drift from the markdown. | File | Rows | ~tokens | vs. markdown | |---|---:|---:|---:| | `hooks.tsv` | 477 | ~19.6k | **31%** | | `items.tsv` | 678 | ~6.9k | 80% | | `skins.tsv` | 104 (2,590 skins) | ~17.9k | 77% | | `api.jsonl` | 150 | ~7.8k | **47%** | | **Total** | | **~52k** | **46%** | `hooks.tsv` normalises the return contract to five codes (`none` / `nonnull` / `bool` / `data` / `?`) so an agent can filter on it. `api.jsonl` is every code example uMod publishes, addressed by page and heading. **Where the win is, honestly.** Large for hooks (3.2×) and API prose (2.1×), because both are mostly explanation. Only ~1.25× for the item and skin tables, because `DEFINITIONS.md` was *already* dense. `agent/README.md` says exactly that rather than quoting a flat number. ## Two things worth recording from building it - **The first `skins.tsv` was 11% *larger* than the markdown it replaces.** One row per skin means repeating the item shortname 2,590 times, which costs more than the markdown's grouped headings. Regrouping to one row per item is what made it a saving at all. Measured, not assumed. - **Signature extraction by brace depth silently captured body lines.** A nested `}` inside `OnUserConnected`'s example ended the block early, so a `Puts(...)` line was recorded as a hook signature. It now matches on the hook's own name; all 477 rows verified to carry a real signature and none to contain a body line. ## Faithfulness - `OnShopCompleteTrade` is **two** records upstream. Both kept; second anchored `#onshopcompletetrade-1`. - Three hooks state no return behaviour upstream at all — marked *(not stated upstream)* / `?` rather than guessed. - Twelve hooks document more than one overload; every block reproduced. - All internal links and anchors across all six markdown files validated: **0 broken**. No leftover raw HTML or unescaped entities in the converted pages. ## Capture procedure Recorded in the README because none of it was obvious. Cloudflare gates uMod's HTML pages but **not** its JSON endpoints, so it took three different routes: a plain `curl` for hooks (`/documentation/hooks/rust.json`, one request, no paging), a rendered browser DOM for the definitions tables, and throttled same-origin fetches for the prose pages — **uMod returns `429 Too Many Requests` on a tight loop, and a 429 is easy to mistake for a real page** because it still returns 200-shaped HTML with a title. Rust wipes monthly and the hook list moves with it, so every file carries its capture date. ## Scope Docs only — no code, no contract changes. The mirror is **reference, not authority**: uMod stays upstream and normative, and nothing here may be cited as a Runic Gateway contract. Deliberately not mirrored, and the README says why: the other games uMod supports (not our ecosystem), the community/process pages, and the `/documentation/umod/*` alias paths. `docs/README.md` gains one row in the `modules/` table. One pre-existing broken link in that README (`android/TRUSTED_DEVICES_APP_HANDOFF.md`) was left alone as out of scope. --- - [x] AI-assisted: written with Claude Code (Claude Opus 5) 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
wtclaude added 1 commit 2026-09-15 14:39:28 +00:00
Mirrors uMod's Rust game API into docs/modules/rust/ so the upcoming
module-rust can be designed against it without a round trip upstream.

- HOOKS.md: all 477 hooks in 20 categories, scraped verbatim from
  umod.org/documentation/games/rust. Each entry keeps its description,
  its return contract, its tags and every C# overload uMod publishes.
  Opens with a category table and a full alphabetical index
  (name -> category -> return contract).
- DEFINITIONS.md: 678 items (short name, item id, display name) and
  2,590 workshop skin ids across 104 items.
- README.md: why the reference exists, how an Oxide hook actually binds
  (by name and arity, by reflection - a typo is silently never called),
  the four return contracts, and how the bridge invariants restate
  against Oxide. Records provenance and the exact refresh procedure:
  the hooks JSON endpoint is not Cloudflare-gated even though the HTML
  page is, and the definitions page has to come out of a browser.

The mirror is reference only - uMod stays upstream and normative, and
nothing here is a Runic Gateway contract. Rust wipes monthly, so both
files carry their capture date (2026-09-15) and a re-capture note.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
wtclaude added 1 commit 2026-09-15 15:01:32 +00:00
Completes the uMod mirror beyond the Rust hook table, and adds agent/ — the
same facts in TSV/JSONL at ~46% of the tokens.

New prose:
- OXIDE_API.md: the 19 developer pages under umod.org/documentation/api/ —
  plugin structure, hooks, commands, IPlayer, permissions, config, data files,
  database, localization, timers, web requests, dependencies, integration,
  preprocessor directives, security, style guide, CI, review. This is the
  framework our plugin is a guest in, where HOOKS.md is what the game says.
- OPERATING.md: the 6 operator pages — installing Oxide on a server, then
  installing, configuring and permissioning plugins.

New machine-readable set (agent/):
- hooks.tsv    477 rows, ~31% of HOOKS.md
- items.tsv    678 rows, ~80% of DEFINITIONS.md's item table
- skins.tsv    104 rows covering 2,590 skins, ~77%
- api.jsonl    150 code examples, ~47% of the two prose docs
Generated in the same pass as the markdown, so the two cannot drift.

HOOKS.md gains the universal-hook split: 34 of the 477 are uMod's own
Covalence hooks, raised identically on every game uMod supports. Verified
against /documentation/games/universal in the same capture - all 34 are in
the Rust set and the Rust page adds none of its own, so the overlap is exact.
The distinction is architectural: a universal hook is the portable part of
the surface.

Two things worth recording from building it:
- The first skins.tsv was one row per skin and came out 11% LARGER than the
  markdown it replaces. Grouping it one row per item is what made it a
  saving. The token win is real for prose (3.2x on hooks) and small for
  tables that were already dense - agent/README.md says so plainly rather
  than claiming a flat number.
- Signature extraction by brace depth silently captured body lines (a nested
  '}' in OnUserConnected's example ended the block early). It now matches on
  the hook's own name; all 477 rows verified to carry a real signature.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
wtclaude changed title from docs(modules): add the Rust Oxide/uMod API reference for module-rust to docs(modules): mirror the uMod/Oxide ecosystem for module-rust 2026-09-15 15:01:59 +00:00
whitlocktech merged commit c487b8fd8c into main 2026-09-15 15:21:01 +00:00
whitlocktech deleted branch docs/rust-oxide-api 2026-09-15 15:21:02 +00:00
Sign in to join this conversation.
No description provided.