diff --git a/build-start-dedicated-server.sh b/build-start-dedicated-server.sh new file mode 100644 index 000000000..7f6bd3a79 --- /dev/null +++ b/build-start-dedicated-server.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.dedicated-server.yml" +SERVICE_NAME="minecraft-lce-dedicated-server" +PERSIST_DIR="${SCRIPT_DIR}/server-data" + +if [[ ! -f "${COMPOSE_FILE}" ]]; then + echo "[error] docker-compose file not found: ${COMPOSE_FILE}" >&2 + exit 1 +fi + +if command -v docker >/dev/null 2>&1; then + COMPOSE_CMD=(docker compose) +elif command -v docker-compose >/dev/null 2>&1; then + COMPOSE_CMD=(docker-compose) +else + echo "[error] docker compose is not available." >&2 + exit 1 +fi + +# can choose between release and debug, but honestly there isn’t much use +if [[ "${#}" -gt 1 ]]; then + echo "Usage: $0 [release|debug|]" >&2 + exit 1 +fi + +if [[ "${#}" -eq 1 ]]; then + case "${1}" in + release) + MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Release" + ;; + debug) + MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Debug" + ;; + *) + MC_RUNTIME_DIR_INPUT="${1}" + ;; + esac +else + if [[ -f "${SCRIPT_DIR}/x64/Minecraft.Server/Release/Minecraft.Server.exe" ]]; then + MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Release" + else + MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Debug" + fi +fi + +if [[ "${MC_RUNTIME_DIR_INPUT}" = /* ]]; then + if [[ "${MC_RUNTIME_DIR_INPUT}" != "${SCRIPT_DIR}"/* ]]; then + echo "[error] runtime-dir must be inside repository: ${MC_RUNTIME_DIR_INPUT}" >&2 + exit 1 + fi + MC_RUNTIME_DIR_REL="${MC_RUNTIME_DIR_INPUT#${SCRIPT_DIR}/}" +else + MC_RUNTIME_DIR_REL="${MC_RUNTIME_DIR_INPUT#./}" +fi + +if [[ -z "${MC_RUNTIME_DIR_REL}" || "${MC_RUNTIME_DIR_REL}" = "." ]]; then + echo "[error] runtime-dir is invalid: ${MC_RUNTIME_DIR_INPUT}" >&2 + exit 1 +fi + +if ! RUNTIME_ABS="$(cd "${SCRIPT_DIR}" && cd "${MC_RUNTIME_DIR_REL}" 2>/dev/null && pwd)"; then + echo "[error] runtime-dir not found: ${MC_RUNTIME_DIR_INPUT}" >&2 + exit 1 +fi + +if [[ "${RUNTIME_ABS}" != "${SCRIPT_DIR}"/* ]]; then + echo "[error] runtime-dir must resolve inside repository: ${MC_RUNTIME_DIR_INPUT}" >&2 + exit 1 +fi + +MC_RUNTIME_DIR_REL="${RUNTIME_ABS#${SCRIPT_DIR}/}" + +if [[ ! -f "${RUNTIME_ABS}/Minecraft.Server.exe" ]]; then + echo "[error] Minecraft.Server.exe not found in: ${RUNTIME_ABS}" >&2 + echo "[hint] Build dedicated server first, then retry." >&2 + exit 1 +fi + +echo "[info] Using runtime (build arg): ${MC_RUNTIME_DIR_REL}" +echo "[info] Persistent data dir: ${PERSIST_DIR}" +MC_RUNTIME_DIR="${MC_RUNTIME_DIR_REL}" "${COMPOSE_CMD[@]}" -f "${COMPOSE_FILE}" up -d --build "${SERVICE_NAME}" +echo "[info] Dedicated server started." diff --git a/docker-compose.dedicated-server.ghcr.yml b/docker-compose.dedicated-server.ghcr.yml new file mode 100644 index 000000000..5a2c28c2b --- /dev/null +++ b/docker-compose.dedicated-server.ghcr.yml @@ -0,0 +1,25 @@ +services: + minecraft-lce-dedicated-server: + image: ghcr.io/kuwacom/minecraft-lce-dedicated-server:nightly-test + container_name: minecraft-lce-dedicated-server + restart: unless-stopped + tty: true + stdin_open: true + environment: + TZ: ${TZ:-Asia/Tokyo} + WINEARCH: win64 + WINEPREFIX: /var/opt/wineprefix64 + WINEDEBUG: -all + # minimum required virtual screen + XVFB_DISPLAY: ${XVFB_DISPLAY:-:99} + XVFB_SCREEN: ${XVFB_SCREEN:-720x1280x16} + volumes: + # - wineprefix64:/var/opt/wineprefix64 + - ./server-data:/srv/persist + ports: + - "25565:25565/tcp" + - "25565:25565/udp" + stop_grace_period: 30s + +# volumes: +# wineprefix64: diff --git a/docker-compose.dedicated-server.yml b/docker-compose.dedicated-server.yml index e4ec3eae9..19b6d4313 100644 --- a/docker-compose.dedicated-server.yml +++ b/docker-compose.dedicated-server.yml @@ -7,6 +7,8 @@ services: MC_RUNTIME_DIR: ${MC_RUNTIME_DIR:-x64/Minecraft.Server/Release} container_name: minecraft-lce-dedicated-server restart: unless-stopped + tty: true + stdin_open: true environment: TZ: ${TZ:-Asia/Tokyo} WINEARCH: win64 diff --git a/start-dedicated-server.sh b/start-dedicated-server.sh index d7d7d5012..8169601c2 100644 --- a/start-dedicated-server.sh +++ b/start-dedicated-server.sh @@ -2,9 +2,9 @@ set -euo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" -COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.dedicated-server.yml" +COMPOSE_FILE="${SCRIPT_DIR}/docker-compose.dedicated-server.ghcr.yml" SERVICE_NAME="minecraft-lce-dedicated-server" -PERSIST_DIR="${SCRIPT_DIR}/mc-server-data" +PERSIST_DIR="${SCRIPT_DIR}/server-data" if [[ ! -f "${COMPOSE_FILE}" ]]; then echo "[error] docker-compose file not found: ${COMPOSE_FILE}" >&2 @@ -20,71 +20,26 @@ else exit 1 fi -# can choose between release and debug, but honestly there isn’t much use if [[ "${#}" -gt 1 ]]; then - echo "Usage: $0 [release|debug|]" >&2 + echo "Usage: $0 [--no-pull]" >&2 exit 1 fi -mkdir -p "${PERSIST_DIR}/GameHDD" -if [[ ! -f "${PERSIST_DIR}/server.properties" ]]; then - : > "${PERSIST_DIR}/server.properties" -fi - +DO_PULL=1 if [[ "${#}" -eq 1 ]]; then - case "${1}" in - release) - MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Release" - ;; - debug) - MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Debug" - ;; - *) - MC_RUNTIME_DIR_INPUT="${1}" - ;; - esac -else - if [[ -f "${SCRIPT_DIR}/x64/Minecraft.Server/Release/Minecraft.Server.exe" ]]; then - MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Release" + if [[ "${1}" == "--no-pull" ]]; then + DO_PULL=0 else - MC_RUNTIME_DIR_INPUT="x64/Minecraft.Server/Debug" - fi -fi - -if [[ "${MC_RUNTIME_DIR_INPUT}" = /* ]]; then - if [[ "${MC_RUNTIME_DIR_INPUT}" != "${SCRIPT_DIR}"/* ]]; then - echo "[error] runtime-dir must be inside repository: ${MC_RUNTIME_DIR_INPUT}" >&2 + echo "Usage: $0 [--no-pull]" >&2 exit 1 fi - MC_RUNTIME_DIR_REL="${MC_RUNTIME_DIR_INPUT#${SCRIPT_DIR}/}" -else - MC_RUNTIME_DIR_REL="${MC_RUNTIME_DIR_INPUT#./}" fi -if [[ -z "${MC_RUNTIME_DIR_REL}" || "${MC_RUNTIME_DIR_REL}" = "." ]]; then - echo "[error] runtime-dir is invalid: ${MC_RUNTIME_DIR_INPUT}" >&2 - exit 1 +if [[ "${DO_PULL}" -eq 1 ]]; then + echo "[info] Pulling latest image from GHCR..." + "${COMPOSE_CMD[@]}" -f "${COMPOSE_FILE}" pull "${SERVICE_NAME}" fi -if ! RUNTIME_ABS="$(cd "${SCRIPT_DIR}" && cd "${MC_RUNTIME_DIR_REL}" 2>/dev/null && pwd)"; then - echo "[error] runtime-dir not found: ${MC_RUNTIME_DIR_INPUT}" >&2 - exit 1 -fi - -if [[ "${RUNTIME_ABS}" != "${SCRIPT_DIR}"/* ]]; then - echo "[error] runtime-dir must resolve inside repository: ${MC_RUNTIME_DIR_INPUT}" >&2 - exit 1 -fi - -MC_RUNTIME_DIR_REL="${RUNTIME_ABS#${SCRIPT_DIR}/}" - -if [[ ! -f "${RUNTIME_ABS}/Minecraft.Server.exe" ]]; then - echo "[error] Minecraft.Server.exe not found in: ${RUNTIME_ABS}" >&2 - echo "[hint] Build dedicated server first, then retry." >&2 - exit 1 -fi - -echo "[info] Using runtime (build arg): ${MC_RUNTIME_DIR_REL}" -echo "[info] Persistent data dir: ${PERSIST_DIR}" -MC_RUNTIME_DIR="${MC_RUNTIME_DIR_REL}" "${COMPOSE_CMD[@]}" -f "${COMPOSE_FILE}" up -d --build "${SERVICE_NAME}" +echo "[info] Starting dedicated server..." +"${COMPOSE_CMD[@]}" -f "${COMPOSE_FILE}" up -d "${SERVICE_NAME}" echo "[info] Dedicated server started."