Client
The client is the Gamehoster code that runs on your machine. Two things live in its source tree. The
tools client is the one command you run on a timer: it generates each game to static code and
syncs it to the server, and it builds the local
browser tools. The browser runtime is the game library
baked into each game's page — the same engine the server runs, for prediction — covered in depth on the
Frontend page. The source is in layers: client/, this
hoster's own modules; common/, the shared toolkit every hoster's client is built from; and the
server's generate.js, which the sync drives at build time.
This page is the file map — every file, then a section giving its exports, or, for the command you run, its
switches.
client/ this hoster's own modules
gamehoster-tools.js the one command you run (tools entry point)
sync.js generate + push game definitions to the server
browse/
game.js build the Game Logs browser
gamehoster-client.js the browser game runtime (baked per game — see Frontend)
rollback.js the browser prediction core (bundled into the library)
common/ the shared toolkit, common to every hoster
net.js config, TLS and API-version plumbing
client/
run.js the orchestrator every hoster's client runs
browse/
web.js build the Web Logs browser
server.js build the Server Logs browser
pull-logs.js mirror the access logs down
pull-stats.js mirror the server stats down
shell.js the page frame: strip, tabs, status, stylesheet
ui.js the UI kit: cards, tables, charts, pagination
format.js shared formatters (esc, bytes, dates)
io.js small render/IO helpers
server/ the generator the sync drives (see Server)
generate.js compile a definition to static server + client code
engine.js · schema.js · loader.js the runtime it reuses and bundles for the browser
Files
| File | What it does |
|---|---|
client/ — this hoster's modules | |
client/gamehoster-tools.js | The single command you run for the server tools. Declares the tool set and the sync hook, then hands off to the shared orchestrator. |
client/sync.js | Generates each game to static code, then diffs the games root against the server by content hash and pushes only the differences. |
client/browse/game.js | Reads the game definitions and renders the browsable Game Logs map — every game, organised by domain. |
client/gamehoster-client.js | The browser game runtime: opens the socket and drives a local simulation. Baked into each game's library; detailed on Frontend. |
client/rollback.js | The client-side rollback core the runtime is built on: fold server updates, re-simulate for prediction and reconciliation. |
common/ — the shared toolkit | |
common/net.js | Reads the config, skips cert verification for a bare-IP endpoint, and discovers the server's API version. |
common/client/run.js | The orchestrator core every hoster's client runs: arg parsing, config, the tool loop, and the tools-site frame. |
common/browse/web.js | Renders the static Web Logs browser from the mirrored Caddy access logs. |
common/browse/server.js | Renders the static Server Logs browser from the mirrored server statistics, drilling month → minute. |
common/browse/pull-logs.js | Mirrors the server's access logs down incrementally (rotated files once, the active log by Range). |
common/browse/pull-stats.js | Mirrors the server's statistics day-files down incrementally, the stats counterpart of pull-logs. |
common/browse/shell.js | The shared page frame: the top strip, tool tabs, per-tool status banner, and stylesheet. |
common/browse/ui.js | The shared UI kit a browser composes: stat cards, tables, chart/table toggles, and pagination. |
common/browse/format.js | The canonical formatters: escaping, numbers, bytes, durations, and month/day labels. |
common/browse/io.js | Small render/IO helpers, chiefly the footer-stripping used by the write-if-changed comparison. |
server/ — the generator the sync drives | |
server/generate.js | Compiles a game definition to a static server module and a front-end library, inlining every body as a real function. Runs on your machine at sync; detailed on Server. |
client/gamehoster-tools.js — entry point
The single thing you run for the server tools, and the only file with no exports. It declares Gamehoster's
tools — the two universal browsers (Web Logs, Server Logs) from the shared toolkit plus the project's own Game
Logs — and its content (sync) hook, then hands off to the shared orchestrator in
common/client/run.js. The sync hook shells
out to sync.js, so content is generated and
pushed before the tools browsers render it. (It is distinct from
gamehoster-client.js, the browser game
runtime — same folder, different job.)
| Switch | What it does |
|---|---|
--config <path>, -c | Path to the client config JSON. Defaults to ./config.json. |
--sync | Generate every game to static code and push the changes to the server. |
--game-logs | Build the Game Logs browser from your game definitions. |
--web-logs | Mirror the access logs down and build the Web Logs browser. |
--server-logs | Mirror the server stats down and build the Server Logs browser. |
--all | Everything in one process: sync and all three browser tools. |
client/sync.js
The sync client. Each run it first generates every game — regenerating its static
gamehoster.server.js and gamehoster.client.js from the definition (via
generate.js, reading
gamehoster-client.js as the library base) — then compares the games root to the server by content
hash and pushes only the differences, pruning files removed locally. What syncs is decided by
structure, not a blocklist: only <domain>/<game>/** under a dotted domain
folder, skipping reserved _/. names. Nothing stays resident. Importable (the exports
below, used by the unified client) and runnable on its own (node client/sync.js --config <path>),
including a --watch loop. The full protocol is the Sync
page.
| Export | What it is |
|---|---|
localTree(root) | Walk the games root into { relpath: { hash, abs } }, taking each <domain>/<game>/ subtree and hashing every file by its SHA-256 content. |
managed(rel) | Whether a server path is one this client owns — and may therefore prune: at least <domain>/<game>/ deep. Reserved dirs and loose files on the server are left untouched. |
isDomain(name), isGame(name) | The structural rules that decide what syncs: a domain is a dotted, non-reserved directory; a game is any non-reserved directory holding a gamehoster-game.json. |
Standalone switches: --config <path> / -c,
--dry-run, --verbose / -v, and --watch / -w
with --interval <seconds> (default 30) to loop.
client/browse/game.js
The Game Logs browser generator, and this hoster's own domain tool (the analog of sitehoster's Automation Logs and datahoster's Data Logs). Where the log browsers read the access logs, this one reads the game definitions — the same tree the server loads — and renders a complete, browsable, static map of every game on the server, organised by domain: each game's config (tick/send rates, capacity), its player and instance state schemas, its entity types, and its commands (the parameters each takes and the state each writes). It composes the shared shell, UI kit and formatters, so it feels like one tool with the log browsers, and it touches no API — everything is built from the local files with write-if-changed and orphan pruning.
| Export | What it is |
|---|---|
build(options) | Scan the game definitions under contentRoot and render the per-domain Game Logs browser. Takes { contentRoot, outDir, ip }; returns the summary the Game Logs card shows. |
client/gamehoster-client.js — browser runtime
The browser game client. It connects to the game socket, drives a local simulation that runs the world at the
game's tick rate, predicts your own commands the instant you send them, and reconstructs everyone else from the
server's per-player delta updates. It is not a Node module: it defines Gamehoster.connect on the
page. At sync, generate.js bakes this
file — together with the bundled engine — into each game's gamehoster.js library with that game's
config and predictors as a preset. The whole prediction model is the
Frontend page.
| Global | What it is |
|---|---|
Gamehoster.connect(game, join, opts) | Open a game socket and return a connection: onReady, send(type, params) (predicted at once), frame() (the reconstructed view for rendering), latest(), auth(id), and close(). |
client/rollback.js
The client-side rollback core, shared by the browser runtime (where the engine is baked in) and Node tests. It keeps a client-mode World, folds in the server's per-player delta updates (a keyframe plus the broadcast command log), and each frame re-simulates from the last authoritative keyframe up to the local leading tick — real commands where known, predicted commands for the ticks not yet received. That single re-simulation is prediction and reconciliation at once. The Instance and Frontend pages are that mechanism in full.
| Export | What it is |
|---|---|
ClientSim | The prediction simulation: onUpdate (fold a server delta), send (predict an own command), advance (step the leading edge), and render (the eased view). Bundled into the library beside the engine. |
common/net.js
The shared API-client plumbing every hoster's downloaders sit on: read the config, skip cert verification for a
bare-IP (self-signed) endpoint, and discover the server's API version so request paths follow it. Meant to be
copied across the hosters unchanged. (The sync client reads its own gamehoster-config-* config
directly; this file backs the log/stat pulls the tools orchestrator runs.)
| Export | What it is |
|---|---|
loadConfig(path) | Read and validate the client config JSON into the shape the tools expect. |
isIpHttps(apiBase) | Whether the endpoint is HTTPS to a bare IP literal (or [ipv6]) — hence self-signed. |
disableTlsVerification() | Quiet the one-time Node warning and disable TLS verification process-wide (only for an IP endpoint). |
resolvePrefix(...) | Discover the server's API version and build the /api/vN path prefix the requests use. |
common/client/run.js
The hoster-tools orchestrator core — the shared engine every hoster's client runs. A project calls
run({ tools, sync, brand }); this owns arg parsing, config and TLS, the isolated phase loop,
and the whole tools-site frame (overview cards, per-tool pages, clash-safe "not run" status, persisted
last-run state). The two universal tools come ready-made from webTool()/serverTool(),
so Gamehoster's entry is a short declaration plus its Game Logs tool and sync hook.
| Export | What it is |
|---|---|
run(opts) | The entry a project calls with { tools, sync, brand }: parse args, run the sync hook and every enabled tool, and write the tools site. |
webTool() | The ready-made Web Logs tool descriptor (pull the access logs, then build the browser). |
serverTool() | The ready-made Server Logs tool descriptor (pull the stats, then build the browser). |
common/browse/web.js
The Web Logs browser generator. It reads the Caddy JSON access logs mirrored down by
pull-logs.js and renders a set of static, self-contained HTML pages so the traffic can be
browsed offline. Composes the shared shell, UI kit and formatters; also runnable standalone.
| Export | What it is |
|---|---|
build(options) | Render the Web Logs browser. The client passes { logsDir, outDir }; run standalone it reads the log dir beside the script. |
common/browse/server.js
The Server Logs browser generator — the reader half of the shared stats facility. It reads the per-type
dated day-files mirrored down by pull-stats.js and writes a drill-down site (all time → month
→ day → hour → minute), each page charting every metric with a chart/table toggle.
| Export | What it is |
|---|---|
build(options) | Render the Server Logs browser. The client passes { dataDir, outDir, serverIp }; run standalone it reads the data dir beside the script. |
common/browse/pull-logs.js
Mirror the server's Caddy access logs into a data dir — the log counterpart of pull-stats.js.
Rotated files are immutable (fetched once, whole); the active log grows, so only its new tail is appended
via a Range request; a newly-appeared rotated file means the active log restarted, so it resets and
re-fetches. TLS is expected to be already configured by the caller.
| Export | What it is |
|---|---|
pull(opts) | Mirror the access logs down incrementally. Takes { logsDir, apiBase, apiToken } and reports how many lines were mirrored. |
common/browse/pull-stats.js
Mirror the server's statistics day-files into a data dir — the stats counterpart of
pull-logs.js. The server samples CPU, memory, disk and IO into per-type dated files; a frozen
past day is fetched once and today's growing file has only its tail appended by Range. TLS is expected to
be already configured by the caller.
| Export | What it is |
|---|---|
pull(opts) | Mirror the stats day-files down incrementally. Takes { dataDir, apiBase, apiToken } and reports what was fetched and appended. |
common/browse/shell.js
The shared shell that owns the page frame for the tools site: the fixed top strip (brand + Overview + a
tab per tool + the IP), the per-tool status banner, the stylesheet, and small formatters. The same strip
goes on every page; the tab set and brand are configured per project by run.js at startup,
so this file carries no project identity and copies across the hosters unchanged.
| Export | What it is |
|---|---|
layout(opts) | Render a full framed page (top strip + body) for the Overview and any not-run tool's status page. |
toolStrip(...) | The fixed top strip a tool browser injects at the top of its own pages, so the tabs are identical everywhere. |
statusBanner(tool) | The per-tool banner shown when a tool has not been run. |
overviewCard(tool, state) | One tool's card on the Overview, reflecting its last-run state. |
setTools(tools), setBrand(brand) | Configure the tab set and brand for this project (called by run.js); TOOLS, brandName() expose them. |
esc, fmtNum, fmtBytes, stripFooter | The formatters and footer-stripper re-exported for convenience, plus STYLESHEET and TOOLSTRIP_CSS. |
common/browse/ui.js
The shared UI kit for the tools browsers — the reusable builders a domain tool composes instead of
hand-rolling markup. The page frame lives in shell.js and the formatters in
format.js; specialised chart bodies stay per-browser, bound to each tool's data.
| Export | What it is |
|---|---|
panel(...), table(...) | A titled panel, and a table with a built-in Show-all toggle. |
statCards(items) | A row of stat blocks (name + value, or a custom cell). |
navButtons(prev, next, up) | Prev / Next (with an optional Up) pagination, used on every dated page. |
viewToggle(...) | A chart ⇄ table switch for a metric. |
SCRIPT, CSS | The shared client JS (table toggle + chart switch) and the common visual furniture. |
common/browse/format.js
The canonical formatters shared by the tools browsers — pure functions with no state, meant to be copied across the hoster projects unchanged.
| Export | What it is |
|---|---|
esc(s) | HTML-escape a value for safe interpolation. |
fmtNum(n) | A grouped decimal number (thousands separators). |
fmtBytes(b) | A human byte size (B, KB, MB, …). |
fmtDuration(ms) | A compact duration (ms, s, or m s). |
monthLabel, monthLabelShort, dayLabel, MONTH_NAMES | Month/day label helpers and the month-name table used by the dated pages. |
common/browse/io.js
Small shared render/IO helpers for the tools browsers. The footer carries the page's generation time,
which changes every run; stripFooter removes the whole footer before the write-if-changed
comparison so a new timestamp alone never forces a rewrite.
| Export | What it is |
|---|---|
stripFooter(html) | Remove the footer block before comparing a freshly rendered page to the one on disk. |
rmrf(p) | Recursively remove a path (for a clean full rebuild). |
GEN_DURATION_TOKEN | The placeholder a browser writes for the generation time and patches with the real value last. |
server/generate.js — run at sync
The code generator the sync drives on your machine. It reads a game definition directory and emits two plain,
static JS files — a server module and a front-end library — with every raw body inlined as a real
function (Gamehoster) { … } literal, so nothing is compiled with new Function at
request time. For the library it also bundles the runtime for the browser: the schema helpers, the
engine and rollback
inlined into one IIFE. It reuses the server's schema.js and loader.js, so the
generated code and the running server can never disagree. Full detail lives on the
Server and Sync pages.
| Export | What it is |
|---|---|
generateServer(dir) | Compile a definition directory to the static gamehoster.server.js module the server requires. |
generateClient(dir, clientBaseSrc) | Compile a definition to the gamehoster.client.js library — the runtime bundle plus the client base plus this game's baked preset. |
readDefinition(dir) | Read a definition directory into raw parts (JSON parsed, body files as source strings) — the shared input both generators build from. |