docs(rust-link): bring INTEGRATION.md up to protocol 14 and name all three helpers #370

Merged
whitlocktech merged 1 commits from docs/rust-link-integration-refresh into main 2026-10-22 15:26:17 -05:00
2 changed files with 39 additions and 24 deletions

View File

@@ -11,7 +11,7 @@ speaks one protocol, never "the latest of each" — and a third, RunicNPC, which
| Component | What it is | Released from |
|---|---|---|
| **The plugin** | `RunicGateway.cs`, one file that runs unchanged on Oxide and Carbon — and beside it, from protocol 13, the optional **ZoneManager helper** `RunicGatewayZones.cs` (PLAN_FIXES D181, D182), installed by default | [Rust-Plugins](https://gitea.whitlocktech.com/RunicGateway/Rust-Plugins/releases) |
| **The plugin** | `RunicGateway.cs`, one file that runs unchanged on Oxide and Carbon — and beside it three optional helpers, each installed by default: the **ZoneManager helper** `RunicGatewayZones.cs` (from protocol 13, PLAN_FIXES D181, D182), the **domes helper** `RunicGatewayDomes.cs` (PLAN_REDESIGNS D194) and the **raids helper** `RunicGatewayRaids.cs` (PLAN_REDESIGNS D204) | [Rust-Plugins](https://gitea.whitlocktech.com/RunicGateway/Rust-Plugins/releases) |
| **The sidecar** | `rust-link-sidecar`, which the plugin dials on loopback and the website reaches over HTTP | [Rust-Link](https://gitea.whitlocktech.com/RunicGateway/Rust-Link/releases) |
| **RunicNPC** | `RunicNPC.cs`, Runic Gateway's NPC plugin ([`../runicnpc/PLAN.md`](../runicnpc/PLAN.md)), placed beside the bridge: the latest RunicNPC release that answers the API the bridge needs (D224). **Required** since RunicNPC's stage 9 (D310): without it the bridge refuses every NPC an event places, Rust's own scientists included, and Admin → Rust → Servers shows the server as incomplete. It needs **Kits**, like the bridge. Its own guide is [`../runicnpc/INSTALL.md`](../runicnpc/INSTALL.md) | [runicnpc-rust](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust/releases) |
@@ -179,7 +179,9 @@ history, and the token is unchanged.
events still score everybody, but ZoneManager's own flags miss that player, and an event zone's
flags such as PvpGod or NoBuild may not hold at all. The second is
`RunicGatewayDomes.cs`, which lets the bridge ask ZoneDomes for a dome over an event zone; leave it
out and zones open without one. To name the server, create its config first —
out and zones open without one. The third is `RunicGatewayRaids.cs` (PLAN_REDESIGNS §11.4, D204),
which lets an event spawn a RaidableBases base of its own and despawn only that base when the event
ends; leave it out and such a base despawns on RaidableBases' own timer. To name the server, create its config first —
`oxide/config/RunicGateway.json` or `carbon/configs/RunicGateway.json` — holding
`{ "ServerId": "<id>", "Port": 7799 }`. Without it, the plugin calls the server `main`.
4. **The sidecar:** put the binary somewhere stable and give it a config:

View File

@@ -4,9 +4,9 @@
how to tell which of the three is wrong when they are not. The contract itself is
[`PROTOCOL.md`](PROTOCOL.md).
There is no installer support for Rust yet — that is a later phase — so everything here is done by
hand. When the installer gains `--game rust`, this page becomes the fallback path rather than the
only one.
**To set a server up, use [`INSTALL.md`](INSTALL.md)**: the installer (`--game rust`), the
Pterodactyl egg, or its own by-hand path. This page walks the same pieces one at a time, by hand, and
is mostly useful for understanding them and for diagnosing a link that does not come up.
---
@@ -14,17 +14,23 @@ only one.
| Piece | Where it comes from |
|---|---|
| A Rust dedicated server with **Oxide** | umod.org |
| `RunicGateway.cs` | [Rust-Plugins](https://gitea.whitlocktech.com/RunicGateway/Rust-Plugins), `overlay/oxide/plugins/` |
| A Rust dedicated server with **Oxide** or **Carbon** | umod.org, or carbonmod.gg |
| `RunicGateway.cs`, and its helpers | [Rust-Plugins](https://gitea.whitlocktech.com/RunicGateway/Rust-Plugins), `overlay/oxide/plugins/` |
| `RunicNPC.cs` — **required** since RunicNPC's stage 9 (D310) | [runicnpc-rust](https://gitea.whitlocktech.com/RunicGateway/runicnpc-rust) |
| `rust-link-sidecar` | [Rust-Link](https://gitea.whitlocktech.com/RunicGateway/Rust-Link) |
| A Runic Gateway website with `module-rust` installed | [Module-Rust](https://gitea.whitlocktech.com/RunicGateway/Module-Rust) |
Take the plugin, RunicNPC and the sidecar from one bundle (`v2/rust/current.json` on the installer's
`bundles` branch), never "the latest of each": the bundle is what CI checked speaks one protocol.
**One game server, one sidecar, on that server's own host.** Six servers means six of the first two
pairs and six rows in the website's admin panel.
The module also expects four third-party Oxide plugins to be present for the features that follow
the bridge itself — `Clans`, `Kits`, `PopupNotifications` and `ZoneManager`, all from k1lly0u on
umod.org. The bridge works without them; the features that read them do not.
The bridge needs two third-party plugins from uMod for the features that follow it, **Kits** and
**ZoneManager**; it works without them, and the features that read them do not. **RunicNPC will not
load without Kits.** PopupNotifications is optional (D141), and so is everything
[`OPERATING.md`](../modules/rust/OPERATING.md) covers. The uMod **Clans** plugin is deliberately not
used (D47): a server's clans come from Rust's own clan system.
---
@@ -48,10 +54,13 @@ there is no second way to read it back.
```json
{
"component": "rust-link-sidecar",
"protocol": 1,
"version": "0.3.0",
"protocol": 14,
"config_path": "/etc/runicgateway/rust-main.toml",
"config_created": true,
"token_generated": true,
"game": { "bind": "127.0.0.1:7799", "server_id": "" },
"web": { "bind": "127.0.0.1:8090", "auth_token": "…", "ws_path": "/ws" },
"web": { "bind": "127.0.0.1:8090", "ws_path": "/ws", "auth_required": true, "auth_token": "…" },
"store": { "path": "/var/lib/runicgateway/rust-link.db" }
}
```
@@ -70,7 +79,7 @@ Check it:
```bash
curl http://127.0.0.1:8090/health
{"status":"degraded","protocol":1,"plugin_connected":false,"database":"ok","uptime":"0m","last_event":null}
{"status":"degraded","protocol":14,"plugin_connected":false,"database":"ok","uptime":"0m","last_event":null,"untyped_frames":0}
```
`degraded` with `plugin_connected: false` is exactly right at this point — nothing is connected yet.
@@ -81,18 +90,21 @@ curl http://127.0.0.1:8090/health
cp RunicGateway.cs /path/to/rust/oxide/plugins/
```
Oxide compiles and loads it on the write. Watch `oxide/logs/`:
Oxide compiles and loads it on the write. Watch `oxide/logs/` (Carbon: `carbon/plugins/` and
`carbon/logs/Carbon.Core.log`):
```
[Info] RunicGateway was compiled successfully in 2295ms
[Info] [Runic Gateway] protocol 1, serverId 'main', sidecar 127.0.0.1:7799
[Info] [Runic Gateway] protocol 14, serverId 'main', sidecar 127.0.0.1:7799
[Info] [Runic Gateway] connected to 127.0.0.1:7799
```
The first load also writes `oxide/config/RunicGateway.json`. Set `ServerId` before you go further:
The first load also writes `oxide/config/RunicGateway.json` (Carbon: `carbon/configs/`). Set
`ServerId` before you go further — or, better, create the file holding just `ServerId` and `Port`
before the first load, as the installer does. The plugin fills in every other key:
```json
{ "Host": "127.0.0.1", "Port": 7799, "QueueCap": 5000, "ServerId": "main" }
{ "Host": "127.0.0.1", "Port": 7799, "QueueCap": 5000, "ServerId": "main", "EventsEnabled": false, … }
```
**`ServerId` is this server's identity as the website knows it, and it is permanent.** It is not
@@ -102,20 +114,20 @@ not lose its history for it. Changing it later orphans everything recorded under
Now `/health` should read:
```json
{"status":"ok","protocol":1,"plugin_connected":true,"database":"ok","uptime":"2m","last_event":"…"}
{"status":"ok","protocol":14,"plugin_connected":true,"database":"ok","uptime":"2m","last_event":"…","untyped_frames":0}
```
If it does not, ask the game server:
```
rg.link
protocol=1 serverId=main connected=True depth=0 sent=3 dropped=0 received=2
connects=1 writeErrors=0 bootId=boot-20260915T194502Z
protocol=14 serverId=main connected=True depth=0 sent=3 dropped=0 received=2
connects=1 writeErrors=0 bootId=boot-20260915T194502Z wipeId=w-20260915T195817Z
```
### 2.3 The website
**Admin → Rust → add a server.** Four values:
**Admin → Rust servers** (`/admin/rust/servers`) **→ Add a server.** Four values:
| Field | Value |
|---|---|
@@ -128,14 +140,15 @@ connects=1 writeErrors=0 bootId=boot-20260915T194502Z
reports only whether one is set. A save that leaves the field blank keeps the stored one — so
renaming a server does not mean re-pasting a credential.
Then press **Test**, which probes the sidecar and reports what came back:
Then press **Test the sidecar**, which probes the sidecar and reports what came back — *The sidecar
answered (protocol 14).* on the page, from this answer:
```json
{ "ok": true, "status": "ok",
"sidecar": { "status": "ok", "protocol": 1, "plugin_connected": true, … } }
"sidecar": { "status": "ok", "protocol": 14, "plugin_connected": true, … } }
```
Within a poll interval the server appears at `/rust/servers`.
Within a poll interval the server appears at `/rust`.
### 2.4 The recommended PopupNotifications look (optional)