Files
Rust-Plugins/overlay.toml
wtclaude adb9df6a2e
All checks were successful
PR Checks / plugin-checks (pull_request) Successful in -1m55s
feat(bridge): Rust's own world events on protocol 14 (PLAN_REDESIGNS §14.3.1)
Stage 1 of the §14.3 integration plan: the patrol helicopter, Bradley, the
cargo ship, the Chinook, airdrops, locked crates, the Travelling Vendor, the
satellite and the Deep Sea, with no plugin (D349).

- `world.event`, one frame kind whose `event` names which of 24 types
  (PROTOCOL.md §20.5). The type is in `event`, never `type`: `type` is the
  envelope's, and the rig's sidecar dropped every world event as untyped when
  the plan's example put it there. Nothing is said before the world loads or
  while the server quits. Positions are x/z; the site works out the grid.
- Credit (D372, D379): a damage table for the patrol helicopter, the Chinook
  and Bradley; `heli.downed`, `chinook.downed` and `bradley.destroyed` carry
  every candidate (blow, last, most, damagers) and the plugin credits nobody.
  D174's `CreditVehicle` and the tally's apcKills/heliKills are gone.
- Locked crates told positively (oil rigs, cargo, ghost ship, a Chinook drop
  joined at the crate's landing); anything else says nothing. A Bradley's
  `where` comes from the game's spawners, not `RoadSpawned` (which defaults to
  true). `airdrop.called` comes from the cargo plane's spawn: `supply.call`
  raised neither OnAirdrop nor OnCargoPlaneSignaled.
- The tally gains cratesHacked and dropsLooted (Safecracker, Scavenger, D356).
- `world.call` (D354, D367, D378): one of a schedule's TriggeredEvents at
  random, without Trigger (which would reset its clock); satellite.random for
  the satellite. A position for the airdrop (InitDropPosition) and the patrol
  helicopter (SetInitialDestination) only, both set before the spawn, as the
  stage-1 spike measured (0-1 m and 10-54 m). Kept; the key is remembered seven
  days in world-calls.json; EventsMaxWorldCalls (default and ceiling 10) per run.
- Hello/status `console.plugins` (D363): the bridge runs its own rg.probe
  through ConsoleSystem.Run from a timer. Carbon 2.0.262 refuses plugin
  commands only inside a console command (or a NextTick one queued), which is
  how §14.2's spike tested; from a timer, and from the link reader's NextTick,
  it finds them. Reads true on both rigs.
- checkPlugin.js: the probe must name a [ConsoleCommand] the plugin declares.

Compiled and loaded on both rigs (Rust 25902425, Oxide 2.0.7830, Carbon
2.0.262); heli.arrived, cargo.arrived and airdrop.called read back from each
rig's sidecar store. Rigs restored. 18 check tests pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
2026-10-15 00:39:00 -05:00

101 lines
6.0 KiB
TOML

# Release metadata for the deployable overlay.
#
# Consumed by the release workflow, which folds these values into the
# manifest.json shipped inside the overlay tarball. The Runic Gateway installer
# reads that manifest to decide what it is deploying and whether it is compatible
# with the sidecar it is about to install.
#
# There is deliberately NO version key here. The release version is derived from
# git tags and conventional commits by the release workflow, so there is no bump
# commit to keep in sync and no way for this file to disagree with the tag.
# ── The loopback wire-protocol version this overlay speaks ───────────────────
#
# The plugin half of the compatibility contract. It MUST equal the sidecar's
# PROTOCOL_VERSION (Rust-Link's sidecar/src/main.rs) for a deployment to work:
# the sidecar rejects a mismatched WEBSITE with 409, and a mismatched PLUGIN is
# worse, because the game link has no such check — it would simply mis-parse.
#
# That asymmetry is why this file exists. The plugin announces its protocol in
# `server.hello`, which is only readable after the game server has booted with it
# loaded — far too late for an installer to refuse a bad pairing. This
# declaration is what lets the bundle CI check the pair BEFORE an operator
# installs either half.
#
# Keeping it honest is a manual duty: when the protocol changes, bump it here in
# the same change that alters the emitters, exactly as the sidecar bumps
# PROTOCOL_VERSION and the module bumps its own constant.
#
# Current: 14 — the transport, the read path, identity, the permission mirror,
# configuration from the site, first-party clans, a raid frame that names who
# lives there, the event leases, the world verbs events place and give back, and
# the rewards: a run's participation tally, kit credits and chat (PROTOCOL.md §16),
# the map: its picture and everything that moves on it (PROTOCOL.md §17), and the
# optional mods: BetterChat titles and group styles, and popups (PROTOCOL.md §18),
# and the first player walk's fixes (PROTOCOL.md §19) — opened by a configuration
# save that answers at once and reports its reload as a `config.outcome` frame,
# and the step editor (PROTOCOL.md §20): `kits.uses`, and the one-time reward
# messages a `perm.sync` carries as `notices`; and Economics (PROTOCOL.md §20.3):
# `economics.pay`, `economics.balances`, `economics.adjust`, the tally's
# `balance` and the `economics.wiped` event; and Backpacks (PROTOCOL.md §20.4):
# `backpacks.read` and hello's `integrations.backpacks.sizes`; and Rust's own world
# events (PROTOCOL.md §20.5): `world.event` with its `event`, `world.call`, hello's
# `console`, and the tally's `cratesHacked` and `dropsLooted` in place of `apcKills`
# and `heliKills`.
protocol = 14
# ── Oxide compatibility ──────────────────────────────────────────────────────
#
# The overlay only ADDS files — the bridge, and beside it the ZoneManager helper
# (`RunicGatewayZones.cs`, docs/modules/rust/PLAN_FIXES.md D181, D182), both into
# `oxide/plugins/` — and patches nothing on disk, so it is expected to work on any
# reasonably current Oxide. The helper patches ZoneManager in memory with Harmony,
# which both frameworks load; without it the bridge still loads and falls back.
# This is the oldest build it is known good on.
#
# There is no `patches_verified_against` key, and there is no `patches/` tier:
# Rust's server is a binary and Oxide's hook API is the supported way in, so
# there is nothing to diff against. That is the whole reason the Rust payload is
# simpler than the ServUO one.
min_oxide_version = "2.0.7585"
# ── Carbon compatibility ─────────────────────────────────────────────────────
#
# The same file runs unchanged on Carbon (docs/modules/rust/PLAN.md R19); the
# installer and the egg decide whether it lands in `oxide/plugins/` or
# `carbon/plugins/`. This is the build R19 was proven on (PLAN.md §34.4).
#
# Neither floor is measured from a DLL by `doctor`: a plugin that compiled and
# connected on this framework is the fact a floor only approximates, so a
# connected plugin is the pass, and the floors are printed with any failure.
min_carbon_version = "2.0.259"
# The `oxide/plugins/` files this overlay expects to find already installed. They
# are not shipped here — they are third-party plugins an operator installs from
# uMod — and the installer's `doctor` reports a missing one rather than
# installing it. Listing them is what turns a missing reward or zone into a
# named prerequisite.
#
# The uMod **Clans** plugin is deliberately NOT listed (docs/modules/rust/PLAN.md
# D47). Teams come from Rust's own clan system, which that plugin never touches,
# so requiring it would split a server's players across two unrelated clan
# systems. Phase 17 dropped the adapter it was meant to get (D134).
#
# **PopupNotifications is not listed either** (D141). It is optional: a popup
# asked of a server without it is refused with a reason, and chat is the default.
# BetterChat is optional in the same way — titles and group styles wait for it.
requires_plugins = ["Kits", "ZoneManager"]
# ── The RunicNPC API the bridge needs ───────────────────────────────────────
#
# RunicNPC (docs/runicnpc/PLAN.md stages 4 to 7): the bridge's npc.* commands call
# RunicNPC's API and need at least this version of it. It MUST equal
# `RunicNpcApiNeeded` in RunicGateway.cs; `node scripts/checkPlugin.js` holds the
# two equal. The release copies it into manifest.json, and the installer's
# bundle carries the latest RunicNPC release that answers at least it (D224).
#
# RunicNPC is required since its stage 9 (D310): without it, or with one older
# than this, every npc.* command and every NPC an event places, Rust's own
# scientists included, is refused as `runicnpc-missing` or `runicnpc-old`.
runicnpc_api = 6