summaryrefslogtreecommitdiff
path: root/meta
diff options
context:
space:
mode:
Diffstat (limited to 'meta')
-rw-r--r--meta/.dockerignore11
-rw-r--r--meta/.envrc1
-rw-r--r--meta/.gitignore17
-rw-r--r--meta/COPYING52
-rw-r--r--meta/README.md37
-rw-r--r--meta/caches/forge_cache/.keep0
-rw-r--r--meta/caches/http_cache/.keep0
-rw-r--r--meta/config.example.sh13
-rw-r--r--meta/flake.lock92
-rw-r--r--meta/flake.nix35
-rw-r--r--meta/garnix.yaml5
-rw-r--r--meta/init.sh29
-rw-r--r--meta/meta/__init__.py1
-rw-r--r--meta/meta/common/__init__.py125
-rw-r--r--meta/meta/common/fabric.py12
-rw-r--r--meta/meta/common/forge.py22
-rw-r--r--meta/meta/common/http.py6
-rw-r--r--meta/meta/common/java.py17
-rw-r--r--meta/meta/common/liteloader.py7
-rw-r--r--meta/meta/common/mojang-library-patches.json4269
-rw-r--r--meta/meta/common/mojang-minecraft-experiments.json159
-rw-r--r--meta/meta/common/mojang-minecraft-legacy-override.json585
-rw-r--r--meta/meta/common/mojang-minecraft-legacy-services.json218
-rw-r--r--meta/meta/common/mojang-minecraft-old-snapshots.json604
-rw-r--r--meta/meta/common/mojang.py23
-rw-r--r--meta/meta/common/neoforge.py14
-rw-r--r--meta/meta/common/quilt.py44
-rw-r--r--meta/meta/model/__init__.py363
-rw-r--r--meta/meta/model/enum.py32
-rw-r--r--meta/meta/model/fabric.py40
-rw-r--r--meta/meta/model/forge.py365
-rw-r--r--meta/meta/model/index.py46
-rw-r--r--meta/meta/model/java.py597
-rw-r--r--meta/meta/model/liteloader.py112
-rw-r--r--meta/meta/model/mojang.py344
-rw-r--r--meta/meta/model/neoforge.py241
-rw-r--r--meta/meta/run/__init__.py1
-rwxr-xr-xmeta/meta/run/generate_fabric.py143
-rwxr-xr-xmeta/meta/run/generate_forge.py467
-rw-r--r--meta/meta/run/generate_java.py537
-rwxr-xr-xmeta/meta/run/generate_liteloader.py118
-rwxr-xr-xmeta/meta/run/generate_mojang.py589
-rw-r--r--meta/meta/run/generate_neoforge.py170
-rwxr-xr-xmeta/meta/run/generate_quilt.py176
-rwxr-xr-xmeta/meta/run/index.py71
-rwxr-xr-xmeta/meta/run/update_fabric.py133
-rwxr-xr-xmeta/meta/run/update_forge.py419
-rw-r--r--meta/meta/run/update_java.py222
-rwxr-xr-xmeta/meta/run/update_liteloader.py37
-rwxr-xr-xmeta/meta/run/update_mojang.py199
-rw-r--r--meta/meta/run/update_neoforge.py317
-rwxr-xr-xmeta/meta/run/update_quilt.py131
-rw-r--r--meta/nix/dev.nix35
-rw-r--r--meta/nix/nixos/default.nix10
-rw-r--r--meta/nix/nixos/meta.nix70
-rw-r--r--meta/nix/packages.nix18
-rw-r--r--meta/nix/pkgs/blockgame-meta.nix70
-rw-r--r--meta/poetry.lock352
-rw-r--r--meta/public/.keep0
-rw-r--r--meta/pyproject.toml39
-rw-r--r--meta/renovate.json6
-rwxr-xr-xmeta/update.sh92
62 files changed, 12960 insertions, 0 deletions
diff --git a/meta/.dockerignore b/meta/.dockerignore
new file mode 100644
index 0000000000..373630e9e5
--- /dev/null
+++ b/meta/.dockerignore
@@ -0,0 +1,11 @@
+.git/
+.idea/
+
+caches/
+.idea/
+__pycache__/
+public/
+
+launcher/
+upstream/
+config/
diff --git a/meta/.envrc b/meta/.envrc
new file mode 100644
index 0000000000..3550a30f2d
--- /dev/null
+++ b/meta/.envrc
@@ -0,0 +1 @@
+use flake
diff --git a/meta/.gitignore b/meta/.gitignore
new file mode 100644
index 0000000000..7f7232ca89
--- /dev/null
+++ b/meta/.gitignore
@@ -0,0 +1,17 @@
+.idea/
+
+# direnv / Nix
+.direnv/
+.pre-commit-config.yaml
+
+result
+
+public/*/
+
+caches/
+!caches/*/.keep
+cache/
+__pycache__
+config.sh
+launcher
+upstream
diff --git a/meta/COPYING b/meta/COPYING
new file mode 100644
index 0000000000..d189af8385
--- /dev/null
+++ b/meta/COPYING
@@ -0,0 +1,52 @@
+Microsoft Public License (Ms-PL)
+
+This license governs use of the accompanying software. If you use the
+software, you accept this license. If you do not accept the license, do not
+use the software.
+
+1. Definitions
+The terms "reproduce," "reproduction," "derivative works," and "distribution"
+have the same meaning here as under U.S. copyright law. A "contribution" is
+the original software, or any additions or changes to the software. A
+"contributor" is any person that distributes its contribution under this
+license. "Licensed patents" are a contributor's patent claims that read
+directly on its contribution.
+
+2. Grant of Rights
+ (A) Copyright Grant- Subject to the terms of this license, including the
+ license conditions and limitations in section 3, each contributor grants
+ you a non-exclusive, worldwide, royalty-free copyright license to
+ reproduce its contribution, prepare derivative works of its contribution,
+ and distribute its contribution or any derivative works that you create.
+
+ (B) Patent Grant- Subject to the terms of this license, including the
+ license conditions and limitations in section 3, each contributor grants
+ you a non-exclusive, worldwide, royalty-free license under its licensed
+ patents to make, have made, use, sell, offer for sale, import, and/or
+ otherwise dispose of its contribution in the software or derivative works
+ of the contribution in the software.
+
+3. Conditions and Limitations
+ (A) No Trademark License- This license does not grant you rights to use
+ any contributors' name, logo, or trademarks.
+
+ (B) If you bring a patent claim against any contributor over patents that
+ you claim are infringed by the software, your patent license from such
+ contributor to the software ends automatically.
+
+ (C) If you distribute any portion of the software, you must retain all
+ copyright, patent, trademark, and attribution notices that are present in
+ the software.
+
+ (D) If you distribute any portion of the software in source code form,
+ you may do so only under this license by including a complete copy of
+ this license with your distribution. If you distribute any portion of the
+ software in compiled or object code form, you may only do so under a
+ license that complies with this license.
+
+ (E) The software is licensed "as-is." You bear the risk of using it. The
+ contributors give no express warranties, guarantees, or conditions. You
+ may have additional consumer rights under your local laws which this
+ license cannot change. To the extent permitted under your local laws, the
+ contributors exclude the implied warranties of merchantability, fitness
+ for a particular purpose and non-infringement. \ No newline at end of file
diff --git a/meta/README.md b/meta/README.md
new file mode 100644
index 0000000000..02b43e60f4
--- /dev/null
+++ b/meta/README.md
@@ -0,0 +1,37 @@
+# Prism Launcher Meta
+
+Scripts to generate jsons and jars that Prism Launcher will access.
+
+## Recommended Deployment
+
+Assuming you have a Flake-based NixOS configuration
+
+- Add Flake input:
+
+ ```nix
+ {
+ inputs.prism-meta.url = "github:PrismLauncher/meta";
+ }
+ ```
+
+- Import NixOS module and configure
+
+ ```nix
+ {inputs, ...}: {
+ imports = [inputs.prism-meta.nixosModules.default];
+ services.blockgame-meta = {
+ enable = true;
+ settings = {
+ DEPLOY_TO_GIT = "true";
+ GIT_AUTHOR_NAME = "Herpington Derpson";
+ GIT_AUTHOR_EMAIL = "herpderp@derpmail.com";
+ GIT_COMMITTER_NAME = "Herpington Derpson";
+ GIT_COMMITTER_EMAIL = "herpderp@derpmail.com";
+ };
+ };
+ }
+ ```
+
+- Rebuild and activate!
+- Trigger it `systemctl start blockgame-meta.service`
+- Monitor it `journalctl -fu blockgame-meta.service`
diff --git a/meta/caches/forge_cache/.keep b/meta/caches/forge_cache/.keep
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/caches/forge_cache/.keep
diff --git a/meta/caches/http_cache/.keep b/meta/caches/http_cache/.keep
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/caches/http_cache/.keep
diff --git a/meta/config.example.sh b/meta/config.example.sh
new file mode 100644
index 0000000000..835059f3af
--- /dev/null
+++ b/meta/config.example.sh
@@ -0,0 +1,13 @@
+export META_UPSTREAM_DIR=upstream
+export META_LAUNCHER_DIR=launcher
+export DEPLOY_TO_FOLDER=false
+export DEPLOY_FOLDER=/app/public/v1
+export DEPLOY_FOLDER_USER=http
+export DEPLOY_FOLDER_GROUP=http
+
+export DEPLOY_TO_GIT=true
+export GIT_AUTHOR_NAME="Herpington Derpson"
+export GIT_AUTHOR_EMAIL="herpderp@derpmail.com"
+export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
+export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
+export GIT_SSH_COMMAND="ssh -i ${BASEDIR}/config/deploy.key"
diff --git a/meta/flake.lock b/meta/flake.lock
new file mode 100644
index 0000000000..6d54022b39
--- /dev/null
+++ b/meta/flake.lock
@@ -0,0 +1,92 @@
+{
+ "nodes": {
+ "flake-parts": {
+ "inputs": {
+ "nixpkgs-lib": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1751413152,
+ "narHash": "sha256-Tyw1RjYEsp5scoigs1384gIg6e0GoBVjms4aXFfRssQ=",
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "rev": "77826244401ea9de6e3bac47c2db46005e1f30b5",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "flake-parts",
+ "type": "github"
+ }
+ },
+ "git-hooks": {
+ "inputs": {
+ "flake-compat": [],
+ "gitignore": "gitignore",
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1750779888,
+ "narHash": "sha256-wibppH3g/E2lxU43ZQHC5yA/7kIKLGxVEnsnVK1BtRg=",
+ "owner": "cachix",
+ "repo": "git-hooks.nix",
+ "rev": "16ec914f6fb6f599ce988427d9d94efddf25fe6d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "cachix",
+ "repo": "git-hooks.nix",
+ "type": "github"
+ }
+ },
+ "gitignore": {
+ "inputs": {
+ "nixpkgs": [
+ "git-hooks",
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1709087332,
+ "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+ "type": "github"
+ },
+ "original": {
+ "owner": "hercules-ci",
+ "repo": "gitignore.nix",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1751382304,
+ "narHash": "sha256-p+UruOjULI5lV16FkBqkzqgFasLqfx0bihLBeFHiZAs=",
+ "owner": "nixos",
+ "repo": "nixpkgs",
+ "rev": "d31a91c9b3bee464d054633d5f8b84e17a637862",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nixos",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "flake-parts": "flake-parts",
+ "git-hooks": "git-hooks",
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/meta/flake.nix b/meta/flake.nix
new file mode 100644
index 0000000000..aaacaa58e5
--- /dev/null
+++ b/meta/flake.nix
@@ -0,0 +1,35 @@
+{
+ description = "Prism Launcher Metadata generation scripts";
+
+ inputs = {
+ nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
+ flake-parts = {
+ url = "github:hercules-ci/flake-parts";
+ inputs.nixpkgs-lib.follows = "nixpkgs";
+ };
+ git-hooks = {
+ url = "github:cachix/git-hooks.nix";
+ inputs.flake-compat.follows = "";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+ };
+
+ outputs = inputs:
+ inputs.flake-parts.lib.mkFlake
+ {inherit inputs;}
+ {
+ imports = [
+ inputs.git-hooks.flakeModule
+
+ ./nix/dev.nix
+ ./nix/nixos
+ ./nix/packages.nix
+ ];
+
+ # Supported systems.
+ systems = [
+ "x86_64-linux"
+ "aarch64-linux"
+ ];
+ };
+}
diff --git a/meta/garnix.yaml b/meta/garnix.yaml
new file mode 100644
index 0000000000..312815da5d
--- /dev/null
+++ b/meta/garnix.yaml
@@ -0,0 +1,5 @@
+builds:
+ include:
+ - "checks.x86_64-linux.*"
+ - "devShells.*.*"
+ - "packages.*.*"
diff --git a/meta/init.sh b/meta/init.sh
new file mode 100644
index 0000000000..c9bfa8133f
--- /dev/null
+++ b/meta/init.sh
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash
+
+set -ex
+
+if [ -f config.sh ]; then
+ source config.sh
+fi
+
+export META_CACHE_DIR=${CACHE_DIRECTORY:-./caches}
+export META_UPSTREAM_DIR=${META_UPSTREAM_DIR:-${STATE_DIRECTORY:-.}/upstream}
+export META_LAUNCHER_DIR=${META_LAUNCHER_DIR:-${STATE_DIRECTORY:-.}/launcher}
+
+function init_repo {
+ # no op if target already exists
+ if [ -d "$1" ]; then
+ return 0
+ fi
+
+ # fail if no repo url is specified
+ if [ -z "$2" ]; then
+ echo "Can't initialize missing $1 directory. Please specify $3" >&2
+ return 1
+ fi
+
+ git clone "$2" "$1"
+}
+
+init_repo "$META_UPSTREAM_DIR" "$META_UPSTREAM_URL" "META_UPSTREAM_URL"
+init_repo "$META_LAUNCHER_DIR" "$META_LAUNCHER_URL" "META_LAUNCHER_URL"
diff --git a/meta/meta/__init__.py b/meta/meta/__init__.py
new file mode 100644
index 0000000000..05cee3e7d7
--- /dev/null
+++ b/meta/meta/__init__.py
@@ -0,0 +1 @@
+"""Meta package of meta"""
diff --git a/meta/meta/common/__init__.py b/meta/meta/common/__init__.py
new file mode 100644
index 0000000000..04e3bdfbb0
--- /dev/null
+++ b/meta/meta/common/__init__.py
@@ -0,0 +1,125 @@
+import os
+import os.path
+import datetime
+import hashlib
+import sys
+from urllib.parse import urlparse
+from typing import Any, Optional, Callable
+
+import requests
+from cachecontrol import CacheControl # type: ignore
+from cachecontrol.caches import FileCache # type: ignore
+
+LAUNCHER_MAVEN = "https://files.prismlauncher.org/maven/%s"
+
+
+def serialize_datetime(dt: datetime.datetime):
+ if dt.tzinfo is None:
+ return dt.replace(tzinfo=datetime.timezone.utc).isoformat()
+
+ return dt.isoformat()
+
+
+def cache_path():
+ if "META_CACHE_DIR" in os.environ:
+ return os.environ["META_CACHE_DIR"]
+ return "cache"
+
+
+def launcher_path():
+ if "META_LAUNCHER_DIR" in os.environ:
+ return os.environ["META_LAUNCHER_DIR"]
+ return "launcher"
+
+
+def upstream_path():
+ if "META_UPSTREAM_DIR" in os.environ:
+ return os.environ["META_UPSTREAM_DIR"]
+ return "upstream"
+
+
+def ensure_upstream_dir(path):
+ path = os.path.join(upstream_path(), path)
+ if not os.path.exists(path):
+ os.makedirs(path)
+
+
+def ensure_component_dir(component_id: str):
+ path = os.path.join(launcher_path(), component_id)
+ if not os.path.exists(path):
+ os.makedirs(path)
+
+
+def transform_maven_key(maven_key: str):
+ return maven_key.replace(":", ".")
+
+
+def replace_old_launchermeta_url(url: str):
+ o = urlparse(url)
+ if o.netloc == "launchermeta.mojang.com":
+ return o._replace(netloc="piston-meta.mojang.com").geturl()
+
+ return url
+
+
+def get_all_bases(cls: type, bases: Optional[list[type]] = None):
+ bases = bases or []
+ bases.append(cls)
+ for c in cls.__bases__:
+ get_all_bases(c, bases)
+ return tuple(bases)
+
+
+def merge_dict(base: dict[Any, Any], overlay: dict[Any, Any]):
+ for k, v in base.items():
+ if isinstance(v, dict):
+ merge_dict(v, overlay.setdefault(k, {})) # type: ignore
+ else:
+ if k not in overlay:
+ overlay[k] = v
+
+ return overlay
+
+
+def default_session():
+ cache = FileCache(os.path.join(cache_path(), "http_cache"))
+ sess = CacheControl(requests.Session(), cache)
+
+ sess.headers.update({"User-Agent": "PrismLauncherMeta/1.0"})
+
+ return sess
+
+
+def remove_files(file_paths: list[str]) -> None:
+ for file_path in file_paths:
+ try:
+ if os.path.isfile(file_path):
+ os.remove(file_path)
+ except Exception as e:
+ print(e)
+
+
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+
+def file_hash(
+ filename: str, hashtype: Callable[[], "hashlib._Hash"], blocksize: int = 65536
+) -> str:
+ hashtype = hashtype()
+ with open(filename, "rb") as f:
+ for block in iter(lambda: f.read(blocksize), b""):
+ hashtype.update(block)
+ return hashtype.hexdigest()
+
+
+def get_file_sha1_from_file(file_name: str, sha1_file: str) -> Optional[str]:
+ if os.path.isfile(sha1_file):
+ with open(sha1_file, "r") as file:
+ return file.read()
+ if not os.path.isfile(file_name):
+ return None
+ new_sha1 = file_hash(file_name, hashlib.sha1)
+ with open(sha1_file, "w") as file:
+ file.write(new_sha1)
+ return None
diff --git a/meta/meta/common/fabric.py b/meta/meta/common/fabric.py
new file mode 100644
index 0000000000..2a35695cf1
--- /dev/null
+++ b/meta/meta/common/fabric.py
@@ -0,0 +1,12 @@
+from os.path import join
+
+BASE_DIR = "fabric"
+
+JARS_DIR = join(BASE_DIR, "jars")
+INSTALLER_INFO_DIR = join(BASE_DIR, "loader-installer-json")
+META_DIR = join(BASE_DIR, "meta-v2")
+
+LOADER_COMPONENT = "net.fabricmc.fabric-loader"
+INTERMEDIARY_COMPONENT = "net.fabricmc.intermediary"
+
+DATETIME_FORMAT_HTTP = "%a, %d %b %Y %H:%M:%S %Z"
diff --git a/meta/meta/common/forge.py b/meta/meta/common/forge.py
new file mode 100644
index 0000000000..3cf5c3d10f
--- /dev/null
+++ b/meta/meta/common/forge.py
@@ -0,0 +1,22 @@
+from os.path import join, dirname
+
+from ..model import GradleSpecifier, make_launcher_library
+
+BASE_DIR = "forge"
+
+JARS_DIR = join(BASE_DIR, "jars")
+INSTALLER_INFO_DIR = join(BASE_DIR, "installer_info")
+INSTALLER_MANIFEST_DIR = join(BASE_DIR, "installer_manifests")
+VERSION_MANIFEST_DIR = join(BASE_DIR, "version_manifests")
+FILE_MANIFEST_DIR = join(BASE_DIR, "files_manifests")
+DERIVED_INDEX_FILE = join(BASE_DIR, "derived_index.json")
+LEGACYINFO_FILE = join(BASE_DIR, "legacyinfo.json")
+
+FORGE_COMPONENT = "net.minecraftforge"
+
+FORGEWRAPPER_LIBRARY = make_launcher_library(
+ GradleSpecifier("io.github.zekerzhayard", "ForgeWrapper", "prism-2025-12-07"),
+ "4c4653d80409e7e968d3e3209196ffae778b7b4e",
+ 29731,
+)
+BAD_VERSIONS = ["1.12.2-14.23.5.2851"]
diff --git a/meta/meta/common/http.py b/meta/meta/common/http.py
new file mode 100644
index 0000000000..20f9d0d135
--- /dev/null
+++ b/meta/meta/common/http.py
@@ -0,0 +1,6 @@
+def download_binary_file(sess, path, url):
+ with open(path, "wb") as f:
+ r = sess.get(url)
+ r.raise_for_status()
+ for chunk in r.iter_content(chunk_size=128):
+ f.write(chunk)
diff --git a/meta/meta/common/java.py b/meta/meta/common/java.py
new file mode 100644
index 0000000000..8b83f65aa0
--- /dev/null
+++ b/meta/meta/common/java.py
@@ -0,0 +1,17 @@
+from os.path import join
+
+BASE_DIR = "java_runtime"
+
+RELEASE_FILE = join(BASE_DIR, "releases.json")
+ADOPTIUM_DIR = join(BASE_DIR, "adoptium")
+OPENJ9_DIR = join(BASE_DIR, "ibm")
+AZUL_DIR = join(BASE_DIR, "azul")
+
+ADOPTIUM_VERSIONS_DIR = join(ADOPTIUM_DIR, "versions")
+OPENJ9_VERSIONS_DIR = join(OPENJ9_DIR, "versions")
+AZUL_VERSIONS_DIR = join(AZUL_DIR, "versions")
+
+JAVA_MINECRAFT_COMPONENT = "net.minecraft.java"
+JAVA_ADOPTIUM_COMPONENT = "net.adoptium.java"
+JAVA_OPENJ9_COMPONENT = "com.ibm.java"
+JAVA_AZUL_COMPONENT = "com.azul.java"
diff --git a/meta/meta/common/liteloader.py b/meta/meta/common/liteloader.py
new file mode 100644
index 0000000000..7a6c19eb46
--- /dev/null
+++ b/meta/meta/common/liteloader.py
@@ -0,0 +1,7 @@
+from os.path import join
+
+BASE_DIR = "liteloader"
+
+VERSIONS_FILE = join(BASE_DIR, "versions.json")
+
+LITELOADER_COMPONENT = "com.mumfrey.liteloader"
diff --git a/meta/meta/common/mojang-library-patches.json b/meta/meta/common/mojang-library-patches.json
new file mode 100644
index 0000000000..d6386746b6
--- /dev/null
+++ b/meta/meta/common/mojang-library-patches.json
@@ -0,0 +1,4269 @@
+[
+ {
+ "_comment": "Only allow osx-arm64 for existing LWJGL 3.3.2/3.3.3/3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.3.2",
+ "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.3.3",
+ "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.3.6",
+ "org.lwjgl:lwjgl-freetype-natives-macos-arm64:3.4.1",
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.4.1",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.4.1",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.4.1",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.4.1",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.4.1",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.4.1",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.4.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Only allow windows-arm64 for existing LWJGL 3.3.2/3.3.3/3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.3.2",
+ "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.3.3",
+ "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.3.6",
+ "org.lwjgl:lwjgl-freetype-natives-windows-arm64:3.4.1",
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.4.1",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.4.1",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.4.1",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.4.1",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.4.1",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.4.1",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.4.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "windows-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Add missing tinyfd to the broken LWJGL 3.2.2 variant",
+ "match": [
+ "org.lwjgl:lwjgl:3.2.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "fcbe606c8f8da6f8f9a05e2c540eb1ee8632b0e9",
+ "size": 7092,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2"
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "fcbe606c8f8da6f8f9a05e2c540eb1ee8632b0e9",
+ "size": 7092,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2.jar"
+ },
+ "classifiers": {
+ "natives-linux": {
+ "sha1": "39e35b161c130635d9c8918ce04e887a30c5b687",
+ "size": 38804,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-linux.jar"
+ },
+ "natives-macos": {
+ "sha1": "46d0798228b8a28e857a2a0f02310fd6ba2a4eab",
+ "size": 42136,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-macos.jar"
+ },
+ "natives-windows": {
+ "sha1": "e9115958773644e863332a6a06488d26f9e1fc9f",
+ "size": 208314,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl-tinyfd/3.2.2/lwjgl-tinyfd-3.2.2-natives-windows.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2",
+ "natives": {
+ "linux": "natives-linux",
+ "osx": "natives-macos",
+ "windows": "natives-windows"
+ }
+ }
+ ],
+ "patchAdditionalLibraries": true
+ },
+ {
+ "_comment": "Add additional library just for osx-arm64. No override needed",
+ "match": [
+ "ca.weblite:java-objc-bridge:1.0.0"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "369a83621e3c65496348491e533cb97fe5f2f37d",
+ "size": 91947,
+ "url": "https://github.com/MinecraftMachina/Java-Objective-C-Bridge/releases/download/1.1.0-mmachina.1/java-objc-bridge-1.1.jar"
+ }
+ },
+ "name": "ca.weblite:java-objc-bridge:1.1.0-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add additional classifiers for jinput-platform",
+ "match": [
+ "net.java.jinput:jinput-platform:2.0.5"
+ ],
+ "override": {
+ "downloads": {
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "5189eb40db3087fb11ca063b68fa4f4c20b199dd",
+ "size": 10031,
+ "url": "https://github.com/r58Playz/jinput-m1/raw/main/plugins/OSX/bin/jinput-platform-2.0.5.jar"
+ },
+ "natives-linux-arm64": {
+ "sha1": "42b388ccb7c63cec4e9f24f4dddef33325f8b212",
+ "size": 10932,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-2.9.4/jinput-platform-2.0.5-natives-linux.jar"
+ },
+ "natives-linux-arm32": {
+ "sha1": "f3c455b71c5146acb5f8a9513247fc06db182fd5",
+ "size": 4521,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-2.9.4/jinput-platform-2.0.5-natives-linux.jar"
+ }
+ }
+ },
+ "natives": {
+ "linux-arm64": "natives-linux-arm64",
+ "linux-arm32": "natives-linux-arm32",
+ "osx-arm64": "natives-osx-arm64"
+ }
+ }
+ },
+ {
+ "_comment": "Use a newer version on osx-arm64",
+ "match": [
+ "com.mojang:text2speech:1.0.10",
+ "com.mojang:text2speech:1.5",
+ "com.mojang:text2speech:1.6",
+ "com.mojang:text2speech:1.7",
+ "com.mojang:text2speech:1.10.1",
+ "com.mojang:text2speech:1.10.3",
+ "com.mojang:text2speech:1.11.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "f378f889797edd7df8d32272c06ca80a1b6b0f58",
+ "size": 13164,
+ "url": "https://libraries.minecraft.net/com/mojang/text2speech/1.11.3/text2speech-1.11.3.jar"
+ }
+ },
+ "name": "com.mojang:text2speech:1.11.3",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl.lwjgl:lwjgl:2.9.3",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131120",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20131017",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1-nightly-20130708-debug3",
+ "org.lwjgl.lwjgl:lwjgl:2.9.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "697517568c68e78ae0b4544145af031c81082dfe",
+ "size": 1047168,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.3",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20131120",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20131017",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1-nightly-20130708-debug3",
+ "org.lwjgl.lwjgl:lwjgl_util:2.9.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d51a7c040a721d13efdfbd34f8b257b2df882ad0",
+ "size": 173887,
+ "url": "https://libraries.minecraft.net/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/lwjgl_util-2.9.4-nightly-20150209.jar"
+ }
+ },
+ "name": "org.lwjgl.lwjgl:lwjgl_util:2.9.4-nightly-20150209",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.4-nightly-20150209",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.3",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20131120",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20131017",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1-nightly-20130708-debug3",
+ "org.lwjgl.lwjgl:lwjgl-platform:2.9.1"
+ ],
+ "override": {
+ "downloads": {
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "eff546c0b319d6ffc7a835652124c18089c67f36",
+ "size": 488316,
+ "url": "https://github.com/MinecraftMachina/lwjgl/releases/download/2.9.4-20150209-mmachina.2/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar"
+ },
+ "natives-linux-arm64": {
+ "sha1": "63ac7da0f4a4785c7eadc0f8edc1e9dcc4dd08cb",
+ "size": 579979,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-2.9.4/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
+ },
+ "natives-linux-arm32": {
+ "sha1": "fa483e540a9a753a5ffbb23dcf7879a5bf752611",
+ "size": 475177,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-2.9.4/lwjgl-platform-2.9.4-nightly-20150209-natives-linux.jar"
+ }
+ }
+ },
+ "natives": {
+ "linux-arm64": "natives-linux-arm64",
+ "linux-arm32": "natives-linux-arm32",
+ "osx-arm64": "natives-osx-arm64"
+ }
+ }
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.2.2",
+ "org.lwjgl:lwjgl-glfw:3.2.1",
+ "org.lwjgl:lwjgl-glfw:3.1.6",
+ "org.lwjgl:lwjgl-glfw:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "155d175037efc76630940c197ca6dea2b17d7e18",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "155d175037efc76630940c197ca6dea2b17d7e18",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "074ad243761147df0d060fbefc814614d2ff75cc",
+ "size": 85072,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "99e9a39fa8ed4167e3ff9e04d47eb32c9e69804d",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "99e9a39fa8ed4167e3ff9e04d47eb32c9e69804d",
+ "size": 108691,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "4265f2fbe3b9d642591165165a17cf406cf7b98e",
+ "size": 80186,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e9a101bca4fa30d26b21b526ff28e7c2d8927f1b",
+ "size": 130128,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e9a101bca4fa30d26b21b526ff28e7c2d8927f1b",
+ "size": 130128,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "71d793d0a5a42e3dfe78eb882abc2523a2c6b496",
+ "size": 129076,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-glfw-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.2.2",
+ "org.lwjgl:lwjgl-jemalloc:3.2.1",
+ "org.lwjgl:lwjgl-jemalloc:3.1.6",
+ "org.lwjgl:lwjgl-jemalloc:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "cc04eec29b2fa8c298791af9800a3766d9617954",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "cc04eec29b2fa8c298791af9800a3766d9617954",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "762d7d80c9cdf3a3f3fc80c8a5f86612255edfe0",
+ "size": 156343,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-jemalloc-patched-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman64.2",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8224ae2e8fc6d8e1a0fc7d84dc917aa3c440620c",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8224ae2e8fc6d8e1a0fc7d84dc917aa3c440620c",
+ "size": 33790,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "9163a2a5559ef87bc13ead8fea84417ea3928748",
+ "size": 134237,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "4fb94224378d3588d52d2beb172f2eeafea2d546",
+ "size": 36976,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "4fb94224378d3588d52d2beb172f2eeafea2d546",
+ "size": 36976,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "b0be721188d2e7195798780b1c5fe7eafe8091c1",
+ "size": 103478,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-jemalloc-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.2.2",
+ "org.lwjgl:lwjgl-openal:3.2.1",
+ "org.lwjgl:lwjgl-openal:3.1.6",
+ "org.lwjgl:lwjgl-openal:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "6dfce9dc6a9629c75b2ae01a8df7e7be80ba0261",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "6dfce9dc6a9629c75b2ae01a8df7e7be80ba0261",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "948e415b5b2a2c650c25b377a4a9f443b21ce92e",
+ "size": 469432,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "304f0571fd5971621ee6da86a4c1e90f6f52e2ee",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "304f0571fd5971621ee6da86a4c1e90f6f52e2ee",
+ "size": 79582,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "ecbc981fdd996492a1f6334f003ed62e5a8c0cd5",
+ "size": 398418,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d48e753d85916fc8a200ccddc709b36e3865cc4e",
+ "size": 88880,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d48e753d85916fc8a200ccddc709b36e3865cc4e",
+ "size": 88880,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "6b80fc0b982a0723b141e88859c42d6f71bd723f",
+ "size": 346131,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-openal-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.2.2",
+ "org.lwjgl:lwjgl-opengl:3.2.1",
+ "org.lwjgl:lwjgl-opengl:3.1.6",
+ "org.lwjgl:lwjgl-opengl:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "198bc2f72e0b2eb401eb6f5999aea52909b31ac4",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "198bc2f72e0b2eb401eb6f5999aea52909b31ac4",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "bd40897077bf7d12f562da898b18ac2c68e1f9d7",
+ "size": 56109,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9762ae928d02147e716cd82e929b74a97ea9600a",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9762ae928d02147e716cd82e929b74a97ea9600a",
+ "size": 937609,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "3af5599c74dd76dd8dbb567b3f9b4963a6abeed5",
+ "size": 56388,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "962c2a8d2a8cdd3b89de3d78d766ab5e2133c2f4",
+ "size": 929233,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "962c2a8d2a8cdd3b89de3d78d766ab5e2133c2f4",
+ "size": 929233,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "bb575058e0372f515587b5d2d04ff7db185f3ffe",
+ "size": 41667,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-opengl-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.2.2",
+ "org.lwjgl:lwjgl-stb:3.2.1",
+ "org.lwjgl:lwjgl-stb:3.1.6",
+ "org.lwjgl:lwjgl-stb:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "46a5735f3eb9d17eb5dcbdd5afa194066d2a6555",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "46a5735f3eb9d17eb5dcbdd5afa194066d2a6555",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "077efa7d7ea41b32df5c6078e912e724cccd06db",
+ "size": 202038,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ea979b0af45b8e689f5f47c989aa8550c148d8a2",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ea979b0af45b8e689f5f47c989aa8550c148d8a2",
+ "size": 104075,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "ec9d70aaebd0ff76dfeecf8f00b56118bf3706b1",
+ "size": 149387,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "703e4b533e2542560e9f94d6d8bd148be1c1d572",
+ "size": 113273,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "703e4b533e2542560e9f94d6d8bd148be1c1d572",
+ "size": 113273,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "98f0ad956c754723ef354d50057cc30417ef376a",
+ "size": 178409,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-stb-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.2.2",
+ "org.lwjgl:lwjgl-tinyfd:3.2.1",
+ "org.lwjgl:lwjgl-tinyfd:3.1.6",
+ "org.lwjgl:lwjgl-tinyfd:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "3a75b9811607633bf33c978f53964df1534a4bc1",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "3a75b9811607633bf33c978f53964df1534a4bc1",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "37c744ca289b5d7ae155d79e39029488b3254e5b",
+ "size": 37893,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "a8c09f5b7fa24bd53ec329c231b566497a163d5b",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "a8c09f5b7fa24bd53ec329c231b566497a163d5b",
+ "size": 5571,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "82d16054ada6633297a3108fb6d8bae98800c76f",
+ "size": 41663,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1203660b3131cbb8681b17ce6437412545be95e0",
+ "size": 6802,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1203660b3131cbb8681b17ce6437412545be95e0",
+ "size": 6802,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "015b931a2daba8f0c317d84c9d14e8e98ae56e0c",
+ "size": 41384,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-tinyfd-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use a newer patched version on osx-arm64, linux-arm64, and linux-arm32",
+ "match": [
+ "org.lwjgl:lwjgl:3.2.2",
+ "org.lwjgl:lwjgl:3.2.1",
+ "org.lwjgl:lwjgl:3.1.6",
+ "org.lwjgl:lwjgl:3.1.2"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "360899386df83d6a8407844a94478607af937f97",
+ "size": 318833,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "360899386df83d6a8407844a94478607af937f97",
+ "size": 318833,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm64": {
+ "sha1": "612efd57d12b2e48e554858eb35e7e2eb46ebb4c",
+ "size": 87121,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.2.2/lwjgl-natives-linux-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman64.1",
+ "natives": {
+ "linux-arm64": "natives-linux-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "16ea3934fca417368250d1ddac01a30c1809d317",
+ "size": 318413,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman32.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "16ea3934fca417368250d1ddac01a30c1809d317",
+ "size": 318413,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-core.jar"
+ },
+ "classifiers": {
+ "natives-linux-arm32": {
+ "sha1": "6bd0b37fef777a309936a72dc7f63126e8c79ea5",
+ "size": 90296,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm32/raw/lwjgl-3.2.2/lwjgl-natives-linux-arm32.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.2.2-gman32.1",
+ "natives": {
+ "linux-arm32": "natives-linux-arm32"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8e664dd69ad7bbcf2053da23efc7848e39e498db",
+ "size": 719038,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.3.1-mmachina.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8e664dd69ad7bbcf2053da23efc7848e39e498db",
+ "size": 719038,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl.jar"
+ },
+ "classifiers": {
+ "natives-osx-arm64": {
+ "sha1": "984df31fadaab86838877b112e5b4e4f68a00ccf",
+ "size": 42693,
+ "url": "https://github.com/MinecraftMachina/lwjgl3/releases/download/3.3.1-mmachina.1/lwjgl-natives-macos-arm64.jar"
+ }
+ }
+ },
+ "name": "org.lwjgl:lwjgl:3.3.1-mmachina.1",
+ "natives": {
+ "osx-arm64": "natives-osx-arm64"
+ },
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Only allow osx-arm64 for existing LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-jemalloc-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-openal-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-opengl-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-stb-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-tinyfd-natives-macos-arm64:3.3.1",
+ "org.lwjgl:lwjgl-natives-macos-arm64:3.3.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Only allow osx-arm64 for existing java-objc-bridge:1.1",
+ "match": [
+ "ca.weblite:java-objc-bridge:1.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Only allow windows-arm64 for existing LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-jemalloc-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-openal-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-opengl-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-stb-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-tinyfd-natives-windows-arm64:3.3.1",
+ "org.lwjgl:lwjgl-natives-windows-arm64:3.3.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "windows-arm64"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "513eb39b866d0fe131a18d5c517087805433b029",
+ "size": 112350,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "749be48a9b86ee2c3a2da5fd77511208adcfb33b",
+ "size": 159993,
+ "url": "https://github.com/theofficialgman/lwjgl3-binaries-arm64/raw/lwjgl-3.3.1/lwjgl-jemalloc-patched-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.1-gman64.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "cf4e303257e82981b8b2e31bba3d7f8f7b8f42b2",
+ "size": 470743,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1c528fb258a6e63e8fceb4482d8db0f3af10a634",
+ "size": 57908,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8e8348a1813aad7f30aaf75ea197151ebb7beba9",
+ "size": 205491,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "964f628b7a82fd909def086c0dd9a4b84bb259ae",
+ "size": 42654,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b597401014acb7196c76d97e15a6288f54f1f692",
+ "size": 86308,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "816d935933f2dd743074c4e717cc25b55720f294",
+ "size": 104027,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "a96a6d6cb3876d7813fcee53c3c24f246aeba3b3",
+ "size": 136157,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ffbe35d7fa5ec9b7eca136a7c71f24d4025a510b",
+ "size": 400129,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e3550fa91097fd56e361b4370fa822220fef3595",
+ "size": 58474,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b08226bab162c06ae69337d8a1b0ee0a3fdf0b90",
+ "size": 153889,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d53d331e859217a61298fcbcf8d79137f3df345c",
+ "size": 48061,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.1",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "41a3c1dd15d6b964eb8196dde69720a3e3e5e969",
+ "size": 82374,
+ "url": "https://build.lwjgl.org/release/3.3.1/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "896e7d9b8f60d7273f3d491c69270afc67ece3ce",
+ "size": 1073374,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "bc49e64bae0f7ff103a312ee8074a34c4eb034c7",
+ "size": 120168,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "5249f18a9ae20ea86c5816bc3107a888ce7a17d2",
+ "size": 206402,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "22408980cc579709feaf9acb807992d3ebcf693f",
+ "size": 590865,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "bb9eb56da6d1d549d6a767218e675e36bc568eb9",
+ "size": 58627,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "11a380c37b0f03cb46db235e064528f84d736ff7",
+ "size": 207419,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "93f8c5bc1984963cd79109891fb5a9d1e580373e",
+ "size": 43381,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8bd89332c90a90e6bc4aa997a25c05b7db02c90a",
+ "size": 90795,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b7f77ceb951182659fd400437272aa7e96709968",
+ "size": 924657,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "5907d9a6b7c44fb0612a63bb1cff5992588f65be",
+ "size": 110067,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9367437ce192e4d6f5725d53d85520644c0b0d6f",
+ "size": 177571,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "7c82bbc33ef49ee4094b216c940db564b2998224",
+ "size": 503352,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "821f9a2d1d583c44893f42b96f6977682b48a99b",
+ "size": 59265,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ca9333da184aade20757151f4615f1e27ca521ae",
+ "size": 154928,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "807e220913aa0740449ff90d3b3d825cf5f359ed",
+ "size": 48788,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.2",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.2"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "afcbfaaa46f217e98a6da4208550f71de1f2a225",
+ "size": 89347,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.2-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "498965aac06c4a0d42df1fbef6bacd05bde7f974",
+ "size": 1093516,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "492a0f11f85b85899a6568f07511160c1b87cd38",
+ "size": 122159,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "eff8b86798191192fe2cba2dc2776109f30c239d",
+ "size": 209315,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ad8f302118a65bb8d615f8a2a680db58fb8f835e",
+ "size": 592963,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "2096f6b94b2d68745d858fbfe53aacf5f0c8074c",
+ "size": 58625,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ddc177afc2be1ee8d93684b11363b80589a13fe1",
+ "size": 207418,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "2823a8c955c758d0954d282888075019ef99cec7",
+ "size": 43864,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "f35d8b6ffe1ac1e3a5eb1d4e33de80f044ad5fd8",
+ "size": 91294,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "7dd3b1f751571adaf2c4dc882bc675a5d1e796e6",
+ "size": 942636,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d9af485c32545b37dd5359b163161d42d7534dcf",
+ "size": 112560,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "109b6931880d02d4e65ced38928a16e41d19873e",
+ "size": 178324,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e1702aa09d20359d6cf5cb2999fa7685a785eca7",
+ "size": 505618,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "dbba17fc5ac0985d14a57c11f9537617d67b9952",
+ "size": 59263,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1ae28ff044699ff29b0e980ffabd73fba8a664b3",
+ "size": 154931,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "c2a0a05c82c4b9f69ded0b6ad5f417addea78ce2",
+ "size": 49495,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.3",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.3"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "2075c51a80f0ef0f22ba616ba54007ac2b0debd4",
+ "size": 89565,
+ "url": "https://build.lwjgl.org/release/3.3.3/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.3-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b5492439c7c9a596655d0d0e06801f93ec491e53",
+ "size": 1093516,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "b54023af492b4c2c72451f3a7aa0f385e9969474",
+ "size": 141056,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1bc2e16e70df7f418d668c2984ac8066f1f6f5b1",
+ "size": 222196,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "fd2c17603c63e8d543cb57d1db77ebd4574f3b7a",
+ "size": 656568,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "44de180f79e0b45c9e5bee10ca7540dcb5ddd373",
+ "size": 79414,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "397f588f867e9c4faf1a34231344c9209dabc052",
+ "size": 256144,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "7806e57c3d9ea6b6a552c72f5e2597343c4d4138",
+ "size": 44504,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9eeb8887b5e3aa672efd2e1b0973ffa5891a3151",
+ "size": 117172,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "3f6a1030be5efdcde35cb363c69810245eb59c5a",
+ "size": 1035183,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "671adf04a6bc4f792af13892e37f804be30b7070",
+ "size": 118670,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "c484cae39a718010dbc7931fe5e12664600a13c2",
+ "size": 176503,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "7830af894fa110e65bf5075deb9183efbdbc50f5",
+ "size": 604338,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ee815fbf454b916f13c10fff62e513eb09042ef0",
+ "size": 58633,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "f47bac442afcb7fd014af7d90892024fe3c0d920",
+ "size": 191834,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "800ad2c9492a7ccadb23886c9e231f60c12a9037",
+ "size": 50599,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "2c9d698e76c3d0fe307d94cc6f428038492f25df",
+ "size": 88490,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "5eea88e3527bb5fd2d81cc03f2bece1c83eada1c",
+ "size": 1199082,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "dde300b71892fddae65e4c524760e650bc924bb2",
+ "size": 119447,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "9c76514b7725d5b8c5731f41218e97dcad3237b9",
+ "size": 197210,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "35fc93e98cf43a51f8fdd2b7e46854cb3820532a",
+ "size": 640228,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-openal/lwjgl-openal-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "c55c0458e903df7bb688401273ad0e7c92c11068",
+ "size": 57863,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "009dbfa917b9fc07459a726e72d9ea9e7178f9d3",
+ "size": 216086,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-stb/lwjgl-stb-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "0dfe4d23c5c5d92bf70a8bc50a964b0a6452add2",
+ "size": 46550,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl:3.3.6"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "830923e74105b08d137413735525e2be80a421b8",
+ "size": 81930,
+ "url": "https://build.lwjgl.org/release/3.3.6/bin/lwjgl/lwjgl-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-riscv64:3.3.6-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8f37d0da3386ff602ec54cd06626881895711041",
+ "size": 1093516,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "e5e87034c47118960746077dba46280e8de864b3",
+ "size": 141056,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "7891964dfb723209c6d02b0401432348fb707cc0",
+ "size": 222196,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "3729b70cdd42df5571b075e051fa2fc8586dc538",
+ "size": 656568,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "61a4103e56bbaeb74ad3f19ec14299fd6891c4b0",
+ "size": 79414,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "3bc107f901f931fea07cb0d80b1d74a34b806a2b",
+ "size": 256144,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "20771d2b4e01f5295156912ab62e170508aef618",
+ "size": 44504,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "46883f3b622d8b4d7f27b627ca3360cda3db0e0e",
+ "size": 117172,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl/lwjgl-natives-linux-arm64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d0bb1ececfdd1e5b75ba75c22d0e075dafe695d1",
+ "size": 1035183,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "bb243e9a857c4301bf7d5e668538686eaa64101e",
+ "size": 118670,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "fc9ce35c94743e23855777cacaba34bc145da6ec",
+ "size": 176503,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "6d4ac5f3d5bab7f2fadfd52c32177d9c12a43b49",
+ "size": 604338,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "172e575948234ff7920abf0d0083d25e37c91ba6",
+ "size": 58633,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8f753f3772863989f1172d2b84b4e56ed18e8c35",
+ "size": 191834,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.3.6",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "62cb99015923df821e2e7a2a5a1e51d1e307126c",
+ "size": 50599,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-arm32 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1511ab1ffb1c8d8e00e2acb452663173ae09bca0",
+ "size": 88490,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl/lwjgl-natives-linux-arm32.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-arm32:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-arm32"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-freetype:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "737708c27a49ba5884ef347565fcb9964e8d85a9",
+ "size": 1199082,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-freetype/lwjgl-freetype-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-freetype-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-glfw:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "d76ed6846bff9804cfd1adb84b068728645a097b",
+ "size": 119447,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-glfw/lwjgl-glfw-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-jemalloc:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "ac7be1f86e87df030e668c02df2dec27c44da32b",
+ "size": 197210,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-jemalloc/lwjgl-jemalloc-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-jemalloc-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-openal:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "652b9424f529dccc79694f2124709083d2712104",
+ "size": 640228,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-openal/lwjgl-openal-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-openal-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-opengl:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "8a6f47236738e3c682e98e15a13cf0358c1da85c",
+ "size": 57863,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-opengl/lwjgl-opengl-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-opengl-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-stb:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "f1d8fe25d44e26c40f4dd4c48189323675467578",
+ "size": 216086,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-stb/lwjgl-stb-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-stb-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl-tinyfd:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "6aa204e5047e9f272c7271119105833cc0ddfd27",
+ "size": 46550,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl-tinyfd/lwjgl-tinyfd-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-tinyfd-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Add linux-riscv64 support for LWJGL 3.4.1",
+ "match": [
+ "org.lwjgl:lwjgl:3.4.1"
+ ],
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "a43b5208883562d31b5a2de1810aa82e2f2bf0ba",
+ "size": 81930,
+ "url": "https://build.lwjgl.org/release/3.4.1/bin/lwjgl/lwjgl-natives-linux-riscv64.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-natives-linux-riscv64:3.4.1-lwjgl.1",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "linux-riscv64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Replace glfw from 3.3.1 with version from 3.3.2 to prevent stack smashing",
+ "match": [
+ "org.lwjgl:lwjgl-glfw-natives-linux:3.3.1"
+ ],
+ "override": {
+ "downloads": {
+ "artifact": {
+ "sha1": "0766bb0e8e829598b1c8052fd8173c62af741c52",
+ "size": 115553,
+ "url": "https://build.lwjgl.org/release/3.3.2/bin/lwjgl-glfw/lwjgl-glfw-natives-linux.jar"
+ }
+ },
+ "name": "org.lwjgl:lwjgl-glfw-natives-linux:3.3.2-lwjgl.1"
+ }
+ },
+ {
+ "_comment": "Use newer JNA on macOS to prevent crashes due to faulty assertion",
+ "match": [
+ "net.java.dev.jna:jna:5.6.0",
+ "net.java.dev.jna:jna:5.8.0",
+ "net.java.dev.jna:jna:5.9.0",
+ "net.java.dev.jna:jna:5.10.0",
+ "net.java.dev.jna:jna:5.12.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "1200e7ebeedbe0d10062093f32925a912020e747",
+ "size": 1879325,
+ "url": "https://libraries.minecraft.net/net/java/dev/jna/jna/5.13.0/jna-5.13.0.jar"
+ }
+ },
+ "name": "net.java.dev.jna:jna:5.13.0",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "_comment": "Use newer JNA on macOS to prevent crashes due to faulty assertion",
+ "match": [
+ "net.java.dev.jna:jna-platform:5.6.0",
+ "net.java.dev.jna:jna-platform:5.8.0",
+ "net.java.dev.jna:jna-platform:5.9.0",
+ "net.java.dev.jna:jna-platform:5.10.0",
+ "net.java.dev.jna:jna-platform:5.12.1"
+ ],
+ "override": {
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ },
+ "additionalLibraries": [
+ {
+ "downloads": {
+ "artifact": {
+ "sha1": "88e9a306715e9379f3122415ef4ae759a352640d",
+ "size": 1363209,
+ "url": "https://libraries.minecraft.net/net/java/dev/jna/jna-platform/5.13.0/jna-platform-5.13.0.jar"
+ }
+ },
+ "name": "net.java.dev.jna:jna-platform:5.13.0",
+ "rules": [
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx"
+ }
+ },
+ {
+ "action": "allow",
+ "os": {
+ "name": "osx-arm64"
+ }
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/meta/meta/common/mojang-minecraft-experiments.json b/meta/meta/common/mojang-minecraft-experiments.json
new file mode 100644
index 0000000000..2a6792a7b0
--- /dev/null
+++ b/meta/meta/common/mojang-minecraft-experiments.json
@@ -0,0 +1,159 @@
+{
+ "experiments": [
+ {
+ "id": "1_21_11_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11",
+ "url": "https://piston-data.mojang.com/v1/objects/82332dfb17146de34cb7a36d2b910e3b2009191a/1_21_11_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-rc3_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Release_Candidate_3",
+ "url": "https://piston-data.mojang.com/v1/objects/7abe399a1b3c07754c5dc3ec4e5c6f50ee03c10e/1_21_11-rc3_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-rc2_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Release_Candidate_2",
+ "url": "https://piston-data.mojang.com/v1/objects/fb70de3ae3e19825622b7687d2fd783d78c4b05f/1_21_11-rc2_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-rc1_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Release_Candidate_1",
+ "url": "https://piston-data.mojang.com/v1/objects/38712002b9d02061e662b69c44753a47d24da516/1_21_11-rc1_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-pre5_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Pre-Release_5",
+ "url": "https://piston-data.mojang.com/v1/objects/931df659128f913ce356d6036c318c5d9a039e85/1_21_11-pre5_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-pre4_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Pre-Release_4",
+ "url": "https://piston-data.mojang.com/v1/objects/834666571f1e1374923b73f4baec4203d44e9c0d/1_21_11-pre4_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-pre3_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Pre-Release_3",
+ "url": "https://piston-data.mojang.com/v1/objects/7717a481468cc33d2414d82ee9c0450f56264db0/1_21_11-pre3_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-pre2_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Pre-Release_2",
+ "url": "https://piston-data.mojang.com/v1/objects/528731e05b7be26c90fedf8f2ef6470abb0d1994/1_21_11-pre2_unobfuscated.zip"
+ },
+ {
+ "id": "1_21_11-pre1_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.21.11_Pre-Release_1",
+ "url": "https://piston-data.mojang.com/v1/objects/f98a0c053a8246cce12f8f29f2ba4ce00872fd53/1_21_11-pre1_unobfuscated.zip"
+ },
+ {
+ "id": "25w46a_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_25w46a",
+ "url": "https://piston-data.mojang.com/v1/objects/f9c5e4f9c1469296299635b498438e94d312f0c6/25w46a_unobfuscated.zip"
+ },
+ {
+ "id": "25w45a_unobfuscated",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_25w45a",
+ "url": "https://piston-data.mojang.com/v1/objects/de334d80d9ddc5abb94c611b8ad10f9125c4c421/25w45a_unobfuscated.zip"
+ },
+ {
+ "id": "1_19_deep_dark_experimental_snapshot-1",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Deep_Dark_Experimental_Snapshot_1",
+ "url": "https://launcher.mojang.com/v1/objects/b1e589c1d6ed73519797214bc796e53f5429ac46/1_19_deep_dark_experimental_snapshot-1.zip"
+ },
+ {
+ "id": "1_18_experimental-snapshot-7",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.18_Experimental_Snapshot_7",
+ "url": "https://launcher.mojang.com/v1/objects/ab4ecebb133f56dd4c4c4c3257f030a947ddea84/1_18_experimental-snapshot-7.zip"
+ },
+ {
+ "id": "1_18_experimental-snapshot-6",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.18_Experimental_Snapshot_6",
+ "url": "https://launcher.mojang.com/v1/objects/4697c84c6a347d0b8766759d5b00bc5a00b1b858/1_18_experimental-snapshot-6.zip"
+ },
+ {
+ "id": "1_18_experimental-snapshot-5",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.18_Experimental_Snapshot_5",
+ "url": "https://launcher.mojang.com/v1/objects/d9cb7f6fb4e440862adfb40a385d83e3f8d154db/1_18_experimental-snapshot-5.zip"
+ },
+ {
+ "id": "1_18_experimental-snapshot-4",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.18_Experimental_Snapshot_4",
+ "url": "https://launcher.mojang.com/v1/objects/b92a360cbae2eb896a62964ad8c06c3493b6c390/1_18_experimental-snapshot-4.zip"
+ },
+ {
+ "id": "1_18_experimental-snapshot-3",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.18_Experimental_Snapshot_3",
+ "url": "https://launcher.mojang.com/v1/objects/846648ff9fe60310d584061261de43010e5c722b/1_18_experimental-snapshot-3.zip"
+ },
+ {
+ "id": "1_18_experimental-snapshot-2",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.18_Experimental_Snapshot_2",
+ "url": "https://launcher.mojang.com/v1/objects/0adfe4f321aa45248fc88ac888bed5556633e7fb/1_18_experimental-snapshot-2.zip"
+ },
+ {
+ "id": "1_18_experimental-snapshot-1",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.18_Experimental_Snapshot_1",
+ "url": "https://launcher.mojang.com/v1/objects/231bba2a21e18b8c60976e1f6110c053b7b93226/1_18_experimental-snapshot-1.zip"
+ },
+ {
+ "id": "1_16_combat-6",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_8c",
+ "url": "https://launcher.mojang.com/experiments/combat/ea08f7eb1f96cdc82464e27c0f95d23965083cfb/1_16_combat-6.zip"
+ },
+ {
+ "id": "1_16_combat-5",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_8b",
+ "url": "https://launcher.mojang.com/experiments/combat/9b2b984d635d373564b50803807225c75d7fd447/1_16_combat-5.zip"
+ },
+ {
+ "id": "1_16_combat-4",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_8",
+ "url": "https://archive.org/download/1-16-combat-4_202404/1_16_combat-4.zip"
+ },
+ {
+ "id": "1_16_combat-3",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_7c",
+ "url": "https://launcher.mojang.com/experiments/combat/2557b99d95588505e988886220779087d7d6b1e9/1_16_combat-3.zip"
+ },
+ {
+ "id": "1_16_combat-2",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_7b",
+ "url": "https://archive.org/download/Combat_Test_7ab/1_16_combat-2.zip"
+ },
+ {
+ "id": "1_16_combat-1",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_7",
+ "url": "https://archive.org/download/Combat_Test_7ab/1_16_combat-1.zip"
+ },
+ {
+ "id": "1_16_combat-0",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_6",
+ "url": "https://launcher.mojang.com/experiments/combat/5a8ceec8681ed96ab6ecb9607fb5d19c8a755559/1_16_combat-0.zip"
+ },
+ {
+ "id": "1_15_combat-6",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_5",
+ "url": "https://launcher.mojang.com/experiments/combat/52263d42a626b40c947e523128f7a195ec5af76a/1_15_combat-6.zip"
+ },
+ {
+ "id": "1_15_combat-1",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_4",
+ "url": "https://launcher.mojang.com/experiments/combat/ac11ea96f3bb2fa2b9b76ab1d20cacb1b1f7ef60/1_15_combat-1.zip"
+ },
+ {
+ "id": "1_14_combat-3",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_3",
+ "url": "https://launcher.mojang.com/experiments/combat/0f209c9c84b81c7d4c88b4632155b9ae550beb89/1_14_combat-3.zip"
+ },
+ {
+ "id": "1_14_combat-0",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_Combat_Test_2",
+ "url": "https://launcher.mojang.com/experiments/combat/d164bb6ecc5fca9ac02878c85f11befae61ac1ca/1_14_combat-0.zip"
+ },
+ {
+ "id": "1_14_combat-212796",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.14.3_-_Combat_Test",
+ "url": "https://launcher.mojang.com/experiments/combat/610f5c9874ba8926d5ae1bcce647e5f0e6e7c889/1_14_combat-212796.zip"
+ }
+ ]
+}
diff --git a/meta/meta/common/mojang-minecraft-legacy-override.json b/meta/meta/common/mojang-minecraft-legacy-override.json
new file mode 100644
index 0000000000..d1d951d05f
--- /dev/null
+++ b/meta/meta/common/mojang-minecraft-legacy-override.json
@@ -0,0 +1,585 @@
+{
+ "versions": {
+ "1.5.2": {
+ "releaseTime": "2013-04-25T17:45:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.5.1": {
+ "releaseTime": "2013-03-20T12:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w12~": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.5": {
+ "releaseTime": "2013-03-07T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w10b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w10a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w09c": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w09b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w09a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w11a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w07a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w06a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w05b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w05a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w04a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w03a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w02b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w02a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w01b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "13w01a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4.7": {
+ "releaseTime": "2012-12-28T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4.6": {
+ "releaseTime": "2012-12-20T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w50b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w50a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w49a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4.5": {
+ "releaseTime": "2012-11-20T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4.4": {
+ "releaseTime": "2012-11-14T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4.3": {
+ "releaseTime": "2012-11-01T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4.2": {
+ "releaseTime": "2012-10-25T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4.1": {
+ "releaseTime": "2012-10-23T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.4": {
+ "releaseTime": "2012-10-19T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w42b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w42a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w41b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w41a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w40b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w40a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w39b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w39a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w38b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w38a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w37a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w36a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w34b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w34a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.3.2": {
+ "releaseTime": "2012-08-16T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w32a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.3.1": {
+ "releaseTime": "2012-08-01T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.3": {
+ "releaseTime": "2012-07-26T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w30e": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w30d": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w30c": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w30b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w30a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w27a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w26a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w25a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w24a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w23b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w23a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w22a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w21b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w21a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w19a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w18a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w17a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w16a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.2.5": {
+ "releaseTime": "2012-03-30T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.2.4": {
+ "releaseTime": "2012-03-22T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.2.3": {
+ "releaseTime": "2012-03-02T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.2.2": {
+ "releaseTime": "2012-03-01T00:00:01+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.2.1": {
+ "releaseTime": "2012-03-01T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.2": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w08a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w07a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w07b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w06a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w05b": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w05a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w04a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w03a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.1": {
+ "releaseTime": "2012-01-12T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "12w01a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "11w50a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "11w49a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "11w48a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "11w47a": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "1.0": {
+ "releaseTime": "2011-11-18T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.9-pre6": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.9-pre5": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.9-pre4": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.9-pre3": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.9-pre2": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.9-pre1": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.8.1": {
+ "releaseTime": "2011-09-19T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.8": {
+ "releaseTime": "2011-09-15T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.8-pre2": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.8-pre1-2": {
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.7.3": {
+ "releaseTime": "2011-07-08T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.7.2": {
+ "releaseTime": "2011-07-01T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.7": {
+ "releaseTime": "2011-06-30T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.6.6": {
+ "releaseTime": "2011-05-31T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.6.5": {
+ "releaseTime": "2011-05-28T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.6.4": {
+ "releaseTime": "2011-05-26T00:00:04+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.6.3": {
+ "releaseTime": "2011-05-26T00:00:03+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.6.2": {
+ "releaseTime": "2011-05-26T00:00:02+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.6.1": {
+ "releaseTime": "2011-05-26T00:00:01+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.6": {
+ "releaseTime": "2011-05-26T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.5_01": {
+ "releaseTime": "2011-04-20T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.5": {
+ "releaseTime": "2011-04-19T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.4_01": {
+ "releaseTime": "2011-04-05T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.4": {
+ "releaseTime": "2011-03-31T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.3_01": {
+ "releaseTime": "2011-02-23T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.3b": {
+ "releaseTime": "2011-02-22T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.2_02": {
+ "releaseTime": "2011-01-21T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.2_01": {
+ "releaseTime": "2011-01-14T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.2": {
+ "releaseTime": "2011-01-13T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.1_02": {
+ "releaseTime": "2010-12-22T00:00:01+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.1_01": {
+ "releaseTime": "2010-12-22T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.0.2": {
+ "releaseTime": "2010-12-21T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.0_01": {
+ "releaseTime": "2010-12-20T00:00:01+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "b1.0": {
+ "releaseTime": "2010-12-20T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.6": {
+ "releaseTime": "2010-12-03T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.5": {
+ "releaseTime": "2010-12-01T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.4_01": {
+ "releaseTime": "2010-11-30T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.3_04": {
+ "releaseTime": "2010-11-26T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.3_02": {
+ "releaseTime": "2010-11-25T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.3_01": {
+ "releaseTime": "2010-11-24T00:00:01+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.3": {
+ "releaseTime": "2010-11-24T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.2b": {
+ "releaseTime": "2010-11-10T00:00:01+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.2a": {
+ "releaseTime": "2010-11-10T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "texturepacks"]
+ },
+ "a1.2.1_01": {
+ "releaseTime": "2010-11-05T00:00:01+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "a1.2.1": {
+ "releaseTime": "2010-11-05T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "a1.2.0_02": {
+ "releaseTime": "2010-11-04T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "a1.2.0_01": {
+ "releaseTime": "2010-10-31T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "a1.2.0": {
+ "releaseTime": "2010-10-30T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "a1.1.2_01": {
+ "releaseTime": "2010-09-23T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.1.2": {
+ "releaseTime": "2010-09-20T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.1.0": {
+ "releaseTime": "2010-09-13T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.17_04": {
+ "releaseTime": "2010-08-23T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.17_02": {
+ "releaseTime": "2010-08-20T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.16": {
+ "releaseTime": "2010-08-12T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.15": {
+ "releaseTime": "2010-08-04T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.14": {
+ "releaseTime": "2010-07-30T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.11": {
+ "releaseTime": "2010-07-23T00:00:00+02:00",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.5_01": {
+ "releaseTime": "2010-07-13T00:00:00+02:00",
+ "mainClass": "y",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "a1.0.4": {
+ "releaseTime": "2010-07-09T00:00:00+02:00",
+ "mainClass": "ax",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "inf-20100618": {
+ "releaseTime": "2010-06-16T00:00:00+02:00",
+ "mainClass": "net.minecraft.client.d",
+ "appletClass": "net.minecraft.client.MinecraftApplet",
+ "+traits": ["legacyLaunch", "no-texturepacks"],
+ "+jvmArgs": ["-Djava.util.Arrays.useLegacyMergeSort=true"]
+ },
+ "c0.30_01c": {
+ "releaseTime": "2009-12-22T00:00:00+02:00",
+ "mainClass": "com.mojang.minecraft.l",
+ "appletClass": "com.mojang.minecraft.MinecraftApplet",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "c0.0.13a_03": {
+ "releaseTime": "2009-05-22T00:00:00+02:00",
+ "mainClass": "com.mojang.minecraft.c",
+ "appletClass": "com.mojang.minecraft.MinecraftApplet",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "c0.0.13a": {
+ "releaseTime": "2009-05-31T00:00:00+02:00",
+ "mainClass": "com.mojang.minecraft.Minecraft",
+ "appletClass": "com.mojang.minecraft.MinecraftApplet",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "c0.0.11a": {
+ "releaseTime": "2009-05-17T00:00:00+02:00",
+ "mainClass": "com.mojang.minecraft.Minecraft",
+ "appletClass": "com.mojang.minecraft.MinecraftApplet",
+ "+traits": ["legacyLaunch", "no-texturepacks"]
+ },
+ "rd-161348": {
+ "releaseTime": "2009-05-16T13:48:00+02:00",
+ "mainClass": "com.mojang.minecraft.RubyDung",
+ "+traits": ["no-texturepacks"]
+ },
+ "rd-160052": {
+ "releaseTime": "2009-05-16T00:52:00+02:00",
+ "mainClass": "com.mojang.rubydung.RubyDung",
+ "+traits": ["no-texturepacks"]
+ },
+ "rd-20090515": {
+ "mainClass": "com.mojang.rubydung.RubyDung",
+ "+traits": ["no-texturepacks"]
+ },
+ "rd-132328": {
+ "releaseTime": "2009-05-13T23:28:00+02:00",
+ "mainClass": "com.mojang.rubydung.RubyDung",
+ "+traits": ["no-texturepacks"]
+ },
+ "rd-132211": {
+ "releaseTime": "2009-05-13T22:11:00+02:00",
+ "mainClass": "com.mojang.rubydung.RubyDung",
+ "+traits": ["no-texturepacks"]
+ }
+ }
+}
diff --git a/meta/meta/common/mojang-minecraft-legacy-services.json b/meta/meta/common/mojang-minecraft-legacy-services.json
new file mode 100644
index 0000000000..420d3f8c74
--- /dev/null
+++ b/meta/meta/common/mojang-minecraft-legacy-services.json
@@ -0,0 +1,218 @@
+[
+ "c0.30_01c",
+ "inf-20100618",
+ "a1.0.4",
+ "a1.0.5_01",
+ "a1.0.11",
+ "a1.0.14",
+ "a1.0.15",
+ "a1.0.16",
+ "a1.0.17_02",
+ "a1.0.17_04",
+ "a1.1.0",
+ "a1.1.2",
+ "a1.1.2_01",
+ "a1.2.0",
+ "a1.2.0_01",
+ "a1.2.0_02",
+ "a1.2.1",
+ "a1.2.1_01",
+ "a1.2.2a",
+ "a1.2.2b",
+ "a1.2.3",
+ "a1.2.3_01",
+ "a1.2.3_02",
+ "a1.2.3_04",
+ "a1.2.4_01",
+ "a1.2.5",
+ "a1.2.6",
+ "b1.0",
+ "b1.0_01",
+ "b1.0.2",
+ "b1.1_01",
+ "b1.1_02",
+ "b1.2",
+ "b1.2_01",
+ "b1.2_02",
+ "b1.3b",
+ "b1.3_01",
+ "b1.4",
+ "b1.4_01",
+ "b1.5",
+ "b1.5_01",
+ "b1.6",
+ "b1.6.1",
+ "b1.6.2",
+ "b1.6.3",
+ "b1.6.4",
+ "b1.6.5",
+ "b1.6.6",
+ "b1.7",
+ "b1.7.2",
+ "b1.7.3",
+ "b1.8-pre1-2",
+ "b1.8-pre2",
+ "b1.8",
+ "b1.8.1",
+ "b1.9-pre1",
+ "b1.9-pre2",
+ "b1.9-pre3",
+ "b1.9-pre4",
+ "b1.9-pre5",
+ "b1.9-pre6",
+ "1.0",
+ "11w47a",
+ "11w48a",
+ "11w49a",
+ "11w50a",
+ "12w01a",
+ "1.1",
+ "12w03a",
+ "12w04a",
+ "12w05a",
+ "12w05b",
+ "12w06a",
+ "12w07b",
+ "12w07a",
+ "12w08a",
+ "1.2",
+ "1.2.1",
+ "1.2.2",
+ "1.2.3",
+ "1.2.4",
+ "1.2.5",
+ "12w16a",
+ "12w17a",
+ "12w18a",
+ "12w19a",
+ "12w21a",
+ "12w21b",
+ "12w22a",
+ "12w23a",
+ "12w23b",
+ "12w24a",
+ "12w25a",
+ "12w26a",
+ "12w27a",
+ "12w30a",
+ "12w30b",
+ "12w30c",
+ "12w30d",
+ "12w30e",
+ "1.3",
+ "1.3.1",
+ "12w32a",
+ "1.3.2",
+ "12w34a",
+ "12w34b",
+ "12w36a",
+ "12w37a",
+ "12w38a",
+ "12w38b",
+ "12w39a",
+ "12w39b",
+ "12w40a",
+ "12w40b",
+ "12w41a",
+ "12w41b",
+ "12w42a",
+ "12w42b",
+ "1.4",
+ "1.4.1",
+ "1.4.2",
+ "1.4.3",
+ "1.4.4",
+ "1.4.5",
+ "12w49a",
+ "12w50a",
+ "12w50b",
+ "1.4.6",
+ "1.4.7",
+ "13w01a",
+ "13w01b",
+ "13w02a",
+ "13w02b",
+ "13w03a",
+ "13w04a",
+ "13w05a",
+ "13w05b",
+ "13w06a",
+ "13w07a",
+ "13w11a",
+ "13w09a",
+ "13w09b",
+ "13w09c",
+ "13w10a",
+ "13w10b",
+ "1.5",
+ "13w12~",
+ "1.5.1",
+ "1.5.2",
+ "13w17a",
+ "13w18a",
+ "13w18b",
+ "13w18c",
+ "13w19a",
+ "13w21a",
+ "13w21b",
+ "13w22a",
+ "13w23a",
+ "13w23b",
+ "13w24a",
+ "13w24b",
+ "13w25a",
+ "13w25b",
+ "13w25c",
+ "13w26a",
+ "1.6",
+ "1.6.1",
+ "1.6.2",
+ "13w36a",
+ "13w36b",
+ "13w37a",
+ "1.6.3",
+ "13w37b",
+ "1.6.4",
+ "13w38a",
+ "13w38b",
+ "13w38c",
+ "13w39a",
+ "13w39b",
+ "13w41a",
+ "13w41b",
+ "13w42a",
+ "13w42b",
+ "13w43a",
+ "1.7",
+ "1.7.1",
+ "1.7.2",
+ "13w47a",
+ "13w47b",
+ "13w47c",
+ "13w47d",
+ "13w47e",
+ "13w48a",
+ "13w48b",
+ "13w49a",
+ "1.7.3",
+ "1.7.4",
+ "14w02a",
+ "14w02b",
+ "14w02c",
+ "14w03a",
+ "14w03b",
+ "14w04a",
+ "14w04b",
+ "14w05a",
+ "14w05b",
+ "14w06a",
+ "14w06b",
+ "14w07a",
+ "1.7.5",
+ "14w08a",
+ "14w10b",
+ "14w10c",
+ "1.7.6-pre1",
+ "1.7.6-pre2",
+ "14w11a"
+]
diff --git a/meta/meta/common/mojang-minecraft-old-snapshots.json b/meta/meta/common/mojang-minecraft-old-snapshots.json
new file mode 100644
index 0000000000..24ee0ce8b8
--- /dev/null
+++ b/meta/meta/common/mojang-minecraft-old-snapshots.json
@@ -0,0 +1,604 @@
+{
+ "old_snapshots": [
+ {
+ "id": "1_2",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_1.2",
+ "url": "https://archive.org/download/Minecraft-JSONs/1.2.json",
+ "sha1": "a2064011425a5e5befd9dee5eeb4f968ddf5ac77",
+ "size": 3988919,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_2/minecraft.jar"
+ },
+ {
+ "id": "11w47a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_11w47a",
+ "url": "https://archive.org/download/Minecraft-JSONs/11w47a.json",
+ "sha1": "4e327918708d22e7443fbadefb9831ca04af4b90",
+ "size": 2242242,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/11w47a/minecraft.jar"
+ },
+ {
+ "id": "11w48a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_11w48a",
+ "url": "https://archive.org/download/Minecraft-JSONs/11w48a.json",
+ "sha1": "fede770abe88a19e844d99dda611a7d18184155a",
+ "size": 2242604,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/11w48a/minecraft.jar"
+ },
+ {
+ "id": "11w49a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_11w49a",
+ "url": "https://archive.org/download/Minecraft-JSONs/11w49a.json",
+ "sha1": "6f92a726e6b8b64f66c7e4d236f983c278d5af54",
+ "size": 3510866,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/11w49a/minecraft.jar"
+ },
+ {
+ "id": "11w50a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_11w50a",
+ "url": "https://archive.org/download/Minecraft-JSONs/11w50a.json",
+ "sha1": "f4981ba0fee00a16d8dc9ec87bf2c4fdb51e4b7c",
+ "size": 3509701,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/11w50a/minecraft.jar"
+ },
+ {
+ "id": "12w01a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w01a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w01a.json",
+ "sha1": "653a9cf55884b6bc4dcf3c574331e04bd5ad1032",
+ "size": 3839447,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w01a/minecraft.jar"
+ },
+ {
+ "id": "12w03a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w03a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w03a.json",
+ "sha1": "e581c7c9dd57cbf73f72b833be5eff6109187df0",
+ "size": 3875210,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w03a/minecraft.jar"
+ },
+ {
+ "id": "12w04a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w04a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w04a.json",
+ "sha1": "4911c473e856ec8102b8419eb36d0f54dad029a0",
+ "size": 3911974,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w04a/minecraft.jar"
+ },
+ {
+ "id": "12w05a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w05a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w05a.json",
+ "sha1": "28328e67b82564335aa8280095a0716a2eb790de",
+ "size": 3931639,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w05a/minecraft.jar"
+ },
+ {
+ "id": "12w05b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w05b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w05b.json",
+ "sha1": "75fbc4a39a244d0f1eb842ff8385e992e2b47dd5",
+ "size": 3931694,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w05b/minecraft.jar"
+ },
+ {
+ "id": "12w06a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w06a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w06a.json",
+ "sha1": "a8403c0d4c0cdb65722d864d9cf42663b8aab08b",
+ "size": 3934973,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w06a/minecraft.jar"
+ },
+ {
+ "id": "12w07a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w07a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w07a.json",
+ "sha1": "e7ad115b29612b893972f0817030d993bc56fb7e",
+ "size": 3956252,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w07a/minecraft.jar"
+ },
+ {
+ "id": "12w07b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w07b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w07b.json",
+ "sha1": "0eea35d588fc2cee5d397472aa3565f48c220217",
+ "size": 3956323,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w07b/minecraft.jar"
+ },
+ {
+ "id": "12w08a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w08a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w08a.json",
+ "sha1": "db2fcfdd23526b0f381ef2f3f2fd049d36227230",
+ "size": 3981486,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w08a/minecraft.jar"
+ },
+ {
+ "id": "12w16a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w16a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w16a.json",
+ "sha1": "6b0a9fe3ac275f79ac6d259f4279752274ec05f8",
+ "size": 4080437,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w16a/minecraft.jar"
+ },
+ {
+ "id": "12w17a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w17a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w17a.json",
+ "sha1": "17d41f8a07e054040ba34e523593bdea7f0fb6ba",
+ "size": 4114768,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w17a/minecraft.jar"
+ },
+ {
+ "id": "12w18a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w18a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w18a.json",
+ "sha1": "9e9ab992317048bee9158ad9d1e2bc758db2b4af",
+ "size": 4317820,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w18a/minecraft.zip/bin/minecraft.jar"
+ },
+ {
+ "id": "12w19a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w19a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w19a.json",
+ "sha1": "474aaac9a8b1dcbf312a5c09c7eae4a6aa401225",
+ "size": 4343792,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w19a/minecraft.zip/bin/minecraft.jar"
+ },
+ {
+ "id": "12w21a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w21a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w21a.json",
+ "sha1": "e755423a04b0efde01e035a9d651acadeba0aef9",
+ "size": 4409586,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w21a/minecraft.jar"
+ },
+ {
+ "id": "12w21b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w21b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w21b.json",
+ "sha1": "84437ded4839b29d34f83e9f3bab07cc48980faf",
+ "size": 4499708,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w21b/minecraft.jar"
+ },
+ {
+ "id": "12w22a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w22a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w22a.json",
+ "sha1": "3631a714cb465d39f5cb5c18aa23abf38031b359",
+ "size": 4542344,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w22a/minecraft.jar"
+ },
+ {
+ "id": "12w23a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w23a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w23a.json",
+ "sha1": "4a5a8e3349ea2e9d67fa4dde6ec68d385bff46f0",
+ "size": 4543912,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w23a/minecraft.jar"
+ },
+ {
+ "id": "12w23b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w23b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w23b.json",
+ "sha1": "e107667bcbb4443afc160a7eeb8f347acc9826f8",
+ "size": 4543928,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w23b/minecraft.jar"
+ },
+ {
+ "id": "12w24a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w24a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w24a.json",
+ "sha1": "e479c425ffe6ca3512d97ad0e02a8cd85356bf83",
+ "size": 4540049,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w24a/minecraft.jar"
+ },
+ {
+ "id": "12w25a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w25a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w25a.json",
+ "sha1": "eddf53994e40ecc44f582d4b47b9a441844909b6",
+ "size": 4556548,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w25a/minecraft.jar"
+ },
+ {
+ "id": "12w26a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w26a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w26a.json",
+ "sha1": "2d1e782a4c4435fe921027ae464a272945cca925",
+ "size": 4573075,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w26a/minecraft.jar"
+ },
+ {
+ "id": "12w27a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w27a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w27a.json",
+ "sha1": "5e69b80f9c757bdc8275c1f6ce7e71820fe6d79a",
+ "size": 4584956,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w27a/minecraft.jar"
+ },
+ {
+ "id": "12w30a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w30a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w30a.json",
+ "sha1": "368215d7fd38ee3e829725e11b3f193d45801128",
+ "size": 4584574,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w30a/minecraft.jar"
+ },
+ {
+ "id": "12w30b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w30b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w30b.json",
+ "sha1": "9d1e450cdb300ec426b50762e031796a8349aa1c",
+ "size": 4584593,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w30b/minecraft.jar"
+ },
+ {
+ "id": "12w30c",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w30c",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w30c.json",
+ "sha1": "92817a0c3f3c913ad68bdb082ac1f147db986282",
+ "size": 4584617,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w30c/minecraft.jar"
+ },
+ {
+ "id": "12w30d",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w30d",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w30d.json",
+ "sha1": "a5e7508de2d3993cb5222d8e4f8415226745d6ff",
+ "size": 4585459,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w30d/minecraft.jar"
+ },
+ {
+ "id": "12w30e",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w30e",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w30e.json",
+ "sha1": "1a37562cda14028dae15b331bfd36108e617a477",
+ "size": 4585506,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w30e/minecraft.jar"
+ },
+ {
+ "id": "12w32a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w32a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w32a.json",
+ "sha1": "13183e023c8918ed08c302c2fe1438f61b53d094",
+ "size": 4628354,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w32a/minecraft.jar"
+ },
+ {
+ "id": "12w34a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w34a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w34a.json",
+ "sha1": "41769085c020f4651b5b5dd50a6f83be2b000b29",
+ "size": 4676139,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w34a/minecraft.jar"
+ },
+ {
+ "id": "12w34b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w34b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w34b.json",
+ "sha1": "5fb51efc8f07ea57ffc2a02a7dac8a2835651b61",
+ "size": 4682004,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w34b/minecraft.jar"
+ },
+ {
+ "id": "12w36a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w36a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w36a.json",
+ "sha1": "914bd89686c4621da327d50375a1edbdd9c177da",
+ "size": 4705667,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w36a/minecraft.jar"
+ },
+ {
+ "id": "12w37a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w37a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w37a.json",
+ "sha1": "50ea0bac2c91b13c0881bbf99aad66a046533781",
+ "size": 4727781,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w37a/minecraft.jar"
+ },
+ {
+ "id": "12w38a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w38a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w38a.json",
+ "sha1": "69e5a531fa615eb870345feb25f26126fe95586b",
+ "size": 4752649,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w38a/minecraft.jar"
+ },
+ {
+ "id": "12w38b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w38b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w38b.json",
+ "sha1": "867505cb4934016bf46cb8c7833ef0eaef8d39d9",
+ "size": 4767044,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w38b/minecraft.jar"
+ },
+ {
+ "id": "12w39a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w39a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w39a.json",
+ "sha1": "65247c02036156b9f34c17f7d8bb053641afd0e7",
+ "size": 4768937,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w39a/minecraft.jar"
+ },
+ {
+ "id": "12w39b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w39b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w39b.json",
+ "sha1": "620d02bfd74204462a810874f83929d0b8b0b936",
+ "size": 4766448,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w39b/minecraft.jar"
+ },
+ {
+ "id": "12w40a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w40a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w40a.json",
+ "sha1": "434652551e93fdfb4de30cbe64310037777f7eff",
+ "size": 4884173,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w40a/minecraft.jar"
+ },
+ {
+ "id": "12w40b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w40b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w40b.json",
+ "sha1": "1612e0fa6062f764844c5a71ff89660c311f38ae",
+ "size": 4884732,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w40b/minecraft.jar"
+ },
+ {
+ "id": "12w41a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w41a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w41a.json",
+ "sha1": "7327bcd4da0d194565d6ee732b1fa48e8b14b347",
+ "size": 4900512,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w41a/minecraft.jar"
+ },
+ {
+ "id": "12w41b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w41b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w41b.json",
+ "sha1": "d73a5b6919d10689811c11d1c3debcd817050039",
+ "size": 4900976,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w41b/minecraft.jar"
+ },
+ {
+ "id": "12w42a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w42a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w42a.json",
+ "sha1": "0b10f7afbd54392b387a23c34547cb0f30d48998",
+ "size": 4919860,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w42a/minecraft.jar"
+ },
+ {
+ "id": "12w42b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w42b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w42b.json",
+ "sha1": "74024eab7588bd33dd53baa756fd4deb92557b0a",
+ "size": 4921744,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w42b/minecraft.jar"
+ },
+ {
+ "id": "12w49a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w49a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w49a.json",
+ "sha1": "a5a4cf65cf89207eb6ad7371c9237973865eba81",
+ "size": 4990865,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w49a/minecraft.jar"
+ },
+ {
+ "id": "12w50a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w50a",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w50a.json",
+ "sha1": "96a6427720aef608a594ed1e0291e77cba398155",
+ "size": 5004175,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w50a/minecraft.jar"
+ },
+ {
+ "id": "12w50b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_12w50b",
+ "url": "https://archive.org/download/Minecraft-JSONs/12w50b.json",
+ "sha1": "73dc6efe46fef478cc5ed123e711872450e193fd",
+ "size": 5005360,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/12w50b/minecraft.jar"
+ },
+ {
+ "id": "13w01a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w01a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w01a.json",
+ "sha1": "e3256fe44cd7c6a1bf45570337e634b030589878",
+ "size": 5033591,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w01a/minecraft.jar"
+ },
+ {
+ "id": "13w01b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w01b",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w01b.json",
+ "sha1": "87f9f88eb3dcc80dcf818e44af774ab7ff63eb66",
+ "size": 5035543,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w01b/minecraft.jar"
+ },
+ {
+ "id": "13w02a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w02a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w02a.json",
+ "sha1": "e9a57e8d5dcddcc9d919054c19b10eb71fcc304e",
+ "size": 5499864,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w02a/minecraft.jar"
+ },
+ {
+ "id": "13w02b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w02b",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w02b.json",
+ "sha1": "9289953c82ce69ec3d2e59a6044a9c900a99478f",
+ "size": 5363159,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w02b/minecraft.jar"
+ },
+ {
+ "id": "13w03a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w03a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w03a.json",
+ "sha1": "6a2d3ffa88b7f5e0949f041193c6525d1c4cc22e",
+ "size": 6401672,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w03a/minecraft.jar"
+ },
+ {
+ "id": "13w04a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w04a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w04a.json",
+ "sha1": "dff06285694aab7771682f949d51bca98ce52359",
+ "size": 6426112,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w04a/minecraft.jar"
+ },
+ {
+ "id": "13w05a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w05a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w05a.json",
+ "sha1": "7808f090cb92afc8084545dd2ea305773bbd5e6e",
+ "size": 6442319,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w05a/minecraft.jar"
+ },
+ {
+ "id": "13w05b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w05b",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w05b.json",
+ "sha1": "72074d7cb843229292f71ae917dcefbc0f01461d",
+ "size": 6442459,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w05b/minecraft.jar"
+ },
+ {
+ "id": "13w06a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w06a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w06a.json",
+ "sha1": "da409ce9f9c910c08cc729aadc6f592b8ff813cb",
+ "size": 6445893,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w06a/minecraft.jar"
+ },
+ {
+ "id": "13w07a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w07a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w07a.json",
+ "sha1": "61f7dad52c34838be7a1e7d37a2370ac847ab87a",
+ "size": 6510193,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w07a/minecraft.jar"
+ },
+ {
+ "id": "13w09a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w09a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w09a.json",
+ "sha1": "9ac49c55ca76eedfc985fa245dd0682e08b34982",
+ "size": 5574252,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w09a/minecraft.jar"
+ },
+ {
+ "id": "13w09b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w09b",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w09b.json",
+ "sha1": "635161d84725b1988f814c890fe5841ad99121e1",
+ "size": 5578604,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w09b/minecraft.jar"
+ },
+ {
+ "id": "13w09c",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w09c",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w09c.json",
+ "sha1": "1367ef1410c2ce7ac0f1c58727aa4883c8677469",
+ "size": 5533426,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w09c/minecraft.jar"
+ },
+ {
+ "id": "13w10a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w10a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w10a.json",
+ "sha1": "9162bca3ba8a77da2cd26cda1e46ca89a44bac4a",
+ "size": 5534991,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w10a/minecraft.jar"
+ },
+ {
+ "id": "13w10b",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w10b",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w10b.json",
+ "sha1": "21e35ffe1772d1cf89aea653c7a883acb54b13a3",
+ "size": 5555235,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w10b/minecraft.jar"
+ },
+ {
+ "id": "13w11a",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w11a",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w11a.json",
+ "sha1": "bec6c96bc4413ea3092428aba93d7425fe6a4ea9",
+ "size": 5556608,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w11a/minecraft.jar"
+ },
+ {
+ "id": "13w12~",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_13w12~",
+ "url": "https://archive.org/download/Minecraft-JSONs/13w12~.json",
+ "sha1": "66d6c6b5205ae1e8f0ad3eb78ccf66500f39c0c7",
+ "size": 5561634,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/13w12_/minecraft.jar"
+ },
+ {
+ "id": "b1_8-pre1",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.8-pre1-2",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.8-pre1-2.json",
+ "sha1": "6789c69ede3aedf83b800c76bea56855d38a0afc",
+ "size": 1893151,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_8-pre/minecraft.jar"
+ },
+ {
+ "id": "b1_8-pre2",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.8-pre2",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.8-pre2.json",
+ "sha1": "44191f2895bf1e064269c9279778f2e3e9c3c9c7",
+ "size": 1897780,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_8-pre2/minecraft.jar"
+ },
+ {
+ "id": "b1_9-pre1",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.9-pre1",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.9-pre1.json",
+ "sha1": "fdeef0129af130aa00702e53c37c5c4029b7d50e",
+ "size": 1966908,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_9-pre/minecraft.jar"
+ },
+ {
+ "id": "b1_9-pre2",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.9-pre2",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.9-pre2.json",
+ "sha1": "b0d40cf43b625631af65e2a645c34b533251da0e",
+ "size": 1988123,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_9-pre2/minecraft.jar"
+ },
+ {
+ "id": "b1_9-pre3",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.9-pre3",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.9-pre3.json",
+ "sha1": "5b7fe76a602b7511c97740e36dc25040ccb6e76b",
+ "size": 2087104,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_9-pre3/minecraft.jar"
+ },
+ {
+ "id": "b1_9-pre4",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.9-pre4",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.9-pre4.json",
+ "sha1": "5c4831d9705f2e00e3cd993e89b822636492932a",
+ "size": 2147107,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_9-pre4/minecraft.jar"
+ },
+ {
+ "id": "b1_9-pre5",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.9-pre5",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.9-pre5.json",
+ "sha1": "e109b297d2c4ee7a0bd6aed72f38f7e3185654cf",
+ "size": 2211261,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_9-pre5/minecraft.jar"
+ },
+ {
+ "id": "b1_9-pre6",
+ "wiki": "https://minecraft.wiki/w/Java_Edition_b1.9-pre6",
+ "url": "https://archive.org/download/Minecraft-JSONs/b1.9-pre6.json",
+ "sha1": "f0983e65cd1c0768b0d1fec471ce4f69173b8126",
+ "size": 2239270,
+ "jar": "https://archive.org/download/assets.minecraft.net-2013-11-13/assets.minecraft.net/1_9-pre6/minecraft.jar"
+ }
+ ]
+}
diff --git a/meta/meta/common/mojang.py b/meta/meta/common/mojang.py
new file mode 100644
index 0000000000..fe36c3c02b
--- /dev/null
+++ b/meta/meta/common/mojang.py
@@ -0,0 +1,23 @@
+from os.path import join, dirname
+
+BASE_DIR = "mojang"
+
+VERSION_MANIFEST_FILE = join(BASE_DIR, "version_manifest_v2.json")
+VERSIONS_DIR = join(BASE_DIR, "versions")
+ASSETS_DIR = join(BASE_DIR, "assets")
+
+STATIC_EXPERIMENTS_FILE = join(dirname(__file__), "mojang-minecraft-experiments.json")
+STATIC_OLD_SNAPSHOTS_FILE = join(
+ dirname(__file__), "mojang-minecraft-old-snapshots.json"
+)
+STATIC_OVERRIDES_FILE = join(dirname(__file__), "mojang-minecraft-legacy-override.json")
+STATIC_LEGACY_SERVICES_FILE = join(
+ dirname(__file__), "mojang-minecraft-legacy-services.json"
+)
+LIBRARY_PATCHES_FILE = join(dirname(__file__), "mojang-library-patches.json")
+
+MINECRAFT_COMPONENT = "net.minecraft"
+LWJGL_COMPONENT = "org.lwjgl"
+LWJGL3_COMPONENT = "org.lwjgl3"
+
+JAVA_MANIFEST_FILE = join(BASE_DIR, "java_all.json")
diff --git a/meta/meta/common/neoforge.py b/meta/meta/common/neoforge.py
new file mode 100644
index 0000000000..83f4890e97
--- /dev/null
+++ b/meta/meta/common/neoforge.py
@@ -0,0 +1,14 @@
+from os.path import join
+
+from ..model import GradleSpecifier, make_launcher_library
+
+BASE_DIR = "neoforge"
+
+JARS_DIR = join(BASE_DIR, "jars")
+INSTALLER_INFO_DIR = join(BASE_DIR, "installer_info")
+INSTALLER_MANIFEST_DIR = join(BASE_DIR, "installer_manifests")
+VERSION_MANIFEST_DIR = join(BASE_DIR, "version_manifests")
+FILE_MANIFEST_DIR = join(BASE_DIR, "files_manifests")
+DERIVED_INDEX_FILE = join(BASE_DIR, "derived_index.json")
+
+NEOFORGE_COMPONENT = "net.neoforged"
diff --git a/meta/meta/common/quilt.py b/meta/meta/common/quilt.py
new file mode 100644
index 0000000000..b8203898b0
--- /dev/null
+++ b/meta/meta/common/quilt.py
@@ -0,0 +1,44 @@
+from os.path import join
+from .fabric import INTERMEDIARY_COMPONENT as FABRIC_INTERMEDIARY_COMPONENT
+
+# Right now Quilt recommends using Fabric's intermediary
+USE_QUILT_MAPPINGS = False
+
+BASE_DIR = "quilt"
+
+JARS_DIR = join(BASE_DIR, "jars")
+INSTALLER_INFO_DIR = join(BASE_DIR, "loader-installer-json")
+META_DIR = join(BASE_DIR, "meta-v3")
+
+LOADER_COMPONENT = "org.quiltmc.quilt-loader"
+INTERMEDIARY_COMPONENT = "org.quiltmc.hashed"
+
+if not USE_QUILT_MAPPINGS:
+ INTERMEDIARY_COMPONENT = FABRIC_INTERMEDIARY_COMPONENT
+
+DISABLE_BEACON_ARG = "-Dloader.disable_beacon=true"
+DISABLE_BEACON_VERSIONS = {
+ "0.19.2-beta.3",
+ "0.19.2-beta.4",
+ "0.19.2-beta.5",
+ "0.19.2-beta.6",
+ "0.19.2-beta.7",
+ "0.19.2",
+ "0.19.3-beta.1",
+ "0.19.3",
+ "0.19.4",
+ "0.20.0-beta.1",
+ "0.20.0-beta.2",
+ "0.20.0-beta.3",
+ "0.20.0-beta.4",
+ "0.20.0-beta.5",
+ "0.20.0-beta.6",
+ "0.20.0-beta.7",
+ "0.20.0-beta.8",
+ "0.20.0-beta.9",
+ "0.20.0-beta.10",
+ "0.20.0-beta.11",
+ "0.20.0-beta.12",
+ "0.20.0-beta.13",
+ "0.20.0-beta.14",
+}
diff --git a/meta/meta/model/__init__.py b/meta/meta/model/__init__.py
new file mode 100644
index 0000000000..203b367ed5
--- /dev/null
+++ b/meta/meta/model/__init__.py
@@ -0,0 +1,363 @@
+import copy
+from datetime import datetime
+from pathlib import Path
+from typing import Optional, List, Dict, Any, Iterator
+
+import pydantic
+from pydantic import Field, validator # type: ignore
+
+from ..common import (
+ LAUNCHER_MAVEN,
+ serialize_datetime,
+ replace_old_launchermeta_url,
+ get_all_bases,
+ merge_dict,
+)
+
+META_FORMAT_VERSION = 1
+
+
+class GradleSpecifier:
+ """
+ A gradle specifier - a maven coordinate. Like one of these:
+ "org.lwjgl.lwjgl:lwjgl:2.9.0"
+ "net.java.jinput:jinput:2.0.5"
+ "net.minecraft:launchwrapper:1.5"
+ """
+
+ def __init__(
+ self,
+ group: str,
+ artifact: str,
+ version: str,
+ classifier: Optional[str] = None,
+ extension: Optional[str] = None,
+ ):
+ if extension is None:
+ extension = "jar"
+ self.group = group
+ self.artifact = artifact
+ self.version = version
+ self.classifier = classifier
+ self.extension = extension
+
+ def __str__(self):
+ ext = ""
+ if self.extension != "jar":
+ ext = "@%s" % self.extension
+ if self.classifier:
+ return "%s:%s:%s:%s%s" % (
+ self.group,
+ self.artifact,
+ self.version,
+ self.classifier,
+ ext,
+ )
+ else:
+ return "%s:%s:%s%s" % (self.group, self.artifact, self.version, ext)
+
+ def filename(self):
+ if self.classifier:
+ return "%s-%s-%s.%s" % (
+ self.artifact,
+ self.version,
+ self.classifier,
+ self.extension,
+ )
+ else:
+ return "%s-%s.%s" % (self.artifact, self.version, self.extension)
+
+ def base(self):
+ return "%s/%s/%s/" % (self.group.replace(".", "/"), self.artifact, self.version)
+
+ def path(self):
+ return self.base() + self.filename()
+
+ def __repr__(self):
+ return f"GradleSpecifier('{self}')"
+
+ def is_lwjgl(self):
+ return self.group in (
+ "org.lwjgl",
+ "org.lwjgl.lwjgl",
+ "net.java.jinput",
+ "net.java.jutils",
+ )
+
+ def is_log4j(self):
+ return self.group == "org.apache.logging.log4j"
+
+ def __eq__(self, other: Any):
+ if isinstance(other, GradleSpecifier):
+ return str(self) == str(other)
+ else:
+ return False
+
+ def __lt__(self, other: "GradleSpecifier"):
+ return str(self) < str(other)
+
+ def __gt__(self, other: "GradleSpecifier"):
+ return str(self) > str(other)
+
+ def __hash__(self):
+ return hash(str(self))
+
+ @classmethod
+ def __get_validators__(cls):
+ yield cls.validate
+
+ @classmethod
+ def from_string(cls, v: str):
+ ext_split = v.split("@")
+
+ components = ext_split[0].split(":")
+ group = components[0]
+ artifact = components[1]
+ version = components[2]
+
+ extension = None
+ if len(ext_split) == 2:
+ extension = ext_split[1]
+
+ classifier = None
+ if len(components) == 4:
+ classifier = components[3]
+ return cls(group, artifact, version, classifier, extension)
+
+ @classmethod
+ def validate(cls, v: "str | GradleSpecifier"):
+ if isinstance(v, cls):
+ return v
+ if isinstance(v, str):
+ return cls.from_string(v)
+ raise TypeError("Invalid type")
+
+
+class MetaBase(pydantic.BaseModel):
+ def dict(self, **kwargs: Any) -> Dict[str, Any]:
+ for k in ["by_alias"]:
+ if k in kwargs:
+ del kwargs[k]
+
+ return super(MetaBase, self).dict(by_alias=True, **kwargs)
+
+ def json(self, **kwargs: Any) -> str:
+ for k in ["exclude_none", "sort_keys", "indent"]:
+ if k in kwargs:
+ del kwargs[k]
+
+ return super(MetaBase, self).json(
+ exclude_none=True, sort_keys=True, by_alias=True, indent=4, **kwargs
+ )
+
+ def write(self, file_path: str):
+ Path(file_path).parent.mkdir(parents=True, exist_ok=True)
+ with open(file_path, "w") as f:
+ f.write(self.json())
+
+ def merge(self, other: "MetaBase"):
+ """
+ Merge other object with self.
+ - Concatenates lists
+ - Combines sets
+ - Merges dictionaries (other takes priority)
+ - Recurses for all fields that are also MetaBase classes
+ - Overwrites for any other field type (int, string, ...)
+ """
+ assert type(other) is type(self)
+ for key, field in self.__fields__.items():
+ ours = getattr(self, key)
+ theirs = getattr(other, key)
+ if theirs is None:
+ continue
+ if ours is None:
+ setattr(self, key, theirs)
+ continue
+
+ if isinstance(ours, list):
+ ours += theirs
+ elif isinstance(ours, set):
+ ours |= theirs
+ elif isinstance(ours, dict):
+ result = merge_dict(ours, copy.deepcopy(theirs)) # type: ignore
+ setattr(self, key, result)
+ elif MetaBase in get_all_bases(field.type_):
+ ours.merge(theirs)
+ else:
+ setattr(self, key, theirs)
+
+ def __hash__(self): # type: ignore
+ return hash(self.json())
+
+ class Config:
+ allow_population_by_field_name = True
+
+ json_encoders = {datetime: serialize_datetime, GradleSpecifier: str}
+
+
+class Versioned(MetaBase):
+ @validator("format_version")
+ def format_version_must_be_supported(cls, v: int):
+ assert v <= META_FORMAT_VERSION
+ return v
+
+ format_version: int = Field(META_FORMAT_VERSION, alias="formatVersion")
+
+
+class MojangArtifactBase(MetaBase):
+ sha1: Optional[str]
+ size: Optional[int]
+ url: str
+
+
+class MojangAssets(MojangArtifactBase):
+ @validator("url")
+ def validate_url(cls, v: str):
+ return replace_old_launchermeta_url(v)
+
+ id: str
+ totalSize: int
+
+
+class MojangArtifact(MojangArtifactBase):
+ path: Optional[str]
+
+
+class MojangLibraryExtractRules(MetaBase):
+ """
+ "rules": [
+ {
+ "action": "allow"
+ },
+ {
+ "action": "disallow",
+ "os": {
+ "name": "osx"
+ }
+ }
+ ]
+ """
+
+ exclude: List[str] # TODO maybe drop this completely?
+
+
+class MojangLibraryDownloads(MetaBase):
+ artifact: Optional[MojangArtifact]
+ classifiers: Optional[Dict[Any, MojangArtifact]]
+
+
+class OSRule(MetaBase):
+ @validator("name")
+ def name_must_be_os(cls, v: str):
+ assert v in [
+ "osx",
+ "linux",
+ "windows",
+ "windows-arm64",
+ "osx-arm64",
+ "linux-arm64",
+ "linux-arm32",
+ "linux-riscv64",
+ ]
+ return v
+
+ name: str
+ version: Optional[str]
+
+
+class MojangRule(MetaBase):
+ @validator("action")
+ def action_must_be_allow_disallow(cls, v: str):
+ assert v in ["allow", "disallow"]
+ return v
+
+ action: str
+ os: Optional[OSRule]
+
+
+class MojangRules(MetaBase):
+ __root__: List[MojangRule]
+
+ def __iter__(self) -> Iterator[MojangRule]: # type: ignore
+ return iter(self.__root__)
+
+ def __getitem__(self, item: int) -> MojangRule:
+ return self.__root__[item]
+
+
+class MojangLoggingArtifact(MojangArtifactBase):
+ id: str
+
+
+class MojangLogging(MetaBase):
+ @validator("type")
+ def validate_type(cls, v):
+ assert v in ["log4j2-xml"]
+ return v
+
+ file: MojangLoggingArtifact
+ argument: str
+ type: str
+
+
+class Library(MetaBase):
+ extract: Optional[MojangLibraryExtractRules]
+ name: Optional[GradleSpecifier]
+ downloads: Optional[MojangLibraryDownloads]
+ natives: Optional[Dict[str, str]]
+ rules: Optional[MojangRules]
+ url: Optional[str]
+ mmcHint: Optional[str] = Field(None, alias="MMC-hint")
+
+
+class JavaAgent(Library):
+ argument: Optional[str]
+
+
+class Dependency(MetaBase):
+ uid: str
+ equals: Optional[str]
+ suggests: Optional[str]
+
+
+class MetaVersion(Versioned):
+ name: str
+ version: str
+ uid: str
+ type: Optional[str]
+ order: Optional[int]
+ volatile: Optional[bool]
+ requires: Optional[List[Dependency]]
+ conflicts: Optional[List[Dependency]]
+ libraries: Optional[List[Library]]
+ asset_index: Optional[MojangAssets] = Field(alias="assetIndex")
+ maven_files: Optional[List[Library]] = Field(alias="mavenFiles")
+ main_jar: Optional[Library] = Field(alias="mainJar")
+ jar_mods: Optional[List[Library]] = Field(alias="jarMods")
+ main_class: Optional[str] = Field(alias="mainClass")
+ applet_class: Optional[str] = Field(alias="appletClass")
+ minecraft_arguments: Optional[str] = Field(alias="minecraftArguments")
+ release_time: Optional[datetime] = Field(alias="releaseTime")
+ compatible_java_majors: Optional[List[int]] = Field(alias="compatibleJavaMajors")
+ compatible_java_name: Optional[str] = Field(alias="compatibleJavaName")
+ java_agents: Optional[List[JavaAgent]] = Field(alias="+agents")
+ additional_traits: Optional[List[str]] = Field(alias="+traits")
+ additional_tweakers: Optional[List[str]] = Field(alias="+tweakers")
+ additional_jvm_args: Optional[List[str]] = Field(alias="+jvmArgs")
+ logging: Optional[MojangLogging]
+
+
+class MetaPackage(Versioned):
+ name: str
+ uid: str
+ recommended: Optional[List[str]]
+ authors: Optional[List[str]]
+ description: Optional[str]
+ project_url: Optional[str] = Field(alias="projectUrl")
+
+
+def make_launcher_library(
+ name: GradleSpecifier, hash: str, size: int, maven=LAUNCHER_MAVEN
+):
+ artifact = MojangArtifact(url=maven % name.path(), sha1=hash, size=size)
+ return Library(name=name, downloads=MojangLibraryDownloads(artifact=artifact))
diff --git a/meta/meta/model/enum.py b/meta/meta/model/enum.py
new file mode 100644
index 0000000000..08dda4bf4a
--- /dev/null
+++ b/meta/meta/model/enum.py
@@ -0,0 +1,32 @@
+import enum
+
+
+class StrEnum(str, enum.Enum):
+ """
+ StrEnum is a Python ``enum.Enum`` that inherits from ``str``. The default
+ ``auto()`` behavior uses the member name as its value.
+
+ Example usage::
+
+ class Example(StrEnum):
+ UPPER_CASE = auto()
+ lower_case = auto()
+ MixedCase = auto()
+
+ assert Example.UPPER_CASE == "UPPER_CASE"
+ assert Example.lower_case == "lower_case"
+ assert Example.MixedCase == "MixedCase"
+ """
+
+ def __new__(cls, value, *args, **kwargs):
+ if not isinstance(value, (str, enum.auto)):
+ raise TypeError(
+ f"Values of StrEnums must be strings: {value!r} is a {type(value)}"
+ )
+ return super().__new__(cls, value, *args, **kwargs)
+
+ def __str__(self):
+ return str(self.value)
+
+ def _generate_next_value_(name, *_):
+ return name
diff --git a/meta/meta/model/fabric.py b/meta/meta/model/fabric.py
new file mode 100644
index 0000000000..5cb0e9caab
--- /dev/null
+++ b/meta/meta/model/fabric.py
@@ -0,0 +1,40 @@
+from datetime import datetime
+from typing import Optional, List, Union
+
+from pydantic import Field
+
+from . import Library, MetaBase
+
+
+class FabricInstallerArguments(MetaBase):
+ client: Optional[List[str]]
+ common: Optional[List[str]]
+ server: Optional[List[str]]
+
+
+class FabricInstallerLaunchwrapper(MetaBase):
+ tweakers: FabricInstallerArguments
+
+
+class FabricInstallerLibraries(MetaBase):
+ client: Optional[List[Library]]
+ common: Optional[List[Library]]
+ server: Optional[List[Library]]
+
+
+class FabricMainClasses(MetaBase):
+ client: Optional[str]
+ common: Optional[str]
+ server: Optional[str]
+
+
+class FabricInstallerDataV1(MetaBase):
+ version: int
+ libraries: FabricInstallerLibraries
+ main_class: Optional[Union[str, FabricMainClasses]] = Field(alias="mainClass")
+ arguments: Optional[FabricInstallerArguments]
+ launchwrapper: Optional[FabricInstallerLaunchwrapper]
+
+
+class FabricJarInfo(MetaBase):
+ release_time: Optional[datetime] = Field(alias="releaseTime")
diff --git a/meta/meta/model/forge.py b/meta/meta/model/forge.py
new file mode 100644
index 0000000000..a59b87aa5c
--- /dev/null
+++ b/meta/meta/model/forge.py
@@ -0,0 +1,365 @@
+from datetime import datetime
+from typing import Optional, List, Dict
+
+from pydantic import Field
+
+from . import MetaBase, GradleSpecifier, Library
+from .mojang import MojangVersion
+
+
+class ForgeFile(MetaBase):
+ classifier: str
+ hash: str
+ extension: str
+
+ def filename(self, long_version):
+ return "%s-%s-%s.%s" % ("forge", long_version, self.classifier, self.extension)
+
+ def url(self, long_version):
+ return "https://maven.minecraftforge.net/net/minecraftforge/forge/%s/%s" % (
+ long_version,
+ self.filename(long_version),
+ )
+
+
+class ForgeEntry(MetaBase):
+ long_version: str = Field(alias="longversion")
+ mc_version: str = Field(alias="mcversion")
+ version: str
+ build: int
+ branch: Optional[str]
+ latest: Optional[bool]
+ recommended: Optional[bool]
+ files: Optional[Dict[str, ForgeFile]]
+
+
+class ForgeMCVersionInfo(MetaBase):
+ latest: Optional[str]
+ recommended: Optional[str]
+ versions: List[str] = Field([])
+
+
+class DerivedForgeIndex(MetaBase):
+ versions: Dict[str, ForgeEntry] = Field({})
+ by_mc_version: Dict[str, ForgeMCVersionInfo] = Field({}, alias="by_mcversion")
+
+
+class FMLLib(
+ MetaBase
+): # old ugly stuff. Maybe merge this with Library or Library later
+ filename: str
+ checksum: str
+ ours: bool
+
+
+class ForgeInstallerProfileInstallSection(MetaBase):
+ """
+ "install": {
+ "profileName": "Forge",
+ "target":"Forge8.9.0.753",
+ "path":"net.minecraftforge:minecraftforge:8.9.0.753",
+ "version":"Forge 8.9.0.753",
+ "filePath":"minecraftforge-universal-1.6.1-8.9.0.753.jar",
+ "welcome":"Welcome to the simple Forge installer.",
+ "minecraft":"1.6.1",
+ "logo":"/big_logo.png",
+ "mirrorList": "http://files.minecraftforge.net/mirror-brand.list"
+ },
+ "install": {
+ "profileName": "forge",
+ "target":"1.11-forge1.11-13.19.0.2141",
+ "path":"net.minecraftforge:forge:1.11-13.19.0.2141",
+ "version":"forge 1.11-13.19.0.2141",
+ "filePath":"forge-1.11-13.19.0.2141-universal.jar",
+ "welcome":"Welcome to the simple forge installer.",
+ "minecraft":"1.11",
+ "mirrorList" : "http://files.minecraftforge.net/mirror-brand.list",
+ "logo":"/big_logo.png",
+ "modList":"none"
+ },
+ """
+
+ profile_name: str = Field(alias="profileName")
+ target: str
+ path: GradleSpecifier
+ version: str
+ file_path: str = Field(alias="filePath")
+ welcome: str
+ minecraft: str
+ logo: str
+ mirror_list: str = Field(alias="mirrorList")
+ mod_list: Optional[str] = Field(alias="modList")
+
+
+class ForgeLibrary(Library):
+ url: Optional[str]
+ server_req: Optional[bool] = Field(alias="serverreq")
+ client_req: Optional[bool] = Field(alias="clientreq")
+ checksums: Optional[List[str]]
+ comment: Optional[str]
+
+
+class ForgeVersionFile(MojangVersion):
+ libraries: Optional[List[ForgeLibrary]] # overrides Mojang libraries
+ inherits_from: Optional[str] = Field("inheritsFrom")
+ jar: Optional[str]
+
+
+class ForgeOptional(MetaBase):
+ """
+ "optionals": [
+ {
+ "name": "Mercurius",
+ "client": true,
+ "server": true,
+ "default": true,
+ "inject": true,
+ "desc": "A mod that collects statistics about Minecraft and your system.<br>Useful for Forge to understand how Minecraft/Forge are used.",
+ "url": "http://www.minecraftforge.net/forum/index.php?topic=43278.0",
+ "artifact": "net.minecraftforge:MercuriusUpdater:1.11.2",
+ "maven": "http://maven.minecraftforge.net/"
+ }
+ ]
+ """
+
+ name: Optional[str]
+ client: Optional[bool]
+ server: Optional[bool]
+ default: Optional[bool]
+ inject: Optional[bool]
+ desc: Optional[str]
+ url: Optional[str]
+ artifact: Optional[GradleSpecifier]
+ maven: Optional[str]
+
+
+class ForgeInstallerProfile(MetaBase):
+ install: ForgeInstallerProfileInstallSection
+ version_info: ForgeVersionFile = Field(alias="versionInfo")
+ optionals: Optional[List[ForgeOptional]]
+
+
+class ForgeLegacyInfo(MetaBase):
+ release_time: Optional[datetime] = Field(alias="releaseTime")
+ size: Optional[int]
+ sha256: Optional[str]
+ sha1: Optional[str]
+
+
+class ForgeLegacyInfoList(MetaBase):
+ number: Dict[str, ForgeLegacyInfo] = Field({})
+
+
+class DataSpec(MetaBase):
+ client: Optional[str]
+ server: Optional[str]
+
+
+class ProcessorSpec(MetaBase):
+ jar: Optional[str]
+ classpath: Optional[List[str]]
+ args: Optional[List[str]]
+ outputs: Optional[Dict[str, str]]
+ sides: Optional[List[str]]
+
+
+class ForgeInstallerProfileV2(MetaBase):
+ _comment: Optional[List[str]]
+ spec: Optional[int]
+ profile: Optional[str]
+ version: Optional[str]
+ icon: Optional[str]
+ json_data: Optional[str] = Field(alias="json")
+ path: Optional[GradleSpecifier]
+ logo: Optional[str]
+ minecraft: Optional[str]
+ welcome: Optional[str]
+ data: Optional[Dict[str, DataSpec]]
+ processors: Optional[List[ProcessorSpec]]
+ libraries: Optional[List[Library]]
+ mirror_list: Optional[str] = Field(alias="mirrorList")
+ server_jar_path: Optional[str] = Field(alias="serverJarPath")
+
+
+class InstallerInfo(MetaBase):
+ sha1hash: Optional[str]
+ sha256hash: Optional[str]
+ size: Optional[int]
+
+
+# A post-processed entry constructed from the reconstructed Forge version index
+class ForgeVersion:
+ def __init__(self, entry: ForgeEntry):
+ self.build = entry.build
+ self.rawVersion = entry.version
+ self.mc_version = entry.mc_version
+ self.mc_version_sane = self.mc_version.replace("_pre", "-pre", 1)
+ self.branch = entry.branch
+ self.installer_filename = None
+ self.installer_url = None
+ self.universal_filename = None
+ self.universal_url = None
+ self.changelog_url = None
+ self.long_version = "%s-%s" % (self.mc_version, self.rawVersion)
+ if self.branch is not None:
+ self.long_version += "-%s" % self.branch
+
+ # this comment's whole purpose is to say this: cringe
+ for classifier, file in entry.files.items():
+ extension = file.extension
+ filename = file.filename(self.long_version)
+ url = file.url(self.long_version)
+ if (classifier == "installer") and (extension == "jar"):
+ self.installer_filename = filename
+ self.installer_url = url
+ if (classifier == "universal" or classifier == "client") and (
+ extension == "jar" or extension == "zip"
+ ):
+ self.universal_filename = filename
+ self.universal_url = url
+ if (classifier == "changelog") and (extension == "txt"):
+ self.changelog_url = url
+
+ def name(self):
+ return "Forge %d" % self.build
+
+ def uses_installer(self):
+ if self.installer_url is None:
+ return False
+ if self.mc_version == "1.5.2":
+ return False
+ return True
+
+ def filename(self):
+ if self.uses_installer():
+ return self.installer_filename
+ return self.universal_filename
+
+ def url(self):
+ if self.uses_installer():
+ return self.installer_url
+ return self.universal_url
+
+ def is_supported(self):
+ if self.url() is None:
+ return False
+
+ foo = self.rawVersion.split(".")
+ if len(foo) < 1:
+ return False
+
+ major_version = foo[0]
+ if not major_version.isnumeric():
+ return False
+
+ # majorVersion = int(majorVersionStr)
+ # if majorVersion >= 37:
+ # return False
+
+ return True
+
+
+def fml_libs_for_version(mc_version: str) -> List[FMLLib]:
+ argo_2_25 = FMLLib(
+ filename="argo-2.25.jar",
+ checksum="bb672829fde76cb163004752b86b0484bd0a7f4b",
+ ours=False,
+ )
+ argo_small_3_2 = FMLLib(
+ filename="argo-small-3.2.jar",
+ checksum="58912ea2858d168c50781f956fa5b59f0f7c6b51",
+ ours=False,
+ )
+ guava_12_0_1 = FMLLib(
+ filename="guava-12.0.1.jar",
+ checksum="b8e78b9af7bf45900e14c6f958486b6ca682195f",
+ ours=False,
+ )
+ guava_14_0_rc3 = FMLLib(
+ filename="guava-14.0-rc3.jar",
+ checksum="931ae21fa8014c3ce686aaa621eae565fefb1a6a",
+ ours=False,
+ )
+ asm_all_4_0 = FMLLib(
+ filename="asm-all-4.0.jar",
+ checksum="98308890597acb64047f7e896638e0d98753ae82",
+ ours=False,
+ )
+ asm_all_4_1 = FMLLib(
+ filename="asm-all-4.1.jar",
+ checksum="054986e962b88d8660ae4566475658469595ef58",
+ ours=False,
+ )
+ bcprov_jdk15on_147 = FMLLib(
+ filename="bcprov-jdk15on-147.jar",
+ checksum="b6f5d9926b0afbde9f4dbe3db88c5247be7794bb",
+ ours=False,
+ )
+ bcprov_jdk15on_148 = FMLLib(
+ filename="bcprov-jdk15on-148.jar",
+ checksum="960dea7c9181ba0b17e8bab0c06a43f0a5f04e65",
+ ours=True,
+ )
+ scala_library = FMLLib(
+ filename="scala-library.jar",
+ checksum="458d046151ad179c85429ed7420ffb1eaf6ddf85",
+ ours=True,
+ )
+
+ deobfuscation_data_1_5 = FMLLib(
+ filename="deobfuscation_data_1.5.zip",
+ checksum="5f7c142d53776f16304c0bbe10542014abad6af8",
+ ours=False,
+ )
+
+ deobfuscation_data_1_5_1 = FMLLib(
+ filename="deobfuscation_data_1.5.1.zip",
+ checksum="22e221a0d89516c1f721d6cab056a7e37471d0a6",
+ ours=False,
+ )
+ deobfuscation_data_1_5_2 = FMLLib(
+ filename="deobfuscation_data_1.5.2.zip",
+ checksum="446e55cd986582c70fcf12cb27bc00114c5adfd9",
+ ours=False,
+ )
+ if mc_version == "1.3.2":
+ return [argo_2_25, guava_12_0_1, asm_all_4_0]
+ elif mc_version in [
+ "1.4",
+ "1.4.1",
+ "1.4.2",
+ "1.4.3",
+ "1.4.4",
+ "1.4.5",
+ "1.4.6",
+ "1.4.7",
+ ]:
+ return [argo_2_25, guava_12_0_1, asm_all_4_0, bcprov_jdk15on_147]
+ elif mc_version == "1.5":
+ return [
+ argo_small_3_2,
+ guava_14_0_rc3,
+ asm_all_4_1,
+ bcprov_jdk15on_148,
+ deobfuscation_data_1_5,
+ scala_library,
+ ]
+ elif mc_version == "1.5.1":
+ return [
+ argo_small_3_2,
+ guava_14_0_rc3,
+ asm_all_4_1,
+ bcprov_jdk15on_148,
+ deobfuscation_data_1_5_1,
+ scala_library,
+ ]
+ elif mc_version == "1.5.2":
+ return [
+ argo_small_3_2,
+ guava_14_0_rc3,
+ asm_all_4_1,
+ bcprov_jdk15on_148,
+ deobfuscation_data_1_5_2,
+ scala_library,
+ ]
+ return []
diff --git a/meta/meta/model/index.py b/meta/meta/model/index.py
new file mode 100644
index 0000000000..c6d82e1aff
--- /dev/null
+++ b/meta/meta/model/index.py
@@ -0,0 +1,46 @@
+from datetime import datetime
+from typing import Optional, List
+
+from pydantic import Field
+
+from meta.model import Dependency, MetaBase, Versioned, MetaVersion
+
+
+class MetaVersionIndexEntry(MetaBase):
+ version: str
+ type: Optional[str]
+ release_time: datetime = Field(alias="releaseTime")
+ requires: Optional[List[Dependency]]
+ conflicts: Optional[List[Dependency]]
+ recommended: Optional[bool]
+ volatile: Optional[bool]
+ sha256: str
+
+ @classmethod
+ def from_meta_version(cls, v: MetaVersion, recommended: bool, sha256: str):
+ return cls(
+ version=v.version,
+ type=v.type,
+ release_time=v.release_time,
+ requires=v.requires,
+ conflicts=v.conflicts,
+ recommended=recommended,
+ volatile=v.volatile,
+ sha256=sha256,
+ )
+
+
+class MetaVersionIndex(Versioned):
+ name: str
+ uid: str
+ versions: List[MetaVersionIndexEntry] = Field([])
+
+
+class MetaPackageIndexEntry(MetaBase):
+ name: str
+ uid: str
+ sha256: str
+
+
+class MetaPackageIndex(Versioned):
+ packages: List[MetaPackageIndexEntry] = Field([])
diff --git a/meta/meta/model/java.py b/meta/meta/model/java.py
new file mode 100644
index 0000000000..c3efde9292
--- /dev/null
+++ b/meta/meta/model/java.py
@@ -0,0 +1,597 @@
+from . import (
+ MetaBase,
+ MetaVersion,
+ Versioned,
+)
+from pydantic import Field
+from datetime import datetime
+from enum import IntEnum, Enum
+from .enum import StrEnum
+from typing import Optional, Any, NamedTuple, Generator
+from urllib.parse import urlencode, urlparse, urlunparse
+from functools import total_ordering
+
+# namedtuple to match the internal signature of urlunparse
+
+
+class JavaRuntimeOS(StrEnum):
+ MacOsX64 = "mac-os-x64"
+ MacOsX86 = "mac-os-x86" # rare
+ MacOsArm64 = "mac-os-arm64"
+ # MacOsArm32 = "mac-os-arm32" # doesn't exist
+ LinuxX64 = "linux-x64"
+ LinuxX86 = "linux-x86"
+ LinuxArm64 = "linux-arm64"
+ LinuxArm32 = "linux-arm32"
+ LinuxRiscv64 = "linux-riscv64"
+ WindowsX64 = "windows-x64"
+ WindowsX86 = "windows-x86"
+ WindowsArm64 = "windows-arm64"
+ WindowsArm32 = "windows-arm32"
+ Unknown = "unknown"
+
+
+class JavaRuntimeDownloadType(StrEnum):
+ Manifest = "manifest"
+ Archive = "archive"
+
+
+@total_ordering
+class JavaVersionMeta(MetaBase):
+ major: int
+ minor: int
+ security: int
+ build: Optional[int] = None
+ buildstr: Optional[str] = None
+ name: Optional[str] = None
+
+ def __str__(self):
+ ver = f"{self.major}.{self.minor}.{self.security}"
+ if self.build is not None:
+ ver = f"{ver}+{self.build}"
+ if self.buildstr is not None:
+ ver = f"{ver}-{self.buildstr}"
+ return ver
+
+ def to_tuple(self):
+ build = 0
+ if self.build is not None:
+ build = self.build
+ return (self.major, self.minor, self.security, build, self.buildstr)
+
+ def __eq__(self, other: Any):
+ return self.to_tuple() == other.to_tuple()
+
+ def __lt__(self, other: "JavaVersionMeta"):
+ return self.to_tuple() < other.to_tuple()
+
+
+class JavaChecksumType(StrEnum):
+ Sha1 = "sha1"
+ Sha256 = "sha256"
+
+
+class JavaChecksumMeta(MetaBase):
+ type: JavaChecksumType
+ hash: str
+
+
+class JavaPackageType(StrEnum):
+ Jre = "jre"
+ Jdk = "jdk"
+
+
+class JavaRuntimeMeta(MetaBase):
+ name: str
+ vendor: str
+ url: str
+ release_time: datetime = Field(alias="releaseTime")
+ checksum: Optional[JavaChecksumMeta]
+ download_type: JavaRuntimeDownloadType = Field(alias="downloadType")
+ package_type: JavaPackageType = Field(alias="packageType")
+ version: JavaVersionMeta
+ runtime_os: JavaRuntimeOS = Field(alias="runtimeOS")
+
+
+class JavaRuntimeVersion(MetaVersion):
+ runtimes: list[JavaRuntimeMeta]
+
+
+class URLComponents(NamedTuple):
+ scheme: str
+ netloc: str
+ url: str
+ path: str
+ query: str
+ fragment: str
+
+
+class APIQuery(MetaBase):
+ def to_query(self):
+ set_parts: dict[str, Any] = {}
+ for key, value in self.dict().items():
+ if value is not None:
+ if isinstance(value, Enum):
+ set_parts[key] = value.value
+ elif isinstance(value, list):
+ if len(value) > 0: # type: ignore
+ set_parts[key] = value
+ elif isinstance(value, datetime):
+ set_parts[key] = value.isoformat()
+ else:
+ set_parts[key] = value
+ return urlencode(set_parts, doseq=True)
+
+
+# Adoptx refers to both Adoptium (Eclipse Temurin) and AdoptOpenJDK (IBM Semeru Runtime Open Edition)
+class AdoptxJvmImpl(StrEnum):
+ Hotspot = "hotspot"
+ OpenJ9 = "openj9"
+
+
+class AdoptxVendor(StrEnum):
+ Eclipse = "eclipse"
+ Ibm = "ibm"
+
+
+class AdoptxArchitecture(StrEnum):
+ X64 = "x64"
+ X86 = "x86"
+ X32 = "x32"
+ Ppc64 = "ppc64"
+ Ppc64le = "ppc64le"
+ S390x = "s390x"
+ Aarch64 = "aarch64"
+ Arm = "arm"
+ Sparcv9 = "sparcv9"
+ Riscv64 = "riscv64"
+
+
+class AdoptxReleaseType(StrEnum):
+ GeneralAccess = "ga"
+ EarlyAccess = "ea"
+
+
+class AdoptxSortMethod(StrEnum):
+ Default = "DEFAULT"
+ Date = "DATE"
+
+
+class AdoptxSortOrder(StrEnum):
+ Asc = "ASC"
+ Desc = "DESC"
+
+
+class AdoptxImageType(StrEnum):
+ Jdk = "jdk"
+ Jre = "jre"
+ Testimage = "testimage"
+ Debugimage = "debugimage"
+ Staticlibs = "staticlibs"
+ Sources = "sources"
+ Sbom = "sbom"
+
+
+class AdoptxHeapSize(StrEnum):
+ Normal = "normal"
+ Large = "large"
+
+
+class AdoptxProject(StrEnum):
+ Jdk = "jdk"
+ Valhalla = "valhalla"
+ Metropolis = "metropolis"
+ Jfr = "jfr"
+ Shenandoah = "shenandoah"
+
+
+class AdoptxCLib(StrEnum):
+ Musl = "musl"
+ Glibc = "glibc"
+
+
+class AdoptxOs(StrEnum):
+ Linux = "linux"
+ Windows = "windows"
+ Mac = "mac"
+ Solaris = "solaris"
+ Aix = "aix"
+ AlpineLinux = "alpine-linux"
+
+
+ADOPTIUM_API_BASE = "https://api.adoptium.net"
+OPENJ9_API_BASE = " https://api.adoptopenjdk.net"
+ADOPTX_API_FEATURE_RELEASES = (
+ f"{{base_url}}/v3/assets/feature_releases/{{feature_version}}/{{release_type}}"
+)
+# ?image_type={{image_type}}&heap_size={{heap_size}}&project={{project}}&vendor={{vendor}}&page_size={{page_size}}&page={{page}}&sort_method={{sort_method}}&sort_order={{sort_order}}
+ADOPTX_API_AVAILABLE_RELEASES = f"{{base_url}}/v3/info/available_releases"
+
+
+class AdoptxAPIFeatureReleasesQuery(APIQuery):
+ architecture: Optional[AdoptxArchitecture] = None
+ before: Optional[datetime] = None
+ c_lib: Optional[AdoptxCLib] = None
+ heap_size: Optional[AdoptxHeapSize] = AdoptxHeapSize.Normal
+ image_type: Optional[AdoptxImageType] = None
+ jvm_impl: Optional[AdoptxJvmImpl] = None
+ os: Optional[AdoptxOs] = None
+ vendor: Optional[AdoptxVendor] = None
+ page_size: int = 10
+ page: int = 0
+ project: Optional[AdoptxProject] = AdoptxProject.Jdk
+ sort_method: Optional[AdoptxSortMethod] = AdoptxSortMethod.Default
+ sort_order: Optional[AdoptxSortOrder] = AdoptxSortOrder.Desc
+
+
+def adoptxAPIFeatureReleasesUrl(
+ base_url: str,
+ feature_version: int,
+ release_type: AdoptxReleaseType = AdoptxReleaseType.GeneralAccess,
+ query: AdoptxAPIFeatureReleasesQuery = AdoptxAPIFeatureReleasesQuery(),
+):
+ url = urlparse(
+ ADOPTX_API_FEATURE_RELEASES.format(
+ base_url=base_url,
+ feature_version=feature_version,
+ release_type=release_type.value,
+ )
+ )
+ return urlunparse(url._replace(query=query.to_query()))
+
+
+def adoptiumAPIFeatureReleasesUrl(
+ feature_version: int,
+ release_type: AdoptxReleaseType = AdoptxReleaseType.GeneralAccess,
+ query: AdoptxAPIFeatureReleasesQuery = AdoptxAPIFeatureReleasesQuery(),
+):
+ return adoptxAPIFeatureReleasesUrl(
+ feature_version=feature_version,
+ release_type=release_type,
+ query=query,
+ base_url=ADOPTIUM_API_BASE,
+ )
+
+
+def openj9APIFeatureReleasesUrl(
+ feature_version: int,
+ release_type: AdoptxReleaseType = AdoptxReleaseType.GeneralAccess,
+ query: AdoptxAPIFeatureReleasesQuery = AdoptxAPIFeatureReleasesQuery(),
+):
+ return adoptxAPIFeatureReleasesUrl(
+ feature_version=feature_version,
+ release_type=release_type,
+ query=query,
+ base_url=OPENJ9_API_BASE,
+ )
+
+
+class AdoptxAvailableReleases(MetaBase):
+ available_releases: list[int]
+ available_lts_releases: list[int]
+ most_recent_lts: Optional[int]
+ most_recent_feature_release: Optional[int]
+ most_recent_feature_version: Optional[int]
+ tip_version: Optional[int]
+
+
+class AdoptxFile(MetaBase):
+ name: str
+ link: str
+ size: Optional[int]
+
+
+class AdoptxPackage(AdoptxFile):
+ checksum: Optional[str]
+ checksum_link: Optional[str]
+ signature_link: Optional[str]
+ metadata_link: Optional[str]
+ # we intentionally omit download_count
+
+
+class AdoptxBinary(MetaBase):
+ os: str
+ architecture: AdoptxArchitecture
+ image_type: AdoptxImageType
+ c_lib: Optional[AdoptxCLib]
+ jvm_impl: AdoptxJvmImpl
+ package: Optional[AdoptxPackage]
+ installer: Optional[AdoptxPackage]
+ heap_size: AdoptxHeapSize
+ updated_at: datetime
+ scm_ref: Optional[str]
+ project: AdoptxProject
+ # we intentionally omit download_count
+
+
+class AdoptxVersion(MetaBase):
+ major: Optional[int]
+ minor: Optional[int]
+ security: Optional[int]
+ patch: Optional[int]
+ pre: Optional[str]
+ adopt_build_number: Optional[int]
+ semver: str
+ openjdk_version: str
+ build: Optional[int]
+ optional: Optional[str]
+
+
+class AdoptxRelease(MetaBase):
+ release_id: str = Field(alias="id")
+ release_link: str
+ release_name: str
+ timestamp: datetime
+ updated_at: datetime
+ binaries: list[AdoptxBinary]
+ release_type: str
+ vendor: AdoptxVendor
+ version_data: AdoptxVersion
+ source: Optional[AdoptxFile]
+ release_notes: Optional[AdoptxFile]
+ # we intentionally omit download_count
+
+
+class AdoptxReleases(MetaBase):
+ __root__: list[AdoptxRelease]
+
+ def __iter__(self) -> Generator[tuple[str, AdoptxRelease], None, None]:
+ yield from ((str(i), val) for i, val in enumerate(self.__root__))
+
+ def __getitem__(self, item: int) -> AdoptxRelease:
+ return self.__root__[item]
+
+ def append(self, rls: AdoptxRelease):
+ self.__root__.append(rls)
+
+
+class AzulProduct(StrEnum):
+ Zulu = "zulu"
+
+
+class AzulAvailabilityType(StrEnum):
+ SA = "SA"
+ CA = "CA"
+ NV = "NV"
+ _LA = "LA"
+
+
+class AzulJavaPackageType(StrEnum):
+ Jdk = "jdk"
+ Jre = "jre"
+
+
+class AzulReleaseType(StrEnum):
+ CPU = "CPU"
+ PSU = "PSU"
+ LU = "LU"
+
+
+class AzulOs(StrEnum):
+ Linux = "linux"
+ Macos = "macos"
+ Qnx = "qnx"
+ Windows = "windows"
+ Solaris = "solaris"
+
+
+class AzulLibCType(StrEnum):
+ Glibc = "glibc"
+ Uclibc = "uclibc"
+ Musl = "musl"
+
+
+class AzulCPUGen(StrEnum):
+ V5 = "v5"
+ V6kV6kz = "v6k_v6kz"
+ V6t2 = "v6t2"
+ V7 = "v7"
+ V8 = "v8"
+
+
+class AzulArch(StrEnum):
+ Arm = "arm"
+ X86 = "x86"
+ Mips = "mips"
+ Ppc = "ppc"
+ Sparcv9 = "sparcv9"
+ Sparc = "sparc"
+
+
+class AzulHwBitness(IntEnum):
+ X32 = 32
+ X64 = 64
+
+
+class AzulAbi(StrEnum):
+ HardFloat = "hard_float"
+ SoftFloat = "soft_float"
+ Spe = "spe"
+ Any = "any"
+
+
+class AzulArchiveType(StrEnum):
+ Deb = "deb"
+ Rpm = "rpm"
+ Dmg = "dmg"
+ Targz = "tar.gz"
+ Zip = "zip"
+ Cab = "cab"
+ Msi = "msi"
+
+
+class AzulReleaseStatus(StrEnum):
+ Eval = "eval"
+ Ea = "ea"
+ Ga = "ga"
+ Both = "both"
+
+
+class AzulSupportTerm(StrEnum):
+ Sts = "sts"
+ Mts = "mts"
+ Lts = "lts"
+
+
+class AzulCertifications(StrEnum):
+ Tck = "tck"
+ _Aqavit = "aqavit"
+ none = "none"
+
+
+class AzulSignatureType(StrEnum):
+ Openpgp = "openpgp"
+
+
+class AzulOsQueryParam(StrEnum):
+ Macos = "macos"
+ Windows = "windows"
+ Linux = "linux"
+ LinuxMusl = "linux-musl"
+ LinuxGlibc = "linux-glibc"
+ Qnx = "qnx"
+ Solaris = "solaris"
+
+
+class AzulArchQueryParam(StrEnum):
+ X86 = "x86"
+ X64 = "x64"
+ Amd64 = "amd64"
+ I686 = "i686"
+ Arm = "arm"
+ Aarch64 = "aarch64"
+ Aarch32 = "aarch32"
+ Aarch32sf = "aarch32sf"
+ Aarch32hf = "aarch32hf"
+ Ppc = "ppc"
+ Ppc64 = "ppc64"
+ Ppc64hf = "ppc64hf"
+ Ppc32 = "ppc32"
+ Ppc32spe = "ppc32spe"
+ Ppc32hf = "ppc32hf"
+ Sparc = "sparc"
+ Sparc32 = "sparc32"
+ Sparcv9 = "sparcv9"
+ Sparcv9_64 = "sparcv9-64"
+
+
+AZUL_API_BASE = "https://api.azul.com/metadata/v1"
+AZUL_API_PACKAGES = f"{AZUL_API_BASE}/zulu/packages/"
+AZUL_API_PACKAGE_DETAIL = f"{AZUL_API_BASE}/zulu/packages/{{package_uuid}}"
+
+
+class AzulApiPackagesQuery(APIQuery):
+ java_version: Optional[str] = None
+ os: Optional[AzulOsQueryParam] = None
+ arch: Optional[AzulArchQueryParam] = None
+ archive_type: Optional[AzulArchiveType] = None
+ java_package_type: Optional[AzulJavaPackageType] = None
+ javafx_bundled: Optional[bool] = None
+ crac_supported: Optional[bool] = None
+ support_term: Optional[AzulSupportTerm] = None
+ release_type: Optional[AzulReleaseType] = None
+ latest: Optional[bool] = None
+ distro_version: Optional[str] = None
+ java_package_features: list[str] = []
+ release_status: Optional[AzulReleaseStatus] = None
+ availability_types: list[AzulAvailabilityType] = []
+ certifications: list[AzulCertifications] = []
+ include_fields: list[str] = []
+ page: int = 0
+ page_size: int = 100
+
+
+def azulApiPackagesUrl(query: AzulApiPackagesQuery = AzulApiPackagesQuery()):
+ url = urlparse(AZUL_API_PACKAGES)
+ return urlunparse(url._replace(query=query.to_query()))
+
+
+def azulApiPackageDetailUrl(package_uuid: str):
+ return AZUL_API_PACKAGE_DETAIL.format(package_uuid=package_uuid)
+
+
+class ZuluSignatureDetail(MetaBase):
+ type: AzulSignatureType
+ url: str
+ details: dict[str, Any]
+ signature_index: int
+ signature: str
+
+
+class ZuluPackageDetail(MetaBase):
+ package_uuid: str
+ name: Optional[str]
+ md5_hash: Optional[str]
+ sha256_hash: Optional[str]
+ build_date: datetime
+ last_modified: datetime
+ download_url: str
+ product: AzulProduct
+ availability_type: AzulAvailabilityType
+ java_version: list[int]
+ openjdk_build_number: Optional[int]
+ java_package_type: AzulJavaPackageType
+ javafx_bundled: bool
+ release_type: AzulReleaseType
+ os: AzulOs
+ lib_c_type: Optional[AzulLibCType]
+ cpu_gen: Optional[list[AzulCPUGen]]
+ arch: AzulArch
+ hw_bitness: AzulHwBitness
+ abi: AzulAbi
+ archive_type: AzulArchiveType
+ release_status: AzulReleaseStatus
+ support_term: AzulSupportTerm
+ certifications: Optional[list[AzulCertifications]]
+ latest: Optional[bool]
+ size: int
+ distro_version: list[int]
+ signatures: list[ZuluSignatureDetail]
+
+
+class ZuluPackage(MetaBase):
+ package_uuid: str
+ name: Optional[str]
+ java_version: list[int]
+ openjdk_build_number: Optional[int]
+ latest: Optional[bool]
+ download_url: str
+ product: Optional[AzulProduct]
+ distro_version: list[int]
+ availability_type: Optional[AzulAvailabilityType]
+
+
+class ZuluPackageList(MetaBase):
+ __root__: list[ZuluPackage]
+
+ def __iter__(self) -> Generator[tuple[str, ZuluPackage], None, None]:
+ yield from ((str(i), val) for i, val in enumerate(self.__root__))
+
+ def __getitem__(self, item: int) -> ZuluPackage:
+ return self.__root__[item]
+
+ def append(self, pkg: ZuluPackage):
+ self.__root__.append(pkg)
+
+
+class ZuluPackagesDetail(MetaBase):
+ __root__: list[ZuluPackageDetail]
+
+ def __iter__(self) -> Generator[tuple[str, ZuluPackageDetail], None, None]:
+ yield from ((str(i), val) for i, val in enumerate(self.__root__))
+
+ def __getitem__(self, item: int) -> ZuluPackageDetail:
+ return self.__root__[item]
+
+ def append(self, pkg: ZuluPackageDetail):
+ self.__root__.append(pkg)
+
+
+MOJANG_OS_NAMES = ["mac-os", "linux", "windows"]
+
+MOJANG_OS_ARCHITECTURES = [
+ "x64",
+ "x86",
+ "arm64",
+ "arm32",
+]
diff --git a/meta/meta/model/liteloader.py b/meta/meta/model/liteloader.py
new file mode 100644
index 0000000000..64cdaadd7e
--- /dev/null
+++ b/meta/meta/model/liteloader.py
@@ -0,0 +1,112 @@
+from datetime import datetime
+from typing import Optional, List, Dict, Any
+
+from pydantic import Field
+
+from . import Library, MetaBase
+
+
+class LiteloaderDev(MetaBase):
+ fgVersion: Optional[str]
+ mappings: Optional[str]
+ mcp: Optional[str]
+
+
+class LiteloaderRepo(MetaBase):
+ """
+ "repo":{
+ "stream":"RELEASE",
+ "type":"m2",
+ "url":"http://dl.liteloader.com/repo/",
+ "classifier":""
+ },
+ """
+
+ stream: str
+ type: str
+ url: str
+ classifier: str
+
+
+class LiteloaderArtefact(MetaBase):
+ """
+ "53639d52340479ccf206a04f5e16606f":{
+ "tweakClass":"com.mumfrey.liteloader.launch.LiteLoaderTweaker",
+ "libraries":[
+ {
+ "name":"net.minecraft:launchwrapper:1.5"
+ },
+ {
+ "name":"net.sf.jopt-simple:jopt-simple:4.5"
+ },
+ {
+ "name":"org.ow2.asm:asm-all:4.1"
+ }
+ ],
+ "stream":"RELEASE",
+ "file":"liteloader-1.5.2_01.jar",
+ "version":"1.5.2_01",
+ "md5":"53639d52340479ccf206a04f5e16606f",
+ "timestamp":"1367366420"
+ },
+ """
+
+ tweakClass: str
+ libraries: List[Library]
+ stream: str
+ file: str
+ version: str
+ build: Optional[str]
+ md5: str
+ timestamp: str
+ srcJar: Optional[str]
+ mcpJar: Optional[str]
+ lastSuccessfulBuild: Optional[int] # only for snapshots
+
+
+class LiteloaderArtefacts(MetaBase):
+ liteloader: Dict[str, LiteloaderArtefact] = Field(alias="com.mumfrey:liteloader")
+ libraries: Optional[List[Library]]
+
+
+class LiteloaderEntry(MetaBase):
+ """
+ "1.10.2":{
+ "dev": { ... },
+ "repo":{ ... },
+ "artefacts":{
+ "com.mumfrey:liteloader":{ },
+ ...
+ },
+ "snapshots":{
+ ...
+ }
+ """
+
+ dev: Optional[LiteloaderDev]
+ repo: LiteloaderRepo
+ artefacts: Optional[LiteloaderArtefacts]
+ snapshots: Optional[LiteloaderArtefacts]
+
+
+class LiteloaderMeta(MetaBase):
+ """
+ "meta":{
+ "description":"LiteLoader is a lightweight mod bootstrap designed to provide basic loader functionality for mods which don't need to modify game mechanics.",
+ "authors":"Mumfrey",
+ "url":"http://dl.liteloader.com",
+ "updated":"2017-02-22T11:34:07+00:00",
+ "updatedTime":1487763247
+ },
+ """
+
+ description: str
+ authors: str
+ url: str
+ updated: datetime
+ updated_time: int = Field(alias="updatedTime")
+
+
+class LiteloaderIndex(MetaBase):
+ meta: LiteloaderMeta
+ versions: Dict[Any, LiteloaderEntry]
diff --git a/meta/meta/model/mojang.py b/meta/meta/model/mojang.py
new file mode 100644
index 0000000000..b3edfe21f9
--- /dev/null
+++ b/meta/meta/model/mojang.py
@@ -0,0 +1,344 @@
+from datetime import datetime
+from typing import Optional, List, Dict, Any, Iterator
+from .enum import StrEnum
+
+from pydantic import validator, Field
+
+from . import (
+ MetaBase,
+ MojangArtifactBase,
+ MojangAssets,
+ MojangArtifact,
+ MojangLibraryDownloads,
+ MojangLogging,
+ Library,
+ MetaVersion,
+ GradleSpecifier,
+)
+
+SUPPORTED_LAUNCHER_VERSION = 21
+SUPPORTED_COMPLIANCE_LEVEL = 1
+DEFAULT_JAVA_MAJOR = 8 # By default, we should recommend Java 8 if we don't know better
+DEFAULT_JAVA_NAME = (
+ "jre-legacy" # By default, we should recommend Java 8 if we don't know better
+)
+COMPATIBLE_JAVA_MAPPINGS = {16: [17]}
+SUPPORTED_FEATURES = ["is_quick_play_multiplayer", "is_quick_play_singleplayer"]
+
+"""
+Mojang index files look like this:
+{
+ "latest": {
+ "release": "1.11.2",
+ "snapshot": "17w06a"
+ },
+ "versions": [
+ ...
+ {
+ "id": "17w06a",
+ "releaseTime": "2017-02-08T13:16:29+00:00",
+ "time": "2017-02-08T13:17:20+00:00",
+ "type": "snapshot",
+ "url": "https://launchermeta.mojang.com/mc/game/7db0c61afa278d016cf1dae2fba0146edfbf2f8e/17w06a.json"
+ },
+ ...
+ ]
+}
+"""
+
+
+class MojangLatestVersion(MetaBase):
+ release: str
+ snapshot: str
+
+
+class MojangIndexEntry(MetaBase):
+ id: Optional[str]
+ release_time: Optional[datetime] = Field(alias="releaseTime")
+ time: Optional[datetime]
+ type: Optional[str]
+ url: Optional[str]
+ sha1: Optional[str]
+ compliance_level: Optional[int] = Field(alias="complianceLevel")
+
+
+class MojangIndex(MetaBase):
+ latest: MojangLatestVersion
+ versions: List[MojangIndexEntry]
+
+
+class MojangIndexWrap:
+ def __init__(self, index: MojangIndex):
+ self.index = index
+ self.latest = index.latest
+ self.versions = dict((x.id, x) for x in index.versions)
+
+
+class ExperimentEntry(MetaBase):
+ id: str
+ url: str
+ wiki: Optional[str]
+
+
+class ExperimentIndex(MetaBase):
+ experiments: List[ExperimentEntry]
+
+
+class ExperimentIndexWrap:
+ def __init__(self, index: ExperimentIndex):
+ self.index: ExperimentIndex = index
+ self.versions: Dict[str, ExperimentEntry] = dict(
+ (x.id, x) for x in index.experiments
+ )
+
+
+class OldSnapshotEntry(MetaBase):
+ id: str
+ url: str
+ wiki: Optional[str]
+ jar: str
+ sha1: str
+ size: int
+
+
+class OldSnapshotIndex(MetaBase):
+ old_snapshots: List[OldSnapshotEntry]
+
+
+class OldSnapshotIndexWrap:
+ def __init__(self, index: OldSnapshotIndex):
+ self.index: OldSnapshotIndex = index
+ self.versions: Dict[str, OldSnapshotEntry] = dict(
+ (x.id, x) for x in index.old_snapshots
+ )
+
+
+class LegacyOverrideEntry(MetaBase):
+ main_class: Optional[str] = Field(alias="mainClass")
+ applet_class: Optional[str] = Field(alias="appletClass")
+ release_time: Optional[datetime] = Field(alias="releaseTime")
+ additional_traits: Optional[List[str]] = Field(alias="+traits")
+ additional_jvm_args: Optional[List[str]] = Field(alias="+jvmArgs")
+
+ def apply_onto_meta_version(self, meta_version: MetaVersion, legacy: bool = True):
+ # simply hard override classes
+ meta_version.main_class = self.main_class
+ meta_version.applet_class = self.applet_class
+ # if we have an updated release time (more correct than Mojang), use it
+ if self.release_time:
+ meta_version.release_time = self.release_time
+
+ # add traits, if any
+ if self.additional_traits:
+ if not meta_version.additional_traits:
+ meta_version.additional_traits = []
+ meta_version.additional_traits += self.additional_traits
+
+ if self.additional_jvm_args:
+ if not meta_version.additional_jvm_args:
+ meta_version.additional_jvm_args = []
+ meta_version.additional_jvm_args += self.additional_jvm_args
+
+ if legacy:
+ # remove all libraries - they are not needed for legacy
+ meta_version.libraries = None
+
+
+class LegacyOverrideIndex(MetaBase):
+ versions: Dict[str, LegacyOverrideEntry]
+
+
+class LibraryPatch(MetaBase):
+ match: List[GradleSpecifier]
+ override: Optional[Library]
+ additionalLibraries: Optional[List[Library]]
+ patchAdditionalLibraries: bool = Field(False)
+
+ def applies(self, target: Library) -> bool:
+ return target.name in self.match
+
+
+class LibraryPatches(MetaBase):
+ __root__: List[LibraryPatch]
+
+ def __iter__(self) -> Iterator[LibraryPatch]:
+ return iter(self.__root__)
+
+ def __getitem__(self, item) -> LibraryPatch:
+ return self.__root__[item]
+
+
+class LegacyServices(MetaBase):
+ __root__: List[str]
+
+ def __iter__(self) -> Iterator[str]:
+ return iter(self.__root__)
+
+ def __getitem__(self, item) -> str:
+ return self.__root__[item]
+
+
+class MojangArguments(MetaBase):
+ game: Optional[List[Any]] # mixture of strings and objects
+ jvm: Optional[List[Any]]
+
+
+class MojangJavaComponent(StrEnum):
+ JreLegacy = "jre-legacy"
+ Alpha = "java-runtime-alpha"
+ Beta = "java-runtime-beta"
+ Gamma = "java-runtime-gamma"
+ GammaSnapshot = "java-runtime-gamma-snapshot"
+ Exe = "minecraft-java-exe"
+ Delta = "java-runtime-delta"
+ Epsilon = "java-runtime-epsilon"
+
+
+class JavaVersion(MetaBase):
+ component: MojangJavaComponent = MojangJavaComponent.JreLegacy
+ major_version: int = Field(8, alias="majorVersion")
+
+
+class MojangJavaIndexAvailability(MetaBase):
+ group: int
+ progress: int
+
+
+class MojangJavaIndexManifest(MetaBase):
+ sha1: str
+ size: int
+ url: str
+
+
+class MojangJavaIndexVersion(MetaBase):
+ name: str
+ released: datetime
+
+
+class MojangJavaRuntime(MetaBase):
+ availability: MojangJavaIndexAvailability
+ manifest: MojangJavaIndexManifest
+ version: MojangJavaIndexVersion
+
+
+class MojangJavaIndexEntry(MetaBase):
+ __root__: dict[MojangJavaComponent, list[MojangJavaRuntime]]
+
+ def __iter__(self) -> Iterator[MojangJavaComponent]:
+ return iter(self.__root__)
+
+ def __getitem__(self, item) -> list[MojangJavaRuntime]:
+ return self.__root__[item]
+
+
+class MojangJavaOsName(StrEnum):
+ Gamecore = "gamecore"
+ Linux = "linux"
+ Linuxi386 = "linux-i386"
+ MacOs = "mac-os"
+ MacOSArm64 = "mac-os-arm64"
+ WindowsArm64 = "windows-arm64"
+ WindowsX64 = "windows-x64"
+ WindowsX86 = "windows-x86"
+
+
+class JavaIndex(MetaBase):
+ __root__: dict[MojangJavaOsName, MojangJavaIndexEntry]
+
+ def __iter__(self) -> Iterator[MojangJavaOsName]:
+ return iter(self.__root__)
+
+ def __getitem__(self, item) -> MojangJavaIndexEntry:
+ return self.__root__[item]
+
+
+class MojangVersion(MetaBase):
+ @validator("minimum_launcher_version")
+ def validate_minimum_launcher_version(cls, v):
+ assert v <= SUPPORTED_LAUNCHER_VERSION
+ return v
+
+ @validator("compliance_level")
+ def validate_compliance_level(cls, v):
+ assert v <= SUPPORTED_COMPLIANCE_LEVEL
+ return v
+
+ id: str # TODO: optional?
+ arguments: Optional[MojangArguments]
+ asset_index: Optional[MojangAssets] = Field(alias="assetIndex")
+ assets: Optional[str]
+ downloads: Optional[Dict[str, MojangArtifactBase]] # TODO improve this?
+ libraries: Optional[List[Library]] # TODO: optional?
+ main_class: Optional[str] = Field(alias="mainClass")
+ applet_class: Optional[str] = Field(alias="appletClass")
+ processArguments: Optional[str]
+ minecraft_arguments: Optional[str] = Field(alias="minecraftArguments")
+ minimum_launcher_version: Optional[int] = Field(alias="minimumLauncherVersion")
+ release_time: Optional[datetime] = Field(alias="releaseTime")
+ time: Optional[datetime]
+ type: Optional[str]
+ inherits_from: Optional[str] = Field("inheritsFrom")
+ logging: Optional[Dict[str, MojangLogging]] # TODO improve this?
+ compliance_level: Optional[int] = Field(alias="complianceLevel")
+ javaVersion: Optional[JavaVersion]
+
+ def to_meta_version(self, name: str, uid: str, version: str) -> MetaVersion:
+ main_jar = None
+ addn_traits = None
+ new_type = self.type
+ compatible_java_majors = None
+ if self.id:
+ client_download = self.downloads["client"]
+ artifact = MojangArtifact(
+ url=client_download.url,
+ sha1=client_download.sha1,
+ size=client_download.size,
+ )
+ downloads = MojangLibraryDownloads(artifact=artifact)
+ main_jar = Library(
+ name=GradleSpecifier("com.mojang", "minecraft", self.id, "client"),
+ downloads=downloads,
+ )
+
+ if not self.compliance_level: # both == 0 and is None
+ pass
+ elif self.compliance_level == 1:
+ if not addn_traits:
+ addn_traits = []
+ addn_traits.append("XR:Initial")
+ else:
+ raise Exception(f"Unsupported compliance level {self.compliance_level}")
+
+ major = DEFAULT_JAVA_MAJOR
+ javaName = DEFAULT_JAVA_NAME
+ if (
+ self.javaVersion is not None
+ ): # some versions don't have this. TODO: maybe maintain manual overrides
+ major = self.javaVersion.major_version
+ javaName = self.javaVersion.component
+
+ compatible_java_majors = [major]
+ if (
+ major in COMPATIBLE_JAVA_MAPPINGS
+ ): # add more compatible Java versions, e.g. 16 and 17 both work for MC 1.17
+ compatible_java_majors += COMPATIBLE_JAVA_MAPPINGS[major]
+
+ if new_type == "pending": # experiments from upstream are type=pending
+ new_type = "experiment"
+
+ return MetaVersion(
+ name=name,
+ uid=uid,
+ version=version,
+ asset_index=self.asset_index,
+ libraries=self.libraries,
+ main_class=self.main_class,
+ minecraft_arguments=self.minecraft_arguments,
+ release_time=self.release_time,
+ type=new_type,
+ compatible_java_majors=compatible_java_majors,
+ compatible_java_name=javaName,
+ additional_traits=addn_traits,
+ main_jar=main_jar,
+ logging=(self.logging or {}).get("client"),
+ )
diff --git a/meta/meta/model/neoforge.py b/meta/meta/model/neoforge.py
new file mode 100644
index 0000000000..ccdb325a23
--- /dev/null
+++ b/meta/meta/model/neoforge.py
@@ -0,0 +1,241 @@
+from datetime import datetime
+from typing import Optional, List, Dict
+
+from pydantic import Field
+
+from . import MetaBase, GradleSpecifier, Library
+from .mojang import MojangVersion
+
+
+class NeoForgeFile(MetaBase):
+ artifact: str
+ classifier: str
+ extension: str
+
+ def filename(self, long_version):
+ return "%s-%s-%s.%s" % (
+ self.artifact,
+ long_version,
+ self.classifier,
+ self.extension,
+ )
+
+ def url(self, long_version):
+ return "https://maven.neoforged.net/releases/net/neoforged/%s/%s/%s" % (
+ self.artifact,
+ long_version,
+ self.filename(long_version),
+ )
+
+
+class NeoForgeEntry(MetaBase):
+ artifact: str
+ long_version: str = Field(alias="longversion")
+ version: str
+ latest: Optional[bool]
+ recommended: Optional[bool]
+ files: Optional[Dict[str, NeoForgeFile]]
+
+
+class NeoForgeMCVersionInfo(MetaBase):
+ latest: Optional[str]
+ recommended: Optional[str]
+ versions: List[str] = Field([])
+
+
+class DerivedNeoForgeIndex(MetaBase):
+ versions: Dict[str, NeoForgeEntry] = Field({})
+
+
+class FMLLib(
+ MetaBase
+): # old ugly stuff. Maybe merge this with Library or Library later
+ filename: str
+ checksum: str
+ ours: bool
+
+
+class NeoForgeInstallerProfileInstallSection(MetaBase):
+ """
+ "install": {
+ "profileName": "NeoForge",
+ "target":"NeoForge8.9.0.753",
+ "path":"net.minecraftNeoForge:minecraftNeoForge:8.9.0.753",
+ "version":"NeoForge 8.9.0.753",
+ "filePath":"minecraftNeoForge-universal-1.6.1-8.9.0.753.jar",
+ "welcome":"Welcome to the simple NeoForge installer.",
+ "minecraft":"1.6.1",
+ "logo":"/big_logo.png",
+ "mirrorList": "http://files.minecraftNeoForge.net/mirror-brand.list"
+ },
+ "install": {
+ "profileName": "NeoForge",
+ "target":"1.11-NeoForge1.11-13.19.0.2141",
+ "path":"net.minecraftNeoForge:NeoForge:1.11-13.19.0.2141",
+ "version":"NeoForge 1.11-13.19.0.2141",
+ "filePath":"NeoForge-1.11-13.19.0.2141-universal.jar",
+ "welcome":"Welcome to the simple NeoForge installer.",
+ "minecraft":"1.11",
+ "mirrorList" : "http://files.minecraftNeoForge.net/mirror-brand.list",
+ "logo":"/big_logo.png",
+ "modList":"none"
+ },
+ """
+
+ profile_name: str = Field(alias="profileName")
+ target: str
+ path: GradleSpecifier
+ version: str
+ file_path: str = Field(alias="filePath")
+ welcome: str
+ minecraft: str
+ logo: str
+ mirror_list: str = Field(alias="mirrorList")
+ mod_list: Optional[str] = Field(alias="modList")
+
+
+class NeoForgeLibrary(Library):
+ url: Optional[str]
+ server_req: Optional[bool] = Field(alias="serverreq")
+ client_req: Optional[bool] = Field(alias="clientreq")
+ checksums: Optional[List[str]]
+ comment: Optional[str]
+
+
+class NeoForgeVersionFile(MojangVersion):
+ libraries: Optional[List[NeoForgeLibrary]] # overrides Mojang libraries
+ inherits_from: Optional[str] = Field("inheritsFrom")
+ jar: Optional[str]
+
+
+class NeoForgeOptional(MetaBase):
+ """
+ "optionals": [
+ {
+ "name": "Mercurius",
+ "client": true,
+ "server": true,
+ "default": true,
+ "inject": true,
+ "desc": "A mod that collects statistics about Minecraft and your system.<br>Useful for NeoForge to understand how Minecraft/NeoForge are used.",
+ "url": "http://www.minecraftNeoForge.net/forum/index.php?topic=43278.0",
+ "artifact": "net.minecraftNeoForge:MercuriusUpdater:1.11.2",
+ "maven": "http://maven.minecraftNeoForge.net/"
+ }
+ ]
+ """
+
+ name: Optional[str]
+ client: Optional[bool]
+ server: Optional[bool]
+ default: Optional[bool]
+ inject: Optional[bool]
+ desc: Optional[str]
+ url: Optional[str]
+ artifact: Optional[GradleSpecifier]
+ maven: Optional[str]
+
+
+class DataSpec(MetaBase):
+ client: Optional[str]
+ server: Optional[str]
+
+
+class ProcessorSpec(MetaBase):
+ jar: Optional[str]
+ classpath: Optional[List[str]]
+ args: Optional[List[str]]
+ outputs: Optional[Dict[str, str]]
+ sides: Optional[List[str]]
+
+
+class NeoForgeInstallerProfileV2(MetaBase):
+ _comment: Optional[List[str]]
+ spec: Optional[int]
+ profile: Optional[str]
+ version: Optional[str]
+ icon: Optional[str]
+ json_data: Optional[str] = Field(alias="json")
+ path: Optional[GradleSpecifier]
+ logo: Optional[str]
+ minecraft: Optional[str]
+ welcome: Optional[str]
+ data: Optional[Dict[str, DataSpec]]
+ processors: Optional[List[ProcessorSpec]]
+ libraries: Optional[List[Library]]
+ mirror_list: Optional[str] = Field(alias="mirrorList")
+ server_jar_path: Optional[str] = Field(alias="serverJarPath")
+
+
+class InstallerInfo(MetaBase):
+ sha1hash: Optional[str]
+ sha256hash: Optional[str]
+ size: Optional[int]
+
+
+# A post-processed entry constructed from the reconstructed NeoForge version index
+class NeoForgeVersion:
+ def __init__(self, entry: NeoForgeEntry):
+ self.artifact = entry.artifact
+ self.rawVersion = entry.version
+ if self.artifact == "neoforge":
+ self.rawVersion = entry.long_version
+
+ self.installer_filename = None
+ self.installer_url = None
+ self.universal_filename = None
+ self.universal_url = None
+ self.changelog_url = None
+ self.long_version = entry.long_version
+
+ # this comment's whole purpose is to say this: cringe
+ for classifier, file in entry.files.items():
+ extension = file.extension
+ filename = file.filename(self.long_version)
+ url = file.url(self.long_version)
+ print(url)
+ print(self.long_version)
+ if (classifier == "installer") and (extension == "jar"):
+ self.installer_filename = filename
+ self.installer_url = url
+ if (classifier == "universal" or classifier == "client") and (
+ extension == "jar" or extension == "zip"
+ ):
+ self.universal_filename = filename
+ self.universal_url = url
+ if (classifier == "changelog") and (extension == "txt"):
+ self.changelog_url = url
+
+ def name(self):
+ return "neoforge %d" % self.build
+
+ def uses_installer(self):
+ return self.installer_url is not None
+
+ def filename(self):
+ if self.uses_installer():
+ return self.installer_filename
+ return self.universal_filename
+
+ def url(self):
+ if self.uses_installer():
+ return self.installer_url
+ return self.universal_url
+
+ def is_supported(self):
+ if self.url() is None:
+ return False
+
+ foo = self.rawVersion.split(".")
+ if len(foo) < 1:
+ return False
+
+ major_version = foo[0]
+ if not major_version.isnumeric():
+ return False
+
+ # majorVersion = int(majorVersionStr)
+ # if majorVersion >= 37:
+ # return False
+
+ return True
diff --git a/meta/meta/run/__init__.py b/meta/meta/run/__init__.py
new file mode 100644
index 0000000000..1bfe4f9ac8
--- /dev/null
+++ b/meta/meta/run/__init__.py
@@ -0,0 +1 @@
+"""Main scripts"""
diff --git a/meta/meta/run/generate_fabric.py b/meta/meta/run/generate_fabric.py
new file mode 100755
index 0000000000..7ca50dd6aa
--- /dev/null
+++ b/meta/meta/run/generate_fabric.py
@@ -0,0 +1,143 @@
+import json
+import os
+
+from meta.common import (
+ ensure_component_dir,
+ launcher_path,
+ upstream_path,
+ transform_maven_key,
+)
+from meta.common.fabric import (
+ JARS_DIR,
+ INSTALLER_INFO_DIR,
+ META_DIR,
+ INTERMEDIARY_COMPONENT,
+ LOADER_COMPONENT,
+)
+from meta.model import MetaVersion, Dependency, Library, MetaPackage, GradleSpecifier
+from meta.model.fabric import FabricJarInfo, FabricInstallerDataV1, FabricMainClasses
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+ensure_component_dir(LOADER_COMPONENT)
+ensure_component_dir(INTERMEDIARY_COMPONENT)
+
+
+def load_jar_info(artifact_key) -> FabricJarInfo:
+ return FabricJarInfo.parse_file(
+ os.path.join(UPSTREAM_DIR, JARS_DIR, f"{artifact_key}.json")
+ )
+
+
+def load_installer_info(version) -> FabricInstallerDataV1:
+ return FabricInstallerDataV1.parse_file(
+ os.path.join(UPSTREAM_DIR, INSTALLER_INFO_DIR, f"{version}.json")
+ )
+
+
+def process_loader_version(entry) -> MetaVersion:
+ jar_info = load_jar_info(transform_maven_key(entry["maven"]))
+ installer_info = load_installer_info(entry["version"])
+
+ v = MetaVersion(
+ name="Fabric Loader", uid="net.fabricmc.fabric-loader", version=entry["version"]
+ )
+ v.release_time = jar_info.release_time
+ v.requires = [Dependency(uid="net.fabricmc.intermediary")]
+ v.order = 10
+ v.type = "release"
+ if isinstance(installer_info.main_class, FabricMainClasses):
+ v.main_class = installer_info.main_class.client
+ else:
+ v.main_class = installer_info.main_class
+ v.libraries = []
+ v.libraries.extend(installer_info.libraries.common)
+ v.libraries.extend(installer_info.libraries.client)
+ loader_lib = Library(
+ name=GradleSpecifier.from_string(entry["maven"]),
+ url="https://maven.fabricmc.net",
+ )
+ v.libraries.append(loader_lib)
+ return v
+
+
+def process_intermediary_version(entry) -> MetaVersion:
+ jar_info = load_jar_info(transform_maven_key(entry["maven"]))
+
+ v = MetaVersion(
+ name="Intermediary Mappings",
+ uid="net.fabricmc.intermediary",
+ version=entry["version"],
+ )
+ v.release_time = jar_info.release_time
+ v.requires = [Dependency(uid="net.minecraft", equals=entry["version"])]
+ v.order = 11
+ v.type = "release"
+ v.libraries = []
+ v.volatile = True
+ intermediary_lib = Library(
+ name=GradleSpecifier.from_string(entry["maven"]),
+ url="https://maven.fabricmc.net",
+ )
+ v.libraries.append(intermediary_lib)
+ return v
+
+
+def main():
+ recommended_loader_versions = []
+ recommended_intermediary_versions = []
+
+ with open(
+ os.path.join(UPSTREAM_DIR, META_DIR, "loader.json"), "r", encoding="utf-8"
+ ) as f:
+ loader_version_index = json.load(f)
+ for entry in loader_version_index:
+ version = entry["version"]
+ print(f"Processing loader {version}")
+
+ v = process_loader_version(entry)
+
+ # Fabric Meta has a separate "stable" field, let's use that
+ if not recommended_loader_versions and entry["stable"]:
+ recommended_loader_versions.append(version)
+
+ v.write(os.path.join(LAUNCHER_DIR, LOADER_COMPONENT, f"{v.version}.json"))
+
+ with open(
+ os.path.join(UPSTREAM_DIR, META_DIR, "intermediary.json"), "r", encoding="utf-8"
+ ) as f:
+ intermediary_version_index = json.load(f)
+ for entry in intermediary_version_index:
+ version = entry["version"]
+ print(f"Processing intermediary {version}")
+
+ v = process_intermediary_version(entry)
+
+ recommended_intermediary_versions.append(
+ version
+ ) # all intermediaries are recommended
+
+ v.write(
+ os.path.join(LAUNCHER_DIR, INTERMEDIARY_COMPONENT, f"{v.version}.json")
+ )
+
+ package = MetaPackage(uid=LOADER_COMPONENT, name="Fabric Loader")
+ package.recommended = recommended_loader_versions
+ package.description = (
+ "Fabric Loader is a tool to load Fabric-compatible mods in game environments."
+ )
+ package.project_url = "https://fabricmc.net"
+ package.authors = ["Fabric Developers"]
+ package.write(os.path.join(LAUNCHER_DIR, LOADER_COMPONENT, "package.json"))
+
+ package = MetaPackage(uid=INTERMEDIARY_COMPONENT, name="Intermediary Mappings")
+ package.recommended = recommended_intermediary_versions
+ package.description = "Intermediary mappings allow using Fabric Loader with mods for Minecraft in a more compatible manner."
+ package.project_url = "https://fabricmc.net"
+ package.authors = ["Fabric Developers"]
+ package.write(os.path.join(LAUNCHER_DIR, INTERMEDIARY_COMPONENT, "package.json"))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/generate_forge.py b/meta/meta/run/generate_forge.py
new file mode 100755
index 0000000000..a01f503ebe
--- /dev/null
+++ b/meta/meta/run/generate_forge.py
@@ -0,0 +1,467 @@
+import os
+import re
+from packaging import version as pversion
+from operator import attrgetter
+from typing import Collection
+
+from meta.common import ensure_component_dir, launcher_path, upstream_path, eprint
+from meta.common.forge import (
+ FORGE_COMPONENT,
+ INSTALLER_MANIFEST_DIR,
+ VERSION_MANIFEST_DIR,
+ DERIVED_INDEX_FILE,
+ LEGACYINFO_FILE,
+ INSTALLER_INFO_DIR,
+ BAD_VERSIONS,
+ FORGEWRAPPER_LIBRARY,
+)
+from meta.common.mojang import MINECRAFT_COMPONENT
+from meta.model import (
+ MetaVersion,
+ Dependency,
+ Library,
+ GradleSpecifier,
+ MojangLibraryDownloads,
+ MojangArtifact,
+ MetaPackage,
+)
+from meta.model.forge import (
+ ForgeVersion,
+ ForgeInstallerProfile,
+ ForgeLegacyInfo,
+ fml_libs_for_version,
+ ForgeInstallerProfileV2,
+ InstallerInfo,
+ DerivedForgeIndex,
+ ForgeLegacyInfoList,
+)
+from meta.model.mojang import MojangVersion
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+ensure_component_dir(FORGE_COMPONENT)
+
+
+# Construct a set of libraries out of a Minecraft version file, for filtering.
+mc_version_cache = {}
+
+
+def load_mc_version_filter(version: str):
+ if version in mc_version_cache:
+ return mc_version_cache[version]
+ v = MetaVersion.parse_file(
+ os.path.join(LAUNCHER_DIR, MINECRAFT_COMPONENT, f"{version}.json")
+ )
+ libs = set(map(attrgetter("name"), v.libraries))
+ mc_version_cache[version] = libs
+ return libs
+
+
+"""
+Match a library coordinate to a set of library coordinates.
+ * Block those that pass completely.
+ * For others, block those with lower versions than in the set.
+"""
+
+
+def should_ignore_artifact(libs: Collection[GradleSpecifier], match: GradleSpecifier):
+ for ver in libs:
+ if (
+ ver.group == match.group
+ and ver.artifact == match.artifact
+ and ver.classifier == match.classifier
+ ):
+ if ver.version == match.version:
+ # Everything is matched perfectly - this one will be ignored
+ return True
+ elif pversion.parse(ver.version) > pversion.parse(match.version):
+ return True
+ else:
+ # Otherwise it did not match - new version is higher and this is an upgrade
+ return False
+ # No match found in the set - we need to keep this
+ return False
+
+
+def version_from_profile(
+ profile: ForgeInstallerProfile, version: ForgeVersion
+) -> MetaVersion:
+ v = MetaVersion(name="Forge", version=version.rawVersion, uid=FORGE_COMPONENT)
+ mc_version = profile.install.minecraft
+ v.requires = [Dependency(uid=MINECRAFT_COMPONENT, equals=mc_version)]
+ v.main_class = profile.version_info.main_class
+ v.release_time = profile.version_info.time
+
+ args = profile.version_info.minecraft_arguments
+ tweakers = []
+ expression = re.compile(r"--tweakClass ([a-zA-Z0-9.]+)")
+ match = expression.search(args)
+ while match is not None:
+ tweakers.append(match.group(1))
+ args = args[: match.start()] + args[match.end() :]
+ match = expression.search(args)
+ if len(tweakers) > 0:
+ args = args.strip()
+ v.additional_tweakers = tweakers
+ # v.minecraftArguments = args
+
+ v.libraries = []
+ mc_filter = load_mc_version_filter(mc_version)
+ for forge_lib in profile.version_info.libraries:
+ if (
+ forge_lib.name.is_lwjgl()
+ or forge_lib.name.is_log4j()
+ or should_ignore_artifact(mc_filter, forge_lib.name)
+ ):
+ continue
+
+ overridden_name = forge_lib.name
+ if overridden_name.group == "net.minecraftforge":
+ if overridden_name.artifact == "minecraftforge":
+ overridden_name.artifact = "forge"
+ overridden_name.version = "%s-%s" % (
+ mc_version,
+ overridden_name.version,
+ )
+
+ overridden_name.classifier = "universal"
+ elif overridden_name.artifact == "forge":
+ overridden_name.classifier = "universal"
+
+ overridden_lib = Library(name=overridden_name)
+ if forge_lib.url == "http://maven.minecraftforge.net/":
+ overridden_lib.url = "https://maven.minecraftforge.net/"
+ else:
+ overridden_lib.url = forge_lib.url
+ # if forge_lib.checksums and len(forge_lib.checksums) == 2:
+ # overridden_lib.mmcHint = "forge-pack-xz"
+ v.libraries.append(overridden_lib)
+
+ v.order = 5
+ return v
+
+
+def version_from_modernized_installer(
+ installer: MojangVersion, version: ForgeVersion
+) -> MetaVersion:
+ v = MetaVersion(name="Forge", version=version.rawVersion, uid=FORGE_COMPONENT)
+ mc_version = version.mc_version
+ v.requires = [Dependency(uid=MINECRAFT_COMPONENT, equals=mc_version)]
+ v.main_class = installer.main_class
+ v.release_time = installer.release_time
+
+ args = installer.minecraft_arguments
+ tweakers = []
+ expression = re.compile("--tweakClass ([a-zA-Z0-9.]+)")
+ match = expression.search(args)
+ while match is not None:
+ tweakers.append(match.group(1))
+ args = args[: match.start()] + args[match.end() :]
+ match = expression.search(args)
+ if len(tweakers) > 0:
+ args = args.strip()
+ v.additional_tweakers = tweakers
+ # v.minecraftArguments = args
+
+ v.libraries = []
+
+ mc_filter = load_mc_version_filter(mc_version)
+ for forge_lib in installer.libraries:
+ if (
+ forge_lib.name.is_lwjgl()
+ or forge_lib.name.is_log4j()
+ or should_ignore_artifact(mc_filter, forge_lib.name)
+ ):
+ continue
+
+ if forge_lib.name.group == "net.minecraftforge":
+ if forge_lib.name.artifact == "forge":
+ overridden_name = forge_lib.name
+ overridden_name.classifier = "universal"
+ forge_lib.downloads.artifact.path = overridden_name.path()
+ forge_lib.downloads.artifact.url = (
+ "https://maven.minecraftforge.net/%s" % overridden_name.path()
+ )
+ forge_lib.name = overridden_name
+
+ elif forge_lib.name.artifact == "minecraftforge":
+ overridden_name = forge_lib.name
+ overridden_name.artifact = "forge"
+ overridden_name.classifier = "universal"
+ overridden_name.version = "%s-%s" % (
+ mc_version,
+ overridden_name.version,
+ )
+ forge_lib.downloads.artifact.path = overridden_name.path()
+ forge_lib.downloads.artifact.url = (
+ "https://maven.minecraftforge.net/%s" % overridden_name.path()
+ )
+ forge_lib.name = overridden_name
+
+ v.libraries.append(forge_lib)
+
+ v.order = 5
+ return v
+
+
+def version_from_legacy(info: ForgeLegacyInfo, version: ForgeVersion) -> MetaVersion:
+ v = MetaVersion(name="Forge", version=version.rawVersion, uid=FORGE_COMPONENT)
+ mc_version = version.mc_version_sane
+ v.requires = [Dependency(uid=MINECRAFT_COMPONENT, equals=mc_version)]
+ v.release_time = info.release_time
+ v.order = 5
+ if fml_libs_for_version(
+ mc_version
+ ): # WHY, WHY DID I WASTE MY TIME REWRITING FMLLIBSMAPPING
+ v.additional_traits = ["legacyFML"]
+
+ classifier = "client"
+ if "universal" in version.url():
+ classifier = "universal"
+
+ main_mod = Library(
+ name=GradleSpecifier(
+ "net.minecraftforge", "forge", version.long_version, classifier
+ )
+ )
+ main_mod.downloads = MojangLibraryDownloads()
+ main_mod.downloads.artifact = MojangArtifact(
+ url=version.url(), sha1=info.sha1, size=info.size
+ )
+ main_mod.downloads.artifact.path = None
+ v.jar_mods = [main_mod]
+ return v
+
+
+def version_from_build_system_installer(
+ installer: MojangVersion, profile: ForgeInstallerProfileV2, version: ForgeVersion
+) -> MetaVersion:
+ v = MetaVersion(name="Forge", version=version.rawVersion, uid=FORGE_COMPONENT)
+ v.requires = [Dependency(uid=MINECRAFT_COMPONENT, equals=version.mc_version_sane)]
+ v.main_class = "io.github.zekerzhayard.forgewrapper.installer.Main"
+
+ # FIXME: Add the size and hash here
+ v.maven_files = []
+
+ # load the locally cached installer file info and use it to add the installer entry in the json
+ info = InstallerInfo.parse_file(
+ os.path.join(UPSTREAM_DIR, INSTALLER_INFO_DIR, f"{version.long_version}.json")
+ )
+ installer_lib = Library(
+ name=GradleSpecifier(
+ "net.minecraftforge", "forge", version.long_version, "installer"
+ )
+ )
+ installer_lib.downloads = MojangLibraryDownloads()
+ installer_lib.downloads.artifact = MojangArtifact(
+ url="https://maven.minecraftforge.net/%s" % (installer_lib.name.path()),
+ sha1=info.sha1hash,
+ size=info.size,
+ )
+ v.maven_files.append(installer_lib)
+
+ for forge_lib in profile.libraries:
+ if forge_lib.name.is_log4j():
+ continue
+
+ if (
+ forge_lib.name.group == "net.minecraftforge"
+ and forge_lib.name.artifact == "forge"
+ and forge_lib.name.classifier == "universal"
+ ):
+ forge_lib.downloads.artifact.url = (
+ "https://maven.minecraftforge.net/%s" % forge_lib.name.path()
+ )
+ v.maven_files.append(forge_lib)
+
+ v.libraries = []
+
+ v.libraries.append(FORGEWRAPPER_LIBRARY)
+
+ for forge_lib in installer.libraries:
+ if forge_lib.name.is_log4j():
+ continue
+
+ if forge_lib.name.group == "net.minecraftforge":
+ if forge_lib.name.artifact == "forge" and not forge_lib.name.classifier:
+ forge_lib.name.classifier = "launcher"
+ forge_lib.downloads.artifact.path = forge_lib.name.path()
+ forge_lib.downloads.artifact.url = (
+ "https://maven.minecraftforge.net/%s" % forge_lib.name.path()
+ )
+ forge_lib.name = forge_lib.name
+ # net.minecraftforge.forge:client doesn't exist??? (49.0.x)
+ if not len(forge_lib.downloads.artifact.url):
+ continue
+ v.libraries.append(forge_lib)
+
+ v.release_time = installer.release_time
+ v.order = 5
+ mc_args = (
+ "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} "
+ "--assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} "
+ "--accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}"
+ )
+ for arg in installer.arguments.game:
+ mc_args += f" {arg}"
+ if "--fml.forgeGroup" not in installer.arguments.game:
+ mc_args += f" --fml.forgeGroup net.minecraftforge"
+ if "--fml.forgeVersion" not in installer.arguments.game:
+ mc_args += f" --fml.forgeVersion {version.rawVersion}"
+ if "--fml.mcVersion" not in installer.arguments.game:
+ mc_args += f" --fml.mcVersion {version.mc_version}"
+ v.minecraft_arguments = mc_args
+ return v
+
+
+def main():
+ # load the locally cached version list
+ remote_versions = DerivedForgeIndex.parse_file(
+ os.path.join(UPSTREAM_DIR, DERIVED_INDEX_FILE)
+ )
+ recommended_versions = []
+
+ legacy_info_list = ForgeLegacyInfoList.parse_file(
+ os.path.join(UPSTREAM_DIR, LEGACYINFO_FILE)
+ )
+ legacy_versions = [
+ "1.1",
+ "1.2.3",
+ "1.2.4",
+ "1.2.5",
+ "1.3.2",
+ "1.4.1",
+ "1.4.2",
+ "1.4.3",
+ "1.4.4",
+ "1.4.5",
+ "1.4.6",
+ "1.4.7",
+ "1.5",
+ "1.5.1",
+ "1.5.2",
+ "1.6.1",
+ "1.6.2",
+ "1.6.3",
+ "1.6.4",
+ "1.7.10",
+ "1.7.10-pre4",
+ "1.7.2",
+ "1.8",
+ "1.8.8",
+ "1.8.9",
+ "1.9",
+ "1.9.4",
+ "1.10",
+ "1.10.2",
+ "1.11",
+ "1.11.2",
+ "1.12",
+ "1.12.1",
+ "1.12.2",
+ ]
+
+ for key, entry in remote_versions.versions.items():
+ if entry.mc_version is None:
+ eprint("Skipping %s with invalid MC version" % key)
+ continue
+
+ version = ForgeVersion(entry)
+
+ if version.long_version in BAD_VERSIONS:
+ # Version 1.12.2-14.23.5.2851 is ultra cringe, I can't imagine why you would even spend one second on
+ # actually adding support for this version.
+ # It is cringe, because it's installer info is broken af
+ eprint(f"Skipping bad version {version.long_version}")
+ continue
+
+ if version.url() is None:
+ eprint("Skipping %s with no valid files" % key)
+ continue
+ eprint("Processing Forge %s" % version.rawVersion)
+ version_elements = version.rawVersion.split(".")
+ if len(version_elements) < 1:
+ eprint("Skipping version %s with not enough version elements" % key)
+ continue
+
+ major_version_str = version_elements[0]
+ if not major_version_str.isnumeric():
+ eprint(
+ "Skipping version %s with non-numeric major version %s"
+ % (key, major_version_str)
+ )
+ continue
+
+ if entry.recommended:
+ recommended_versions.append(version.rawVersion)
+
+ # If we do not have the corresponding Minecraft version, we ignore it
+ if not os.path.isfile(
+ os.path.join(
+ LAUNCHER_DIR, MINECRAFT_COMPONENT, f"{version.mc_version_sane}.json"
+ )
+ ):
+ eprint(
+ "Skipping %s with no corresponding Minecraft version %s"
+ % (key, version.mc_version_sane)
+ )
+ continue
+
+ # Path for new-style build system based installers
+ installer_version_filepath = os.path.join(
+ UPSTREAM_DIR, VERSION_MANIFEST_DIR, f"{version.long_version}.json"
+ )
+ profile_filepath = os.path.join(
+ UPSTREAM_DIR, INSTALLER_MANIFEST_DIR, f"{version.long_version}.json"
+ )
+
+ eprint(installer_version_filepath)
+ if os.path.isfile(installer_version_filepath):
+ installer = MojangVersion.parse_file(installer_version_filepath)
+ if entry.mc_version in legacy_versions:
+ v = version_from_modernized_installer(installer, version)
+ else:
+ profile = ForgeInstallerProfileV2.parse_file(profile_filepath)
+ v = version_from_build_system_installer(installer, profile, version)
+ else:
+ if version.uses_installer():
+ # If we do not have the Forge json, we ignore this version
+ if not os.path.isfile(profile_filepath):
+ eprint("Skipping %s with missing profile json" % key)
+ continue
+ profile = ForgeInstallerProfile.parse_file(profile_filepath)
+ v = version_from_profile(profile, version)
+ else:
+ # Generate json for legacy here
+ if version.mc_version_sane == "1.6.1":
+ continue
+ build = version.build
+ if (
+ str(build).encode("utf-8").decode("utf8")
+ not in legacy_info_list.number
+ ):
+ eprint(
+ "Legacy build %d is missing in legacy info. Ignoring." % build
+ )
+ continue
+
+ v = version_from_legacy(legacy_info_list.number[str(build)], version)
+
+ v.write(os.path.join(LAUNCHER_DIR, FORGE_COMPONENT, f"{v.version}.json"))
+
+ recommended_versions.sort()
+
+ print("Recommended versions:", recommended_versions)
+
+ package = MetaPackage(
+ uid=FORGE_COMPONENT,
+ name="Forge",
+ project_url="https://www.minecraftforge.net/forum/",
+ )
+ package.recommended = recommended_versions
+ package.write(os.path.join(LAUNCHER_DIR, FORGE_COMPONENT, "package.json"))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/generate_java.py b/meta/meta/run/generate_java.py
new file mode 100644
index 0000000000..9f23e3a4d3
--- /dev/null
+++ b/meta/meta/run/generate_java.py
@@ -0,0 +1,537 @@
+import copy
+import datetime
+import os
+from typing import Optional
+from functools import reduce
+
+from meta.common import ensure_component_dir, launcher_path, upstream_path
+
+from meta.common.java import (
+ JAVA_MINECRAFT_COMPONENT,
+ JAVA_ADOPTIUM_COMPONENT,
+ JAVA_OPENJ9_COMPONENT,
+ JAVA_AZUL_COMPONENT,
+ ADOPTIUM_DIR,
+ ADOPTIUM_VERSIONS_DIR,
+ OPENJ9_DIR,
+ OPENJ9_VERSIONS_DIR,
+ AZUL_DIR,
+ AZUL_VERSIONS_DIR,
+)
+from meta.model import MetaPackage
+from meta.model.java import (
+ JavaRuntimeOS,
+ JavaRuntimeVersion,
+ JavaRuntimeMeta,
+ JavaVersionMeta,
+ JavaPackageType,
+ JavaChecksumMeta,
+ JavaChecksumType,
+ JavaRuntimeDownloadType,
+ AdoptxAvailableReleases,
+ AdoptxReleases,
+ AdoptxRelease,
+ AdoptxImageType,
+ AdoptxBinary,
+ ZuluPackageList,
+ ZuluPackageDetail,
+ AzulJavaPackageType,
+ AzulArch,
+)
+
+from meta.common.mojang import (
+ JAVA_MANIFEST_FILE,
+)
+
+from meta.model.mojang import (
+ JavaIndex,
+ MojangJavaComponent,
+ MojangJavaOsName,
+ MojangJavaRuntime,
+)
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+
+MOJANG_OS_ARCHITECTURES = [
+ "x64",
+ "x86",
+ "arm64",
+ "arm32",
+ "riscv64",
+]
+
+MOJANG_OS_ARCHITECTURE_TRANSLATIONS = {
+ 64: "x64",
+ 32: "x86",
+ "x32": "x86",
+ "i386": "x86",
+ "aarch64": "arm64",
+ "x86_64": "x64",
+ "arm": "arm32",
+ "riscv64": "riscv64",
+}
+
+
+def translate_arch(arch: str | int):
+ if isinstance(arch, str):
+ arch = arch.lower()
+ if arch in MOJANG_OS_ARCHITECTURES:
+ return arch
+ elif arch in MOJANG_OS_ARCHITECTURE_TRANSLATIONS:
+ return MOJANG_OS_ARCHITECTURE_TRANSLATIONS[arch]
+ else:
+ return None
+
+
+MOJANG_OS_NAMES = [
+ "mac-os",
+ "linux",
+ "windows",
+]
+
+MOJANG_OS_TRANSLATIONS = {
+ "osx": "mac-os",
+ "mac": "mac-os",
+ "macos": "mac-os",
+}
+
+
+def translate_os(os: str):
+ os = os.lower()
+ if os in MOJANG_OS_NAMES:
+ return os
+ elif os in MOJANG_OS_TRANSLATIONS:
+ return MOJANG_OS_TRANSLATIONS[os]
+ else:
+ return None
+
+
+def mojang_os_to_java_os(mojang_os: MojangJavaOsName) -> JavaRuntimeOS:
+ match mojang_os:
+ case MojangJavaOsName.Linux:
+ return JavaRuntimeOS.LinuxX64
+ case MojangJavaOsName.Linuxi386:
+ return JavaRuntimeOS.LinuxX86
+ case MojangJavaOsName.MacOs:
+ return JavaRuntimeOS.MacOsX64
+ case MojangJavaOsName.MacOSArm64:
+ return JavaRuntimeOS.MacOsArm64
+ case MojangJavaOsName.WindowsArm64:
+ return JavaRuntimeOS.WindowsArm64
+ case MojangJavaOsName.WindowsX64:
+ return JavaRuntimeOS.WindowsX64
+ case MojangJavaOsName.WindowsX86:
+ return JavaRuntimeOS.WindowsX86
+ case _:
+ return JavaRuntimeOS.Unknown
+
+
+def mojang_component_to_major(mojang_component: MojangJavaComponent) -> int:
+ match mojang_component:
+ case MojangJavaComponent.JreLegacy:
+ return 8
+ case MojangJavaComponent.Alpha:
+ return 17
+ case MojangJavaComponent.Beta:
+ return 17
+ case MojangJavaComponent.Gamma:
+ return 17
+ case MojangJavaComponent.GammaSnapshot:
+ return 17
+ case MojangJavaComponent.Exe:
+ return 0
+ case MojangJavaComponent.Delta:
+ return 21
+ case MojangJavaComponent.Epsilon:
+ return 25
+ case _:
+ return 0
+
+
+def mojang_runtime_to_java_runtime(
+ mojang_runtime: MojangJavaRuntime,
+ mojang_component: MojangJavaComponent,
+ runtime_os: JavaRuntimeOS,
+) -> JavaRuntimeMeta:
+ major, _, trail = mojang_runtime.version.name.partition("u")
+ security, _, buildstr = trail.partition("-")
+
+ if buildstr == "":
+ buildstr = None
+
+ if major and security:
+ version_parts = [int(major), 0, int(security)]
+ else:
+ version_parts = [int(part) for part in mojang_runtime.version.name.split(".")]
+
+ while len(version_parts) < 3:
+ version_parts.append(0)
+
+ build = None
+ if len(version_parts) >= 4:
+ build = version_parts[3]
+
+ version = JavaVersionMeta(
+ major=version_parts[0],
+ minor=version_parts[1],
+ security=version_parts[2],
+ build=build,
+ buildstr=buildstr,
+ name=mojang_runtime.version.name,
+ )
+ return JavaRuntimeMeta(
+ name=mojang_component,
+ vendor="mojang",
+ url=mojang_runtime.manifest.url,
+ releaseTime=mojang_runtime.version.released,
+ checksum=JavaChecksumMeta(
+ type=JavaChecksumType.Sha1, hash=mojang_runtime.manifest.sha1
+ ),
+ downloadType=JavaRuntimeDownloadType.Manifest,
+ packageType=JavaPackageType.Jre,
+ version=version,
+ runtime_os=runtime_os,
+ )
+
+
+def adoptx_release_binary_to_java_runtime(
+ rls: AdoptxRelease,
+ binary: AdoptxBinary,
+ runtime_os: JavaRuntimeOS,
+) -> JavaRuntimeMeta:
+ assert binary.package is not None
+
+ checksum = None
+ if binary.package.checksum is not None:
+ checksum = JavaChecksumMeta(
+ type=JavaChecksumType.Sha256, hash=binary.package.checksum
+ )
+
+ pkg_type = JavaPackageType(str(binary.image_type))
+
+ version = JavaVersionMeta(
+ major=rls.version_data.major if rls.version_data.major is not None else 0,
+ minor=rls.version_data.minor if rls.version_data.minor is not None else 0,
+ security=(
+ rls.version_data.security if rls.version_data.security is not None else 0
+ ),
+ build=rls.version_data.build,
+ )
+
+ if rls.vendor == "eclipse":
+ rls_distribution = "temurin"
+ elif rls.vendor == "ibm":
+ rls_distribution = "semeru-open"
+
+ rls_name = f"{rls.vendor}_{rls_distribution}_{binary.image_type}{version}"
+ return JavaRuntimeMeta(
+ name=rls_name,
+ vendor=rls.vendor,
+ url=binary.package.link,
+ releaseTime=rls.timestamp,
+ checksum=checksum,
+ downloadType=JavaRuntimeDownloadType.Archive,
+ packageType=pkg_type,
+ version=version,
+ runtime_os=runtime_os,
+ )
+
+
+def azul_package_to_java_runtime(
+ pkg: ZuluPackageDetail, runtime_os: JavaRuntimeOS
+) -> JavaRuntimeMeta:
+ version_parts = copy.copy(pkg.java_version)
+
+ build = None
+ while len(version_parts) < 3:
+ version_parts.append(0)
+
+ if len(version_parts) >= 4:
+ build = version_parts[3]
+
+ version = JavaVersionMeta(
+ major=version_parts[0],
+ minor=version_parts[1],
+ security=version_parts[2],
+ build=build,
+ )
+
+ pkg_type = JavaPackageType(str(pkg.java_package_type))
+
+ rls_name = f"azul_{pkg.product}_{pkg.java_package_type}{version}"
+
+ checksum = None
+ if pkg.sha256_hash is not None:
+ checksum = JavaChecksumMeta(type=JavaChecksumType.Sha256, hash=pkg.sha256_hash)
+
+ return JavaRuntimeMeta(
+ name=rls_name,
+ vendor="azul",
+ url=pkg.download_url,
+ releaseTime=pkg.build_date,
+ checksum=checksum,
+ downloadType=JavaRuntimeDownloadType.Archive,
+ packageType=pkg_type,
+ version=version,
+ runtime_os=runtime_os,
+ )
+
+
+def writeJavas(javas: dict[int, list[JavaRuntimeMeta]], uid: str):
+ def oldest_timestamp(a: datetime.datetime | None, b: datetime.datetime):
+ if a is None or a > b:
+ return b
+ return a
+
+ ensure_component_dir(uid)
+
+ # small hack to sort the versions after major
+ javas = dict(sorted(javas.items(), key=lambda item: item[0]))
+ timestamps: dict[int, datetime.datetime | None] = {}
+ prevDate: datetime.datetime | None = None
+ for major, runtimes in javas.items():
+ releaseTime = reduce(
+ oldest_timestamp,
+ (runtime.release_time for runtime in runtimes),
+ None,
+ )
+ if prevDate is not None and releaseTime < prevDate:
+ releaseTime = prevDate + datetime.timedelta(seconds=1)
+ prevDate = releaseTime
+ timestamps[major] = releaseTime
+
+ for major, runtimes in javas.items():
+ version_file = os.path.join(LAUNCHER_DIR, uid, f"java{major}.json")
+ java_version = JavaRuntimeVersion(
+ name=f"Java {major}",
+ uid=uid,
+ version=f"java{major}",
+ releaseTime=timestamps.get(major),
+ runtimes=runtimes,
+ )
+ java_version.write(version_file)
+
+ package = MetaPackage(uid=uid, name="Java Runtimes", recommended=[])
+ package.write(os.path.join(LAUNCHER_DIR, uid, "package.json"))
+
+
+def main():
+ javas: dict[int, list[JavaRuntimeMeta]] = {}
+ extra_mojang_javas: dict[int, list[JavaRuntimeMeta]] = {}
+
+ def add_java_runtime(runtime: JavaRuntimeMeta, major: int):
+ if major not in javas:
+ javas[major] = list[JavaRuntimeMeta]()
+ print(f"Registering runtime: {runtime.name} for Java {major}")
+ javas[major].append(runtime)
+
+ # only add specific versions to the list
+ if (
+ (
+ runtime.runtime_os
+ in [JavaRuntimeOS.MacOsArm64, JavaRuntimeOS.WindowsArm64]
+ and major == 8
+ )
+ or (
+ runtime.runtime_os
+ in [
+ JavaRuntimeOS.WindowsArm32,
+ JavaRuntimeOS.LinuxArm32,
+ JavaRuntimeOS.LinuxArm64,
+ ]
+ and major in [8, 17, 21, 25]
+ )
+ or (
+ runtime.runtime_os
+ in [JavaRuntimeOS.LinuxX86, JavaRuntimeOS.LinuxRiscv64]
+ and major in [17, 21, 25]
+ )
+ ):
+ if major not in extra_mojang_javas:
+ extra_mojang_javas[major] = list[JavaRuntimeMeta]()
+ extra_mojang_javas[major].append(runtime)
+
+ print("Processing Adoptium Releases")
+ adoptium_path = os.path.join(UPSTREAM_DIR, ADOPTIUM_DIR, "available_releases.json")
+ if os.path.exists(adoptium_path):
+ adoptium_available_releases = AdoptxAvailableReleases.parse_file(adoptium_path)
+ for major in adoptium_available_releases.available_releases:
+ adoptium_releases = AdoptxReleases.parse_file(
+ os.path.join(UPSTREAM_DIR, ADOPTIUM_VERSIONS_DIR, f"java{major}.json")
+ )
+ for _, rls in adoptium_releases:
+ for binary in rls.binaries:
+ if (
+ binary.package is None
+ or binary.image_type is not AdoptxImageType.Jre
+ ):
+ continue
+ binary_arch = translate_arch(str(binary.architecture))
+ binary_os = translate_os(str(binary.os))
+ if binary_arch is None or binary_os is None:
+ print(f"Ignoring release for {binary.os} {binary.architecture}")
+ continue
+
+ java_os = JavaRuntimeOS(f"{binary_os}-{binary_arch}")
+ runtime = adoptx_release_binary_to_java_runtime(
+ rls, binary, java_os
+ )
+ add_java_runtime(runtime, major)
+ writeJavas(javas=javas, uid=JAVA_ADOPTIUM_COMPONENT)
+ javas = {}
+
+ print("Processing OpenJ9 Releases")
+ openj9_path = os.path.join(UPSTREAM_DIR, OPENJ9_DIR, "available_releases.json")
+ if os.path.exists(openj9_path):
+ openj9_available_releases = AdoptxAvailableReleases.parse_file(openj9_path)
+ for major in openj9_available_releases.available_releases:
+ path = os.path.join(UPSTREAM_DIR, OPENJ9_VERSIONS_DIR, f"java{major}.json")
+
+ if not os.path.exists(path):
+ continue
+
+ openj9_releases = AdoptxReleases.parse_file(path)
+ for _, rls in openj9_releases:
+ for binary in rls.binaries:
+ if (
+ binary.package is None
+ or binary.image_type is not AdoptxImageType.Jre
+ ):
+ continue
+ binary_arch = translate_arch(str(binary.architecture))
+ binary_os = translate_os(str(binary.os))
+ if binary_arch is None or binary_os is None:
+ print(f"Ignoring release for {binary.os} {binary.architecture}")
+ continue
+
+ java_os = JavaRuntimeOS(f"{binary_os}-{binary_arch}")
+ runtime = adoptx_release_binary_to_java_runtime(
+ rls, binary, java_os
+ )
+ add_java_runtime(runtime, major)
+ writeJavas(javas=javas, uid=JAVA_OPENJ9_COMPONENT)
+ javas = {}
+
+ print("Processing Azul Packages")
+ azul_path = os.path.join(UPSTREAM_DIR, AZUL_DIR, "packages.json")
+ if os.path.exists(azul_path):
+ azul_packages = ZuluPackageList.parse_file(azul_path)
+ for _, pkg in azul_packages:
+ pkg_detail = ZuluPackageDetail.parse_file(
+ os.path.join(
+ UPSTREAM_DIR, AZUL_VERSIONS_DIR, f"{pkg.package_uuid}.json"
+ )
+ )
+ major = pkg_detail.java_version[0]
+ if major < 8 or pkg_detail.java_package_type is not AzulJavaPackageType.Jre:
+ continue # we will never need java versions less than 8
+
+ pkg_os = translate_os(str(pkg_detail.os))
+ if pkg_detail.arch == AzulArch.Arm:
+ pkg_arch = translate_arch(f"{pkg_detail.arch}{pkg_detail.hw_bitness}")
+ elif pkg_detail.arch == AzulArch.X86:
+ pkg_arch = translate_arch(int(pkg_detail.hw_bitness))
+ else:
+ pkg_arch = None
+ if pkg_arch is None or pkg_os is None:
+ print(
+ f"Ignoring release for {pkg_detail.os} {pkg_detail.arch}_{pkg_detail.hw_bitness}"
+ )
+ continue
+
+ java_os = JavaRuntimeOS(f"{pkg_os}-{pkg_arch}")
+ runtime = azul_package_to_java_runtime(pkg_detail, java_os)
+ add_java_runtime(runtime, major)
+ writeJavas(javas=javas, uid=JAVA_AZUL_COMPONENT)
+ javas = {}
+
+ # constructs the missing mojang javas based on adoptium or azul (do not consider openj9 since it is for more niche cases)
+ def get_mojang_extra_java(
+ mojang_component: MojangJavaComponent, java_os: JavaRuntimeOS
+ ) -> JavaRuntimeMeta | None:
+ java_major = mojang_component_to_major(mojang_component)
+ if not java_major in extra_mojang_javas:
+ return None
+ posible_javas = list(
+ filter(lambda x: x.runtime_os == java_os, extra_mojang_javas[java_major])
+ )
+ if len(posible_javas) == 0:
+ return None
+ prefered_vendor = list(filter(lambda x: x.vendor != "azul", posible_javas))
+ if len(prefered_vendor) == 0:
+ prefered_vendor = posible_javas
+ prefered_vendor.sort(key=lambda x: x.version, reverse=True)
+ runtime = prefered_vendor[0]
+ runtime.name = mojang_component
+ return runtime
+
+ print("Processing Mojang Javas")
+ mojang_java_manifest = JavaIndex.parse_file(
+ os.path.join(UPSTREAM_DIR, JAVA_MANIFEST_FILE)
+ )
+ # print(mojang_java_manifest)
+ for mojang_os_name in mojang_java_manifest:
+ if mojang_os_name == MojangJavaOsName.Gamecore:
+ continue # empty
+ java_os = mojang_os_to_java_os(mojang_os_name)
+ for comp in mojang_java_manifest[mojang_os_name]:
+ if comp == MojangJavaComponent.Exe:
+ continue # doesn't appear to be used and not marked with a full verison so I don't trust it
+ mojang_runtimes = mojang_java_manifest[mojang_os_name][comp]
+ if len(mojang_runtimes) == 0:
+ if mojang_os_name in [
+ MojangJavaOsName.WindowsArm64,
+ MojangJavaOsName.MacOSArm64,
+ ]:
+ if comp in [MojangJavaComponent.Alpha, MojangJavaComponent.Beta]:
+ mojang_runtimes = mojang_java_manifest[mojang_os_name][
+ MojangJavaComponent.Gamma
+ ]
+ elif (
+ comp == MojangJavaComponent.JreLegacy
+ ): # arm version of win and mac is missing the legacy java
+ runtime = get_mojang_extra_java(comp, java_os)
+ if runtime != None:
+ add_java_runtime(runtime, mojang_component_to_major(comp))
+ if (
+ mojang_os_name == MojangJavaOsName.Linuxi386
+ and comp != MojangJavaComponent.JreLegacy
+ ): # the linux x86 is missing all but legacy
+ runtime = get_mojang_extra_java(comp, java_os)
+ if runtime != None:
+ add_java_runtime(runtime, mojang_component_to_major(comp))
+ for mojang_runtime in mojang_runtimes:
+ if comp == MojangJavaComponent.JreLegacy:
+ major = 8
+ else:
+ major = int(mojang_runtime.version.name.partition(".")[0])
+ runtime = mojang_runtime_to_java_runtime(mojang_runtime, comp, java_os)
+ add_java_runtime(runtime, major)
+ # mojang doesn't provide any versions for the following systems so borrow info from adoptium/azul (do not consider openj9 since it is for more niche cases)
+ for java_os in [
+ JavaRuntimeOS.WindowsArm32,
+ JavaRuntimeOS.LinuxArm32,
+ JavaRuntimeOS.LinuxArm64,
+ JavaRuntimeOS.LinuxRiscv64,
+ ]:
+ for comp in [
+ MojangJavaComponent.JreLegacy,
+ MojangJavaComponent.Alpha,
+ MojangJavaComponent.Beta,
+ MojangJavaComponent.Gamma,
+ MojangJavaComponent.GammaSnapshot,
+ MojangJavaComponent.Delta,
+ MojangJavaComponent.Epsilon,
+ ]:
+ runtime = get_mojang_extra_java(comp, java_os)
+ if runtime != None:
+ add_java_runtime(runtime, mojang_component_to_major(comp))
+
+ writeJavas(javas=javas, uid=JAVA_MINECRAFT_COMPONENT)
+ javas = {}
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/generate_liteloader.py b/meta/meta/run/generate_liteloader.py
new file mode 100755
index 0000000000..2fe95fcc42
--- /dev/null
+++ b/meta/meta/run/generate_liteloader.py
@@ -0,0 +1,118 @@
+import os
+from datetime import datetime
+from typing import List, Tuple, Dict, Optional
+
+from meta.common import ensure_component_dir, launcher_path, upstream_path
+from meta.common.liteloader import LITELOADER_COMPONENT, VERSIONS_FILE
+from meta.common.mojang import MINECRAFT_COMPONENT
+from meta.model import MetaVersion, GradleSpecifier, Library, MetaPackage, Dependency
+from meta.model.liteloader import LiteloaderIndex, LiteloaderArtefact
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+ensure_component_dir(LITELOADER_COMPONENT)
+
+
+def process_artefacts(
+ mc_version: str, artefacts: Dict[str, LiteloaderArtefact], is_snapshot: bool
+) -> Tuple[List[MetaVersion], Optional[MetaVersion]]:
+ versions: List[MetaVersion] = []
+ lookup: Dict[str, MetaVersion] = {}
+ latest_version = None
+ latest = None
+ for x, artefact in artefacts.items():
+ if x == "latest":
+ latest_version = artefact.version
+ continue
+ v = MetaVersion(
+ name="LiteLoader",
+ uid=LITELOADER_COMPONENT,
+ version=artefact.version,
+ requires=[Dependency(uid=MINECRAFT_COMPONENT, equals=mc_version)],
+ release_time=datetime.utcfromtimestamp(int(artefact.timestamp)),
+ additional_tweakers=[artefact.tweakClass],
+ main_class="net.minecraft.launchwrapper.Launch",
+ order=10,
+ libraries=artefact.libraries,
+ type="release",
+ )
+
+ if is_snapshot:
+ v.type = "snapshot"
+
+ # hack to make broken liteloader versions work
+ for lib in v.libraries:
+ if lib.name == GradleSpecifier("org.ow2.asm", "asm-all", "5.0.3"):
+ lib.url = "https://repo.maven.apache.org/maven2/"
+ if lib.name == GradleSpecifier("org.ow2.asm", "asm-all", "5.2"):
+ lib.url = "http://repo.liteloader.com/"
+
+ liteloader_lib = Library(
+ name=GradleSpecifier("com.mumfrey", "liteloader", v.version),
+ url="http://dl.liteloader.com/versions/",
+ )
+ if is_snapshot:
+ liteloader_lib.mmcHint = "always-stale"
+ v.libraries.append(liteloader_lib)
+
+ versions.append(v)
+ lookup[v.version] = v
+
+ if latest_version:
+ latest = lookup[latest_version]
+ return versions, latest
+
+
+def process_versions(index: LiteloaderIndex) -> Tuple[List[MetaVersion], List[str]]:
+ all_versions: List[MetaVersion] = []
+ recommended: List[str] = []
+ for mcVersion, versionObject in index.versions.items():
+ # ignore this for now. It should be a jar mod or something.
+ if mcVersion == "1.5.2":
+ continue
+
+ latest_release = None
+ if versionObject.artefacts:
+ versions, latest_release = process_artefacts(
+ mcVersion, versionObject.artefacts.liteloader, False
+ )
+ all_versions.extend(versions)
+ if versionObject.snapshots:
+ versions, latest_snapshot = process_artefacts(
+ mcVersion, versionObject.snapshots.liteloader, True
+ )
+ all_versions.extend(versions)
+
+ if latest_release:
+ recommended.append(latest_release.version)
+
+ recommended.sort()
+
+ all_versions.sort(key=lambda x: x.release_time, reverse=True)
+ return all_versions, recommended
+
+
+def main():
+ index = LiteloaderIndex.parse_file(os.path.join(UPSTREAM_DIR, VERSIONS_FILE))
+
+ all_versions, recommended = process_versions(index)
+
+ for version in all_versions:
+ version.write(
+ os.path.join(LAUNCHER_DIR, LITELOADER_COMPONENT, f"{version.version}.json")
+ )
+
+ package = MetaPackage(
+ uid=LITELOADER_COMPONENT,
+ name="LiteLoader",
+ description=index.meta.description,
+ project_url=index.meta.url,
+ authors=[index.meta.authors],
+ recommended=recommended,
+ )
+ package.write(os.path.join(LAUNCHER_DIR, LITELOADER_COMPONENT, "package.json"))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/generate_mojang.py b/meta/meta/run/generate_mojang.py
new file mode 100755
index 0000000000..9d2063263a
--- /dev/null
+++ b/meta/meta/run/generate_mojang.py
@@ -0,0 +1,589 @@
+import copy
+import hashlib
+import re
+import os
+from collections import defaultdict, namedtuple
+from operator import attrgetter
+from pprint import pprint
+from packaging import version as pversion
+from typing import Optional, List
+
+from meta.common import ensure_component_dir, launcher_path, upstream_path
+from meta.common.mojang import (
+ STATIC_LEGACY_SERVICES_FILE,
+ VERSION_MANIFEST_FILE,
+ MINECRAFT_COMPONENT,
+ LWJGL3_COMPONENT,
+ LWJGL_COMPONENT,
+ STATIC_OVERRIDES_FILE,
+ VERSIONS_DIR,
+ LIBRARY_PATCHES_FILE,
+)
+from meta.model import (
+ MetaVersion,
+ Library,
+ GradleSpecifier,
+ MojangLibraryDownloads,
+ MojangArtifact,
+ Dependency,
+ MetaPackage,
+ MojangRules,
+)
+from meta.model.mojang import (
+ LegacyServices,
+ MojangIndexWrap,
+ MojangIndex,
+ MojangVersion,
+ LegacyOverrideIndex,
+ LibraryPatches,
+ SUPPORTED_FEATURES,
+)
+
+APPLY_SPLIT_NATIVES_WORKAROUND = True
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+ensure_component_dir(MINECRAFT_COMPONENT)
+ensure_component_dir(LWJGL_COMPONENT)
+ensure_component_dir(LWJGL3_COMPONENT)
+
+
+def map_log4j_artifact(version):
+ x = pversion.parse(version)
+ if x <= pversion.parse("2.0"):
+ return "2.0-beta9-fixed", "https://files.prismlauncher.org/maven/%s"
+ if x <= pversion.parse("2.17.1"):
+ return (
+ "2.17.1",
+ "https://repo1.maven.org/maven2/%s",
+ ) # This is the only version that's patched (as of 2022/02/19)
+ return None, None
+
+
+LOG4J_HASHES = {
+ "2.0-beta9-fixed": {
+ "log4j-api": {
+ "sha1": "b61eaf2e64d8b0277e188262a8b771bbfa1502b3",
+ "size": 107347,
+ },
+ "log4j-core": {
+ "sha1": "677991ea2d7426f76309a73739cecf609679492c",
+ "size": 677588,
+ },
+ },
+ "2.17.1": {
+ "log4j-api": {
+ "sha1": "d771af8e336e372fb5399c99edabe0919aeaf5b2",
+ "size": 301872,
+ },
+ "log4j-core": {
+ "sha1": "779f60f3844dadc3ef597976fcb1e5127b1f343d",
+ "size": 1790452,
+ },
+ "log4j-slf4j18-impl": {
+ "sha1": "ca499d751f4ddd8afb016ef698c30be0da1d09f7",
+ "size": 21268,
+ },
+ },
+}
+
+# We want versions that contain natives for all platforms. If there are multiple, pick the latest one
+# LWJGL versions we want
+PASS_VARIANTS = [
+ "1fd0e4d1f0f7c97e8765a69d38225e1f27ee14ef", # 3.4.1 (2026-02-17 12:42:24+00:00)
+ "2b00f31688148fc95dbc8c8ef37308942cf0dce0", # 3.3.6 (2025-10-21 11:38:51+00:00)
+ "73974b3af2afeb5b272ffbadcd7963014387c84f", # 3.3.3 (2024-05-22 16:25:41+00:00)
+ "765b4ab443051d286bdbb1c19cd7dc86b0792dce", # 3.3.2 (2024-01-17 13:19:20+00:00)
+ "54c4fb1d6a96ac3007c947bf310c8bcf94a862be", # 3.3.1 (2023-04-20 11:55:19+00:00) split natives, with WoA natives
+ "ea4973ebc9eadf059f30f0958c89f330898bff51", # 3.2.2 (2019-07-04 14:41:05+00:00) will be patched, missing tinyfd
+ "235fc413bc4c76b269c207f7bca6464f1e1f1d80", # 3.2.1 (2019-02-13 16:12:08+00:00)
+ "deb1a436d806413207350735a00e04b54d113916", # 3.1.6 (2018-10-18 14:46:12+00:00)
+ "3e47f0f742fb759401754769fa59c508fd8fda75", # 3.1.2 (2018-06-21 12:57:11+00:00)
+ "a3f254df5a63a0a1635755733022029e8cfae1b3", # 2.9.4-nightly-20150209 (2016-12-20 14:05:34+00:00)
+ "879be09c0bd0d4bafc2ea4ea3d2ab8607a0d976c", # 2.9.3 (2015-01-30 11:58:24+00:00)
+ "8d4951d00253dfaa36a0faf1c8be541431861c30", # 2.9.1 (2014-05-22 14:44:33+00:00)
+ "cf58c9f92fed06cb041a7244c6b4b667e6d544cc", # 2.9.1-nightly-20131120 (2013-12-06 13:55:34+00:00)
+ "27dcadcba29a1a7127880ca1a77efa9ece866f24", # 2.9.0 (2013-09-06 12:31:58+00:00)
+]
+
+# LWJGL versions we def. don't want!
+BAD_VARIANTS = [
+ "6f32ef730d05562ede7db0b845b72ea16dd239d5", # 3.3.3 (2024-05-29 12:04:43+00:00) missing os rule for freetype natives-macos-patch
+ "8a9b08f11271eb4de3b50e5d069949500b2c7bc1", # 3.3.3 (2024-04-03 11:49:39+00:00) seems to have a broken libfreetype for macOS x86_64
+ "79bde9e46e9ad9accebda11e8293ed08d80dbdc3", # 3.3.2 (2023-08-30 11:24:35+00:00) does not have lwjgl-freetype
+ "8836c419f90f69a278b97d945a34af165c24ff60", # 3.3.1 (2022-05-18 13:51:54+00:00) split natives, with workaround, replaced by 23w26a
+ "3c624b94c06dbc4abae08fe6156d74abe4a2cca5", # 3.3.1 (2022-05-04 14:41:35+00:00) we already have a nice 3.3.1
+ "e1106ca765798218323b7a6d7528050260ea9d88", # 3.3.1 (2022-05-04 14:41:35+00:00) doesn't use split natives
+ "90b3d9ca01058286c033b6b7ae7f6dc370a04015", # 3.2.2 (2022-03-31 14:53:25+00:00) only linux, windows
+ "d986df9598fa2bcf4a5baab5edf044548e66d011", # 3.2.2 (2021-12-10 03:36:38+00:00) only linux, windows
+ "4b73fccb9e5264c2068bdbc26f9651429abbf21a", # 3.2.2 (2021-08-25 14:41:57+00:00) only linux, windows
+ "090cec3577ecfe438b890b2a9410ea07aa725e16", # 3.2.2 (2021-04-07 14:04:09+00:00) only linux, windows
+ "ab463e9ebc6a36abf22f2aa27b219dd372ff5069", # 3.2.2 (2019-08-13 07:33:42+00:00) only linux, windows
+ "51d8ff5a7efc949b4ad2088930e151d6b88ba616", # 3.2.2 (2019-07-19 09:25:47+00:00) only linux, windows
+ "854649a5bd1455b89117593ae82ff90c8132cacf", # 3.2.1 (2019-04-18 11:05:19+00:00) only osx, windows
+ "89fcb489261b05f622e8052fe0b588b0cfe49c24", # 3.1.6 (2019-04-18 11:05:19+00:00) only linux
+ "f04052162b50fa1433f67e1a90bc79466c4ab776", # 2.9.0 (2013-10-21 16:34:47+00:00) only linux, windows
+ "6442fc475f501fbd0fc4244fd1c38c02d9ebaf7e", # 2.9.0 (2011-03-30 22:00:00+00:00) fine but newer variant available
+]
+
+
+def add_or_get_bucket(buckets, rules: Optional[MojangRules]) -> MetaVersion:
+ rule_hash = None
+ if rules:
+ rule_hash = hash(rules.json())
+
+ if rule_hash in buckets:
+ bucket = buckets[rule_hash]
+ else:
+ bucket = MetaVersion(name="LWJGL", version="undetermined", uid=LWJGL_COMPONENT)
+ bucket.type = "release"
+ buckets[rule_hash] = bucket
+ return bucket
+
+
+def hash_lwjgl_version(lwjgl: MetaVersion):
+ lwjgl_copy = copy.deepcopy(lwjgl)
+ lwjgl_copy.release_time = None
+ return hashlib.sha1(lwjgl_copy.json().encode("utf-8", "strict")).hexdigest()
+
+
+def sort_libs_by_name(library):
+ return library.name
+
+
+LWJGLEntry = namedtuple("LWJGLEntry", ("version", "sha1"))
+
+lwjglVersionVariants = defaultdict(list)
+
+
+def add_lwjgl_version(variants, lwjgl):
+ lwjgl_copy = copy.deepcopy(lwjgl)
+ libraries = list(lwjgl_copy.libraries)
+ libraries.sort(key=sort_libs_by_name)
+ lwjgl_copy.libraries = libraries
+
+ version = lwjgl_copy.version
+ current_hash = hash_lwjgl_version(lwjgl_copy)
+ found = False
+ for variant in variants[version]:
+ existing_hash = variant.sha1
+ if current_hash == existing_hash:
+ found = True
+ break
+ if not found:
+ print("!!! New variant for LWJGL version %s" % version)
+ variants[version].append(LWJGLEntry(version=lwjgl_copy, sha1=current_hash))
+
+
+def remove_paths_from_lib(lib):
+ if lib.downloads.artifact:
+ lib.downloads.artifact.path = None
+ if lib.downloads.classifiers:
+ for key, value in lib.downloads.classifiers.items():
+ value.path = None
+
+
+def adapt_new_style_arguments(arguments):
+ foo = []
+ # we ignore the jvm arguments entirely.
+ # grab the strings, log the complex stuff
+ for arg in arguments.game:
+ if isinstance(arg, str):
+ if arg == "--clientId":
+ continue
+ if arg == "${clientid}":
+ continue
+ if arg == "--xuid":
+ continue
+ if arg == "${auth_xuid}":
+ continue
+ foo.append(arg)
+ else:
+ print("!!! Unrecognized structure in Minecraft game arguments:")
+ pprint(arg)
+ return " ".join(foo)
+
+
+def adapt_new_style_arguments_to_traits(arguments):
+ foo = []
+ # we ignore the jvm arguments entirely.
+ # grab the object, log the errors
+ for arg in arguments.game:
+ if isinstance(arg, dict):
+ for rule in arg["rules"]:
+ for k, v in rule["features"].items():
+ if rule["action"] == "allow" and v and k in SUPPORTED_FEATURES:
+ foo.append(f"feature:{k}")
+ return foo
+
+
+def is_macos_only(rules: Optional[MojangRules]):
+ allows_osx = False
+ allows_all = False
+ # print("Considering", specifier, "rules", rules)
+ if rules:
+ for rule in rules:
+ if rule.action == "allow" and rule.os and rule.os.name == "osx":
+ allows_osx = True
+ if rule.action == "allow" and not rule.os:
+ allows_all = True
+ if allows_osx and not allows_all:
+ return True
+ return False
+
+
+def patch_library(lib: Library, patches: LibraryPatches) -> List[Library]:
+ to_patch = [lib]
+
+ new_libraries = []
+ while to_patch:
+ target = to_patch.pop(0)
+
+ for patch in patches:
+ if patch.applies(target):
+ if patch.override:
+ target.merge(patch.override)
+
+ if patch.additionalLibraries:
+ additional_copy = copy.deepcopy(patch.additionalLibraries)
+ new_libraries += list(dict.fromkeys(additional_copy))
+ if patch.patchAdditionalLibraries:
+ to_patch += additional_copy
+
+ return new_libraries
+
+
+def process_single_variant(lwjgl_variant: MetaVersion, patches: LibraryPatches):
+ lwjgl_version = lwjgl_variant.version
+ v = copy.deepcopy(lwjgl_variant)
+
+ new_libraries = []
+ for lib in v.libraries:
+ new_libraries += patch_library(lib, patches)
+ v.libraries += list(dict.fromkeys(new_libraries))
+
+ if lwjgl_version[0] == "2":
+ filename = os.path.join(LAUNCHER_DIR, LWJGL_COMPONENT, f"{lwjgl_version}.json")
+
+ v.name = "LWJGL 2"
+ v.uid = LWJGL_COMPONENT
+ v.conflicts = [Dependency(uid=LWJGL3_COMPONENT)]
+ elif lwjgl_version[0] == "3":
+ filename = os.path.join(LAUNCHER_DIR, LWJGL3_COMPONENT, f"{lwjgl_version}.json")
+
+ v.name = "LWJGL 3"
+ v.uid = LWJGL3_COMPONENT
+ v.conflicts = [Dependency(uid=LWJGL_COMPONENT)]
+ # remove jutils and jinput from LWJGL 3
+ # this is a dependency that Mojang kept in, but doesn't belong there anymore
+ filtered_libraries = list(
+ filter(lambda l: l.name.artifact not in ["jutils", "jinput"], v.libraries)
+ )
+ v.libraries = filtered_libraries
+ else:
+ raise Exception("LWJGL version not recognized: %s" % v.version)
+
+ v.volatile = True
+ v.order = -1
+ good = True
+ for lib in v.libraries:
+ # skip libraries without natives or that we patched
+ if not lib.natives or lib in new_libraries:
+ continue
+ checked_dict = {"linux", "windows", "osx"}
+ if not checked_dict.issubset(lib.natives.keys()):
+ print("Missing system classifier!", v.version, lib.name, lib.natives.keys())
+ good = False
+ break
+ if lib.downloads:
+ for entry in checked_dict:
+ baked_entry = lib.natives[entry]
+ if baked_entry not in lib.downloads.classifiers:
+ print(
+ "Missing download for classifier!",
+ v.version,
+ lib.name,
+ baked_entry,
+ lib.downloads.classifiers.keys(),
+ )
+ good = False
+ break
+ if good:
+ v.write(filename)
+ else:
+ print("Skipped LWJGL", v.version)
+
+
+def lib_is_split_native(lib: Library) -> bool:
+ if lib.name.classifier and lib.name.classifier.startswith("natives-"):
+ return True
+ return False
+
+
+def version_has_split_natives(v: MojangVersion) -> bool:
+ for lib in v.libraries:
+ if lib_is_split_native(lib):
+ return True
+ return False
+
+
+def main():
+ # get the local version list
+ override_index = LegacyOverrideIndex.parse_file(STATIC_OVERRIDES_FILE)
+ legacy_services = LegacyServices.parse_file(STATIC_LEGACY_SERVICES_FILE)
+ library_patches = LibraryPatches.parse_file(LIBRARY_PATCHES_FILE)
+
+ found_any_lwjgl3 = False
+
+ for filename in os.listdir(os.path.join(UPSTREAM_DIR, VERSIONS_DIR)):
+ input_file = os.path.join(UPSTREAM_DIR, VERSIONS_DIR, filename)
+ if not input_file.endswith(".json"):
+ # skip non JSON files
+ continue
+ print("Processing", filename)
+ mojang_version = MojangVersion.parse_file(input_file)
+ v = mojang_version.to_meta_version(
+ "Minecraft", MINECRAFT_COMPONENT, mojang_version.id
+ )
+
+ libs_minecraft = []
+ new_libs_minecraft = []
+ is_lwjgl_3 = False
+ has_split_natives = version_has_split_natives(v)
+ buckets = {}
+
+ for lib in v.libraries:
+ specifier = lib.name
+
+ # generic fixes
+ remove_paths_from_lib(lib)
+
+ if APPLY_SPLIT_NATIVES_WORKAROUND and lib_is_split_native(lib):
+ # merge classifier into artifact name to workaround bug in launcher
+ specifier.artifact += f"-{specifier.classifier}"
+ specifier.classifier = None
+
+ if specifier.is_lwjgl():
+ if has_split_natives: # implies lwjgl3
+ bucket = add_or_get_bucket(buckets, None)
+ is_lwjgl_3 = True
+ found_any_lwjgl3 = True
+ bucket.version = specifier.version
+ if not bucket.libraries:
+ bucket.libraries = []
+ bucket.libraries.append(lib)
+ bucket.release_time = v.release_time
+ else:
+ rules = None
+ if lib.rules:
+ rules = lib.rules
+ lib.rules = None
+ if is_macos_only(rules):
+ print(
+ "Candidate library ",
+ specifier,
+ " is only for macOS and is therefore ignored.",
+ )
+ continue
+ bucket = add_or_get_bucket(buckets, rules)
+ if (
+ specifier.group == "org.lwjgl.lwjgl"
+ and specifier.artifact == "lwjgl"
+ ):
+ bucket.version = specifier.version
+ if specifier.group == "org.lwjgl" and specifier.artifact == "lwjgl":
+ is_lwjgl_3 = True
+ found_any_lwjgl3 = True
+ bucket.version = specifier.version
+ if not bucket.libraries:
+ bucket.libraries = []
+ bucket.libraries.append(lib)
+ bucket.release_time = v.release_time
+ # FIXME: workaround for insane log4j nonsense from December 2021. Probably needs adjustment.
+ elif lib.name.is_log4j():
+ version_override, maven_override = map_log4j_artifact(lib.name.version)
+
+ if version_override and maven_override:
+ if version_override not in LOG4J_HASHES:
+ raise Exception(
+ "ERROR: unhandled log4j version (overriden) %s!"
+ % version_override
+ )
+
+ if lib.name.artifact not in LOG4J_HASHES[version_override]:
+ raise Exception(
+ "ERROR: unhandled log4j artifact %s!" % lib.name.artifact
+ )
+
+ replacement_name = GradleSpecifier(
+ "org.apache.logging.log4j", lib.name.artifact, version_override
+ )
+ artifact = MojangArtifact(
+ url=maven_override % (replacement_name.path()),
+ sha1=LOG4J_HASHES[version_override][lib.name.artifact]["sha1"],
+ size=LOG4J_HASHES[version_override][lib.name.artifact]["size"],
+ )
+
+ libs_minecraft.append(
+ Library(
+ name=replacement_name,
+ downloads=MojangLibraryDownloads(artifact=artifact),
+ )
+ )
+ else:
+ libs_minecraft.append(lib)
+ else:
+ new_libs_minecraft += patch_library(lib, library_patches)
+ libs_minecraft.append(lib)
+ if len(buckets) == 1:
+ for key in buckets:
+ lwjgl = buckets[key]
+ lwjgl.libraries = sorted(lwjgl.libraries, key=attrgetter("name"))
+ add_lwjgl_version(lwjglVersionVariants, lwjgl)
+ print("Found only candidate LWJGL", lwjgl.version, key)
+ else:
+ # multiple buckets for LWJGL. [None] is common to all, other keys are for different sets of rules
+ for key in buckets:
+ if key is None:
+ continue
+ lwjgl = buckets[key]
+ if None in buckets:
+ lwjgl.libraries = sorted(
+ lwjgl.libraries + buckets[None].libraries,
+ key=attrgetter("name"),
+ )
+ else:
+ lwjgl.libraries = sorted(lwjgl.libraries, key=attrgetter("name"))
+ add_lwjgl_version(lwjglVersionVariants, lwjgl)
+ print("Found candidate LWJGL", lwjgl.version, key)
+ # remove the common bucket...
+ if None in buckets:
+ del buckets[None]
+ v.libraries = libs_minecraft + list(dict.fromkeys(new_libs_minecraft))
+
+ if is_lwjgl_3:
+ lwjgl_dependency = Dependency(uid=LWJGL3_COMPONENT)
+ else:
+ lwjgl_dependency = Dependency(uid=LWJGL_COMPONENT)
+ if len(buckets) == 1:
+ suggested_version = next(iter(buckets.values())).version
+ if is_lwjgl_3:
+ lwjgl_dependency.suggests = suggested_version
+ else:
+ lwjgl_dependency.suggests = "2.9.4-nightly-20150209"
+ else:
+ bad_versions = {"3.1.6", "3.2.1"}
+ our_versions = set()
+
+ for lwjgl in iter(buckets.values()):
+ our_versions = our_versions.union({lwjgl.version})
+
+ if our_versions == bad_versions:
+ print("Found broken 3.1.6/3.2.1 combo, forcing LWJGL to 3.2.1")
+ suggested_version = "3.2.1"
+ lwjgl_dependency.suggests = suggested_version
+ else:
+ raise Exception(
+ "ERROR: cannot determine single suggested LWJGL version in %s"
+ % mojang_version.id
+ )
+
+ # if it uses LWJGL 3, add the trait that enables starting on first thread on macOS
+ if is_lwjgl_3:
+ if not v.additional_traits:
+ v.additional_traits = []
+ v.additional_traits.append("FirstThreadOnMacOS")
+ v.requires = [lwjgl_dependency]
+ v.order = -2
+ # process 1.13 arguments into previous version
+ if not mojang_version.minecraft_arguments and mojang_version.arguments:
+ v.minecraft_arguments = adapt_new_style_arguments(mojang_version.arguments)
+ if not v.additional_traits:
+ v.additional_traits = []
+ v.additional_traits.extend(
+ adapt_new_style_arguments_to_traits(mojang_version.arguments)
+ )
+ out_filename = os.path.join(
+ LAUNCHER_DIR, MINECRAFT_COMPONENT, f"{v.version}.json"
+ )
+ if v.version in override_index.versions:
+ override = override_index.versions[v.version]
+ override.apply_onto_meta_version(v)
+ if v.version in legacy_services:
+ if v.additional_traits == None:
+ v.additional_traits = []
+ v.additional_traits.append("legacyServices")
+
+ # 13w16a-13w23a require legacyLaunch and those + 13w23b require texturepacks
+ if re.match(r"13w[1,2]\d[a-c]", v.version) and 16 <= int(v.version[3:-1]) <= 23:
+ if v.additional_traits == None:
+ v.additional_traits = []
+ if v.version != "13w23b":
+ v.additional_traits.append("legacyLaunch")
+ v.additional_traits.append("texturepacks")
+
+ v.write(out_filename)
+
+ for lwjglVersionVariant in lwjglVersionVariants:
+ decided_variant = None
+ passed_variants = 0
+ unknown_variants = 0
+ print(
+ "%d variant(s) for LWJGL %s:"
+ % (len(lwjglVersionVariants[lwjglVersionVariant]), lwjglVersionVariant)
+ )
+
+ for variant in lwjglVersionVariants[lwjglVersionVariant]:
+ if variant.sha1 in BAD_VARIANTS:
+ print("Variant %s ignored because it's marked as bad." % variant.sha1)
+ continue
+ if variant.sha1 in PASS_VARIANTS:
+ print("Variant %s accepted." % variant.sha1)
+ decided_variant = variant
+ passed_variants += 1
+ continue
+ # print natives classifiers to decide which variant to use
+ n = [
+ x.natives.keys()
+ for x in variant.version.libraries
+ if x.natives is not None
+ ]
+ print(n)
+
+ print(
+ f' "{variant.sha1}", # {lwjglVersionVariant} ({variant.version.release_time})'
+ )
+ unknown_variants += 1
+ print("")
+
+ if decided_variant and passed_variants == 1 and unknown_variants == 0:
+ process_single_variant(decided_variant.version, library_patches)
+ else:
+ raise Exception(
+ "No variant decided for version %s out of %d possible ones and %d unknown ones."
+ % (lwjglVersionVariant, passed_variants, unknown_variants)
+ )
+
+ lwjgl_package = MetaPackage(uid=LWJGL_COMPONENT, name="LWJGL 2")
+ lwjgl_package.write(os.path.join(LAUNCHER_DIR, LWJGL_COMPONENT, "package.json"))
+
+ if found_any_lwjgl3:
+ lwjgl_package = MetaPackage(uid=LWJGL3_COMPONENT, name="LWJGL 3")
+ lwjgl_package.write(
+ os.path.join(LAUNCHER_DIR, LWJGL3_COMPONENT, "package.json")
+ )
+
+ mojang_index = MojangIndexWrap(
+ MojangIndex.parse_file(os.path.join(UPSTREAM_DIR, VERSION_MANIFEST_FILE))
+ )
+
+ minecraft_package = MetaPackage(uid=MINECRAFT_COMPONENT, name="Minecraft")
+ minecraft_package.recommended = [mojang_index.latest.release]
+ minecraft_package.write(
+ os.path.join(LAUNCHER_DIR, MINECRAFT_COMPONENT, "package.json")
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/generate_neoforge.py b/meta/meta/run/generate_neoforge.py
new file mode 100644
index 0000000000..de32256869
--- /dev/null
+++ b/meta/meta/run/generate_neoforge.py
@@ -0,0 +1,170 @@
+from copy import deepcopy
+import os
+import re
+from operator import attrgetter
+from typing import Collection
+
+from meta.common import ensure_component_dir, launcher_path, upstream_path, eprint
+from meta.common.neoforge import (
+ NEOFORGE_COMPONENT,
+ INSTALLER_MANIFEST_DIR,
+ VERSION_MANIFEST_DIR,
+ DERIVED_INDEX_FILE,
+ INSTALLER_INFO_DIR,
+)
+from meta.common.forge import FORGEWRAPPER_LIBRARY
+from meta.common.mojang import MINECRAFT_COMPONENT
+from meta.model import (
+ MetaVersion,
+ Dependency,
+ Library,
+ GradleSpecifier,
+ MojangLibraryDownloads,
+ MojangArtifact,
+ MetaPackage,
+)
+from meta.model.neoforge import (
+ NeoForgeVersion,
+ NeoForgeInstallerProfileV2,
+ InstallerInfo,
+ DerivedNeoForgeIndex,
+)
+from meta.model.mojang import MojangVersion
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+ensure_component_dir(NEOFORGE_COMPONENT)
+
+
+def version_from_build_system_installer(
+ installer: MojangVersion,
+ profile: NeoForgeInstallerProfileV2,
+ version: NeoForgeVersion,
+) -> MetaVersion:
+ v = MetaVersion(name="NeoForge", version=version.rawVersion, uid=NEOFORGE_COMPONENT)
+ v.main_class = "io.github.zekerzhayard.forgewrapper.installer.Main"
+
+ # FIXME: Add the size and hash here
+ v.maven_files = []
+
+ # load the locally cached installer file info and use it to add the installer entry in the json
+ info = InstallerInfo.parse_file(
+ os.path.join(UPSTREAM_DIR, INSTALLER_INFO_DIR, f"{version.long_version}.json")
+ )
+ installer_lib = Library(
+ name=GradleSpecifier(
+ "net.neoforged", version.artifact, version.long_version, "installer"
+ )
+ )
+ installer_lib.downloads = MojangLibraryDownloads()
+ installer_lib.downloads.artifact = MojangArtifact(
+ url="https://maven.neoforged.net/releases/%s" % (installer_lib.name.path()),
+ sha1=info.sha1hash,
+ size=info.size,
+ )
+ v.maven_files.append(installer_lib)
+
+ for forge_lib in profile.libraries:
+ if forge_lib.name.is_log4j():
+ continue
+
+ v.maven_files.append(forge_lib)
+
+ v.libraries = []
+
+ v.libraries.append(FORGEWRAPPER_LIBRARY)
+
+ for forge_lib in installer.libraries:
+ if forge_lib.name.is_log4j():
+ continue
+
+ v.libraries.append(forge_lib)
+
+ v.release_time = installer.release_time
+ v.order = 5
+ mc_args = (
+ "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} "
+ "--assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} "
+ "--accessToken ${auth_access_token} --userType ${user_type} --versionType ${version_type}"
+ )
+ for arg in installer.arguments.game:
+ mc_args += f" {arg}"
+ v.minecraft_arguments = mc_args
+ return v
+
+
+def main():
+ # load the locally cached version list
+ remote_versions = DerivedNeoForgeIndex.parse_file(
+ os.path.join(UPSTREAM_DIR, DERIVED_INDEX_FILE)
+ )
+ recommended_versions = []
+
+ for key, entry in remote_versions.versions.items():
+ version = NeoForgeVersion(entry)
+
+ if version.url() is None:
+ eprint("Skipping %s with no valid files" % key)
+ continue
+ eprint("Processing NeoForge %s" % version.rawVersion)
+ version_elements = version.rawVersion.split(".")
+ if len(version_elements) < 1:
+ eprint("Skipping version %s with not enough version elements" % key)
+ continue
+
+ major_version_str = version_elements[0]
+ if not major_version_str.isnumeric():
+ eprint(
+ "Skipping version %s with non-numeric major version %s"
+ % (key, major_version_str)
+ )
+ continue
+
+ if entry.recommended:
+ recommended_versions.append(version.rawVersion)
+
+ # Path for new-style build system based installers
+ installer_version_filepath = os.path.join(
+ UPSTREAM_DIR, VERSION_MANIFEST_DIR, f"{version.long_version}.json"
+ )
+ profile_filepath = os.path.join(
+ UPSTREAM_DIR, INSTALLER_MANIFEST_DIR, f"{version.long_version}.json"
+ )
+
+ eprint(installer_version_filepath)
+ assert os.path.isfile(
+ installer_version_filepath
+ ), f"version {installer_version_filepath} does not have installer version manifest"
+ installer = MojangVersion.parse_file(installer_version_filepath)
+ profile = NeoForgeInstallerProfileV2.parse_file(profile_filepath)
+ v = version_from_build_system_installer(installer, profile, version)
+
+ # we can get the minecraft version from the profile json info, so let's just do that instead of hacky regex
+ v.requires = [Dependency(uid=MINECRAFT_COMPONENT, equals=profile.minecraft)]
+ # If we do not have the corresponding Minecraft version, we ignore it
+ if not os.path.isfile(
+ os.path.join(LAUNCHER_DIR, MINECRAFT_COMPONENT, f"{profile.minecraft}.json")
+ ):
+ eprint(
+ "Skipping %s with no corresponding Minecraft version %s"
+ % (key, profile.minecraft)
+ )
+ continue
+ v.write(os.path.join(LAUNCHER_DIR, NEOFORGE_COMPONENT, f"{v.version}.json"))
+
+ recommended_versions.sort()
+
+ print("Recommended versions:", recommended_versions)
+
+ package = MetaPackage(
+ uid=NEOFORGE_COMPONENT,
+ name="NeoForge",
+ project_url="https://neoforged.net",
+ )
+ package.recommended = recommended_versions
+ package.write(os.path.join(LAUNCHER_DIR, NEOFORGE_COMPONENT, "package.json"))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/generate_quilt.py b/meta/meta/run/generate_quilt.py
new file mode 100755
index 0000000000..01964d5864
--- /dev/null
+++ b/meta/meta/run/generate_quilt.py
@@ -0,0 +1,176 @@
+import json
+import os
+import sys
+
+from meta.common import (
+ ensure_component_dir,
+ launcher_path,
+ upstream_path,
+ transform_maven_key,
+)
+from meta.common.quilt import (
+ JARS_DIR,
+ INSTALLER_INFO_DIR,
+ META_DIR,
+ INTERMEDIARY_COMPONENT,
+ LOADER_COMPONENT,
+ USE_QUILT_MAPPINGS,
+ DISABLE_BEACON_ARG,
+ DISABLE_BEACON_VERSIONS,
+)
+from meta.model import MetaVersion, Dependency, Library, MetaPackage, GradleSpecifier
+from meta.model.fabric import FabricJarInfo, FabricInstallerDataV1, FabricMainClasses
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+ensure_component_dir(LOADER_COMPONENT)
+ensure_component_dir(INTERMEDIARY_COMPONENT)
+
+
+def eprint(*args, **kwargs):
+ print(*args, file=sys.stderr, **kwargs)
+
+
+def load_jar_info(artifact_key) -> FabricJarInfo:
+ return FabricJarInfo.parse_file(
+ os.path.join(UPSTREAM_DIR, JARS_DIR, f"{artifact_key}.json")
+ )
+
+
+def load_installer_info(version) -> FabricInstallerDataV1:
+ return FabricInstallerDataV1.parse_file(
+ os.path.join(UPSTREAM_DIR, INSTALLER_INFO_DIR, f"{version}.json")
+ )
+
+
+def process_loader_version(entry) -> (MetaVersion, bool):
+ should_recommend = (
+ "-" not in entry["version"]
+ ) # Don't recommend pre releases as per SemVer
+
+ jar_info = load_jar_info(transform_maven_key(entry["maven"]))
+ installer_info = load_installer_info(entry["version"])
+
+ v = MetaVersion(name="Quilt Loader", uid=LOADER_COMPONENT, version=entry["version"])
+ v.release_time = jar_info.release_time
+ v.requires = [Dependency(uid=INTERMEDIARY_COMPONENT)]
+ v.order = 10
+ v.type = "release"
+ if isinstance(installer_info.main_class, FabricMainClasses):
+ v.main_class = installer_info.main_class.client
+ else:
+ v.main_class = installer_info.main_class
+ v.libraries = []
+ v.libraries.extend(installer_info.libraries.common)
+ v.libraries.extend(installer_info.libraries.client)
+ loader_lib = Library(
+ name=GradleSpecifier.from_string(entry["maven"]),
+ url="https://maven.quiltmc.org/repository/release",
+ )
+ v.libraries.append(loader_lib)
+
+ if entry["version"] in DISABLE_BEACON_VERSIONS:
+ if not v.additional_jvm_args:
+ v.additional_jvm_args = []
+ v.additional_jvm_args.append(DISABLE_BEACON_ARG)
+
+ return v, should_recommend
+
+
+def process_intermediary_version(entry) -> MetaVersion:
+ jar_info = load_jar_info(transform_maven_key(entry["maven"]))
+
+ v = MetaVersion(
+ name="Quilt Intermediary Mappings",
+ uid=INTERMEDIARY_COMPONENT,
+ version=entry["version"],
+ )
+ v.release_time = jar_info.release_time
+ v.requires = [Dependency(uid="net.minecraft", equals=entry["version"])]
+ v.order = 11
+ v.type = "release"
+ v.libraries = []
+ v.volatile = True
+ intermediary_lib = Library(
+ name=GradleSpecifier.from_string(entry["maven"]),
+ url="https://maven.quiltmc.org/repository/release",
+ )
+ v.libraries.append(intermediary_lib)
+ return v
+
+
+def main():
+ recommended_loader_versions = []
+ recommended_intermediary_versions = []
+
+ with open(
+ os.path.join(UPSTREAM_DIR, META_DIR, "loader.json"), "r", encoding="utf-8"
+ ) as f:
+ loader_version_index = json.load(f)
+ for entry in loader_version_index:
+ version = entry["version"]
+ print(f"Processing loader {version}")
+ try:
+ v, should_recommend = process_loader_version(entry)
+
+ if (
+ not recommended_loader_versions and should_recommend
+ ): # newest stable loader is recommended
+ recommended_loader_versions.append(version)
+
+ v.write(
+ os.path.join(LAUNCHER_DIR, LOADER_COMPONENT, f"{v.version}.json")
+ )
+ except Exception as e:
+ eprint("Failed to download %s" % version)
+ eprint("Error is %s" % e)
+ continue
+
+ if USE_QUILT_MAPPINGS:
+ with open(
+ os.path.join(UPSTREAM_DIR, META_DIR, "hashed.json"), "r", encoding="utf-8"
+ ) as f:
+ intermediary_version_index = json.load(f)
+ for entry in intermediary_version_index:
+ version = entry["version"]
+ print(f"Processing intermediary {version}")
+
+ try:
+ v = process_intermediary_version(entry)
+
+ recommended_intermediary_versions.append(
+ version
+ ) # all intermediaries are recommended
+
+ v.write(
+ os.path.join(
+ LAUNCHER_DIR, INTERMEDIARY_COMPONENT, f"{v.version}.json"
+ )
+ )
+ except Exception as e:
+ eprint("Failed to download %s" % version)
+ eprint("Error is %s" % e)
+ continue
+ package = MetaPackage(uid=LOADER_COMPONENT, name="Quilt Loader")
+ package.recommended = recommended_loader_versions
+ package.description = "The Quilt project is an open, community-driven modding toolchain designed primarily for Minecraft."
+ package.project_url = "https://quiltmc.org/"
+ package.authors = ["Quilt Project"]
+ package.write(os.path.join(LAUNCHER_DIR, LOADER_COMPONENT, "package.json"))
+
+ if USE_QUILT_MAPPINGS:
+ package = MetaPackage(
+ uid=INTERMEDIARY_COMPONENT, name="Quilt Intermediary Mappings"
+ )
+ package.recommended = recommended_intermediary_versions
+ package.description = "Intermediary mappings allow using Quilt Loader with mods for Minecraft in a more compatible manner."
+ package.project_url = "https://quiltmc.org/"
+ package.authors = ["Quilt Project"]
+ package.write(
+ os.path.join(LAUNCHER_DIR, INTERMEDIARY_COMPONENT, "package.json")
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/index.py b/meta/meta/run/index.py
new file mode 100755
index 0000000000..22abea8457
--- /dev/null
+++ b/meta/meta/run/index.py
@@ -0,0 +1,71 @@
+import hashlib
+import os
+from operator import attrgetter
+
+from meta.common import launcher_path, file_hash
+
+
+from meta.model import MetaVersion, MetaPackage
+from meta.model.index import (
+ MetaPackageIndex,
+ MetaVersionIndex,
+ MetaVersionIndexEntry,
+ MetaPackageIndexEntry,
+)
+
+LAUNCHER_DIR = launcher_path()
+
+
+# ignore these files when indexing versions
+ignore = {"index.json", "package.json", ".git", ".github"}
+
+# initialize output structures - package list level
+packages = MetaPackageIndex()
+
+# walk through all the package folders
+for package in sorted(os.listdir(LAUNCHER_DIR)):
+ if package in ignore:
+ continue
+
+ sharedData = MetaPackage.parse_file(
+ os.path.join(LAUNCHER_DIR, package, "package.json")
+ )
+ recommendedVersions = set()
+ if sharedData.recommended:
+ recommendedVersions = set(sharedData.recommended)
+
+ # initialize output structures - version list level
+ versionList = MetaVersionIndex(uid=package, name=sharedData.name)
+
+ # walk through all the versions of the package
+ for filename in os.listdir(LAUNCHER_DIR + "/%s" % package):
+ if filename in ignore:
+ continue
+ # parse and hash the version file
+ filepath = LAUNCHER_DIR + "/%s/%s" % (package, filename)
+ filehash = file_hash(filepath, hashlib.sha256)
+ versionFile = MetaVersion.parse_file(filepath)
+ is_recommended = versionFile.version in recommendedVersions
+
+ versionEntry = MetaVersionIndexEntry.from_meta_version(
+ versionFile, is_recommended, filehash
+ )
+
+ versionList.versions.append(versionEntry)
+
+ # sort the versions in descending order by time of release
+ versionList.versions = sorted(
+ versionList.versions, key=attrgetter("release_time"), reverse=True
+ )
+
+ # write the version index for the package
+ outFilePath = LAUNCHER_DIR + "/%s/index.json" % package
+ versionList.write(outFilePath)
+
+ # insert entry into the package index
+ packageEntry = MetaPackageIndexEntry(
+ uid=package, name=sharedData.name, sha256=file_hash(outFilePath, hashlib.sha256)
+ )
+ packages.packages.append(packageEntry)
+
+packages.write(os.path.join(LAUNCHER_DIR, "index.json"))
diff --git a/meta/meta/run/update_fabric.py b/meta/meta/run/update_fabric.py
new file mode 100755
index 0000000000..d19540b5e4
--- /dev/null
+++ b/meta/meta/run/update_fabric.py
@@ -0,0 +1,133 @@
+from collections import deque
+from multiprocessing import Pool
+import json
+import os
+import zipfile
+from datetime import datetime
+
+import requests
+
+from meta.common import (
+ upstream_path,
+ ensure_upstream_dir,
+ transform_maven_key,
+ default_session,
+)
+from meta.common.fabric import (
+ JARS_DIR,
+ INSTALLER_INFO_DIR,
+ META_DIR,
+ DATETIME_FORMAT_HTTP,
+)
+from meta.model.fabric import FabricJarInfo
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(JARS_DIR)
+ensure_upstream_dir(INSTALLER_INFO_DIR)
+ensure_upstream_dir(META_DIR)
+
+sess = default_session()
+
+
+def get_maven_url(maven_key, server, ext):
+ parts = maven_key.split(":", 3)
+ maven_ver_url = (
+ server + parts[0].replace(".", "/") + "/" + parts[1] + "/" + parts[2] + "/"
+ )
+ maven_url = maven_ver_url + parts[1] + "-" + parts[2] + ext
+ return maven_url
+
+
+def get_json_file(path, url):
+ with open(path, "w", encoding="utf-8") as f:
+ r = sess.get(url)
+ r.raise_for_status()
+ version_json = r.json()
+ json.dump(version_json, f, sort_keys=True, indent=4)
+ return version_json
+
+
+def head_file(url):
+ r = sess.head(url)
+ r.raise_for_status()
+ return r.headers
+
+
+def get_binary_file(path, url):
+ r = sess.get(url)
+ r.raise_for_status()
+ with open(path, "wb") as f:
+ for chunk in r.iter_content(chunk_size=128):
+ f.write(chunk)
+
+
+def compute_jar_file(path, url):
+ # These two approaches should result in the same metadata, except for the timestamp which might be a few minutes
+ # off for the fallback method
+ try:
+ # Let's not download a Jar file if we don't need to.
+ headers = head_file(url)
+ tstamp = datetime.strptime(headers["Last-Modified"], DATETIME_FORMAT_HTTP)
+ except requests.HTTPError:
+ # Just in case something changes in the future
+ print(f"Falling back to downloading jar for {url}")
+
+ jar_path = path + ".jar"
+ get_binary_file(jar_path, url)
+ tstamp = datetime.fromtimestamp(0)
+ with zipfile.ZipFile(jar_path) as jar:
+ allinfo = jar.infolist()
+ for info in allinfo:
+ tstamp_new = datetime(*info.date_time)
+ if tstamp_new > tstamp:
+ tstamp = tstamp_new
+
+ data = FabricJarInfo(release_time=tstamp)
+ data.write(path + ".json")
+
+
+def compute_jar_file_concurrent(it):
+ print(f"Processing {it['version']} ")
+ jar_maven_url = get_maven_url(it["maven"], "https://maven.fabricmc.net/", ".jar")
+ compute_jar_file(
+ os.path.join(UPSTREAM_DIR, JARS_DIR, transform_maven_key(it["maven"])),
+ jar_maven_url,
+ )
+ print(f"Processing {it['version']} Done")
+
+
+def get_json_file_concurrent(it):
+ print(f"Downloading JAR info for loader {it['version']} ")
+ maven_url = get_maven_url(it["maven"], "https://maven.fabricmc.net/", ".json")
+ get_json_file(
+ os.path.join(UPSTREAM_DIR, INSTALLER_INFO_DIR, f"{it['version']}.json"),
+ maven_url,
+ )
+ print(f"Downloading JAR info for loader {it['version']} Done")
+
+
+def main():
+ # get the version list for each component we are interested in
+ for component in ["intermediary", "loader"]:
+ index = get_json_file(
+ os.path.join(UPSTREAM_DIR, META_DIR, f"{component}.json"),
+ "https://meta.fabricmc.net/v2/versions/" + component,
+ )
+ with Pool(None) as pool:
+ deque(pool.imap_unordered(compute_jar_file_concurrent, index, 32), 0)
+
+ # for each loader, download installer JSON file from maven
+ with open(
+ os.path.join(UPSTREAM_DIR, META_DIR, "loader.json"), "r", encoding="utf-8"
+ ) as loaderVersionIndexFile:
+ loader_version_index = json.load(loaderVersionIndexFile)
+ with Pool(None) as pool:
+ deque(
+ pool.imap_unordered(get_json_file_concurrent, loader_version_index, 32),
+ 0,
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/update_forge.py b/meta/meta/run/update_forge.py
new file mode 100755
index 0000000000..c74865b31f
--- /dev/null
+++ b/meta/meta/run/update_forge.py
@@ -0,0 +1,419 @@
+"""
+Get the source files necessary for generating Forge versions
+"""
+
+import concurrent.futures
+import copy
+import hashlib
+import json
+import os
+import re
+import zipfile
+from contextlib import suppress
+from datetime import datetime
+from pathlib import Path
+from pprint import pprint
+
+from pydantic import ValidationError
+
+from meta.common import (
+ upstream_path,
+ ensure_upstream_dir,
+ default_session,
+ remove_files,
+ eprint,
+ file_hash,
+ get_file_sha1_from_file,
+)
+from meta.common.forge import (
+ JARS_DIR,
+ INSTALLER_INFO_DIR,
+ INSTALLER_MANIFEST_DIR,
+ VERSION_MANIFEST_DIR,
+ FILE_MANIFEST_DIR,
+ BAD_VERSIONS,
+ LEGACYINFO_FILE,
+)
+from meta.model.forge import (
+ ForgeFile,
+ ForgeEntry,
+ ForgeMCVersionInfo,
+ ForgeLegacyInfoList,
+ DerivedForgeIndex,
+ ForgeVersion,
+ ForgeInstallerProfile,
+ ForgeInstallerProfileV2,
+ InstallerInfo,
+ ForgeLegacyInfo,
+)
+from meta.common.http import download_binary_file
+from meta.model.mojang import MojangVersion
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(JARS_DIR)
+ensure_upstream_dir(INSTALLER_INFO_DIR)
+ensure_upstream_dir(INSTALLER_MANIFEST_DIR)
+ensure_upstream_dir(VERSION_MANIFEST_DIR)
+ensure_upstream_dir(FILE_MANIFEST_DIR)
+
+LEGACYINFO_PATH = os.path.join(UPSTREAM_DIR, LEGACYINFO_FILE)
+
+sess = default_session()
+
+
+def get_single_forge_files_manifest(longversion):
+ print(f"Getting Forge manifest for {longversion}")
+ path_thing = UPSTREAM_DIR + "/forge/files_manifests/%s.json" % longversion
+ files_manifest_file = Path(path_thing)
+ from_file = False
+ if files_manifest_file.is_file():
+ with open(path_thing, "r") as f:
+ files_json = json.load(f)
+ from_file = True
+ else:
+ file_url = (
+ "https://files.minecraftforge.net/net/minecraftforge/forge/%s/meta.json"
+ % longversion
+ )
+ r = sess.get(file_url)
+ r.raise_for_status()
+ files_json = r.json()
+
+ ret_dict = dict()
+
+ for classifier, extensionObj in files_json.get("classifiers").items():
+ assert type(classifier) == str
+ assert type(extensionObj) == dict
+
+ # assert len(extensionObj.items()) == 1
+ index = 0
+ count = 0
+ while index < len(extensionObj.items()):
+ mutable_copy = copy.deepcopy(extensionObj)
+ extension, hashtype = mutable_copy.popitem()
+ if not type(classifier) == str:
+ pprint(classifier)
+ pprint(extensionObj)
+ if not type(hashtype) == str:
+ pprint(classifier)
+ pprint(extensionObj)
+ print(
+ "%s: Skipping missing hash for extension %s:"
+ % (longversion, extension)
+ )
+ index += 1
+ continue
+ assert type(classifier) == str
+ processed_hash = re.sub(r"\W", "", hashtype)
+ if not len(processed_hash) == 32:
+ print(
+ "%s: Skipping invalid hash for extension %s:"
+ % (longversion, extension)
+ )
+ pprint(extensionObj)
+ index += 1
+ continue
+
+ file_obj = ForgeFile(
+ classifier=classifier, hash=processed_hash, extension=extension
+ )
+ if count == 0:
+ ret_dict[classifier] = file_obj
+ index += 1
+ count += 1
+ else:
+ print(
+ "%s: Multiple objects detected for classifier %s:"
+ % (longversion, classifier)
+ )
+ pprint(extensionObj)
+ assert False
+
+ if not from_file:
+ with open(path_thing, "w", encoding="utf-8") as f:
+ json.dump(files_json, f, sort_keys=True, indent=4)
+
+ return ret_dict
+
+
+def process_forge_version(version, jar_path):
+ installer_info_path = (
+ UPSTREAM_DIR + "/forge/installer_info/%s.json" % version.long_version
+ )
+ profile_path = (
+ UPSTREAM_DIR + "/forge/installer_manifests/%s.json" % version.long_version
+ )
+ version_file_path = (
+ UPSTREAM_DIR + "/forge/version_manifests/%s.json" % version.long_version
+ )
+
+ new_sha1 = None
+ sha1_file = jar_path + ".sha1"
+ fileSha1 = get_file_sha1_from_file(jar_path, sha1_file)
+ try:
+ rfile = sess.get(version.url() + ".sha1")
+ rfile.raise_for_status()
+ new_sha1 = rfile.text.strip()
+ if fileSha1 != new_sha1:
+ remove_files([jar_path, profile_path, installer_info_path, sha1_file])
+ except Exception as e:
+ eprint("Failed to check sha1 %s" % version.url())
+ eprint("Error is %s" % e)
+
+ installer_refresh_required = not os.path.isfile(profile_path) or not os.path.isfile(
+ installer_info_path
+ )
+
+ if installer_refresh_required:
+ # grab the installer if it's not there
+ if not os.path.isfile(jar_path):
+ eprint("Downloading %s" % version.url())
+ download_binary_file(sess, jar_path, version.url())
+ if new_sha1 is None:
+ try:
+ rfile = sess.get(version.url() + ".sha1")
+ rfile.raise_for_status()
+ new_sha1 = rfile.text.strip()
+ except Exception as e:
+ eprint("Failed to download new sha1 %s" % version.url())
+ eprint("Error is %s" % e)
+ if new_sha1 is not None: # this is in case the fetch failed
+ with open(sha1_file, "w") as file:
+ file.write(new_sha1)
+
+ eprint("Processing %s" % version.url())
+ # harvestables from the installer
+ if not os.path.isfile(profile_path):
+ print(jar_path)
+ with zipfile.ZipFile(jar_path) as jar:
+ with suppress(KeyError):
+ with jar.open("version.json") as profile_zip_entry:
+ version_data = profile_zip_entry.read()
+
+ # Process: does it parse?
+ MojangVersion.parse_raw(version_data)
+
+ with open(version_file_path, "wb") as versionJsonFile:
+ versionJsonFile.write(version_data)
+ versionJsonFile.close()
+
+ with jar.open("install_profile.json") as profile_zip_entry:
+ install_profile_data = profile_zip_entry.read()
+
+ # Process: does it parse?
+ is_parsable = False
+ exception = None
+ try:
+ ForgeInstallerProfile.parse_raw(install_profile_data)
+ is_parsable = True
+ except ValidationError as err:
+ exception = err
+ try:
+ ForgeInstallerProfileV2.parse_raw(install_profile_data)
+ is_parsable = True
+ except ValidationError as err:
+ exception = err
+
+ if not is_parsable:
+ if version.is_supported():
+ raise exception
+ else:
+ eprint(
+ "Version %s is not supported and won't be generated later."
+ % version.long_version
+ )
+
+ with open(profile_path, "wb") as profileFile:
+ profileFile.write(install_profile_data)
+ profileFile.close()
+
+ # installer info v1
+ if not os.path.isfile(installer_info_path):
+ installer_info = InstallerInfo()
+ installer_info.sha1hash = file_hash(jar_path, hashlib.sha1)
+ installer_info.sha256hash = file_hash(jar_path, hashlib.sha256)
+ installer_info.size = os.path.getsize(jar_path)
+ installer_info.write(installer_info_path)
+
+
+def main():
+ # get the remote version list fragments
+ r = sess.get(
+ "https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json"
+ )
+ r.raise_for_status()
+ main_json = r.json()
+ assert type(main_json) == dict
+
+ r = sess.get(
+ "https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"
+ )
+ r.raise_for_status()
+ promotions_json = r.json()
+ assert type(promotions_json) == dict
+
+ promoted_key_expression = re.compile(
+ "(?P<mc>[^-]+)-(?P<promotion>(latest)|(recommended))(-(?P<branch>[a-zA-Z0-9\\.]+))?"
+ )
+
+ recommended_set = set()
+
+ new_index = DerivedForgeIndex()
+
+ # FIXME: does not fully validate that the file has not changed format
+ # NOTE: For some insane reason, the format of the versions here is special. It having a branch at the end means it
+ # affects that particular branch.
+ # We don't care about Forge having branches.
+ # Therefore we only use the short version part for later identification and filter out the branch-specific
+ # promotions (among other errors).
+ print("Processing promotions:")
+ for promoKey, shortversion in promotions_json.get("promos").items():
+ match = promoted_key_expression.match(promoKey)
+ if not match:
+ print("Skipping promotion %s, the key did not parse:" % promoKey)
+ pprint(promoKey)
+ assert match
+ if not match.group("mc"):
+ print(
+ "Skipping promotion %s, because it has no Minecraft version." % promoKey
+ )
+ continue
+ if match.group("branch"):
+ print("Skipping promotion %s, because it on a branch only." % promoKey)
+ continue
+ elif match.group("promotion") == "recommended":
+ recommended_set.add(shortversion)
+ print("%s added to recommended set" % shortversion)
+ elif match.group("promotion") == "latest":
+ pass
+ else:
+ assert False
+
+ version_expression = re.compile(
+ "^(?P<mc>[0-9a-zA-Z_\\.]+)-(?P<ver>[0-9\\.]+\\.(?P<build>[0-9]+))(-(?P<branch>[a-zA-Z0-9\\.]+))?$"
+ )
+
+ print("")
+ print("Processing versions:")
+ for mc_version, value in main_json.items():
+ assert type(mc_version) == str
+ assert type(value) == list
+ for long_version in value:
+ assert type(long_version) == str
+ match = version_expression.match(long_version)
+ if not match:
+ pprint(long_version)
+ assert match
+ assert match.group("mc") == mc_version
+
+ files = get_single_forge_files_manifest(long_version)
+
+ build = int(match.group("build"))
+ version = match.group("ver")
+ branch = match.group("branch")
+
+ is_recommended = version in recommended_set
+
+ entry = ForgeEntry(
+ long_version=long_version,
+ mc_version=mc_version,
+ version=version,
+ build=build,
+ branch=branch,
+ # NOTE: we add this later after the fact. The forge promotions file lies about these.
+ latest=False,
+ recommended=is_recommended,
+ files=files,
+ )
+ new_index.versions[long_version] = entry
+ if not new_index.by_mc_version:
+ new_index.by_mc_version = dict()
+ if mc_version not in new_index.by_mc_version:
+ new_index.by_mc_version.setdefault(mc_version, ForgeMCVersionInfo())
+ new_index.by_mc_version[mc_version].versions.append(long_version)
+ # NOTE: we add this later after the fact. The forge promotions file lies about these.
+ # if entry.latest:
+ # new_index.by_mc_version[mc_version].latest = long_version
+ if entry.recommended:
+ new_index.by_mc_version[mc_version].recommended = long_version
+
+ print("")
+ print("Post processing promotions and adding missing 'latest':")
+ for mc_version, info in new_index.by_mc_version.items():
+ latest_version = info.versions[-1]
+ info.latest = latest_version
+ new_index.versions[latest_version].latest = True
+ print("Added %s as latest for %s" % (latest_version, mc_version))
+
+ print("")
+ print("Dumping index files...")
+
+ with open(UPSTREAM_DIR + "/forge/maven-metadata.json", "w", encoding="utf-8") as f:
+ json.dump(main_json, f, sort_keys=True, indent=4)
+
+ with open(UPSTREAM_DIR + "/forge/promotions_slim.json", "w", encoding="utf-8") as f:
+ json.dump(promotions_json, f, sort_keys=True, indent=4)
+
+ new_index.write(UPSTREAM_DIR + "/forge/derived_index.json")
+
+ legacy_info_list = ForgeLegacyInfoList()
+
+ print("Grabbing installers and dumping installer profiles...")
+ # get the installer jars - if needed - and get the installer profiles out of them
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ futures = []
+ for key, entry in new_index.versions.items():
+ eprint("Updating Forge %s" % key)
+ if entry.mc_version is None:
+ eprint("Skipping %d with invalid MC version" % entry.build)
+ continue
+
+ version = ForgeVersion(entry)
+ if version.url() is None:
+ eprint("Skipping %d with no valid files" % version.build)
+ continue
+ if version.long_version in BAD_VERSIONS:
+ eprint(f"Skipping bad version {version.long_version}")
+ continue
+
+ jar_path = os.path.join(UPSTREAM_DIR, JARS_DIR, version.filename())
+
+ if version.uses_installer():
+ futures.append(
+ executor.submit(process_forge_version, version, jar_path)
+ )
+ else:
+ # ignore the two versions without install manifests and jar mod class files
+ # TODO: fix those versions?
+ if version.mc_version_sane == "1.6.1":
+ continue
+
+ # only gather legacy info if it's missing
+ if not os.path.isfile(LEGACYINFO_PATH):
+ # grab the jar/zip if it's not there
+ if not os.path.isfile(jar_path):
+ download_binary_file(sess, jar_path, version.url())
+ # find the latest timestamp in the zip file
+ tstamp = datetime.fromtimestamp(0)
+ with zipfile.ZipFile(jar_path) as jar:
+ for info in jar.infolist():
+ tstamp_new = datetime(*info.date_time)
+ if tstamp_new > tstamp:
+ tstamp = tstamp_new
+ legacy_info = ForgeLegacyInfo()
+ legacy_info.release_time = tstamp
+ legacy_info.sha1 = file_hash(jar_path, hashlib.sha1)
+ legacy_info.sha256 = file_hash(jar_path, hashlib.sha256)
+ legacy_info.size = os.path.getsize(jar_path)
+ legacy_info_list.number[key] = legacy_info
+ for f in futures:
+ f.result()
+
+ # only write legacy info if it's missing
+ if not os.path.isfile(LEGACYINFO_PATH):
+ legacy_info_list.write(LEGACYINFO_PATH)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/update_java.py b/meta/meta/run/update_java.py
new file mode 100644
index 0000000000..80ca7b4a70
--- /dev/null
+++ b/meta/meta/run/update_java.py
@@ -0,0 +1,222 @@
+import os
+
+from meta.common import upstream_path, ensure_upstream_dir, default_session
+from meta.common.java import (
+ BASE_DIR,
+ ADOPTIUM_DIR,
+ OPENJ9_DIR,
+ AZUL_DIR,
+ ADOPTIUM_VERSIONS_DIR,
+ OPENJ9_VERSIONS_DIR,
+ AZUL_VERSIONS_DIR,
+)
+from meta.model.java import (
+ ADOPTIUM_API_BASE,
+ OPENJ9_API_BASE,
+ ADOPTX_API_AVAILABLE_RELEASES,
+ adoptxAPIFeatureReleasesUrl,
+ adoptiumAPIFeatureReleasesUrl,
+ openj9APIFeatureReleasesUrl,
+ AdoptxJvmImpl,
+ AdoptxVendor,
+ AdoptxImageType,
+ AdoptxAPIFeatureReleasesQuery,
+ AdoptxAvailableReleases,
+ AdoptxRelease,
+ AdoptxReleases,
+ azulApiPackagesUrl,
+ AzulApiPackagesQuery,
+ ZuluPackage,
+ ZuluPackageList,
+ AzulArchiveType,
+ AzulReleaseStatus,
+ AzulAvailabilityType,
+ AzulJavaPackageType,
+ azulApiPackageDetailUrl,
+ ZuluPackageDetail,
+ ZuluPackagesDetail,
+)
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(BASE_DIR)
+ensure_upstream_dir(ADOPTIUM_DIR)
+ensure_upstream_dir(OPENJ9_DIR)
+ensure_upstream_dir(AZUL_DIR)
+ensure_upstream_dir(ADOPTIUM_VERSIONS_DIR)
+ensure_upstream_dir(OPENJ9_VERSIONS_DIR)
+ensure_upstream_dir(AZUL_VERSIONS_DIR)
+
+
+sess = default_session()
+
+
+def main():
+ print("Getting Adoptium Release Manifests ")
+ r = sess.get(ADOPTX_API_AVAILABLE_RELEASES.format(base_url=ADOPTIUM_API_BASE))
+ r.raise_for_status()
+
+ available = AdoptxAvailableReleases(**r.json())
+
+ available_releases_file = os.path.join(
+ UPSTREAM_DIR, ADOPTIUM_DIR, "available_releases.json"
+ )
+ available.write(available_releases_file)
+
+ for feature in available.available_releases:
+ print("Getting Manifests for Adoptium feature release:", feature)
+
+ page_size = 10
+
+ releases_for_feature: list[AdoptxRelease] = []
+ page = 0
+ while True:
+ query = AdoptxAPIFeatureReleasesQuery(
+ image_type=AdoptxImageType.Jre,
+ page_size=page_size,
+ page=page,
+ jvm_impl=AdoptxJvmImpl.Hotspot,
+ vendor=AdoptxVendor.Eclipse,
+ )
+ api_call = adoptiumAPIFeatureReleasesUrl(feature, query=query)
+ print("Fetching JRE Page:", page, api_call)
+ r_rls = sess.get(api_call)
+ if r_rls.status_code == 404:
+ break
+ else:
+ r_rls.raise_for_status()
+
+ releases = list(AdoptxRelease(**rls) for rls in r_rls.json())
+ releases_for_feature.extend(releases)
+
+ if len(r_rls.json()) < page_size:
+ break
+ page += 1
+
+ print("Total Adoptium releases for feature:", len(releases_for_feature))
+ releases = AdoptxReleases(__root__=releases_for_feature)
+ feature_file = os.path.join(
+ UPSTREAM_DIR, ADOPTIUM_VERSIONS_DIR, f"java{feature}.json"
+ )
+ releases.write(feature_file)
+
+ print("Getting OpenJ9 Release Manifests ")
+ r = sess.get(ADOPTX_API_AVAILABLE_RELEASES.format(base_url=OPENJ9_API_BASE))
+ r.raise_for_status()
+
+ available = AdoptxAvailableReleases(**r.json())
+
+ available_releases_file = os.path.join(
+ UPSTREAM_DIR, OPENJ9_DIR, "available_releases.json"
+ )
+ available.write(available_releases_file)
+
+ for feature in available.available_releases:
+ print("Getting Manifests for OpenJ9 feature release:", feature)
+
+ page_size = 10
+
+ releases_for_feature: list[AdoptxRelease] = []
+ page = 0
+ while True:
+ query = AdoptxAPIFeatureReleasesQuery(
+ image_type=AdoptxImageType.Jre,
+ page_size=page_size,
+ page=page,
+ jvm_impl=AdoptxJvmImpl.OpenJ9,
+ vendor=AdoptxVendor.Ibm,
+ )
+ api_call = openj9APIFeatureReleasesUrl(feature, query=query)
+ print("Fetching JRE Page:", page, api_call)
+ r_rls = sess.get(api_call)
+ if r_rls.status_code == 404:
+ break
+ else:
+ r_rls.raise_for_status()
+
+ releases = list(AdoptxRelease(**rls) for rls in r_rls.json())
+ releases_for_feature.extend(releases)
+
+ if len(r_rls.json()) < page_size:
+ break
+ page += 1
+
+ print("Total OpenJ9 releases for feature:", len(releases_for_feature))
+ releases = AdoptxReleases(__root__=releases_for_feature)
+ if len(releases_for_feature) == 0:
+ continue
+ feature_file = os.path.join(
+ UPSTREAM_DIR, OPENJ9_VERSIONS_DIR, f"java{feature}.json"
+ )
+ releases.write(feature_file)
+
+ print("Getting Azul Release Manifests")
+ zulu_packages: list[ZuluPackage] = []
+ page = 1
+ page_size = 100
+ while True:
+
+ query = AzulApiPackagesQuery(
+ archive_type=AzulArchiveType.Zip,
+ release_status=AzulReleaseStatus.Ga,
+ availability_types=[AzulAvailabilityType.CA],
+ java_package_type=AzulJavaPackageType.Jre,
+ javafx_bundled=False,
+ latest=True,
+ page=page,
+ page_size=page_size,
+ )
+ api_call = azulApiPackagesUrl(query=query)
+
+ print("Processing Page:", page, api_call)
+
+ r = sess.get(api_call)
+ if r.status_code == 404:
+ break
+ else:
+ r.raise_for_status()
+
+ packages = list(ZuluPackage(**pkg) for pkg in r.json())
+ zulu_packages.extend(packages)
+ if len(packages) < page_size:
+ break
+ page += 1
+
+ print("Total Azul Packages:", len(zulu_packages))
+ packages = ZuluPackageList(__root__=zulu_packages)
+ azul_manifest_file = os.path.join(UPSTREAM_DIR, AZUL_DIR, "packages.json")
+ packages.write(azul_manifest_file)
+
+ azul_major_versions: dict[int, ZuluPackagesDetail] = {}
+
+ for _, pkg in packages:
+
+ major_version = pkg.java_version[0]
+ if major_version not in azul_major_versions:
+ azul_major_versions[major_version] = ZuluPackagesDetail(__root__=[])
+
+ pkg_file = os.path.join(
+ UPSTREAM_DIR, AZUL_VERSIONS_DIR, f"{pkg.package_uuid}.json"
+ )
+ if os.path.exists(pkg_file) and os.path.isfile(pkg_file):
+ pkg_detail = ZuluPackageDetail.parse_file(pkg_file)
+ azul_major_versions[major_version].append(pkg_detail)
+ else:
+
+ api_call = azulApiPackageDetailUrl(pkg.package_uuid)
+ print("Fetching Azul package manifest:", pkg.package_uuid)
+ r_pkg = sess.get(api_call)
+ r_pkg.raise_for_status()
+
+ pkg_detail = ZuluPackageDetail(**r_pkg.json())
+ pkg_detail.write(pkg_file)
+ azul_major_versions[major_version].append(pkg_detail)
+
+ for major in azul_major_versions:
+ major_file = os.path.join(UPSTREAM_DIR, AZUL_VERSIONS_DIR, f"java{major}.json")
+ azul_major_versions[major].write(major_file)
+
+
+if __name__ == "__main__":
+ main()
+#
diff --git a/meta/meta/run/update_liteloader.py b/meta/meta/run/update_liteloader.py
new file mode 100755
index 0000000000..383644754d
--- /dev/null
+++ b/meta/meta/run/update_liteloader.py
@@ -0,0 +1,37 @@
+import json
+import os
+
+from meta.common import upstream_path, ensure_upstream_dir, default_session
+from meta.common.liteloader import VERSIONS_FILE, BASE_DIR
+from meta.model.liteloader import LiteloaderIndex
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(BASE_DIR)
+
+sess = default_session()
+
+
+def main():
+ # get the remote version list
+ r = sess.get("http://dl.liteloader.com/versions/versions.json")
+ r.raise_for_status()
+
+ # make sure it's JSON
+ main_json = r.json()
+
+ # make sure we understand the schema
+ remote_versions = LiteloaderIndex.parse_obj(main_json)
+ parsed = remote_versions.json()
+ original = json.dumps(main_json, sort_keys=True, indent=4)
+ assert parsed == original
+
+ print("Successfully parsed index")
+ print(f"Last updated {remote_versions.meta.updated}")
+
+ # save the json it to file
+ remote_versions.write(os.path.join(UPSTREAM_DIR, VERSIONS_FILE))
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/update_mojang.py b/meta/meta/run/update_mojang.py
new file mode 100755
index 0000000000..c05b15ce46
--- /dev/null
+++ b/meta/meta/run/update_mojang.py
@@ -0,0 +1,199 @@
+import concurrent.futures
+import json
+import os
+import zipfile
+
+from meta.common import upstream_path, ensure_upstream_dir, default_session
+from meta.common.http import download_binary_file
+from meta.common.mojang import (
+ BASE_DIR,
+ VERSION_MANIFEST_FILE,
+ VERSIONS_DIR,
+ ASSETS_DIR,
+ STATIC_EXPERIMENTS_FILE,
+ STATIC_OLD_SNAPSHOTS_FILE,
+ JAVA_MANIFEST_FILE,
+)
+from meta.model.mojang import (
+ MojangIndexWrap,
+ MojangIndex,
+ ExperimentIndex,
+ ExperimentIndexWrap,
+ OldSnapshotIndexWrap,
+ OldSnapshotIndex,
+ JavaIndex,
+)
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(BASE_DIR)
+ensure_upstream_dir(VERSIONS_DIR)
+ensure_upstream_dir(ASSETS_DIR)
+
+sess = default_session()
+
+
+def fetch_zipped_version(path, url):
+ zip_path = f"{path}.zip"
+ download_binary_file(sess, zip_path, url)
+ with zipfile.ZipFile(zip_path) as z:
+ for info in z.infolist():
+ if info.filename.endswith(".json"):
+ print(f"Found {info.filename} as version json")
+ version_json = json.load(z.open(info))
+ break
+
+ assert version_json
+
+ version_json["type"] = "experiment"
+
+ with open(path, "w", encoding="utf-8") as f:
+ json.dump(version_json, f, sort_keys=True, indent=4)
+
+ return version_json
+
+
+def fetch_modified_version(path, version):
+ r = sess.get(version.url)
+ r.raise_for_status()
+ version_json = r.json()
+
+ version_json["releaseTime"] = version_json["releaseTime"] + "T00:00:00+02:00"
+ version_json["time"] = version_json["releaseTime"]
+
+ downloads = {
+ "client": {"url": version.jar, "sha1": version.sha1, "size": version.size}
+ }
+
+ version_json["downloads"] = downloads
+ version_json["type"] = "old_snapshot"
+
+ with open(path, "w", encoding="utf-8") as f:
+ json.dump(version_json, f, sort_keys=True, indent=4)
+
+ return version_json
+
+
+def fetch_version(path, url):
+ r = sess.get(url)
+ r.raise_for_status()
+ version_json = r.json()
+
+ with open(path, "w", encoding="utf-8") as f:
+ json.dump(version_json, f, sort_keys=True, indent=4)
+
+ return version_json
+
+
+MOJANG_JAVA_URL = "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"
+
+
+def update_javas():
+ r = sess.get(MOJANG_JAVA_URL)
+ r.raise_for_status()
+
+ remote_javas = JavaIndex(__root__=r.json())
+
+ java_manifest_path = os.path.join(UPSTREAM_DIR, JAVA_MANIFEST_FILE)
+
+ remote_javas.write(java_manifest_path)
+
+
+def fetch_version_concurrent(remote_versions, x):
+ version = remote_versions.versions[x]
+ print(
+ "Updating "
+ + version.id
+ + " to timestamp "
+ + version.release_time.strftime("%s")
+ )
+ fetch_version(os.path.join(UPSTREAM_DIR, VERSIONS_DIR, f"{x}.json"), version.url)
+
+
+def fetch_modified_version_concurrent(old_snapshots, x):
+ version = old_snapshots.versions[x]
+ old_snapshots_path = os.path.join(UPSTREAM_DIR, VERSIONS_DIR, f"{x}.json")
+
+ print("Updating old snapshot " + version.id)
+ if not os.path.isfile(old_snapshots_path):
+ fetch_modified_version(old_snapshots_path, version)
+ else:
+ print("Already have old snapshot " + version.id)
+
+
+def main():
+ # get the remote version list
+ r = sess.get("https://piston-meta.mojang.com/mc/game/version_manifest_v2.json")
+ r.raise_for_status()
+
+ remote_versions = MojangIndexWrap(MojangIndex(**r.json()))
+ remote_ids = set(remote_versions.versions.keys())
+
+ version_manifest_path = os.path.join(UPSTREAM_DIR, VERSION_MANIFEST_FILE)
+
+ if os.path.exists(version_manifest_path):
+ # get the local version list
+ current_versions = MojangIndexWrap(
+ MojangIndex.parse_file(version_manifest_path)
+ )
+ local_ids = set(current_versions.versions.keys())
+
+ # versions not present locally but present remotely are new
+ pending_ids = remote_ids.difference(local_ids)
+
+ for x in local_ids:
+ remote_version = remote_versions.versions[x]
+ local_version = current_versions.versions[x]
+ if remote_version.time > local_version.time:
+ pending_ids.add(x)
+ else:
+ pending_ids = remote_ids
+
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ futures = [
+ executor.submit(fetch_version_concurrent, remote_versions, x)
+ for x in pending_ids
+ ]
+ for f in futures:
+ f.result()
+
+ # deal with experimental snapshots separately
+ if os.path.exists(STATIC_EXPERIMENTS_FILE):
+ experiments = ExperimentIndexWrap(
+ ExperimentIndex.parse_file(STATIC_EXPERIMENTS_FILE)
+ )
+ experiment_ids = set(experiments.versions.keys())
+
+ for x in experiment_ids:
+ version = experiments.versions[x]
+ experiment_path = os.path.join(UPSTREAM_DIR, VERSIONS_DIR, f"{x}.json")
+
+ print("Updating experiment " + version.id)
+ if not os.path.isfile(experiment_path):
+ fetch_zipped_version(experiment_path, version.url)
+ else:
+ print("Already have experiment " + version.id)
+
+ # deal with old snapshots
+ if os.path.exists(STATIC_OLD_SNAPSHOTS_FILE):
+ old_snapshots = OldSnapshotIndexWrap(
+ OldSnapshotIndex.parse_file(STATIC_OLD_SNAPSHOTS_FILE)
+ )
+ old_snapshots_ids = set(old_snapshots.versions.keys())
+
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ futures = [
+ executor.submit(fetch_modified_version_concurrent, old_snapshots, x)
+ for x in old_snapshots_ids
+ ]
+ for f in futures:
+ f.result()
+
+ remote_versions.index.write(version_manifest_path)
+
+ print("Getting Mojang Java runtime manfest")
+ update_javas()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/update_neoforge.py b/meta/meta/run/update_neoforge.py
new file mode 100644
index 0000000000..9957aad1bd
--- /dev/null
+++ b/meta/meta/run/update_neoforge.py
@@ -0,0 +1,317 @@
+"""
+Get the source files necessary for generating Forge versions
+"""
+
+import concurrent.futures
+import copy
+import hashlib
+import json
+import os
+import re
+import zipfile
+from contextlib import suppress
+from datetime import datetime
+from pathlib import Path
+from pprint import pprint
+import urllib.parse
+
+from pydantic import ValidationError
+
+from meta.common import (
+ upstream_path,
+ ensure_upstream_dir,
+ default_session,
+ remove_files,
+ eprint,
+ file_hash,
+ get_file_sha1_from_file,
+)
+from meta.common.http import download_binary_file
+from meta.common.neoforge import (
+ JARS_DIR,
+ INSTALLER_INFO_DIR,
+ INSTALLER_MANIFEST_DIR,
+ VERSION_MANIFEST_DIR,
+ FILE_MANIFEST_DIR,
+)
+from meta.model.neoforge import (
+ NeoForgeFile,
+ NeoForgeEntry,
+ NeoForgeMCVersionInfo,
+ DerivedNeoForgeIndex,
+ NeoForgeVersion,
+ NeoForgeInstallerProfileV2,
+ InstallerInfo,
+)
+from meta.model.mojang import MojangVersion
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(JARS_DIR)
+ensure_upstream_dir(INSTALLER_INFO_DIR)
+ensure_upstream_dir(INSTALLER_MANIFEST_DIR)
+ensure_upstream_dir(VERSION_MANIFEST_DIR)
+ensure_upstream_dir(FILE_MANIFEST_DIR)
+
+sess = default_session()
+
+
+def find_nth(haystack, needle, n):
+ start = haystack.find(needle)
+ while start >= 0 and n > 1:
+ start = haystack.find(needle, start + len(needle))
+ n -= 1
+ return start
+
+
+def get_single_forge_files_manifest(longversion, artifact: str):
+ print(f"Getting NeoForge manifest for {longversion}")
+ path_thing = UPSTREAM_DIR + "/neoforge/files_manifests/%s.json" % longversion
+ files_manifest_file = Path(path_thing)
+ from_file = False
+ if files_manifest_file.is_file():
+ with open(path_thing, "r") as f:
+ files_json = json.load(f)
+ from_file = True
+ else:
+ file_url = (
+ f"https://maven.neoforged.net/api/maven/details/releases/net%2Fneoforged%2F{artifact}%2F"
+ + urllib.parse.quote(longversion)
+ )
+ r = sess.get(file_url)
+ r.raise_for_status()
+ files_json = r.json()
+
+ ret_dict = dict()
+
+ for file in files_json.get("files"):
+ assert type(file) == dict
+ name = file["name"]
+ prefix = f"{artifact}-{longversion}"
+ assert name.startswith(
+ prefix
+ ), f"{longversion} classifier {name} doesn't start with {prefix}"
+ file_name = name[len(prefix) :]
+ if file_name.startswith("-"):
+ file_name = file_name[1:]
+ if file_name.startswith("."):
+ continue
+
+ classifier, ext = os.path.splitext(file_name)
+
+ if ext in [".md5", ".sha1", ".sha256", ".sha512"]:
+ continue
+
+ # assert len(extensionObj.items()) == 1
+ file_obj = NeoForgeFile(
+ artifact=artifact, classifier=classifier, extension=ext[1:]
+ )
+ ret_dict[classifier] = file_obj
+
+ if not from_file:
+ Path(path_thing).parent.mkdir(parents=True, exist_ok=True)
+ with open(path_thing, "w", encoding="utf-8") as f:
+ json.dump(files_json, f, sort_keys=True, indent=4)
+
+ return ret_dict
+
+
+def process_neoforge_version(key, entry):
+ eprint("Updating NeoForge %s" % key)
+
+ version = NeoForgeVersion(entry)
+ if version.url() is None:
+ eprint("Skipping %d with no valid files" % version.build)
+ return
+ if not version.uses_installer():
+ eprint(f"version {version.long_version} does not use installer")
+ return
+
+ jar_path = os.path.join(UPSTREAM_DIR, JARS_DIR, version.filename())
+
+ installer_info_path = (
+ UPSTREAM_DIR + "/neoforge/installer_info/%s.json" % version.long_version
+ )
+ profile_path = (
+ UPSTREAM_DIR + "/neoforge/installer_manifests/%s.json" % version.long_version
+ )
+ version_file_path = (
+ UPSTREAM_DIR + "/neoforge/version_manifests/%s.json" % version.long_version
+ )
+
+ new_sha1 = None
+ sha1_file = jar_path + ".sha1"
+ fileSha1 = get_file_sha1_from_file(jar_path, sha1_file)
+ try:
+ rfile = sess.get(version.url() + ".sha1")
+ rfile.raise_for_status()
+ new_sha1 = rfile.text.strip()
+ if fileSha1 != new_sha1:
+ remove_files([jar_path, profile_path, installer_info_path, sha1_file])
+ except Exception as e:
+ eprint("Failed to check sha1 %s" % version.url())
+ eprint("Error is %s" % e)
+
+ installer_refresh_required = not os.path.isfile(profile_path) or not os.path.isfile(
+ installer_info_path
+ )
+
+ if installer_refresh_required:
+ # grab the installer if it's not there
+ if not os.path.isfile(jar_path):
+ eprint("Downloading %s" % version.url())
+ try:
+ Path(jar_path).parent.mkdir(parents=True, exist_ok=True)
+ download_binary_file(sess, jar_path, version.url())
+ except Exception as e:
+ eprint("Failed to download %s" % version.url())
+ eprint("Error is %s" % e)
+ return
+ if new_sha1 is None:
+ try:
+ rfile = sess.get(version.url() + ".sha1")
+ rfile.raise_for_status()
+ new_sha1 = rfile.text.strip()
+ except Exception as e:
+ eprint("Failed to download new sha1 %s" % version.url())
+ eprint("Error is %s" % e)
+ if new_sha1 is not None: # this is in case the fetch failed
+ with open(sha1_file, "w") as file:
+ file.write(new_sha1)
+
+ eprint("Processing %s" % version.url())
+ # harvestables from the installer
+ if not os.path.isfile(profile_path):
+ print(jar_path)
+ with zipfile.ZipFile(jar_path) as jar:
+ with suppress(KeyError):
+ with jar.open("version.json") as profile_zip_entry:
+ version_data = profile_zip_entry.read()
+
+ # Process: does it parse?
+ MojangVersion.parse_raw(version_data)
+
+ Path(version_file_path).parent.mkdir(parents=True, exist_ok=True)
+ with open(version_file_path, "wb") as versionJsonFile:
+ versionJsonFile.write(version_data)
+ versionJsonFile.close()
+
+ with jar.open("install_profile.json") as profile_zip_entry:
+ install_profile_data = profile_zip_entry.read()
+
+ # Process: does it parse?
+ is_parsable = False
+ exception = None
+ try:
+ NeoForgeInstallerProfileV2.parse_raw(install_profile_data)
+ is_parsable = True
+ except ValidationError as err:
+ exception = err
+
+ if not is_parsable:
+ if version.is_supported():
+ raise exception
+ else:
+ eprint(
+ "Version %s is not supported and won't be generated later."
+ % version.long_version
+ )
+
+ Path(profile_path).parent.mkdir(parents=True, exist_ok=True)
+ with open(profile_path, "wb") as profileFile:
+ profileFile.write(install_profile_data)
+ profileFile.close()
+
+ # installer info v1
+ if not os.path.isfile(installer_info_path):
+ installer_info = InstallerInfo()
+ installer_info.sha1hash = file_hash(jar_path, hashlib.sha1)
+ installer_info.sha256hash = file_hash(jar_path, hashlib.sha256)
+ installer_info.size = os.path.getsize(jar_path)
+ installer_info.write(installer_info_path)
+
+
+def main():
+ # get the 1.20.1 remote version list fragments
+ r = sess.get(
+ "https://maven.neoforged.net/api/maven/versions/releases/net%2Fneoforged%2Fforge"
+ )
+ r.raise_for_status()
+ main_json = r.json()["versions"]
+ assert type(main_json) == list
+
+ # get the new remote version list fragments
+ r = sess.get(
+ "https://maven.neoforged.net/api/maven/versions/releases/net%2Fneoforged%2Fneoforge"
+ )
+ r.raise_for_status()
+ new_main_json = r.json()["versions"]
+ assert type(new_main_json) == list
+
+ main_json += new_main_json
+
+ new_index = DerivedNeoForgeIndex()
+
+ # let's keep the regex here to remove the 1.20.1-
+ version_expression = re.compile(
+ r"^(?P<mc>[0-9a-zA-Z_\.]+)-(?P<ver>[0-9\.]+\.(?P<build>[0-9]+))(-(?P<branch>[a-zA-Z0-9\.]+))?$"
+ )
+
+ print("")
+ print("Processing versions:")
+ for long_version in main_json:
+ assert type(long_version) == str
+
+ legacyMatch = version_expression.match(long_version)
+ if legacyMatch:
+ version = legacyMatch.group("ver")
+ artifact = "forge"
+ else:
+ version = long_version
+ artifact = "neoforge"
+
+ try:
+ files = get_single_forge_files_manifest(long_version, artifact)
+ except:
+ continue
+
+ # TODO: what *is* recommended?
+ is_recommended = False
+
+ entry = NeoForgeEntry(
+ artifact=artifact,
+ long_version=long_version,
+ version=version,
+ # NOTE: we add this later after the fact. The forge promotions file lies about these.
+ latest=False,
+ recommended=is_recommended,
+ files=files,
+ )
+ new_index.versions[long_version] = entry
+
+ if entry.recommended:
+ new_index.recommended = long_version
+
+ print("")
+ print("Dumping index files...")
+
+ with open(
+ UPSTREAM_DIR + "/neoforge/maven-metadata.json", "w", encoding="utf-8"
+ ) as f:
+ json.dump(main_json, f, sort_keys=True, indent=4)
+
+ new_index.write(UPSTREAM_DIR + "/neoforge/derived_index.json")
+
+ print("Grabbing installers and dumping installer profiles...")
+ # get the installer jars - if needed - and get the installer profiles out of them
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ futures = [
+ executor.submit(process_neoforge_version, key, entry)
+ for key, entry in new_index.versions.items()
+ ]
+ for f in futures:
+ f.result()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/meta/run/update_quilt.py b/meta/meta/run/update_quilt.py
new file mode 100755
index 0000000000..e694fd7b46
--- /dev/null
+++ b/meta/meta/run/update_quilt.py
@@ -0,0 +1,131 @@
+import concurrent.futures
+import json
+import os
+import zipfile
+from datetime import datetime
+
+from meta.common import (
+ upstream_path,
+ ensure_upstream_dir,
+ transform_maven_key,
+ default_session,
+)
+from meta.common.quilt import JARS_DIR, INSTALLER_INFO_DIR, META_DIR, USE_QUILT_MAPPINGS
+from meta.model.fabric import FabricJarInfo
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(JARS_DIR)
+ensure_upstream_dir(INSTALLER_INFO_DIR)
+ensure_upstream_dir(META_DIR)
+
+sess = default_session()
+
+
+def get_maven_url(maven_key, server, ext):
+ parts = maven_key.split(":", 3)
+ maven_ver_url = (
+ server + parts[0].replace(".", "/") + "/" + parts[1] + "/" + parts[2] + "/"
+ )
+ maven_url = maven_ver_url + parts[1] + "-" + parts[2] + ext
+ return maven_url
+
+
+def get_json_file(path, url):
+ with open(path, "w", encoding="utf-8") as f:
+ r = sess.get(url)
+ r.raise_for_status()
+ print(f"QUILT DEBUG {r.headers}")
+ version_json = r.json()
+ json.dump(version_json, f, sort_keys=True, indent=4)
+ return version_json
+
+
+def head_file(url):
+ r = sess.head(url)
+ r.raise_for_status()
+ return r.headers
+
+
+def get_binary_file(path, url):
+ with open(path, "wb") as f:
+ r = sess.get(url)
+ r.raise_for_status()
+ for chunk in r.iter_content(chunk_size=128):
+ f.write(chunk)
+
+
+def compute_jar_file(path, url):
+ # NOTE: Quilt Meta does not make any guarantees about Last-Modified.
+ # Always download the JAR file instead
+ jar_path = path + ".jar"
+ get_binary_file(jar_path, url)
+ tstamp = datetime.fromtimestamp(0)
+ with zipfile.ZipFile(jar_path) as jar:
+ allinfo = jar.infolist()
+ for info in allinfo:
+ tstamp_new = datetime(*info.date_time)
+ if tstamp_new > tstamp:
+ tstamp = tstamp_new
+
+ data = FabricJarInfo(release_time=tstamp)
+ data.write(path + ".json")
+
+
+def compute_jar_file_concurrent(component, it):
+ print(f"Processing {component} {it['version']} ")
+ jar_maven_url = get_maven_url(
+ it["maven"], "https://maven.quiltmc.org/repository/release/", ".jar"
+ )
+ compute_jar_file(
+ os.path.join(UPSTREAM_DIR, JARS_DIR, transform_maven_key(it["maven"])),
+ jar_maven_url,
+ )
+ print(f"Processing {component} {it['version']} Done")
+
+
+def get_json_file_concurrent(it):
+ print(f"Downloading JAR info for loader {it['version']} ")
+ maven_url = get_maven_url(
+ it["maven"], "https://maven.quiltmc.org/repository/release/", ".json"
+ )
+ get_json_file(
+ os.path.join(UPSTREAM_DIR, INSTALLER_INFO_DIR, f"{it['version']}.json"),
+ maven_url,
+ )
+
+
+def main():
+ # get the version list for each component we are interested in
+ components = ["loader"]
+ if USE_QUILT_MAPPINGS:
+ components.append("hashed")
+ for component in components:
+ index = get_json_file(
+ os.path.join(UPSTREAM_DIR, META_DIR, f"{component}.json"),
+ "https://meta.quiltmc.org/v3/versions/" + component,
+ )
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ futures = [
+ executor.submit(compute_jar_file_concurrent, component, it)
+ for it in index
+ ]
+ for f in futures:
+ f.result()
+
+ # for each loader, download installer JSON file from maven
+ with open(
+ os.path.join(UPSTREAM_DIR, META_DIR, "loader.json"), "r", encoding="utf-8"
+ ) as loaderVersionIndexFile:
+ loader_version_index = json.load(loaderVersionIndexFile)
+ with concurrent.futures.ThreadPoolExecutor() as executor:
+ futures = [
+ executor.submit(get_json_file_concurrent, it)
+ for it in loader_version_index
+ ]
+ for f in futures:
+ f.result()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/nix/dev.nix b/meta/nix/dev.nix
new file mode 100644
index 0000000000..1ca4edfc91
--- /dev/null
+++ b/meta/nix/dev.nix
@@ -0,0 +1,35 @@
+{
+ perSystem = {
+ config,
+ pkgs,
+ self',
+ ...
+ }: {
+ pre-commit.settings = {
+ excludes = ["flake.lock"];
+ hooks = {
+ markdownlint.enable = true;
+
+ alejandra.enable = true;
+ deadnix.enable = true;
+ nil.enable = true;
+
+ black.enable = true;
+ };
+ };
+
+ devShells.default = pkgs.mkShell {
+ shellHook = ''
+ ${config.pre-commit.installationScript}
+ '';
+
+ buildInputs = with pkgs; [
+ poetry
+ ];
+
+ inputsFrom = [self'.packages.default];
+ };
+
+ formatter = pkgs.alejandra;
+ };
+}
diff --git a/meta/nix/nixos/default.nix b/meta/nix/nixos/default.nix
new file mode 100644
index 0000000000..c4aa24174b
--- /dev/null
+++ b/meta/nix/nixos/default.nix
@@ -0,0 +1,10 @@
+{self, ...}: {
+ flake.nixosModules = {
+ default = self.nixosModules.meta;
+ meta = {
+ imports = [self.nixosModules.metaBare];
+ nixpkgs.overlays = [self.overlays.default];
+ };
+ metaBare = ./meta.nix;
+ };
+}
diff --git a/meta/nix/nixos/meta.nix b/meta/nix/nixos/meta.nix
new file mode 100644
index 0000000000..c03d4e6e01
--- /dev/null
+++ b/meta/nix/nixos/meta.nix
@@ -0,0 +1,70 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}: let
+ inherit (lib) getExe getExe' mkEnableOption mkIf mkOption mkPackageOption types;
+
+ settingsFormat = pkgs.formats.keyValue {};
+
+ cfg = config.services.blockgame-meta;
+in {
+ options.services.blockgame-meta = {
+ enable = mkEnableOption "blockgame-meta service";
+
+ package = mkPackageOption pkgs "blockgame-meta" {};
+
+ settings = mkOption {
+ type = types.submodule {
+ freeformType = settingsFormat.type;
+ options = {
+ DEPLOY_TO_S3 = mkOption {
+ type = types.str;
+ default = "false";
+ };
+ DEPLOY_TO_FOLDER = mkOption {
+ type = types.str;
+ default = "false";
+ };
+ DEPLOY_TO_GIT = mkOption {
+ type = types.str;
+ default = "false";
+ };
+ };
+ };
+ };
+ };
+ config = mkIf cfg.enable {
+ users.users."blockgame-meta" = {
+ isSystemUser = true;
+ group = "blockgame-meta";
+ };
+
+ users.groups."blockgame-meta" = {};
+
+ systemd = {
+ services."blockgame-meta" = {
+ description = "blockgame metadata generator";
+ after = ["network-online.target"];
+ wants = ["network-online.target"];
+ serviceConfig = {
+ EnvironmentFile = [(settingsFormat.generate "blockgame-meta.env" cfg.settings)];
+ ExecStartPre = getExe' cfg.package "init";
+ ExecStart = getExe cfg.package;
+ StateDirectory = "blockgame-meta";
+ CacheDirectory = "blockgame-meta";
+ User = "blockgame-meta";
+ };
+ };
+
+ timers."blockgame-meta" = {
+ timerConfig = {
+ OnCalendar = "hourly";
+ RandomizedDelaySec = "5m";
+ };
+ wantedBy = ["timers.target"];
+ };
+ };
+ };
+}
diff --git a/meta/nix/packages.nix b/meta/nix/packages.nix
new file mode 100644
index 0000000000..4af7b97e5b
--- /dev/null
+++ b/meta/nix/packages.nix
@@ -0,0 +1,18 @@
+{inputs, ...}: {
+ imports = [inputs.flake-parts.flakeModules.easyOverlay];
+
+ perSystem = {
+ config,
+ final,
+ ...
+ }: {
+ packages = {
+ blockgame-meta = final.python3.pkgs.callPackage ./pkgs/blockgame-meta.nix {};
+ default = config.packages.blockgame-meta;
+ };
+
+ overlayAttrs = {
+ inherit (config.packages) blockgame-meta;
+ };
+ };
+}
diff --git a/meta/nix/pkgs/blockgame-meta.nix b/meta/nix/pkgs/blockgame-meta.nix
new file mode 100644
index 0000000000..8409c37cb4
--- /dev/null
+++ b/meta/nix/pkgs/blockgame-meta.nix
@@ -0,0 +1,70 @@
+{
+ lib,
+ buildPythonApplication,
+ poetry-core,
+ bash,
+ cachecontrol,
+ requests,
+ filelock,
+ git,
+ openssh,
+ packaging,
+ pydantic_1,
+ python,
+ rsync,
+}:
+buildPythonApplication {
+ pname = "blockgame-meta";
+ version = "unstable";
+
+ pyproject = true;
+
+ src = with lib.fileset;
+ toSource {
+ root = ../../.;
+ fileset = unions (map (fileName: ../../${fileName}) [
+ "meta"
+ "init.sh"
+ "pyproject.toml"
+ "poetry.lock"
+ "README.md"
+ "update.sh"
+ ]);
+ };
+
+ nativeBuildInputs = [
+ poetry-core
+ ];
+
+ buildInputs = [
+ bash
+ ];
+
+ propagatedBuildInputs = [
+ cachecontrol
+ requests
+ filelock
+ packaging
+ pydantic_1
+ ];
+
+ postInstall = ''
+ install -Dm755 $src/update.sh $out/bin/update
+ install -Dm755 $src/init.sh $out/bin/init
+
+ wrapProgram $out/bin/update \
+ --prefix PYTHONPATH : "$PYTHONPATH" \
+ --prefix PATH : ${lib.makeBinPath [git openssh python rsync]}
+
+ wrapProgram $out/bin/init \
+ --prefix PATH : ${lib.makeBinPath [git openssh]}
+ '';
+
+ meta = with lib; {
+ description = "Metadata generator for blockgame launcher.";
+ platforms = platforms.linux;
+ license = licenses.mspl;
+ maintainers = with maintainers; [Scrumplex];
+ mainProgram = "update";
+ };
+}
diff --git a/meta/poetry.lock b/meta/poetry.lock
new file mode 100644
index 0000000000..8bfa4c06b8
--- /dev/null
+++ b/meta/poetry.lock
@@ -0,0 +1,352 @@
+# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand.
+
+[[package]]
+name = "cachecontrol"
+version = "0.14.2"
+description = "httplib2 caching for requests"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "cachecontrol-0.14.2-py3-none-any.whl", hash = "sha256:ebad2091bf12d0d200dfc2464330db638c5deb41d546f6d7aca079e87290f3b0"},
+ {file = "cachecontrol-0.14.2.tar.gz", hash = "sha256:7d47d19f866409b98ff6025b6a0fca8e4c791fb31abbd95f622093894ce903a2"},
+]
+
+[package.dependencies]
+msgpack = ">=0.5.2,<2.0.0"
+requests = ">=2.16.0"
+
+[package.extras]
+dev = ["CacheControl[filecache,redis]", "build", "cherrypy", "codespell[tomli]", "furo", "mypy", "pytest", "pytest-cov", "ruff", "sphinx", "sphinx-copybutton", "tox", "types-redis", "types-requests"]
+filecache = ["filelock (>=3.8.0)"]
+redis = ["redis (>=2.10.5)"]
+
+[[package]]
+name = "certifi"
+version = "2024.2.2"
+description = "Python package for providing Mozilla's CA Bundle."
+optional = false
+python-versions = ">=3.6"
+groups = ["main"]
+files = [
+ {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"},
+ {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"},
+]
+
+[[package]]
+name = "charset-normalizer"
+version = "3.3.2"
+description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
+optional = false
+python-versions = ">=3.7.0"
+groups = ["main"]
+files = [
+ {file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
+ {file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
+ {file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
+ {file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
+ {file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
+ {file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
+ {file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
+ {file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
+]
+
+[[package]]
+name = "filelock"
+version = "3.16.1"
+description = "A platform independent file lock."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"},
+ {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"},
+]
+
+[package.extras]
+docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"]
+testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"]
+typing = ["typing-extensions (>=4.12.2) ; python_version < \"3.11\""]
+
+[[package]]
+name = "idna"
+version = "3.7"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+groups = ["main"]
+files = [
+ {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"},
+ {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"},
+]
+
+[[package]]
+name = "msgpack"
+version = "1.0.8"
+description = "MessagePack serializer"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:505fe3d03856ac7d215dbe005414bc28505d26f0c128906037e66d98c4e95868"},
+ {file = "msgpack-1.0.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6b7842518a63a9f17107eb176320960ec095a8ee3b4420b5f688e24bf50c53c"},
+ {file = "msgpack-1.0.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:376081f471a2ef24828b83a641a02c575d6103a3ad7fd7dade5486cad10ea659"},
+ {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e390971d082dba073c05dbd56322427d3280b7cc8b53484c9377adfbae67dc2"},
+ {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00e073efcba9ea99db5acef3959efa45b52bc67b61b00823d2a1a6944bf45982"},
+ {file = "msgpack-1.0.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:82d92c773fbc6942a7a8b520d22c11cfc8fd83bba86116bfcf962c2f5c2ecdaa"},
+ {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9ee32dcb8e531adae1f1ca568822e9b3a738369b3b686d1477cbc643c4a9c128"},
+ {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e3aa7e51d738e0ec0afbed661261513b38b3014754c9459508399baf14ae0c9d"},
+ {file = "msgpack-1.0.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:69284049d07fce531c17404fcba2bb1df472bc2dcdac642ae71a2d079d950653"},
+ {file = "msgpack-1.0.8-cp310-cp310-win32.whl", hash = "sha256:13577ec9e247f8741c84d06b9ece5f654920d8365a4b636ce0e44f15e07ec693"},
+ {file = "msgpack-1.0.8-cp310-cp310-win_amd64.whl", hash = "sha256:e532dbd6ddfe13946de050d7474e3f5fb6ec774fbb1a188aaf469b08cf04189a"},
+ {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9517004e21664f2b5a5fd6333b0731b9cf0817403a941b393d89a2f1dc2bd836"},
+ {file = "msgpack-1.0.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d16a786905034e7e34098634b184a7d81f91d4c3d246edc6bd7aefb2fd8ea6ad"},
+ {file = "msgpack-1.0.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2872993e209f7ed04d963e4b4fbae72d034844ec66bc4ca403329db2074377b"},
+ {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c330eace3dd100bdb54b5653b966de7f51c26ec4a7d4e87132d9b4f738220ba"},
+ {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:83b5c044f3eff2a6534768ccfd50425939e7a8b5cf9a7261c385de1e20dcfc85"},
+ {file = "msgpack-1.0.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1876b0b653a808fcd50123b953af170c535027bf1d053b59790eebb0aeb38950"},
+ {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:dfe1f0f0ed5785c187144c46a292b8c34c1295c01da12e10ccddfc16def4448a"},
+ {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3528807cbbb7f315bb81959d5961855e7ba52aa60a3097151cb21956fbc7502b"},
+ {file = "msgpack-1.0.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e2f879ab92ce502a1e65fce390eab619774dda6a6ff719718069ac94084098ce"},
+ {file = "msgpack-1.0.8-cp311-cp311-win32.whl", hash = "sha256:26ee97a8261e6e35885c2ecd2fd4a6d38252246f94a2aec23665a4e66d066305"},
+ {file = "msgpack-1.0.8-cp311-cp311-win_amd64.whl", hash = "sha256:eadb9f826c138e6cf3c49d6f8de88225a3c0ab181a9b4ba792e006e5292d150e"},
+ {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:114be227f5213ef8b215c22dde19532f5da9652e56e8ce969bf0a26d7c419fee"},
+ {file = "msgpack-1.0.8-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d661dc4785affa9d0edfdd1e59ec056a58b3dbb9f196fa43587f3ddac654ac7b"},
+ {file = "msgpack-1.0.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d56fd9f1f1cdc8227d7b7918f55091349741904d9520c65f0139a9755952c9e8"},
+ {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0726c282d188e204281ebd8de31724b7d749adebc086873a59efb8cf7ae27df3"},
+ {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8db8e423192303ed77cff4dce3a4b88dbfaf43979d280181558af5e2c3c71afc"},
+ {file = "msgpack-1.0.8-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99881222f4a8c2f641f25703963a5cefb076adffd959e0558dc9f803a52d6a58"},
+ {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b5505774ea2a73a86ea176e8a9a4a7c8bf5d521050f0f6f8426afe798689243f"},
+ {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ef254a06bcea461e65ff0373d8a0dd1ed3aa004af48839f002a0c994a6f72d04"},
+ {file = "msgpack-1.0.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e1dd7839443592d00e96db831eddb4111a2a81a46b028f0facd60a09ebbdd543"},
+ {file = "msgpack-1.0.8-cp312-cp312-win32.whl", hash = "sha256:64d0fcd436c5683fdd7c907eeae5e2cbb5eb872fafbc03a43609d7941840995c"},
+ {file = "msgpack-1.0.8-cp312-cp312-win_amd64.whl", hash = "sha256:74398a4cf19de42e1498368c36eed45d9528f5fd0155241e82c4082b7e16cffd"},
+ {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ceea77719d45c839fd73abcb190b8390412a890df2f83fb8cf49b2a4b5c2f40"},
+ {file = "msgpack-1.0.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ab0bbcd4d1f7b6991ee7c753655b481c50084294218de69365f8f1970d4c151"},
+ {file = "msgpack-1.0.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1cce488457370ffd1f953846f82323cb6b2ad2190987cd4d70b2713e17268d24"},
+ {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3923a1778f7e5ef31865893fdca12a8d7dc03a44b33e2a5f3295416314c09f5d"},
+ {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a22e47578b30a3e199ab067a4d43d790249b3c0587d9a771921f86250c8435db"},
+ {file = "msgpack-1.0.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd739c9251d01e0279ce729e37b39d49a08c0420d3fee7f2a4968c0576678f77"},
+ {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:d3420522057ebab1728b21ad473aa950026d07cb09da41103f8e597dfbfaeb13"},
+ {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5845fdf5e5d5b78a49b826fcdc0eb2e2aa7191980e3d2cfd2a30303a74f212e2"},
+ {file = "msgpack-1.0.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6a0e76621f6e1f908ae52860bdcb58e1ca85231a9b0545e64509c931dd34275a"},
+ {file = "msgpack-1.0.8-cp38-cp38-win32.whl", hash = "sha256:374a8e88ddab84b9ada695d255679fb99c53513c0a51778796fcf0944d6c789c"},
+ {file = "msgpack-1.0.8-cp38-cp38-win_amd64.whl", hash = "sha256:f3709997b228685fe53e8c433e2df9f0cdb5f4542bd5114ed17ac3c0129b0480"},
+ {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f51bab98d52739c50c56658cc303f190785f9a2cd97b823357e7aeae54c8f68a"},
+ {file = "msgpack-1.0.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:73ee792784d48aa338bba28063e19a27e8d989344f34aad14ea6e1b9bd83f596"},
+ {file = "msgpack-1.0.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f9904e24646570539a8950400602d66d2b2c492b9010ea7e965025cb71d0c86d"},
+ {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e75753aeda0ddc4c28dce4c32ba2f6ec30b1b02f6c0b14e547841ba5b24f753f"},
+ {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbf059fb4b7c240c873c1245ee112505be27497e90f7c6591261c7d3c3a8228"},
+ {file = "msgpack-1.0.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4916727e31c28be8beaf11cf117d6f6f188dcc36daae4e851fee88646f5b6b18"},
+ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7938111ed1358f536daf311be244f34df7bf3cdedb3ed883787aca97778b28d8"},
+ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:493c5c5e44b06d6c9268ce21b302c9ca055c1fd3484c25ba41d34476c76ee746"},
+ {file = "msgpack-1.0.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fbb160554e319f7b22ecf530a80a3ff496d38e8e07ae763b9e82fadfe96f273"},
+ {file = "msgpack-1.0.8-cp39-cp39-win32.whl", hash = "sha256:f9af38a89b6a5c04b7d18c492c8ccf2aee7048aff1ce8437c4683bb5a1df893d"},
+ {file = "msgpack-1.0.8-cp39-cp39-win_amd64.whl", hash = "sha256:ed59dd52075f8fc91da6053b12e8c89e37aa043f8986efd89e61fae69dc1b011"},
+ {file = "msgpack-1.0.8.tar.gz", hash = "sha256:95c02b0e27e706e48d0e5426d1710ca78e0f0628d6e89d5b5a5b91a5f12274f3"},
+]
+
+[[package]]
+name = "packaging"
+version = "25.0"
+description = "Core utilities for Python packages"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"},
+ {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"},
+]
+
+[[package]]
+name = "pydantic"
+version = "1.10.26"
+description = "Data validation and settings management using python type hints"
+optional = false
+python-versions = ">=3.7"
+groups = ["main"]
+files = [
+ {file = "pydantic-1.10.26-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f7ae36fa0ecef8d39884120f212e16c06bb096a38f523421278e2f39c1784546"},
+ {file = "pydantic-1.10.26-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d95a76cf503f0f72ed7812a91de948440b2bf564269975738a4751e4fadeb572"},
+ {file = "pydantic-1.10.26-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a943ce8e00ad708ed06a1d9df5b4fd28f5635a003b82a4908ece6f24c0b18464"},
+ {file = "pydantic-1.10.26-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:465ad8edb29b15c10b779b16431fe8e77c380098badf6db367b7a1d3e572cf53"},
+ {file = "pydantic-1.10.26-cp310-cp310-win_amd64.whl", hash = "sha256:80e6be6272839c8a7641d26ad569ab77772809dd78f91d0068dc0fc97f071945"},
+ {file = "pydantic-1.10.26-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:116233e53889bcc536f617e38c1b8337d7fa9c280f0fd7a4045947515a785637"},
+ {file = "pydantic-1.10.26-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c3cfdd361addb6eb64ccd26ac356ad6514cee06a61ab26b27e16b5ed53108f77"},
+ {file = "pydantic-1.10.26-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0e4451951a9a93bf9a90576f3e25240b47ee49ab5236adccb8eff6ac943adf0f"},
+ {file = "pydantic-1.10.26-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9858ed44c6bea5f29ffe95308db9e62060791c877766c67dd5f55d072c8612b5"},
+ {file = "pydantic-1.10.26-cp311-cp311-win_amd64.whl", hash = "sha256:ac1089f723e2106ebde434377d31239e00870a7563245072968e5af5cc4d33df"},
+ {file = "pydantic-1.10.26-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:468d5b9cacfcaadc76ed0a4645354ab6f263ec01a63fb6d05630ea1df6ae453f"},
+ {file = "pydantic-1.10.26-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2c1b0b914be31671000ca25cf7ea17fcaaa68cfeadf6924529c5c5aa24b7ab1f"},
+ {file = "pydantic-1.10.26-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:15b13b9f8ba8867095769e1156e0d7fbafa1f65b898dd40fd1c02e34430973cb"},
+ {file = "pydantic-1.10.26-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad7025ca324ae263d4313998e25078dcaec5f9ed0392c06dedb57e053cc8086b"},
+ {file = "pydantic-1.10.26-cp312-cp312-win_amd64.whl", hash = "sha256:4482b299874dabb88a6c3759e3d85c6557c407c3b586891f7d808d8a38b66b9c"},
+ {file = "pydantic-1.10.26-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1ae7913bb40a96c87e3d3f6fe4e918ef53bf181583de4e71824360a9b11aef1c"},
+ {file = "pydantic-1.10.26-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8154c13f58d4de5d3a856bb6c909c7370f41fb876a5952a503af6b975265f4ba"},
+ {file = "pydantic-1.10.26-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f8af0507bf6118b054a9765fb2e402f18a8b70c964f420d95b525eb711122d62"},
+ {file = "pydantic-1.10.26-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:dcb5a7318fb43189fde6af6f21ac7149c4bcbcfffc54bc87b5becddc46084847"},
+ {file = "pydantic-1.10.26-cp313-cp313-win_amd64.whl", hash = "sha256:71cde228bc0600cf8619f0ee62db050d1880dcc477eba0e90b23011b4ee0f314"},
+ {file = "pydantic-1.10.26-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6b40730cc81d53d515dc0b8bb5c9b43fadb9bed46de4a3c03bd95e8571616dba"},
+ {file = "pydantic-1.10.26-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c3bbb9c0eecdf599e4db9b372fa9cc55be12e80a0d9c6d307950a39050cb0e37"},
+ {file = "pydantic-1.10.26-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc2e3fe7bc4993626ef6b6fa855defafa1d6f8996aa1caef2deb83c5ac4d043a"},
+ {file = "pydantic-1.10.26-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:36d9e46b588aaeb1dcd2409fa4c467fe0b331f3cc9f227b03a7a00643704e962"},
+ {file = "pydantic-1.10.26-cp314-cp314-win_amd64.whl", hash = "sha256:81ce3c8616d12a7be31b4aadfd3434f78f6b44b75adbfaec2fe1ad4f7f999b8c"},
+ {file = "pydantic-1.10.26-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bc5c91a3b3106caf07ac6735ec6efad8ba37b860b9eb569923386debe65039ad"},
+ {file = "pydantic-1.10.26-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dde599e0388e04778480d57f49355c9cc7916de818bf674de5d5429f2feebfb6"},
+ {file = "pydantic-1.10.26-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8be08b5cfe88e58198722861c7aab737c978423c3a27300911767931e5311d0d"},
+ {file = "pydantic-1.10.26-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0141f4bafe5eda539d98c9755128a9ea933654c6ca4306b5059fc87a01a38573"},
+ {file = "pydantic-1.10.26-cp38-cp38-win_amd64.whl", hash = "sha256:eb664305ffca8a9766a8629303bb596607d77eae35bb5f32ff9245984881b638"},
+ {file = "pydantic-1.10.26-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:502b9d30d18a2dfaf81b7302f6ba0e5853474b1c96212449eb4db912cb604b7d"},
+ {file = "pydantic-1.10.26-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0d8f6087bf697dec3bf7ffcd7fe8362674f16519f3151789f33cbe8f1d19fc15"},
+ {file = "pydantic-1.10.26-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dd40a99c358419910c85e6f5d22f9c56684c25b5e7abc40879b3b4a52f34ae90"},
+ {file = "pydantic-1.10.26-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:ce3293b86ca9f4125df02ff0a70be91bc7946522467cbd98e7f1493f340616ba"},
+ {file = "pydantic-1.10.26-cp39-cp39-win_amd64.whl", hash = "sha256:1a4e3062b71ab1d5df339ba12c48f9ed5817c5de6cb92a961dd5c64bb32e7b96"},
+ {file = "pydantic-1.10.26-py3-none-any.whl", hash = "sha256:c43ad70dc3ce7787543d563792426a16fd7895e14be4b194b5665e36459dd917"},
+ {file = "pydantic-1.10.26.tar.gz", hash = "sha256:8c6aa39b494c5af092e690127c283d84f363ac36017106a9e66cb33a22ac412e"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.2.0"
+
+[package.extras]
+dotenv = ["python-dotenv (>=0.10.4)"]
+email = ["email-validator (>=1.0.3)"]
+
+[[package]]
+name = "requests"
+version = "2.32.4"
+description = "Python HTTP for Humans."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"},
+ {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"},
+]
+
+[package.dependencies]
+certifi = ">=2017.4.17"
+charset_normalizer = ">=2,<4"
+idna = ">=2.5,<4"
+urllib3 = ">=1.21.1,<3"
+
+[package.extras]
+socks = ["PySocks (>=1.5.6,!=1.5.7)"]
+use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.11.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"},
+ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"},
+]
+
+[[package]]
+name = "urllib3"
+version = "2.2.1"
+description = "HTTP library with thread-safe connection pooling, file post, and more."
+optional = false
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+ {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
+]
+
+[package.extras]
+brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""]
+h2 = ["h2 (>=4,<5)"]
+socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
+zstd = ["zstandard (>=0.18.0)"]
+
+[metadata]
+lock-version = "2.1"
+python-versions = "^3.8"
+content-hash = "2ed3cbaf03c118578cad2e4ea78c7baefeb741fae05c96472df8a4a59d97a9ae"
diff --git a/meta/public/.keep b/meta/public/.keep
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/meta/public/.keep
diff --git a/meta/pyproject.toml b/meta/pyproject.toml
new file mode 100644
index 0000000000..295d05a859
--- /dev/null
+++ b/meta/pyproject.toml
@@ -0,0 +1,39 @@
+[tool.poetry]
+name = "meta"
+version = "0.0.1"
+description = "Prism Launcher meta generator"
+authors = ["Sefa Eyeoglu <contact@scrumplex.net>"]
+license = "MS-PL"
+readme = "README.md"
+repository = "https://github.com/PrismLauncher/meta"
+documentation = "https://github.com/PrismLauncher/meta"
+keywords = ["metadata", "prism", "launcher"]
+
+[tool.poetry.scripts]
+generateFabric = "meta.run.generate_fabric:main"
+generateForge = "meta.run.generate_forge:main"
+generateLiteloader = "meta.run.generate_liteloader:main"
+generateMojang = "meta.run.generate_mojang:main"
+generateNeoForge = "meta.run.generate_neoforge:main"
+generateQuilt = "meta.run.generate_quilt:main"
+generateJava = "meta.run.generate_java:main"
+updateFabric = "meta.run.update_fabric:main"
+updateForge = "meta.run.update_forge:main"
+updateLiteloader = "meta.run.update_liteloader:main"
+updateMojang = "meta.run.update_mojang:main"
+updateNeoForge = "meta.run.update_neoforge:main"
+updateQuilt = "meta.run.update_quilt:main"
+updateJava = "meta.run.update_java:main"
+index = "meta.run.index:main"
+
+[tool.poetry.dependencies]
+python = "^3.8"
+cachecontrol = "^0.14.0"
+requests = "^2.31.0"
+filelock = "^3.13.1"
+packaging = "^25.0"
+pydantic = "^1.10.13"
+
+[build-system]
+requires = ["poetry-core>=1.0.0"]
+build-backend = "poetry.core.masonry.api"
diff --git a/meta/renovate.json b/meta/renovate.json
new file mode 100644
index 0000000000..39a2b6e9a5
--- /dev/null
+++ b/meta/renovate.json
@@ -0,0 +1,6 @@
+{
+ "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+ "extends": [
+ "config:base"
+ ]
+}
diff --git a/meta/update.sh b/meta/update.sh
new file mode 100755
index 0000000000..15df54e2b0
--- /dev/null
+++ b/meta/update.sh
@@ -0,0 +1,92 @@
+#!/usr/bin/env bash
+
+set -x
+
+if [ -f config.sh ]; then
+ source config.sh
+fi
+
+export META_CACHE_DIR=${CACHE_DIRECTORY:-./caches}
+export META_UPSTREAM_DIR=${META_UPSTREAM_DIR:-${STATE_DIRECTORY:-.}/upstream}
+export META_LAUNCHER_DIR=${META_LAUNCHER_DIR:-${STATE_DIRECTORY:-.}/launcher}
+
+function fail_in() {
+ upstream_git reset --hard HEAD
+ exit 1
+}
+
+function fail_out() {
+ launcher_git reset --hard HEAD
+ exit 1
+}
+
+function upstream_git() {
+ git -C "${META_UPSTREAM_DIR}" "$@"
+}
+
+function launcher_git() {
+ git -C "${META_LAUNCHER_DIR}" "$@"
+}
+
+# make sure we *could* push to our repo
+
+currentDate=$(date -I)
+
+upstream_git reset --hard HEAD || exit 1
+upstream_git pull
+
+python -m meta.run.update_mojang || fail_in
+python -m meta.run.update_forge || fail_in
+python -m meta.run.update_neoforge || fail_in
+python -m meta.run.update_fabric || fail_in
+python -m meta.run.update_quilt || fail_in
+python -m meta.run.update_liteloader || fail_in
+python -m meta.run.update_java || fail_in
+
+if [ "${DEPLOY_TO_GIT}" = true ]; then
+ upstream_git add mojang/version_manifest_v2.json mojang/java_all.json mojang/versions/* || fail_in
+ upstream_git add forge/*.json forge/version_manifests/*.json forge/installer_manifests/*.json forge/files_manifests/*.json forge/installer_info/*.json forge/jars/*.sha1 || fail_in
+ upstream_git add neoforge/*.json neoforge/version_manifests/*.json neoforge/installer_manifests/*.json neoforge/files_manifests/*.json neoforge/installer_info/*.json neoforge/jars/*.sha1 || fail_in
+ upstream_git add fabric/loader-installer-json/*.json fabric/meta-v2/*.json fabric/jars/*.json || fail_in
+ upstream_git add quilt/loader-installer-json/*.json quilt/meta-v3/*.json quilt/jars/*.json || fail_in
+ upstream_git add liteloader/*.json || fail_in
+ upstream_git add java_runtime/adoptium/available_releases.json java_runtime/adoptium/versions/*.json java_runtime/azul/packages.json java_runtime/azul/versions/*.json java_runtime/ibm/available_releases.json java_runtime/ibm/versions/*.json || fail_in
+ if ! upstream_git diff --cached --exit-code; then
+ upstream_git commit -a -m "Update ${currentDate}" || fail_in
+ upstream_git push || exit 1
+ fi
+fi
+
+launcher_git reset --hard HEAD || exit 1
+launcher_git pull
+
+python -m meta.run.generate_mojang || fail_out
+python -m meta.run.generate_forge || fail_out
+python -m meta.run.generate_neoforge || fail_out
+python -m meta.run.generate_fabric || fail_out
+python -m meta.run.generate_quilt || fail_out
+python -m meta.run.generate_liteloader || fail_out
+python -m meta.run.generate_java || fail_out
+python -m meta.run.index || fail_out
+
+if [ "${DEPLOY_TO_GIT}" = true ]; then
+ launcher_git add index.json org.lwjgl/* org.lwjgl3/* net.minecraft/* || fail_out
+ launcher_git add net.minecraftforge/* || fail_out
+ launcher_git add net.neoforged/* || fail_out
+ launcher_git add net.fabricmc.fabric-loader/* net.fabricmc.intermediary/* || fail_out
+ launcher_git add org.quiltmc.quilt-loader/* || fail_out # TODO: add Quilt hashed, once it is actually used
+ launcher_git add com.mumfrey.liteloader/* || fail_out
+ launcher_git add net.minecraft.java/* net.adoptium.java/* com.azul.java/* com.ibm.java/* || fail_out
+
+ if ! launcher_git diff --cached --exit-code; then
+ launcher_git commit -a -m "Update ${currentDate}" || fail_out
+ launcher_git push || exit 1
+ fi
+fi
+
+if [ "${DEPLOY_TO_FOLDER}" = true ]; then
+ echo "Deploying to ${DEPLOY_FOLDER}"
+ rsync -rvog --chown="${DEPLOY_FOLDER_USER}:${DEPLOY_FOLDER_GROUP}" --exclude=.git "${META_LAUNCHER_DIR}/" "${DEPLOY_FOLDER}"
+fi
+
+exit 0