Skip to the content.

Game server catalog files

The library is data, not code. Each supported game is a JSON file in game-servers/catalogue/ in the repository, and the panel reads the same folder from its data directory at runtime. Adding a game means adding a file, not editing TypeScript.

How the panel loads the catalog

Two folders are merged at startup:

A file in the data folder with a built-in ID replaces the built-in. That is how a local tweak wins without forking the release. Every file is validated against the shared schema before it can influence anything; an invalid one is skipped with its name logged, not loaded.

The built-ins themselves are refreshed on each update, so a correction shipped in a release reaches installs that already have the old copy. A shipped config you have edited is left exactly as you left it - the panel says so on startup rather than silently keeping you on an old version. To customise a built-in and still receive updates to the rest, add your own file with a different name and the same id: it overrides by ID, and the shipped file stays shipped.

The fields a config carries

Field What it does
id Unique catalog ID. Lowercase, stable, used to merge overrides.
provider How the files are fetched: steam, download (a zip from downloadUrl), or minecraft-java (Mojang’s signed manifest). minecraft-bedrock is an older name for download.
name / description Shown in the library and on the server card.
status ready or planned. Only ready can be created.
genre / art Genre label and local fallback art theme.
requiresEula Whether the creation form demands an EULA tick.
steamRequiresOwnership Whether the game needs a Steam account that owns it.
steamAppId / steamArtAppId The install ID and the retail ID used for library artwork.
artUrl Official cover art URL for games that are not on Steam. Proxied and cached by the panel.
configFile The main settings file, relative to the server’s data folder. Adds an edit shortcut on the server page. Omit it to hide the shortcut.
executable / launchExecutable The file that proves a download completed, and the binary the service actually runs.
runtime native, or java to run the panel’s own Java runtime instead of a binary from the download.
launchArgs The service’s arguments, with placeholders expanded at install time.
workingDirectory install (default), data, or executable - the folder the service runs from.
seedFiles Config files written before the first start, so the game learns its allocated ports and generated passwords.
secrets Passwords the panel generates, stores in the vault, and expands as {secret:name}.
heap minMb / maxMb / reserveMb for JVM games. Enables {heapMb}, sized from the memory free at install time.
classpathDirectory Folder of jars joined into {classpath}, for games launched through their own bundled JVM.
downloadUrl / downloadSha256 Official download and optional checksum for non-Steam providers.
console rcon (log tail plus commands), logs (read-only tail), or none.
workshop Steam Workshop support. Present, the server page grows a Workshop tab. See below.
dataDirectory The provider’s data folder, relative to the install root, mapped into the Files view. Omit it to use the panel’s own data folder; . means the install root itself.
ports Named bindings with protocol, purpose, visibility, and a default port.

Placeholders

The same tokens work in launchArgs, in seedFiles values, and in a seed file’s own path. Nothing else in the panel knows what any of them mean for a particular game.

Token Expands to
{port:<name>} The port allocated to the binding with that name, or that purpose.
{gamePort} Shorthand for {port:game}.
{secret:<name>} A generated password declared in secrets.
{slug} / {displayName} The server’s slug and the name its owner gave it.
{installPath} / {dataDir} Absolute paths to the install root and the resolved data folder.
{version} The version installed, where the provider resolves one.
{classpath} Every jar in classpathDirectory, joined for the JVM.
{heapMb} The heap size chosen from heap and the machine’s free memory.

A {port:...} or {secret:...} the config never declared stops the install with a clear message rather than reaching the command line. A typo that silently got through would start a server bound to nothing and look like a firewall problem. Braces that are not tokens are left alone, so a game whose own arguments use them still works.

Seeding a config file

Most games need to be told which port they were given, and every one of them keeps that somewhere different. seedFiles describes the file instead of the installer knowing about it:

"seedFiles": [
  {
    "path": "Server/{slug}.ini",
    "format": "ini",
    "mode": "create",
    "eol": "crlf",
    "values": { "DefaultPort": "{port:game}", "PublicName": "{displayName}" }
  }
]

Steam Workshop

A workshop block is all it takes for a game to get a Workshop tab, where the server’s owner searches for mods and adds them. The download runs on the machine, under the operator’s own SteamCMD - a customer never signs in to Steam, and never sees the operator’s account:

"workshop": {
  "appId": 108600,
  "anonymous": true,
  "modsDirectory": "mods",
  "modManifestFile": "mod.info",
  "modManifestKey": "id",
  "config": {
    "path": "Server/{slug}.ini",
    "itemsKey": "WorkshopItems",
    "modsKey": "Mods",
    "separator": ";",
    "eol": "crlf"
  }
}

Ports are defaults, not assignments

The port field in a config is the starting point, not a guarantee. WinPanel allocates from the shared safety domain, so two people can run the same game and each gets a free port. The config tells the panel where to begin looking; the allocator walks from there. If the default is taken by a website, another game server, or Windows, the next free one is used instead. The actual binding is shown on the server’s Connection panel.

Some games let you set player limits in launch arguments; others, like Nomad, keep them in the config file. A config can describe either shape, because launchArgs and dataDirectory are separate. The panel does not enforce a universal max-players field - that is provider-specific, and pretending otherwise would produce a setting that does nothing on half the catalog.

An example

A minimal Steam config for a game that downloads anonymously:

{
  "id": "my-game-dedicated",
  "provider": "steam",
  "name": "My Game",
  "description": "My Game dedicated server for Windows.",
  "status": "ready",
  "genre": "Survival",
  "art": "steel",
  "requiresEula": true,
  "steamRequiresOwnership": false,
  "steamAppId": 12345,
  "executable": "MyServer.exe",
  "launchArgs": ["-port", "{port:game}", "-batchmode"],
  "console": "none",
  "ports": [
    { "name": "game", "protocol": "udp", "purpose": "game", "visibility": "public", "port": 25000 }
  ]
}

The panel validates the file at startup, and the game appears in the library the next time it loads. A bad file is skipped with its name in the log, so a typo never takes the catalog down.

Everything the built-in games do is expressible this way. Project Zomboid - a Steam download, run through its own bundled JVM, with a generated admin password, a sized heap and a CRLF settings file in a folder the game insists on - is a catalog file and no TypeScript at all. If a game needs something the schema cannot describe, that is a gap in the schema worth reporting, not a reason to special-case the installer.

Trying one without a rebuild

The catalog folders are read at startup and again whenever you ask, so writing a config is a normal edit-and-check loop rather than a release cycle:

  1. Drop the .json file into <data>/game-servers/catalogue/ on the machine.
  2. Open Game Servers → Add a server and press Reload configs.
  3. The game appears in the library. If it does not, the page says which file was skipped and why, in plain words from the schema.

There is no build step and no restart. A file that fails validation is skipped on its own; the rest of the library keeps working.

What the panel does for you

Only id, provider, name, description, genre, requiresEula, executable and ports are required. Everything else has a default, so a straightforward Steam server is a short file. Whatever the config declares, the panel handles the parts that are the same for every game:

Sharing a config

A config that works on your server works on everyone’s. If you have written one for a game that is not in the library, open a pull request that adds the file to game-servers/catalogue/ - nothing else. No TypeScript, no release notes; the loader finds it and the next release carries it.

Before opening it, check the file against the list below. These are the things a review will ask about, in the order it will ask them:

Artwork is optional. Steam games get cover art from their steamArtAppId automatically. For anything else, artUrl points at the publisher’s official image and the panel proxies it; the themed letter fallback is fine without one.