#!/usr/bin/env bash # Compile le plugin, configure le serveur de dev, puis lance Hytale. set -euo pipefail ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$ROOT" JAVA_HOME="/usr/lib/jvm/java-25-openjdk" export JAVA_HOME export PATH="$JAVA_HOME/bin:$PATH" GRADLE_PROPS="$ROOT/gradle.properties" HYTALE_PROPS="$ROOT/hytale.properties" GRADLE_ARGS=() read_property() { local file="$1" local key="$2" if [[ -f "$file" ]]; then grep -E "^${key}=" "$file" 2>/dev/null | tail -1 | cut -d= -f2- | tr -d '\r' || true fi } find_assets_zip() { local home="$1" [[ -z "$home" || ! -d "$home" ]] && return 1 local candidates=( "$home/install/release/package/game/latest/Assets.zip" "$home/Assets.zip" ) local path for path in "${candidates[@]}"; do if [[ -f "$path" && -s "$path" ]]; then echo "$path" return 0 fi done find "$home" -name "Assets.zip" -size +1M 2>/dev/null | head -1 } detect_hytale_home() { local candidates=( "${HYTALE_HOME:-}" "$(read_property "$HYTALE_PROPS" "hytale.home_path")" "$(read_property "$GRADLE_PROPS" "hytale.home_path")" "$HOME/.var/app/com.hypixel.HytaleLauncher/data/Hytale" "$HOME/.local/share/Hytale" "$HOME/AppData/Roaming/Hytale" ) local candidate assets for candidate in "${candidates[@]}"; do [[ -z "$candidate" ]] && continue assets="$(find_assets_zip "$candidate" || true)" if [[ -n "$assets" ]]; then echo "$candidate" return 0 fi done return 1 } ensure_hytale_home_path() { local home home="$(detect_hytale_home || true)" if [[ -z "$home" ]]; then echo "Erreur: Assets.zip introuvable (fichier vide ou installation absente)." >&2 echo "" >&2 echo "Le serveur a besoin des assets du jeu Hytale. Configurez le chemin :" >&2 echo "" >&2 echo " cp hytale.properties.example hytale.properties" >&2 echo " # puis éditez hytale.home_path=/chemin/vers/Hytale" >&2 echo "" >&2 echo " Ou : export HYTALE_HOME=/chemin/vers/Hytale" >&2 echo " Ou : ajoutez hytale.home_path=... dans gradle.properties" >&2 echo "" >&2 echo "Le dossier doit contenir install/.../Assets.zip (via le launcher Hytale)." >&2 exit 1 fi local assets assets="$(find_assets_zip "$home")" echo "Hytale: $home" echo "Assets: $assets" GRADLE_ARGS+=("-Phytale.home_path=$home") if [[ ! -f "$HYTALE_PROPS" ]] || [[ "$(read_property "$HYTALE_PROPS" "hytale.home_path")" != "$home" ]]; then echo "hytale.home_path=$home" > "$HYTALE_PROPS" echo "Enregistré dans hytale.properties" fi } reset_devserver_if_needed() { if [[ "${HYTALE_RESET_DEVSERVER:-}" == "1" && -d "$ROOT/devserver" ]]; then echo "HYTALE_RESET_DEVSERVER=1 : suppression de devserver/" rm -rf "$ROOT/devserver" fi } sync_third_party_plugins() { local src="$ROOT/plugins" local dest="$ROOT/devserver/mods" local jar [[ -d "$src" ]] || return 0 mkdir -p "$dest" shopt -s nullglob for jar in "$src"/*.jar; do cp -u "$jar" "$dest/" echo "Plugin tiers: $(basename "$jar") -> devserver/mods/" done shopt -u nullglob } apply_world_spawn() { local world_config="$ROOT/devserver/universe/worlds/default/config.json" local spawn_template="$ROOT/config/universe/worlds/default/spawn-provider.json" local players_dir="$ROOT/devserver/universe/players" [[ -f "$spawn_template" ]] || return 0 [[ -f "$world_config" ]] || return 0 python3 - "$spawn_template" "$world_config" "$players_dir" <<'PY' import json import sys from pathlib import Path spawn_template = Path(sys.argv[1]) world_config = Path(sys.argv[2]) players_dir = Path(sys.argv[3]) patch = json.loads(spawn_template.read_text(encoding="utf-8")) config = json.loads(world_config.read_text(encoding="utf-8")) config.update(patch) world_config.write_text(json.dumps(config, indent=2) + "\n", encoding="utf-8") spawn = patch["SpawnProvider"]["SpawnPoint"] last_position = { "X": spawn["X"], "Y": spawn["Y"], "Z": spawn["Z"], "Pitch": spawn.get("Pitch", 0.0), "Yaw": spawn.get("Yaw", 0.0), "Roll": spawn.get("Roll", 0.0), } position = {"X": spawn["X"], "Y": spawn["Y"], "Z": spawn["Z"]} rotation = { "Pitch": spawn.get("Pitch", 0.0), "Yaw": spawn.get("Yaw", 0.0), "Roll": spawn.get("Roll", 0.0), } if players_dir.is_dir(): for player_file in players_dir.glob("*.json"): data = json.loads(player_file.read_text(encoding="utf-8")) components = data.get("Components", {}) transform = components.get("Transform") if isinstance(transform, dict): transform["Position"] = dict(position) transform["Rotation"] = dict(rotation) player_data = components.get("Player", {}).get("PlayerData", {}) per_world = player_data.get("PerWorldData", {}).get("default") if isinstance(per_world, dict): per_world["LastPosition"] = dict(last_position) player_file.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8") print( f"Spawn default: X={spawn['X']}, Y={spawn['Y']}, Z={spawn['Z']} " f"(world config + joueurs existants)" ) PY } run_gradle() { "$ROOT/gradlew" --stop 2>/dev/null || true "$ROOT/gradlew" "${GRADLE_ARGS[@]}" "$@" } if [[ ! -d "$JAVA_HOME" ]]; then echo "Erreur: JDK introuvable: $JAVA_HOME" >&2 exit 1 fi echo "JAVA_HOME=$JAVA_HOME ($("$JAVA_HOME/bin/java" -version 2>&1 | head -1))" ensure_hytale_home_path reset_devserver_if_needed echo "Configuration du serveur de dev..." run_gradle setupServer sync_third_party_plugins echo "Compilation..." run_gradle build apply_world_spawn echo "Démarrage du serveur (logs: devserver/logs/)..." exec "$ROOT/gradlew" "${GRADLE_ARGS[@]}" runServer