Skip to content
This repository was archived by the owner on May 26, 2018. It is now read-only.
This repository was archived by the owner on May 26, 2018. It is now read-only.

Suggestion: Improved JSON format for mod info #637

@rbuckton

Description

@rbuckton

Introduction

After having spent quite a bit of time working with NodeJS and NPM, I've become quite impressed with the power and simplicity of the package.json file format. I've noticed that FML internally uses a somewhat similar format in the form of the mcmod.info file, but I've found that there are a few drawbacks to the format:

  • While most mods embed mcmod.info in the JAR, there doesn't seem to be a public repository of these files. As a result, each mod needs to write its own update checking logic (or rely on a shared library).
  • The "version" field of mcmod.info is arbitrary. As a result, update checking logic must be unique to the version format used by the mod author.
  • The "dependencies" and "requiredMods" fields of mcmod.info do not specify version information.

The package.json format used by nodejs shares similar characteristics with mcmod.info, but provides some additional capabilities:

  • The "version" field requires a canonical format, via semantic versioning.
  • The "dependencies" field is a map of required dependencies to their minimal version, using a specialized format for specifying version ranges.
  • The "repository" field contains information about where to clone or contribute to the package if it is open source.
  • The "bugs" field contains information about where to file bugs against the package.
  • The "directories" and "files" fields contain information about the contents of the package.

Proposal

I propose that a new JSON format be introduced for FML mods. This format would use the following structure:

NOTE: The following listing uses TypeScript interfaces to describe the structure of the JSON file.

  • The ? token following a field name marks the field as optional.
  • The | token between types means the field must be either of the types.
  • The [] tokens following a type or parenthesized type indicate an array.

NOTE: Not all of the existing fields from mcmod.info are listed below, and some have been renamed or moved. This does not mean they should be lost, but rather merged into this format as appropriate.

// The primary structure for the JSON file
interface Mod {
  // The name of the mod, used as a key for dependencies (previously "modid")
  name: string;

  // A descriptive name for the mod (previously "name")
  title?: string;

  // A long description for the mod
  description?: string;

  // Additional keywords or tags for the mod
  keywords?: string[];

  // The semantic version of the mod: http://semver.org
  version: string;

  // The primary author of the mod (previously "credits"/"authorList"). 
  author?: string | Person;

  // Additional contributors to the mod (previously "authorList")
  contributors?: (string | Person)[];

  // A url to the homepage for the mod
  homepage?: string;

  // A url to download the binary version of the mod
  url?: string | FileResource;

  // Urls to download additional resources for the mod
  urls?: (string | FileResource)[];

  // The source code repository for the mod, if it is open source
  repository?: string | Resource;

  // The means with which users can file bugs
  bugs?: BugTracker

  // Required dependencies for the mod (previously "dependencies", "requiredMods", "mcversion")
  dependencies?: DependencyMap;

  // Optional dependencies for the mod
  optionalDependencies?: DependencyMap

  // Developer dependencies for the mod
  devDependencies?: DependencyMap;

  // License information for the mod. See https://spdx.org/licenses/
  license?: string;

  // Directories in the mod (under the mods/[mod name] folder)
  directories?: string[];

  // Files in the mod (under the mods/[mod name] folder)
  files?: string;

  // Extensibility for future updates
  [key: string]: any;
}

// Extended information about a Person
interface Person {
  // The display name for the person
  name: string;

  // The email for the person 
  email?: string;

  // A url for the person (homepage, blog, profile, etc.)
  url?: string;
}

// Extended information about a url resource
interface Resource {
  // What type of resource is this? A file? A feed? A git repository?
  type: string;

  // The url to the resource
  url: string;
}

// Extended information about a file url resource
interface FileResource extends Resource {
  // The MD5 hash of the file resource (in hexadecimal)
  md5?: string;
  // The SHA1 hash of the file resource (in hexadecimal)
  sha1?: string;
}

// Extended information about a bug tracker
interface BugTracker {
  // A url to a public bug tracker
  url?: string;

  // An email for bug reports
  email?: string;
}

// A key-value map for dependencies to the required version spec:
interface DependencyMap {
  [dependency: string]: string;
}

Dependencies

A dependency can specify the version range required (useful both for version testing when loading the mod, and to allow loaders or mod management tools to check for updates and version mismatches. For an example of version ranges, see https://docs.npmjs.com/misc/semver.

Example

Here is an example from converting the mcmod.info for Thermal Foundation:

{
  "name": "ThermalFoundation",
  "title": "Thermal Foundation",
  "description": "The foundation of a Thermally enhanced world!",
  "version": "1.0.0-RC4+58",
  "author": "TeamCoFH",
  "contributors": [
    "KingLemming",
    "skyboy026",
    "ZeldoKavira"
  ],
  "homepage": "http://www.curse.com/mc-mods/minecraft/222880-thermal-foundation",
  "dependencies": {
    "Minecraft": "1.7.10",
    "MinecraftForge": "10.13.2",
    "CoFHCore": "3.0.0"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/CoFH/ThermalFoundation"
  },
  "bugs": {
    "url": "https://github.com/CoFH/Feedback/issues"
  },
  "files": [
    "ThermalFoundation-[1.7.10]1.0.0RC4-58.jar"
  ]
}

And here is an example for Forge:

{
  "name": "MinecraftForage",
  "title": "Forge",
  "version": "10.13.2+1291",
  "dependencies": {
    "Minecraft": "1.7.10"
  },  
  "homepage": "http://files.minecraftforge.net/",
  "author": "LexManos",
  "urls": [
    {
      "type": "Universal",
      "url": "http://files.minecraftforge.net/maven/net/minecraftforge/forge/1.7.10-10.13.2.1291/forge-1.7.10-10.13.2.1291-universal.jar",
      "md5": "e71e88c744588fdad48d3b3beb4935fc"
    },
    {
      "type": "Installer-win",
      "url": "http://files.minecraftforge.net/maven/net/minecraftforge/forge/1.7.10-10.13.2.1291/forge-1.7.10-10.13.2.1291-installer-win.exe",
      "md5": "0b8598a75955dedf99a56e39c5c721ce"
    },
    {
      "type": "Changelog",
      "url": "http://files.minecraftforge.net/maven/net/minecraftforge/forge/1.7.10-10.13.2.1291/forge-1.7.10-10.13.2.1291-changelog.txt"
    }
  ],
  "repository": {
    "type": "git",
    "url": "https://github.com/MinecraftForge/MinecraftForge"
  },
  "bugs": {
    "url": "https://github.com/MinecraftForge/MinecraftForge/issues"
  }
}

Benefits

By adopting this format, and assuming a central repository to which mod authors could publish these files, in addition to embedding them in the JAR, there would be a number of benefits:

  • Mod authors can easily specify version ranges for dependencies.
  • Mod authors have control over how their mods are downloaded (automatic updates, or require the user to navigate to a home page or an adfly link, etc).
  • A central repository (like http://modlist.mcf.li, Curse, or something else similar to http://npmjs.org) could manage these dependencies.
  • A tool similar to npm could be used to install and update mods on a server or client
  • Server operators could easily update their servers and ensure compatible versions of dependent mods are updated all at once.
  • Clients could easily download mods by following links in the JSON files stored either in a central repository or from a Minecraft server.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions