What it is
The authoritative half of RareIcon. Headless — no window, no renderer, no asset
loading. It owns where everybody is and tells the clients about it. The art, the
tilesheets and the camera belong to apps/rareicon/game, and none of them are
linked here.
Built on lightyear over Bevy. The
wire is crates/mmorpg_net’s dim2 — the same crate the client links with the
same feature, so the two cannot drift apart without one of them failing to
compile.
What is authoritative
Positions. A client sends which keys are down and never a position. The server integrates that intent against the same numbers the client predicts with, and the client rolls back when the two disagree. A client that lies about its keys can walk at walking speed in a direction of its choosing, which is what a player can do anyway.
Not yet authoritative, and deliberately: collision, terrain, energy, and casting. Each is a rule the client also has to run to predict correctly, so each arrives as a matched pair of changes — one at a time, which is what keeps the two in step.
Two lanes into one world
| Lane | Port | Who uses it |
|---|---|---|
| UDP | 7985 | native clients, through an L4 LoadBalancer |
| WebSocket | 7986 | browsers, which cannot open a UDP socket at all, at wss.rareicon.com |
| HTTP door | 7987 | /token and /healthz, through the Cilium gateway |
Both game lanes land in the same world, and nothing after admission knows which
way a player arrived. lightyear refuses an app with more than one started
Server, so both sockets hang off a single server entity.
Admission
A player asks POST /token before opening anything, and is given a signed
ConnectToken. Admission is HTTP because a browser cannot put an
Authorization header on a WebSocket — you cannot present a credential on the
socket you are trying to open.
It also keeps the signing key server-side. The name the door picks travels
inside the token’s signed user_data, and the game server reads it back rather
than inventing one, so a client cannot rename itself. Every caller is currently
admitted as a guest; adding a real sign-in is a change to how the door picks the
name and to nothing else.
In the cluster
The agones feature links the SDK: Ready() once the sockets are actually
listening rather than at startup, a health ping inside the sidecar’s deadline,
and a watch that exits the process when the cluster moves the GameServer to
Shutdown. It is off by default — the SDK talks to a sidecar that only exists
in a pod — and the image build turns it on.
One pod, on purpose: everyone lands in the same world, and the single public UDP
address assumes it. See kube/agones/rareicon/manifests/README.md.