#!/bin/sh set -e # # DEFAULT VARIABLE GENERATORS # MEMORY="${MEMORY:-1G}" jvm_args() { printf -- "-Xms$MEMORY -Xmx$MEMORY " printf -- "-XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 " printf -- "-XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch " printf -- "-XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M " printf -- "-XX:G1ReservePercent=20 -XX:G1HeapWastePercent=5 -XX:G1MixedGCCountTarget=4 " printf -- "-XX:InitiatingHeapOccupancyPercent=15 -XX:G1MixedGCLiveThresholdPercent=90 " printf -- "-XX:G1RSetUpdatingPauseTimePercent=5 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem " printf -- "-XX:MaxTenuringThreshold=1" } lower() { echo "$1" | tr '[:upper:]' '[:lower:]' } # # ENV VARS # SERVER_DIR="$(realpath ${SERVER_DIR:-./server})" JVMARGS=${JVMARGS:-$(jvm_args)} MC_TYPE="$(lower "${MC_TYPE:-vanilla}")" MC_VERSION="$(lower "${MC_VERSION:-latest}")" # # PREDEFINE VARS # MCLAUNCHER_INFO="" MCLAUNCHER_BINARY="" MCLAUNCHER_QUIET=0 MCLAUNCHER_CACHE="$SERVER_DIR/.mclauncher" # # INTERNET CHECK # HAS_INTERNET=1 UPDATED=0 # # HELPERS # error() { printf '\x1b[31m[ERROR]\t\x1b[0m%s\n' "$*" > /dev/stderr exit 1; } log() { if [ "$MCLAUNCHER_QUIET" -eq 0 ]; then printf '\x1b[0m[LOG]\t%s\n' "$*" > /dev/stderr fi } warn() { if [ "$MCLAUNCHER_QUIET" -eq 0 ]; then printf '\x1b[33m[WARN]\t\x1b[0m%s\n' "$*" > /dev/stderr fi } step() { if [ "$MCLAUNCHER_QUIET" -eq 0 ]; then printf '\x1b[36m[STEP]\t\x1b[0m%s\n' "$*" > /dev/stderr fi } get_key() { echo "$MCLAUNCHER_INFO" | grep "$1=" | awk -F '=' '{ print $2 }' } # # INFO STEP # gets the up to date information from mcjar # info_step() { step "info" # check if we can use the internet if ! nc -zw1 google.com 443 &>/dev/null; then warn "Cannot internet access internet" HAS_INTERNET=0 fi # get the latest from mcjar if possible if [ $HAS_INTERNET -eq 1 ]; then if ! MCLAUNCHER_INFO="$(mcjar -a)"; then warn "Failed to get newest information from mcjar" MCLAUNCHER_INFO="" fi fi # get information from cache if latest failed if [ "$MCLAUNCHER_INFO" == "" ]; then if [ ! -e "$MCLAUNCHER_CACHE" ]; then error "No offline cache file found" fi MCLAUNCHER_INFO="$(cat "$MCLAUNCHER_CACHE")" fi echo "$MCLAUNCHER_INFO" > "$MCLAUNCHER_CACHE" [ "$MCLAUNCHER_QUIET" -eq 1 ] || echo "$MCLAUNCHER_INFO"; } # # BINARY STEP # attempts to find the current binary installed on the system # binary_step_forge() { jar_name="$(get_key "JAR_NAME")" jar_prefix="${jar_name%-installer.jar}" suffixs="$(echo ".jar;-shim.jar;-universal.jar" | tr ";" "\n")" IFS=$'\n' for suffix in $suffixs; do if [ -f "$SERVER_DIR/$jar_prefix$suffix" ]; then MCLAUNCHER_BINARY="$jar_prefix$suffix" return; fi done } binary_step_default() { jar_name="$(get_key "JAR_NAME")" if [ -f "$SERVER_DIR/$jar_name" ]; then MCLAUNCHER_BINARY="$jar_name" fi } binary_step() { step "binary" MCLAUNCHER_BINARY="" type="$(get_key "MC_TYPE")" case "$type" in "forge") binary_step_forge ;; *) binary_step_default ;; esac if [ "$MCLAUNCHER_BINARY" != "" ]; then log "found binary '$MCLAUNCHER_BINARY'" else log "could not locate binary... will download" fi } # # DOWNLOAD STEP # download the binary if it needs to needs updated # download_step() { step "download" if [ "$MCLAUNCHER_BINARY" != "" ]; then # check if jar file is valid if ! 7z t "$MCLAUNCHER_BINARY" &>/dev/null; then warn "jar file is corrupted" else log "jar is up to date... skipping" return; fi fi if [ $HAS_INTERNET -eq 0 ]; then error "Cannot download jar due to lack of internet" fi # clean up old files rm -f "$SERVER_DIR"/*.jar rm -f "$SERVER_DIR"/*.jar.log rm -f "$SERVER_DIR"/*.bat rm -f "$SERVER_DIR"/run.sh # update the jar log "jar is out of date... updating" jar_url="$(get_key "JAR_URL")" jar_name="$(get_key "JAR_NAME")" log "downloading '$jar_url'" wget -q "$jar_url" -O "$SERVER_DIR/$jar_name" MCLAUNCHER_BINARY="$jar_name" UPDATED=1 } # # INSTALL STEP # some mc types need an extra install step to setup the server files before running # install_step_forge() { log "installing forge server" jar_name="$(get_key "JAR_NAME")" java -jar "$SERVER_DIR/$jar_name" --installServer binary_step_forge if [ "$MCLAUNCHER_BINARY" = "" ]; then error "could not locate forge binary" fi } install_step() { step "install" if [ "$UPDATED" -eq 0 ]; then log "jar not updated... skipping" return; fi type="$(get_key "MC_TYPE")" case "$type" in "forge") install_step_forge ;; "neoforged") install_step_forge ;; *) log "install step not needed for '$type'" ;; esac } # # EXECUTE STEP # run the thing!!!!!! # execute_step_default() { jar_name="$(get_key "JAR_NAME")" exec java $JVMARGS -jar "$SERVER_DIR/$jar_name" nogui } execute_step_forge() { if [ -f "$SERVER_DIR/run.sh" ]; then echo "$JVMARGS" | tr ' ' '\n' > "$SERVER_DIR/user_jvm_args.txt" { chmod +x "$SERVER_DIR/run.sh" || true; } exec "$SERVER_DIR/run.sh" nogui else exec java $JVMARGS -jar "$SERVER_DIR/$MCLAUNCHER_BINARY" nogui fi } execute_step() { step "execute" echo "eula=true" > "$SERVER_DIR/eula.txt" type="$(get_key "MC_TYPE")" case "$type" in "forge") execute_step_forge ;; "neoforged") execute_step_forge ;; *) execute_step_default ;; esac } chk_command() { if ! command -v "$1" > /dev/null; then >&2 echo "error: command '$1' could not be found" exit 1 fi } help() { printf "usage: mclauncher [options]\n\n" printf "options:\n" printf "\t-h\tshow this message\n" printf "\t-l\tshow logging (verbose)\n\n" printf "environment:\n" printf "\tsee 'mcjar -h' for environment\n" } chk_command mcjar chk_command java chk_command awk chk_command getopts while getopts "hl" arg 2>/dev/null; do case "$arg" in h) help exit 0 ;; l) MCLAUNCHER_QUIET=0 ;; ?) error "unknown option" ;; esac; done; mkdir -p "$SERVER_DIR" cd "$SERVER_DIR" info_step binary_step download_step install_step execute_step