{
  "$id": "https://json.schemastore.org/fabric.mod.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "definitions": {
    "entrypoint": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "adapter": {
              "type": "string",
              "description": "The language adapter to use",
              "default": "default"
            },
            "value": {
              "type": "string",
              "description": "The entrypoint function or class"
            }
          },
          "required": ["value"]
        },
        {
          "type": "string",
          "description": "The entrypoint function or class"
        }
      ]
    },
    "contactInfo": {
      "type": "object",
      "properties": {
        "email": {
          "type": "string",
          "description": "Contact e-mail pertaining to the mod"
        },
        "irc": {
          "type": "string",
          "description": "IRC channel pertaining to the mod. Must be of a valid URL format"
        },
        "homepage": {
          "type": "string",
          "description": "Project or user homepage. Must be a valid HTTP/HTTPS address"
        },
        "issues": {
          "type": "string",
          "description": "Project issue tracker. Must be a valid HTTP/HTTPS address"
        },
        "sources": {
          "type": "string",
          "description": "Project source code repository. Must be a valid URL"
        }
      },
      "additionalProperties": {
        "type": "string",
        "description": "Custom contact or profile information"
      }
    },
    "environment": {
      "type": "string",
      "enum": ["*", "client", "server"],
      "description": "The environment where this mod will be loaded"
    },
    "nestedJar": {
      "type": "object",
      "properties": {
        "file": {
          "type": "string",
          "description": "A string value pointing to a path from the root of the JAR to a nested JAR which should be loaded alongside the outer mod JAR"
        }
      },
      "required": ["file"]
    },
    "person": {
      "oneOf": [
        {
          "type": "string",
          "description": "The name of the person"
        },
        {
          "type": "object",
          "properties": {
            "name": {
              "type": "string",
              "description": "The name of the person"
            },
            "contact": {
              "description": "Contact information for the person",
              "$ref": "#/definitions/contactInfo"
            }
          },
          "required": ["name"]
        }
      ]
    },
    "versionRanges": {
      "oneOf": [
        {
          "$ref": "#/definitions/versionRange"
        },
        {
          "type": "array",
          "description": "Multiple version ranges that are combined with an \"OR\" relationship - only one of the ranges needs to match",
          "items": {
            "$ref": "#/definitions/versionRange"
          }
        }
      ]
    },
    "versionRange": {
      "type": "string",
      "description": "A version range that matches versions. The following variants are supported:\n\n- A single asterisk matches any version.\n- Ranges following NPM semver specification including >=, >, =, <, <=, X-ranges (1.x), tilde ranges (fixed minor) and caret ranges (fixed major).\n- Additionally exact string matches will always be performed.",
      "x-intellij-html-description": "<p>A version range or an array of those that match versions. The following variants are supported:</p><ul><li><code>*</code> matches any version.</li><li>Ranges following <a href=\"https://docs.npmjs.com/about-semantic-versioning\">NPM semver specification</a>:<ul><li><code>&gt;=</code>, <code>&gt;</code>, <code>=</code>, <code>&lt;</code> and <code>&lt;</code></li><li>X-ranges to specify variable components, e.g. <code>1.x</code></li><li>tilde ranges that allow patch version changes, e.g. <code>~1.2.3</code></li><li>caret ranges that allow up to minor version changes, e.g. <code>^1.2.3</code></li></ul></li><li>Exact string matches are always performed as well.</li></ul><p>If an array of ranges is used, they're treated as in an \"OR\" relationship - only one of the ranges needs to match.</p>",
      "markdownDescription": "A version range or an array of those that match versions. The following variants are supported:\n\n- `*` matches any version.\n- Ranges following [NPM semver specification](https://docs.npmjs.com/about-semantic-versioning):\n  - `>=`, `>`, `=`, `<` and `<=`\n  - X-ranges to specify variable components, e.g. `1.x`\n  - tilde ranges that allow patch version changes, e.g. `~1.2.3`\n  - caret ranges that allow up to minor version changes, e.g. `^1.2.3`\n- Exact string matches are always performed as well.\n\nIf an array of ranges is used, they're treated as in an \"OR\" relationship - only one of the ranges needs to match."
    }
  },
  "properties": {
    "id": {
      "type": "string",
      "pattern": "^[a-z][a-z0-9-_]{1,63}$",
      "description": "The mod identifier"
    },
    "version": {
      "type": "string",
      "description": "The mod version"
    },
    "schemaVersion": {
      "type": "integer",
      "description": "The version of the fabric.mod.json schema",
      "const": 1
    },
    "environment": {
      "$ref": "#/definitions/environment"
    },
    "entrypoints": {
      "type": "object",
      "properties": {
        "main": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/entrypoint"
          },
          "description": "The entrypoint for all environments (classes must implement ModInitializer)"
        },
        "client": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/entrypoint"
          },
          "description": "The entrypoint for the client environment (classes must implement ClientModInitializer)"
        },
        "server": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/entrypoint"
          },
          "description": "The entrypoint for the server environment (classes must implement DedicatedServerModInitializer)"
        },
        "preLaunch": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/entrypoint"
          },
          "description": "The entrypoint called just before the game instance is created (classes must implement PreLaunchEntrypoint)"
        },
        "fabric-datagen": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/entrypoint"
          },
          "description": "The entrypoint for the data generator environment (classes must implement DataGeneratorEntrypoint)"
        },
        "fabric-gametest": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/entrypoint"
          },
          "description": "The entrypoint for the Game Test environment (classes must implement FabricGameTest)"
        }
      },
      "additionalProperties": {
        "type": "array",
        "items": {
          "$ref": "#/definitions/entrypoint"
        },
        "description": "Custom mod entrypoints"
      },
      "description": "The entrypoints used by this mod"
    },
    "jars": {
      "type": "array",
      "description": "Contains an array of nestedJar objects",
      "items": {
        "$ref": "#/definitions/nestedJar"
      }
    },
    "languageAdapters": {
      "type": "object",
      "description": "A string→string dictionary, connecting namespaces to LanguageAdapter implementations",
      "additionalProperties": {
        "type": "string"
      }
    },
    "mixins": {
      "type": "array",
      "items": {
        "oneOf": [
          {
            "type": "string",
            "description": "Path to mixin file from the root of the JAR"
          },
          {
            "type": "object",
            "properties": {
              "config": {
                "type": "string",
                "description": "Path to mixin file from the root of the JAR"
              },
              "environment": {
                "$ref": "#/definitions/environment"
              }
            }
          }
        ]
      }
    },
    "accessWidener": {
      "type": "string",
      "description": "Path to an access widener definition file"
    },
    "depends": {
      "type": "object",
      "description": "id→versionRange map for dependencies. Failure to meet these causes a hard failure",
      "additionalProperties": {
        "$ref": "#/definitions/versionRanges"
      }
    },
    "recommends": {
      "type": "object",
      "description": "id→versionRange map for dependencies. Failure to meet these causes a soft failure (warning)",
      "additionalProperties": {
        "$ref": "#/definitions/versionRanges"
      }
    },
    "suggests": {
      "type": "object",
      "description": "id→versionRange map for dependencies. Are not matched and are mainly used as metadata",
      "additionalProperties": {
        "$ref": "#/definitions/versionRanges"
      }
    },
    "conflicts": {
      "type": "object",
      "description": "id→versionRange map for dependencies. A successful match causes a soft failure (warning)",
      "additionalProperties": {
        "$ref": "#/definitions/versionRanges"
      }
    },
    "breaks": {
      "type": "object",
      "description": "id→versionRange map for dependencies. A successful match causes a hard failure",
      "additionalProperties": {
        "$ref": "#/definitions/versionRanges"
      }
    },
    "name": {
      "type": "string",
      "description": "Name of the mod"
    },
    "description": {
      "type": "string",
      "description": "Description of the mod"
    },
    "authors": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/person"
      },
      "description": "The direct authorship information"
    },
    "contributors": {
      "type": "array",
      "items": {
        "$ref": "#/definitions/person"
      },
      "description": "Contributors to this mod"
    },
    "contact": {
      "$ref": "#/definitions/contactInfo",
      "description": "Contact information for the mod"
    },
    "license": {
      "oneOf": [
        {
          "type": "string"
        },
        {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      ],
      "description": "The license the mod uses"
    },
    "icon": {
      "oneOf": [
        {
          "type": "string",
          "description": "The path to a single .PNG file from the root of the JAR"
        },
        {
          "type": "object",
          "description": "A string→string dictionary, where the keys conform to widths of each PNG file, and the values are said files' paths",
          "propertyNames": {
            "pattern": "^[1-9][0-9]*$"
          },
          "additionalProperties": {
            "type": "string",
            "description": "The path to a single .PNG file from the root of the JAR"
          }
        }
      ]
    },
    "custom": {
      "type": "object",
      "description": "A map of namespace:id→value for custom data fields."
    }
  },
  "required": ["id", "version", "schemaVersion"],
  "type": "object"
}
