Skip to content
OpenPerpetuumPublic

About

Wiki for Open Perpetuum

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

OpenPerpetuum Wiki

The player- and developer-facing wiki for the Open Perpetuum MMO server, built with Zola.

License: Apache-2.0 (see LICENSE/).

Sections

  • 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)

Building

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/ (runs make i18n + i18n-check first)
make serve   # live-reload server on http://localhost:8085 (WIKI_PORT=NNNN to override)
make clean   # remove public/

Architecture

+--------------------------------------------------------------+
| GAME SERVER DATABASE (.NET)                                  |
| Perpetuum.WikiGenerate (C#)                                  |
+------------------------------+-------------------------------+
                               |  make generate (WIKI_DB=...)
                               v
+--------------------------------------------------------------+
| content/  (English markdown, committed to git)               |
|   _index.md          (home page)                             |
|   features/*.md      (gameplay systems)                      |
|   content/*.md       (item stat pages, 4500+ files)          |
|   zones/*.md         (zone pages + world map SVG)            |
|   formats/*.md       (dev field reference)                   |
+-------------+--------------------------------+---------------+
              | make i18n                      | make zonemaps
              v                                v
+---------------------------+   +------------------------------+
| translations/*.json       |   | gen_zone_teleport_maps.py    |
| (14 language files)       |   | (Python, numpy, matplotlib)  |
+-------------+-------------+   +--------------+---------------+
              | gen_content_translations.py    |
              | gen_zone_translations.py       |
              | gen_lang_pages.py              |
              | gen_i18n.py                    |
              | gen_menu_tree.py               |
              | gen_item_translations.py       |
              | gen_item_catalog.py            |
              v                                v
+---------------------------+   +------------------------------+
| content/<lang>/*.md       |   | static/zonemaps/<slug>/*.svg |
| (13 translated trees,     |   | (80 zone SVGs + thumbs       |
|  ~19 500 item pages each) |   |  + non-passable overlays)    |
+-------------+-------------+   +--------------+---------------+
              |                                |
              +---------------+----------------+
                              |
                              v
+--------------------------------------------------------------+
| static/  (JS, CSS, JSON)                                     |
|   i18n.js           (generated: STRINGS, LANG_PAGES)         |
|   lang-pages.json   (page manifest, 2692 pages)              |
|   menu_tree.json    (sidenav, 99 entries)                    |
|   search_index.json (40 700 pages)                           |
|   map.js              (world map zoom/pan)                   |
|   zone-map.js         (zone map modes, landmarks)            |
|   style.css           (dark theme, 4 palettes)               |
+------------------------------+-------------------------------+
                               |
                               v
+--------------------------------------------------------------+
| templates/  (Tera templates)                                 |
|   base.html    (topbar, sidenav, palette, i18n)              |
|   page.html    (article wrapper, extends base)               |
|   index.html   (home page: activity cards)                   |
+------------------------------+-------------------------------+
                               |  zola build (Docker, pinned v0.
                               v
+--------------------------------------------------------------+
| public/  (40 601 static HTML pages)                          |
|   index.html           (English home)                        |
|   de/index.html        (German home)                         |
|   features/robots/     (English feature page)                |
|   de/features/robots/  (German feature page)                 |
|   ...                (x 14 languages)                        |
+------------------------------+-------------------------------+
                               |  GitHub Pages / any static host
                               v
+--------------------------------------------------------------+
| LIVE SITE  (openperpetuum.github.io/wiki)                    |
+--------------------------------------------------------------+

Build pipeline (top → bottom)

Stage Tool Input Output
1. Generate .NET Perpetuum.WikiGenerate Game DB content/**/*.md (English)
2. Translate Python tools/gen_*.py English md + translations/*.json content/<lang>/**/*.md
3. Zone maps Python tools/gen_zone_teleport_maps.py Game DB (terrain) static/zonemaps/*.svg
4. i18n assets Python tools/gen_i18n.py translations/*.json + content static/i18n.js, lang-pages.json, menu_tree.json
5. Search index Python tools/gen_search_index.py All built pages static/search_index.json
6. Static build Zola (Docker) content + templates + static public/ (40 601 HTML files)

Languages

The site is available in English (the source language) and 13 more — Čeština, Deutsch, Español, Français, Italiano, 日本語, 한국어, Nederlands, Polski, Português, Русский, 简体中文 and 繁體中文. All translatable strings (UI chrome, game names, generated content) live in translations/<lang>.json; the per-language pages are generated into content/<lang>/ at build time.

Adding a new language: drop a translations/<lang>.json in place and run make build. The file must carry the same keys as translations/en.json (make i18n-check enforces this — missing keys and empty values fail the build); start from en.json and translate the values. No further wiring: tools/gen_i18n.py picks the new file up automatically, so the topbar language menu, the /<lang>/ routes and the translated menu labels in the search results all appear with it. Game display names go under the "names" key, extracted from the client's per-language string file (see below).

The file format, the translation conventions (in-game terms stay English, {lang} placeholder exception, mermaid \n), the name-extraction workflow, and the test setup are documented in TRANSLATIONS.md.

Testing

make test    # Playwright suite (tests/) against the built site.
             # One-time setup: npm install && npx playwright install chromium
make test-py # Python generator tests (tests_py/) with coverage
             # (pytest + coverage; the in-place idempotency tests need the
             #  working tree in a generated state — plain `make build` is enough)
make i18n-check  # translation-file CI gate (key parity, placeholders, empty values)

The i18n machinery (translation files, generators, conventions, and the Python/browser test suites) is documented in TRANSLATIONS.md.

Regenerating the content pages

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/plantrules

Client 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.

Zone map terrain

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:

  1. a local PerpetuumServer2 checkout (sibling ../PerpetuumServer2 or the server/ submodule) when it has custom-layers/ — make zonemaps uses it directly, no download
  2. otherwise tools/fetch_zone_layers.sh fetches what is publicly available into .assets/ (the same sources the PerpetuumServer2 CI uses): the original zones' .bin layers 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.

Content tools (no database needed)

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.

CI and action pinning

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

About

Wiki for Open Perpetuum

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages