Serving Modpacks for the Modpack Installer

This document discusses how to set up a web server so that users can download modpacks you publish.

To host modpacks, you need a web server that can host plain static files. You do not need to run any custom code or frameworks on that web server, just to publish files with a specific layout, detailed below.

On the modpack server, there are up to three layers of files required:

  1. A list of available modpacks (optional, advanced).

  2. One control file per modpack.

  3. The individual files comprising the modpacks.

Each of these layers is described in detail below.

Each layer refers to files in the next layer down. References can be with relative URLs (so that a modpack or set of modpacks can be moved without changing any file contents), or with absolute URLs (so that the different layers can be hosted on different web servers).

Almost all of these file formats are specific to one major version of Freeciv21. This document only describes the formats for the major version of Freeciv21 it is shipped with.

1. List of Modpacks

This is only needed if you want to let users browse a list of available modpacks before choosing one to install. To look at your modpack list instead of the standard one, users will usually have to start the modpack installer with non-standard arguments (see above).

The modpack list is a standard JSON file with a specific structure.

Here’s an example:

{
  "info": {
    "options": "+modpack-index-1.0",
    "message": "Example modpack list loaded successfully"
  },
  "modpacks": [
    {
      "name": "Example",
      "version": "0.0",
      "license": "WTFPL",
      "type": "Modpack",
      "url": "https://example.com/example.json",
      "notes": "This is an example"
    }
  ]
}

This file uses the modpack index format version 1.0, as is indicated in the info.options field. The optional info.message is displayed on the status line when the modpack installer starts up. It should be kept to one line.

The modpacks list contains a list of modpacks. This example contains just one modpack. Each modpack may contain the following fields:

“name”, “version”, “type”

These three fields should match those in the .json file which URL links to.

“subtype”

Optional free text. For tilesets or scenarios, conventionally indicates the map topology with one of overhead, iso, hex, or hex & iso (and these will be localised). Otherwise use -.

“license”

Free text summarising the distribution terms for the modpack content, by naming a well-known license, not quoting the full license text! Consider using SPDX identifiers (https://spdx.org/licenses/).

“URL”

The URL to a .json file for the individual modpack. The URL can be either relative in which case it’s relative to the URL of modpack.list, or absolute - which can be on some other web server.

“notes”

Optional free text; usually shown as a tooltip.

2. Control File: Defining an Individual Modpack

This is the core control file for a modpack, specifying what files it contains, where to download them from, and where they are installed.

Some modpack authors will just publish the URL of an .json file directly, for users to give to the modpack installer tool. There doesn’t have to be a modpack.list file anywhere that refers to the .json file.

Again, this is a file in standard JSON format. Its filename must end in .json.

Here is an example of a modpack control file:

{
  "info": {
    "options": "+modpack-1.0",
    "base_url": ".",
    "name": "Some ruleset",
    "type": "Modpack",
    "version": "0.0"
  },
  "files": [
    "some_ruleset.serv",
    "some_ruleset.tilespec",
    "some_ruleset/nation/german.ruleset",
    "some_ruleset/nation/indian.ruleset"
  ]
}

The info section has overall control information:

“options”

Defines the version of the file format. Should be exactly as shown in the example.

“name”

A short name for the modpack. This is used for version and dependency tracking, so should not contain minor version information, and should not change once a modpack has been released for a given major version of Freeciv21. Case-insensitive.

“version”

Textual version information. If another modpack uses this one as a dependency, this string is subject to version number comparison (using the rules of Freeciv21’s cvercmp library, which should give sensible results for most version numbering schemes).

“type”

This must be one of the following:

  • Ruleset: foo.serv, foo/*.ruleset, foo/*.lua, etc.

  • Tileset: foo.tilespec, foo/*.png, etc.

  • Soundset: foo.soundspec, foo/*.ogg, etc.

  • Musicset: foo.musicspec, foo/*.ogg, etc.

  • Scenario: foo.sav; installed to a version-independent location.

  • Modpack: Conventionally used for modpacks that contain more than one of the above kinds of material

  • Group: Contains no files but only depends on other modpacks At the moment, only Scenario causes special behavior.

“base_url”

URL to prepend to the src filenames in the files list. May be relative to the .json file – starting with ./ – or absolute in which case the files can be on some web server different to where the .json file lives.

The files list defines the individual files comprising your modpack. It must list every file individually; any files in the same directory on the webserver that are not listed will not be downloaded. Entries can be strings as shown above, in which case the same file name is used for downloading relative to info.base_url and installing relative to the data directory. If the installed name is different from the name on the server, the following syntax can be used instead:

{
  "url": "some-remote-file",
  "dest": "where-to-install-it"
}

The URL can be either relative (to info.base_url) or absolute. The two syntaxes can be mixed in the same modpack.

Note

Forward slash / (and not backslash \) should be used to separate directories.

Some advice on the structure of files in modpacks:

  • You should generally install files in a directory named after the modpack, with a few exceptions (.serv, .tilespec, .soundspec, and .musicspec files must be installed to the top level, and should reference files in your subdirectory). Individual files and directories install names should usually not embed version numbers, dates, etc., so that when a new version of modpack X is installed, it cleanly overwrites the old version, rather than leaving both cluttering up the user’s installation.

  • The modpack installer does not stop different modpacks overwriting each other’s files, so published modpacks should be disciplined about namespace usage. If you’ve derived from someone else’s modpack, you should probably give your derivative new filenames, so that both can be installed simultaneously.

  • There is no white-out facility to delete files from a user’s installation – if a newer version of a modpack has fewer files than an old one, the old file will persist in some users’ installations, so your modpacks should be designed to be tolerant of that.

  • At the moment, there is no restriction on what kind of files a given type can install, but modpacks should stick to installing the advertised kinds of content. It’s OK to install extra files such as documentation in any case (LICENSE/COPYING, README.txt, etc.).

  • If your modpack contains a ruleset, you should usually install a .serv file at the top level (which can be a one-line file consisting of rulesetdir <name>, as this is needed for the server to enumerate the available rulesets.

In some cases, a modpack may depend on other modpacks, for instance if it reuses some of their files. This can be handled by declaring a dependency with respect to the other modpack. Dependencies are listed in the optional dependencies list of the JSON file. Each entry in that list must contain the following object:

{
  "modpack": "...",
  "url": "...",
  "type": "...",
  "version": "..."
}

The keys are explained below:

  • modpack: What the dependency modpack calls itself when installed (that is, name from its .json file).

  • url: URL to download modpack if needed. Can be relative or absolute.

  • type: Must match type from dependency’s .json file.

  • version: Minimum version of dependency (as declared in its .json file). Subject to version number comparison algorithm.

If the modpack installer thinks the required version, or a newer version, of the dependency is already installed, it will do nothing, otherwise it will download the dependency modpack, and any of its own dependencies, recursively.

3. Individual Modpack Files

These are the files comprising the modpack (*.ruleset, *.png, etc.), that will be copied verbatim to the user’s Freeciv21 profile directory and read by the Freeciv21 client and server. The modpack installer does not modify the files in any way.

The files must be hosted individually on the web server; the modpack installer tool cannot unpack any archives such as .zip files. Individual scenarios can be compressed (e.g. .sav.gz, as the Freeciv21 engine can uncompress these files.

Because the *.json file can change the file paths / names on download, the layout on the modpack server doesn’t have to correspond with the installed layout. An individual file can be shared between multiple modpacks, if you want.