|
|
|
|
@@ -132,28 +132,46 @@ forwarded, a lossy live feed, an authenticated read API with a version on it.
|
|
|
|
|
|
|
|
|
|
## "But my game already speaks a remote-control protocol"
|
|
|
|
|
|
|
|
|
|
Then your sidecar is **thin**, not absent.
|
|
|
|
|
Then your sidecar is **thin**, not absent — and be sure the surface you are
|
|
|
|
|
thinking of actually carries what your module needs, because that is where this
|
|
|
|
|
question usually goes wrong.
|
|
|
|
|
|
|
|
|
|
Rust — the survival game — is the worked example here, in
|
|
|
|
|
[`rust-dryrun.md`][dryrun]: a module designed on paper for a game chosen for how
|
|
|
|
|
little it shares with Ultima Online. Rust ships RCON over WebSocket, so a
|
|
|
|
|
`rust-link` has no protocol to invent and no game-side plugin to write at all. It
|
|
|
|
|
keeps:
|
|
|
|
|
A remote-control channel is built for an operator typing commands: it tells you
|
|
|
|
|
what you asked about, when you ask. What a website needs is what *happened* —
|
|
|
|
|
every kill, every join, every departure, delivered whether or not anyone was
|
|
|
|
|
listening at that moment. Those are different products, and a channel that
|
|
|
|
|
answers the first can only approximate the second by polling it, which turns
|
|
|
|
|
"someone left the clan at 14:02" into "the count was different at 14:03".
|
|
|
|
|
|
|
|
|
|
- the RCON connection, its credentials and its reconnect loop, **out of an Express
|
|
|
|
|
process** — where the failure mode is a wedged request handler;
|
|
|
|
|
- a store, so the site is not blank whenever the game is restarting, which for that
|
|
|
|
|
genre is a daily scheduled event;
|
|
|
|
|
- an HTTP + WS API with a version on it, so the module talks to one shape of thing
|
|
|
|
|
regardless of what the game speaks.
|
|
|
|
|
So the honest test is not *does my game expose a protocol* but **does it deliver
|
|
|
|
|
events**. If it does, your sidecar keeps that connection, its credentials and its
|
|
|
|
|
reconnect loop out of an Express process, keeps a store so the site is not blank
|
|
|
|
|
whenever the game restarts, and presents your module one versioned HTTP + WS
|
|
|
|
|
shape. That is what thin means: less code, the same architecture.
|
|
|
|
|
|
|
|
|
|
It drops the bespoke wire protocol and the plugin. That is what "thin" means: less
|
|
|
|
|
code, not a different architecture.
|
|
|
|
|
**Rust is the worked example, and it is not that case.** The dry run in
|
|
|
|
|
[`rust-dryrun.md`][dryrun] designs a module for it precisely because it shares so
|
|
|
|
|
little with Ultima Online — and its answer is an **Oxide plugin**: C# loaded by
|
|
|
|
|
the mod framework a modded Rust server already runs, hooking the game's events and
|
|
|
|
|
dialling out to a sidecar, exactly as the ServUO overlay does. The Rust server is a
|
|
|
|
|
*binary*, where ServUO is source a shard owner compiles, so the way in is a
|
|
|
|
|
published hook API rather than a file you edit. **The three-part shape survives
|
|
|
|
|
that unchanged**, which is the more useful finding: the plugin-dials-out
|
|
|
|
|
arrangement is not a property of having source access.
|
|
|
|
|
|
|
|
|
|
That document originally concluded the opposite — "no sidecar, the module dials
|
|
|
|
|
RCON directly" — and it carries a dated correction saying so, rather than having
|
|
|
|
|
been quietly rewritten. The value of a dry run is the record of what it found,
|
|
|
|
|
including where it was overruled.
|
|
|
|
|
It also pairs **one sidecar to one game server**, on that server's own host,
|
|
|
|
|
rather than one sidecar fronting a community's several — because those servers sit
|
|
|
|
|
on separate machines, and a shared sidecar would be reached across a network by
|
|
|
|
|
plugins that are supposed to talk to it over loopback. Worth knowing before you
|
|
|
|
|
design yours: if your game runs as a fleet, the question "how many sidecars" is
|
|
|
|
|
answered by where the loopback boundary is, not by how many processes you would
|
|
|
|
|
rather run. Your module holding several clients is the cheaper end of that trade,
|
|
|
|
|
and core never learns there is more than one.
|
|
|
|
|
|
|
|
|
|
That document reached the game over RCON until 2026-08-19, and before that
|
|
|
|
|
concluded there should be **no sidecar at all**. It carries both corrections,
|
|
|
|
|
dated, rather than having been quietly rewritten — the value of a dry run is the
|
|
|
|
|
record of what it found, including where it was overruled.
|
|
|
|
|
|
|
|
|
|
## Building yours
|
|
|
|
|
|
|
|
|
|
|