{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://catalog.lintel.tools/schemas/schemastore/minecraft-custom-main-menu-mod/latest.json",
  "title": "Minecraft Custom Main Menu Mod Schema",
  "description": "A schema describing the structure of the JSON configuration files used by the Custom Main Menu Minecraft mod.",
  "x-lintel": {
    "source": "https://www.schemastore.org/minecraft-custom-main-menu-mod.json",
    "sourceSha256": "381872f4fa5af31387447a89ead87783ab47c3ca2535d5ab4e48f3b2a2d326eb",
    "fileMatch": [
      "mainmenu.yml",
      "mainmenu.yaml",
      "mainmenu.json"
    ],
    "parsers": [
      "json",
      "yaml"
    ]
  },
  "type": "object",
  "properties": {
    "images": {
      "type": "object",
      "description": "A dictionary of image definitions which specify images to be displayed on the current menu.",
      "additionalProperties": false,
      "patternProperties": {
        "^.*$": {
          "$ref": "#/$defs/image"
        }
      }
    },
    "buttons": {
      "type": "object",
      "description": "A dictionary of button definitions which specify buttons to be displayed on the current menu.",
      "additionalProperties": false,
      "patternProperties": {
        "^.*$": {
          "$ref": "#/$defs/button"
        }
      }
    },
    "labels": {
      "type": "object",
      "description": "A dictionary of label definitions which specify text labels to be displayed on the current menu.",
      "additionalProperties": false,
      "patternProperties": {
        "^.*$": {
          "$ref": "#/$defs/label"
        }
      }
    },
    "other": {
      "type": "object",
      "description": "A dictionary of special properties such as splash texts, backgrounds, and panoramas.",
      "allOf": [
        {
          "properties": {
            "splash-text": {
              "$ref": "#/$defs/splashText"
            }
          }
        },
        {
          "properties": {
            "background": {
              "$ref": "#/$defs/background"
            }
          }
        },
        {
          "properties": {
            "panorama": {
              "$ref": "#/$defs/panorama"
            }
          }
        },
        {
          "not": {
            "anyOf": [
              {
                "required": [
                  "background",
                  "panorama"
                ]
              }
            ]
          }
        }
      ]
    }
  },
  "$defs": {
    "size": {
      "type": "object",
      "description": "A definition for the size of an element.",
      "properties": {
        "width": {
          "type": "integer",
          "description": "The width of the element in pixels."
        },
        "height": {
          "type": "integer",
          "description": "The height of the element in pixels."
        }
      }
    },
    "position": {
      "type": "object",
      "description": "A definition for the position of an element.",
      "properties": {
        "posX": {
          "type": "integer",
          "description": "The offset on the X-axis of the element on the screen from the alignment position.\nFor example: if the alignment is set to 'top_center' and the posX is set to 0, the element's left edge will be aligned with the center of the screen.\nIf posY is also set to 0, the element's top edge will be at the top of the screen."
        },
        "posY": {
          "type": "integer",
          "description": "The offset on the Y-axis of the element on the screen from the alignment position.\nFor example: if the alignment is set to 'top_center' and the posX is set to 0, the element's left edge will be aligned with the center of the screen.\nIf posY is also set to 0, the element's top edge will be at the top of the screen."
        }
      }
    },
    "rect": {
      "type": "object",
      "description": "A definition for a rectangular area. Can be used to define the position and size of buttons, images, and other elements.",
      "allOf": [
        {
          "$ref": "#/$defs/size"
        },
        {
          "$ref": "#/$defs/position",
          "required": [
            "posX",
            "posY"
          ]
        }
      ]
    },
    "alignment": {
      "type": "object",
      "properties": {
        "alignment": {
          "type": "string",
          "description": "The alignment of the element relative to the screen.",
          "enum": [
            "top_right",
            "top_left",
            "top_center",
            "right_center",
            "left_center",
            "center",
            "button",
            "bottom_right",
            "bottom_left",
            "bottom_center"
          ]
        }
      }
    },
    "image": {
      "type": "object",
      "description": "An image definition.",
      "allOf": [
        {
          "$ref": "#/$defs/rect"
        },
        {
          "$ref": "#/$defs/alignment"
        },
        {
          "type": "object",
          "description": "Image-specific properties.",
          "required": [
            "image"
          ],
          "properties": {
            "image": {
              "type": "string",
              "description": "An image resource identifier representing the image to be displayed."
            },
            "hoverImage": {
              "type": "string",
              "description": "An image resource identifier representing the image to be displayed when the mouse hovers over the image."
            },
            "slideshow": {
              "$ref": "#/$defs/slideshow"
            }
          }
        }
      ]
    },
    "slideshow": {
      "type": "object",
      "description": "Defines the image as a slideshow, which cycles through various images, having a fading transition between them.",
      "required": [
        "images",
        "displayDuration",
        "fadeDuration"
      ],
      "properties": {
        "images": {
          "type": "array",
          "description": "A list of An image resource identifiers representing the images to be displayed in the slideshow.",
          "items": {
            "type": "string"
          }
        },
        "displayDuration": {
          "type": "integer",
          "description": "The duration in Minecraft ticks that each image in the slideshow is displayed for before transitioning to the next."
        },
        "fadeDuration": {
          "type": "integer",
          "description": "The duration in Minecraft ticks that the transition between images in the slideshow lasts for."
        },
        "shuffle": {
          "type": "boolean",
          "description": "Whether the order of the images should be shuffled each time Minecraft runs."
        },
        "synced": {
          "type": "boolean",
          "description": "Synced is a property for slideshows, panoramas and splash texts on the current menu.\n\nIf it is set to true, instead of creating a new slideshow/panorama/splash text instance each time, the current menu will use the same one as the main menu. Therefore the panorama and/or the slideshow will continue to run where they left off when switching GUIs, and the splash text will stay the same.\n\nNotice that this property should only be set on the GUIs you want synced to the main menu, not on the main menu itself. Also if the main menu doesn't have a slideshow/panorama/splash text but you set it to sync in another menu, your game will probably crash.\n\nNotice that synced only works on a background slideshow, it will have no effect on an image that is a slideshow."
        }
      }
    },
    "button": {
      "type": "object",
      "description": "A button definition. Buttons execute actions when clicked, which can be: opening a GUI (including custom ones), connecting to a server, opening a link, or loading a world.",
      "allOf": [
        {
          "$ref": "#/$defs/rect"
        },
        {
          "$ref": "#/$defs/alignment"
        },
        {
          "type": "object",
          "description": "Button-specific properties.",
          "required": [
            "text"
          ],
          "properties": {
            "text": {
              "type": "string",
              "description": "A text resource identifier representing the text to be displayed on the button. Can be an empty string - this is useful when you want to create an 'icon button' through the 'texture' property."
            },
            "hoverText": {
              "type": "string",
              "description": "A text resource identifier representing the text to be displayed on the button when the mouse hovers over it."
            },
            "normalTextColor": {
              "type": "integer",
              "description": "The color of the text on the button. Has to be a hexadecimal color value represented as a decimal number."
            },
            "hoverTextColor": {
              "type": "integer",
              "description": "The color of the text on the button when the mouse hovers over it. Has to be a hexadecimal color value represented as a decimal number."
            },
            "textOffsetX": {
              "type": "integer",
              "description": "The offset on the X-axis of the text inside the button."
            },
            "textOffsetY": {
              "type": "integer",
              "description": "The offset on the Y-axis of the text inside the button."
            },
            "texture": {
              "type": "string",
              "description": "An image resource identifier representing the image to be displayed on the button i.e. the button's texture/background image. The image has to contain a normal and a hovered version of the button, one on top of the other."
            },
            "imageWidth": {
              "type": "integer",
              "description": "The width of the button's texture/background image in pixels. By default it is the same width as the button."
            },
            "imageHeight": {
              "type": "integer",
              "description": "The height of the button's texture/background image in pixels. By default it is the same height as the button."
            },
            "pressSound": {
              "type": "string",
              "description": "An audio resource identifier representing the sound to be played when the button is pressed."
            },
            "hoverSound": {
              "type": "string",
              "description": "An audio resource identifier representing the sound to be played when the mouse hovers over the button."
            },
            "tooltip": {
              "type": "string",
              "description": "A text resource identifier representing the text to be displayed in a tooltip when the mouse hovers over the button."
            },
            "action": {
              "$ref": "#/$defs/buttonAction"
            },
            "wrappedButton": {
              "type": "string",
              "description": "The ID of a button added by another mod.\n\nCustom Main Menu removes all buttons added by other mods because they don't fit the schema used by CMM.\n\nUsing Wrapped Buttons you can create buttons that mimic the functionality of those removed buttons, with the added capability of being able to define and customize them like any other CMM button.\n\nFor them to work you need to find out the button ID of the button you want to re-add - look into your latest FML client log and search for 'wrapped button'. All removed mod buttons are logged with their respective button ID."
            }
          }
        }
      ]
    },
    "buttonAction": {
      "type": "object",
      "description": "The action to be executed when the button is clicked.",
      "properties": {
        "type": {
          "anyOf": [
            {
              "type": "string",
              "const": "openLink",
              "description": "Opens a link in the default browser."
            },
            {
              "type": "string",
              "const": "openGui",
              "description": "Opens a GUI. Can also open a custom GUI."
            },
            {
              "type": "string",
              "const": "connectToServer",
              "description": "Connects to a server."
            },
            {
              "type": "string",
              "const": "loadWorld",
              "description": "Loads a world."
            },
            {
              "type": "string",
              "const": "openFolder",
              "description": "Opens a folder."
            },
            {
              "type": "string",
              "const": "quit",
              "description": "Quits the game."
            },
            {
              "type": "string",
              "const": "refresh",
              "description": "Refreshes the current menu."
            }
          ]
        }
      },
      "allOf": [
        {
          "if": {
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "openLink"
              }
            },
            "type": "object"
          },
          "then": {
            "required": [
              "link"
            ],
            "properties": {
              "link": {
                "type": "string",
                "description": "The URL to be opened."
              }
            },
            "type": "object"
          }
        },
        {
          "if": {
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "openGui"
              }
            },
            "type": "object"
          },
          "then": {
            "required": [
              "gui"
            ],
            "properties": {
              "gui": {
                "type": "string",
                "description": "The name of the GUI to be opened. Can also be a custom GUI ID.",
                "enum": [
                  "mods",
                  "singleplayer",
                  "singleplayer.createworld",
                  "multiplayer",
                  "options",
                  "languages",
                  "options.resourcepacks",
                  "options.snooper",
                  "options.sounds",
                  "options.video",
                  "options.controls",
                  "options.multiplayer"
                ]
              }
            },
            "type": "object"
          }
        },
        {
          "if": {
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "connectToServer"
              }
            },
            "type": "object"
          },
          "then": {
            "required": [
              "ip"
            ],
            "properties": {
              "ip": {
                "type": "string",
                "description": "The IP address of the server to connect to."
              }
            },
            "type": "object"
          }
        },
        {
          "if": {
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "loadWorld"
              }
            },
            "type": "object"
          },
          "then": {
            "required": [
              "dirName"
            ],
            "properties": {
              "dirName": {
                "type": "string",
                "description": "The name of the directory the save is located in (in the saves folder)."
              },
              "saveName": {
                "type": "string",
                "description": "Not really necessary, but might appear as the name of the save in certain dialogs while loading the world."
              }
            },
            "type": "object"
          }
        },
        {
          "if": {
            "required": [
              "type"
            ],
            "properties": {
              "type": {
                "const": "openFolder"
              }
            },
            "type": "object"
          },
          "then": {
            "required": [
              "folderName"
            ],
            "properties": {
              "folderName": {
                "type": "string",
                "description": "The name of the folder to be opened (with the .minecraft folder as the root)."
              }
            },
            "type": "object"
          }
        }
      ]
    },
    "text": {
      "type": "string",
      "description": "A text resource identifier representing the text to be displayed."
    },
    "label": {
      "type": "object",
      "description": "A label definition. Labels are used to display text on the screen.",
      "allOf": [
        {
          "$ref": "#/$defs/size"
        },
        {
          "$ref": "#/$defs/alignment"
        },
        {
          "type": "object",
          "description": "Label-specific properties.",
          "required": [
            "text"
          ],
          "properties": {
            "text": {
              "type": "string",
              "description": "A text resource identifier representing the text to be displayed."
            },
            "hoverText": {
              "type": "string",
              "description": "A text resource identifier representing the text to be displayed when the mouse hovers over it."
            },
            "fontSize": {
              "type": "integer",
              "description": "The multiplier of the font size. 2 would be twice as big, 0.5 would be half as big, etc. The default font size is 1."
            },
            "color": {
              "type": "integer",
              "description": "The color of the text. Has to be a hexadecimal color value represented as a decimal number."
            },
            "hoverColor": {
              "type": "integer",
              "description": "The color of the text when the mouse hovers over it. Has to be a hexadecimal color value represented as a decimal number."
            },
            "anchor": {
              "type": "string",
              "description": "The anchor of the text. Makes the text left, center, or right aligned.",
              "enum": [
                "start",
                "middle",
                "end"
              ]
            },
            "pressSound": {
              "type": "string",
              "description": "An audio resource identifier representing a sound to play when the label is pressed."
            },
            "hoverSound": {
              "type": "string",
              "description": "An audio resource identifier representing a sound to play when the mouse hovers over the label."
            }
          }
        }
      ]
    },
    "background": {
      "description": "A regular background of the current menu. Can be a static image, a slideshow, or the default background of eg. the options menu.\n\nNotice that you cannot have both a background image and a panorama at the same time.",
      "oneOf": [
        {
          "type": "object",
          "required": [
            "image"
          ],
          "properties": {
            "image": {
              "type": "string",
              "description": "An image resource identifier representing an an image to be displayed."
            },
            "mode": {
              "type": "string",
              "description": "The image sizing/positioning mode.",
              "anyOf": [
                {
                  "type": "string",
                  "const": "fill",
                  "description": "The image is upscaled to cover the entire screen. The aspect ratio of the image is preserved, so parts of the image might be cut off. This mode will not produce any black bars."
                },
                {
                  "type": "string",
                  "const": "stretch",
                  "description": "The image is stretched to cover the entire screen. The aspect ratio of the image is not preserved, so the image might look distorted. This mode will not produce any black bars."
                },
                {
                  "type": "string",
                  "const": "center",
                  "description": "The image is simple placed on the center of the screen. The aspect ratio of the image is preserved, as well as the original size of the image. This mode will produce black bars on the sides of the image if the image is not wide and tall enough to cover the entire screen."
                },
                {
                  "type": "string",
                  "const": "tile",
                  "description": "The image is tiled to cover the entire screen. The aspect ratio of the image is preserved, as well as the original size of the image. This mode will not produce any black bars."
                }
              ]
            },
            "slideshow": {
              "$ref": "#/$defs/slideshow"
            }
          }
        },
        {
          "type": "string",
          "description": "The default background of the vanilla options menu (dirt).",
          "const": "options"
        }
      ]
    },
    "panorama": {
      "type": "object",
      "description": "A panorama background of the current menu, made up of 6 images. \n\nNotice that you cannot have both a background image and a panorama at the same time",
      "properties": {
        "images": {
          "description": "Either a list of image resource identifiers representing images to be displayed in the panorama, or a single image resource identifier in the form of a string.",
          "oneOf": [
            {
              "type": "array",
              "description": "A list of image resource identifiers representing images to be displayed in the panorama.",
              "items": {
                "type": "string"
              },
              "maxItems": 6,
              "minItems": 6
            },
            {
              "type": "string",
              "description": "An image resource identifier. The provided image will be used for all 6 panorama slides.\n\nIf an image resource identifier containing '%c' is provided, then any occurrences of '%c' in the string will be replaced with the current index of the image (0-5), for eg. 'panorama_%c.png' will be replaced with 'panorama_0.png', 'panorama_1.png', etc. at runtime\n\nThis is useful when you don't want to individually specify the resource path for each image in the panorama, but instead want to use a naming convention for the images, for eg. 'panorama_0.png', 'panorama_1.png', etc."
            }
          ]
        },
        "blur": {
          "type": "boolean",
          "description": "Whether the panorama should be blurred."
        },
        "gradient": {
          "type": "boolean",
          "description": "Whether the panorama should have a top-to-bottom white-to-back gradient overlay."
        },
        "animate": {
          "type": "boolean",
          "description": "Whether the panorama should spin like normal."
        },
        "animationSpeed": {
          "type": "integer",
          "description": "The integer multiple of the speed of the panorama animation. 1 is the default speed, 2 is double the speed, -1 makes it play in reverse, etc."
        },
        "position": {
          "type": "integer",
          "description": "At which position the panorama should start from (or stay at, if 'animate' is false).\n\nTODO: What is the range and step of this property?"
        },
        "synced": {
          "type": "boolean",
          "description": "Synced is a property for slideshows, panoramas and splash texts on the current menu.\n\nIf it is set to true, instead of creating a new slideshow/panorama/splash text instance each time, the current menu will use the same one as the main menu. Therefore the panorama and/or the slideshow will continue to run where they left off when switching GUIs, and the splash text will stay the same.\n\nNotice that this property should only be set on the GUIs you want synced to the main menu, not on the main menu itself. Also if the main menu doesn't have a slideshow/panorama/splash text but you set it to sync in another menu, your game will probably crash.\n\nNotice that synced only works on a background slideshow, it will have no effect on an image that is a slideshow."
        }
      }
    },
    "splashText": {
      "type": "object",
      "description": "A splash text definition. Splash texts are the random text that appears on the main menu.",
      "allOf": [
        {
          "$ref": "#/$defs/position",
          "required": [
            "posX",
            "posY"
          ]
        },
        {
          "$ref": "#/$defs/alignment"
        },
        {
          "type": "object",
          "description": "Splash text-specific properties.",
          "properties": {
            "color": {
              "type": "integer",
              "description": "The color of the text. Has to be a hexadecimal color value represented as a decimal number."
            },
            "texts": {
              "type": "string",
              "description": "A text resource identifier representing the text to be displayed. Separate splash texts are separated by newlines."
            },
            "synced": {
              "type": "boolean",
              "description": "Synced is a property for slideshows, panoramas and splash texts on the current menu.\n\nIf it is set to true, instead of creating a new slideshow/panorama/splash text instance each time, the current menu will use the same one as the main menu. Therefore the panorama and/or the slideshow will continue to run where they left off when switching GUIs, and the splash text will stay the same.\n\nNotice that this property should only be set on the GUIs you want synced to the main menu, not on the main menu itself. Also if the main menu doesn't have a slideshow/panorama/splash text but you set it to sync in another menu, your game will probably crash.\n\nNotice that synced only works on a background slideshow, it will have no effect on an image that is a slideshow."
            }
          }
        }
      ]
    }
  },
  "additionalProperties": true
}
