Compare commits

..

16 Commits

Author SHA1 Message Date
Geoff Bourne 737a9879f7 Add github workflow to label issues/prs authored by sponsor (#4120) 2026-06-21 14:59:06 -05:00
renovate[bot] 8b5f7ed771 Update dependency itzg/mc-image-helper to v1.61.1 (#4118) 2026-06-20 17:53:37 -05:00
Geoff Bourne d20cd2dfe1 Add jattach utility (#4114) 2026-06-17 21:26:48 -05:00
renovate[bot] b67d88f713 Update dependency itzg/restify to v1.7.16 (#4112) 2026-06-16 07:54:05 -05:00
James Wagner 0dce4ed863 Added: STOP_SERVER_DELAY_COMMAND (#4109) 2026-06-16 07:22:32 -05:00
renovate[bot] 85170775fd Update dependency itzg/mc-image-helper to v1.61.0 (#4111) 2026-06-16 06:59:00 -05:00
renovate[bot] 11a78f5070 Update dependency itzg/mc-server-runner to v1.15.0 (#4110) 2026-06-15 19:15:21 -05:00
renovate[bot] 56179b56f5 Update dependency itzg/easy-add to v0.8.14 (#4105) 2026-06-14 22:31:00 -05:00
renovate[bot] cfa58bb78c Update dependency itzg/mc-monitor to v0.16.7 (#4106) 2026-06-14 22:15:36 -05:00
renovate[bot] 6094348d8f Update dependency itzg/restify to v1.7.15 (#4108) 2026-06-14 21:57:05 -05:00
renovate[bot] ab018d75a0 Update dependency itzg/mc-server-runner to v1.14.8 (#4107) 2026-06-14 21:07:08 -05:00
renovate[bot] 1a8844cb62 Update dependency itzg/rcon-cli to v1.7.6 (#4103) 2026-06-13 07:12:28 -05:00
Leon Kampwerth 2433473015 Improve get gtnh download path (#4101) 2026-06-12 07:14:52 -05:00
renovate[bot] 4495d9f8a7 Update dependency itzg/mc-image-helper to v1.60.2 (#4102) 2026-06-12 06:57:25 -05:00
Echo Nar 56c4c95606 examples: podman quadlet example (#4099) 2026-06-10 07:17:02 -05:00
dependabot[bot] 47efe3e4bb build(deps): bump the patches group in /docs with 2 updates (#4100) 2026-06-10 07:14:40 -05:00
18 changed files with 260 additions and 93 deletions
+23
View File
@@ -0,0 +1,23 @@
name: Label Sponsor Contributions
on:
issues:
types:
- opened
pull_request_target:
types:
- opened
jobs:
label-sponsor:
runs-on: ubuntu-latest
permissions:
pull-requests: write
issues: write
steps:
- name: Check if sponsor
uses: JasonEtco/is-sponsor-label-action@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
label: sponsor
+35
View File
@@ -0,0 +1,35 @@
name: Verify Docs
on:
pull_request:
paths:
- 'docs/**'
- 'zensical.toml'
- '.github/workflows/verify-docs.yml'
workflow_dispatch:
jobs:
verify:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build docs image
uses: docker/build-push-action@v6
with:
context: .
file: docs/Dockerfile
load: true
tags: docs-verifier:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Verify rendering
run: |
docker run --rm \
-v ${{ github.workspace }}:/docs \
docs-verifier:latest build --strict
+6 -6
View File
@@ -26,36 +26,36 @@ ARG APPS_REV=1
ARG GITHUB_BASEURL=https://github.com ARG GITHUB_BASEURL=https://github.com
# renovate: datasource=github-releases packageName=itzg/easy-add # renovate: datasource=github-releases packageName=itzg/easy-add
ARG EASY_ADD_VERSION=0.8.13 ARG EASY_ADD_VERSION=0.8.14
ADD ${GITHUB_BASEURL}/itzg/easy-add/releases/download/${EASY_ADD_VERSION}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add ADD ${GITHUB_BASEURL}/itzg/easy-add/releases/download/${EASY_ADD_VERSION}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add
RUN chmod +x /usr/bin/easy-add RUN chmod +x /usr/bin/easy-add
# renovate: datasource=github-releases packageName=itzg/restify # renovate: datasource=github-releases packageName=itzg/restify
ARG RESTIFY_VERSION=1.7.14 ARG RESTIFY_VERSION=1.7.16
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${RESTIFY_VERSION} --var app=restify --file {{.app}} \ --var version=${RESTIFY_VERSION} --var app=restify --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/rcon-cli # renovate: datasource=github-releases packageName=itzg/rcon-cli
ARG RCON_CLI_VERSION=1.7.5 ARG RCON_CLI_VERSION=1.7.6
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${RCON_CLI_VERSION} --var app=rcon-cli --file {{.app}} \ --var version=${RCON_CLI_VERSION} --var app=rcon-cli --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/mc-monitor # renovate: datasource=github-releases packageName=itzg/mc-monitor
ARG MC_MONITOR_VERSION=0.16.6 ARG MC_MONITOR_VERSION=0.16.7
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${MC_MONITOR_VERSION} --var app=mc-monitor --file {{.app}} \ --var version=${MC_MONITOR_VERSION} --var app=mc-monitor --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/mc-server-runner # renovate: datasource=github-releases packageName=itzg/mc-server-runner
ARG MC_SERVER_RUNNER_VERSION=1.14.7 ARG MC_SERVER_RUNNER_VERSION=1.15.0
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
--var version=${MC_SERVER_RUNNER_VERSION} --var app=mc-server-runner --file {{.app}} \ --var version=${MC_SERVER_RUNNER_VERSION} --var app=mc-server-runner --file {{.app}} \
--from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz --from ${GITHUB_BASEURL}/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
# renovate: datasource=github-releases packageName=itzg/mc-image-helper versioning=loose # renovate: datasource=github-releases packageName=itzg/mc-image-helper versioning=loose
ARG MC_HELPER_VERSION=1.60.1 ARG MC_HELPER_VERSION=1.61.1
ARG MC_HELPER_BASE_URL=${GITHUB_BASEURL}/itzg/mc-image-helper/releases/download/${MC_HELPER_VERSION} ARG MC_HELPER_BASE_URL=${GITHUB_BASEURL}/itzg/mc-image-helper/releases/download/${MC_HELPER_VERSION}
# used for cache busting local copy of mc-image-helper # used for cache busting local copy of mc-image-helper
ARG MC_HELPER_REV=1 ARG MC_HELPER_REV=1
+1
View File
@@ -33,6 +33,7 @@ apk add --no-cache -U \
libwebp \ libwebp \
libcap \ libcap \
numactl \ numactl \
jattach \
${EXTRA_ALPINE_PACKAGES} ${EXTRA_ALPINE_PACKAGES}
# Download and install patched knockd # Download and install patched knockd
+1
View File
@@ -30,6 +30,7 @@ apt-get install -y \
libpcap0.8 \ libpcap0.8 \
libnuma1 \ libnuma1 \
libcap2-bin \ libcap2-bin \
jattach \
${EXTRA_DEB_PACKAGES} ${EXTRA_DEB_PACKAGES}
# Clean up APT when done # Clean up APT when done
+2
View File
@@ -50,6 +50,8 @@ If this behavior interferes with the log content, then disable TTY or remove the
To allow time for players to finish what they're doing during a graceful server shutdown, set `STOP_SERVER_ANNOUNCE_DELAY` to a number of seconds to delay after an announcement is posted by the server. To allow time for players to finish what they're doing during a graceful server shutdown, set `STOP_SERVER_ANNOUNCE_DELAY` to a number of seconds to delay after an announcement is posted by the server.
To set a custom command to run at the start of this delay period, set `STOP_SERVER_DELAY_COMMAND` to the full command. This will run in place of the announcement.
!!! warning "Increase stop grace period" !!! warning "Increase stop grace period"
The Docker stop grace period must be increased to a value longer than the announce delay. The value to use that is longer than announce delay will vary based upon the amount of time it takes for final world data saving. If the container exits with exit code 137, then that indicates a longer grace period is needed. The Docker stop grace period must be increased to a value longer than the announce delay. The value to use that is longer than announce delay will vary based upon the amount of time it takes for final world data saving. If the container exits with exit code 137, then that indicates a longer grace period is needed.
+16
View File
@@ -36,3 +36,19 @@ The labels that are most interesting are:
- `org.opencontainers.image.created` : the date/time the image was built - `org.opencontainers.image.created` : the date/time the image was built
- `org.opencontainers.image.revision` : which maps to <https://github.com/itzg/docker-minecraft-server/commit/REVISION> - `org.opencontainers.image.revision` : which maps to <https://github.com/itzg/docker-minecraft-server/commit/REVISION>
- `org.opencontainers.image.version` : image tag and variant [as described in this page](../versions/java.md) - `org.opencontainers.image.version` : image tag and variant [as described in this page](../versions/java.md)
## jattach
This image bundles the [jattach](https://github.com/jattach/jattach) utility for attaching to running Java processes. It is described as
> The utility to send commands to a JVM process via Dynamic Attach mechanism.
>
> All-in-one jmap + jstack + jcmd + jinfo functionality in a single tiny program.
When exec'ed interactively into the container, jattach can be invoked against the Minecraft server's java process by using commands similar to the following
!!! example
```shell
jattach $(pgrep java) threaddump
```
+2 -2
View File
@@ -11,7 +11,7 @@ mkdocs==1.6.1
mkdocs-autorefs==1.4.4 mkdocs-autorefs==1.4.4
mkdocs-get-deps==0.2.2 mkdocs-get-deps==0.2.2
mkdocstrings==1.0.4 mkdocstrings==1.0.4
mkdocstrings-python==2.0.3 mkdocstrings-python==2.0.4
packaging==26.2 packaging==26.2
pathspec==1.1.1 pathspec==1.1.1
platformdirs==4.10.0 platformdirs==4.10.0
@@ -22,4 +22,4 @@ PyYAML==6.0.3
pyyaml_env_tag==1.1 pyyaml_env_tag==1.1
six==1.17.0 six==1.17.0
watchdog==6.0.0 watchdog==6.0.0
zensical==0.0.43 zensical==0.0.45
+2 -2
View File
@@ -6,7 +6,7 @@ The container can host an SSH console. It is enabled by setting `ENABLE_SSH` to
The SSH server only supports password based authentication. The password is the same as the RCON password. The SSH server only supports password based authentication. The password is the same as the RCON password.
!!! question !!! question
See [the RCON password](../configuration/server-properties.md/#rcon-password) section under configuration/server-properties for more information on how to set an RCON password. See [the RCON password](../configuration/server-properties.md#rcon-password) section under configuration/server-properties for more information on how to set an RCON password.
The SSH server runs on port `2222` inside the container. The SSH server runs on port `2222` inside the container.
@@ -15,7 +15,7 @@ The SSH server runs on port `2222` inside the container.
!!! warning "Security Implications" !!! warning "Security Implications"
By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the SSH console accessible to any device that can reach your host machine. By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the SSH console accessible to any device that can reach your host machine.
Since the SSH console grants **full administrative access** to your server, it is critical to use a strong [RCON password](../configuration/server-properties.md/#rcon-password). Since the SSH console grants **full administrative access** to your server, it is critical to use a strong [RCON password](../configuration/server-properties.md#rcon-password).
If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing/#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:2222:2222`). If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing/#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:2222:2222`).
+2 -2
View File
@@ -26,9 +26,9 @@ When a connection is established, the last 50 (by default, configurable with `WE
!!! warning "Security Implications" !!! warning "Security Implications"
By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the WebSocket console accessible to any device that can reach your host machine. By default, publishing ports in Docker binds them to all network interfaces (`0.0.0.0`), making the WebSocket console accessible to any device that can reach your host machine.
Since the WebSocket console grants **full administrative access** to your server, it is critical to use a strong [WebSocket password](#password) or [RCON password](../configuration/server-properties.md/#rcon-password). Since the WebSocket console grants **full administrative access** to your server, it is critical to use a strong [WebSocket password](#password) or [RCON password](../configuration/server-properties.md#rcon-password).
If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing/#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:80:80`). If you wish to restrict access to the local machine only, refer to the [Docker documentation](https://docs.docker.com/engine/network/port-publishing#publishing-ports) on binding to specific IP addresses (e.g., `127.0.0.1:80:80`).
If WebSocket access is only intended for inter-container connections, consider **NOT** forwarding the port to the host machine, and putting the containers in a shared [Docker network](https://docs.docker.com/engine/network/#user-defined-networks). If WebSocket access is only intended for inter-container connections, consider **NOT** forwarding the port to the host machine, and putting the containers in a shared [Docker network](https://docs.docker.com/engine/network/#user-defined-networks).
+6
View File
@@ -246,6 +246,12 @@ alternatively, you can mount: <code>/etc/localtime:/etc/localtime:ro
<td><code></code></td> <td><code></code></td>
<td>⬜️</td> <td>⬜️</td>
</tr> </tr>
<tr>
<td><code>STOP_SERVER_DELAY_COMMAND</code></td>
<td>To set a custom command to run at the start of this delay period, set <code>STOP_SERVER_DELAY_COMMAND</code> to the full command. This will run in place of the announcement.</td>
<td><code></code></td>
<td>⬜️</td>
</tr>
<tr> <tr>
<td><code>PROXY</code></td> <td><code>PROXY</code></td>
<td>You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL</td> <td>You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL</td>
+45
View File
@@ -0,0 +1,45 @@
# Podman Quadlet Example
This example demonstrates how to deploy multiple autoscaling minecraft servers behind mc-router with [podman quadlets](https://docs.podman.io/en/stable/markdown/podman-systemd.unit.5.html).
The commands listed below assume rootless podman but can easily be modified for rootful.
## mc-router.host label
In `mc@.container`, replace `example.com` with your domain.
## Server instance configuration
Each server instance requries an environment file with a matching name in the mc folder; e.g. instance `example` uses `mc/example.env`.[^1]
## Container auto-removal fix
Once the quadlets files are installed and daemon-reloaded, the generated service file needs to be edited due to generated quadlets always adding `--rm`.[^2]
To fix this, run `systemctl --user edit mc@.service` and replace the `ExecStart` entry with a copy that substitues `--restart=unless-stopped` where `--rm` is.
The drop-in should look something like this:
```ini
[Service]
ExecStart=
ExecStart=/usr/bin/podman run --name %p-%i --replace --restart=unless-stopped ...
```
## Start containers/services
```sh
systemctl --user enable --now podman.socket
systemctl --user start mc@example.service mc-router.service
# instances are enabled by symlinking from the template
ln -s ${XDG_CONFIG_HOME}/containers/systemd/mc@.service ${XDG_CONFIG_HOME}/containers/systemd/mc@example.service
```
## Rootless notes
If running rootless, be sure to enable lingering with `sudo loginctl enable-linger $USER`.
Also note that source IPs are currently lost due to how rootless podman handles custom networks.
This should be fixed in a future podman release.[^3]
[^1]: The base config is a [template file](https://docs.podman.io/en/stable/markdown/podman-systemd.unit.5.html#template-files) with instance names after the @ sign .
[^2]: <https://github.com/podman-container-tools/podman/discussions/28837>
[^3]: <https://github.com/podman-container-tools/podman/pull/28478>
@@ -0,0 +1,24 @@
[Unit]
Description=Minecraft proxy with autoscaling support
[Container]
Image=docker.io/itzg/mc-router
ContainerName=%N
AutoUpdate=registry
UserNS=host
Volume=%t/podman/podman.sock:/var/run/docker.sock:ro
Network=minecraft.network
PublishPort=25565:25565
SecurityLabelDisable=true
Environment=\
"IN_DOCKER=true" \
"AUTO_SCALE_DOWN=true" \
"AUTO_SCALE_UP=true" \
"AUTO_SCALE_DOWN_AFTER=10m" \
"AUTO_SCALE_ASLEEP_MOTD='Server is asleep. Join again to wake it up!'"
[Service]
Restart=always
[Install]
WantedBy=default.target
+9
View File
@@ -0,0 +1,9 @@
# General options
INIT_MEMORY=1G
MAX_MEMORY=4G
# Server options
EULA=TRUE
VIEW_DISTANCE=16
DIFFICULTY=normal
MOTD=Example Server!\nRunning version %VERSION%
+26
View File
@@ -0,0 +1,26 @@
[Unit]
Description=Minecraft server instance
Before=mc-router.service
[Container]
Image=docker.io/itzg/minecraft-server
ContainerName=%p-%i
AutoUpdate=registry
UserNS=auto
Volume=%p-%i:/data:Z,U
Network=minecraft.network
PodmanArgs=--tty --interactive
HealthCmd="/usr/local/bin/mc-health"
HealthInterval=10s
HealthRetries=20
HealthStartPeriod=1m
HealthTimeout=10s
Label=mc-router.host=%p-%i.example.com
EnvironmentFile=./mc/%i.env
[Service]
Restart=on-abnormal
RemainAfterExit=yes
[Install]
WantedBy=default.target
@@ -0,0 +1,2 @@
[Network]
Driver=bridge
+48 -74
View File
@@ -6,87 +6,61 @@
# Define setup functions # Define setup functions
function getGTNHdownloadPath(){ function getGTNHdownloadPath(){
gtnh_download_path="" gtnh_download_path=""
current_java_version=$(mc-image-helper java-release) local release_object=""
local current_java_version=$(mc-image-helper java-release)
# Select release JSON object
if [ "$GTNH_PACK_VERSION" == "latest-dev" ]; then
if ! release_object="$(
curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
| jq -r '.versions|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Beta release"))|.[-1]'
)"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
exit 1
fi
log "Selected $(jq '.key' <<< "$release_object") as latest dev version for download."
elif [ "$GTNH_PACK_VERSION" == "latest" ]; then
if ! release_object="$(
curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
| jq -r '.versions|to_entries|sort_by(.value.releaseDate)|map(select(.value.title=="Stable release"))|.[-1]'
)"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
exit 1
fi
log "Selected $(jq '.key' <<< "$release_object") as latest version for download."
else
if ! release_object="$(
curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
| jq -r --arg USRIN $GTNH_PACK_VERSION '.versions|to_entries|sort_by(.value.releaseDate)|map(select(.key==$USRIN))|.[]'
)"; then logError "Failed to retrieve release from https://downloads.gtnewhorizons.com/versions.json"
exit 1
fi
log "Selected $(jq -r '.key' <<< "$release_object") as matching version for download."
if ! packs_data="$(
curl -fsSL "https://downloads.gtnewhorizons.com/versions.json" \
| jq -r '.versions[]?.server? | .[]? | select(type=="string" and test("Server"))'
)"; then
logError "Failed to retrieve data from https://downloads.gtnewhorizons.com/versions.json"
exit 1
fi fi
mapfile -t packs <<< "$packs_data"
log "Start locating server files..." # Select compatible server files for java version
for pack in "${packs[@]}"; do if (( current_java_version == 8 )); then
# Extract the Java version(s) from the pack filename gtnh_download_path=$(jq -r '.value.server.java8Url' <<< "$release_object")
if ! pack_java_version=$(basename "$pack" | grep -Eo 'Java_[0-9]+(-[0-9]+)?' | sed 's/Java_//'); then log "Use GTNH Server Java 8 release."
logWarning "Could not parse java version of $pack"
elif (( current_java_version >= 17 )); then
if (( current_java_version > $(jq '.value.maxJavaVersion' <<< "$release_object") )); then
logError "Container Java version $current_java_version is not supported by GTNH. Try an older release."
exit 1
fi fi
# Skip the pack if the current Java version is not compatible gtnh_download_path=$(jq -r '.value.server.java17_2XUrl' <<< "$release_object")
if [[ "$pack_java_version" == *-* ]]; then log "Use GTNH Server Java 17+ release."
# Handle range of Java versions (e.g., "17-21")
java_min_version=$(echo "$pack_java_version" | cut -d'-' -f1)
java_max_version=$(echo "$pack_java_version" | cut -d'-' -f2)
if (( current_java_version < java_min_version || current_java_version > java_max_version )); then
debug "Skipping $pack due to incompatible Java version: $current_java_version not in range $java_min_version-$java_max_version"
continue
fi
else
# Handle single Java version (e.g., "8")
if (( current_java_version != pack_java_version )); then
debug "Skipping $pack due to incompatible Java version: $current_java_version != $pack_java_version"
continue
fi
fi
# Extract version numbers and release type (beta or RC) from the file names else
logError "Container Java version $current_java_version is not supported by GTNH."
exit 1
if ! pack_version=$(basename "$pack" | grep -Eo '[0-9]+(\.[0-9]+)+'); then fi
logWarning "Could not parse version of $pack"
fi debug "Download source URL: $gtnh_download_path"
if ! pack_release_type=$(basename "$pack" | grep -Eo '(beta|RC)(-[0-9]+)?' || echo ""); then
logWarning "Could not parse release type of $pack"
fi
if ! current_version=$(basename "$gtnh_download_path" | grep -Eo '[0-9]+(\.[0-9]+)+'); then
debug "Could not parse version of selected download path. String might be empty."
fi
if ! current_release_type=$(basename "$gtnh_download_path" | grep -Eo '(beta|RC)(-[0-9]+)?' || echo ""); then
debug "Could not parse release type of selected download path. String might be empty."
fi
# Check if the pack matches the desired type based on GTNH_PACK_VERSION:
# - If GTNH_PACK_VERSION is "latest-dev", only consider beta packs (path contains "/betas/").
# - If GTNH_PACK_VERSION is "latest", only consider non-beta packs (path does not contain "/betas/").
if [[ ($pack == *"/betas/"* && $GTNH_PACK_VERSION == "latest-dev") || ($pack != *"/betas/"* && $GTNH_PACK_VERSION == "latest") ]]; then
# Compare versions and update gtnh_download_path if pack is newer
# Check if the current version is unset or if the pack version is newer than the current version.
# This comparison uses version sorting to determine the latest version.
if [[ -z "$current_version" || "$(printf '%s\n' "$pack_version" "$current_version" | sort -V | tail -n 1)" == "$pack_version" ]]; then
# If the pack version is the same as the current version, prioritize based on release type.
# Full versions are preferred over RC (Release Candidate), and RC is preferred over beta.
# Within the same release type, higher numbered versions are preferred.
if [[ "$pack_version" == "$current_version" ]]; then
if [[ -z "$pack_release_type" || ("$pack_release_type" == "RC" && "$current_release_type" == "beta") ||
("$pack_release_type" == "$current_release_type" && "$(printf '%s\n' "$pack_release_type" "$current_release_type" | sort -V | tail -n 1)" == "$pack_release_type") ]]; then
debug "$current_version-$current_release_type is older than $pack_version-$pack_release_type! Update latest version to: $pack_version-$pack_release_type"
gtnh_download_path="$pack"
fi
else
# If the pack version is newer than the current version, set it as the download path.
debug "$current_version is older than $pack_version! Update latest version to: $pack_version"
gtnh_download_path="$pack"
fi
fi
else
if [[ "$pack_version" == "$GTNH_PACK_VERSION" || "$pack_version-$pack_release_type" == "$GTNH_PACK_VERSION" ]]; then
log "Found exact match $pack_version = $GTNH_PACK_VERSION! Select $pack_version for download."
gtnh_download_path="$pack"
break
fi
fi
done
} }
function deleteGTNHbackup(){ function deleteGTNHbackup(){
@@ -104,7 +78,7 @@ function updateGTNH(){
folders_to_update=("libraries" "mods" "resources" "scripts") folders_to_update=("libraries" "mods" "resources" "scripts")
files_to_update=("lwjgl3ify-forgePatches.jar" "java9args.txt" "startserver-java9.bat" "startserver-java9.sh" "forge-1.7.10-10.13.4.1614-1.7.10-universal.jar" "startserver.bat" "startserver.sh" "server-icon.png") files_to_update=("lwjgl3ify-forgePatches.jar" "java9args.txt" "startserver-java9.bat" "startserver-java9.sh" "forge-1.7.10-10.13.4.1614-1.7.10-universal.jar" "startserver.bat" "startserver.sh" "server-icon.png")
config_folder="config" config_folder="config"
backup_folder="/data/gtnh-upgrade-${current_version}${current_release_type:+-$current_release_type}-$current_datetime" backup_folder="/data/gtnh-upgrade-$current_datetime"
journey_map_folder="JourneyMapServer" journey_map_folder="JourneyMapServer"
# Delete specified folders if they exist # Delete specified folders if they exist
+3
View File
@@ -481,6 +481,9 @@ fi
if [[ ${STOP_SERVER_ANNOUNCE_DELAY} ]]; then if [[ ${STOP_SERVER_ANNOUNCE_DELAY} ]]; then
mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s") mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s")
fi fi
if [[ ${STOP_SERVER_DELAY_COMMAND} ]]; then
mcServerRunnerArgs+=(--stop-server-delay-command "${STOP_SERVER_DELAY_COMMAND}s")
fi
if isTrue "${ENABLE_SSH}"; then if isTrue "${ENABLE_SSH}"; then
mcServerRunnerArgs+=(--remote-console) mcServerRunnerArgs+=(--remote-console)
fi fi