The kit taught, to an audience outside this org, that Rust needs "no game-side plugin to write at all" because it ships RCON. That is overruled: the Rust dry run reaches the game through a MOD - a plugin loaded by the server's own framework, hooking events and dialling out - exactly as the ServUO overlay does (docs#170). Chapter 3's section kept its question and lost its example, which turned out to improve it. The useful test is not "does my game expose a protocol" but "does it DELIVER EVENTS": a remote-control channel is built for an operator typing commands and tells you what you asked about, when you ask, and a website needs what happened whether or not anyone was listening. A channel that answers questions can only be polled, and polling turns "someone left the clan at 14:02" into "the count was different at 14:03". Rust now appears in that section as the counter-example rather than the example, and carries the finding that is actually worth having: its server is a BINARY where ServUO is source you compile, and the three-part shape survives that unchanged. The plugin-dials-out arrangement is not a property of having source access. Chapter 4 said a game with a remote-control protocol may not need any of it, and that its worked example is source you build. Both now say what is true - the rules in that chapter are properties of being inside a game loop, and apply identically to a mod in a closed server. Co-Authored-By: Claude <noreply@anthropic.com>
111 lines
5.8 KiB
Markdown
111 lines
5.8 KiB
Markdown
# Runic Gateway — Integration Kit
|
|
|
|
**How to put a game on a Runic Gateway site.**
|
|
|
|
Runic Gateway is a website platform for game communities. Core knows nothing about
|
|
any particular game: everything game-specific — routes, tables, pages, navigation,
|
|
notifications — arrives as an installable **module**, and an operator installs one
|
|
from an admin panel without building anything. [`module-uo`][module-uo] is the
|
|
first module and serves an *Ultima Online* shard. This kit is how you write the
|
|
second one.
|
|
|
|
> ### 🚧 This is a draft
|
|
>
|
|
> The kit is finished when **someone outside this project builds a working module
|
|
> for a new game by following it alone, without reading core's source.** That has
|
|
> not happened yet, so treat every chapter as untested on you. If you are that
|
|
> person: the places you get stuck are the most valuable thing this repo can
|
|
> receive — [tell us][issues], and please say where you left the kit and what you
|
|
> did next.
|
|
|
|
---
|
|
|
|
## What you are building
|
|
|
|
Three things, and the kit is one book rather than a page in three repos because
|
|
the reasons live in the joins between them:
|
|
|
|
| # | Part | What it is |
|
|
| --- | --- | --- |
|
|
| 1 | **The website module** | A bundle core loads at boot: server routes, a schema fragment, a prebuilt client chunk, navigation. The bulk of the work, and the only part every module needs. |
|
|
| 2 | **The sidecar** | A small service that owns the connection to your game server, and owns the durable copy of what the game said. **Not optional** — see below. |
|
|
| 3 | **The game-side plugin** | Whatever runs inside your game and feeds the sidecar, without ever letting the sidecar stall the game. |
|
|
|
|
```
|
|
your game server ──dials out──▶ your sidecar ──HTTP + WS──▶ website core
|
|
(plugin: bounded (owns the socket, (loads your module,
|
|
queue, writer thread) persists to its own serves the pages)
|
|
store, then forwards)
|
|
```
|
|
|
|
**The website process never opens a connection to a game server.** That is a rule
|
|
in the contract ([`MODULE_API.md`][api] §2.7, `MODULE_API_VERSION` 1.4.0), not a
|
|
style preference, and chapter 3 is mostly about why. The short version: the
|
|
website is the internet-facing process and your game is not; the sidecar persists
|
|
before it forwards, so a website that is down or mid-deploy loses nothing; and a
|
|
game must never block on a web request. A game that genuinely delivers events on a
|
|
surface of its own needs a *thin* sidecar, not none — but check that it delivers
|
|
events rather than answering questions, because a channel built for an operator
|
|
typing commands can only be polled, and polling turns "someone left at 14:02" into
|
|
"the count was different at 14:03".
|
|
|
|
## Start here
|
|
|
|
1. **[The dry run][dryrun]** — a complete module designed on paper for a second
|
|
game, *Rust*, chosen for how little it shares with Ultima Online. Read it first.
|
|
It is the shortest honest picture of the whole job, and it names the one thing
|
|
the contract cannot do yet.
|
|
2. **`template/`** — a module that builds and loads, doing almost nothing. Copy it,
|
|
rename it, and you have a running module before you have read a chapter.
|
|
3. **The book** — [`book/`](book/), four chapters, in the order the work happens.
|
|
|
|
## The one rule this kit follows
|
|
|
|
**It never re-specifies a contract.** These documents are normative, and where the
|
|
kit and one of them disagree, they win and the kit has a bug:
|
|
|
|
| Authority | For |
|
|
| --- | --- |
|
|
| [`MODULE_API.md`][api] | Everything a module may do: `module.json`, `ctx`, the `register*` calls, the client registry, the UI kit, schema-fragment rules, the loader's obligations. |
|
|
| [`MODULE_SYSTEM.md`][system] | Why the module system is shaped this way, and how a module is installed and removed. |
|
|
| [`link/PLAN.md`][linkplan] + [`INTEGRATION.md`][linkint] | The shard↔sidecar wire protocol, as one real sidecar implements it. |
|
|
|
|
The kit *teaches*: the order to do things in, the reasoning, worked examples, and
|
|
the mistakes that cost this project time. Where it must show a member list it
|
|
quotes with a pointer rather than copying, because a guide that restates a
|
|
contract diverges from it silently — and a reader who follows the divergent copy
|
|
gets a module that fails validation for reasons the guide cannot explain.
|
|
|
|
## What this repo contains
|
|
|
|
```
|
|
book/ the chapters
|
|
template/ a module that builds — copy this
|
|
scripts/ the checks CI runs over both
|
|
```
|
|
|
|
CI clones core at a **pinned commit**, asserts the version the template declares
|
|
still matches that core's `MODULE_API_VERSION`, builds the template and runs its
|
|
guards, checks every link in the book, holds the template's rename checklist
|
|
against the template's own tree, and checks that every path a chapter names is
|
|
still there. So a change to the contract breaks this repo's build loudly instead
|
|
of leaving a chapter quietly wrong.
|
|
|
|
None of that can tell you whether a paragraph has become untrue about a file that
|
|
still exists. That is a reviewer's job on every pull request, and a
|
|
`MODULE_API_VERSION` bump is when it is owed in full.
|
|
|
|
## Licence
|
|
|
|
GPL-3.0-or-later, like every Runic Gateway repo — see [LICENSE.md](LICENSE.md).
|
|
The `template/` directory is meant to be copied and made yours; it carries the
|
|
same licence, and so does anything derived from it.
|
|
|
|
[module-uo]: https://gitea.whitlocktech.com/RunicGateway/Module-uo
|
|
[api]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_API.md
|
|
[system]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/website/MODULE_SYSTEM.md
|
|
[dryrun]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/modules/rust-dryrun.md
|
|
[linkplan]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/link/PLAN.md
|
|
[linkint]: https://gitea.whitlocktech.com/RunicGateway/docs/src/branch/main/link/INTEGRATION.md
|
|
[issues]: https://gitea.whitlocktech.com/RunicGateway/Integration-kit/issues
|