Fireteam: Requiem checking

Features · this website

The live integration

Nothing on this site is a copy of anything in the game. The changelog you read here is docs/changelog.md; the map descriptions are the same text files the server sends to a client; the numbers on the front page came out of the running server a few seconds ago. This page says how, and what it can and cannot see.

Checking both ends…

Why the server is not the thing answering these requests

Everything the game server says to a client goes down an ENet channel, encrypted, in a space-separated vocabulary a browser has no way of speaking. Putting an HTTP server inside the game loop to solve that would mean the process that owns every shot in the game also parsing requests from the open internet, which is the sort of decision that is regretted once.

So the game server does the one thing it is already good at: it writes down what is true. Every two seconds it rewrites server/web/status.json with the whole picture. A separate process — web/bridge.py, about six hundred lines of standard library Python with no dependencies — reads that file and serves this site.

The bridge never writes anything and never speaks to the game server at all. It has no route that changes anything, no authentication to get wrong, and no path from a request on this website to a match in progress. The worst a broken or hostile web front end can do to a game in progress is nothing.

How it is put together

server/fr_server.exe                the game server
  └── writes server/web/status.json  every 2 seconds, whole

web/bridge.py                       reads it; serves this site
  ├── /api/status                   the live picture, plus how old it is
  ├── /api/motd                     the message of the day
  ├── /api/docs, /api/docs/<id>     the game's own documents
  ├── /api/changelog                docs/changelog.md, cut at its headings
  ├── /api/maps, /api/maps/<id>     the map descriptions, live
  ├── /api/weapons, /api/vehicles   the tables, as the server holds them
  ├── /api/modes                    what the server offers
  └── /api/health                   whether either end is up

What is in the status file, and what is not

In it

  • Who is online, and where each of them is
  • Every match, and how it stands
  • Both Sprawls, and which way out is open in each
  • The message of the day
  • The modes, and the maps with their counts
  • Uptime, peak, version, and the port

Not in it

  • Positions
  • Health or shields
  • Chat
  • Passwords or account files
  • Addresses
  • Anything that would let somebody watch a match they are not in

“Where somebody is” means “in the lobby” or “in Slayer on Valhalla” — the same sentence /who has always given every player in the game, and nothing finer. The one thing on the map that is given away in detail is the Sprawl's open extraction, and that is announced to everybody on the map by design: the whole mode turns on the exit being public.

Telling a quiet server from a dead one

An empty lobby and an offline server look identical unless somebody says which. So the status file carries the interval it is written at, and the bridge compares that against the file's age: three missed writes and the server is called down rather than quiet — one missed write is a busy tick and two is a slow disk, and neither of those should put offline on the front page.

When it is down, this site says so plainly and stops reporting people as online. It will show you the last thing the server said, labelled as the last thing the server said.

Reading a file that is being written

The server rewrites the status file in one call, but a read can still land in the middle of one and get half a document. That is not an error worth showing anybody — it is a file that will be complete again in a moment — so a parse failure falls back to the last copy that parsed, and the age stamp goes on telling the truth about how old that copy is.

Running it yourself

From the game's own folder, with the server running beside it:

python web/bridge.py                 port 8080
python web/bridge.py --port 9000
python web/bridge.py --root ..       if run from elsewhere

Python 3, no packages to install. If it cannot see the game's files it says which ones are missing and where it looked, at startup, rather than as a 404 an hour later.

Pages ask only while somebody is looking

Every live page polls every five seconds and stops entirely when the tab is hidden, asking again the moment it comes forward rather than waiting out the rest of the interval. A site left open in a background tab overnight costs nothing, and coming back to it never shows numbers from an hour ago.