#!/bin/bash # shellcheck source=start-utils . "$(dirname "$0")/start-utils" # Define setup functions function getGTNHdownloadPath(){ gtnh_download_path="" local release_object="" # Select release JSON object # latest-dev will be removed in the future, but is still supported for now. if [ "$GTNH_PACK_VERSION" == "latest-dev" ] || [ "$GTNH_PACK_VERSION" == "latest-beta" ]; then if [ "$GTNH_PACK_VERSION" == "latest-dev" ]; then logWarning "GTNH_PACK_VERSION=latest-dev is deprecated and will be removed in the future." fi if ! release_object="$( curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \ | jq -r '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Beta release"))|.[-1]' )"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json" exit 1 fi log "Selected $(jq '.key' <<< "$release_object") as latest dev version for download." elif [ "$GTNH_PACK_VERSION" == "latest" ]; then if ! release_object="$( curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \ | jq -r '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Stable release"))|.[-1]' )"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json" exit 1 fi log "Selected $(jq '.key' <<< "$release_object") as latest version for download." else if ! release_object="$( curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \ | jq -r --arg USRIN "$GTNH_PACK_VERSION" '(.versions // .)|to_entries|sort_by(.value.releaseDate)|map(select(.key==$USRIN))|.[]' )"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json" exit 1 fi log "Selected $(jq -r '.key' <<< "$release_object") as matching version for download." fi if [[ -z $release_object ]]; then logError "No release found for GTNH_PACK_VERSION=$GTNH_PACK_VERSION. Please check if the version is valid." exit 1 fi # Select compatible server files for java version if (( java_version == 8 )); then gtnh_download_path=$(jq -r '.value.server.java8Url' <<< "$release_object") log "Use GTNH Server Java 8 release." elif (( java_version >= 17 )); then if (( java_version > $(jq '.value.maxJavaVersion' <<< "$release_object") )); then logError "Container Java version $java_version is not supported by GTNH. Try an older release." exit 1 fi gtnh_download_path=$(jq -r '.value.server.java17_2XUrl' <<< "$release_object") log "Use GTNH Server Java 17+ release." fi if [[ -z $gtnh_download_path ]]; then logError "Server files not found! Please check if the selected GTNH_PACK_VERSION=$GTNH_PACK_VERSION is valid." exit 1 fi debug "Download source URL: $gtnh_download_path" } function getGTNHdownloadOptions(){ # Used for GTNH daily build downloads, to pass additional options to the download command. gtnh_download_options=() # Used for dryrun check gtnh_download_path="" # Check if GH_TOKEN is set for daily builds if [ -z "$GH_TOKEN" ]; then logError "GH_TOKEN environment variable must be set to use daily builds." exit 1 fi gtnh_download_options+=( --output-filename ) # prepare download options as an array to safely append patterns if [ "$GTNH_PACK_VERSION" == "latest" ] || [ "$GTNH_PACK_VERSION" == "latest-dev" ]; then if [ "$GTNH_PACK_VERSION" == "latest-dev" ]; then logWarning "GTNH_PACK_VERSION=latest-dev is deprecated and will be removed in the future." fi gtnh_download_options+=( --workflow=daily-modpack-build.yml ) log "Using latest daily build for GTNH server files." elif [ "$GTNH_PACK_VERSION" == "latest-beta" ]; then gtnh_download_options+=( --workflow=daily-modpack-build.yml ) logWarning "Using daily build instead of latest beta release for GTNH server files. If this is not intended, set GTNH_USE_DAILY_BUILD=false to use the latest beta release instead." else gtnh_download_options+=( --run-id="$GTNH_PACK_VERSION" ) log "Using specific daily build run ID $GTNH_PACK_VERSION for GTNH server files." fi # Select compatible server files for java version if (( java_version == 8 )); then log "Use GTNH Server Java 8 release." gtnh_download_options+=( --artifact-pattern='GTNH-daily-\d{4}-\d{2}-\d{2}\+\d+-server-java8\.zip' ) elif (( java_version >= 17 )); then log "Use GTNH Server Java 17+ release." gtnh_download_options+=( --artifact-pattern='GTNH-daily-\d{4}-\d{2}-\d{2}\+\d+-server-java17-\d{2}\.zip' ) fi debug "GTNH daily build download options: ${gtnh_download_options[*]}" if ! gtnh_download_path=$(mc-image-helper github download-artifact --no-download "${gtnh_download_options[@]}" GTNewHorizons/DreamAssemblerXXL); then logError "Failed to find a matching daily build for GTNH server files with the specified options." exit 1 fi debug "GTNH daily build download path: $gtnh_download_path" } function deleteGTNHbackup(){ log "Start deleting all config backups" if ! find . -maxdepth 1 -type d -name 'gtnh-upgrade-*' -exec rm -rf {} + ; then logWarning "Can not delete config backup!" fi } function downloadGTNH(){ gtnh_download="" base_dir=/data/.tmp/gtnh_base debug "Creating temporary /data/.tmp/packs folder for GTNH download" mkdir -p /data/.tmp/packs trap 'rm -rf /data/.tmp' EXIT mkdir -p "${base_dir}" if isTrue "$GTNH_USE_DAILY_BUILD"; then log "Downloading Daily Build for GTNH server files." # gtnh_download_options is injecting download parameters -> (--workflow or --run-id) and --artifact-pattern if ! gtnh_download=$(mc-image-helper github download-artifact -o=$base_dir --unzip "${gtnh_download_options[@]}" GTNewHorizons/DreamAssemblerXXL); then logError "Failed to download Daily Build for GTNH server files." exit 1 fi else log "Downloading $gtnh_download_path." if ! gtnh_download=$(mc-image-helper get -o /data/.tmp/packs --output-filename --skip-up-to-date "$gtnh_download_path"); then logError "Failed to download $gtnh_download_path" exit 1 fi debug "Downloaded GTNH server files to $gtnh_download" # Unpacking Server files into temporary directory log "Unpacking Server Files into $base_dir" extract "${gtnh_download}" "${base_dir}" fi # Remove any eula file since container manages it debug "Removing eula.txt from $base_dir" rm -f "${base_dir}/eula.txt" # recalculate the actual base directory of content if ! base_dir=$(mc-image-helper find \ --max-depth=3 --type=directory --name=mods,config \ --only-shallowest --fail-no-matches --format '%h' \ "$base_dir"); then logError "Unable to find content base of downloaded Server Files" exit 1 fi debug "Base directory of unpacked Server Files: $base_dir" } function updateGTNHresource(){ local resource="$1" local new_resource="$2" log "Trying to update $resource" if [[ -z "$resource" ]]; then logWarning "No resource specified for update" return 0 fi if [[ -e "$resource" ]]; then log "Deleting existing resource: $resource" if ! rm -rf "$resource"; then logError "Failed to delete resource: $resource" exit 1 fi fi if [[ -d "$new_resource" ]]; then log "Copying $new_resource to /data" if ! cp -r "$new_resource" "/data/"; then logError "Failed to copy $new_resource to /data" exit 1 fi return 0 fi if [[ -f "$new_resource" ]]; then log "Copying $new_resource to /data" if ! cp "$new_resource" "/data/"; then logError "Failed to copy $new_resource to /data" exit 1 fi return 0 fi logWarning "Resource update failed: $new_resource does not exist!" return 0 } function updateGTNH(){ # Get the current date and time local current_datetime="" current_datetime=$(date +%Y-%m-%dT+%H%M) # Define folders and files to update # base_dir is already defined in handleGTNH function local folders_to_update=("libraries" "mods" "resources" "scripts") local files_to_update=("lwjgl3ify-forgePatches.jar" "java9args.txt" "startserver-java9.bat" "startserver-java9.sh" "forge-1.7.10-10.13.4.1614-1.7.10-universal.jar" "startserver.bat" "startserver.sh" "server-icon.png") local config_folder="config" local backup_folder="/data/gtnh-upgrade-$current_datetime" local journey_map_folder="JourneyMapServer" # Backup the config folder if [[ -d "/data/$config_folder" ]]; then log "Creating backup of /data/$config_folder at $backup_folder" cp -r "/data/$config_folder" "$backup_folder" fi # Update resources from unpacked server files to /data for resource in "${folders_to_update[@]}" "$config_folder" "${files_to_update[@]}"; do local resource_path="/data/$resource" local new_resource_path="$base_dir/$resource" debug "Updating resource: $resource_path with new resource: $new_resource_path" updateGTNHresource "$resource_path" "$new_resource_path" done # Restore JourneyMapServer folder from backup if [[ -d "$backup_folder/$journey_map_folder" ]]; then if [[ ! -d "/data/$config_folder" ]]; then log "/data/$config_folder folder does not exist. Creating it now." mkdir -p "/data/$config_folder" fi log "Restoring $journey_map_folder to /data/$config_folder" cp -r "$backup_folder/$journey_map_folder" "/data/$config_folder/" else logWarning "$journey_map_folder not found in backup!" fi # Copy the changelog file to /data local gtnh_changelog_file="" gtnh_changelog_file=$(mc-image-helper find --max-depth=1 --type=file --name=changelog*.md "$base_dir") if [[ -n "$gtnh_changelog_file" ]]; then debug "Found changelog file: $gtnh_changelog_file" log "Copying changelog file to /data" cp -f "$gtnh_changelog_file" /data/ fi } function handleGTNH() { : "${GTNH_PACK_VERSION:=latest}" : "${GTNH_DELETE_BACKUPS:=false}" : "${SKIP_GTNH_UPDATE_CHECK:=false}" : "${GTNH_USE_DAILY_BUILD:=false}" debug "GTNH VAR CHECK: GTNH_DELETE_BACKUPS=$GTNH_DELETE_BACKUPS, GTNH_PACK_VERSION=$GTNH_PACK_VERSION, TYPE=$TYPE, SKIP_GTNH_UPDATE_CHECK=$SKIP_GTNH_UPDATE_CHECK, GTNH_USE_DAILY_BUILD=$GTNH_USE_DAILY_BUILD" if isTrue "$GTNH_DELETE_BACKUPS"; then deleteGTNHbackup fi if [[ -n "$GTNH_PACK_VERSION" ]] && isFalse "$SKIP_GTNH_UPDATE_CHECK"; then if isFalse "$GTNH_USE_DAILY_BUILD"; then getGTNHdownloadPath log "Server files located! Will proceed update $gtnh_download_path." else getGTNHdownloadOptions log "Will proceed update with daily build options: ${gtnh_download_options[*]}." fi # Decide if update or install is needed or not. if [[ ! -f /data/.gtnh-version || "$(basename "$gtnh_download_path")" != "$(cat /data/.gtnh-version)" ]]; then log "Update/Install required: /data/.gtnh-version is missing or does not match the selected version $(basename "$gtnh_download_path")." # Download and unpack GTNH server files downloadGTNH log "GTNH server files downloaded and unpacked to $base_dir." # Split installation from update path. Check for version file. if [[ -f /data/.gtnh-version ]]; then log ".gtnh-version file detected! Assuming old version already exists. Proceed updating existing server..." updateGTNH else log "No .gtnh-version file detected! Assuming no old server exists. Proceed installing new server..." cp -R -f "${base_dir}"/* /data fi # Update .gtnh-version basename "$gtnh_download" > /data/.gtnh-version # Cleaning up temporary files rm -rf /data/.tmp else log "No update required: /data/.gtnh-version matches the selected version $(basename "$gtnh_download_path")." fi else log "SKIP_GTNH_UPDATE_CHECK=$SKIP_GTNH_UPDATE_CHECK ... Skipping GTNH Update/Install" fi } # Set server.properties defaults suitable for gtnh servers log "Applying GTNH optimized server defaults" export ALLOW_FLIGHT="${ALLOW_FLIGHT:=true}" export LEVEL_TYPE="${LEVEL_TYPE:=rwg}" export DIFFICULTY="${DIFFICULTY:=3}" export ENABLE_COMMAND_BLOCK="${ENABLE_COMMAND_BLOCK:=true}" export MOTD="${MOTD:="Greg Tech New Horizons $GTNH_PACK_VERSION"}" debug "Set MOTD=$MOTD, ENABLE_COMMAND_BLOCK=$ENABLE_COMMAND_BLOCK, DIFFICULTY=$DIFFICULTY, LEVEL_TYPE=$LEVEL_TYPE, ALLOW_FLIGHT=$ALLOW_FLIGHT" isDebugging && set -x ensureRemoveAllModsOff "MODPACK_PLATFORM=GTNH" java_version=$(mc-image-helper java-release) if (( java_version == 8 )); then export SERVER=/data/forge-1.7.10-10.13.4.1614-1.7.10-universal.jar elif (( java_version >= 17 )); then export SERVER=/data/lwjgl3ify-forgePatches.jar else logError "Greg Tech New Horizons only supports the following Java versions: 8, 17 or later" exit 1 fi log "TYPE=GTNH, setting Minecraft version to 1.7.10" export VERSION=1.7.10 # Start setup gtnh server files handleGTNH export USES_MODS=true exec "$(dirname "$0")/start-setupWorld" "$@"