From e67fb661825606af7d0a68d26b06289b851561f7 Mon Sep 17 00:00:00 2001 From: Birdman Date: Mon, 29 Jun 2026 13:31:16 -0400 Subject: [PATCH 1/9] Updated Install for Java Server It adds custom install-folder support, including external SSDs, and saves the selected path so updates/uninstall use the correct folder. --- apps/Minecraft Java Server/install | 254 +++++++++++++++++++++++------ 1 file changed, 205 insertions(+), 49 deletions(-) diff --git a/apps/Minecraft Java Server/install b/apps/Minecraft Java Server/install index 45279762af..f5bdfa0cd1 100755 --- a/apps/Minecraft Java Server/install +++ b/apps/Minecraft Java Server/install @@ -1,9 +1,55 @@ #!/bin/bash +# Pi-Apps style installer for Minecraft Java Server with custom server directory support. +# Default server folder: $HOME/Minecraft-Java-Server +# Service name: minecraft-server +# Screen session: Minecraft_Server +# Desktop launcher: Minecraft Java Server + status "This script helps you setup a Minecraft-Java-Server (for any version)." -#allow user to skip installation if executed from an update -if [[ "$1" == "update" ]];then +SERVICE_NAME="minecraft-server" +SCREEN_NAME="Minecraft_Server" +SERVER_FOLDER_NAME="Minecraft-Java-Server" +DESKTOP_FILE="$HOME/.local/share/applications/Minecraft-Java-Server.desktop" +CONFIG_DIR="$HOME/.config/minecraft-java-server" +CONFIG_FILE="$CONFIG_DIR/server_dir" +DEFAULT_SERVER_DIR="$HOME/$SERVER_FOLDER_NAME" + + +ensure_server_dir() { + # Create the server folder. External drives under /media sometimes need sudo for + # folder creation, but the Minecraft server still needs the regular user to be + # able to write inside the final folder. + mkdir -p "$server_dir" 2>/dev/null || sudo mkdir -p "$server_dir" || error "Could not create server directory: $server_dir" + + # Best effort ownership/permissions. On exFAT these may be ignored, because + # ownership comes from mount options, but this helps on ext4 and normal folders. + sudo chown "$USER":"$USER" "$server_dir" 2>/dev/null || true + sudo chmod 775 "$server_dir" 2>/dev/null || true + + if ! touch "$server_dir/.write-test" 2>/dev/null; then + # If the folder was created with sudo on an external drive, try once more to + # create a test file and then hand it to the user. If the user still cannot + # write, the mount permissions need fixed outside this installer. + sudo touch "$server_dir/.write-test" 2>/dev/null || true + sudo chown "$USER":"$USER" "$server_dir/.write-test" 2>/dev/null || true + sudo rm -f "$server_dir/.write-test" 2>/dev/null || true + + touch "$server_dir/.write-test" 2>/dev/null || error "The chosen server directory exists, but is not writable by $USER: +$server_dir + +Try this outside Pi-Apps: +touch \"$server_dir/test-write.txt\" + +If that fails too, the external drive is mounted without write access for $USER." + fi + + rm -f "$server_dir/.write-test" +} + +# allow user to skip installation if executed from an update +if [[ "$1" == "update" ]]; then description="The Minecraft Java Server script was executed as part of an update to improve platform support.\nWould you like to check for newer versions of Minecraft to upgrade your server to or exit now?" userinput_func "$description" "Yes, check for newer Minecraft versions and upgrade my install" "No, leave my install alone and exit now" if [ "$output" == "No, leave my install alone and exit now" ]; then @@ -15,14 +61,118 @@ fi # add jq to use in script install_packages jq || exit 1 -mkdir -p "$HOME/Minecraft-Java-Server" -cd "$HOME/Minecraft-Java-Server" || error "Could not enter Minecraft-Java-Server folder." +choose_server_directory() { + # On update, reuse the previously chosen directory when possible. + if [[ "$1" == "update" ]] && [ -f "$CONFIG_FILE" ]; then + server_dir="$(head -n 1 "$CONFIG_FILE")" + if [ -n "$server_dir" ]; then + status "Using existing Minecraft server folder:\n$server_dir" + ensure_server_dir + return + fi + fi + + description="Where do you want your Minecraft Java Server files to live?\n\nThis installer defaults to:\n$DEFAULT_SERVER_DIR\n\nYou can also choose an already-mounted drive path, such as /media/$USER/MySSD/$SERVER_FOLDER_NAME.\n\nThe selected folder will be used for server files, start-server.sh, the desktop launcher, and the systemd service." + + table=("Home folder: $DEFAULT_SERVER_DIR") + + # Add currently mounted user media drives, if any. This does not permanently mount them. + if [ -d "/media/$USER" ]; then + while IFS= read -r mount_dir; do + [ -d "$mount_dir" ] || continue + candidate="$mount_dir/$SERVER_FOLDER_NAME" + table+=("Mounted drive: $candidate") + done < <(find "/media/$USER" -mindepth 1 -maxdepth 1 -type d 2>/dev/null | sort) + fi + + table+=("Custom path") + + userinput_func "$description" "${table[@]}" + selected_choice="$output" + + case "$selected_choice" in + "Home folder: "*) + server_dir="$DEFAULT_SERVER_DIR" + ;; + "Mounted drive: "*) + server_dir="${selected_choice#Mounted drive: }" + ;; + "Custom path") + server_dir=$(yad --center --wrap \ + --text "Enter the full path where the Minecraft server should be installed.\n\nExamples:\n$HOME/$SERVER_FOLDER_NAME\n/media/$USER/MySSD/$SERVER_FOLDER_NAME\n\nAvoid spaces in the path." \ + --entry \ + --entry-text "$DEFAULT_SERVER_DIR" \ + --button="Use this path":0) + ;; + *) + server_dir="$DEFAULT_SERVER_DIR" + ;; + esac + + if [ -z "$server_dir" ]; then + error "No server directory was selected. Exiting." + fi + + # Expand leading ~ if user typed it. + server_dir="${server_dir/#\~/$HOME}" + + # Normalize path if readlink supports -m. + if command -v readlink >/dev/null 2>&1; then + server_dir="$(readlink -m "$server_dir")" + fi + + # Keep this simple and safe for systemd paths. + if [[ "$server_dir" =~ [[:space:]] ]]; then + error "The chosen path contains spaces:\n$server_dir\n\nPlease choose a path without spaces." + fi + + + ensure_server_dir + + mkdir -p "$CONFIG_DIR" + printf '%s\n' "$server_dir" > "$CONFIG_FILE" + + status "Minecraft server files will be installed in:\n$server_dir" +} + +choose_server_directory "$1" + +ensure_server_dir +cd "$server_dir" || error "Could not enter Minecraft server folder." description="What type of Minecraft server\ndo you want to run?" table=("Vanilla" "Fabric" "Forge" "Paper" "Folia" "Purpur") userinput_func "$description" "${table[@]}" server_category="$output" +# Helper for PaperMC Fill v3 downloads. +# PaperMC documents Fill v3 at fill.papermc.io and recommends stable builds. +download_fill_project() { + PROJECT="$1" + VERSION="$2" + USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" + + builds_response=$(wget --user-agent="$USER_AGENT" -O- "https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds") || error "Could not fetch $PROJECT builds for $VERSION." + + # Prefer the newest STABLE build. If none exists, fall back to the newest build so Folia/experimental projects can still be tested. + build_json=$(echo "$builds_response" | jq -c '([.[] | select(.channel == "STABLE")] | last) // (last)') + + if [ -z "$build_json" ] || [ "$build_json" = "null" ]; then + error "No $PROJECT build was found for version $VERSION." + fi + + server_jar="$(echo "$build_json" | jq -r '.downloads."server:default".name')" + download_url="$(echo "$build_json" | jq -r '.downloads."server:default".url')" + channel="$(echo "$build_json" | jq -r '.channel // "unknown"')" + + if [ -z "$server_jar" ] || [ "$server_jar" = "null" ] || [ -z "$download_url" ] || [ "$download_url" = "null" ]; then + error "Could not determine $PROJECT server jar or download URL for $VERSION." + fi + + status "Selected $PROJECT $VERSION build channel: $channel" + wget --user-agent="$USER_AGENT" -O "$server_jar" "$download_url" || exit 1 +} + case "$server_category" in "Fabric") available_versions=$(wget -O- https://meta.fabricmc.net/v2/versions/game | jq -r '.[] | select( .stable == true ) | .version') @@ -46,35 +196,28 @@ case "$server_category" in status "Selected $server_category version $server_version" installer_version=$(wget -O- https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json | jq -r '.'\"$server_version\"' | [last] | .[]') - # example file formats - # https://maven.minecraftforge.net/net/minecraftforge/forge/1.18.1-39.0.63/forge-1.18.1-39.0.63-installer.jar - # https://maven.minecraftforge.net/net/minecraftforge/forge/1.3.2-4.3.5.318/forge-1.3.2-4.3.5.318-universal.zip - # https://maven.minecraftforge.net/net/minecraftforge/forge/1.2.5-3.4.9.171/forge-1.2.5-3.4.9.171-server.zip - server_jar="forge-$installer_version-installer.jar" wget -O "$server_jar" "https://maven.minecraftforge.net/net/minecraftforge/forge/$installer_version/forge-$installer_version-installer.jar" || exit 1 ;; "Paper") - available_versions=$(wget -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') + USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" + available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" server_version="$output" status "Selected $server_category version $server_version" - version_info=$(wget -O- https://fill.papermc.io/v3/projects/paper/versions/$server_version/builds/latest | jq -r '.downloads."server:default"') - server_jar="$(echo "$version_info" | jq -r '.name')" - wget -O "$server_jar" "$(echo "$version_info" | jq -r '.url')" || exit 1 + download_fill_project "paper" "$server_version" ;; "Folia") - available_versions=$(wget -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') + USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" + available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" server_version="$output" status "Selected $server_category version $server_version" - version_info=$(wget -O- https://fill.papermc.io/v3/projects/folia/versions/$server_version/builds/latest | jq -r '.downloads."server:default"') - server_jar="$(echo "$version_info" | jq -r '.name')" - wget -O "$server_jar" "$(echo "$version_info" | jq -r '.url')" || exit 1 + download_fill_project "folia" "$server_version" ;; "Purpur") available_versions=$(wget -O- https://api.purpurmc.org/v2/purpur/ | jq -r '.versions | .[]') @@ -103,9 +246,9 @@ case "$server_category" in ;; esac -while [[ ! -a $(echo ${server_jar}) ]]; do +while [[ ! -a "$server_jar" ]]; do description="Please use the website which has opened to download your chosen version of the Minecraft Java Server.\ - \nAdd your ${server_jar} file to the folder opened $HOME/Minecraft-Java-Server and press OK.\ + \nAdd your ${server_jar} file to the folder opened $server_dir and press OK.\ \n\nYou have not added a ${server_jar}." table=("OK") userinput_func "$description" "${table[@]}" @@ -206,18 +349,25 @@ case "$java_selection" in "Java 21") if package_available temurin-21-jre ;then install_packages temurin-21-jre || exit 1 + java_location="/usr/lib/jvm/temurin-21-jre-$dpkg_arch/bin/java" else error "Java 21 is not available for your platform from Adoptium. Exiting the script." fi - java_location="/usr/lib/jvm/temurin-21-jre-$dpkg_arch/bin/java" ;; "Java 25") if package_available temurin-25-jre ;then install_packages temurin-25-jre || exit 1 + java_location="/usr/lib/jvm/temurin-25-jre-$dpkg_arch/bin/java" + elif package_available java-25-amazon-corretto-jdk ;then + install_packages java-25-amazon-corretto-jdk || exit 1 + java_location="/usr/lib/jvm/java-25-amazon-corretto/bin/java" + elif [ -x "/usr/lib/jvm/java-25-amazon-corretto/bin/java" ]; then + java_location="/usr/lib/jvm/java-25-amazon-corretto/bin/java" + elif command -v java >/dev/null 2>&1 && java -version 2>&1 | grep -q 'version "25'; then + java_location="$(command -v java)" else - error "Java 25 is not available for your platform from Adoptium. Exiting the script." + error "Java 25 is not available from Adoptium and no working Java 25 executable was found. Exiting the script." fi - java_location="/usr/lib/jvm/temurin-25-jre-$dpkg_arch/bin/java" ;; esac @@ -237,13 +387,10 @@ done if [[ "$server_category" == "Forge" ]]; then # run the server installer rm -f start-server.sh - $java_location -jar $HOME/Minecraft-Java-Server/${server_jar} --installServer || error "Failed to install forge server" + $java_location -jar "$server_dir/${server_jar}" --installServer || error "Failed to install forge server" rm -f ${server_jar} # forge has MANY ways to launch depending on the version - # for some reason they like re-inventing the wheel and doing things differently than everyone else - # the below covers all the ways I have seen from 1.6.4 - 1.18.1 - # its possible I missed an obscure format that was only used once... please create an issue if that is the case if [[ -f "minecraftforge-universal-$installer_version.jar" ]]; then server_jar="minecraftforge-universal-$installer_version.jar" elif [[ -f "forge-$installer_version-universal.jar" ]]; then @@ -254,7 +401,6 @@ if [[ "$server_category" == "Forge" ]]; then server_jar="forge-$installer_version.jar" elif [[ -f "run.sh" ]]; then # set server_jar to empty to skip start-server.sh universal script creation - # this is the most up to date forge launch format where their own run.sh file is provided server_jar="" sed -i "s:java:${java_location}:g" run.sh sed -i 's:"$@":nogui:g' run.sh @@ -267,60 +413,70 @@ if [[ "$server_category" == "Forge" ]]; then fi if [ -n "$server_jar" ]; then - sh -c "cat > $HOME/Minecraft-Java-Server/start-server.sh << _EOF_ + cat > "$server_dir/start-server.sh" < eula.txt +echo "eula=true" > "$server_dir/eula.txt" # make mods directory -mkdir mods +mkdir -p "$server_dir/mods" mkdir -p "$HOME/.local/share/applications" -tee "$HOME/.local/share/applications/Minecraft-Java-Server.desktop" < Games -> Minecraft Java Server -Attach to a server in the background with: screen -r Minecraft_Server +Attach to a server in the background with: screen -r $SCREEN_NAME Detach from a running server session with: CTRL+A then D -To start from a terminal: sudo systemctl start minecraft-server -To stop the server: sudo systemctl stop minecraft-server -To start now, start on boot, and stop on shutdown: sudo systemctl enable --now minecraft-server +To start from a terminal: sudo systemctl start $SERVICE_NAME +To stop the server: sudo systemctl stop $SERVICE_NAME +To start now, start on boot, and stop on shutdown: sudo systemctl enable --now $SERVICE_NAME " From de3da8d043218306d295933b351e22cec70a6ea3 Mon Sep 17 00:00:00 2001 From: Birdman Date: Fri, 3 Jul 2026 13:35:01 -0400 Subject: [PATCH 2/9] Update uninstall --- apps/Minecraft Java Server/uninstall | 82 +++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 9 deletions(-) diff --git a/apps/Minecraft Java Server/uninstall b/apps/Minecraft Java Server/uninstall index bb4d9ae7b2..48ab8e8a57 100755 --- a/apps/Minecraft Java Server/uninstall +++ b/apps/Minecraft Java Server/uninstall @@ -2,19 +2,83 @@ shopt -s extglob -#skip uninstallation if executed from an update -if [[ "$1" != "update" ]];then - text="You chose to uninstall the Minecraft Java Server script.\nAll files within your $HOME/Minecraft-Java-Server folder will be deleted except the worlds, mods, and versions subfolders.\nIf you would like to backup any other files/folders do that NOW before clicking the prompt." +SERVICE_NAME="minecraft-server" +SCREEN_NAME="Minecraft_Server" +SERVER_FOLDER_NAME="Minecraft-Java-Server" +DESKTOP_FILE="$HOME/.local/share/applications/Minecraft-Java-Server.desktop" +CONFIG_DIR="$HOME/.config/minecraft-java-server" +CONFIG_FILE="$CONFIG_DIR/server_dir" +DEFAULT_SERVER_DIR="$HOME/$SERVER_FOLDER_NAME" + +get_server_dir() { + if [ -f "$CONFIG_FILE" ]; then + head -n 1 "$CONFIG_FILE" + return + fi + + if systemctl cat "$SERVICE_NAME.service" >/dev/null 2>&1; then + systemctl cat "$SERVICE_NAME.service" 2>/dev/null | sed -n 's/^WorkingDirectory=//p' | tail -n 1 + return + fi + + if [ -f "$DESKTOP_FILE" ]; then + sed -n 's/^Path=//p' "$DESKTOP_FILE" | tail -n 1 + return + fi + + echo "$DEFAULT_SERVER_DIR" +} + +# skip uninstallation if executed from an update +if [[ "$1" != "update" ]]; then + server_dir="$(get_server_dir)" + + if [ -z "$server_dir" ]; then + server_dir="$DEFAULT_SERVER_DIR" + fi + + text="You chose to uninstall the Minecraft Java Server script. + +The detected server folder is: +$server_dir + +Files within this folder will be deleted except the world, world_nether, world_the_end, mods, plugins, and versions subfolders. + +If you would like to backup any other files/folders do that NOW before clicking the prompt." userinput_func "$text" "Ok, I have made any backups I wish, continue" - cd $HOME/Minecraft-Java-Server && rm -rf !(world|mods|versions) - rm -rf $HOME/.local/share/applications/Minecraft-Java-Server.desktop || error "Failed to remove the desktop file" + # disable server from starting on boot and stop - sudo systemctl disable --now minecraft-server - + sudo systemctl disable --now "$SERVICE_NAME" 2>/dev/null || true + + # make sure any leftover screen session is closed + screen -S "$SCREEN_NAME" -X quit 2>/dev/null || true + # remove the systemd service - sudo rm -f /etc/systemd/system/minecraft-server.service + sudo rm -f "/etc/systemd/system/$SERVICE_NAME.service" sudo systemctl daemon-reload - + + rm -f "$DESKTOP_FILE" || error "Failed to remove the desktop file" + + if [ -d "$server_dir" ]; then + find "$server_dir" -mindepth 1 -maxdepth 1 -print0 | while IFS= read -r -d '' item; do + base="$(basename "$item")" + case "$base" in + world|world_nether|world_the_end|mods|plugins|versions) + echo "Preserving: $item" + ;; + *) + echo "Removing: $item" + rm -rf -- "$item" 2>/dev/null || sudo rm -rf -- "$item" + ;; + esac + done + else + echo "Server folder not found: $server_dir" + fi + + rm -f "$CONFIG_FILE" + rmdir "$CONFIG_DIR" 2>/dev/null || true + purge_packages || error "Dependencies failed to uninstall" rm_external_repo "adoptium" remove_repofile_if_unused /etc/apt/sources.list.d/adoptopenjdk.list From 4546a666c7c03ee68a5e74bf971ff0a0948bff4c Mon Sep 17 00:00:00 2001 From: Botspot <54716352+Botspot@users.noreply.github.com> Date: Mon, 6 Jul 2026 00:32:19 -0500 Subject: [PATCH 3/9] add user error to failed touch --- apps/Minecraft Java Server/install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/Minecraft Java Server/install b/apps/Minecraft Java Server/install index f5bdfa0cd1..997fb47cae 100755 --- a/apps/Minecraft Java Server/install +++ b/apps/Minecraft Java Server/install @@ -36,7 +36,7 @@ ensure_server_dir() { sudo chown "$USER":"$USER" "$server_dir/.write-test" 2>/dev/null || true sudo rm -f "$server_dir/.write-test" 2>/dev/null || true - touch "$server_dir/.write-test" 2>/dev/null || error "The chosen server directory exists, but is not writable by $USER: + touch "$server_dir/.write-test" 2>/dev/null || error "User error: The chosen server directory exists, but is not writable by $USER: $server_dir Try this outside Pi-Apps: From c80a6f3f518d1df015aa4ec31b2dcbb4c50e9ef8 Mon Sep 17 00:00:00 2001 From: Birdman Date: Tue, 7 Jul 2026 10:18:40 -0400 Subject: [PATCH 4/9] Update install Did Gman's requests, minor fixes overall --- apps/Minecraft Java Server/install | 65 ++++++++++++------------------ 1 file changed, 25 insertions(+), 40 deletions(-) diff --git a/apps/Minecraft Java Server/install b/apps/Minecraft Java Server/install index 997fb47cae..303aca03c7 100755 --- a/apps/Minecraft Java Server/install +++ b/apps/Minecraft Java Server/install @@ -29,14 +29,7 @@ ensure_server_dir() { sudo chmod 775 "$server_dir" 2>/dev/null || true if ! touch "$server_dir/.write-test" 2>/dev/null; then - # If the folder was created with sudo on an external drive, try once more to - # create a test file and then hand it to the user. If the user still cannot - # write, the mount permissions need fixed outside this installer. - sudo touch "$server_dir/.write-test" 2>/dev/null || true - sudo chown "$USER":"$USER" "$server_dir/.write-test" 2>/dev/null || true - sudo rm -f "$server_dir/.write-test" 2>/dev/null || true - - touch "$server_dir/.write-test" 2>/dev/null || error "User error: The chosen server directory exists, but is not writable by $USER: + error "The chosen server directory exists, but is not writable by $USER: $server_dir Try this outside Pi-Apps: @@ -99,7 +92,7 @@ choose_server_directory() { ;; "Custom path") server_dir=$(yad --center --wrap \ - --text "Enter the full path where the Minecraft server should be installed.\n\nExamples:\n$HOME/$SERVER_FOLDER_NAME\n/media/$USER/MySSD/$SERVER_FOLDER_NAME\n\nAvoid spaces in the path." \ + --text "Enter the full path where the Minecraft server should be installed.\n\nExamples:\n$HOME/$SERVER_FOLDER_NAME\n/media/$USER/My SSD/$SERVER_FOLDER_NAME\n\nPaths with spaces are supported, but the path must be an absolute path." \ --entry \ --entry-text "$DEFAULT_SERVER_DIR" \ --button="Use this path":0) @@ -121,12 +114,6 @@ choose_server_directory() { server_dir="$(readlink -m "$server_dir")" fi - # Keep this simple and safe for systemd paths. - if [[ "$server_dir" =~ [[:space:]] ]]; then - error "The chosen path contains spaces:\n$server_dir\n\nPlease choose a path without spaces." - fi - - ensure_server_dir mkdir -p "$CONFIG_DIR" @@ -150,9 +137,7 @@ server_category="$output" download_fill_project() { PROJECT="$1" VERSION="$2" - USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" - - builds_response=$(wget --user-agent="$USER_AGENT" -O- "https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds") || error "Could not fetch $PROJECT builds for $VERSION." + builds_response=$(wget -O- "https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds") || error "Could not fetch $PROJECT builds for $VERSION." # Prefer the newest STABLE build. If none exists, fall back to the newest build so Folia/experimental projects can still be tested. build_json=$(echo "$builds_response" | jq -c '([.[] | select(.channel == "STABLE")] | last) // (last)') @@ -170,7 +155,7 @@ download_fill_project() { fi status "Selected $PROJECT $VERSION build channel: $channel" - wget --user-agent="$USER_AGENT" -O "$server_jar" "$download_url" || exit 1 + wget -O "$server_jar" "$download_url" || exit 1 } case "$server_category" in @@ -196,12 +181,16 @@ case "$server_category" in status "Selected $server_category version $server_version" installer_version=$(wget -O- https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json | jq -r '.'\"$server_version\"' | [last] | .[]') + # example file formats + # https://maven.minecraftforge.net/net/minecraftforge/forge/1.18.1-39.0.63/forge-1.18.1-39.0.63-installer.jar + # https://maven.minecraftforge.net/net/minecraftforge/forge/1.3.2-4.3.5.318/forge-1.3.2-4.3.5.318-universal.zip + # https://maven.minecraftforge.net/net/minecraftforge/forge/1.2.5-3.4.9.171/forge-1.2.5-3.4.9.171-server.zip + server_jar="forge-$installer_version-installer.jar" wget -O "$server_jar" "https://maven.minecraftforge.net/net/minecraftforge/forge/$installer_version/forge-$installer_version-installer.jar" || exit 1 ;; "Paper") - USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" - available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') + available_versions=$(wget -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" @@ -210,8 +199,7 @@ case "$server_category" in download_fill_project "paper" "$server_version" ;; "Folia") - USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" - available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') + available_versions=$(wget -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" @@ -357,17 +345,10 @@ case "$java_selection" in "Java 25") if package_available temurin-25-jre ;then install_packages temurin-25-jre || exit 1 - java_location="/usr/lib/jvm/temurin-25-jre-$dpkg_arch/bin/java" - elif package_available java-25-amazon-corretto-jdk ;then - install_packages java-25-amazon-corretto-jdk || exit 1 - java_location="/usr/lib/jvm/java-25-amazon-corretto/bin/java" - elif [ -x "/usr/lib/jvm/java-25-amazon-corretto/bin/java" ]; then - java_location="/usr/lib/jvm/java-25-amazon-corretto/bin/java" - elif command -v java >/dev/null 2>&1 && java -version 2>&1 | grep -q 'version "25'; then - java_location="$(command -v java)" else - error "Java 25 is not available from Adoptium and no working Java 25 executable was found. Exiting the script." + error "Java 25 is not available for your platform from Adoptium. Exiting the script." fi + java_location="/usr/lib/jvm/temurin-25-jre-$dpkg_arch/bin/java" ;; esac @@ -391,6 +372,9 @@ if [[ "$server_category" == "Forge" ]]; then rm -f ${server_jar} # forge has MANY ways to launch depending on the version + # for some reason they like re-inventing the wheel and doing things differently than everyone else + # the below covers all the ways I have seen from 1.6.4 - 1.18.1 + # its possible I missed an obscure format that was only used once... please create an issue if that is the case if [[ -f "minecraftforge-universal-$installer_version.jar" ]]; then server_jar="minecraftforge-universal-$installer_version.jar" elif [[ -f "forge-$installer_version-universal.jar" ]]; then @@ -401,6 +385,7 @@ if [[ "$server_category" == "Forge" ]]; then server_jar="forge-$installer_version.jar" elif [[ -f "run.sh" ]]; then # set server_jar to empty to skip start-server.sh universal script creation + # this is the most up to date forge launch format where their own run.sh file is provided server_jar="" sed -i "s:java:${java_location}:g" run.sh sed -i 's:"$@":nogui:g' run.sh @@ -413,14 +398,14 @@ if [[ "$server_category" == "Forge" ]]; then fi if [ -n "$server_jar" ]; then - cat > "$server_dir/start-server.sh" < "$server_dir/start-server.sh" < "$server_dir/eula.txt" mkdir -p "$server_dir/mods" mkdir -p "$HOME/.local/share/applications" -tee "$DESKTOP_FILE" < Date: Tue, 7 Jul 2026 10:34:56 -0400 Subject: [PATCH 5/9] Update install to Gman requests Forgot 2 things, fixed them here --- apps/Minecraft Java Server/install | 54 +++++++++++++++++------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/apps/Minecraft Java Server/install b/apps/Minecraft Java Server/install index 303aca03c7..f1b99acac9 100755 --- a/apps/Minecraft Java Server/install +++ b/apps/Minecraft Java Server/install @@ -29,7 +29,14 @@ ensure_server_dir() { sudo chmod 775 "$server_dir" 2>/dev/null || true if ! touch "$server_dir/.write-test" 2>/dev/null; then - error "The chosen server directory exists, but is not writable by $USER: + # If the folder was created with sudo on an external drive, try once more to + # create a test file and then hand it to the user. If the user still cannot + # write, the mount permissions need fixed outside this installer. + sudo touch "$server_dir/.write-test" 2>/dev/null || true + sudo chown "$USER":"$USER" "$server_dir/.write-test" 2>/dev/null || true + sudo rm -f "$server_dir/.write-test" 2>/dev/null || true + + touch "$server_dir/.write-test" 2>/dev/null || error "The chosen server directory exists, but is not writable by $USER: $server_dir Try this outside Pi-Apps: @@ -92,7 +99,7 @@ choose_server_directory() { ;; "Custom path") server_dir=$(yad --center --wrap \ - --text "Enter the full path where the Minecraft server should be installed.\n\nExamples:\n$HOME/$SERVER_FOLDER_NAME\n/media/$USER/My SSD/$SERVER_FOLDER_NAME\n\nPaths with spaces are supported, but the path must be an absolute path." \ + --text "Enter the full path where the Minecraft server should be installed.\n\nExamples:\n$HOME/$SERVER_FOLDER_NAME\n/media/$USER/MySSD/$SERVER_FOLDER_NAME\n\nAvoid spaces in the path." \ --entry \ --entry-text "$DEFAULT_SERVER_DIR" \ --button="Use this path":0) @@ -114,6 +121,12 @@ choose_server_directory() { server_dir="$(readlink -m "$server_dir")" fi + # Keep this simple and safe for systemd paths. + if [[ "$server_dir" =~ [[:space:]] ]]; then + error "The chosen path contains spaces:\n$server_dir\n\nPlease choose a path without spaces." + fi + + ensure_server_dir mkdir -p "$CONFIG_DIR" @@ -137,7 +150,9 @@ server_category="$output" download_fill_project() { PROJECT="$1" VERSION="$2" - builds_response=$(wget -O- "https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds") || error "Could not fetch $PROJECT builds for $VERSION." + USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" + + builds_response=$(wget --user-agent="$USER_AGENT" -O- "https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds") || error "Could not fetch $PROJECT builds for $VERSION." # Prefer the newest STABLE build. If none exists, fall back to the newest build so Folia/experimental projects can still be tested. build_json=$(echo "$builds_response" | jq -c '([.[] | select(.channel == "STABLE")] | last) // (last)') @@ -155,7 +170,7 @@ download_fill_project() { fi status "Selected $PROJECT $VERSION build channel: $channel" - wget -O "$server_jar" "$download_url" || exit 1 + wget --user-agent="$USER_AGENT" -O "$server_jar" "$download_url" || exit 1 } case "$server_category" in @@ -181,16 +196,12 @@ case "$server_category" in status "Selected $server_category version $server_version" installer_version=$(wget -O- https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json | jq -r '.'\"$server_version\"' | [last] | .[]') - # example file formats - # https://maven.minecraftforge.net/net/minecraftforge/forge/1.18.1-39.0.63/forge-1.18.1-39.0.63-installer.jar - # https://maven.minecraftforge.net/net/minecraftforge/forge/1.3.2-4.3.5.318/forge-1.3.2-4.3.5.318-universal.zip - # https://maven.minecraftforge.net/net/minecraftforge/forge/1.2.5-3.4.9.171/forge-1.2.5-3.4.9.171-server.zip - server_jar="forge-$installer_version-installer.jar" wget -O "$server_jar" "https://maven.minecraftforge.net/net/minecraftforge/forge/$installer_version/forge-$installer_version-installer.jar" || exit 1 ;; "Paper") - available_versions=$(wget -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') + USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" + available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" @@ -199,7 +210,8 @@ case "$server_category" in download_fill_project "paper" "$server_version" ;; "Folia") - available_versions=$(wget -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') + USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" + available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" @@ -372,9 +384,6 @@ if [[ "$server_category" == "Forge" ]]; then rm -f ${server_jar} # forge has MANY ways to launch depending on the version - # for some reason they like re-inventing the wheel and doing things differently than everyone else - # the below covers all the ways I have seen from 1.6.4 - 1.18.1 - # its possible I missed an obscure format that was only used once... please create an issue if that is the case if [[ -f "minecraftforge-universal-$installer_version.jar" ]]; then server_jar="minecraftforge-universal-$installer_version.jar" elif [[ -f "forge-$installer_version-universal.jar" ]]; then @@ -385,7 +394,6 @@ if [[ "$server_category" == "Forge" ]]; then server_jar="forge-$installer_version.jar" elif [[ -f "run.sh" ]]; then # set server_jar to empty to skip start-server.sh universal script creation - # this is the most up to date forge launch format where their own run.sh file is provided server_jar="" sed -i "s:java:${java_location}:g" run.sh sed -i 's:"$@":nogui:g' run.sh @@ -398,14 +406,14 @@ if [[ "$server_category" == "Forge" ]]; then fi if [ -n "$server_jar" ]; then - cat > "$server_dir/start-server.sh" < "$server_dir/start-server.sh" < "$server_dir/eula.txt" mkdir -p "$server_dir/mods" mkdir -p "$HOME/.local/share/applications" -tee "$DESKTOP_FILE" < Date: Tue, 7 Jul 2026 10:45:04 -0400 Subject: [PATCH 6/9] Update install Fixed EOF2 Forgot EOF2 changes back to EOF --- apps/Minecraft Java Server/install | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/Minecraft Java Server/install b/apps/Minecraft Java Server/install index f1b99acac9..01a8d11aae 100755 --- a/apps/Minecraft Java Server/install +++ b/apps/Minecraft Java Server/install @@ -406,14 +406,14 @@ if [[ "$server_category" == "Forge" ]]; then fi if [ -n "$server_jar" ]; then - cat > "$server_dir/start-server.sh" < "$server_dir/start-server.sh" < "$server_dir/eula.txt" mkdir -p "$server_dir/mods" mkdir -p "$HOME/.local/share/applications" -tee "$DESKTOP_FILE" < Date: Tue, 7 Jul 2026 10:49:27 -0400 Subject: [PATCH 7/9] Update install Fixed USER AGENT as Gman requested --- apps/Minecraft Java Server/install | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/Minecraft Java Server/install b/apps/Minecraft Java Server/install index 01a8d11aae..3db38bceea 100755 --- a/apps/Minecraft Java Server/install +++ b/apps/Minecraft Java Server/install @@ -150,9 +150,7 @@ server_category="$output" download_fill_project() { PROJECT="$1" VERSION="$2" - USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" - - builds_response=$(wget --user-agent="$USER_AGENT" -O- "https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds") || error "Could not fetch $PROJECT builds for $VERSION." + builds_response=$(wget -O- "https://fill.papermc.io/v3/projects/${PROJECT}/versions/${VERSION}/builds") || error "Could not fetch $PROJECT builds for $VERSION." # Prefer the newest STABLE build. If none exists, fall back to the newest build so Folia/experimental projects can still be tested. build_json=$(echo "$builds_response" | jq -c '([.[] | select(.channel == "STABLE")] | last) // (last)') @@ -170,7 +168,7 @@ download_fill_project() { fi status "Selected $PROJECT $VERSION build channel: $channel" - wget --user-agent="$USER_AGENT" -O "$server_jar" "$download_url" || exit 1 + wget -O "$server_jar" "$download_url" || exit 1 } case "$server_category" in @@ -196,12 +194,16 @@ case "$server_category" in status "Selected $server_category version $server_version" installer_version=$(wget -O- https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json | jq -r '.'\"$server_version\"' | [last] | .[]') + # example file formats + # https://maven.minecraftforge.net/net/minecraftforge/forge/1.18.1-39.0.63/forge-1.18.1-39.0.63-installer.jar + # https://maven.minecraftforge.net/net/minecraftforge/forge/1.3.2-4.3.5.318/forge-1.3.2-4.3.5.318-universal.zip + # https://maven.minecraftforge.net/net/minecraftforge/forge/1.2.5-3.4.9.171/forge-1.2.5-3.4.9.171-server.zip + server_jar="forge-$installer_version-installer.jar" wget -O "$server_jar" "https://maven.minecraftforge.net/net/minecraftforge/forge/$installer_version/forge-$installer_version-installer.jar" || exit 1 ;; "Paper") - USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" - available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') + available_versions=$(wget -O- https://fill.papermc.io/v3/projects/paper/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" @@ -210,8 +212,7 @@ case "$server_category" in download_fill_project "paper" "$server_version" ;; "Folia") - USER_AGENT="pi-apps-minecraft-java-server/1.0 ($USER)" - available_versions=$(wget --user-agent="$USER_AGENT" -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') + available_versions=$(wget -O- https://fill.papermc.io/v3/projects/folia/versions | jq -r '.versions.[].version.id') description="What version of $server_category do you want to run?" table=($available_versions) userinput_func "$description" "${table[@]}" From dede5f8d702b0468ab1769707be07c2be0bf3222 Mon Sep 17 00:00:00 2001 From: Birdman Date: Tue, 7 Jul 2026 10:56:15 -0400 Subject: [PATCH 8/9] Update install Added documentation back as requested by the Gman From 629ede50a053da24a46b354ffbcb7c66f174e2fa Mon Sep 17 00:00:00 2001 From: Birdman Date: Tue, 7 Jul 2026 10:59:46 -0400 Subject: [PATCH 9/9] Update install Github decided to remove my changes?? Should be fixed now.