# PaperMC & Plugins Auto-Updater This script automates updating your PaperMC server and key plugins (EssentialsX, mcMMO) with detailed logging and safety checks. ## Features - **PaperMC:** - Fetches the latest stable PaperMC version and build (above a minimum build number). - Downloads and replaces the server jar only if a newer stable build is available. - Backs up the old server jar before updating. - Tracks the current build in `current_build.txt`. - **EssentialsX Plugins:** - Downloads the latest EssentialsX jars (excluding Discord, GeoIP, XMPP variants). - Backs up old EssentialsX jars before replacing them. - **mcMMO Plugin:** - Downloads the latest mcMMO jar. - Backs up the old mcMMO jar before replacing it. ## Usage 1. Ensure `jq` and `curl` are installed. 2. Place the script in your PaperMC server directory. 3. Run: `bash paper_updater.sh` Backups are stored in the `backups` directory and plugin subfolders. --- **Note:** - The script must be run with permissions to write to the server and plugins directories. - Review and adjust paths if your server structure differs.
192 lines
6.4 KiB
Bash
192 lines
6.4 KiB
Bash
#!/bin/bash
|
|
|
|
# PaperMC automatic updater script with detailed logging
|
|
# - Always fetches the latest stable PaperMC version
|
|
# - Only updates if the build is stable (not beta/experimental) and build number > MIN_BUILD
|
|
# - Stores current build number in current_build.txt
|
|
|
|
API_BASE="https://api.papermc.io/v2/projects/paper"
|
|
MIN_BUILD=9
|
|
BUILD_FILE="current_build.txt"
|
|
JAR_NAME="paperclip.jar"
|
|
BACKUP_DIR="./backups"
|
|
|
|
set -e
|
|
|
|
log() {
|
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
|
|
}
|
|
|
|
log "=== PaperMC Updater Script Starting ==="
|
|
|
|
# Ensure jq is installed
|
|
if ! command -v jq &> /dev/null; then
|
|
log "ERROR: jq is required but not installed. Please install jq."
|
|
exit 1
|
|
fi
|
|
|
|
# Create backup directory if it doesn't exist
|
|
log "Ensuring backup directory exists at $BACKUP_DIR"
|
|
mkdir -p "$BACKUP_DIR"
|
|
|
|
# 1. Get all versions and pick the latest
|
|
log "Fetching all PaperMC versions from $API_BASE"
|
|
VERSIONS_JSON=$(curl -s "$API_BASE")
|
|
if [ -z "$VERSIONS_JSON" ]; then
|
|
log "ERROR: Failed to fetch versions from PaperMC API."
|
|
exit 1
|
|
fi
|
|
log "Received versions JSON: $(echo "$VERSIONS_JSON" | jq -c '{versions}')"
|
|
LATEST_VERSION=$(echo "$VERSIONS_JSON" | jq -r '.versions | last')
|
|
log "Latest PaperMC version: $LATEST_VERSION"
|
|
|
|
if [ -z "$LATEST_VERSION" ]; then
|
|
log "ERROR: Could not determine latest PaperMC version."
|
|
exit 1
|
|
fi
|
|
|
|
# 2. Get builds for the latest version
|
|
log "Fetching builds for version $LATEST_VERSION"
|
|
BUILDS_JSON=$(curl -s "$API_BASE/versions/$LATEST_VERSION")
|
|
if [ -z "$BUILDS_JSON" ]; then
|
|
log "ERROR: Failed to fetch builds for version $LATEST_VERSION."
|
|
exit 1
|
|
fi
|
|
log "Received builds JSON: $(echo "$BUILDS_JSON" | jq -c '{builds}')"
|
|
BUILD_NUMBERS=$(echo "$BUILDS_JSON" | jq '.builds | map(select(. > '"$MIN_BUILD"')) | sort | reverse | .[]')
|
|
log "Build numbers above MIN_BUILD ($MIN_BUILD): $BUILD_NUMBERS"
|
|
|
|
# 3. Find the latest stable build above MIN_BUILD
|
|
log "Searching for latest stable build (channel == \"default\") above MIN_BUILD..."
|
|
LATEST_BUILD=""
|
|
for build in $BUILD_NUMBERS; do
|
|
log "Checking build $build"
|
|
BUILD_META=$(curl -s "$API_BASE/versions/$LATEST_VERSION/builds/$build")
|
|
if [ -z "$BUILD_META" ]; then
|
|
log "WARNING: Failed to fetch metadata for build $build"
|
|
continue
|
|
fi
|
|
CHANNEL=$(echo "$BUILD_META" | jq -r '.channel')
|
|
log "Build $build channel: $CHANNEL"
|
|
if [ "$CHANNEL" = "default" ]; then
|
|
LATEST_BUILD=$build
|
|
log "Found latest stable build: $LATEST_BUILD"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -z "$LATEST_BUILD" ]; then
|
|
log "ERROR: No suitable stable build found for version $LATEST_VERSION."
|
|
exit 1
|
|
fi
|
|
|
|
# 4. Compare with current build
|
|
CURRENT_BUILD=$(cat "$BUILD_FILE" 2>/dev/null || echo "0")
|
|
log "Current build: $CURRENT_BUILD, Latest available: $LATEST_BUILD"
|
|
if [ "$LATEST_BUILD" -le "$CURRENT_BUILD" ]; then
|
|
log "No update needed. Current build: $CURRENT_BUILD, Latest: $LATEST_BUILD"
|
|
exit 0
|
|
fi
|
|
|
|
# 5. Download and update
|
|
JAR_URL="$API_BASE/versions/$LATEST_VERSION/builds/$LATEST_BUILD/downloads/paper-$LATEST_VERSION-$LATEST_BUILD.jar"
|
|
log "Downloading PaperMC $LATEST_VERSION build $LATEST_BUILD from $JAR_URL"
|
|
if curl -fsSL -o "$JAR_NAME.new" "$JAR_URL"; then
|
|
log "Download successful: $JAR_NAME.new"
|
|
else
|
|
log "ERROR: Failed to download PaperMC jar from $JAR_URL"
|
|
exit 1
|
|
fi
|
|
|
|
# 6. Backup old jar if it exists
|
|
if [ -f "$JAR_NAME" ]; then
|
|
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
|
BACKUP_PATH="$BACKUP_DIR/paperclip_${CURRENT_BUILD}_$TIMESTAMP.jar"
|
|
log "Backing up existing $JAR_NAME to $BACKUP_PATH"
|
|
mv "$JAR_NAME" "$BACKUP_PATH"
|
|
else
|
|
log "No existing $JAR_NAME found, skipping backup."
|
|
fi
|
|
|
|
# 7. Replace with new jar
|
|
log "Replacing $JAR_NAME with new version"
|
|
mv "$JAR_NAME.new" "$JAR_NAME"
|
|
echo "$LATEST_BUILD" > "$BUILD_FILE"
|
|
log "Updated to PaperMC $LATEST_VERSION build $LATEST_BUILD"
|
|
|
|
# --- Update EssentialsX plugins ---
|
|
PLUGINS_DIR="/home/paper/plugins"
|
|
TEMP_ESS_DIR="$PLUGINS_DIR/.tmp_essentials_update"
|
|
log "Updating EssentialsX plugins in $PLUGINS_DIR"
|
|
mkdir -p "$TEMP_ESS_DIR"
|
|
cd "$TEMP_ESS_DIR"
|
|
|
|
# Jenkins API for EssentialsX
|
|
ESS_API="https://ci.ender.zone/job/EssentialsX/lastSuccessfulBuild/api/json"
|
|
ESS_BASE="https://ci.ender.zone/job/EssentialsX/lastSuccessfulBuild/artifact"
|
|
|
|
log "Fetching EssentialsX artifact list from $ESS_API"
|
|
ESS_ARTIFACTS=$(curl -s "$ESS_API")
|
|
ESS_DOWNLOAD_SUCCESS=1
|
|
if [ -z "$ESS_ARTIFACTS" ]; then
|
|
log "WARNING: Failed to fetch EssentialsX artifacts."
|
|
ESS_DOWNLOAD_SUCCESS=0
|
|
else
|
|
echo "$ESS_ARTIFACTS" | jq -r '
|
|
.artifacts[]
|
|
| select(
|
|
.fileName | startswith("EssentialsX")
|
|
and (contains("Discord") | not)
|
|
and (contains("DiscordLink") | not)
|
|
and (contains("GeoIP") | not)
|
|
and (contains("XMPP") | not)
|
|
)
|
|
| .relativePath
|
|
' | while read -r relpath; do
|
|
jarname=$(basename "$relpath")
|
|
log "Downloading $jarname from $ESS_BASE/$relpath"
|
|
if curl -fsSL -o "$jarname" "$ESS_BASE/$relpath"; then
|
|
log "Downloaded $jarname"
|
|
else
|
|
log "WARNING: Failed to download $jarname"
|
|
ESS_DOWNLOAD_SUCCESS=0
|
|
fi
|
|
done
|
|
fi
|
|
|
|
# Only replace old jars if all new ones downloaded successfully
|
|
cd "$PLUGINS_DIR"
|
|
if [ "$ESS_DOWNLOAD_SUCCESS" -eq 1 ] && [ "$(ls -1 "$TEMP_ESS_DIR"/Essentials*.jar 2>/dev/null | wc -l)" -gt 0 ]; then
|
|
log "All EssentialsX jars downloaded successfully. Backing up and replacing old jars."
|
|
BACKUP_ESS="$PLUGINS_DIR/backup_essentials_$(date +%Y%m%d_%H%M%S)"
|
|
mkdir -p "$BACKUP_ESS"
|
|
mv Essentials*.jar "$BACKUP_ESS"/ 2>/dev/null || true
|
|
mv "$TEMP_ESS_DIR"/Essentials*.jar "$PLUGINS_DIR"/
|
|
else
|
|
log "EssentialsX update failed or no new jars found. Old jars remain untouched."
|
|
fi
|
|
rm -rf "$TEMP_ESS_DIR"
|
|
|
|
# --- Update mcMMO plugin ---
|
|
log "Updating mcMMO plugin in $PLUGINS_DIR"
|
|
cd "$PLUGINS_DIR"
|
|
TEMP_MCM="$PLUGINS_DIR/.tmp_mcmmo_update"
|
|
mkdir -p "$TEMP_MCM"
|
|
|
|
# Download latest mcMMO jar to temp dir
|
|
MCMMO_URL="https://popicraft.net/jenkins/job/mcMMO/lastSuccessfulBuild/artifact/target/mcMMO.jar"
|
|
log "Downloading mcMMO.jar from $MCMMO_URL"
|
|
if curl -fsSL -o "$TEMP_MCM/mcMMO.jar" "$MCMMO_URL"; then
|
|
log "Downloaded mcMMO.jar"
|
|
if [ -f mcMMO.jar ]; then
|
|
BACKUP_MCM="$PLUGINS_DIR/backup_mcmmo_$(date +%Y%m%d_%H%M%S)"
|
|
mkdir -p "$BACKUP_MCM"
|
|
mv mcMMO.jar "$BACKUP_MCM"/
|
|
fi
|
|
mv "$TEMP_MCM/mcMMO.jar" .
|
|
else
|
|
log "WARNING: Failed to download mcMMO.jar. Old jar remains untouched."
|
|
fi
|
|
rm -rf "$TEMP_MCM"
|
|
|
|
log "=== PaperMC Updater Script Finished ==="
|