Mod Pack String (proposal)

Doesn't fit in the other categories, like libraries, small fixes or modpacks.
Post Reply
Hornwitser
Fast Inserter
Fast Inserter
Posts: 205
Joined: Fri Oct 05, 2018 4:34 pm
Contact:

Mod Pack String (proposal)

Post by Hornwitser »

Mod Pack String is a string format I'm proposing for exchanging a complete mod pack setup between client and server tools that deal with mods. They are similar to Blueprint Strings and for example allow a user to easily transfer a pack of mods including the mod settings between different mod and server managers.

Basic Format

A Mod Pack String is a JSON structure that has been compressed with zlib deflate and then base64 encoded. This is very similar to blueprint strings except there's no version byte in front. The root of the JSON structure is a ModString object containing all of the information of the mod pack. Note that all fields documented here are required to be present unless explicitly marked optional.

ModString object
  • name <string> - The name of this mod pack. Should not be an empty string.
  • description <string> - A description for this mod pack. May be an empty string if the user provides no description for this mod pack.
  • factorio_version <string>- The exact version of Factorio this Mod Pack String was made for, i.e. 1.1.68. Partial versions like 1.1 should not be used.
  • mods <ModEntry[]> - Contains an array of ModEntry objects defining the mods of this mod pack. The order of the mods is unspecified and must not be relied upon. Multiple mod entries with the same name must not be present in the array. The builtin base mod should always be present in the array. The builtin core mod should not be present in the array.
  • settings <object> - Contains ModSettings objects under the "startup", "runtime-global" and "runtime-per-user" keys which defines the mod settings used in this mod pack and correspond to the three scopes a mod setting may be present under in the game.
    • startup <ModSettings> - Startup settings for mods.
    • runtime-global <ModSettings> - Map settings for mods, this is only relevant when creating a new save.
    • runtime-per-user <ModSettings> - Per player settings for mods, this is only relevant when creating a new save.
ModEntry
  • name <string> - Internal name of the mod, this is the value of the "name" field in the mod's info.json file.
  • enabled <boolean> - If the mod should be loaded. Including a mod that is not loaded has two use cases: To disable the base mod that is bundled with the game, and to provide optional mods in a mod pack that a user can easily choose to enable or not. This field should not be used for dumping all the disabled mods a user may have in their mods folder into a mod pack.
  • version <string> - Version of the mod, this is the value of the "version" field in the mod's info.json file.
  • sha1 <string> (optional) - 40 lower case hex digits representing the SHA1 digest of the mod's zip file. If present this should be used to validate the integrity of the mod.

ModSettings

Object mapping mod setting names to <ModSetting> objects, the property names correspond to the internal name mods have defined and access the setting under. If there are no settings for this scope then this is an empty object.
  • setting-name <ModSetting> (optional) - Value for the mod setting of the given name.
ModSetting

The value of a mod setting is an object containing the single property "value" with the actual value of the setting. This mirrors how the game serialize mod settings into mod-settings.dat.
  • value <boolean|number|string|object> - Value of the mod setting.
JSON Schema

A complete description of the format follows in JSON Schema.

Code: Select all

{
    "$id": "ModString",
    "$defs": {
        "ModEntry": {
            "type": "object",
            "required": ["name", "enabled", "version"],
            "properties": {
                "name": { "type": "string" },
                "enabled": { "type": "boolean" },
                "version": { "type": "string", "format": "^\\d+\\.\\d+\\.\\d+$" },
                "sha1": { "type": "string", "format": "^[0-9a-f]{40}$" }
            }
        },
        "ModSetting": {
            "type": "object",
            "required": ["value"],
            "properties": {
                "value": {
                    "type": ["boolean", "number", "string", "object"],
                    "properties": {
                    	"r": { "type": "number" },
                    	"g": { "type": "number" },
                    	"b": { "type": "number" },
                    	"a": { "type": "number" }
                    }
                }
            }
        },
        "ModSettings": {
            "type": "object",
            "additionalProperties": { "$ref": "#/$defs/ModSetting" }
        }
    },
    "type": "object",
    "required": ["name", "description", "factorio_version", "mods", "settings"],
    "properties": {
        "name": { "type": "string" },
        "description": { "type": "string" },
        "factorio_version": { "type": "string", "format": "^\\d+\\.\\d+\\.\\d+$" },
        "mods": {
            "type": "array",
            "items": { "$ref": "#/$defs/ModEntry" }
        },
        "settings": {
            "type": "object",
            "required": ["startup", "runtime-global", "runtime-per-user"],
            "properties": {
                "startup": { "$ref": "#/$defs/ModSettings" },
                "runtime-global": { "$ref": "#/$defs/ModSettings" },
                "runtime-per-user": { "$ref": "#/$defs/ModSettings" }
            }
        }
    }
}
Creating Mod Pack Strings

The simplest way to create a mod pack string is to inspect game.active_mods, settings and player.mod_settings from the Lua API while the game is running, and then build a JSON table from those. As an example, the following command will print a mod pack string of the currently loaded mods to the client/server log file:

Code: Select all

/command
local modpack = {
    name="pack", description="", factorio_version=game.active_mods.base, mods={},
    settings={ startup={}, ["runtime-global"]={}, ["runtime-per-user"]={} } }
for n, v in pairs(game.active_mods) do table.insert(modpack.mods, { name=n, enabled=true, version=v }) end
local function set(settings, scope)
    for n, v in pairs(settings) do modpack.settings[scope][n] = v end
end
set(settings.startup, "startup")
set(settings.global, "runtime-global")
if game.player then
    set(game.player.mod_settings, "runtime-per-user")
else
    set(settings.player, "runtime-per-user")
end
log(game.encode_string(game.table_to_json(modpack)))
It is possible to create a modpack string by inspecting the mods in the mods directory along with mod-list.json and mod-settings.dat, but this should be avoided because it has the major drawback that mod-settings.dat contains all settings for all mods ever loaded (unless it was freshly created). Another option is to recreate the Lua settings stage and run it for all enabled mods and then use the resulting settings prototypes, but that is rather involved to set up.

Applying Mod Pack Strings

To apply a Mod Pack String to a mods folder, obtain any missing mods from The Mod Portal API, then replace mod-list.json such that it enables mods enabled in the mod pack string and disabled all other mods. Then update mod-settings.dat (a description of the format is on the wiki) by overwriting any settings defined in the modpack and leaving the rest untouched. The structure of the settings key mirror that of the structure of the mod-settings.dat file. Once done Factorio should start up with the same mods and settings as the mod pack.

Editing Mod Pack Strings

The goal of the Mod Pack string is to contain only what's necessary to recreate a given configuration of mods and their settings, and for this reason it does not contain enough information to effectively edit it on its own. Therefore the best approach to edit a mod pack string is to download all the mods in it in order to extract the necessary dependency and settings prototype information from the mods to then build a UI and edit tools from that. While it would be possible to include this information in the mod pack string it would bloat the string and the information would be of little use because as soon as any mods are added, updated or removed it's no longer valid.

Software Supporting Mod Pack Strings

Nothing that I know of. I'm currently working on mod management for Clusterio which will support importing and exporting Mod Packs with strings as defined here. Feel free to add support for mod pack strings in your own software, if you have any suggestions, issues, or know about something using mod pack strings please let me know.

Changes

2024-01-21: Added color-setting values to the JSON schema.

Post Reply

Return to “Mod Packs / Libs / Special Interest”