The player- and developer-facing wiki for the Open Perpetuum MMO server, built with Zola.
License: Apache-2.0 (see LICENSE/).
- Features — how the gameplay systems work (robots, combat, market, missions, ...)
- Content — generated stat catalogs: items (one page per item), ores, plants, deployables, robots, extensions, tech tree, missions, recipes, shop
- Zones — resource generation mechanics, zone index, worked examples, and the zone map (all zones on the x/y grid with their teleport connections)
- Formats — file format and field reference (zone files, stat fields)
The site build needs no database — the generated markdown is committed to git.
All commands run from this directory; the Zola build runs in a Docker container
(pinned ghcr.io/getzola/zola:v0.23.6), so no local Zola install is required.
make build # build the static site into public/
make serve # live-reload server on http://localhost:8085 (WIKI_PORT=NNNN to override)
make clean # remove public/Only needed when the game database changes. Requires the .NET 8 SDK, a reachable game database, and the plant rule files from a GameRoot:
make generate \
WIKI_DB="Server=...;Database=perpetuumsa;User Id=sa;Password=...;TrustServerCertificate=True" \
WIKI_PLANTRULES=/path/to/GameRoot/plantrulesClient display names are a static snapshot of the official client's English
string dictionary (generator/Perpetuum.WikiGenerate/ClientNames.cs, 4,266
entries) — no client archive is needed. The snapshot predates the end of
official client development, so it does not need refreshing; entities the
client never named fall back to a name derived from the internal identifier.
Commit the regenerated pages — the site build always uses the committed markdown.
See generator/README.md for what each generated page is built from, and idea.md for the original design notes.
The zone teleport maps (static/zonemaps/*.svg) show each zone's real
terrain. The layer data is not in this repo — only the small SVGs are
committed, plus derived 512×512 PNGs for the zones whose layer data is not
fetchable in CI (see below). The PNGs for the other zones are generated at
build time by tools/gen_zone_teleport_maps.py (pure standard-library
Python, one process per core) from the game's layer files, sourced in order:
- a local PerpetuumServer2 checkout (sibling
../PerpetuumServer2or theserver/submodule) when it hascustom-layers/—make zonemapsuses it directly, no download - otherwise
tools/fetch_zone_layers.shfetches what is publicly available into.assets/(the same sources the PerpetuumServer2 CI uses): the original zones'.binlayers from the Dedicated Server installer (Steam app 693060, anonymous) and the latest gamma/custom zones from the public Google Drive archive
The remaining zones (classic 2048×2048 worlds) ship only in the game
client's Perpetuum.gbf, which needs a Steam account — not available to CI
yet. For those, static/zonemaps-fallback/<zone>/{height,color}.png holds
previously derived terrain PNGs committed to the repo (~11 MB); the tool
keeps them instead of downgrading to the procedural placeholder. Once a
Steam account can fetch the client data, regenerate locally and delete the
fallback directory.
After re-running make generate (new zones or moved teleports), re-run
make zonemaps to refresh the map backgrounds and links.
The .NET generator is the long-term source of the generated pages, but a few
tools/ scripts transform the already-committed markdown without a database —
use them when the .NET toolchain is not at hand. Each one is idempotent and
kept in sync with its generator counterpart (the page it feeds):
| Tool | What it does | Generator counterpart |
|---|---|---|
tools/gen_production_pages.py |
adds the "Production" (components → item) and "Used in production" (item → products) mermaid sections to item pages from the tools/recipes_data.json cache, which the .NET generator writes from the components/itemresearchlevels tables |
ItemsPage.cs |
tools/gen_recipes_cards.py |
lays out the recipes page as category sections of reward-style cards, each linked to the item's page | RecipesPage.cs |
tools/gen_extension_categories.py |
builds static/extensions-categories.svg (the 15 skill categories with cross-category prerequisite arrows, each box linking to its section) and embeds it inline in the extensions page's "Main categories" section |
ExtensionsCategories.cs |
tools/regen_search_index.py |
rewrites static/search_index.json from the committed pages (title/description/URL per page) |
SearchIndex.cs |
Run order for a full refresh: gen_production_pages.py, then
gen_recipes_cards.py and gen_extension_categories.py (independent), then
regen_search_index.py, then rebuild.
GitHub Actions in .github/workflows/ are pinned to commit SHAs with
ratchet (the # ratchet:... comment
records the original tag constraint). CI lints the pins on every run; to
refresh them to the latest matching tags:
docker run --rm -v "${PWD}:${PWD}" -w "${PWD}" ghcr.io/sethvargo/ratchet:latest update .github/workflows/wiki.yml