Files
pt-minecraft-modpack/start.sh

305 lines
9.0 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
INSTALL_ROOT="${PT_INSTALL_ROOT:-$SCRIPT_DIR}"
SERVER_NAME="${PT_SERVER:-${1:-}}"
RUNTIME_BASE_DIR="${PT_RUNTIME_DIR:-$INSTALL_ROOT/.pt-panel-runtime}"
DOWNLOAD_DIR="$RUNTIME_BASE_DIR/downloads"
BOOTSTRAP_JAR="$DOWNLOAD_DIR/packwiz-installer-bootstrap.jar"
PACKWIZ_META_FILE="packwiz-installer.json"
JAVA_BIN="${JAVA_BIN:-java}"
JAVA_ARGS="${PT_JAVA_ARGS:--Xms1G -Xmx1G}"
SERVER_JAR_OVERRIDE="${PT_SERVER_JAR:-}"
FORCE_UPDATE="${PT_FORCE_UPDATE:-0}"
DRY_RUN="${PT_DRY_RUN:-0}"
AUTO_EULA="${PT_AUTO_EULA:-TRUE}"
PACKWIZ_BOOTSTRAP_NO_UPDATE="${PT_PACKWIZ_BOOTSTRAP_NO_UPDATE:-0}"
FABRIC_INSTALLER_VERSION="${PT_FABRIC_INSTALLER_VERSION:-}"
PACKWIZ_BOOTSTRAP_URL="${PT_PACKWIZ_BOOTSTRAP_URL:-https://github.com/packwiz/packwiz-installer-bootstrap/releases/latest/download/packwiz-installer-bootstrap.jar}"
PACKWIZ_BOOTSTRAP_MAIN_JAR="${PT_PACKWIZ_BOOTSTRAP_MAIN_JAR:-}"
PACK_DIR=""
PACK_URL=""
PACK_SLUG=""
STAMP_FILE=""
log() {
printf '[pt-panel] %s\n' "$*"
}
fail() {
printf '[pt-panel] ERROR: %s\n' "$*" >&2
exit 1
}
need_cmd() {
command -v "$1" >/dev/null 2>&1 || fail "缺少命令: $1"
}
fetch() {
local url="$1"
local dest="$2"
if command -v curl >/dev/null 2>&1; then
curl -fL --retry 3 --retry-delay 2 -o "$dest" "$url"
elif command -v wget >/dev/null 2>&1; then
wget -O "$dest" "$url"
else
fail "缺少 curl 或 wget无法下载文件"
fi
}
fetch_to_stdout() {
local url="$1"
if command -v curl >/dev/null 2>&1; then
curl -fL --retry 3 --retry-delay 2 "$url"
elif command -v wget >/dev/null 2>&1; then
wget -O - "$url"
else
fail "缺少 curl 或 wget无法下载文件"
fi
}
trim_quotes() {
local value="$1"
value="${value#\"}"
value="${value%\"}"
printf '%s' "$value"
}
toml_value() {
local key="$1"
local file="$2"
local line
line="$(grep -E "^${key}[[:space:]]*=" "$file" | head -n 1 || true)"
[ -n "$line" ] || return 1
line="${line#*=}"
line="${line#${line%%[![:space:]]*}}"
trim_quotes "$line"
}
list_available_servers() {
find "$SCRIPT_DIR" -mindepth 1 -maxdepth 1 -type d -name 'server-*' -exec basename {} \; | sort
}
select_server() {
local available count first
if [ -n "$SERVER_NAME" ]; then
PACK_DIR="$SCRIPT_DIR/$SERVER_NAME"
[ -f "$PACK_DIR/pack.toml" ] || fail "指定的服务端不存在: $SERVER_NAME"
return 0
fi
available="$(list_available_servers || true)"
count="$(printf '%s\n' "$available" | sed '/^$/d' | wc -l | awk '{print $1}')"
if [ "$count" = "1" ]; then
first="$(printf '%s\n' "$available" | sed -n '1p')"
SERVER_NAME="$first"
PACK_DIR="$SCRIPT_DIR/$SERVER_NAME"
return 0
fi
if [ "$count" = "0" ]; then
fail "仓库中没有找到任何 server-* 服务端目录"
fi
printf '[pt-panel] 可选服务端:\n%s\n' "$(printf '%s\n' "$available" | sed 's/^/ - /')" >&2
fail "检测到多个服务端,请通过 PT_SERVER=<目录名> 或第一个参数指定例如PT_SERVER=server-01-random-block bash start.sh"
}
ensure_dirs() {
mkdir -p "$INSTALL_ROOT" "$RUNTIME_BASE_DIR" "$DOWNLOAD_DIR"
}
prepare_server_paths() {
PACK_SLUG="$(printf '%s' "$SERVER_NAME" | tr '/' '_')"
STAMP_FILE="$RUNTIME_BASE_DIR/fabric-install-${PACK_SLUG}.stamp"
}
load_pack_versions() {
[ -f "$PACK_DIR/pack.toml" ] || fail "找不到 $PACK_DIR/pack.toml请确认服务端 pack 存在"
MINECRAFT_VERSION="$(toml_value 'minecraft' "$PACK_DIR/pack.toml")"
FABRIC_LOADER_VERSION="$(toml_value 'fabric' "$PACK_DIR/pack.toml")"
[ -n "$MINECRAFT_VERSION" ] || fail "无法从 $PACK_DIR/pack.toml 读取 minecraft 版本"
[ -n "$FABRIC_LOADER_VERSION" ] || fail "无法从 $PACK_DIR/pack.toml 读取 fabric 版本"
}
compute_pack_url() {
if [ -n "${PT_PACK_URL:-}" ]; then
PACK_URL="$PT_PACK_URL"
return 0
fi
if [ -n "${PT_REPO_URL:-}" ] && [ -n "${PT_REPO_REF:-}" ]; then
PACK_URL="${PT_REPO_URL%/}/raw/branch/${PT_REPO_REF}/${SERVER_NAME}/pack.toml"
return 0
fi
PACK_URL="$PACK_DIR/pack.toml"
}
load_latest_fabric_installer_version() {
if [ -n "$FABRIC_INSTALLER_VERSION" ]; then
printf '%s' "$FABRIC_INSTALLER_VERSION"
return 0
fi
local meta version
meta="$(fetch_to_stdout 'https://meta.fabricmc.net/v2/versions/installer')"
version="$(printf '%s\n' "$meta" | grep '"version"' | head -n 1 | sed 's/.*"version": *"\([^"]*\)".*/\1/')"
[ -n "$version" ] || fail "无法获取最新 Fabric installer 版本"
printf '%s' "$version"
}
ensure_packwiz_bootstrap() {
if [ -f "$BOOTSTRAP_JAR" ] && [ "$FORCE_UPDATE" != "1" ]; then
return 0
fi
log "下载 packwiz-installer-bootstrap"
fetch "$PACKWIZ_BOOTSTRAP_URL" "$BOOTSTRAP_JAR"
}
install_fabric_server() {
local installer_version installer_jar wanted_stamp current_stamp
installer_version="$(load_latest_fabric_installer_version)"
installer_jar="$DOWNLOAD_DIR/fabric-installer-${installer_version}.jar"
wanted_stamp="server=$SERVER_NAME mc=$MINECRAFT_VERSION loader=$FABRIC_LOADER_VERSION installer=$installer_version"
current_stamp="$(cat "$STAMP_FILE" 2>/dev/null || true)"
if [ "$FORCE_UPDATE" != "1" ] && [ -f "$INSTALL_ROOT/fabric-server-launch.jar" ] && [ "$wanted_stamp" = "$current_stamp" ]; then
log "Fabric 服务端已就绪,跳过重复安装"
return 0
fi
log "准备安装 Fabric 服务端:$SERVER_NAME (Minecraft $MINECRAFT_VERSION / Loader $FABRIC_LOADER_VERSION)"
fetch "https://maven.fabricmc.net/net/fabricmc/fabric-installer/${installer_version}/fabric-installer-${installer_version}.jar" "$installer_jar"
if [ "$DRY_RUN" = "1" ]; then
log "DRY RUN: 跳过执行 Fabric installer"
return 0
fi
(
cd "$INSTALL_ROOT"
"$JAVA_BIN" -jar "$installer_jar" server -mcversion "$MINECRAFT_VERSION" -loader "$FABRIC_LOADER_VERSION" -downloadMinecraft
)
printf '%s\n' "$wanted_stamp" > "$STAMP_FILE"
}
run_packwiz_installer() {
local args=( -jar "$BOOTSTRAP_JAR" -g --side server --pack-folder "$INSTALL_ROOT" --meta-file "$PACKWIZ_META_FILE" "$PACK_URL" )
if [ -n "$PACKWIZ_BOOTSTRAP_MAIN_JAR" ] && [ "$PACKWIZ_BOOTSTRAP_NO_UPDATE" = "1" ]; then
args=( -jar "$BOOTSTRAP_JAR" --bootstrap-no-update --bootstrap-main-jar "$PACKWIZ_BOOTSTRAP_MAIN_JAR" -g --side server --pack-folder "$INSTALL_ROOT" --meta-file "$PACKWIZ_META_FILE" "$PACK_URL" )
elif [ -n "$PACKWIZ_BOOTSTRAP_MAIN_JAR" ]; then
args=( -jar "$BOOTSTRAP_JAR" --bootstrap-main-jar "$PACKWIZ_BOOTSTRAP_MAIN_JAR" -g --side server --pack-folder "$INSTALL_ROOT" --meta-file "$PACKWIZ_META_FILE" "$PACK_URL" )
elif [ "$PACKWIZ_BOOTSTRAP_NO_UPDATE" = "1" ]; then
args=( -jar "$BOOTSTRAP_JAR" --bootstrap-no-update -g --side server --pack-folder "$INSTALL_ROOT" --meta-file "$PACKWIZ_META_FILE" "$PACK_URL" )
fi
if [ "$DRY_RUN" = "1" ]; then
log "DRY RUN: 跳过执行 packwiz-installer"
log "pack.toml URL: $PACK_URL"
return 0
fi
log "使用 packwiz-installer 同步服务端模组"
(
cd "$INSTALL_ROOT"
"$JAVA_BIN" "${args[@]}"
)
}
write_eula() {
if [ "$AUTO_EULA" = "TRUE" ] || [ "$AUTO_EULA" = "true" ] || [ "$AUTO_EULA" = "1" ]; then
printf 'eula=true\n' > "$INSTALL_ROOT/eula.txt"
log "已写入 eula.txt"
else
log "已跳过自动写入 EULAPT_AUTO_EULA=$AUTO_EULA"
fi
}
find_server_jar() {
if [ -n "$SERVER_JAR_OVERRIDE" ]; then
printf '%s' "$SERVER_JAR_OVERRIDE"
return 0
fi
if [ -f "$INSTALL_ROOT/fabric-server-launch.jar" ]; then
printf '%s' "$INSTALL_ROOT/fabric-server-launch.jar"
return 0
fi
local candidate
candidate="$(find "$INSTALL_ROOT" -maxdepth 1 -type f \( -name 'fabric-server-launch.jar' -o -name 'fabric-server-*.jar' -o -name 'server.jar' \) | sort | head -n 1 || true)"
[ -n "$candidate" ] || return 1
printf '%s' "$candidate"
}
start_server() {
local server_jar
server_jar="$(find_server_jar || true)"
if [ "$DRY_RUN" = "1" ]; then
if [ -n "$server_jar" ]; then
log "使用服务端文件: $server_jar"
else
log "DRY RUN: 当前尚未生成服务端 jar正式运行时会先执行 Fabric installer"
fi
log "安装目录: $INSTALL_ROOT"
log "启动参数: $JAVA_ARGS"
log "DRY RUN: 跳过实际启动"
return 0
fi
[ -n "$server_jar" ] || fail "找不到可启动的服务端 jar请检查 Fabric 安装是否成功"
log "使用服务端: $SERVER_NAME"
log "使用服务端文件: $server_jar"
log "安装目录: $INSTALL_ROOT"
log "启动参数: $JAVA_ARGS"
cd "$INSTALL_ROOT"
exec "$JAVA_BIN" $JAVA_ARGS -jar "$server_jar" nogui
}
main() {
need_cmd "$JAVA_BIN"
need_cmd grep
need_cmd sed
need_cmd awk
need_cmd find
select_server
ensure_dirs
prepare_server_paths
load_pack_versions
compute_pack_url
ensure_packwiz_bootstrap
log "脚本目录: $SCRIPT_DIR"
log "安装目录: $INSTALL_ROOT"
log "选择服务端: $SERVER_NAME"
log "Pack 目录: $PACK_DIR"
log "Pack URL: $PACK_URL"
log "Minecraft 版本: $MINECRAFT_VERSION"
log "Fabric Loader 版本: $FABRIC_LOADER_VERSION"
install_fabric_server
run_packwiz_installer
write_eula
start_server
}
main "$@"