#!/bin/sh set -e lower() { echo "$1" | tr '[:upper:]' '[:lower:]' } upper() { echo "$1" | tr '[:lower:]' '[:upper:]' } # global MC_TYPE="$(lower "${MC_TYPE:-vanilla}")" MC_VERSION="$(lower "${MC_VERSION:-latest}")" # papermc PAPERMC_BUILD="$(lower "${PAPERMC_BUILD:-latest}")" # fabric FABRIC_LOADER="$(lower "${FABRIC_LOADER:-latest}")" FABRIC_INSTALLER="$(lower "${FABRIC_INSTALLER:-latest}")" # forge FORGE_VERSION="$(lower "${FORGE_VERSION:-recommended}")" # other QUIET=1 # all output ALL=0 req() { res=$(curl --fail --silent "$1") code=$? if [ $code -ne 0 ] || [ "$res" = "" ]; then echo "null"; else echo "$res"; fi } error() { printf '\x1b[31m[ERROR]\t\x1b[0m%s\n' "$*" > /dev/stderr exit 1; } log() { if [ "$QUIET" -eq 0 ]; then printf '\x1b[0m[LOG]\t%s\n' "$*" > /dev/stderr fi } index_array() { array="$1" key="$2" type="$3" if [ "$key" = "latest" ]; then index=$(echo "$array" | jq ". | index( last )"); else index=$(echo "$array" | jq ". | index( \"$key\" )"); fi if [ "$index" = "null" ]; then error "Invalid $type: $key" else echo "$array" | jq -r ".[$index]"; fi } #https://api.papermc.io/v2/projects/velocity/versions/3.3.0-SNAPSHOT/ papermc() { api="https://api.papermc.io/v2/projects" log "Using papermc api v2" get_version() { log "Getting VERSION for '$MC_TYPE'" versions=$(req "$api/$MC_TYPE" | jq -r '.versions') if [ "$versions" = "null" ]; then error "Invalid TYPE: $MC_TYPE (no versions)" fi MC_VERSION=$(index_array "$versions" "$MC_VERSION" "VERSION") log "VERSION: $MC_VERSION" } get_build() { log "Getting BUILD for '$MC_TYPE@$MC_VERSION'" builds=$(req "$api/$MC_TYPE/versions/$MC_VERSION" | jq -r ".builds") if [ "$builds" = "null" ]; then error "Invalid VERSION: $MC_TYPE@$MC_TYPE (no builds)" fi PAPERMC_BUILD=$(index_array "$builds" "$PAPERMC_BUILD" "BUILD") log "BUILD: $PAPERMC_BUILD" } get_version get_build name="$MC_TYPE-$MC_VERSION-$PAPERMC_BUILD.jar" url="$api/$MC_TYPE/versions/$MC_VERSION/builds/$PAPERMC_BUILD/downloads/$name" if [ $ALL -eq 1 ]; then echo "JAR_NAME=$name" echo "JAR_URL=$url" echo "MC_TYPE=$MC_TYPE" echo "MC_VERSION=$MC_VERSION" echo "PAPERMC_BUILD=$PAPERMC_BUILD" else echo "$url" fi } fabric() { api="https://meta.fabricmc.net/v2/versions" log "Using fabric api v2" get_fabric_impl() { type="$1" value="$2" res="" if [ "$value" = "latest" ]; then res=$(req "$api/$type" | jq -r 'map(select(.stable == true) | .version) | reverse') else res=$(req "$api/$type" | jq -r 'map(.version) | reverse') fi; echo $res; } get_game() { log "Getting VERSION for '$MC_TYPE'" games=$(get_fabric_impl "game" "$MC_VERSION") MC_VERSION=$(index_array "$games" "$MC_VERSION" "VERSION") log "VERSION: $MC_VERSION" } get_loader() { log "Getting LOADER for '$MC_TYPE'" loaders=$(get_fabric_impl "loader" "$FABRIC_LOADER") FABRIC_LOADER=$(index_array "$loaders" "$FABRIC_LOADER" "LOADER") log "LOADER: $FABRIC_LOADER" } get_installer() { log "Getting INSTALLER for '$MC_TYPE'" installers=$(get_fabric_impl "installer" "$FABRIC_INSTALLER") FABRIC_INSTALLER=$(index_array "$installers" "$FABRIC_INSTALLER" "INSTALLER") log "INSTALLER: $FABRIC_INSTALLER" } get_game get_loader get_installer url="$api/loader/$MC_VERSION/$FABRIC_LOADER/$FABRIC_INSTALLER/server/jar" if [ $ALL -eq 1 ]; then echo "JAR_NAME=fabric-$MC_VERSION-$FABRIC_LOADER-$FABRIC_INSTALLER.jar" echo "JAR_URL=$url" echo "MC_TYPE=$MC_TYPE" echo "MC_VERSION=$MC_VERSION" echo "FABRIC_LOADER=$FABRIC_LOADER" echo "FABRIC_INSTALLER=$FABRIC_INSTALLER" else echo "$url" fi } vanilla() { versions=$(req 'https://launchermeta.mojang.com/mc/game/version_manifest.json' | jq '.versions | map({ "id": .id, "type": .type, "url": .url }) | reverse'); map_type_impl() { type="$1" echo "$versions" | jq -r "map(select(.type == \"$type\"))" } url="" get_version() { log "Getting VERSION for '$MC_TYPE'" version="" case "$MC_VERSION" in "latest") version=$(map_type_impl "release" | jq -r 'last') ;; "snapshot") version=$(map_type_impl "snapshot" | jq -r 'last') ;; *) version=$(echo "$versions" | jq ".[] | select(.id == \"$MC_VERSION\")") ;; esac if [ "$version" = "null" ] || [ "$version" = "" ]; then error "Invalid VERSION: $MC_VERSION" fi MC_VERSION=$(echo "$version" | jq -r '.id') log "VERSION: $MC_VERSION" json=$(echo "$version" | jq -r '.url') url=$(req "$json" | jq -r '.downloads.server.url') if [ "$url" = "null" ]; then error "Cannot get server jar for VERSION: $MC_VERSION" fi } get_version if [ $ALL -eq 1 ]; then echo "JAR_NAME=minecraft-$MC_VERSION.jar" echo "JAR_URL=$url" echo "MC_TYPE=$MC_TYPE" echo "MC_VERSION=$MC_VERSION" else echo "$url" fi } forge() { versions=$(req "https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json" | jq -r '.promos'); log "Using forge promotions slim json" url="" get_forge_url() { url="https://maven.minecraftforge.net/net/minecraftforge/forge/$1/forge-$1-installer.jar" code=0 wget -q --spider "$url" || code=$? if [ $code -eq 0 ]; then echo "$url"; fi } get_version() { log "Getting VERSION for '$MC_TYPE'" if [ "$MC_VERSION" = "latest" ]; then MC_VERSION=$(echo "$versions" | jq -r '. | keys | .[]' | awk -F '-' '{print $1}' | sort -t "." -n -k1,1 -k2,2 -k3,3 | tail -n1) fi log "VERSION: $MC_VERSION" } try_forge_version() { ver=$(echo "$versions" | jq -r ".\"$MC_VERSION-$FORGE_VERSION\"") if [ "$ver" = "null" ] && [ "$FORGE_VERSION" != "latest" ]; then FORGE_VERSION=latest try_forge_version else echo "$ver" fi } get_forge_version() { log "Getting FORGE VERSION for '$MC_TYPE'" if [ "$FORGE_VERSION" != "latest" ] && [ "$FORGE_VERSION" != "recommended" ]; then return; fi ver=$(try_forge_version) if [ "$ver" = "null" ]; then error "Invalid VERSION: $MC_VERSION-$FORGE_VERSION" fi FORGE_VERSION="$ver" log "FORGE VERSION: $FORGE_VERSION" } search_for_url() { log "Searching for forge URL" log "Trying MC_VERSION-FORGE_VERSION" ver=$(get_forge_url "$MC_VERSION-$FORGE_VERSION") if [ "$ver" != "" ]; then url="$ver"; return 0; fi log "Trying MC_VERSION-FORGE_VERSION-MC_VERSION" ver=$(get_forge_url "$MC_VERSION-$FORGE_VERSION-$MC_VERSION") if [ "$ver" != "" ]; then url="$ver"; return 0; fi log "Trying MC_VERSION-FORGE_VERSION-mc172" ver=$(get_forge_url "$MC_VERSION-$FORGE_VERSION-mc172") if [ "$ver" != "" ]; then url="$ver"; return 0; fi error "Invalid VERSION: $MC_VERSION-$FORGE_VERSION" } get_version get_forge_version search_for_url if [ $ALL -eq 1 ]; then echo "JAR_NAME=forge-$MC_VERSION-$FORGE_VERSION-installer.jar" echo "JAR_URL=$url" echo "MC_TYPE=$MC_TYPE" echo "MC_VERSION=$MC_VERSION" echo "FORGE_VERSION=$FORGE_VERSION" else echo "$url" fi } get_url() { log "TYPE: $MC_TYPE" case "$MC_TYPE" in "vanilla") vanilla ;; "paper" | "waterfall" | "velocity" | "folia") papermc ;; "fabric") fabric ;; "forge") forge ;; *) error "Invalid TYPE: $MC_TYPE" ;; esac } usage() { printf "usage: mcjar [options]\n" } help() { printf "usage: mcjar [options]\n\n" printf "options:\n" printf "\t-h\tshow this message\n" printf "\t-l\tshow logging (verbose)\n\n" printf "\t-a\toutput all variables\n\n" printf "\t-t TYPE\t\tset the mc server type\n" printf "\t [vanilla,fabric,forge,paper,folia,velocity,waterfall]\n\n" printf "\t-v VERSION\tset the mc server version\n" printf "\t [latest,snapshot,]\n\n" printf "environment:\n" printf "\tMC_TYPE\t\tsets the mc server type (same as -t TYPE)\n" printf "\tMC_VERSION\tsets the mc server version (same as -v VERSION)\n\n" printf "\tPAPERMC_BUILD\tsets the papermc build\n\n" printf "\tFABRIC_LOADER\t\tsets the fabric loder version\n" printf "\tFABRIC_INSTALLER\tsets the fabric installer version\n\n" printf "\tFORGE_VERSION\tsets the forge loader version\n\n" } chk_command() { if ! command -v "$1" > /dev/null; then >&2 echo "error: command '$1' could not be found" exit 1 fi } chk_command jq chk_command curl chk_command getopts while getopts "hlat:v:" arg 2> /dev/null; do case $arg in h) help exit 0 ;; l) QUIET=0 ;; a) ALL=1 ;; t) MC_TYPE=${OPTARG} ;; v) MC_VERSION=${OPTARG} ;; ?) error "unknown option" ;; esac; done; get_url