mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-02-21 16:46:23 +00:00
Auto-merging via docker-versions-create
This commit is contained in:
46
scripts/start
Executable file
46
scripts/start
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
umask 0002
|
||||
chmod g+w /data
|
||||
|
||||
if ! isTrue "${SKIP_SUDO:-false}" && [ $(id -u) = 0 ]; then
|
||||
runAsUser=minecraft
|
||||
runAsGroup=minecraft
|
||||
|
||||
if [[ -v UID ]]; then
|
||||
if [[ $UID != 0 ]]; then
|
||||
if [[ $UID != $(id -u minecraft) ]]; then
|
||||
log "Changing uid of minecraft to $UID"
|
||||
usermod -u $UID minecraft
|
||||
fi
|
||||
else
|
||||
runAsUser=root
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -v GID ]]; then
|
||||
if [[ $GID != 0 ]]; then
|
||||
if [[ $GID != $(id -g minecraft) ]]; then
|
||||
log "Changing gid of minecraft to $GID"
|
||||
groupmod -o -g $GID minecraft
|
||||
fi
|
||||
else
|
||||
runAsGroup=root
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $(stat -c "%u" /data) != $UID ]]; then
|
||||
log "Changing ownership of /data to $UID ..."
|
||||
chown -R ${runAsUser}:${runAsGroup} /data
|
||||
fi
|
||||
|
||||
if [[ ${SKIP_NSSWITCH_CONF^^} != TRUE ]]; then
|
||||
echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
fi
|
||||
|
||||
exec gosu ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
|
||||
else
|
||||
exec ${SCRIPTS:-/}start-configuration $@
|
||||
fi
|
||||
67
scripts/start-autopause
Executable file
67
scripts/start-autopause
Executable file
@@ -0,0 +1,67 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
log "Autopause functionality enabled"
|
||||
|
||||
cp /autopause/knockd-config.cfg /tmp/knockd-config.cfg
|
||||
|
||||
# update server port to listen to
|
||||
regseq="^\s*sequence\s*=\s*$SERVER_PORT\s*$"
|
||||
linenum=$(grep -nm1 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $SERVER_PORT/" /tmp/knockd-config.cfg
|
||||
log "Updated server port in knockd config"
|
||||
fi
|
||||
# update rcon port to listen to
|
||||
regseq="^\s*sequence\s*=\s*$RCON_PORT\s*$"
|
||||
linenum=$(grep -nm2 sequence /tmp/knockd-config.cfg | cut -d : -f 1 | tail -n1)
|
||||
if ! [[ $(awk "NR==$linenum" /tmp/knockd-config.cfg) =~ $regseq ]]; then
|
||||
sed -i "${linenum}s/sequence.*/sequence = $RCON_PORT/" /tmp/knockd-config.cfg
|
||||
log "Updated rcon port in knockd config"
|
||||
fi
|
||||
|
||||
if ! [[ $AUTOPAUSE_PERIOD =~ ^[0-9]+$ ]]; then
|
||||
AUTOPAUSE_PERIOD=10
|
||||
export AUTOPAUSE_PERIOD
|
||||
log "Warning: AUTOPAUSE_PERIOD is not numeric, set to 10 (seconds)"
|
||||
fi
|
||||
if [ "$AUTOPAUSE_PERIOD" -eq "0" ] ; then
|
||||
AUTOPAUSE_PERIOD=10
|
||||
export AUTOPAUSE_PERIOD
|
||||
log "Warning: AUTOPAUSE_PERIOD must not be 0, set to 10 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOPAUSE_TIMEOUT_KN =~ ^[0-9]+$ ]] ; then
|
||||
AUTOPAUSE_TIMEOUT_KN=120
|
||||
export AUTOPAUSE_TIMEOUT_KN
|
||||
log "Warning: AUTOPAUSE_TIMEOUT_KN is not numeric, set to 120 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOPAUSE_TIMEOUT_EST =~ ^[0-9]+$ ]] ; then
|
||||
AUTOPAUSE_TIMEOUT_EST=3600
|
||||
export AUTOPAUSE_TIMEOUT_EST
|
||||
log "Warning: AUTOPAUSE_TIMEOUT_EST is not numeric, set to 3600 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOPAUSE_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
|
||||
AUTOPAUSE_TIMEOUT_INIT=600
|
||||
export AUTOPAUSE_TIMEOUT_INIT
|
||||
log "Warning: AUTOPAUSE_TIMEOUT_INIT is not numeric, set to 600 (seconds)"
|
||||
fi
|
||||
if [[ "$AUTOPAUSE_KNOCK_INTERFACE" == "lo" ]] ; then
|
||||
log "Warning: AUTOPAUSE_KNOCK_INTERFACE is set to the local loopback interface."
|
||||
log " This is not advisable, as incoming connections are likely not picked up there."
|
||||
log " Continuing with this setting."
|
||||
fi
|
||||
|
||||
if [[ -n "$MAX_TICK_TIME" && "$MAX_TICK_TIME" != "-1" ]] ; then
|
||||
log "Warning: MAX_TICK_TIME is non-default, for autopause to work properly, this check should be disabled (-1 for versions >= 1.8.1)"
|
||||
elif [[ -z "$MAX_TICK_TIME" ]] ; then
|
||||
if versionLessThan 1.8.1; then
|
||||
# 10 years
|
||||
MAX_TICK_TIME=315360000000
|
||||
else
|
||||
MAX_TICK_TIME=-1
|
||||
fi
|
||||
export MAX_TICK_TIME
|
||||
fi
|
||||
|
||||
/autopause/autopause-daemon.sh &
|
||||
173
scripts/start-configuration
Executable file
173
scripts/start-configuration
Executable file
@@ -0,0 +1,173 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
: "${EULA:=}"
|
||||
: "${PROXY:=}"
|
||||
: "${RCON_PASSWORD_FILE:=}"
|
||||
|
||||
shopt -s nullglob
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
#umask 002
|
||||
export HOME=/data
|
||||
|
||||
log "Running as uid=$(id -u) gid=$(id -g) with /data as '$(ls -lnd /data)'"
|
||||
|
||||
if [ ! -e /data/eula.txt ]; then
|
||||
if ! isTrue "$EULA"; then
|
||||
log ""
|
||||
log "Please accept the Minecraft EULA at"
|
||||
log " https://account.mojang.com/documents/minecraft_eula"
|
||||
log "by adding the following immediately after 'docker run':"
|
||||
log " -e EULA=TRUE"
|
||||
log ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
writeEula
|
||||
fi
|
||||
|
||||
|
||||
if [[ $PROXY ]]; then
|
||||
export http_proxy="$PROXY"
|
||||
export https_proxy="$PROXY"
|
||||
export JAVA_TOOL_OPTIONS+="-Djava.net.useSystemProxies=true"
|
||||
log "INFO: Giving proxy time to startup..."
|
||||
sleep 5
|
||||
fi
|
||||
|
||||
if [[ $RCON_PASSWORD_FILE ]]; then
|
||||
log ""
|
||||
if [ ! -e ${RCON_PASSWORD_FILE} ]; then
|
||||
log "Initial RCON password file ${RCON_PASSWORD_FILE} does not seems to exist."
|
||||
log "Please ensure your configuration."
|
||||
log "If you are using Docker Secrets feature, please check this for further information: "
|
||||
log " https://docs.docker.com/engine/swarm/secrets"
|
||||
log ""
|
||||
exit 1
|
||||
else
|
||||
RCON_PASSWORD=$(cat ${RCON_PASSWORD_FILE})
|
||||
export RCON_PASSWORD
|
||||
fi
|
||||
log ""
|
||||
fi
|
||||
|
||||
if ! which java > /dev/null; then
|
||||
log "Fixing PATH to include java"
|
||||
PATH="${PATH}:/opt/java/openjdk/bin"
|
||||
fi
|
||||
|
||||
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
|
||||
|
||||
case "X$VERSION" in
|
||||
X|XLATEST|Xlatest)
|
||||
if ! VANILLA_VERSION=$(get --json-path '$.latest.release' "$VERSIONS_JSON"); then
|
||||
log "ERROR: version lookup failed: $VANILLA_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
XSNAPSHOT|Xsnapshot)
|
||||
if ! VANILLA_VERSION=$(get --json-path '$.latest.snapshot' "$VERSIONS_JSON"); then
|
||||
log "ERROR: version lookup failed: $VANILLA_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
VANILLA_VERSION=$VERSION
|
||||
;;
|
||||
esac
|
||||
export VANILLA_VERSION
|
||||
log "Resolved version given ${VERSION} into ${VANILLA_VERSION}"
|
||||
|
||||
cd /data || exit 1
|
||||
|
||||
export ORIGINAL_TYPE=${TYPE^^}
|
||||
|
||||
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||
${SCRIPTS:-/}start-autopause
|
||||
fi
|
||||
|
||||
log "Resolving type given ${TYPE}"
|
||||
case "${TYPE^^}" in
|
||||
*BUKKIT|SPIGOT)
|
||||
exec ${SCRIPTS:-/}start-deployBukkitSpigot "$@"
|
||||
;;
|
||||
|
||||
PAPER)
|
||||
exec ${SCRIPTS:-/}start-deployPaper "$@"
|
||||
;;
|
||||
|
||||
FORGE)
|
||||
exec ${SCRIPTS:-/}start-deployForge "$@"
|
||||
;;
|
||||
|
||||
FABRIC)
|
||||
exec ${SCRIPTS:-/}start-deployFabric "$@"
|
||||
;;
|
||||
|
||||
FTBA)
|
||||
exec ${SCRIPTS:-/}start-deployFTBA "$@"
|
||||
;;
|
||||
|
||||
FTB|CURSEFORGE)
|
||||
exec ${SCRIPTS:-/}start-deployCF "$@"
|
||||
;;
|
||||
|
||||
VANILLA)
|
||||
exec "${SCRIPTS:-/}start-deployVanilla" "$@"
|
||||
;;
|
||||
|
||||
SPONGEVANILLA)
|
||||
exec ${SCRIPTS:-/}start-deploySpongeVanilla "$@"
|
||||
;;
|
||||
|
||||
CUSTOM)
|
||||
exec ${SCRIPTS:-/}start-deployCustom "$@"
|
||||
;;
|
||||
|
||||
MAGMA)
|
||||
exec ${SCRIPTS:-/}start-deployMagma "$@"
|
||||
;;
|
||||
|
||||
MOHIST)
|
||||
exec ${SCRIPTS:-/}start-deployMohist "$@"
|
||||
;;
|
||||
|
||||
CATSERVER)
|
||||
exec ${SCRIPTS:-/}start-deployCatserver "$@"
|
||||
;;
|
||||
|
||||
PURPUR)
|
||||
exec ${SCRIPTS:-/}start-deployPurpur "$@"
|
||||
;;
|
||||
|
||||
AIRPLANE)
|
||||
exec ${SCRIPTS:-/}start-deployAirplane "$@"
|
||||
;;
|
||||
|
||||
CANYON)
|
||||
exec ${SCRIPTS:-/}start-deployCanyon "$@"
|
||||
;;
|
||||
|
||||
LIMBO)
|
||||
exec ${SCRIPTS:-/}start-deployLimbo "$@"
|
||||
;;
|
||||
|
||||
CRUCIBLE)
|
||||
exec "${SCRIPTS:-/}start-deployCrucible" "$@"
|
||||
;;
|
||||
|
||||
*)
|
||||
log "Invalid type: '$TYPE'"
|
||||
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
|
||||
log " CURSEFORGE, SPONGEVANILLA, PURPUR, CUSTOM,"
|
||||
log " MAGMA, MOHIST, CATSERVER, AIRPLANE, CANYON, LIMBO, CRUCIBLE"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
esac
|
||||
52
scripts/start-deployAirplane
Executable file
52
scripts/start-deployAirplane
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
if [ "${VERSION}" != "LATEST" ] && [ "${VERSION}" != "1.16" ] && [ "${VERSION}" != "1.17" ] && [ "${VERSION}" != "PURPUR" ] && [ "${VERSION}" != "PURPUR-1.16" ] ; then
|
||||
log "ERROR: Airplane server type only supports VERSION=LATEST, VERSION=1.17, VERSION=1.16, VERSION=PURPUR or VERSION=PURPUR-1.16. Note that these are branches, not #.#.# versions."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: ${AIRPLANE_BUILD:=lastSuccessfulBuild}
|
||||
: ${AIRPLANE_TYPE:=airplane}
|
||||
|
||||
if [ "${VERSION}" = "LATEST" ] || [ "${VERSION}" = "1.17" ]; then
|
||||
AIRPLANE_BRANCH="1.17"
|
||||
fi
|
||||
|
||||
if [ "${VERSION}" = "1.16" ]; then
|
||||
AIRPLANE_BRANCH="1.16"
|
||||
fi
|
||||
|
||||
if [ "${VERSION}" = "PURPUR" ]; then
|
||||
AIRPLANE_BRANCH="Purpur-1.17"
|
||||
AIRPLANE_TYPE="airplanepurpur"
|
||||
fi
|
||||
|
||||
if [ "${VERSION}" = "PURPUR-1.16" ]; then
|
||||
AIRPLANE_BRANCH="Purpur-1.16"
|
||||
AIRPLANE_TYPE="airplanepurpur"
|
||||
fi
|
||||
|
||||
log "Using Airplane-${AIRPLANE_BRANCH} branch"
|
||||
|
||||
export SERVER=airplane-${AIRPLANE_BRANCH}-${AIRPLANE_BUILD}.jar
|
||||
|
||||
if [ ! -f "$SERVER" ] || isTrue "${FORCE_REDOWNLOAD:-false}"; then
|
||||
downloadUrl="https://ci.tivy.ca/job/Airplane-${AIRPLANE_BRANCH}/${AIRPLANE_BUILD}/artifact/launcher-${AIRPLANE_TYPE}.jar"
|
||||
log "Downloading Airplane from $downloadUrl ..."
|
||||
curl -fsSL -o "$SERVER" "$downloadUrl"
|
||||
if [ ! -f "$SERVER" ]; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for later operations
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
132
scripts/start-deployBukkitSpigot
Executable file
132
scripts/start-deployBukkitSpigot
Executable file
@@ -0,0 +1,132 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
set -e
|
||||
|
||||
function buildSpigotFromSource {
|
||||
if [[ ${TYPE^^} = *BUKKIT ]] && ! versionLessThan "1.14"; then
|
||||
log "ERR craftbukkit build is only supported for versions less than 1.14"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Building Spigot $VANILLA_VERSION from source, might take a while, get some coffee"
|
||||
rm -rf /data/temp
|
||||
mkdir /data/temp
|
||||
cd /data/temp
|
||||
|
||||
jvmOpts="-Xms${INIT_MEMORY:-$MEMORY} -Xmx${MAX_MEMORY:-$MEMORY}"
|
||||
|
||||
logn ''
|
||||
curl -sSL -o /data/temp/BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar && \
|
||||
java $jvmOpts -jar /data/temp/BuildTools.jar --rev $VANILLA_VERSION 2>&1 |tee /data/spigot_build.log| while read l; do echo -n .; done; log "done"
|
||||
|
||||
case ${TYPE^^} in
|
||||
SPIGOT)
|
||||
if ! mv spigot-*.jar /data/${SERVER}; then
|
||||
log "ERR failed to build Spigot"
|
||||
cat /data/spigot_build.log
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*BUKKIT)
|
||||
if ! mv craftbukkit-*.jar /data/${SERVER}; then
|
||||
log "ERR failed to build Spigot"
|
||||
cat /data/spigot_build.log
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
log "Cleaning up"
|
||||
rm -rf /data/temp
|
||||
cd /data
|
||||
}
|
||||
|
||||
function downloadSpigot {
|
||||
local match
|
||||
case "$TYPE" in
|
||||
*BUKKIT|*bukkit)
|
||||
match="CraftBukkit"
|
||||
downloadUrl=${BUKKIT_DOWNLOAD_URL}
|
||||
getbukkitFlavor=craftbukkit
|
||||
;;
|
||||
*)
|
||||
match="Spigot"
|
||||
downloadUrl=${SPIGOT_DOWNLOAD_URL}
|
||||
getbukkitFlavor=spigot
|
||||
;;
|
||||
esac
|
||||
|
||||
if [[ ${VERSION^^} = LATEST ]]; then
|
||||
VANILLA_VERSION=$(restify https://getbukkit.org/download/spigot --attribute='property=og:title' | jq -r '.[0] | .attributes | select(.property == "og:title") | .content | split(" ") | .[-1]')
|
||||
fi
|
||||
|
||||
if [[ -z $downloadUrl ]]; then
|
||||
if versionLessThan 1.16.5; then
|
||||
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
||||
else
|
||||
downloadUrl="https://download.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
||||
fi
|
||||
fi
|
||||
|
||||
setServerVar
|
||||
if [ -f $SERVER ]; then
|
||||
# tell curl to only download when newer
|
||||
curlArgs="-z $SERVER"
|
||||
fi
|
||||
if isDebugging; then
|
||||
curlArgs="$curlArgs -v"
|
||||
fi
|
||||
log "Downloading $match from $downloadUrl ..."
|
||||
curl -fsSL -o $SERVER $curlArgs "$downloadUrl"
|
||||
if [[ $? != 0 || $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
|
||||
cat <<EOF
|
||||
|
||||
ERROR: failed to download from $downloadUrl
|
||||
Visit https://getbukkit.org/download/${getbukkitFlavor} to lookup the
|
||||
exact version, such as 1.4.6-R0.4-SNAPSHOT or 1.8-R0.1-SNAPSHOT-latest.
|
||||
Click into the version entry to find the **exact** version, because something
|
||||
like "1.8" is not sufficient according to their download naming.
|
||||
|
||||
EOF
|
||||
|
||||
if isDebugging && [[ $(grep -c "DOCTYPE html" $SERVER) != 0 ]]; then
|
||||
cat $SERVER
|
||||
fi
|
||||
|
||||
# remove invalid download
|
||||
rm $SERVER
|
||||
exit 3
|
||||
fi
|
||||
|
||||
JVM_OPTS="${JVM_OPTS} -DIReallyKnowWhatIAmDoingISwear"
|
||||
export JVM_OPTS
|
||||
}
|
||||
|
||||
function setServerVar {
|
||||
case "$TYPE" in
|
||||
*BUKKIT|*bukkit)
|
||||
export SERVER=craftbukkit_server-${VANILLA_VERSION}.jar
|
||||
;;
|
||||
*)
|
||||
export SERVER=spigot_server-${VANILLA_VERSION}.jar
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
if isTrue "$BUILD_SPIGOT_FROM_SOURCE" || isTrue "$BUILD_FROM_SOURCE"; then
|
||||
setServerVar
|
||||
if [ ! -f $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
buildSpigotFromSource
|
||||
fi
|
||||
else
|
||||
downloadSpigot
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for operations below
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
236
scripts/start-deployCF
Executable file
236
scripts/start-deployCF
Executable file
@@ -0,0 +1,236 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
|
||||
loadForgeVars() {
|
||||
cfgFile=${1?}
|
||||
pat='^([^#;][^=]+)=[:space:]*([^;]*)'
|
||||
while read -r line || [[ -n "$line" ]] ; do
|
||||
if [[ $line =~ $pat ]]; then
|
||||
#echo "MATCHED $line"
|
||||
k=${BASH_REMATCH[1]}
|
||||
v=${BASH_REMATCH[2]}
|
||||
case $k in
|
||||
FORGEURL)
|
||||
forgeInstallerUrl="$v"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
done < "$cfgFile"
|
||||
}
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
: "${FTB_BASE_DIR:=${CF_BASE_DIR:-/data/FeedTheBeast}}"
|
||||
export FTB_BASE_DIR
|
||||
|
||||
legacyJavaFixerUrl=https://ftb.forgecdn.net/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
|
||||
export TYPE=CURSEFORGE
|
||||
|
||||
FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
|
||||
|
||||
log "Looking for Feed-The-Beast / CurseForge server modpack."
|
||||
requireVar FTB_SERVER_MOD
|
||||
|
||||
if ! isTrue "${USE_MODPACK_START_SCRIPT:-true}"; then
|
||||
if ! [ -f "${FTB_SERVER_MOD}" ]; then
|
||||
log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
needsInstall=true
|
||||
installMarker=/data/.curseforge-installed
|
||||
if [ -f $installMarker ]; then
|
||||
if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then
|
||||
log "Upgrading modpack"
|
||||
|
||||
serverJar=$(find "${FTB_BASE_DIR}" -not -name "forge*installer.jar" -name "forge*.jar")
|
||||
if [[ "${serverJar}" ]]; then
|
||||
rm -rf "$(dirname "${serverJar}")"/{mods,*.jar,libraries,resources,scripts,config}
|
||||
fi
|
||||
else
|
||||
needsInstall=false
|
||||
fi
|
||||
fi
|
||||
|
||||
if $needsInstall; then
|
||||
log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..."
|
||||
mkdir -p "${FTB_BASE_DIR}"
|
||||
unzip -o "${FTB_SERVER_MOD}" -d "${FTB_BASE_DIR}" | awk '{printf "."} END {print ""}'
|
||||
|
||||
serverJar=$(find "${FTB_BASE_DIR}" -type f \( -path "*/libraries/*" -o -path "*/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||
if [[ -z "$serverJar" ]]; then
|
||||
|
||||
if [ -f "${FTB_BASE_DIR}/settings.cfg" ]; then
|
||||
loadForgeVars "${FTB_BASE_DIR}/settings.cfg"
|
||||
|
||||
if [[ $forgeInstallerUrl ]]; then
|
||||
forgeInstallerJar="${FTB_BASE_DIR}/forge-installer.jar"
|
||||
if ! curl -fsSL -o "$forgeInstallerJar" "$forgeInstallerUrl" ; then
|
||||
log "ERROR failed to download Forge installer from $forgeInstallerUrl"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
else
|
||||
forgeInstallerJar=$(find "${FTB_BASE_DIR}" -name "forge*installer.jar")
|
||||
fi
|
||||
|
||||
if [[ -z "${forgeInstallerJar}" ]]; then
|
||||
log "ERROR Unable to find forge installer in modpack"
|
||||
log " or download using modpack config."
|
||||
log " Make sure you downloaded the server files."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
log "Installing forge server"
|
||||
dirOfInstaller=$(dirname "${forgeInstallerJar}")
|
||||
(cd "${dirOfInstaller}"; java -jar "$(basename "${forgeInstallerJar}")" --installServer)
|
||||
fi
|
||||
|
||||
echo "${FTB_SERVER_MOD}" > $installMarker
|
||||
fi
|
||||
|
||||
SERVER=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||
if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then
|
||||
log "ERROR unable to locate installed forge server jar"
|
||||
isDebugging && find "${FTB_BASE_DIR}" -name "forge*.jar"
|
||||
exit 2
|
||||
fi
|
||||
export SERVER
|
||||
|
||||
FTB_DIR=$(dirname "${SERVER}")
|
||||
export FTB_DIR
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
fi
|
||||
|
||||
entryScriptExpr="
|
||||
-name ServerStart.sh
|
||||
-o -name serverstart.sh
|
||||
-o -name ServerStartLinux.sh
|
||||
-o -name LaunchServer.sh
|
||||
-o -name server-start.sh
|
||||
-o -name start-server.sh
|
||||
-o -name startserver.sh
|
||||
-o -name StartServer.sh
|
||||
"
|
||||
|
||||
if [[ -d ${FTB_BASE_DIR} ]]; then
|
||||
startScriptCount=$(find "${FTB_BASE_DIR}" $entryScriptExpr |wc -l)
|
||||
if (( startScriptCount > 1 )); then
|
||||
log "Conflicting FTB/CurseForge packages have been installed. Please cleanup ${FTB_BASE_DIR}"
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
startScriptCount=0
|
||||
fi
|
||||
|
||||
# only download and install if a mod pack isn't already installed
|
||||
# also check for the start script rather than just the folder
|
||||
# this allows saving just the world separate from the rest of the data directory
|
||||
if [[ $startScriptCount = 0 ]]; then
|
||||
srv_modpack=${FTB_SERVER_MOD}
|
||||
if isURL "${srv_modpack}"; then
|
||||
log "Downloading modpack from ${srv_modpack}..."
|
||||
if ! srv_modpack=$(get -o /data --output-filename --skip-existing "${srv_modpack}"); then
|
||||
log "ERROR: failed to download modpack"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ "${srv_modpack:0:5}" == "data/" ]]; then
|
||||
# Prepend with "/"
|
||||
srv_modpack="/${srv_modpack}"
|
||||
fi
|
||||
if [[ ! "${srv_modpack:0:1}" == "/" ]]; then
|
||||
# If not an absolute path, assume file is in "/data"
|
||||
srv_modpack=/data/${srv_modpack}
|
||||
fi
|
||||
if [[ ! -f "${srv_modpack}" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} not found."
|
||||
exit 2
|
||||
fi
|
||||
if [[ ! "${srv_modpack: -4}" == ".zip" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} is not a zip archive."
|
||||
log "Please set FTB_SERVER_MOD to a file with a .zip extension."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
log "Unpacking FTB server modpack ${srv_modpack} ..."
|
||||
mkdir -p "${FTB_BASE_DIR}"
|
||||
unzip -o "${srv_modpack}" -d "${FTB_BASE_DIR}" | awk '{printf "."} END {print ""}'
|
||||
|
||||
installScript=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f -name install.sh)
|
||||
if [[ "$installScript" ]]; then
|
||||
(
|
||||
cd "$(dirname "${installScript}")"
|
||||
chmod +x ./install.sh
|
||||
log "Running included install.sh"
|
||||
./install.sh
|
||||
)
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $(find "${FTB_BASE_DIR}" $entryScriptExpr | wc -l) = 0 ]]; then
|
||||
|
||||
# Allow up to 2 levels since some modpacks have a top-level directory named
|
||||
# for the modpack
|
||||
forgeJar=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||
if [[ "$forgeJar" ]]; then
|
||||
FTB_BASE_DIR=$(dirname "${forgeJar}")
|
||||
export FTB_BASE_DIR
|
||||
log "No entry script found, so building one for ${forgeJar}"
|
||||
cat > "${FTB_BASE_DIR}/ServerStart.sh" <<EOF
|
||||
#!/bin/sh
|
||||
. ./settings-local.sh
|
||||
java \${JAVA_PARAMETERS} -Xmx\${MAX_RAM} -jar $(basename "${forgeJar}") nogui
|
||||
EOF
|
||||
chmod +x "${FTB_BASE_DIR}/ServerStart.sh"
|
||||
else
|
||||
log "Please make sure you are using the server version of the FTB modpack!"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
scriptCount=$(find "${FTB_BASE_DIR}" $entryScriptExpr | wc -l)
|
||||
if [[ $scriptCount = 0 ]]; then
|
||||
log "Please make sure you are using the server version of the FTB modpack!"
|
||||
exit 2
|
||||
elif (( scriptCount > 1 )); then
|
||||
log "Ambiguous startup scripts in FTB modpack! Found:"
|
||||
find "${FTB_BASE_DIR}" $entryScriptExpr
|
||||
exit 2
|
||||
fi
|
||||
|
||||
FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr)
|
||||
export FTB_SERVER_START
|
||||
|
||||
FTB_DIR=$(dirname "${FTB_SERVER_START}")
|
||||
export FTB_DIR
|
||||
chmod a+x "${FTB_SERVER_START}"
|
||||
grep fml.queryResult=confirm "${FTB_SERVER_START}" > /dev/null || \
|
||||
sed -i 's/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}"
|
||||
sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}"
|
||||
legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar"
|
||||
|
||||
if isTrue "${FTB_LEGACYJAVAFIXER}" && [ ! -e "${legacyJavaFixerPath}" ]; then
|
||||
log "Installing legacy java fixer to ${legacyJavaFixerPath}"
|
||||
if ! get -o "${legacyJavaFixerPath}" ${legacyJavaFixerUrl}; then
|
||||
log "ERROR failed to download legacy java fixer from ${legacyJavaFixerUrl}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -e "${FTB_DIR}/FTBInstall.sh" ]; then
|
||||
pushd "${FTB_DIR}"
|
||||
sh FTBInstall.sh
|
||||
popd
|
||||
elif [ -e "${FTB_DIR}/Install.sh" ]; then
|
||||
pushd "${FTB_DIR}"
|
||||
sh Install.sh
|
||||
popd
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
54
scripts/start-deployCanyon
Executable file
54
scripts/start-deployCanyon
Executable file
@@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
: ${CANYON_BUILD:=lastSuccessfulBuild}
|
||||
JAVA_VER=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
|
||||
|
||||
if [ "${JAVA_VER}" != "8" ]; then
|
||||
log "ERROR: Canyon server type only supports Java version 8"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${VERSION}" != "b1.7.3" ]; then
|
||||
log "ERROR: Canyon server type only supports VERSION=b1.7.3"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
canyonJob="https://ci.velocitypowered.com/job/Canyon"
|
||||
|
||||
buildRelPath=$(
|
||||
curl -fsSL "${canyonJob}/${CANYON_BUILD}/api/json" |
|
||||
jq -r '.artifacts[0].relativePath'
|
||||
)
|
||||
buildNumber=$(
|
||||
curl -fsSL "${canyonJob}/${CANYON_BUILD}/api/json" |
|
||||
jq -r '.number'
|
||||
)
|
||||
baseName=$(basename "${buildRelPath}")
|
||||
|
||||
# Add build tag to non-tagged builds for version detection
|
||||
if [ ${baseName%.*} = 'canyon-server' ]; then
|
||||
export SERVER=${baseName%.*}_build${buildNumber}.jar
|
||||
else
|
||||
export SERVER="${baseName}"
|
||||
fi
|
||||
|
||||
if [ ! -f "$SERVER" ]; then
|
||||
downloadUrl="${canyonJob}/${CANYON_BUILD}/artifact/${buildRelPath}"
|
||||
log "Downloading Canyon build ${buildNumber} from $downloadUrl ..."
|
||||
curl -fsSL -o "$SERVER" "$downloadUrl"
|
||||
if [ ! -f "$SERVER" ]; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for later operations
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
32
scripts/start-deployCatserver
Executable file
32
scripts/start-deployCatserver
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -o pipefail
|
||||
set -e
|
||||
|
||||
latestAsset=$(
|
||||
curl -fsSL https://api.github.com/repos/Luohuayu/CatServer/releases/latest | \
|
||||
jq '.assets[] | select(.name | match(".*-universal.jar"))'
|
||||
)
|
||||
|
||||
if [[ -z "${latestAsset}" ]]; then
|
||||
log "ERROR: latest release of Catserver is missing universal.jar asset"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
isDebugging && log "Latest asset ${latestAsset}"
|
||||
latestJarName=$(echo ${latestAsset} | jq --raw-output '.name')
|
||||
latestJarId=$(echo ${latestAsset} | jq --raw-output '.id')
|
||||
|
||||
|
||||
export SERVER="/data/${latestJarName}"
|
||||
|
||||
if [ ! -f ${SERVER} ]; then
|
||||
log "Downloading ${latestJarName}"
|
||||
curl -H "Accept:application/octet-stream" -o "$SERVER" -fsSL https://api.github.com/repos/Luohuayu/CatServer/releases/assets/${latestJarId}
|
||||
fi
|
||||
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||
60
scripts/start-deployCrucible
Executable file
60
scripts/start-deployCrucible
Executable file
@@ -0,0 +1,60 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-$(dirname "$0")}/start-utils"
|
||||
set -o pipefail
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
|
||||
requireVar VANILLA_VERSION
|
||||
: "${CRUCIBLE_RELEASE:=latest}"
|
||||
|
||||
crucibleReleasesUrl=https://api.github.com/repos/CrucibleMC/Crucible/releases
|
||||
if [[ ${CRUCIBLE_RELEASE^^} = LATEST ]]; then
|
||||
crucibleReleaseUrl=${crucibleReleasesUrl}/latest
|
||||
else
|
||||
crucibleReleaseUrl=${crucibleReleasesUrl}/tags/${CRUCIBLE_RELEASE}
|
||||
fi
|
||||
|
||||
if ! downloadUrl=$(get --json-path "$.assets[?(@.name =~ /Crucible-${VANILLA_VERSION}-.*\.jar/)].browser_download_url" \
|
||||
--accept "application/vnd.github.v3+json" "$crucibleReleaseUrl"); then
|
||||
log "ERROR: failed to access ${CRUCIBLE_RELEASE} release of Crucible"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $downloadUrl = null ]]; then
|
||||
log "ERROR: failed to locate Crucible jar for $VANILLA_VERSION from ${CRUCIBLE_RELEASE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Downloading Crucible from $downloadUrl"
|
||||
if ! SERVER=$(get --skip-existing --output-filename -o /data "$downloadUrl"); then
|
||||
log "ERROR: failed to download Crucible jar from $downloadUrl"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
librariesDir=/data/libraries
|
||||
if [ ! -d "$librariesDir" ]; then
|
||||
if ! librariesUrl=$(get --json-path "$.assets[?(@.name == 'libraries.zip')].browser_download_url" \
|
||||
--accept "application/vnd.github.v3+json" "$crucibleReleaseUrl"); then
|
||||
log "ERROR: failed to access ${CRUCIBLE_RELEASE} release of Crucible for libraries"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Downloading Crucible libraries"
|
||||
if ! get -o /tmp/libraries.zip "$librariesUrl"; then
|
||||
log "ERROR: failed to download Crucible libraries from $librariesUrl"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! unzip /tmp/libraries.zip -d "$librariesDir"; then
|
||||
log "ERROR: failed to unzip Crucible libraries"
|
||||
exit 1
|
||||
fi
|
||||
rm /tmp/libraries.zip
|
||||
fi
|
||||
|
||||
export SERVER
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec "${SCRIPTS:-$(dirname "$0")}/start-setupWorld" "$@"
|
||||
35
scripts/start-deployCustom
Executable file
35
scripts/start-deployCustom
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
if isURL ${CUSTOM_SERVER}; then
|
||||
filename=$(basename ${CUSTOM_SERVER})
|
||||
export SERVER=/data/${filename}
|
||||
|
||||
if [[ -f ${SERVER} ]] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
log "Using previously downloaded jar at ${SERVER}"
|
||||
else
|
||||
log "Downloading custom server jar from ${CUSTOM_SERVER} ..."
|
||||
if ! curl -sSL -o ${SERVER} ${CUSTOM_SERVER}; then
|
||||
log "Failed to download from ${CUSTOM_SERVER}"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
elif [[ -f ${CUSTOM_SERVER} ]]; then
|
||||
export SERVER=${CUSTOM_SERVER}
|
||||
|
||||
elif [[ ${GENERIC_PACK} ]]; then
|
||||
log "Using custom server jar from generic pack at ${CUSTOM_SERVER} ..."
|
||||
export SERVER=${CUSTOM_SERVER}
|
||||
|
||||
else
|
||||
log "CUSTOM_SERVER is not properly set to a URL or existing jar file"
|
||||
exit 2
|
||||
|
||||
fi
|
||||
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
82
scripts/start-deployFTBA
Executable file
82
scripts/start-deployFTBA
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/bin/bash
|
||||
|
||||
ftbInstallMarker=".ftb-installed"
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
set -e
|
||||
|
||||
if ! [[ -v FTB_MODPACK_ID ]]; then
|
||||
log "ERROR FTB_MODPACK_ID is required with TYPE=FTB"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [[ ${FTB_MODPACK_ID} =~ [0-9]+ ]]; then
|
||||
log "ERROR FTB_MODPACK_ID needs to be numeric"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ! $FTB_MODPACK_VERSION_ID ]]; then
|
||||
if ! FTB_MODPACK_VERSION_ID=$(curl -fsSL https://api.modpacks.ch/public/modpack/${FTB_MODPACK_ID} | jq -r '.versions | sort_by(.updated)[-1].id'); then
|
||||
log "ERROR unable to resolve latest modpack version ID for modpack ${FTB_MODPACK_ID}"
|
||||
exit 1
|
||||
fi
|
||||
elif ! [[ ${FTB_MODPACK_VERSION_ID} =~ [0-9]+ ]]; then
|
||||
log "ERROR FTB_MODPACK_VERSION_ID needs to be numeric"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! [ -f "${ftbInstallMarker}" ] || [ $(cat "${ftbInstallMarker}") != "${FTB_MODPACK_ID}=${FTB_MODPACK_VERSION_ID}" ]; then
|
||||
ftbInstaller=/data/ftb-installer
|
||||
if ! [[ -f "${ftbInstaller}" ]]; then
|
||||
log "Downloading FTB installer"
|
||||
if [ "$(uname -m)" == "aarch64" ]; then
|
||||
log "Downloading ARM installer"
|
||||
curl -fsSL https://api.modpacks.ch/public/modpack/1/1/server/arm/linux -o "${ftbInstaller}"
|
||||
else
|
||||
log "Downloading x86 installer"
|
||||
curl -fsSL https://api.modpacks.ch/public/modpack/1/1/server/linux -o "${ftbInstaller}"
|
||||
fi
|
||||
chmod +x "${ftbInstaller}"
|
||||
fi
|
||||
|
||||
rm -rf forge*jar mods config libraries defaultconfigs changelogs
|
||||
|
||||
log "Installing modpack ID ${FTB_MODPACK_ID}, version ID ${FTB_MODPACK_VERSION_ID}"
|
||||
${ftbInstaller} ${FTB_MODPACK_ID} ${FTB_MODPACK_VERSION_ID} --noscript --auto
|
||||
rm -f forge*installer.jar
|
||||
|
||||
echo "${FTB_MODPACK_ID}=${FTB_MODPACK_VERSION_ID}" > ${ftbInstallMarker}
|
||||
|
||||
writeEula
|
||||
|
||||
# some modpacks result in --w----r-- permissions
|
||||
chmod a+r version.json
|
||||
else
|
||||
log "FTB modpack ID ${FTB_MODPACK_ID}, version ID ${FTB_MODPACK_VERSION_ID} is ready to go"
|
||||
fi
|
||||
|
||||
isDebugging && cat version.json
|
||||
forgeVersion=$(jq -r '.targets|unique[] | select(.name == "forge") | .version' version.json)
|
||||
fabricVersion=$(jq -r '.targets|unique[] | select(.name == "fabric") | .version' version.json)
|
||||
mcVersion=$(jq -r '.targets|unique[] | select(.name == "minecraft") | .version' version.json)
|
||||
|
||||
variants=(
|
||||
forge-${mcVersion}-${forgeVersion}.jar
|
||||
forge-${mcVersion}-${forgeVersion}-universal.jar
|
||||
forge-${mcVersion}-${forgeVersion}-${mcVersion}-universal.jar
|
||||
fabric-${mcVersion}-${fabricVersion}-server-launch.jar
|
||||
)
|
||||
for f in ${variants[@]}; do
|
||||
if [ -f $f ]; then
|
||||
export SERVER=$f
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ! [ -v SERVER ]; then
|
||||
log "ERROR unable to locate the installed FTB server jar"
|
||||
ls *.jar
|
||||
exit 2
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
72
scripts/start-deployFabric
Executable file
72
scripts/start-deployFabric
Executable file
@@ -0,0 +1,72 @@
|
||||
#!/bin/bash
|
||||
set -eu
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
requireVar VANILLA_VERSION
|
||||
export TYPE=FABRIC
|
||||
export SERVER=fabric-server-${VANILLA_VERSION}.jar
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
if [[ ! -e ${SERVER} ]]; then
|
||||
|
||||
: ${FABRIC_INSTALLER:=}
|
||||
: ${FABRIC_INSTALLER_URL:=}
|
||||
: ${FABRIC_LOADER_VERSION:=LATEST}
|
||||
: ${FABRIC_INSTALLER_VERSION:=${FABRICVERSION:-LATEST}}
|
||||
|
||||
if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
|
||||
log "Checking Fabric version information."
|
||||
if [[ ${FABRIC_INSTALLER_VERSION^^} = LATEST ]]; then
|
||||
FABRIC_INSTALLER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
|
||||
fi
|
||||
|
||||
FABRIC_INSTALLER="fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
|
||||
FABRIC_INSTALLER_URL="https://maven.fabricmc.net/net/fabricmc/fabric-installer/${FABRIC_INSTALLER_VERSION}/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
|
||||
elif [[ -z $FABRIC_INSTALLER ]]; then
|
||||
FABRIC_INSTALLER="fabric-installer.jar"
|
||||
elif [[ ! -e $FABRIC_INSTALLER ]]; then
|
||||
log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [[ -z $FABRIC_LOADER_VERSION || ${FABRIC_LOADER_VERSION^^} = LATEST ]]; then
|
||||
log "Checking Fabric Loader version information."
|
||||
|
||||
FABRIC_LOADER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-loader/maven-metadata.xml)
|
||||
fi
|
||||
|
||||
if [[ ! -e $FABRIC_INSTALLER ]]; then
|
||||
log "Downloading $FABRIC_INSTALLER_URL ..."
|
||||
if ! get -o "$FABRIC_INSTALLER" "$FABRIC_INSTALLER_URL"; then
|
||||
log "Failed to download from given location $FABRIC_INSTALLER_URL"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Installing Fabric ${VANILLA_VERSION} using $FABRIC_INSTALLER with loader version $FABRIC_LOADER_VERSION"
|
||||
|
||||
tries=3
|
||||
set +e
|
||||
while ((--tries >= 0)); do
|
||||
java -jar $FABRIC_INSTALLER server \
|
||||
-mcversion $VANILLA_VERSION \
|
||||
-loader $FABRIC_LOADER_VERSION \
|
||||
-downloadMinecraft \
|
||||
-dir /data
|
||||
if [[ $? == 0 ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
set -e
|
||||
if (($tries < 0)); then
|
||||
log "Fabric failed to install after several tries." >&2
|
||||
exit 10
|
||||
fi
|
||||
|
||||
mv fabric-server-launch.jar "${SERVER}"
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||
150
scripts/start-deployForge
Executable file
150
scripts/start-deployForge
Executable file
@@ -0,0 +1,150 @@
|
||||
#!/bin/bash
|
||||
|
||||
: "${FORGEVERSION:=RECOMMENDED}"
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-$(dirname "$0")}/start-utils"
|
||||
isDebugging && set -x
|
||||
|
||||
get_installer() {
|
||||
if [[ -z $FORGE_INSTALLER_URL ]]; then
|
||||
log "Downloading $normForgeVersion"
|
||||
|
||||
forgeFileNames="
|
||||
$normForgeVersion/forge-$normForgeVersion-installer.jar
|
||||
$shortForgeVersion/forge-$shortForgeVersion-installer.jar
|
||||
"
|
||||
|
||||
for fn in $forgeFileNames; do
|
||||
downloadUrl=https://maven.minecraftforge.net/net/minecraftforge/forge/$fn
|
||||
log "...trying $downloadUrl"
|
||||
if get -o "$FORGE_INSTALLER" "$downloadUrl"; then
|
||||
return
|
||||
fi
|
||||
done
|
||||
log "Unable to locate usable URL for $normForgeVersion"
|
||||
exit 2
|
||||
else
|
||||
log "Downloading $FORGE_INSTALLER_URL ..."
|
||||
if ! get -o "$FORGE_INSTALLER" "$FORGE_INSTALLER_URL"; then
|
||||
log "Failed to download from given location $FORGE_INSTALLER_URL"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
install() {
|
||||
if [ ! -e "$FORGE_INSTALLER" ]; then
|
||||
get_installer "$normForgeVersion" "$shortForgeVersion"
|
||||
fi
|
||||
|
||||
log "Installing Forge $shortForgeVersion using $FORGE_INSTALLER"
|
||||
mkdir -p mods
|
||||
tries=3
|
||||
while ((--tries >= 0)); do
|
||||
if java -jar "$FORGE_INSTALLER" --installServer; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ((tries < 0)); then
|
||||
log "Forge failed to install after several tries." >&2
|
||||
exit 10
|
||||
fi
|
||||
# NOTE $shortForgeVersion will be empty if installer location was given to us
|
||||
log "Finding installed server jar..."
|
||||
unset -v latest
|
||||
# 1.17+ ?
|
||||
if [ -f /data/run.sh ]; then
|
||||
latest=/data/run.sh
|
||||
# else pre 1.17
|
||||
else
|
||||
for file in *forge*.jar; do
|
||||
if ! [[ $file =~ installer ]]; then
|
||||
if [[ -z $latest ]] || [[ $file -nt $latest ]]; then
|
||||
latest=$file
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
if [[ -z $latest ]]; then
|
||||
log "Unable to derive server jar for Forge"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
export SERVER=$latest
|
||||
log "Using server $SERVER"
|
||||
debug "Writing install marker at $installMarker"
|
||||
echo "$SERVER" > "$installMarker"
|
||||
}
|
||||
|
||||
resolve_versions() {
|
||||
if [[ -z $FORGE_INSTALLER && -z $FORGE_INSTALLER_URL ]]; then
|
||||
norm=$VANILLA_VERSION
|
||||
|
||||
case $VANILLA_VERSION in
|
||||
*.*.*)
|
||||
norm=$VANILLA_VERSION ;;
|
||||
*.*)
|
||||
norm=${VANILLA_VERSION}.0 ;;
|
||||
esac
|
||||
|
||||
#################################################################################
|
||||
promosUrl=http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json
|
||||
|
||||
log "Checking Forge version information."
|
||||
case $FORGEVERSION in
|
||||
LATEST)
|
||||
if ! FORGE_VERSION=$(get --json-path ".promos['$VANILLA_VERSION-latest']" "$promosUrl"); then
|
||||
log "ERROR: Version $VANILLA_VERSION is not supported by Forge"
|
||||
log " Refer to http://files.minecraftforge.net/ for supported versions"
|
||||
exit 2
|
||||
fi
|
||||
;;
|
||||
|
||||
RECOMMENDED)
|
||||
if ! FORGE_VERSION=$(get --json-path ".promos['$VANILLA_VERSION-recommended']" "$promosUrl"); then
|
||||
if ! FORGE_VERSION=$(get --json-path ".promos['$VANILLA_VERSION-latest']" "$promosUrl"); then
|
||||
log "ERROR: Version $VANILLA_VERSION is not supported by Forge"
|
||||
log " Refer to http://files.minecraftforge.net/ for supported versions"
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
FORGE_VERSION=$FORGEVERSION
|
||||
;;
|
||||
esac
|
||||
|
||||
normForgeVersion=$VANILLA_VERSION-$FORGE_VERSION-$norm
|
||||
shortForgeVersion=$VANILLA_VERSION-$FORGE_VERSION
|
||||
|
||||
FORGE_INSTALLER="/tmp/forge-$shortForgeVersion-installer.jar"
|
||||
elif [[ -z $FORGE_INSTALLER ]]; then
|
||||
FORGE_INSTALLER="/tmp/forge-installer.jar"
|
||||
elif [[ ! -e $FORGE_INSTALLER ]]; then
|
||||
log "ERROR: the given Forge installer doesn't exist : $FORGE_INSTALLER"
|
||||
exit 2
|
||||
else
|
||||
shortForgeVersion=$VANILLA_VERSION-${FORGE_INSTALLER_CUSTOM_VERSION:-custom}
|
||||
fi
|
||||
}
|
||||
|
||||
### main
|
||||
|
||||
resolve_versions
|
||||
|
||||
installMarker="/data/.forge-installed-$shortForgeVersion"
|
||||
|
||||
if [ ! -e "$installMarker" ] || isTrue "${FORCE_REINSTALL:-false}"; then
|
||||
install
|
||||
else
|
||||
SERVER=$(cat "$installMarker")
|
||||
export SERVER
|
||||
if [ ! -e "$SERVER" ]; then
|
||||
rm "$installMarker"
|
||||
install
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
63
scripts/start-deployLimbo
Executable file
63
scripts/start-deployLimbo
Executable file
@@ -0,0 +1,63 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
: ${LIMBO_BUILD:=LATEST}
|
||||
: ${FORCE_REDOWNLOAD:=false}
|
||||
: ${LIMBO_SCHEMA_FILENAME:=default.schem}
|
||||
: ${LEVEL:=Default;${LIMBO_SCHEMA_FILENAME}}
|
||||
# defaults to localhost, if this is not set
|
||||
: ${SERVER_IP:=0.0.0.0}
|
||||
|
||||
export LEVEL SERVER_IP
|
||||
|
||||
if [[ ${LIMBO_BUILD^^} == LATEST ]]; then
|
||||
LIMBO_BUILD=lastStableBuild
|
||||
fi
|
||||
|
||||
baseUrl="https://ci.loohpjames.com/job/Limbo/${LIMBO_BUILD}"
|
||||
buildInfoUrl="${baseUrl}/api/json"
|
||||
buildJson=$(curl -fsSL "${buildInfoUrl}")
|
||||
if [ $? != 0 ]; then
|
||||
log "ERROR failed to get build info from ${buildInfoUrl} (status=$?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${LIMBO_BUILD} = lastStableBuild ]]; then
|
||||
LIMBO_BUILD=$(jq -r '.number' <<<${buildJson})
|
||||
log "Resolved latest Limbo build to ${LIMBO_BUILD}"
|
||||
fi
|
||||
artifactPath=$(jq -r '.artifacts[] | select(.fileName|test("^Limbo-")) | .relativePath' <<<${buildJson})
|
||||
defaultSchemaPath=$(jq -r '.artifacts[] | select(.fileName|test(".*\\.schem")) | .relativePath' <<<${buildJson})
|
||||
|
||||
export SERVER="limbo-${LIMBO_BUILD}.jar"
|
||||
|
||||
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
|
||||
downloadUrl="${baseUrl}/artifact/${artifactPath}"
|
||||
log "Downloading Limbo from $downloadUrl ..."
|
||||
if ! curl -fsSL -o "$SERVER" "$downloadUrl"; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
if [ ! -f "${LIMBO_SCHEMA_FILENAME}" ]; then
|
||||
log "Downloading default schem file"
|
||||
if ! curl -o "${LIMBO_SCHEMA_FILENAME}" -fsSL "${baseUrl}/artifact/${defaultSchemaPath}"; then
|
||||
log "ERROR: failed to download schema file $baseUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ ${LEVEL} != *\;* ]]; then
|
||||
LEVEL="${LEVEL};${LIMBO_SCHEMA_FILENAME}"
|
||||
fi
|
||||
export LEVEL
|
||||
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
92
scripts/start-deployMagma
Executable file
92
scripts/start-deployMagma
Executable file
@@ -0,0 +1,92 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
: ${VANILLA_VERSION?}
|
||||
# stable, dev
|
||||
: ${MAGMA_CHANNEL:=stable}
|
||||
|
||||
|
||||
magmaDownloadServer() {
|
||||
url=${1?}
|
||||
tagName=${2?}
|
||||
markerFile=${3?}
|
||||
|
||||
export SERVER="/data/magma-server-${VANILLA_VERSION}.jar"
|
||||
|
||||
log "Downloading Magma server file for ${VANILLA_VERSION} @ ${tagName}"
|
||||
if ! curl -o /data/magma-server-${VANILLA_VERSION}.jar -fsSL "$url"; then
|
||||
log "ERROR failed to download Magma server from $url (status=$?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -n "$SERVER" > "$markerFile"
|
||||
}
|
||||
|
||||
magmaHandleInstaller() {
|
||||
url=${1?}
|
||||
tagName=${2?}
|
||||
markerFile=${3?}
|
||||
|
||||
installerFile="magma-installer-${VANILLA_VERSION}-${tagName}.jar"
|
||||
log "Downloading Magma installer file for ${VANILLA_VERSION} @ ${tagName}"
|
||||
if ! curl -o "$installerFile" -fsSL "$url"; then
|
||||
log "ERROR failed to download Magma installer from $url (status=$?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "forge" > "$markerFile"
|
||||
|
||||
export FORGE_INSTALLER="$installerFile"
|
||||
export FORGE_INSTALLER_CUSTOM_VERSION="$tagName"
|
||||
|
||||
# now hand off the rest to forge
|
||||
exec ${SCRIPTS:-/}start-deployForge "$@"
|
||||
}
|
||||
|
||||
latestMeta=$(curl -fsSL https://api.magmafoundation.org/api/resources/Magma/${VANILLA_VERSION}/${MAGMA_CHANNEL}/latest || exit $?)
|
||||
if [ $? != 0 ]; then
|
||||
log "ERROR failed to locate latest Magma info for ${VANILLA_VERSION} in channel ${MAGMA_CHANNEL} (error=$?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
tagName=$(echo "${latestMeta}" | jq -r '.tag_name')
|
||||
markerFile=".magma-installed-${VANILLA_VERSION}-${tagName}"
|
||||
if [ -f "${markerFile}" ]; then
|
||||
installedTagName=$(cat "${markerFile}")
|
||||
fi
|
||||
|
||||
if [ ! -f "${markerFile}" ]; then
|
||||
|
||||
if versionLessThan 1.16; then
|
||||
assetType=server
|
||||
else
|
||||
assetType=installer
|
||||
fi
|
||||
|
||||
assetUrl=$(echo "${latestMeta}" | jq -r ".assets | .[].browser_download_url | select(test(\"${assetType}\"))")
|
||||
if [ $? != 0 ] || [ -z "$assetUrl" ]; then
|
||||
log "ERROR failed to extract ${assetType} asset type for ${VANILLA_VERSION} in channel ${MAGMA_CHANNEL}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${assetType} = server ]]; then
|
||||
magmaDownloadServer "$assetUrl" "$tagName" "$markerFile"
|
||||
else
|
||||
magmaHandleInstaller "$assetUrl" "$tagName" "$markerFile"
|
||||
fi
|
||||
else
|
||||
export SERVER=$(cat "${markerFile}")
|
||||
|
||||
if [[ $SERVER == "forge" ]]; then
|
||||
export FORGE_INSTALLER="magma-installer-${VANILLA_VERSION}-${tagName}.jar"
|
||||
export FORGE_INSTALLER_CUSTOM_VERSION="$tagName"
|
||||
# now hand off the rest to forge
|
||||
exec ${SCRIPTS:-/}start-deployForge "$@"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
43
scripts/start-deployMohist
Executable file
43
scripts/start-deployMohist
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-$(dirname "$0")}/start-utils"
|
||||
set -o pipefail
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
|
||||
requireVar VANILLA_VERSION
|
||||
: "${MOHIST_BUILD:=lastSuccessfulBuild}"
|
||||
|
||||
mohistJobs=https://ci.codemc.io/job/MohistMC/job/
|
||||
mohistJob=${mohistJobs}Mohist-${VANILLA_VERSION}/
|
||||
|
||||
if ! get --exists "${mohistJob}"; then
|
||||
log "ERROR: mohist builds do not exist for ${VANILLA_VERSION}"
|
||||
log " check https://ci.codemc.io/job/MohistMC/ for available versions"
|
||||
log " and set VERSION accordingly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
buildRelPath=$(
|
||||
get --json-path '$.artifacts[0].relativePath' "${mohistJob}${MOHIST_BUILD}/api/json"
|
||||
)
|
||||
|
||||
baseName=$(basename "${buildRelPath}")
|
||||
if [[ ${baseName} != *-server.jar* ]]; then
|
||||
log "ERROR: mohist build for ${VANILLA_VERSION} is not a valid server jar, found ${baseName}"
|
||||
log " check https://ci.codemc.io/job/MohistMC/ for available versions"
|
||||
log " and set VERSION accordingly"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export SERVER="/data/${baseName}"
|
||||
|
||||
if [ ! -f "${SERVER}" ]; then
|
||||
log "Downloading ${baseName}"
|
||||
get -o "${SERVER}" "${mohistJob}${MOHIST_BUILD}/artifact/${buildRelPath}"
|
||||
fi
|
||||
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec "${SCRIPTS:-$(dirname "$0")}/start-setupWorld" "$@"
|
||||
79
scripts/start-deployPaper
Executable file
79
scripts/start-deployPaper
Executable file
@@ -0,0 +1,79 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -o pipefail
|
||||
isDebugging && set -x
|
||||
|
||||
if [[ $PAPER_DOWNLOAD_URL ]]; then
|
||||
export SERVER=$(getFilenameFromUrl "${PAPER_DOWNLOAD_URL}")
|
||||
|
||||
if [ -f "$SERVER" ]; then
|
||||
zarg=(-z "$SERVER")
|
||||
fi
|
||||
|
||||
echo "Preparing custom PaperMC jar from $PAPER_DOWNLOAD_URL"
|
||||
|
||||
curl -fsSL -o "$SERVER" "${zarg[@]}" "${PAPER_DOWNLOAD_URL}"
|
||||
else
|
||||
# PaperMC API v2 docs : https://papermc.io/api/docs/swagger-ui/index.html?configUrl=/api/openapi/swagger-config
|
||||
|
||||
build=${PAPERBUILD:=$(curl -fsSL "https://papermc.io/api/v2/projects/paper/versions/${VANILLA_VERSION}" -H "accept: application/json" \
|
||||
| jq '.builds[-1]')}
|
||||
case $? in
|
||||
0)
|
||||
;;
|
||||
22)
|
||||
versions=$(curl -fsSL "https://papermc.io/api/v2/projects/paper" -H "accept: application/json")
|
||||
if [[ $VERSION = LATEST ]]; then
|
||||
VANILLA_VERSION=$(echo "$versions" | jq -r '.versions[-1]')
|
||||
log "WARN: using ${VANILLA_VERSION} since that's the latest provided by PaperMC"
|
||||
# re-execute the current script with the newly computed version
|
||||
exec "$0" "$@"
|
||||
fi
|
||||
log "ERROR: ${VANILLA_VERSION} is not published by PaperMC"
|
||||
log " Set VERSION to one of the following: "
|
||||
log " $(echo "$versions" | jq -r '.versions | join(", ")')"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown error while looking up PaperMC version=${VANILLA_VERSION}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if [ $? != 0 ]; then
|
||||
echo "ERROR: failed to lookup PaperMC build from version ${VANILLA_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export SERVER=$(curl -fsSL "https://papermc.io/api/v2/projects/paper/versions/${VANILLA_VERSION}/builds/${build}" -H "accept: application/json" \
|
||||
| jq -r '.downloads.application.name')
|
||||
if [ $? != 0 ]; then
|
||||
echo "ERROR: failed to lookup PaperMC download file from version=${VANILLA_VERSION} build=${build}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "$SERVER" ]; then
|
||||
zarg=(-z "$SERVER")
|
||||
fi
|
||||
|
||||
log "Removing old PaperMC versions ..."
|
||||
shopt -s nullglob
|
||||
for f in paper-*.jar; do
|
||||
[[ $f != $SERVER ]] && rm $f
|
||||
done
|
||||
|
||||
log "Downloading PaperMC $VANILLA_VERSION (build $build) ..."
|
||||
curl -fsSL -o "$SERVER" "${zarg[@]}" \
|
||||
"https://papermc.io/api/v2/projects/paper/versions/${VANILLA_VERSION}/builds/${build}/downloads/${SERVER}" \
|
||||
-H "accept: application/java-archive"
|
||||
if [ $? != 0 ]; then
|
||||
echo "ERROR: failed to download PaperMC from version=${VANILLA_VERSION} build=${build} download=${SERVER}"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for downstream operations
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
37
scripts/start-deployPurpur
Executable file
37
scripts/start-deployPurpur
Executable file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
: ${VANILLA_VERSION:?}
|
||||
: ${PURPUR_BUILD:=LATEST}
|
||||
: ${FORCE_REDOWNLOAD:=false}
|
||||
|
||||
if [[ ${PURPUR_BUILD} == LATEST ]]; then
|
||||
PURPUR_BUILD=$(curl -fsSL "https://api.pl3x.net/v2/purpur/${VANILLA_VERSION}" |
|
||||
jq -r '.builds.latest' || echo "")
|
||||
if [[ -z ${PURPUR_BUILD} ]]; then
|
||||
log "ERROR: Failed to locate a Purpur build for ${VANILLA_VERSION}."
|
||||
log " Please check if a download is available at https://purpur.pl3x.net/downloads/"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
export SERVER="purpur-${VANILLA_VERSION}-${PURPUR_BUILD}.jar"
|
||||
|
||||
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
|
||||
downloadUrl="https://api.pl3x.net/v2/purpur/${VANILLA_VERSION}/${PURPUR_BUILD}/download"
|
||||
log "Downloading Purpur from $downloadUrl ..."
|
||||
if ! curl -fsSL -o "$SERVER" "$downloadUrl"; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for later operations
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
40
scripts/start-deploySpongeVanilla
Executable file
40
scripts/start-deploySpongeVanilla
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
export TYPE=spongevanilla
|
||||
: ${SPONGEBRANCH:=STABLE}
|
||||
: ${SPONGEVERSION:=}
|
||||
|
||||
# Parse branch
|
||||
log "Choosing branch for Sponge"
|
||||
case "$SPONGEBRANCH" in
|
||||
|
||||
EXPERIMENTAL|experimental|BLEEDING|bleeding)
|
||||
SPONGEBRANCH=bleeding
|
||||
;;
|
||||
|
||||
*)
|
||||
SPONGEBRANCH=stable
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
# If not SPONGEVERSION selected, detect last version on selected branch
|
||||
if [ -z $SPONGEVERSION ]; then
|
||||
log "Choosing Version for Sponge"
|
||||
if [ "$SPONGEBRANCH" == "stable" ]; then
|
||||
export SPONGEVERSION=`curl -fsSL https://dl-api.spongepowered.org/v1/org.spongepowered/$TYPE | jq -r '.buildTypes.stable.latest.version'`
|
||||
else
|
||||
export SPONGEVERSION=`curl -fsSL https://dl-api.spongepowered.org/v1/org.spongepowered/$TYPE | jq -r '.buildTypes.bleeding.latest.version'`
|
||||
fi
|
||||
fi
|
||||
|
||||
export SERVER="spongevanilla-$SPONGEVERSION.jar"
|
||||
|
||||
if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
log "Downloading $SERVER ..."
|
||||
curl -sSL -o $SERVER https://repo.spongepowered.org/maven/org/spongepowered/$TYPE/$SPONGEVERSION/$SERVER
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
46
scripts/start-deployVanilla
Executable file
46
scripts/start-deployVanilla
Executable file
@@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
isDebugging && set -x
|
||||
set -o pipefail
|
||||
|
||||
export SERVER="minecraft_server.${VANILLA_VERSION// /_}.jar"
|
||||
|
||||
if [ ! -e "$SERVER" ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
log "Downloading $SERVER ..."
|
||||
debug "Finding version manifest for $VANILLA_VERSION"
|
||||
versionManifestUrl=$(get 'https://launchermeta.mojang.com/mc/game/version_manifest.json' | jq --arg VANILLA_VERSION "$VANILLA_VERSION" --raw-output '[.versions[]|select(.id == $VANILLA_VERSION)][0].url')
|
||||
result=$?
|
||||
if [ $result != 0 ]; then
|
||||
log "ERROR failed to obtain version manifest URL ($result)"
|
||||
exit 1
|
||||
fi
|
||||
if [ "$versionManifestUrl" = "null" ]; then
|
||||
log "ERROR couldn't find a matching manifest entry for $VANILLA_VERSION"
|
||||
exit 1
|
||||
fi
|
||||
debug "Found version manifest at $versionManifestUrl"
|
||||
|
||||
serverDownloadUrl=$(get --json-path '$.downloads.server.url' "${versionManifestUrl}")
|
||||
result=$?
|
||||
if [ $result != 0 ]; then
|
||||
log "ERROR failed to obtain version manifest from $versionManifestUrl ($result)"
|
||||
exit 1
|
||||
elif [ "$serverDownloadUrl" = "null" ]; then
|
||||
log "ERROR version $VANILLA_VERSION does not provide a server download"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
debug "Downloading server from $serverDownloadUrl"
|
||||
get -o "$SERVER" "$serverDownloadUrl"
|
||||
result=$?
|
||||
if [ $result != 0 ]; then
|
||||
log "ERROR failed to download server from $serverDownloadUrl ($result)"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
isDebugging && ls -l
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
261
scripts/start-finalExec
Executable file
261
scripts/start-finalExec
Executable file
@@ -0,0 +1,261 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
if [ -n "$OPS" ]; then
|
||||
log "Updating ops"
|
||||
rm -f /data/ops.txt.converted
|
||||
echo $OPS | awk -v RS=, '{print}' > /data/ops.txt
|
||||
fi
|
||||
if isTrue "${OVERRIDE_OPS}"; then
|
||||
log "Recreating ops.json file at server startup"
|
||||
rm -f /data/ops.json
|
||||
fi
|
||||
|
||||
if [ -n "$WHITELIST" ]; then
|
||||
log "Updating whitelist"
|
||||
rm -f /data/white-list.txt.converted
|
||||
echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt
|
||||
fi
|
||||
if isTrue "${OVERRIDE_WHITELIST}"; then
|
||||
log "Recreating whitelist.json file at server startup"
|
||||
rm -f /data/whitelist.json
|
||||
fi
|
||||
|
||||
if [ -n "$ICON" ]; then
|
||||
if [ ! -e server-icon.png ] || [ "${OVERRIDE_ICON}" == "TRUE" ]; then
|
||||
log "Using server icon from $ICON..."
|
||||
# Not sure what it is yet...call it "img"
|
||||
curl -sSL -o /tmp/icon.img $ICON
|
||||
specs=$(identify /tmp/icon.img | awk '{print $2,$3}')
|
||||
if [ "$specs" = "PNG 64x64" ]; then
|
||||
mv /tmp/icon.img /data/server-icon.png
|
||||
else
|
||||
log "Converting image to 64x64 PNG..."
|
||||
convert /tmp/icon.img -resize 64x64! /data/server-icon.png
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if isTrue ${ENABLE_ROLLING_LOGS:-false}; then
|
||||
# Set up log configuration
|
||||
LOGFILE="/data/log4j2.xml"
|
||||
if [ ! -e "$LOGFILE" ]; then
|
||||
log "Creating log4j2.xml in ${LOGFILE}"
|
||||
cp /tmp/log4j2.xml "$LOGFILE"
|
||||
else
|
||||
log "log4j2.xml already created, skipping"
|
||||
fi
|
||||
JVM_OPTS="-Dlog4j.configurationFile=/data/log4j2.xml ${JVM_OPTS}"
|
||||
fi
|
||||
|
||||
# Make sure files exist and are valid JSON (for pre-1.12 to 1.12 upgrades)
|
||||
log "Checking for JSON files."
|
||||
JSON_FILES=$(find /data -maxdepth 1 -name '*.json')
|
||||
for j in $JSON_FILES; do
|
||||
if [[ $(cat "$j" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//') == "" ]]; then
|
||||
log "Fixing JSON $j"
|
||||
echo '[]' > $j
|
||||
fi
|
||||
done
|
||||
|
||||
# Optional disable console
|
||||
if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
|
||||
EXTRA_ARGS+=" --noconsole"
|
||||
fi
|
||||
|
||||
# Optional disable GUI for headless servers
|
||||
if [[ ${GUI} = false || ${GUI} = FALSE ]]; then
|
||||
EXTRA_ARGS+=" nogui"
|
||||
fi
|
||||
|
||||
# put these prior JVM_OPTS at the end to give any memory settings there higher precedence
|
||||
log "Setting initial memory to ${INIT_MEMORY:=${MEMORY}} and max to ${MAX_MEMORY:=${MEMORY}}"
|
||||
|
||||
expandedDOpts=
|
||||
if [ -n "$JVM_DD_OPTS" ]; then
|
||||
for dopt in $JVM_DD_OPTS
|
||||
do
|
||||
expandedDOpts="${expandedDOpts} -D${dopt/:/=}"
|
||||
done
|
||||
fi
|
||||
|
||||
if isTrue ${ENABLE_JMX}; then
|
||||
: ${JMX_PORT:=7091}
|
||||
JVM_OPTS="${JVM_OPTS}
|
||||
-Dcom.sun.management.jmxremote.local.only=false
|
||||
-Dcom.sun.management.jmxremote.port=${JMX_PORT}
|
||||
-Dcom.sun.management.jmxremote.rmi.port=${JMX_PORT}
|
||||
-Dcom.sun.management.jmxremote.authenticate=false
|
||||
-Dcom.sun.management.jmxremote.ssl=false
|
||||
-Dcom.sun.management.jmxremote.host=${JMX_BINDING:-0.0.0.0}
|
||||
-Djava.rmi.server.hostname=${JMX_HOST:-localhost}"
|
||||
|
||||
log "JMX is enabled. Make sure you have port forwarding for ${JMX_PORT}"
|
||||
fi
|
||||
|
||||
if isTrue "${USE_AIKAR_FLAGS}"; then
|
||||
# From https://mcflags.emc.gs/
|
||||
|
||||
if (( $(normalizeMemSize "${MAX_MEMORY}") >= $(normalizeMemSize 12g) )); then
|
||||
log "Using Aikar's >12GB flags"
|
||||
G1NewSizePercent=40
|
||||
G1MaxNewSizePercent=50
|
||||
G1HeapRegionSize=16M
|
||||
G1ReservePercent=15
|
||||
InitiatingHeapOccupancyPercent=20
|
||||
else
|
||||
log "Using Aikar's flags"
|
||||
G1NewSizePercent=30
|
||||
G1MaxNewSizePercent=40
|
||||
G1HeapRegionSize=8M
|
||||
G1ReservePercent=20
|
||||
InitiatingHeapOccupancyPercent=15
|
||||
fi
|
||||
|
||||
JVM_XX_OPTS="${JVM_XX_OPTS}
|
||||
-XX:+UseG1GC
|
||||
-XX:+ParallelRefProcEnabled
|
||||
-XX:MaxGCPauseMillis=200
|
||||
-XX:+UnlockExperimentalVMOptions
|
||||
-XX:+DisableExplicitGC
|
||||
-XX:+AlwaysPreTouch
|
||||
-XX:G1NewSizePercent=${G1NewSizePercent}
|
||||
-XX:G1MaxNewSizePercent=${G1MaxNewSizePercent}
|
||||
-XX:G1HeapRegionSize=${G1HeapRegionSize}
|
||||
-XX:G1ReservePercent=${G1ReservePercent}
|
||||
-XX:G1HeapWastePercent=5
|
||||
-XX:G1MixedGCCountTarget=4
|
||||
-XX:InitiatingHeapOccupancyPercent=${InitiatingHeapOccupancyPercent}
|
||||
-XX:G1MixedGCLiveThresholdPercent=90
|
||||
-XX:G1RSetUpdatingPauseTimePercent=5
|
||||
-XX:SurvivorRatio=32
|
||||
-XX:+PerfDisableSharedMem
|
||||
-XX:MaxTenuringThreshold=1
|
||||
-Dusing.aikars.flags=https://mcflags.emc.gs
|
||||
-Daikars.new.flags=true
|
||||
"
|
||||
fi
|
||||
|
||||
if isTrue "${USE_LARGE_PAGES}"; then
|
||||
JVM_XX_OPTS="${JVM_XX_OPTS}
|
||||
-XX:+UseLargePagesInMetaspace
|
||||
"
|
||||
fi
|
||||
|
||||
if isTrue "${USE_FLARE_FLAGS}"; then
|
||||
JVM_XX_OPTS="${JVM_XX_OPTS}
|
||||
-XX:+UnlockDiagnosticVMOptions
|
||||
-XX:+DebugNonSafepoints
|
||||
"
|
||||
fi
|
||||
|
||||
if isTrue "${DEBUG_MEMORY}"; then
|
||||
log "Memory usage and availability (in MB)"
|
||||
uname -a
|
||||
free -m
|
||||
fi
|
||||
|
||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||
|
||||
function copyFilesForCurseForge() {
|
||||
# copy player modification files unconditionally since their
|
||||
# processing into json is additive anyway
|
||||
[ -f /data/ops.txt ] && cp -f /data/ops.txt "${FTB_DIR}/"
|
||||
[ -f /data/white-list.txt ] && cp -f /data/white-list.txt "${FTB_DIR}/"
|
||||
|
||||
if [ ! -e "${FTB_DIR}/server-icon.png" -a -e /data/server-icon.png ]; then
|
||||
cp -f /data/server-icon.png "${FTB_DIR}/"
|
||||
fi
|
||||
|
||||
cp -f /data/eula.txt "${FTB_DIR}/"
|
||||
}
|
||||
|
||||
mcServerRunnerArgs=(
|
||||
--stop-duration "${STOP_DURATION:-60}s"
|
||||
--named-pipe "${CONSOLE_IN_NAMED_PIPE:-/tmp/minecraft-console-in}"
|
||||
)
|
||||
if [[ ${STOP_SERVER_ANNOUNCE_DELAY} ]]; then
|
||||
mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s")
|
||||
fi
|
||||
|
||||
if [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then
|
||||
copyFilesForCurseForge
|
||||
|
||||
cd "${FTB_DIR}" || (log "ERROR: can't go into ${FTB_DIR}"; exit 1)
|
||||
log "Starting CurseForge server in ${FTB_DIR}..."
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
exec mc-server-runner ${bootstrapArgs} "${mcServerRunnerArgs[@]}" java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar $(basename "${SERVER}") "$@" $EXTRA_ARGS
|
||||
elif [[ ${TYPE} == "CURSEFORGE" ]]; then
|
||||
mcServerRunnerArgs+=(--shell bash)
|
||||
|
||||
copyFilesForCurseForge
|
||||
|
||||
cat > "${FTB_DIR}/settings-local.sh" <<EOF
|
||||
export MIN_RAM="${INIT_MEMORY}"
|
||||
export MAX_RAM="${MAX_MEMORY}"
|
||||
export JAVA_PARAMETERS="${JVM_XX_OPTS} -Xms${INIT_MEMORY} ${JVM_OPTS} $expandedDOpts"
|
||||
EOF
|
||||
|
||||
# patch CurseForge cfg file, if present
|
||||
if [ -f "${FTB_DIR}/settings.cfg" ]; then
|
||||
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
|
||||
fi
|
||||
|
||||
cd "${FTB_DIR}" || (log "ERROR: can't go into ${FTB_DIR}"; exit 1)
|
||||
log "Running FTB ${FTB_SERVER_START} in ${FTB_DIR} ..."
|
||||
|
||||
finalArgs="${FTB_SERVER_START}"
|
||||
|
||||
if isTrue ${SETUP_ONLY:=false}; then
|
||||
echo "SETUP_ONLY: ${finalArgs}"
|
||||
exit
|
||||
fi
|
||||
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
if isTrue ${EXEC_DIRECTLY:-false}; then
|
||||
"${finalArgs[@]}"
|
||||
else
|
||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" "${finalArgs[@]}"
|
||||
fi
|
||||
elif [[ -x run.sh ]]; then
|
||||
log "Using Forge supplied run.sh script..."
|
||||
echo $JVM_XX_OPTS $JVM_OPTS $expandedDOpts > user_jvm_args.txt
|
||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" --shell bash run.sh
|
||||
else
|
||||
# If we have a bootstrap.txt file... feed that in to the server stdin
|
||||
if [ -f /data/bootstrap.txt ]; then
|
||||
bootstrapArgs="--bootstrap /data/bootstrap.txt"
|
||||
fi
|
||||
|
||||
log "Starting the Minecraft server..."
|
||||
|
||||
finalArgs=(
|
||||
$JVM_XX_OPTS
|
||||
$JVM_OPTS
|
||||
$expandedDOpts
|
||||
-jar "$SERVER"
|
||||
"$@" $EXTRA_ARGS
|
||||
)
|
||||
|
||||
if isTrue ${SETUP_ONLY:=false}; then
|
||||
echo "SETUP_ONLY: java ${finalArgs[*]}"
|
||||
exit
|
||||
fi
|
||||
|
||||
if isTrue ${DEBUG_EXEC}; then
|
||||
set -x
|
||||
fi
|
||||
|
||||
if isTrue ${EXEC_DIRECTLY:-false}; then
|
||||
exec java "${finalArgs[@]}"
|
||||
else
|
||||
exec mc-server-runner ${bootstrapArgs} "${mcServerRunnerArgs[@]}" java "${finalArgs[@]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
34
scripts/start-setupEnvVariables
Executable file
34
scripts/start-setupEnvVariables
Executable file
@@ -0,0 +1,34 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
set -e
|
||||
|
||||
: ${REPLACE_ENV_IN_PLACE:=${REPLACE_ENV_VARIABLES:-false}}
|
||||
: ${REPLACE_ENV_PATHS:=/data}
|
||||
: ${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}
|
||||
: ${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}
|
||||
: ${REPLACE_ENV_VARIABLES_EXCLUDES:=}
|
||||
: ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}
|
||||
: ${PATCH_DEFINITIONS:=}
|
||||
: ${DEBUG:=false}
|
||||
|
||||
if isTrue "${REPLACE_ENV_IN_PLACE}"; then
|
||||
log "Replacing env variables in ${REPLACE_ENV_PATHS} that match the prefix $REPLACE_ENV_VARIABLE_PREFIX ..."
|
||||
|
||||
mc-image-helper --debug=${DEBUG} interpolate \
|
||||
--replace-env-file-suffixes="${REPLACE_ENV_SUFFIXES}" \
|
||||
--replace-env-excludes="${REPLACE_ENV_VARIABLES_EXCLUDES}" \
|
||||
--replace-env-exclude-paths="${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS}" \
|
||||
--replace-env-prefix=${REPLACE_ENV_VARIABLE_PREFIX} \
|
||||
"${REPLACE_ENV_PATHS[@]}"
|
||||
fi
|
||||
|
||||
if [[ ${PATCH_DEFINITIONS} ]]; then
|
||||
log "Applying patch definitions from ${PATCH_DEFINITIONS}"
|
||||
mc-image-helper --debug=${DEBUG} patch \
|
||||
--patch-env-prefix=${REPLACE_ENV_VARIABLE_PREFIX} \
|
||||
"${PATCH_DEFINITIONS}"
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-finalExec $@
|
||||
27
scripts/start-setupModconfig
Executable file
27
scripts/start-setupModconfig
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
# If supplied with a URL for a config (simple zip of configurations), download it and unpack
|
||||
if [[ "$MODCONFIG" ]]; then
|
||||
case "X$MODCONFIG" in
|
||||
X[Hh][Tt][Tt][Pp]*[Zz][iI][pP])
|
||||
log "Downloading mod/plugin configs via HTTP"
|
||||
log " from $MODCONFIG ..."
|
||||
curl -sSL -o /tmp/modconfig.zip "$MODCONFIG"
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
mkdir -p /data/plugins
|
||||
unzip -o -d /data/plugins /tmp/modconfig.zip
|
||||
else
|
||||
mkdir -p /data/config
|
||||
unzip -o -d /data/config /tmp/modconfig.zip
|
||||
fi
|
||||
rm -f /tmp/modconfig.zip
|
||||
;;
|
||||
*)
|
||||
log "Invalid URL given for modconfig: Must be HTTP or HTTPS and a ZIP file"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupMounts $@
|
||||
207
scripts/start-setupModpack
Executable file
207
scripts/start-setupModpack
Executable file
@@ -0,0 +1,207 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
: "${REMOVE_OLD_MODS:=false}"
|
||||
: "${MODS_FILE:=}"
|
||||
: "${REMOVE_OLD_MODS_DEPTH:=1} "
|
||||
: "${REMOVE_OLD_MODS_INCLUDE:=*.jar}"
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-$(dirname "$0")}/start-utils"
|
||||
isDebugging && set -x
|
||||
|
||||
# CURSE_URL_BASE used in manifest downloads below
|
||||
CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
|
||||
|
||||
# Remove old mods/plugins
|
||||
if isTrue "${REMOVE_OLD_MODS}" && [ -z "${MODS_FILE}" ]; then
|
||||
removeOldMods /data/mods
|
||||
removeOldMods /data/plugins
|
||||
fi
|
||||
|
||||
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack
|
||||
if [[ "$MODPACK" ]]; then
|
||||
if isURL "${MODPACK}"; then
|
||||
log "Downloading mod/plugin pack"
|
||||
if ! get -o /tmp/modpack.zip "${MODPACK}"; then
|
||||
log "ERROR: failed to download from ${MODPACK}"
|
||||
exit 2
|
||||
fi
|
||||
elif [[ "$MODPACK" =~ .*\.zip ]]; then
|
||||
if ! cp "$MODPACK" /tmp/modpack.zip; then
|
||||
log "ERROR: failed to copy from $MODPACK"
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
log "ERROR Invalid URL or Path given for MODPACK: $MODPACK"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
mkdir -p /data/plugins
|
||||
if ! unzip -o -d /data/plugins /tmp/modpack.zip; then
|
||||
log "ERROR: failed to unzip the modpack from ${MODPACK}"
|
||||
fi
|
||||
else
|
||||
mkdir -p /data/mods
|
||||
if ! unzip -o -d /data/mods /tmp/modpack.zip; then
|
||||
log "ERROR: failed to unzip the modpack from ${MODPACK}"
|
||||
fi
|
||||
fi
|
||||
rm -f /tmp/modpack.zip
|
||||
|
||||
elif [[ "$MODS" ]]; then
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
out_dir=/data/plugins
|
||||
else
|
||||
out_dir=/data/mods
|
||||
fi
|
||||
mkdir -p "$out_dir"
|
||||
|
||||
for i in ${MODS//,/ }
|
||||
do
|
||||
if isURL "$i"; then
|
||||
log "Downloading mod/plugin $i ..."
|
||||
if ! get -o "${out_dir}" "$i"; then
|
||||
log "ERROR: failed to download from $i into $out_dir"
|
||||
exit 2
|
||||
fi
|
||||
elif [[ -f "$i" && "$i" =~ .*\.jar ]]; then
|
||||
log "Copying plugin located at $i ..."
|
||||
out_file=$(basename "$i")
|
||||
if ! cp "$i" "${out_dir}/$out_file"; then
|
||||
log "ERROR: failed to copy from $i into $out_dir"
|
||||
exit 2
|
||||
fi
|
||||
elif [[ -d "$i" ]]; then
|
||||
log "Copying plugin jars from $i ..."
|
||||
cp "$i"/*.jar "${out_dir}"
|
||||
else
|
||||
log "ERROR Invalid URL or path given in MODS: $i"
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
elif [[ "$MODS_FILE" ]]; then
|
||||
if [ ! -f "$MODS_FILE" ]; then
|
||||
log "ERROR: given MODS_FILE file does not exist"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
out_dir=/data/plugins
|
||||
else
|
||||
out_dir=/data/mods
|
||||
fi
|
||||
mkdir -p "$out_dir"
|
||||
|
||||
args=(
|
||||
-o "${out_dir}"
|
||||
--log-progress-each
|
||||
--skip-existing
|
||||
--uris-file "${MODS_FILE}"
|
||||
)
|
||||
if isTrue "${REMOVE_OLD_MODS}"; then
|
||||
args+=(
|
||||
--prune-others "${REMOVE_OLD_MODS_INCLUDE}"
|
||||
--prune-depth "${REMOVE_OLD_MODS_DEPTH}"
|
||||
)
|
||||
fi
|
||||
|
||||
if ! get "${args[@]}" ; then
|
||||
log "ERROR: failed to retrieve one or more mods"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$MANIFEST" ]]; then
|
||||
if [[ -e "$MANIFEST" ]]; then
|
||||
EFFECTIVE_MANIFEST_FILE=$MANIFEST
|
||||
elif isURL "$MANIFEST"; then
|
||||
EFFECTIVE_MANIFEST_FILE=/tmp/manifest.json
|
||||
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{effective_url} $MANIFEST)
|
||||
curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL"
|
||||
else
|
||||
log "MANIFEST='$MANIFEST' is not a valid manifest url or location"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
case "X$EFFECTIVE_MANIFEST_FILE" in
|
||||
X*.json)
|
||||
if [ -f "${EFFECTIVE_MANIFEST_FILE}" ]; then
|
||||
MOD_DIR=${FTB_BASE_DIR:-/data}/mods
|
||||
if [ ! -d "$MOD_DIR" ]
|
||||
then
|
||||
log "Creating mods dir $MOD_DIR"
|
||||
mkdir -p "$MOD_DIR"
|
||||
fi
|
||||
log "Starting manifest download..."
|
||||
cat "${EFFECTIVE_MANIFEST_FILE}" | jq -r '.files[] | (.projectID|tostring) + " " + (.fileID|tostring)'| while read -r p f
|
||||
do
|
||||
if [ ! -f $MOD_DIR/${p}_${f}.jar ]
|
||||
then
|
||||
redirect_url="$(curl -Ls -o /dev/null -w %{effective_url} ${CURSE_URL_BASE}/${p})"
|
||||
url="$redirect_url/download/${f}/file"
|
||||
log Downloading curseforge mod $url
|
||||
# Manifest usually doesn't have mod names. Using id should be fine, tho
|
||||
curl -sSL "${url}" -o $MOD_DIR/${p}_${f}.jar
|
||||
fi
|
||||
done
|
||||
else
|
||||
log "Could not find manifest file, insufficient privileges, or malformed path."
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
log "Invalid manifest file for modpack. Please make sure it is a .json file."
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if [[ "${GENERIC_PACK}" ]]; then
|
||||
if isURL "${GENERIC_PACK}"; then
|
||||
log "Downloading generic pack ..."
|
||||
if ! curl -fsSL -o /tmp/generic_pack.zip "${GENERIC_PACK}"; then
|
||||
log "ERROR: failed to download ${GENERIC_PACK}"
|
||||
exit 2
|
||||
fi
|
||||
GENERIC_PACK=/tmp/generic_pack.zip
|
||||
fi
|
||||
|
||||
sum_file=/data/.generic_pack.sum
|
||||
isDebugging && [ -f "$sum_file}" ] && cat "$sum_file"
|
||||
if ! sha256sum -c "${sum_file}" --status 2> /dev/null; then
|
||||
base_dir=/tmp/generic_pack_base
|
||||
mkdir -p ${base_dir}
|
||||
isDebugging && ls -l "${GENERIC_PACK}"
|
||||
unzip -q -d ${base_dir} "${GENERIC_PACK}"
|
||||
|
||||
# recalculate the actual base directory of content
|
||||
base_dir=$(find "$base_dir" -type d \( -name mods -o -name plugins -o -name config \) -printf '%h' -quit)
|
||||
if [[ ! $base_dir ]]; then
|
||||
log "Unable to find content base of generic pack ${GENERIC_PACK}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f /data/manifest.txt ]; then
|
||||
log "Manifest exists from older generic pack, cleaning up ..."
|
||||
while read -r f; do
|
||||
rm -rf "/data/${f}"
|
||||
done < /data/manifest.txt
|
||||
# prune empty dirs
|
||||
find /data -mindepth 1 -depth -type d -empty -delete
|
||||
rm -f /data/manifest.txt
|
||||
fi
|
||||
|
||||
log "Writing generic pack manifest ... "
|
||||
find "${base_dir}" -type f -printf "%P\n" > /data/manifest.txt
|
||||
|
||||
log "Applying generic pack ..."
|
||||
cp -R -f "${base_dir}"/* /data
|
||||
rm -rf /tmp/generic_pack_base
|
||||
sha256sum "${GENERIC_PACK}" > "${sum_file}"
|
||||
isDebugging && cat "$sum_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-$(dirname "$0")}/start-setupModconfig" "$@"
|
||||
69
scripts/start-setupMounts
Executable file
69
scripts/start-setupMounts
Executable file
@@ -0,0 +1,69 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
: ${SYNC_SKIP_NEWER_IN_DESTINATION:=${PLUGINS_SYNC_UPDATE:-true}}
|
||||
: ${REPLACE_ENV_DURING_SYNC:=true}
|
||||
: ${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}
|
||||
: ${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}
|
||||
: ${REPLACE_ENV_VARIABLES_EXCLUDES:=}
|
||||
: ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}
|
||||
: ${DEBUG:=false}
|
||||
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
|
||||
if isTrue ${SYNC_SKIP_NEWER_IN_DESTINATION}; then
|
||||
updateArg="--skip-newer-in-destination"
|
||||
fi
|
||||
|
||||
if isTrue ${REPLACE_ENV_DURING_SYNC}; then
|
||||
subcommand=sync-and-interpolate
|
||||
else
|
||||
subcommand=sync
|
||||
fi
|
||||
|
||||
if [ -d /plugins ]; then
|
||||
case ${TYPE} in
|
||||
SPIGOT|BUKKIT|PAPER|MAGMA)
|
||||
mkdir -p /data/plugins
|
||||
log "Copying plugins over..."
|
||||
mc-image-helper \
|
||||
--debug=${DEBUG} ${subcommand} $updateArg \
|
||||
--replace-env-file-suffixes="${REPLACE_ENV_SUFFIXES}" \
|
||||
--replace-env-excludes="${REPLACE_ENV_VARIABLES_EXCLUDES}" \
|
||||
--replace-env-exclude-paths="${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS}" \
|
||||
--replace-env-prefix=${REPLACE_ENV_VARIABLE_PREFIX} \
|
||||
/plugins /data/plugins
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# If any modules have been provided, copy them over
|
||||
: ${COPY_MODS_DEST:="/data/mods"}
|
||||
|
||||
if [ -d /mods ]; then
|
||||
log "Copying any mods over..."
|
||||
mc-image-helper \
|
||||
--debug=${DEBUG} ${subcommand} $updateArg \
|
||||
--replace-env-file-suffixes="${REPLACE_ENV_SUFFIXES}" \
|
||||
--replace-env-excludes="${REPLACE_ENV_VARIABLES_EXCLUDES}" \
|
||||
--replace-env-exclude-paths="${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS}" \
|
||||
--replace-env-prefix=${REPLACE_ENV_VARIABLE_PREFIX} \
|
||||
/mods "${COPY_MODS_DEST}"
|
||||
fi
|
||||
|
||||
: ${COPY_CONFIG_DEST:="/data/config"}
|
||||
|
||||
if [ -d /config ]; then
|
||||
log "Copying any configs from /config to ${COPY_CONFIG_DEST}"
|
||||
mc-image-helper \
|
||||
--debug=${DEBUG} ${subcommand} $updateArg \
|
||||
--replace-env-file-suffixes="${REPLACE_ENV_SUFFIXES}" \
|
||||
--replace-env-excludes="${REPLACE_ENV_VARIABLES_EXCLUDES}" \
|
||||
--replace-env-exclude-paths="${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS}" \
|
||||
--replace-env-prefix=${REPLACE_ENV_VARIABLE_PREFIX} \
|
||||
/config "${COPY_CONFIG_DEST}"
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupServerProperties $@
|
||||
221
scripts/start-setupServerProperties
Executable file
221
scripts/start-setupServerProperties
Executable file
@@ -0,0 +1,221 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
: ${SERVER_PROPERTIES:=/data/server.properties}
|
||||
|
||||
# FUNCTIONS
|
||||
function setServerProp {
|
||||
local prop=$1
|
||||
local var=$2
|
||||
if [ -n "$var" ]; then
|
||||
# normalize booleans
|
||||
case ${var^^} in
|
||||
TRUE|FALSE)
|
||||
var=${var,,} ;;
|
||||
esac
|
||||
if grep "${prop}" "$SERVER_PROPERTIES" > /dev/null; then
|
||||
log "Setting ${prop} to '${var}' in ${SERVER_PROPERTIES}"
|
||||
sed -i "/^${prop}\s*=/ c ${prop}=${var//\\/\\\\}" "$SERVER_PROPERTIES"
|
||||
else
|
||||
log "Adding ${prop} with '${var}' in ${SERVER_PROPERTIES}"
|
||||
echo "${prop}=${var}" >> "$SERVER_PROPERTIES"
|
||||
fi
|
||||
else
|
||||
isDebugging && log "Skip setting ${prop}"
|
||||
fi
|
||||
}
|
||||
|
||||
function customizeServerProps {
|
||||
if [ -n "$WHITELIST" ] || isTrue ${ENABLE_WHITELIST:-false}; then
|
||||
log "Creating whitelist"
|
||||
setServerProp "whitelist" "true"
|
||||
setServerProp "white-list" "true"
|
||||
else
|
||||
log "Disabling whitelist"
|
||||
setServerProp "whitelist" "false"
|
||||
setServerProp "white-list" "false"
|
||||
fi
|
||||
|
||||
# If not provided, generate a reasonable default message-of-the-day,
|
||||
# which shows up in the server listing in the client
|
||||
if [ -z "$MOTD" ]; then
|
||||
# snapshot is the odd case where we have to look at version to identify that label
|
||||
if [[ ${ORIGINAL_TYPE} == "VANILLA" && ${VERSION} == "SNAPSHOT" ]]; then
|
||||
label=SNAPSHOT
|
||||
else
|
||||
label=${ORIGINAL_TYPE}
|
||||
fi
|
||||
|
||||
# Convert label to title-case
|
||||
label=${label,,}
|
||||
label=${label^}
|
||||
MOTD="A ${label} Minecraft Server powered by Docker"
|
||||
fi
|
||||
|
||||
setServerProp "server-name" "$SERVER_NAME"
|
||||
setServerProp "server-ip" "$SERVER_IP"
|
||||
setServerProp "server-port" "$SERVER_PORT"
|
||||
setServerProp "motd" "$(echo $MOTD | mc-image-helper asciify)"
|
||||
setServerProp "allow-nether" "$ALLOW_NETHER"
|
||||
setServerProp "announce-player-achievements" "$ANNOUNCE_PLAYER_ACHIEVEMENTS"
|
||||
setServerProp "enable-command-block" "$ENABLE_COMMAND_BLOCK"
|
||||
setServerProp "spawn-animals" "$SPAWN_ANIMALS"
|
||||
setServerProp "spawn-monsters" "$SPAWN_MONSTERS"
|
||||
setServerProp "spawn-npcs" "$SPAWN_NPCS"
|
||||
setServerProp "spawn-protection" "$SPAWN_PROTECTION"
|
||||
setServerProp "generate-structures" "$GENERATE_STRUCTURES"
|
||||
setServerProp "view-distance" "$VIEW_DISTANCE"
|
||||
setServerProp "hardcore" "$HARDCORE"
|
||||
setServerProp "snooper-enabled" "$SNOOPER_ENABLED"
|
||||
setServerProp "max-build-height" "$MAX_BUILD_HEIGHT"
|
||||
setServerProp "force-gamemode" "$FORCE_GAMEMODE"
|
||||
setServerProp "max-tick-time" "$MAX_TICK_TIME"
|
||||
setServerProp "enable-query" "$ENABLE_QUERY"
|
||||
setServerProp "query.port" "$QUERY_PORT"
|
||||
setServerProp "enable-rcon" "$ENABLE_RCON"
|
||||
setServerProp "rcon.password" "$RCON_PASSWORD"
|
||||
setServerProp "rcon.port" "$RCON_PORT"
|
||||
setServerProp "max-players" "$MAX_PLAYERS"
|
||||
setServerProp "max-world-size" "$MAX_WORLD_SIZE"
|
||||
setServerProp "level-name" "$LEVEL"
|
||||
setServerProp "level-seed" "$SEED"
|
||||
setServerProp "pvp" "${PVP}"
|
||||
setServerProp "generator-settings" "$GENERATOR_SETTINGS"
|
||||
setServerProp "online-mode" "$ONLINE_MODE"
|
||||
setServerProp "allow-flight" "$ALLOW_FLIGHT"
|
||||
setServerProp "level-type" "${LEVEL_TYPE^^}"
|
||||
setServerProp "resource-pack" "$RESOURCE_PACK"
|
||||
setServerProp "resource-pack-sha1" "$RESOURCE_PACK_SHA1"
|
||||
setServerProp "player-idle-timeout" "$PLAYER_IDLE_TIMEOUT"
|
||||
setServerProp "broadcast-console-to-ops" "$BROADCAST_CONSOLE_TO_OPS"
|
||||
setServerProp "broadcast-rcon-to-ops" "$BROADCAST_RCON_TO_OPS"
|
||||
setServerProp "enable-jmx-monitoring" "$ENABLE_JMX"
|
||||
setServerProp "sync-chunk-writes" "$SYNC_CHUNK_WRITES"
|
||||
setServerProp "enable-status" "$ENABLE_STATUS"
|
||||
setServerProp "entity-broadcast-range-percentage" "$ENTITY_BROADCAST_RANGE_PERCENTAGE"
|
||||
setServerProp "function-permission-level" "$FUNCTION_PERMISSION_LEVEL"
|
||||
setServerProp "network-compression-threshold" "$NETWORK_COMPRESSION_THRESHOLD"
|
||||
setServerProp "op-permission-level" "$OP_PERMISSION_LEVEL"
|
||||
setServerProp "prevent-proxy-connections" "$PREVENT_PROXY_CONNECTIONS"
|
||||
setServerProp "use-native-transport" "$USE_NATIVE_TRANSPORT"
|
||||
setServerProp "enforce-whitelist" "$ENFORCE_WHITELIST"
|
||||
setServerProp "simulation-distance" "$SIMULATION_DISTANCE"
|
||||
|
||||
if [ -n "$DIFFICULTY" ]; then
|
||||
case $DIFFICULTY in
|
||||
peaceful|0)
|
||||
if versionLessThan 1.13; then
|
||||
DIFFICULTY=0
|
||||
else
|
||||
DIFFICULTY=peaceful
|
||||
fi
|
||||
;;
|
||||
easy|1)
|
||||
if versionLessThan 1.13; then
|
||||
DIFFICULTY=1
|
||||
else
|
||||
DIFFICULTY=easy
|
||||
fi
|
||||
;;
|
||||
normal|2)
|
||||
if versionLessThan 1.13; then
|
||||
DIFFICULTY=2
|
||||
else
|
||||
DIFFICULTY=normal
|
||||
fi
|
||||
;;
|
||||
hard|3)
|
||||
if versionLessThan 1.13; then
|
||||
DIFFICULTY=3
|
||||
else
|
||||
DIFFICULTY=hard
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
log "DIFFICULTY must be peaceful, easy, normal, or hard."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
setServerProp "difficulty" "$DIFFICULTY"
|
||||
fi
|
||||
|
||||
if [ -n "$MODE" ]; then
|
||||
log "Setting mode"
|
||||
MODE_LC=$( echo $MODE | tr '[:upper:]' '[:lower:]' )
|
||||
case $MODE_LC in
|
||||
su*|0)
|
||||
if versionLessThan 1.13; then
|
||||
MODE=0
|
||||
else
|
||||
MODE=survival
|
||||
fi
|
||||
;;
|
||||
c*|1)
|
||||
if versionLessThan 1.13; then
|
||||
MODE=1
|
||||
else
|
||||
MODE=creative
|
||||
fi
|
||||
;;
|
||||
a*|2)
|
||||
if versionLessThan 1.13; then
|
||||
MODE=2
|
||||
else
|
||||
MODE=adventure
|
||||
fi
|
||||
;;
|
||||
sp*|3)
|
||||
if versionLessThan 1.13; then
|
||||
MODE=3
|
||||
else
|
||||
MODE=spectator
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
log "ERROR: Invalid game mode: $MODE"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
setServerProp "gamemode" "$MODE"
|
||||
fi
|
||||
}
|
||||
|
||||
# Deploy server.properties file
|
||||
if [[ ${TYPE} == "CURSEFORGE" ]]; then
|
||||
export SERVER_PROPERTIES="${FTB_DIR}/server.properties"
|
||||
log "detected FTB, changing properties path to ${SERVER_PROPERTIES}"
|
||||
fi
|
||||
|
||||
if [ ! -e "$SERVER_PROPERTIES" ]; then
|
||||
log "Creating server.properties in ${SERVER_PROPERTIES}"
|
||||
cp /tmp/server.properties "$SERVER_PROPERTIES"
|
||||
customizeServerProps
|
||||
elif [ -n "${OVERRIDE_SERVER_PROPERTIES}" ]; then
|
||||
case ${OVERRIDE_SERVER_PROPERTIES^^} in
|
||||
TRUE|1)
|
||||
customizeServerProps
|
||||
;;
|
||||
*)
|
||||
log "server.properties already created, skipping"
|
||||
;;
|
||||
esac
|
||||
else
|
||||
log "server.properties already created, skipping"
|
||||
fi
|
||||
|
||||
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||
current_max_tick=$( grep 'max-tick-time' "$SERVER_PROPERTIES" | sed -r 's/( )+//g' | awk -F= '{print $2}' )
|
||||
if (( $current_max_tick > 0 && $current_max_tick < 86400000 )); then
|
||||
log "Warning: The server.properties for the server doesn't have the Server Watchdog (effectively) disabled."
|
||||
log "Warning (cont): Autopause functionality resuming the process might trigger the Watchdog and restart the server completely."
|
||||
log "Warning (cont): Set the max-tick-time property to a high value (or disable the Watchdog with value -1 for versions 1.8.1+)."
|
||||
fi
|
||||
fi
|
||||
|
||||
if isDebugging; then
|
||||
log "DEBUG Dumping server.properties"
|
||||
cat "${SERVER_PROPERTIES}"
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupEnvVariables $@
|
||||
74
scripts/start-setupWorld
Executable file
74
scripts/start-setupWorld
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
|
||||
: ${LEVEL:=world}
|
||||
export LEVEL
|
||||
|
||||
if [ $TYPE = "CURSEFORGE" ]; then
|
||||
worldDest=$FTB_DIR/$LEVEL
|
||||
else
|
||||
worldDest=/data/$LEVEL
|
||||
fi
|
||||
|
||||
if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then
|
||||
if isTrue "${FORCE_WORLD_COPY}"; then
|
||||
log "Removing existing world data in $worldDest ${worldDest}_nether ${worldDest}_the_end"
|
||||
rm -rf "$worldDest" \
|
||||
"${worldDest}_nether" \
|
||||
"${worldDest}_the_end"
|
||||
fi
|
||||
|
||||
if isURL $WORLD; then
|
||||
curl -fsSL "$WORLD" -o /tmp/world.zip
|
||||
zipSrc=/tmp/world.zip
|
||||
elif [[ "$WORLD" =~ .*\.zip ]]; then
|
||||
zipSrc="$WORLD"
|
||||
fi
|
||||
|
||||
if [[ "$zipSrc" ]]; then
|
||||
log "Unzipping world"
|
||||
|
||||
# Stage contents so that the correct subdirectory can be picked off
|
||||
mkdir -p /tmp/world-data
|
||||
(cd /tmp/world-data && unzip -o -q "$zipSrc")
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
baseDirs=$(find /tmp/world-data -name "level.dat" -not -path "*_nether*" -not -path "*_the_end*" -exec dirname "{}" \;)
|
||||
else
|
||||
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
|
||||
fi
|
||||
|
||||
count=$(echo "$baseDirs" | wc -l)
|
||||
if [[ $count -gt 1 ]]; then
|
||||
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
|
||||
baseName=$(basename "$baseDir")
|
||||
log "WARN multiple levels found, picking: $baseName"
|
||||
elif [[ $count -gt 0 ]]; then
|
||||
baseDir="$baseDirs"
|
||||
else
|
||||
log "ERROR invalid world content"
|
||||
exit 1
|
||||
fi
|
||||
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest"
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
log "Copying end and nether ..."
|
||||
[ -d "${baseDir}_nether" ] && rsync --remove-source-files --recursive --delete "${baseDir}_nether/" "${worldDest}_nether"
|
||||
[ -d "${baseDir}_the_end" ] && rsync --remove-source-files --recursive --delete "${baseDir}_the_end/" "${worldDest}_the_end"
|
||||
fi
|
||||
else
|
||||
log "Cloning world directory from $WORLD ..."
|
||||
rsync --recursive --delete "${WORLD%/}"/ "$worldDest"
|
||||
fi
|
||||
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
# Reorganise if a Spigot server
|
||||
log "Moving End and Nether maps to Spigot location"
|
||||
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "${worldDest}_the_end"
|
||||
[ -d "$worldDest/DIM-1" ] && mv -f "$worldDest/DIM-1" "${worldDest}_nether"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupModpack $@
|
||||
104
scripts/start-spiget
Executable file
104
scripts/start-spiget
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
handleDebugMode
|
||||
|
||||
: ${SPIGET_RESOURCES:=}
|
||||
: ${SPIGET_DOWNLOAD_TOLERANCE:=5} # in minutes
|
||||
|
||||
containsJars() {
|
||||
file=${1?}
|
||||
|
||||
pat='\.jar$'
|
||||
|
||||
while read -r line; do
|
||||
if [[ $line =~ $pat ]]; then
|
||||
return 0
|
||||
fi
|
||||
done <<<$(unzip -l "$file")
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
getResourceFromSpiget() {
|
||||
resource=${1?}
|
||||
|
||||
log "Downloading resource ${resource} ..."
|
||||
|
||||
mkdir -p /data/plugins
|
||||
|
||||
versionfile="/data/plugins/.${resource}-version.json"
|
||||
versionfileNew="/tmp/.${resource}-version.json"
|
||||
|
||||
if [ -f "$versionfile" ]; then
|
||||
if [[ -n $(find "$versionfile" -mmin +${SPIGET_DOWNLOAD_TOLERANCE}) ]]; then
|
||||
urlVersion="https://api.spiget.org/v2/resources/${resource}/versions/latest"
|
||||
if ! curl -o "${versionfileNew}" -fsSL -H "User-Agent: itzg/minecraft-server" "${extraCurlArgs[@]}" "${urlVersion}"; then
|
||||
log "ERROR failed to download resource version meta data '${resource}' from ${urlVersion}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
installedVersion=$(jq -r '.name' $versionfile)
|
||||
newVersion=$(jq -r '.name' $versionfileNew)
|
||||
|
||||
if [ "$installedVersion" = "$newVersion" ]; then
|
||||
log "resource '${resource}' not downloaded because installed version '${installedVersion}' already up to date ('${newVersion}')"
|
||||
mv "${versionfileNew}" "${versionfile}"
|
||||
else
|
||||
if downloadResourceFromSpiget "${resource}"; then
|
||||
mv "${versionfileNew}" "${versionfile}"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
log "resource '${resource}' not checked because version meta file newer than '${SPIGET_DOWNLOAD_TOLERANCE}' minutes"
|
||||
fi
|
||||
else
|
||||
if downloadResourceFromSpiget "${resource}"; then
|
||||
urlVersion="https://api.spiget.org/v2/resources/${resource}/versions/latest"
|
||||
if ! curl -o "${versionfileNew}" -fsSL -H "User-Agent: itzg/minecraft-server" "${extraCurlArgs[@]}" "${urlVersion}"; then
|
||||
log "ERROR failed to download resource version meta data '${resource}' from ${urlVersion}"
|
||||
exit 2
|
||||
fi
|
||||
mv "${versionfileNew}" "${versionfile}"
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
downloadResourceFromSpiget() {
|
||||
resource=${1?}
|
||||
|
||||
tmpfile="/tmp/${resource}.zip"
|
||||
url="https://api.spiget.org/v2/resources/${resource}/download"
|
||||
if ! curl -o "${tmpfile}" -fsSL -H "User-Agent: itzg/minecraft-server" "${extraCurlArgs[@]}" "${url}"; then
|
||||
log "ERROR failed to download resource '${resource}' from ${url}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if containsJars "${tmpfile}"; then
|
||||
log "Extracting contents of resource ${resource} into plugins"
|
||||
unzip -o -q -d /data/plugins "${tmpfile}"
|
||||
rm "${tmpfile}"
|
||||
else
|
||||
log "Moving resource ${resource} into plugins"
|
||||
mv "${tmpfile}" "/data/plugins/${resource}.jar"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
if [[ ${SPIGET_RESOURCES} ]]; then
|
||||
if isTrue ${REMOVE_OLD_MODS:-false}; then
|
||||
removeOldMods /data/plugins
|
||||
REMOVE_OLD_MODS=false
|
||||
fi
|
||||
|
||||
log "Getting plugins via Spiget"
|
||||
IFS=',' read -r -a resources <<<"${SPIGET_RESOURCES}"
|
||||
for resource in "${resources[@]}"; do
|
||||
getResourceFromSpiget "${resource}"
|
||||
done
|
||||
fi
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
190
scripts/start-utils
Executable file
190
scripts/start-utils
Executable file
@@ -0,0 +1,190 @@
|
||||
#!/bin/bash
|
||||
|
||||
function join_by() {
|
||||
local d=$1
|
||||
shift
|
||||
echo -n "$1"
|
||||
shift
|
||||
printf "%s" "${@/#/$d}"
|
||||
}
|
||||
|
||||
function isURL() {
|
||||
local value=$1
|
||||
|
||||
if [[ ${value:0:8} == "https://" || ${value:0:7} == "http://" || ${value:0:6} == "ftp://" ]]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function isValidFileURL() {
|
||||
suffix=${1:?Missing required suffix arg}
|
||||
url=${2:?Missing required url arg}
|
||||
|
||||
[[ "$url" == http*://*.${suffix} || "$url" == http*://*.${suffix}\?* ]]
|
||||
}
|
||||
|
||||
function resolveEffectiveUrl() {
|
||||
url="${1:?Missing required url argument}"
|
||||
if ! curl -Ls -o /dev/null -w %{url_effective} "$url"; then
|
||||
log "ERROR failed to resolve effective URL from $url"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
function getFilenameFromUrl() {
|
||||
url="${1:?Missing required url argument}"
|
||||
strippedOfQuery="${url%\?*}"
|
||||
basename "$strippedOfQuery"
|
||||
}
|
||||
|
||||
function isTrue() {
|
||||
local value=${1,,}
|
||||
|
||||
result=
|
||||
|
||||
case ${value} in
|
||||
true | on)
|
||||
result=0
|
||||
;;
|
||||
*)
|
||||
result=1
|
||||
;;
|
||||
esac
|
||||
|
||||
return ${result}
|
||||
}
|
||||
|
||||
function isDebugging() {
|
||||
if isTrue "${DEBUG:-false}"; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function handleDebugMode() {
|
||||
if isDebugging; then
|
||||
set -x
|
||||
extraCurlArgs=(-v)
|
||||
fi
|
||||
}
|
||||
|
||||
function debug() {
|
||||
if isDebugging; then
|
||||
log "DEBUG: $*"
|
||||
fi
|
||||
}
|
||||
|
||||
function logn() {
|
||||
echo -n "[init] $*"
|
||||
}
|
||||
|
||||
function log() {
|
||||
echo "[init] $*"
|
||||
}
|
||||
|
||||
function logAutopause() {
|
||||
echo "[Autopause loop] $*"
|
||||
}
|
||||
|
||||
function logAutopauseAction() {
|
||||
echo "[$(date -Iseconds)] [Autopause] $*"
|
||||
}
|
||||
|
||||
function normalizeMemSize() {
|
||||
local scale=1
|
||||
case ${1,,} in
|
||||
*k)
|
||||
scale=1024
|
||||
;;
|
||||
*m)
|
||||
scale=1048576
|
||||
;;
|
||||
*g)
|
||||
scale=1073741824
|
||||
;;
|
||||
esac
|
||||
|
||||
val=${1:0:-1}
|
||||
echo $((val * scale))
|
||||
}
|
||||
|
||||
function versionLessThan() {
|
||||
local activeParts
|
||||
IFS=. read -ra activeParts <<<"${VANILLA_VERSION}"
|
||||
|
||||
local givenParts
|
||||
IFS=. read -ra givenParts <<<"$1"
|
||||
|
||||
if ((${#activeParts[@]} < 2)); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ((${#activeParts[@]} == 2)); then
|
||||
if ((activeParts[0] < givenParts[0])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])); then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
if ((activeParts[0] < givenParts[0])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] == givenParts[1] && activeParts[2] < givenParts[2])); then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
requireVar() {
|
||||
if [ ! -v $1 ]; then
|
||||
log "ERROR: $1 is required to be set"
|
||||
exit 1
|
||||
fi
|
||||
if [ -z "${!1}" ]; then
|
||||
log "ERROR: $1 is required to be set"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
requireEnum() {
|
||||
var=${1?}
|
||||
shift
|
||||
|
||||
for allowed in $*; do
|
||||
if [[ ${!var} = $allowed ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
log "ERROR: $var must be set to one of $@"
|
||||
# exit 1
|
||||
}
|
||||
|
||||
function writeEula() {
|
||||
if ! echo "# Generated via Docker
|
||||
# $(date)
|
||||
eula=${EULA,,}
|
||||
" >/data/eula.txt; then
|
||||
log "ERROR: unable to write eula to /data. Please make sure attached directory is writable by uid=${UID}"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
function removeOldMods {
|
||||
if [ -d "$1" ]; then
|
||||
find "$1" -mindepth 1 -maxdepth ${REMOVE_OLD_MODS_DEPTH:-16} -wholename "${REMOVE_OLD_MODS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_MODS_EXCLUDE:-}" -delete
|
||||
fi
|
||||
}
|
||||
|
||||
function get() {
|
||||
local flags=()
|
||||
if isTrue "${DEBUG_GET:-false}"; then
|
||||
flags+=("--debug")
|
||||
fi
|
||||
mc-image-helper "${flags[@]}" get "$@"
|
||||
}
|
||||
Reference in New Issue
Block a user