mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-02-17 15:13:55 +00:00
Compare commits
102 Commits
java8
...
2021.23.1-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adde46bc73 | ||
|
|
6510a6f361 | ||
|
|
9204e06b63 | ||
|
|
95b5088c3b | ||
|
|
2c106575f0 | ||
|
|
234d70786e | ||
|
|
7cf7193ef4 | ||
|
|
1d923a5878 | ||
|
|
34125769fa | ||
|
|
c6124bdd01 | ||
|
|
9f0edde0b3 | ||
|
|
1d97fccfdf | ||
|
|
5ad85de964 | ||
|
|
c273e99007 | ||
|
|
72ea47148a | ||
|
|
25782fc63e | ||
|
|
283b5ba431 | ||
|
|
5933fffcca | ||
|
|
de5b7cb601 | ||
|
|
c836e29ac3 | ||
|
|
d9214f0204 | ||
|
|
a7efcfff49 | ||
|
|
618d6236ba | ||
|
|
929eeeedfc | ||
|
|
6494ca8864 | ||
|
|
d964231906 | ||
|
|
1d8c28e024 | ||
|
|
d63c570cf3 | ||
|
|
f7f1855e24 | ||
|
|
8ccf0201a8 | ||
|
|
fa9e59edd8 | ||
|
|
25a2ab6ff3 | ||
|
|
bb780c000d | ||
|
|
cb4691a9ac | ||
|
|
76b8b89295 | ||
|
|
551e4d6346 | ||
|
|
61a660ee48 | ||
|
|
5e9806736c | ||
|
|
d5865cd60c | ||
|
|
2b0b8f8a62 | ||
|
|
e94b40bddf | ||
|
|
2dabf34349 | ||
|
|
eb864c0fb8 | ||
|
|
2e0f469748 | ||
|
|
aa95dc291b | ||
|
|
d22280fae7 | ||
|
|
aac3c1c77a | ||
|
|
61b0eff4ca | ||
|
|
8c5f0a53bf | ||
|
|
fffeb7bb9c | ||
|
|
a060cc88d1 | ||
|
|
4421aaa22d | ||
|
|
3a51db6d24 | ||
|
|
969a23ae27 | ||
|
|
1a62592fe2 | ||
|
|
c316dbb5d2 | ||
|
|
bb64135c9b | ||
|
|
ef98de154c | ||
|
|
3d00077ef8 | ||
|
|
0d3ab75683 | ||
|
|
87681e64bb | ||
|
|
8ce986d3d7 | ||
|
|
67fda61de4 | ||
|
|
7c6ec41822 | ||
|
|
93af2025a2 | ||
|
|
c1b040af77 | ||
|
|
4148325787 | ||
|
|
7083cd15e8 | ||
|
|
7418dab476 | ||
|
|
94bbc8e649 | ||
|
|
3e5e62229a | ||
|
|
fe2a9d56ed | ||
|
|
27571999b2 | ||
|
|
bbd7d9e39a | ||
|
|
ef6f308229 | ||
|
|
49d89d3e73 | ||
|
|
74203b23f4 | ||
|
|
4fb791b490 | ||
|
|
ced25ad50a | ||
|
|
48efc224ba | ||
|
|
467c1d9954 | ||
|
|
9ced230f55 | ||
|
|
f3a8276362 | ||
|
|
b91d63716e | ||
|
|
46cccfd531 | ||
|
|
9fe1cb4a0d | ||
|
|
076038b470 | ||
|
|
aa416729ea | ||
|
|
812c6365ec | ||
|
|
42a5131b19 | ||
|
|
624f6a210f | ||
|
|
1c63cd18b7 | ||
|
|
6266a7e3cc | ||
|
|
871ecd4d9d | ||
|
|
c572c95161 | ||
|
|
f7b58fbbb1 | ||
|
|
eccfa444a9 | ||
|
|
e831d25706 | ||
|
|
12e931332b | ||
|
|
ceee9eddc9 | ||
|
|
60ba668743 | ||
|
|
fd1b15e01f |
4
.github/release.yml
vendored
4
.github/release.yml
vendored
@@ -1,4 +0,0 @@
|
||||
changelog:
|
||||
exclude:
|
||||
authors:
|
||||
- dependabot
|
||||
98
.github/workflows/build-multiarch.yml
vendored
98
.github/workflows/build-multiarch.yml
vendored
@@ -3,60 +3,30 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- test/**
|
||||
- java8-multiarch
|
||||
- java8-openj9
|
||||
- java11*
|
||||
- java16*
|
||||
- java17*
|
||||
- test/*
|
||||
- fix/*
|
||||
tags:
|
||||
- "[0-9]+.[0-9]+.[0-9]+"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-java8-multiarch"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-java8-openj9"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-java11*"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-java16*"
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
- "docs/**"
|
||||
- "examples/**"
|
||||
|
||||
env:
|
||||
IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
if: github.repository == 'itzg/docker-minecraft-server'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
variant:
|
||||
- java17
|
||||
- java17-openj9
|
||||
- java8-multiarch
|
||||
- java8-openj9
|
||||
- java11
|
||||
- java11-openj9
|
||||
include:
|
||||
- variant: java17
|
||||
baseImage: eclipse-temurin:17
|
||||
tagPrefix: java17-
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
mcVersion: LATEST
|
||||
- variant: java17-openj9
|
||||
baseImage: ibm-semeru-runtimes:open-17-jdk
|
||||
tagPrefix: java17-openj9-
|
||||
platforms: linux/amd64,linux/arm64
|
||||
mcVersion: LATEST
|
||||
- variant: java8-multiarch
|
||||
baseImage: eclipse-temurin:8-jdk
|
||||
tagPrefix: java8-
|
||||
platforms: linux/amd64,linux/arm64
|
||||
mcVersion: 1.12.2
|
||||
- variant: java8-openj9
|
||||
baseImage: ibm-semeru-runtimes:open-8-jdk
|
||||
tagPrefix: java8-openj9-
|
||||
platforms: linux/amd64,linux/arm64
|
||||
mcVersion: 1.12.2
|
||||
- variant: java11
|
||||
baseImage: adoptopenjdk:11-jdk-hotspot
|
||||
tagPrefix: java11-
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
mcVersion: 1.16.5
|
||||
- variant: java11-openj9
|
||||
baseImage: ibm-semeru-runtimes:open-11-jdk
|
||||
tagPrefix: java11-openj9-
|
||||
platforms: linux/amd64,linux/arm64
|
||||
mcVersion: 1.16.5
|
||||
env:
|
||||
IMAGE_TO_TEST: itzg/minecraft-server:test-${{ matrix.variant }}-${{ github.run_id }}
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
@@ -69,13 +39,10 @@ jobs:
|
||||
images: |
|
||||
itzg/minecraft-server
|
||||
tags: |
|
||||
type=ref,event=tag,enable=${{ matrix.variant == 'java17' }}
|
||||
type=ref,event=tag,suffix=-${{ matrix.variant }}
|
||||
type=raw,value=${{ matrix.variant }}
|
||||
type=ref,event=branch
|
||||
type=ref,event=tag
|
||||
flavor: |
|
||||
latest=${{ matrix.variant == 'java17' }}
|
||||
labels: |
|
||||
org.opencontainers.image.authors=Geoff Bourne <itzgeoff@gmail.com>
|
||||
latest=${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
@@ -90,37 +57,38 @@ jobs:
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build for test
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.7.0
|
||||
if: github.ref_name == 'master'
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
tags: ${{ env.IMAGE_TO_TEST }}
|
||||
# ensure latest base image is used
|
||||
pull: true
|
||||
# load into daemon for test usage in next step
|
||||
load: true
|
||||
push: false
|
||||
build-args: |
|
||||
BASE_IMAGE=${{ matrix.baseImage }}
|
||||
cache-from: type=gha,scope=${{ matrix.variant }}
|
||||
# no cache-to to avoid cross-cache update from next build step
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
MINECRAFT_VERSION: ${{ matrix.mcVersion }}
|
||||
# It is assumed that image variants are merged from master and tested there
|
||||
if: github.ref_name == 'master'
|
||||
run: |
|
||||
tests/test.sh
|
||||
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.7.0
|
||||
with:
|
||||
platforms: ${{ matrix.platforms }}
|
||||
push: ${{ github.ref_type == 'tag' || github.ref_name == 'master' }}
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
# ensure latest base image is used
|
||||
pull: true
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
BASE_IMAGE=${{ matrix.baseImage }}
|
||||
cache-from: type=gha,scope=${{ matrix.variant }}
|
||||
cache-to: type=gha,mode=max,scope=${{ matrix.variant }}
|
||||
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
|
||||
43
.github/workflows/ci.yml
vendored
43
.github/workflows/ci.yml
vendored
@@ -1,43 +0,0 @@
|
||||
name: ContinuousIntegration
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'dev*'
|
||||
- '!master'
|
||||
- '!java*'
|
||||
- '!multi*'
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
- "docs/**"
|
||||
- "examples/**"
|
||||
|
||||
env:
|
||||
IMAGE_TO_TEST: ${{ secrets.IMAGE_ORG }}/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }}
|
||||
MODS_FORGEAPI_KEY: ${{ secrets.MODS_FORGEAPI_KEY }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
tags: ${{ env.IMAGE_TO_TEST }}
|
||||
load: true
|
||||
cache-from: type=gha
|
||||
|
||||
- name: Run Setup Only Tests
|
||||
run: bash tests/setuponlytests/test.sh
|
||||
|
||||
# - name: Run Full Minecraft Service Tests
|
||||
# run: |
|
||||
# tests/fulltests/test.sh
|
||||
26
.github/workflows/discord.yml
vendored
26
.github/workflows/discord.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Discord notifications
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["ContinuousIntegration", "Build and Publish", "Build and publish multiarch" ]
|
||||
types:
|
||||
- completed
|
||||
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||
|
||||
jobs:
|
||||
discord:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: on-success
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
uses: Ilshidur/action-discord@master
|
||||
with:
|
||||
args: "Github repo: ${{ github.repository }}\n- Branch: ${{ github.event.workflow_run.head_branch }}\n- [Link: to Actions](<${{ github.event.workflow_run.html_url }}>)\n- Status: 🎉 ${{ github.event.workflow_run.conclusion }} 🍏"
|
||||
- name: on-failure
|
||||
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
|
||||
uses: Ilshidur/action-discord@master
|
||||
with:
|
||||
args: "Github repo: ${{ github.repository }}\n- Branch: ${{ github.event.workflow_run.head_branch }}\n- [Link: to Actions](<${{ github.event.workflow_run.html_url }}>)\n- Status: 🤔 ${{ github.event.workflow_run.conclusion }} 💣💥"
|
||||
2
.github/workflows/generate-toc.yml
vendored
2
.github/workflows/generate-toc.yml
vendored
@@ -16,6 +16,6 @@ jobs:
|
||||
curl https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc -o gh-md-toc
|
||||
chmod a+x gh-md-toc
|
||||
./gh-md-toc --insert --no-backup README.md
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4.13.1
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4.12.0
|
||||
with:
|
||||
commit_message: "docs: Auto update markdown TOC"
|
||||
25
.github/workflows/issue-label.yml
vendored
25
.github/workflows/issue-label.yml
vendored
@@ -1,25 +0,0 @@
|
||||
name: Issue labels
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
env:
|
||||
DISCORD_WEBHOOK: ${{ secrets.DISCORD_ISSUES_WEBHOOK }}
|
||||
|
||||
jobs:
|
||||
labelNotify:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: notify
|
||||
if: >
|
||||
github.event.label.name == 'enhancement'
|
||||
|| github.event.label.name == 'bug'
|
||||
|| github.event.label.name == 'help wanted'
|
||||
|| github.event.label.name == 'priority/high'
|
||||
|| github.event.label.name == 'question'
|
||||
|| github.event.label.name == 'status/waiting on upstream'
|
||||
uses: Ilshidur/action-discord@master
|
||||
with:
|
||||
args: "[${{ github.event.issue.title }} (#${{ github.event.issue.number }})](<${{ github.event.issue.html_url }}>) added `${{ github.event.label.name }}` label"
|
||||
15
.github/workflows/main.yml
vendored
15
.github/workflows/main.yml
vendored
@@ -4,9 +4,16 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- java8
|
||||
- openj9
|
||||
- openj9-11
|
||||
- adopt11
|
||||
- test/alpine/*
|
||||
tags:
|
||||
- "[0-9]+.[0-9]+.[0-9]+-java8"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-openj9"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-openj9-11"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-openj9-nightly"
|
||||
- "[0-9]+.[0-9]+.[0-9]+-adopt11"
|
||||
|
||||
env:
|
||||
IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }}
|
||||
@@ -46,7 +53,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Build for test
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.7.0
|
||||
if: github.ref_name == 'java8'
|
||||
with:
|
||||
context: .
|
||||
@@ -68,7 +75,7 @@ jobs:
|
||||
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.7.0
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
@@ -85,4 +92,6 @@ jobs:
|
||||
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
|
||||
org.opencontainers.image.source=https://github.com/itzg/docker-minecraft-server
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
org.opencontainers.image.authors=Geoff Bourne <itzgeoff@gmail.com>
|
||||
|
||||
- name: Image digest
|
||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||
|
||||
40
.github/workflows/pr.yml
vendored
40
.github/workflows/pr.yml
vendored
@@ -1,21 +1,15 @@
|
||||
name: PullRequest
|
||||
name: Validate PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
types: [assigned, opened, synchronize, labeled]
|
||||
paths-ignore:
|
||||
- "*.md"
|
||||
- "docs/**"
|
||||
- "examples/**"
|
||||
|
||||
env:
|
||||
IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }}
|
||||
MODS_FORGEAPI_KEY: ${{ secrets.MODS_FORGEAPI_KEY }}
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2.4.0
|
||||
@@ -24,41 +18,15 @@ jobs:
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Build
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
uses: docker/build-push-action@v2.7.0
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64
|
||||
tags: ${{ env.IMAGE_TO_TEST }}
|
||||
load: true
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
tests/test.sh
|
||||
|
||||
- name: Gather Docker metadata
|
||||
if: contains(github.event.pull_request.labels.*.name, 'ci/push-image')
|
||||
id: meta
|
||||
uses: docker/metadata-action@v3
|
||||
with:
|
||||
images: |
|
||||
itzg/minecraft-server
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: contains(github.event.pull_request.labels.*.name, 'ci/push-image')
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Push
|
||||
if: contains(github.event.pull_request.labels.*.name, 'ci/push-image')
|
||||
uses: docker/build-push-action@v2.9.0
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
pull: true
|
||||
push: true
|
||||
cache-from: type=gha
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
4
.github/workflows/stale-check.yml
vendored
4
.github/workflows/stale-check.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Process Stale Issues
|
||||
uses: actions/stale@v4.1.0
|
||||
uses: actions/stale@v4.0.0
|
||||
with:
|
||||
stale-issue-label: status/stale
|
||||
stale-pr-label: status/stale
|
||||
@@ -21,5 +21,5 @@ jobs:
|
||||
Please add a comment describing the reason to keep this issue open.
|
||||
days-before-stale: 30
|
||||
days-before-close: 5
|
||||
exempt-issue-labels: 'enhancement,keep,status/needs triage,priority/high'
|
||||
exempt-issue-labels: 'enhancement,keep,status/needs triage'
|
||||
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,5 +1,4 @@
|
||||
.vscode
|
||||
/data/
|
||||
/.idea/
|
||||
*.iml
|
||||
/gh-md-toc
|
||||
/gh-md-toc
|
||||
@@ -15,24 +15,8 @@ Individual scripts can be iteratively developed, debugged, and tested using the
|
||||
|
||||
First, build a baseline of the image to include the packages needed by existing or new scripts:
|
||||
|
||||
PowerShell:
|
||||
```powershell
|
||||
$env:IMAGE_TO_TEST="mc-dev"
|
||||
docker build -t $env:IMAGE_TO_TEST .
|
||||
pushd tests/setuponlytests/vanillatweaks_file/
|
||||
docker-compose run mc
|
||||
docker-compose down --remove-orphans
|
||||
popd
|
||||
```
|
||||
|
||||
Bash:
|
||||
```bash
|
||||
export IMAGE_TO_TEST=mc-dev
|
||||
docker build -t $IMAGE_TO_TEST .
|
||||
pushd tests/setuponlytests/vanillatweaks_file/
|
||||
docker-compose run mc
|
||||
docker-compose down --remove-orphans
|
||||
popd
|
||||
```shell script
|
||||
docker build -t mc-dev .
|
||||
```
|
||||
|
||||
Using the baseline image, an interactive container can be started to iteratively run the scripts to be developed. By attaching the current workspace directory, you can use the local editor of your choice to iteratively modify scripts while using the container to run them.
|
||||
@@ -132,4 +116,4 @@ for b in "${branches[@]}"; do
|
||||
git merge -s ours -m "Track latest from master" master
|
||||
git push origin
|
||||
done
|
||||
```
|
||||
```
|
||||
87
Dockerfile
87
Dockerfile
@@ -1,42 +1,40 @@
|
||||
ARG BASE_IMAGE=openjdk:8-jdk-alpine
|
||||
FROM ${BASE_IMAGE}
|
||||
FROM eclipse-temurin:8-jdk
|
||||
|
||||
RUN apk add --no-cache -U \
|
||||
openssl \
|
||||
LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>"
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive \
|
||||
apt-get install -y \
|
||||
imagemagick \
|
||||
file \
|
||||
lsof \
|
||||
su-exec \
|
||||
# GNU compatible 'find'
|
||||
findutils \
|
||||
shadow \
|
||||
bash \
|
||||
curl iputils \
|
||||
gosu \
|
||||
sudo \
|
||||
net-tools \
|
||||
iputils-ping \
|
||||
curl wget \
|
||||
git \
|
||||
jq \
|
||||
dos2unix \
|
||||
mysql-client \
|
||||
tzdata \
|
||||
rsync \
|
||||
nano \
|
||||
sudo \
|
||||
knock \
|
||||
unzip \
|
||||
knockd \
|
||||
ttf-dejavu \
|
||||
zstd
|
||||
&& apt-get clean
|
||||
|
||||
RUN addgroup -g 1000 minecraft \
|
||||
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
|
||||
&& mkdir -m 777 /data \
|
||||
&& chown minecraft:minecraft /data /home/minecraft
|
||||
RUN addgroup --gid 1000 minecraft \
|
||||
&& adduser --system --shell /bin/false --uid 1000 --ingroup minecraft --home /data minecraft
|
||||
|
||||
COPY --chmod=644 files/sudoers* /etc/sudoers.d
|
||||
COPY files/sudoers* /etc/sudoers.d
|
||||
|
||||
EXPOSE 25565 25575
|
||||
|
||||
# hook into docker BuildKit --platform support
|
||||
# see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
|
||||
ARG TARGETOS=linux
|
||||
ARG TARGETARCH=amd64
|
||||
ARG TARGETVARIANT=""
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
ARG TARGETVARIANT
|
||||
|
||||
ARG EASY_ADD_VER=0.7.1
|
||||
ADD https://github.com/itzg/easy-add/releases/download/${EASY_ADD_VER}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add
|
||||
@@ -47,26 +45,26 @@ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--var version=1.5.1 --var app=rcon-cli --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
--var version=1.5.1 --var app=rcon-cli --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--var version=0.10.3 --var app=mc-monitor --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
--var version=0.10.3 --var app=mc-monitor --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--var version=1.8.0 --var app=mc-server-runner --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
--var version=1.8.0 --var app=mc-server-runner --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--var version=0.1.1 --var app=maven-metadata-release --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
--var version=0.1.1 --var app=maven-metadata-release --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
ARG MC_HELPER_VERSION=1.16.5
|
||||
ARG MC_HELPER_VERSION=1.9.10
|
||||
ARG MC_HELPER_BASE_URL=https://github.com/itzg/mc-image-helper/releases/download/v${MC_HELPER_VERSION}
|
||||
RUN curl -fsSL ${MC_HELPER_BASE_URL}/mc-image-helper-${MC_HELPER_VERSION}.tgz \
|
||||
| tar -C /usr/share -zxf - \
|
||||
&& ln -s /usr/share/mc-image-helper-${MC_HELPER_VERSION}/bin/mc-image-helper /usr/bin
|
||||
| tar -C /usr/share -zxf - \
|
||||
&& ln -s /usr/share/mc-image-helper-${MC_HELPER_VERSION}/bin/mc-image-helper /usr/bin
|
||||
|
||||
VOLUME ["/data"]
|
||||
WORKDIR /data
|
||||
@@ -74,22 +72,21 @@ WORKDIR /data
|
||||
STOPSIGNAL SIGTERM
|
||||
|
||||
ENV UID=1000 GID=1000 \
|
||||
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
|
||||
MEMORY="1G" \
|
||||
TYPE=VANILLA VERSION=LATEST \
|
||||
ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
|
||||
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 \
|
||||
AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0 \
|
||||
ENABLE_AUTOSTOP=false AUTOSTOP_TIMEOUT_EST=3600 AUTOSTOP_TIMEOUT_INIT=1800 AUTOSTOP_PERIOD=10
|
||||
AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0
|
||||
|
||||
COPY --chmod=755 scripts/start* /
|
||||
COPY --chmod=755 bin/ /usr/local/bin/
|
||||
COPY --chmod=755 bin/mc-health /health.sh
|
||||
COPY --chmod=644 files/server.properties /tmp/server.properties
|
||||
COPY --chmod=644 files/log4j2.xml /tmp/log4j2.xml
|
||||
COPY --chmod=755 files/autopause /autopause
|
||||
COPY --chmod=755 files/autostop /autostop
|
||||
COPY scripts/start* /
|
||||
COPY bin/ /usr/local/bin/
|
||||
COPY bin/mc-health /health.sh
|
||||
COPY files/server.properties /tmp/server.properties
|
||||
COPY files/log4j2.xml /tmp/log4j2.xml
|
||||
COPY files/autopause /autopause
|
||||
|
||||
RUN dos2unix /start* /autopause/* /autostop/*
|
||||
RUN dos2unix /start* && chmod +x /start* \
|
||||
&& dos2unix /autopause/* && chmod +x /autopause/*.sh
|
||||
|
||||
ENTRYPOINT [ "/start" ]
|
||||
HEALTHCHECK --start-period=1m CMD mc-health
|
||||
|
||||
306
README.md
306
README.md
@@ -24,7 +24,6 @@ By default, the container will download the latest version of the "vanilla" [Min
|
||||
**TABLE OF CONTENTS**
|
||||
|
||||
<!--ts-->
|
||||
* [Mitigated Log4jShell Vulnerability](#mitigated-log4jshell-vulnerability)
|
||||
* [Looking for a Bedrock Dedicated Server](#looking-for-a-bedrock-dedicated-server)
|
||||
* [Interacting with the server](#interacting-with-the-server)
|
||||
* [Data Directory](#data-directory)
|
||||
@@ -46,7 +45,6 @@ By default, the container will download the latest version of the "vanilla" [Min
|
||||
* [Running a Bukkit/Spigot server](#running-a-bukkitspigot-server)
|
||||
* [Running a Paper server](#running-a-paper-server)
|
||||
* [Running an Airplane server](#running-an-airplane-server)
|
||||
* [Running a Pufferfish server](#running-a-pufferfish-server)
|
||||
* [Running a Purpur server](#running-a-purpur-server)
|
||||
* [Running a Magma server](#running-a-magma-server)
|
||||
* [Running a Mohist server](#running-a-mohist-server)
|
||||
@@ -68,16 +66,13 @@ By default, the container will download the latest version of the "vanilla" [Min
|
||||
* [Optional plugins, mods, and config attach points](#optional-plugins-mods-and-config-attach-points)
|
||||
* [Auto-downloading SpigotMC/Bukkit/PaperMC plugins](#auto-downloading-spigotmcbukkitpapermc-plugins)
|
||||
* [Downloadable mod/plugin pack for Forge, Fabric, and Bukkit-like Servers](#downloadable-modplugin-pack-for-forge-fabric-and-bukkit-like-servers)
|
||||
* [ForgeAPI usage to use non-version specific projects](#forgeapi-usage-to-use-non-version-specific-projects)
|
||||
* [Generic pack files](#generic-pack-files)
|
||||
* [Generic pack file](#generic-pack-file)
|
||||
* [Mod/Plugin URL Listing File](#modplugin-url-listing-file)
|
||||
* [Remove old mods/plugins](#remove-old-modsplugins)
|
||||
* [Working with world data](#working-with-world-data)
|
||||
* [Downloadable world](#downloadable-world)
|
||||
* [Cloning world from a container path](#cloning-world-from-a-container-path)
|
||||
* [Overwrite world on start](#overwrite-world-on-start)
|
||||
* [Datapacks](#datapacks)
|
||||
* [VanillaTweaks](#vanillatweaks)
|
||||
* [Server configuration](#server-configuration)
|
||||
* [Message of the Day](#message-of-the-day)
|
||||
* [Difficulty](#difficulty)
|
||||
@@ -133,23 +128,16 @@ By default, the container will download the latest version of the "vanilla" [Min
|
||||
* [Explicitly disable GUI](#explicitly-disable-gui)
|
||||
* [Stop Duration](#stop-duration)
|
||||
* [Setup only](#setup-only)
|
||||
* [Enable Flare Flags](#enable-flare-flags)
|
||||
* [Enable timestamps in init logs](#enable-timestamps-in-init-logs)
|
||||
* [Autopause](#autopause)
|
||||
* [Description](#description)
|
||||
* [Enabling Autopause](#enabling-autopause)
|
||||
* [Autostop](#autostop)
|
||||
* [Running on RaspberryPi](#running-on-raspberrypi)
|
||||
* [Contributing](#contributing)
|
||||
|
||||
<!-- Added by: runner, at: Sun Feb 6 18:45:39 UTC 2022 -->
|
||||
<!-- Added by: runner, at: Tue Dec 7 03:43:47 UTC 2021 -->
|
||||
|
||||
<!--te-->
|
||||
|
||||
## Mitigated Log4jShell Vulnerability
|
||||
|
||||
**Please ensure you have pulled the latest image** since [all official mitigations](https://www.minecraft.net/en-us/article/important-message--security-vulnerability-java-edition) are automatically applied by the container startup process.
|
||||
|
||||
## Looking for a Bedrock Dedicated Server
|
||||
|
||||
For Minecraft clients running on consoles, mobile, or native Windows, you'll need to
|
||||
@@ -245,8 +233,6 @@ If you had used the commands in the first section, without the `-v` volume attac
|
||||
|
||||
> In this example, it is assumed the original container was given a `--name` of "mc", so change the container identifier accordingly.
|
||||
|
||||
> You can also locate the Docker-managed directory from the `Source` field obtained from `docker inspect <container id or name> -f "{{json .Mounts}}"`
|
||||
|
||||
First, stop the existing container:
|
||||
```shell
|
||||
docker stop mc
|
||||
@@ -295,8 +281,8 @@ When using the image `itzg:/minecraft-server` without a tag, the `latest` image
|
||||
| java8-openj9 | 8 | Debian | OpenJ9 | amd64 |
|
||||
| java11 | 11 | Debian | Hotspot | amd64,arm64,armv7 |
|
||||
| java11-openj9 | 11 | Debian | OpenJ9 | amd64 |
|
||||
| java16-openj9 | 16 | Debian | OpenJ9 | amd64 |
|
||||
| java17 | 17 | Ubuntu | Hotspot | amd64,arm64,armv7 |
|
||||
| java17-openj9 | 17 | Debian | OpenJ9 | amd64 |
|
||||
|
||||
For example, to use Java version 8 on any supported architecture:
|
||||
|
||||
@@ -314,7 +300,7 @@ The following image tags have been deprecated and are no longer receiving update
|
||||
- adopt15
|
||||
- openj9-nightly
|
||||
- multiarch-latest
|
||||
- java16/java16-openj9
|
||||
- java16
|
||||
|
||||
## Healthcheck
|
||||
|
||||
@@ -394,7 +380,7 @@ To troubleshoot any issues with memory allocation reported by the JVM, set the e
|
||||
|
||||
### Running a Forge Server
|
||||
|
||||
Enable [Forge server](http://www.minecraftforge.net/) mode by adding a `-e TYPE=FORGE` to your command-line.
|
||||
Enable [Forge server](http://www.minecraftforge.net/wiki/) mode by adding a `-e TYPE=FORGE` to your command-line.
|
||||
|
||||
The overall version is specified by `VERSION`, [as described in the section above](#versions) and will run the recommended Forge version by default. You can also choose to run a specific Forge version with `FORGEVERSION`, such as `-e FORGEVERSION=14.23.5.2854`.
|
||||
|
||||
@@ -466,13 +452,19 @@ Plugins can either be managed within the `plugins` subdirectory of the [data dir
|
||||
|
||||
Enable Paper server mode by adding a `-e TYPE=PAPER` to your command-line.
|
||||
|
||||
By default, the container will run the latest build of [Paper server](https://papermc.io/downloads) but you can also choose to run a specific build with `-e PAPERBUILD=205`.
|
||||
By default the container will run the latest build of [Paper server](https://papermc.io/downloads)
|
||||
but you can also choose to run a specific build with `-e PAPERBUILD=205`.
|
||||
|
||||
docker run -d -v /path/on/host:/data \
|
||||
-e TYPE=PAPER \
|
||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||
|
||||
If you are hosting your own copy of Paper you can override the download URL with `PAPER_DOWNLOAD_URL=<url>`.
|
||||
If you are hosting your own copy of Paper you can override the download URL with:
|
||||
|
||||
- -e PAPER_DOWNLOAD_URL=<url>
|
||||
|
||||
An example compose file is provided at
|
||||
[examples/docker-compose-paper.yml](examples/docker-compose-paper.yml).
|
||||
|
||||
If you have attached a host directory to the `/data` volume, then you can install plugins via the `plugins` subdirectory. You can also [attach a `/plugins` volume](#optional-plugins-mods-and-config-attach-points). If you add plugins while the container is running, you'll need to restart it to pick those up.
|
||||
|
||||
@@ -484,24 +476,12 @@ An [Airplane](https://airplane.gg) server, which is "a stable, optimized, well s
|
||||
|
||||
-e TYPE=AIRPLANE
|
||||
|
||||
> NOTE: The `VERSION` variable is used to select an Airplane type to download. The available options are "LATEST" and "PURPUR", both 1.17.1. Airplane does not support 1.18 -- use Paper/Pufferfish/Purpur.
|
||||
> NOTE: The `VERSION` variable is used to select an Airplane branch to download from. The available options are "LATEST" "1.17" "1.16" "PURPUR" and "PURPUR-1.16"
|
||||
|
||||
Extra variables:
|
||||
- `AIRPLANE_BUILD=lastSuccessfulBuild` : set a specific Airplane build to use
|
||||
- `FORCE_REDOWNLOAD=false` : set to true to force the located server jar to be re-downloaded
|
||||
- `USE_FLARE_FLAGS=false` : set to true to add appropriate flags for the built-in [Flare](https://blog.airplane.gg/flare) profiler
|
||||
|
||||
### Running a Pufferfish server
|
||||
|
||||
A [Pufferfish](https://github.com/pufferfish-gg/Pufferfish) server, which is "a highly optimized Paper fork designed for large servers requiring both maximum performance, stability, and "enterprise" features."
|
||||
|
||||
-e TYPE=PUFFERFISH
|
||||
|
||||
> NOTE: The `VERSION` variable is used to select a Pufferfish branch to download from. The available options are "LATEST" and "1.18"
|
||||
|
||||
Extra variables:
|
||||
- `PUFFERFISH_BUILD=lastSuccessfulBuild` : set a specific Pufferfish build to use
|
||||
- `FORCE_REDOWNLOAD=false` : set to true to force the located server jar to be re-downloaded
|
||||
- `USE_FLARE_FLAGS=false` : set to true to add appropriate flags for the built-in [Flare](https://blog.airplane.gg/flare) profiler
|
||||
- `USE_FLARE_FLAGS=false` : set to true to add appropriate flags for the [Flare](https://blog.airplane.gg/flare) profiler
|
||||
|
||||
### Running a Purpur server
|
||||
|
||||
@@ -514,7 +494,7 @@ A [Purpur](https://purpur.pl3x.net/) server, which is "drop-in replacement for P
|
||||
Extra variables:
|
||||
- `PURPUR_BUILD=LATEST` : set a specific Purpur build to use
|
||||
- `FORCE_REDOWNLOAD=false` : set to true to force the located server jar to be re-downloaded
|
||||
- `USE_FLARE_FLAGS=false` : set to true to add appropriate flags for the built-in [Flare](https://blog.airplane.gg/flare) profiler
|
||||
- `USE_FLARE_FLAGS=false` : set to true to add appropriate flags for the [Flare](https://blog.airplane.gg/flare) profiler
|
||||
|
||||
### Running a Magma server
|
||||
|
||||
@@ -591,8 +571,6 @@ Configuration options with defaults:
|
||||
- `LIMBO_SCHEMA_FILENAME`=default.schem
|
||||
- `LEVEL`="Default;${LIMBO_SCHEMA_FILENAME}"
|
||||
|
||||
> NOTE: instead of using format codes in the MOTD, Limbo requires [JSON chat content](https://minecraft.fandom.com/wiki/Raw_JSON_text_format#Java_Edition). If a plain string is provided, which is the default, then it gets converted into the required JSON structure.
|
||||
|
||||
### Running a Crucible server
|
||||
|
||||
A [Crucible](https://github.com/CrucibleMC/Crucible) server can be run by setting `TYPE` to `CRUCIBLE`.
|
||||
@@ -747,77 +725,11 @@ You may also download or copy over individual mods using the `MODS` environment
|
||||
|
||||
docker run -d -e MODS=https://www.example.com/mods/mod1.jar,/plugins/common,/plugins/special/mod2.jar ...
|
||||
|
||||
### ForgeAPI usage to use non-version specific projects
|
||||
### Generic pack file
|
||||
|
||||
**NOTE:** This potentially could lead to unexpected behavior if the Mod receives an update with unexpected behavior.
|
||||
To install all of the server content (jars, mods, plugins, configs, etc) from a zip file, such as a CurseForge modpack that is missing a server start script, then set `GENERIC_PACK` to the container path of the zip file. That, combined with `TYPE`, allows for custom content along with container managed server download and install.
|
||||
|
||||
This is more complicated because you will be pulling/using the latest mod for the release of your game. To get started make sure you have a [CursedForge API Key](https://docs.curseforge.com/#getting-started). Then use the environmental parameters in your docker build.
|
||||
|
||||
Parameters to use the ForgeAPI:
|
||||
|
||||
* `MODS_FORGEAPI_KEY` - Required
|
||||
* `MODS_FORGEAPI_FILE` - Required or use MODS_FORGEAPI_PROJECTIDS (Overrides MODS_FORGEAPI_PROJECTIDS)
|
||||
* `MODS_FORGEAPI_PROJECTIDS` - Required or use MODS_FORGEAPI_FILE
|
||||
* `MODS_FORGEAPI_RELEASES` - Default is release, Options: [Release|Beta|Alpha]
|
||||
* `MODS_FORGEAPI_DOWNLOAD_DEPENDENCIES` - Default is False, attempts to download required mods (releaseType Release) defined in Forge.
|
||||
* `REMOVE_OLD_FORGEAPI_MODS` - Default is False
|
||||
* `REMOVE_OLD_DATAPACKS_DEPTH` - Default is 1
|
||||
* `REMOVE_OLD_DATAPACKS_INCLUDE` - Default is *.jar
|
||||
|
||||
Example of expected forge api project ids, releases, and key:
|
||||
|
||||
```yaml
|
||||
MODS_FORGEAPI_PROJECTIDS: 306612,256717
|
||||
MODS_FORGEAPI_RELEASES: Release
|
||||
MODS_FORGEAPI_KEY: $WRX...
|
||||
```
|
||||
|
||||
Example of expected ForgeAPI file format.
|
||||
|
||||
**Field Description**:
|
||||
* `name` is currently unused, but can be used to document each entry.
|
||||
* `projectId` id is the id found on the CurseForge website for a particular mod
|
||||
* `releaseType` Type corresponds to forge's R, B, A icon for each file. Default Release, options are (release|beta|alpha).
|
||||
* `fileName` is used for version pinning if latest file will not work for you.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"name": "fabric api",
|
||||
"projectId": "306612",
|
||||
"releaseType": "release"
|
||||
},
|
||||
{
|
||||
"name": "fabric voice mod",
|
||||
"projectId": "416089",
|
||||
"releaseType": "beta"
|
||||
},
|
||||
{
|
||||
"name": "Biomes o plenty",
|
||||
"projectId": "220318",
|
||||
"fileName": "BiomesOPlenty-1.18.1-15.0.0.100-universal.jar",
|
||||
"releaseType": "release"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Generic pack files
|
||||
|
||||
To install all the server content (jars, mods, plugins, configs, etc.) from a zip or tgz file, then set `GENERIC_PACK` to the container path or URL of the archive file. This can also be used to apply a CurseForge modpack that is missing a server start script and/or Forge installer.
|
||||
|
||||
If multiple generic packs need to be applied together, set `GENERIC_PACKS` instead, with a comma separated list of archive file paths and/or URLs to files.
|
||||
|
||||
To avoid repetition, each entry will be prefixed by the value of `GENERIC_PACKS_PREFIX` and suffixed by the value of `GENERIC_PACKS_SUFFIX`, both of which are optional. For example, the following variables
|
||||
|
||||
```
|
||||
GENERIC_PACKS=configs-v9.0.1,mods-v4.3.6
|
||||
GENERIC_PACKS_PREFIX=https://cdn.example.org/
|
||||
GENERIC_PACKS_SUFFIX=.zip
|
||||
```
|
||||
|
||||
would expand to `https://cdn.example.org/configs-v9.0.1.zip,https://cdn.example.org/mods-v4.3.6.zip`.
|
||||
|
||||
If applying large generic packs, the update check can be time-consuming since a SHA1 checksum is compared. To skip the update check set `SKIP_GENERIC_PACK_UPDATE_CHECK` to "true". Conversely, the generic pack(s) can be forced to be applied without comparing the checksum by setting `FORCE_GENERIC_PACK_UPDATE` to "true".
|
||||
If multiple generic packs need to be applied together, set `GENERIC_PACKS` instead, with a comma separated list of zip file paths and/or URLs to zip files.
|
||||
|
||||
### Mod/Plugin URL Listing File
|
||||
|
||||
@@ -857,19 +769,23 @@ before unpacking new content from the MODPACK or MODS.
|
||||
|
||||
### Downloadable world
|
||||
|
||||
Instead of mounting the `/data` volume, you can instead specify the URL of a ZIP or compressed TAR file containing an archived world. It will be searched for a file `level.dat` and the containing subdirectory moved to the directory named by `$LEVEL`. This means that most of the archived Minecraft worlds downloadable from the Internet will already be in the correct format.
|
||||
Instead of mounting the `/data` volume, you can instead specify the URL of a ZIP file containing an archived world. It will be searched for a file `level.dat` and the containing subdirectory moved to the directory named by `$LEVEL`. This means that most of the archived Minecraft worlds downloadable from the Internet will already be in the correct format.
|
||||
|
||||
docker run -d -e WORLD=http://www.example.com/worlds/MySave.zip ...
|
||||
|
||||
**NOTE:** This URL must be accessible from inside the container. Therefore, you should use an IP address or a globally resolvable FQDN, or else the name of a linked container.
|
||||
**NOTE:** This URL must be accessible from inside the container. Therefore,
|
||||
you should use an IP address or a globally resolvable FQDN, or else the
|
||||
name of a linked container.
|
||||
|
||||
**NOTE:** If the archive contains more than one `level.dat`, then the one to select can be picked with `WORLD_INDEX`, which defaults to 1.
|
||||
|
||||
### Cloning world from a container path
|
||||
|
||||
The `WORLD` option can also be used to reference a directory, zip file, or compressed tar file that will be used as a source to clone or extract the world directory.
|
||||
The `WORLD` option can also be used to reference a directory or zip file that will be used as a source to clone or unzip the world directory.
|
||||
|
||||
For example, the following would initially clone the world's content from `/worlds/basic`. Also notice in the example that you should use a read-only volume attachment to ensure the clone source remains pristine.
|
||||
For example, the following would initially clone the world's content
|
||||
from `/worlds/basic`. Also notice in the example that you can use a
|
||||
read-only volume attachment to ensure the clone source remains pristine.
|
||||
|
||||
```
|
||||
docker run ... -v $HOME/worlds:/worlds:ro -e WORLD=/worlds/basic
|
||||
@@ -882,87 +798,6 @@ The following diagram shows how this option can be used in a compose deployment
|
||||
### Overwrite world on start
|
||||
The world will only be downloaded or copied if it doesn't exist already. Set `FORCE_WORLD_COPY=TRUE` to force overwrite the world on every server start.
|
||||
|
||||
### Datapacks
|
||||
Datapacks can be installed in a similar manner to mods/plugins. There are many environment variables which function in the same way they do for [mods](#working-with-mods-and-plugins):
|
||||
* `DATAPACKS`
|
||||
* `DATAPACKS_FILE`
|
||||
* `REMOVE_OLD_DATAPACKS`
|
||||
* `REMOVE_OLD_DATAPACKS_DEPTH`
|
||||
* `REMOVE_OLD_DATAPACKS_INCLUDE`
|
||||
* `REMOVE_OLD_DATAPACKS_EXCLUDE`
|
||||
Datapacks will be placed in `/data/$LEVEL/datapacks`
|
||||
|
||||
### VanillaTweaks
|
||||
|
||||
VanillaTweaks datapacks can be installed with a share code from the website UI **OR** a json file to specify packs to download and install.
|
||||
|
||||
Datapacks will be placed in `/data/$LEVEL/datapacks`
|
||||
Resourcepacks will be placed in `/data/resourcepacks`
|
||||
|
||||
Accepted Parameters:
|
||||
|
||||
- `VANILLATWEAKS_FILE`
|
||||
- `VANILLATWEAKS_SHARECODE`
|
||||
- `REMOVE_OLD_VANILLATWEAKS`
|
||||
- `REMOVE_OLD_VANILLATWEAKS_DEPTH`
|
||||
- `REMOVE_OLD_VANILLATWEAKS_INCLUDE`
|
||||
- `REMOVE_OLD_VANILLATWEAKS_EXCLUDE`
|
||||
|
||||
Example of expected Vanillatweaks sharecode:
|
||||
**Note**: ResourcePacks, DataPacks, and CraftingTweaks all have separate sharecodes
|
||||
|
||||
```yaml
|
||||
VANILLATWEAKS_SHARECODE: MGr52E,tF1zL2,LnEDwT
|
||||
```
|
||||
|
||||
Example of expected Vanillatweaks file format:
|
||||
|
||||
```yaml
|
||||
VANILLATWEAKS_FILE: /config/vt-datapacks.json,/config/vt-craftingtweaks.json,/config/vt-resourcepacks.json
|
||||
```
|
||||
|
||||
Datapacks Json:
|
||||
```json
|
||||
{
|
||||
"version": "1.18",
|
||||
"packs": {
|
||||
"survival": [
|
||||
"graves",
|
||||
"multiplayer sleep",
|
||||
],
|
||||
"items": ["armored elytra"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Resourcepacks Json:
|
||||
```json
|
||||
{
|
||||
"type": "resourcepacks",
|
||||
"version": "1.18",
|
||||
"packs": {
|
||||
"aesthetic": ["CherryPicking", "BlackNetherBricks", "AlternateBlockDestruction"]
|
||||
},
|
||||
"result": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
CraftingTweaks Json:
|
||||
```json
|
||||
{
|
||||
"type": "craftingtweaks",
|
||||
"version": "1.18",
|
||||
"packs": {
|
||||
"quality of life": [
|
||||
"dropper to dispenser",
|
||||
"double slabs",
|
||||
"back to blocks"
|
||||
]
|
||||
},
|
||||
"result": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
## Server configuration
|
||||
|
||||
By default, the server configuration will be created and set based on the following environment variables, but only the first time the server is started. If the `server.properties` file already exists, the values in them will not be changed.
|
||||
@@ -1011,35 +846,30 @@ values.
|
||||
|
||||
> **NOTE** it is very important to set this with servers exposed to the internet where you want only limited players to join.
|
||||
|
||||
To whitelist players for your Minecraft server, you can:
|
||||
- Provide the url or path to a whitelist file via `WHITELIST_FILE` environment variable
|
||||
`docker run -d -e WHITELIST_FILE=/extra/whitelist.json ...`
|
||||
- Provide a list of usernames and/or UUIDs separated by commas via the `WHITELIST` environment variable
|
||||
`docker run -d -e WHITELIST=user1,uuid2 ...`
|
||||
To whitelist players for your Minecraft server, pass the Minecraft usernames separated by commas via the `WHITELIST` environment variable, such as
|
||||
|
||||
To enforce the whitelist and auto-kick players not included in whitelist configuration, set `ENFORCE_WHITELIST=TRUE`. **By default** any user can join your Minecraft server if it's publicly accessible, regardless of your whitelist configuration.
|
||||
docker run -d -e WHITELIST=user1,user2 ...
|
||||
|
||||
If whitelist configuration already exists, `WHITELIST_FILE` will not be retrieved and any usernames in `WHITELIST` are **added** to the whitelist configuration. You can enforce regeneration of the whitelist on each server startup by setting `OVERRIDE_WHITELIST` to "true". This will delete the whitelist file before processing whitelist configuration.
|
||||
or
|
||||
|
||||
> NOTE: You can provide both `WHITELIST_FILE` and `WHITELIST`, which are processed in that order.
|
||||
docker run -d -e WHITELIST=uuid1,uuid2 ...
|
||||
|
||||
> NOTE: UUIDs passed via `WHITELIST` need to be the dashed variant, otherwise it not be recognised and instead added as a username.
|
||||
If the `WHITELIST` environment variable is not used, any user can join your Minecraft server if it's publicly accessible.
|
||||
|
||||
> If running Minecraft 1.7.5 or earlier, these variables will apply to `white-list.txt`, with 1.7.6 implementing support for `whitelist.json`. Make sure your `WHITELIST_FILE` is in the appropriate format.
|
||||
> NOTE: When using uuids in the whitelist, please make sure it is the dashed variant otherwise it will not parse correctly.
|
||||
|
||||
If either `WHITELIST_FILE` or `WHITELIST` is provided, the server property `white-list` is automatically set to `true`, enabline whitelist functionality. Alternatively you can set `ENABLE_WHITELIST=TRUE` to only set the server property `white-list` without modifying the whitelist file. In this case the whitelist can be managed using the `whitelist add` and `whitelist remove` commands. Remember you can set enforcement via the `ENFORCE_WHITELIST` variable.
|
||||
> NOTE: When `WHITELIST` is used the server properties `white-list` and `whitelist` will automatically get set to `true`.
|
||||
|
||||
> By default, the players in `WHITELIST` are **added** to the final `whitelist.json` file by the Minecraft server. If you set `OVERRIDE_WHITELIST` to "true" then the `whitelist.json` file will be recreated on each server startup.
|
||||
|
||||
Alternatively, you can set `ENABLE_WHITELIST=true` to only set the server properties `white-list` and `whitelist` without modifying the whitelist file. In this case the whitelist is solely managed using the `whitelist add` and `whitelist remove` commands.
|
||||
### Op/Administrator Players
|
||||
|
||||
Similar to the whitelist, to add users as operators (aka adminstrators) to your Minecraft server, you can:
|
||||
- Provide te url or path to an ops file via `OPS_FILE` environment variable
|
||||
`docker run -d -e OPS_FILE=https://config.example.com/extra/ops.json ...`
|
||||
- Provide a list of usernames and/or UUIDs separated by commas via the `OPS` environment variable
|
||||
`docker run -d -e OPS=user1,uuid2 ...`
|
||||
To add more "op" (aka adminstrator) users to your Minecraft server, pass the Minecraft usernames separated by commas via the `OPS` environment variable, such as
|
||||
|
||||
If ops configuration already exists, `OPS_FILE` will not be retrieved and any usernames in `OPS` are **added** to the ops configuration. You can enforce regeneration of the ops configuration on each server startup by setting `OVERRIDE_OPS` to "true". This will delete the ops file before processing ops configuration.
|
||||
docker run -d -e OPS=user1,user2 ...
|
||||
|
||||
> Similar to whitelists, you can provide both `OPS_FILE` and `OPS`, and Minecraft 1.7.5 or earlier will use `ops.txt` rather than `ops.json`.
|
||||
> By default, the players in `OPS` are **added** to the final `ops.json` file by the Minecraft server. If you set `OVERRIDE_OPS` to "true" then the `ops.json` file will be recreated on each server startup.
|
||||
|
||||
### Server icon
|
||||
|
||||
@@ -1497,8 +1327,6 @@ If you would like to `docker attach` to the Minecraft server console with color
|
||||
> This will bypass graceful server shutdown handling when using `docker stop`, so be sure the server console's `stop` command.
|
||||
>
|
||||
> Make to enable stdin and tty with `-it` when using `docker run` or `stdin_open: true` and `tty: true` when using docker compose.
|
||||
>
|
||||
> This feature is incompatible with Autopause and cannot be set when `ENABLE_AUTOPAUSE=true`.
|
||||
|
||||
### Server Shutdown Options
|
||||
|
||||
@@ -1559,6 +1387,10 @@ To enable remote JMX, such as for profiling with VisualVM or JMC, add the enviro
|
||||
|
||||
When `MEMORY` is greater than or equal to 12G, then the Aikar flags will be adjusted according to the article.
|
||||
|
||||
Large page support can also be enabled by adding
|
||||
|
||||
-e USE_LARGE_PAGES=true
|
||||
|
||||
### HTTP Proxy
|
||||
|
||||
You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL via the `PROXY`
|
||||
@@ -1583,28 +1415,6 @@ When the container is signalled to stop, the Minecraft process wrapper will atte
|
||||
### Setup only
|
||||
|
||||
If you are using a host-attached data directory, then you can have the image setup the Minecraft server files and stop prior to launching the server process by setting `SETUP_ONLY` to `true`.
|
||||
|
||||
### Enable Flare Flags
|
||||
|
||||
To enable the JVM flags required to fully support the [Flare profiling suite](https://blog.airplane.gg/flare), set the following variable:
|
||||
|
||||
-e USE_FLARE_FLAGS=true
|
||||
|
||||
Flare is built-in to Airplane/Pufferfish/Purpur, and is available in [plugin form](https://github.com/TECHNOVE/FlarePlugin) for other server types.
|
||||
|
||||
### Enable timestamps in init logs
|
||||
|
||||
Before the container starts the Minecraft Server its output is prefixed with `[init]`, such as
|
||||
|
||||
```
|
||||
[init] Starting the Minecraft server...
|
||||
```
|
||||
|
||||
To also include the timestamp with each log, set `LOG_TIMESTAMP` to "true". The log output will then look like:
|
||||
|
||||
```
|
||||
[init] 2022-02-05 16:58:33+00:00 Starting the Minecraft server...
|
||||
```
|
||||
|
||||
## Autopause
|
||||
|
||||
@@ -1634,10 +1444,6 @@ Enable the Autopause functionality by setting:
|
||||
-e ENABLE_AUTOPAUSE=TRUE
|
||||
```
|
||||
|
||||
Autopause is not compatible with `EXEC_DIRECTLY=true` and the two cannot be set together.
|
||||
|
||||
> When configuring kubernetes readiness/liveness health checks with auto-pause enabled, be sure to reference the `mc-health` wrapper script rather than `mc-status` directly.
|
||||
|
||||
The following environment variables define the behaviour of auto-pausing:
|
||||
* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds)
|
||||
describes the time between the last client disconnect and the pausing of the process (read as timeout established)
|
||||
@@ -1650,28 +1456,6 @@ The following environment variables define the behaviour of auto-pausing:
|
||||
* `AUTOPAUSE_KNOCK_INTERFACE`, default `eth0`
|
||||
<br>Describes the interface passed to the `knockd` daemon. If the default interface does not work, run the `ifconfig` command inside the container and derive the interface receiving the incoming connection from its output. The passed interface must exist inside the container. Using the loopback interface (`lo`) does likely not yield the desired results.
|
||||
|
||||
## Autostop
|
||||
|
||||
An option to stop the server after a specified time has been added for niche applications (e.g. billing saving on AWS Fargate). The function is incompatible with the Autopause functionality, as they basically cancel out each other.
|
||||
|
||||
Note that the docker container variables have to be set accordingly (restart policy set to "no") and that the container has to be manually restarted.
|
||||
|
||||
A starting, example compose file has been provided in [examples/docker-compose-autostop.yml](examples/docker-compose-autostop.yml).
|
||||
|
||||
Enable the Autostop functionality by setting:
|
||||
|
||||
```
|
||||
-e ENABLE_AUTOSTOP=TRUE
|
||||
```
|
||||
|
||||
The following environment variables define the behaviour of auto-stopping:
|
||||
* `AUTOSTOP_TIMEOUT_EST`, default `3600` (seconds)
|
||||
describes the time between the last client disconnect and the stopping of the server (read as timeout established)
|
||||
* `AUTOSTOP_TIMEOUT_INIT`, default `1800` (seconds)
|
||||
describes the time between server start and the stopping of the server, when no client connects inbetween (read as timeout initialized)
|
||||
* `AUTOSTOP_PERIOD`, default `10` (seconds)
|
||||
describes period of the daemonized state machine, that handles the stopping of the server
|
||||
|
||||
## Running on RaspberryPi
|
||||
|
||||
To run this image on a RaspberryPi 3 B+, 4, or newer, use any of the image tags [list in the Java version section](#running-minecraft-server-on-different-java-version) that specify `armv7` for the architecture, which includes `itzg/minecraft-server:latest`.
|
||||
|
||||
@@ -12,4 +12,4 @@ if [ ! -p "${CONSOLE_IN_NAMED_PIPE}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
gosu minecraft bash -c "echo $* > '${CONSOLE_IN_NAMED_PIPE:-/tmp/minecraft-console-in}'"
|
||||
echo "$@" > "${CONSOLE_IN_NAMED_PIPE:-/tmp/minecraft-console-in}"
|
||||
@@ -3,6 +3,12 @@
|
||||
# Use this variable to indicate a list of branches that docker hub is watching
|
||||
branches_list=(
|
||||
'java8'
|
||||
'java8-multiarch'
|
||||
'java8-openj9'
|
||||
'java11'
|
||||
'java11-openj9'
|
||||
'java16-openj9'
|
||||
'java17'
|
||||
)
|
||||
|
||||
function TrapExit {
|
||||
@@ -124,28 +130,3 @@ EOL
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
if [[ $tag ]]; then
|
||||
if [ -f "$HOME/.github.env" ]; then
|
||||
source "$HOME/.github.env"
|
||||
if [[ $GITHUB_TOKEN ]]
|
||||
then
|
||||
auth=(-u ":$GITHUB_TOKEN")
|
||||
base=https://api.github.com
|
||||
: "${owner:=itzg}"
|
||||
: "${repo:=docker-minecraft-server}"
|
||||
read -r -d '' releaseBody << EOF
|
||||
{
|
||||
"tag_name": "$tag",
|
||||
"name": "$tag",
|
||||
"generate_release_notes": true
|
||||
}
|
||||
EOF
|
||||
if ! curl "${auth[@]}" -H "Accept: application/vnd.github.v3+json" \
|
||||
"${base}/repos/${owner}/${repo}/releases" -d "$releaseBody"; then
|
||||
echo "ERROR failed to create github release $tag"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
@@ -1,20 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
minecraft:
|
||||
image: itzg/minecraft-server
|
||||
ports:
|
||||
- "25565:25565"
|
||||
volumes:
|
||||
- "mc:/data"
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
ENABLE_AUTOSTOP: "TRUE"
|
||||
# More aggressive settings for demo purposes
|
||||
AUTOSTOP_TIMEOUT_INIT: "30"
|
||||
AUTOSTOP_TIMEOUT_EST: "20"
|
||||
# Important not to auto-restart the server!!!
|
||||
restart: "no"
|
||||
|
||||
volumes:
|
||||
mc: {}
|
||||
@@ -13,7 +13,6 @@ services:
|
||||
VERSION: ${VERSION:-1.17.1}
|
||||
FORGEVERSION: ${FORGEVERSION:-37.0.90}
|
||||
GENERIC_PACK: /modpacks/${MODPACK:-Server-Files-0.0.21.zip}
|
||||
REMOVE_OLD_MODS: "${REMOVE_OLD_MODS:-false}"
|
||||
ports:
|
||||
- "25565:25565"
|
||||
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
mc:
|
||||
image: itzg/minecraft-server
|
||||
container_name: paper
|
||||
environment:
|
||||
EULA: "true"
|
||||
ENABLE_RCON: "true"
|
||||
TYPE: PAPER
|
||||
VIEW_DISTANCE: 10
|
||||
MEMORY: 2G
|
||||
VERSION: 1.9.4
|
||||
# needed for Paper versions before 1.14
|
||||
CONSOLE: "false"
|
||||
ports:
|
||||
- 25565:25565
|
||||
volumes:
|
||||
- mc-paper:/data
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
mc-paper:
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
version: "3.3"
|
||||
|
||||
services:
|
||||
vanillatweaks_file:
|
||||
restart: "no"
|
||||
image: itzg/minecraft-server
|
||||
ports:
|
||||
- "25565:25565/tcp"
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
VANILLATWEAKS_FILE: /config/vanillatweaks-datapacks.json
|
||||
REMOVE_OLD_VANILLATWEAKS: "TRUE"
|
||||
volumes:
|
||||
- data:/data
|
||||
- ./vanillatweaks-datapacks.json:/config/vanillatweaks-datapacks.json:ro
|
||||
vanillatweaks_sharecode:
|
||||
# port is set to 25566 to not conflict with vanillatweaks_file example
|
||||
ports:
|
||||
- "25566:25565/tcp"
|
||||
restart: "no"
|
||||
image: itzg/minecraft-server
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
VANILLATWEAKS_SHARECODE: MGr52E
|
||||
REMOVE_OLD_VANILLATWEAKS: "TRUE"
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"version": "1.18",
|
||||
"packs": {
|
||||
"survival": [
|
||||
"graves",
|
||||
"multiplayer sleep",
|
||||
"afk display",
|
||||
"armor statues",
|
||||
"unlock all recipes",
|
||||
"fast leaf decay",
|
||||
"coordinates hud"
|
||||
],
|
||||
"items": ["armored elytra"]
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,15 @@ current_uptime() {
|
||||
}
|
||||
|
||||
java_running() {
|
||||
[[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
|
||||
[[ $( ps -ax -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]]
|
||||
}
|
||||
|
||||
java_process_exists() {
|
||||
[[ -n "$(ps -a -o comm | grep 'java')" ]]
|
||||
[[ -n "$(ps -ax -o comm | grep 'java')" ]]
|
||||
}
|
||||
|
||||
rcon_client_exists() {
|
||||
[[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
|
||||
[[ -n "$(ps -ax -o comm | grep 'rcon-cli')" ]]
|
||||
}
|
||||
|
||||
mc_server_listening() {
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
[unpauseMCServer-server]
|
||||
sequence = 25565
|
||||
seq_timeout = 1
|
||||
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
|
||||
command = /usr/sbin/gosu minecraft:minecraft /autopause/resume.sh
|
||||
tcpflags = syn
|
||||
[unpauseMCServer-rcon]
|
||||
sequence = 25575
|
||||
seq_timeout = 1
|
||||
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
|
||||
command = /usr/sbin/gosu minecraft:minecraft /autopause/resume.sh
|
||||
tcpflags = syn
|
||||
[unpauseMCServer-bedrock]
|
||||
sequence = 19132:udp
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
. /start-utils
|
||||
|
||||
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; then
|
||||
if [[ $( ps -ax -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^S.*$ ]] ; then
|
||||
# save world
|
||||
rcon-cli save-all >/dev/null
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
. /start-utils
|
||||
|
||||
if [[ $( ps -a -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^T.*$ ]] ; then
|
||||
if [[ $( ps -ax -o stat,comm | grep 'java' | awk '{ print $1 }') =~ ^T.*$ ]] ; then
|
||||
logAutopauseAction "Knocked, resuming Java process"
|
||||
pkill -CONT java
|
||||
fi
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# needed for the clients connected function residing in autopause
|
||||
. /autopause/autopause-fcns.sh
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
# wait for java process to be started
|
||||
while :
|
||||
do
|
||||
if java_process_exists ; then
|
||||
break
|
||||
fi
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
STATE=INIT
|
||||
|
||||
while :
|
||||
do
|
||||
case X$STATE in
|
||||
XINIT)
|
||||
# Server startup
|
||||
if mc_server_listening ; then
|
||||
TIME_THRESH=$(($(current_uptime)+$AUTOSTOP_TIMEOUT_INIT))
|
||||
logAutostop "MC Server listening for connections - stopping in $AUTOSTOP_TIMEOUT_INIT seconds"
|
||||
STATE=II
|
||||
fi
|
||||
;;
|
||||
XII)
|
||||
# Initial idle
|
||||
if java_clients_connected ; then
|
||||
logAutostop "Client connected - waiting for disconnect"
|
||||
STATE=E
|
||||
else
|
||||
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
|
||||
logAutostop "No client connected since startup - stopping server"
|
||||
/autostop/stop.sh
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
XE)
|
||||
# Established
|
||||
if ! java_clients_connected ; then
|
||||
TIME_THRESH=$(($(current_uptime)+$AUTOSTOP_TIMEOUT_EST))
|
||||
logAutostop "All clients disconnected - stopping in $AUTOSTOP_TIMEOUT_EST seconds"
|
||||
STATE=I
|
||||
fi
|
||||
;;
|
||||
XI)
|
||||
# Idle
|
||||
if java_clients_connected ; then
|
||||
logAutostop "Client reconnected - waiting for disconnect"
|
||||
STATE=E
|
||||
else
|
||||
if [[ $(current_uptime) -ge $TIME_THRESH ]] ; then
|
||||
logAutostop "No client reconnected - stopping"
|
||||
/autostop/stop.sh
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
logAutostop "Error: invalid state: $STATE"
|
||||
;;
|
||||
esac
|
||||
sleep $AUTOSTOP_PERIOD
|
||||
done
|
||||
@@ -1,6 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
. /start-utils
|
||||
|
||||
logAutostopAction "Stopping Java process"
|
||||
kill -SIGTERM 1
|
||||
@@ -40,7 +40,7 @@ if ! isTrue "${SKIP_SUDO:-false}" && [ $(id -u) = 0 ]; then
|
||||
echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||
fi
|
||||
|
||||
exec su-exec ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration "$@"
|
||||
exec gosu ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
|
||||
else
|
||||
exec ${SCRIPTS:-/}start-configuration "$@"
|
||||
exec ${SCRIPTS:-/}start-configuration $@
|
||||
fi
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
|
||||
: "${SERVER_PORT:=25565}"
|
||||
export SERVER_PORT
|
||||
|
||||
log "Autostop functionality enabled"
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
if ! [[ $AUTOSTOP_PERIOD =~ ^[0-9]+$ ]]; then
|
||||
AUTOSTOP_PERIOD=10
|
||||
export AUTOSTOP_PERIOD
|
||||
log "Warning: AUTOSTOP_PERIOD is not numeric, set to 10 (seconds)"
|
||||
fi
|
||||
if [ "$AUTOSTOP_PERIOD" -eq "0" ] ; then
|
||||
AUTOSTOP_PERIOD=10
|
||||
export AUTOSTOP_PERIOD
|
||||
log "Warning: AUTOSTOP_PERIOD must not be 0, set to 10 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOSTOP_TIMEOUT_EST =~ ^[0-9]+$ ]] ; then
|
||||
AUTOSTOP_TIMEOUT_EST=3600
|
||||
export AUTOSTOP_TIMEOUT_EST
|
||||
log "Warning: AUTOSTOP_TIMEOUT_EST is not numeric, set to 3600 (seconds)"
|
||||
fi
|
||||
if ! [[ $AUTOSTOP_TIMEOUT_INIT =~ ^[0-9]+$ ]] ; then
|
||||
AUTOSTOP_TIMEOUT_INIT=1800
|
||||
export AUTOSTOP_TIMEOUT_INIT
|
||||
log "Warning: AUTOSTOP_TIMEOUT_INIT is not numeric, set to 1800 (seconds)"
|
||||
fi
|
||||
|
||||
/autostop/autostop-daemon.sh &
|
||||
@@ -3,7 +3,7 @@ set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
: "${EULA:=}"
|
||||
: "${PROXY:=}"
|
||||
@@ -32,15 +32,6 @@ if [ ! -e /data/eula.txt ]; then
|
||||
writeEula
|
||||
fi
|
||||
|
||||
if isTrue "${ENABLE_AUTOPAUSE}" && isTrue "${EXEC_DIRECTLY:-false}"; then
|
||||
log "EXEC_DIRECTLY=true is incompatible with ENABLE_AUTOPAUSE=true"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if isTrue "${ENABLE_AUTOPAUSE}" && isTrue "${ENABLE_AUTOSTOP}"; then
|
||||
log "ENABLE_AUTOPAUSE=true is incompatible with ENABLE_AUTOSTOP=true"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $PROXY ]]; then
|
||||
export http_proxy="$PROXY"
|
||||
@@ -66,12 +57,9 @@ if [[ $RCON_PASSWORD_FILE ]]; then
|
||||
log ""
|
||||
fi
|
||||
|
||||
# Some Docker management UIs grab all the image declared variables and present them for configuration.
|
||||
# When upgrading images across Java versions, that creates a mismatch in PATH's expected by base image.
|
||||
if ! which java > /dev/null; then
|
||||
log "ERROR: PATH should not be explicitly passed into the container"
|
||||
log " Remove configuration of that variable."
|
||||
exit 1
|
||||
log "Fixing PATH to include java"
|
||||
PATH="${PATH}:/opt/java/openjdk/bin"
|
||||
fi
|
||||
|
||||
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
|
||||
@@ -104,10 +92,6 @@ if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||
${SCRIPTS:-/}start-autopause
|
||||
fi
|
||||
|
||||
if isTrue "${ENABLE_AUTOSTOP}"; then
|
||||
${SCRIPTS:-/}start-autostop
|
||||
fi
|
||||
|
||||
if versionLessThan 1.7; then
|
||||
echo "
|
||||
MC_HEALTH_EXTRA_ARGS=(
|
||||
@@ -119,31 +103,27 @@ fi
|
||||
log "Resolving type given ${TYPE}"
|
||||
case "${TYPE^^}" in
|
||||
*BUKKIT|SPIGOT)
|
||||
exec "${SCRIPTS:-/}start-deployBukkitSpigot" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployBukkitSpigot "$@"
|
||||
;;
|
||||
|
||||
PAPER)
|
||||
exec "${SCRIPTS:-/}start-deployPaper" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployPaper "$@"
|
||||
;;
|
||||
|
||||
FORGE)
|
||||
evaluateJavaCompatibilityForForge
|
||||
exec "${SCRIPTS:-/}start-deployForge" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployForge "$@"
|
||||
;;
|
||||
|
||||
FABRIC)
|
||||
exec "${SCRIPTS:-/}start-deployFabric" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployFabric "$@"
|
||||
;;
|
||||
|
||||
FTBA)
|
||||
log "ERROR: TYPE=FTBA is not supported with this image variant."
|
||||
log " Use itzg/minecraft-server:java8-multiarch instead."
|
||||
exit 1
|
||||
exec ${SCRIPTS:-/}start-deployFTBA "$@"
|
||||
;;
|
||||
|
||||
FTB|CURSEFORGE)
|
||||
evaluateJavaCompatibilityForForge
|
||||
exec "${SCRIPTS:-/}start-deployCF" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployCF "$@"
|
||||
;;
|
||||
|
||||
VANILLA)
|
||||
@@ -151,47 +131,39 @@ case "${TYPE^^}" in
|
||||
;;
|
||||
|
||||
SPONGEVANILLA)
|
||||
exec "${SCRIPTS:-/}start-deploySpongeVanilla" "$@"
|
||||
exec ${SCRIPTS:-/}start-deploySpongeVanilla "$@"
|
||||
;;
|
||||
|
||||
CUSTOM)
|
||||
evaluateJavaCompatibilityForForge
|
||||
exec "${SCRIPTS:-/}start-deployCustom" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployCustom "$@"
|
||||
;;
|
||||
|
||||
MAGMA)
|
||||
evaluateJavaCompatibilityForForge
|
||||
exec "${SCRIPTS:-/}start-deployMagma" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployMagma "$@"
|
||||
;;
|
||||
|
||||
MOHIST)
|
||||
evaluateJavaCompatibilityForForge
|
||||
exec "${SCRIPTS:-/}start-deployMohist" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployMohist "$@"
|
||||
;;
|
||||
|
||||
CATSERVER)
|
||||
evaluateJavaCompatibilityForForge
|
||||
exec "${SCRIPTS:-/}start-deployCatserver" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployCatserver "$@"
|
||||
;;
|
||||
|
||||
PURPUR)
|
||||
exec "${SCRIPTS:-/}start-deployPurpur" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployPurpur "$@"
|
||||
;;
|
||||
|
||||
AIRPLANE)
|
||||
exec "${SCRIPTS:-/}start-deployAirplane" "$@"
|
||||
;;
|
||||
|
||||
PUFFERFISH)
|
||||
exec "${SCRIPTS:-/}start-deployPufferfish" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployAirplane "$@"
|
||||
;;
|
||||
|
||||
CANYON)
|
||||
exec "${SCRIPTS:-/}start-deployCanyon" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployCanyon "$@"
|
||||
;;
|
||||
|
||||
LIMBO)
|
||||
exec "${SCRIPTS:-/}start-deployLimbo" "$@"
|
||||
exec ${SCRIPTS:-/}start-deployLimbo "$@"
|
||||
;;
|
||||
|
||||
CRUCIBLE)
|
||||
@@ -202,7 +174,7 @@ case "${TYPE^^}" in
|
||||
log "Invalid type: '$TYPE'"
|
||||
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
|
||||
log " CURSEFORGE, SPONGEVANILLA, PURPUR, CUSTOM,"
|
||||
log " MAGMA, MOHIST, CATSERVER, AIRPLANE, PUFFERFISH, CANYON, LIMBO, CRUCIBLE"
|
||||
log " MAGMA, MOHIST, CATSERVER, AIRPLANE, CANYON, LIMBO, CRUCIBLE"
|
||||
exit 1
|
||||
;;
|
||||
|
||||
|
||||
@@ -1,46 +1,52 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -euo pipefail
|
||||
isDebugging && set -x
|
||||
|
||||
IFS=$'\n\t'
|
||||
|
||||
if [ "${VERSION}" != "LATEST" ] && [ "${VERSION}" != "PURPUR" ] ; then
|
||||
log "ERROR: Airplane server type only supports VERSION=LATEST, VERSION=PURPUR."
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
if [ "${VERSION}" != "LATEST" ] && [ "${VERSION}" != "1.16" ] && [ "${VERSION}" != "1.17" ] && [ "${VERSION}" != "PURPUR" ] && [ "${VERSION}" != "PURPUR-1.16" ] ; then
|
||||
log "ERROR: Airplane server type only supports VERSION=LATEST, VERSION=1.17, VERSION=1.16, VERSION=PURPUR or VERSION=PURPUR-1.16. Note that these are branches, not #.#.# versions."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: ${AIRPLANE_BUILD:=lastSuccessfulBuild}
|
||||
: ${AIRPLANE_TYPE:=airplane}
|
||||
|
||||
if [ "${VERSION}" = "LATEST" ] ; then
|
||||
AIRPLANE_TYPE="airplane"
|
||||
if [ "${VERSION}" = "LATEST" ] || [ "${VERSION}" = "1.17" ]; then
|
||||
AIRPLANE_BRANCH="1.17"
|
||||
fi
|
||||
|
||||
if [ "${VERSION}" = "1.16" ]; then
|
||||
AIRPLANE_BRANCH="1.16"
|
||||
fi
|
||||
|
||||
if [ "${VERSION}" = "PURPUR" ]; then
|
||||
AIRPLANE_BRANCH="Purpur-1.17"
|
||||
AIRPLANE_TYPE="airplanepurpur"
|
||||
fi
|
||||
|
||||
log "Using ${AIRPLANE_TYPE} 1.17.1 (1.18 unsupported - use Paper/Pufferfish/Purpur for newer versions)"
|
||||
if [ "${VERSION}" = "PURPUR-1.16" ]; then
|
||||
AIRPLANE_BRANCH="Purpur-1.16"
|
||||
AIRPLANE_TYPE="airplanepurpur"
|
||||
fi
|
||||
|
||||
export SERVER=${AIRPLANE_TYPE}-1.17.1.jar
|
||||
log "Using Airplane-${AIRPLANE_BRANCH} branch"
|
||||
|
||||
log "Removing old Airplane versions ..."
|
||||
shopt -s nullglob
|
||||
for f in airplane*.jar; do
|
||||
[[ $f != $SERVER ]] && rm $f
|
||||
done
|
||||
export SERVER=airplane-${AIRPLANE_BRANCH}-${AIRPLANE_BUILD}.jar
|
||||
|
||||
if [ ! -f "$SERVER" ] || isTrue "${FORCE_REDOWNLOAD:-false}"; then
|
||||
downloadUrl="https://airplane.gg/dl/launcher-${AIRPLANE_TYPE}1.17.1.jar"
|
||||
downloadUrl="https://ci.tivy.ca/job/Airplane-${AIRPLANE_BRANCH}/${AIRPLANE_BUILD}/artifact/launcher-${AIRPLANE_TYPE}.jar"
|
||||
log "Downloading Airplane from $downloadUrl ..."
|
||||
if ! get -o "$SERVER" "$downloadUrl"; then
|
||||
curl -fsSL -o "$SERVER" "$downloadUrl"
|
||||
if [ ! -f "$SERVER" ]; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for later operations
|
||||
export FAMILY=SPIGOT
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec "${SCRIPTS:-/}start-spiget" "$@"
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
|
||||
@@ -126,6 +126,7 @@ else
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for operations below
|
||||
export FAMILY=SPIGOT
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
|
||||
@@ -35,37 +35,11 @@ FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
|
||||
log "Looking for Feed-The-Beast / CurseForge server modpack."
|
||||
requireVar FTB_SERVER_MOD
|
||||
|
||||
downloadModpack() {
|
||||
srv_modpack=${FTB_SERVER_MOD}
|
||||
if isURL "${srv_modpack}"; then
|
||||
log "Downloading modpack from ${srv_modpack}..."
|
||||
if ! srv_modpack=$(get -o /data --output-filename --skip-existing "${srv_modpack}"); then
|
||||
log "ERROR: failed to download modpack"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ "${srv_modpack:0:5}" == "data/" ]]; then
|
||||
# Prepend with "/"
|
||||
srv_modpack="/${srv_modpack}"
|
||||
fi
|
||||
if [[ ! "${srv_modpack:0:1}" == "/" ]]; then
|
||||
# If not an absolute path, assume file is in "/data"
|
||||
srv_modpack=/data/${srv_modpack}
|
||||
fi
|
||||
if [[ ! -f "${srv_modpack}" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} not found."
|
||||
exit 2
|
||||
fi
|
||||
if [[ ! "${srv_modpack: -4}" == ".zip" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} is not a zip archive."
|
||||
log "Please set FTB_SERVER_MOD to a file with a .zip extension."
|
||||
exit 2
|
||||
fi
|
||||
FTB_SERVER_MOD=${srv_modpack}
|
||||
}
|
||||
|
||||
if ! isTrue "${USE_MODPACK_START_SCRIPT:-true}"; then
|
||||
downloadModpack
|
||||
if ! [ -f "${FTB_SERVER_MOD}" ]; then
|
||||
log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
needsInstall=true
|
||||
installMarker=/data/.curseforge-installed
|
||||
@@ -73,7 +47,7 @@ if ! isTrue "${USE_MODPACK_START_SCRIPT:-true}"; then
|
||||
if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then
|
||||
log "Upgrading modpack"
|
||||
|
||||
serverJar=$(find "${FTB_BASE_DIR}" -type f \( -path "*/libraries/*" -o -path "*/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||
serverJar=$(find "${FTB_BASE_DIR}" -not -name "forge*installer.jar" -name "forge*.jar")
|
||||
if [[ "${serverJar}" ]]; then
|
||||
rm -rf "$(dirname "${serverJar}")"/{mods,*.jar,libraries,resources,scripts,config}
|
||||
fi
|
||||
@@ -111,8 +85,6 @@ if ! isTrue "${USE_MODPACK_START_SCRIPT:-true}"; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
forgeInstallerJar=$(ls -t "${forgeInstallerJar}" | head -1)
|
||||
|
||||
log "Installing forge server"
|
||||
dirOfInstaller=$(dirname "${forgeInstallerJar}")
|
||||
(cd "${dirOfInstaller}"; java -jar "$(basename "${forgeInstallerJar}")" --installServer)
|
||||
@@ -160,9 +132,32 @@ fi
|
||||
# also check for the start script rather than just the folder
|
||||
# this allows saving just the world separate from the rest of the data directory
|
||||
if [[ $startScriptCount = 0 ]]; then
|
||||
downloadModpack
|
||||
srv_modpack=${FTB_SERVER_MOD}
|
||||
|
||||
if isURL "${srv_modpack}"; then
|
||||
log "Downloading modpack from ${srv_modpack}..."
|
||||
if ! srv_modpack=$(get -o /data --output-filename --skip-existing "${srv_modpack}"); then
|
||||
log "ERROR: failed to download modpack"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ "${srv_modpack:0:5}" == "data/" ]]; then
|
||||
# Prepend with "/"
|
||||
srv_modpack="/${srv_modpack}"
|
||||
fi
|
||||
if [[ ! "${srv_modpack:0:1}" == "/" ]]; then
|
||||
# If not an absolute path, assume file is in "/data"
|
||||
srv_modpack=/data/${srv_modpack}
|
||||
fi
|
||||
if [[ ! -f "${srv_modpack}" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} not found."
|
||||
exit 2
|
||||
fi
|
||||
if [[ ! "${srv_modpack: -4}" == ".zip" ]]; then
|
||||
log "FTB server modpack ${srv_modpack} is not a zip archive."
|
||||
log "Please set FTB_SERVER_MOD to a file with a .zip extension."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
log "Unpacking FTB server modpack ${srv_modpack} ..."
|
||||
mkdir -p "${FTB_BASE_DIR}"
|
||||
unzip -o "${srv_modpack}" -d "${FTB_BASE_DIR}" | awk '{printf "."} END {print ""}'
|
||||
@@ -238,5 +233,4 @@ elif [ -e "${FTB_DIR}/Install.sh" ]; then
|
||||
popd
|
||||
fi
|
||||
|
||||
export FAMILY=FORGE
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
|
||||
@@ -43,6 +43,7 @@ if [ ! -f "$SERVER" ]; then
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for later operations
|
||||
export FAMILY=SPIGOT
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -o pipefail
|
||||
set -e
|
||||
|
||||
@@ -27,6 +26,7 @@ if [ ! -f ${SERVER} ]; then
|
||||
curl -H "Accept:application/octet-stream" -o "$SERVER" -fsSL https://api.github.com/repos/Luohuayu/CatServer/releases/assets/${latestJarId}
|
||||
fi
|
||||
|
||||
export FAMILY=HYBRID
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
# Continue to Final Setup
|
||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||
|
||||
@@ -47,7 +47,6 @@ if [ ! -d "$librariesDir" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir "$librariesDir"
|
||||
if ! unzip /tmp/libraries.zip -d "$librariesDir"; then
|
||||
log "ERROR: failed to unzip Crucible libraries"
|
||||
exit 1
|
||||
@@ -56,6 +55,6 @@ if [ ! -d "$librariesDir" ]; then
|
||||
fi
|
||||
|
||||
export SERVER
|
||||
export FAMILY=HYBRID
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec "${SCRIPTS:-$(dirname "$0")}/start-setupWorld" "$@"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
if isURL ${CUSTOM_SERVER}; then
|
||||
@@ -31,6 +30,6 @@ else
|
||||
|
||||
fi
|
||||
|
||||
export FAMILY=HYBRID
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
|
||||
ftbInstallMarker=".ftb-installed"
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
set -e
|
||||
|
||||
@@ -80,6 +79,4 @@ if ! [ -v SERVER ]; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
export FAMILY=FORGE
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
|
||||
@@ -2,31 +2,27 @@
|
||||
set -eu
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
requireVar VANILLA_VERSION
|
||||
export TYPE=FABRIC
|
||||
: "${FABRIC_INSTALLER_VERSION:=${FABRICVERSION:-LATEST}}"
|
||||
: "${FABRIC_INSTALLER:=}"
|
||||
: "${FABRIC_INSTALLER_URL:=}"
|
||||
: "${FABRIC_LOADER_VERSION:=LATEST}"
|
||||
export SERVER=fabric-server-${VANILLA_VERSION}.jar
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
log "Checking Fabric version information."
|
||||
if [[ $FABRIC_INSTALLER ]]; then
|
||||
FABRIC_INSTALLER_VERSION=$(echo -n "$FABRIC_INSTALLER" | mc-image-helper hash)
|
||||
elif [[ $FABRIC_INSTALLER_URL ]]; then
|
||||
FABRIC_INSTALLER_VERSION=$(echo -n "$FABRIC_INSTALLER_URL" | mc-image-helper hash)
|
||||
elif [[ ${FABRIC_INSTALLER_VERSION^^} = LATEST ]]; then
|
||||
FABRIC_INSTALLER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
|
||||
fi
|
||||
if [[ ! -e ${SERVER} ]]; then
|
||||
|
||||
export SERVER=fabric-server-${VANILLA_VERSION}-${FABRIC_INSTALLER_VERSION}.jar
|
||||
|
||||
if [ ! \( -e ${SERVER} -a -e "server-${VANILLA_VERSION}.jar" \) ]; then
|
||||
: ${FABRIC_INSTALLER:=}
|
||||
: ${FABRIC_INSTALLER_URL:=}
|
||||
: ${FABRIC_LOADER_VERSION:=LATEST}
|
||||
: ${FABRIC_INSTALLER_VERSION:=${FABRICVERSION:-LATEST}}
|
||||
|
||||
if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
|
||||
log "Checking Fabric version information."
|
||||
if [[ ${FABRIC_INSTALLER_VERSION^^} = LATEST ]]; then
|
||||
FABRIC_INSTALLER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-installer/maven-metadata.xml)
|
||||
fi
|
||||
|
||||
FABRIC_INSTALLER="fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
|
||||
FABRIC_INSTALLER_URL="https://maven.fabricmc.net/net/fabricmc/fabric-installer/${FABRIC_INSTALLER_VERSION}/fabric-installer-${FABRIC_INSTALLER_VERSION}.jar"
|
||||
elif [[ -z $FABRIC_INSTALLER ]]; then
|
||||
@@ -70,12 +66,7 @@ if [ ! \( -e ${SERVER} -a -e "server-${VANILLA_VERSION}.jar" \) ]; then
|
||||
exit 10
|
||||
fi
|
||||
|
||||
mv server.jar "server-${VANILLA_VERSION}.jar"
|
||||
mv fabric-server-launch.jar "${SERVER}"
|
||||
fi
|
||||
|
||||
# Specify which server jar to run
|
||||
echo "serverJar=server-${VANILLA_VERSION}.jar" > fabric-server-launcher.properties
|
||||
|
||||
export FAMILY=FABRIC
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||
|
||||
@@ -38,23 +38,18 @@ install() {
|
||||
get_installer "$normForgeVersion" "$shortForgeVersion"
|
||||
fi
|
||||
|
||||
log "Installing Forge $shortForgeVersion. This might take a minute or two..."
|
||||
log "Installing Forge $shortForgeVersion using $FORGE_INSTALLER"
|
||||
mkdir -p mods
|
||||
tries=3
|
||||
while true; do
|
||||
if ! java -jar "$FORGE_INSTALLER" --installServer &> forge-installer.log; then
|
||||
if ((--tries <= 0)); then
|
||||
cat forge-installer.log
|
||||
log "
|
||||
ERROR Forge failed to install after several tries.
|
||||
"
|
||||
exit 1
|
||||
fi
|
||||
log "Install failed. Trying again..."
|
||||
else
|
||||
break # out of this loop
|
||||
while ((--tries >= 0)); do
|
||||
if java -jar "$FORGE_INSTALLER" --installServer; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
if ((tries < 0)); then
|
||||
log "Forge failed to install after several tries." >&2
|
||||
exit 10
|
||||
fi
|
||||
# NOTE $shortForgeVersion will be empty if installer location was given to us
|
||||
log "Finding installed server jar..."
|
||||
unset -v latest
|
||||
@@ -152,6 +147,4 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
export FAMILY=FORGE
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
|
||||
@@ -58,5 +58,6 @@ if [[ ${LEVEL} != *\;* ]]; then
|
||||
fi
|
||||
export LEVEL
|
||||
|
||||
export FAMILY=LIMBO
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
isDebugging && set -x
|
||||
|
||||
: "${VANILLA_VERSION?}"
|
||||
: ${VANILLA_VERSION?}
|
||||
# stable, dev
|
||||
: "${MAGMA_CHANNEL:=stable}"
|
||||
: ${MAGMA_CHANNEL:=stable}
|
||||
|
||||
|
||||
magmaDownloadServer() {
|
||||
@@ -88,6 +89,4 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
export FAMILY=HYBRID
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
|
||||
@@ -38,6 +38,6 @@ if [ ! -f "${SERVER}" ]; then
|
||||
get -o "${SERVER}" "${mohistJob}${MOHIST_BUILD}/artifact/${buildRelPath}"
|
||||
fi
|
||||
|
||||
export FAMILY=HYBRID
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec "${SCRIPTS:-$(dirname "$0")}/start-setupWorld" "$@"
|
||||
|
||||
@@ -73,6 +73,7 @@ else
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for downstream operations
|
||||
export FAMILY=SPIGOT
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
set -euo pipefail
|
||||
isDebugging && set -x
|
||||
|
||||
IFS=$'\n\t'
|
||||
|
||||
if [ "${VERSION}" != "LATEST" ] && [ "${VERSION}" != "1.18" ] ; then
|
||||
log "ERROR: Pufferfish server type only supports VERSION=LATEST, VERSION=1.18. Note that these are branches, not #.#.# versions."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
: ${PUFFERFISH_BUILD:=lastSuccessfulBuild}
|
||||
|
||||
if [ "${VERSION}" = "LATEST" ] || [ "${VERSION}" = "1.18" ]; then
|
||||
PUFFERFISH_BRANCH="1.18"
|
||||
PUFFERFISH_VERSION="1.18.1-R0.1"
|
||||
fi
|
||||
|
||||
log "Using Pufferfish-${PUFFERFISH_BRANCH} branch"
|
||||
|
||||
export SERVER=pufferfish-${PUFFERFISH_BRANCH}-${PUFFERFISH_BUILD}.jar
|
||||
|
||||
log "Removing old Pufferfish versions ..."
|
||||
shopt -s nullglob
|
||||
for f in pufferfish-*.jar; do
|
||||
[[ $f != $SERVER ]] && rm $f
|
||||
done
|
||||
|
||||
if [ ! -f "$SERVER" ] || isTrue "${FORCE_REDOWNLOAD:-false}"; then
|
||||
artifact="build/libs/pufferfish-paperclip-${PUFFERFISH_VERSION}-SNAPSHOT-reobf.jar"
|
||||
downloadUrl="https://ci.pufferfish.host/job/Pufferfish-${PUFFERFISH_BRANCH}/${PUFFERFISH_BUILD}/artifact/${artifact}"
|
||||
log "Downloading Pufferfish from $downloadUrl ..."
|
||||
if ! get -o "$SERVER" "$downloadUrl"; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for later operations
|
||||
export FAMILY=SPIGOT
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
@@ -2,19 +2,20 @@
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
: "${VANILLA_VERSION:?}"
|
||||
: "${PURPUR_BUILD:=LATEST}"
|
||||
: "${FORCE_REDOWNLOAD:=false}"
|
||||
: ${VANILLA_VERSION:?}
|
||||
: ${PURPUR_BUILD:=LATEST}
|
||||
: ${FORCE_REDOWNLOAD:=false}
|
||||
|
||||
if [[ ${PURPUR_BUILD} == LATEST ]]; then
|
||||
if ! PURPUR_BUILD=$(get --json-path=".builds.latest" "https://api.purpurmc.org/v2/purpur/${VANILLA_VERSION}"); then
|
||||
PURPUR_BUILD=$(curl -fsSL "https://api.purpurmc.org/v2/purpur/${VANILLA_VERSION}" |
|
||||
jq -r '.builds.latest' || echo "")
|
||||
if [[ -z ${PURPUR_BUILD} ]]; then
|
||||
log "ERROR: Failed to locate a Purpur build for ${VANILLA_VERSION}."
|
||||
log " Please check if a download is available at https://purpur.pl3x.net/downloads/"
|
||||
exit 1
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -23,13 +24,14 @@ export SERVER="purpur-${VANILLA_VERSION}-${PURPUR_BUILD}.jar"
|
||||
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
|
||||
downloadUrl="https://api.purpurmc.org/v2/purpur/${VANILLA_VERSION}/${PURPUR_BUILD}/download"
|
||||
log "Downloading Purpur from $downloadUrl ..."
|
||||
if ! get -o "$SERVER" "$downloadUrl"; then
|
||||
if ! curl -fsSL -o "$SERVER" "$downloadUrl"; then
|
||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||
exit 3
|
||||
fi
|
||||
fi
|
||||
|
||||
# Normalize on Spigot for later operations
|
||||
export FAMILY=SPIGOT
|
||||
export TYPE=SPIGOT
|
||||
export SKIP_LOG4J_CONFIG=true
|
||||
|
||||
exec "${SCRIPTS:-/}start-spiget" "$@"
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
|
||||
@@ -37,5 +37,4 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
||||
curl -sSL -o $SERVER https://repo.spongepowered.org/maven/org/spongepowered/$TYPE/$SPONGEVERSION/$SERVER
|
||||
fi
|
||||
|
||||
export FAMILY=SPONGE
|
||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||
|
||||
@@ -52,5 +52,5 @@ elif [[ -L /data/minecraft_server.jar ]]; then
|
||||
fi
|
||||
|
||||
isDebugging && ls -l
|
||||
export FAMILY=VANILLA
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||
|
||||
@@ -1,9 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
isDebugging && set -x
|
||||
|
||||
if [ -n "$OPS" ]; then
|
||||
log "Updating ops"
|
||||
rm -f /data/ops.txt.converted
|
||||
echo $OPS | awk -v RS=, '{print}' > /data/ops.txt
|
||||
fi
|
||||
if isTrue "${OVERRIDE_OPS}"; then
|
||||
log "Recreating ops.json file at server startup"
|
||||
rm -f /data/ops.json
|
||||
fi
|
||||
|
||||
if [ -n "$WHITELIST" ]; then
|
||||
log "Updating whitelist"
|
||||
rm -f /data/white-list.txt.converted
|
||||
if [[ $WHITELIST == *"-"* ]]; then
|
||||
echo $WHITELIST | awk -v RS=, '{print}' | xargs -l -i curl -s https://playerdb.co/api/player/minecraft/{} | jq -r '.["data"]["player"] | {"uuid": .id, "name": .username}' | jq -s . > "whitelist.json"
|
||||
else
|
||||
echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt
|
||||
fi
|
||||
fi
|
||||
if isTrue "${OVERRIDE_WHITELIST}"; then
|
||||
log "Recreating whitelist.json file at server startup"
|
||||
rm -f /data/whitelist.json
|
||||
fi
|
||||
|
||||
if [ -n "$ICON" ]; then
|
||||
if [ ! -e server-icon.png ] || [ "${OVERRIDE_ICON}" == "TRUE" ]; then
|
||||
log "Using server icon from $ICON..."
|
||||
@@ -19,47 +42,7 @@ if [ -n "$ICON" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
canUseRollingLogs=true
|
||||
useFallbackJvmFlag=false
|
||||
|
||||
patchLog4jConfig() {
|
||||
file=${1?}
|
||||
url=${2?}
|
||||
if ! get -o "$file" "$url"; then
|
||||
log "ERROR: failed to download corrected log4j config, fallback to JVM flag"
|
||||
useFallbackJvmFlag=true
|
||||
return 1
|
||||
fi
|
||||
JVM_OPTS="-Dlog4j.configurationFile=${file} ${JVM_OPTS}"
|
||||
canUseRollingLogs=false
|
||||
}
|
||||
|
||||
# Patch Log4j remote code execution vulnerability
|
||||
# See https://www.minecraft.net/en-us/article/important-message--security-vulnerability-java-edition
|
||||
if versionLessThan 1.7; then
|
||||
: # No patch required here.
|
||||
elif isFamily VANILLA && versionLessThan 1.12; then
|
||||
patchLog4jConfig log4j2_17-111.xml https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml
|
||||
elif isFamily VANILLA && versionLessThan 1.17; then
|
||||
patchLog4jConfig log4j2_112-116.xml https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml
|
||||
# See https://purpurmc.org/docs/Log4j/
|
||||
elif isType PURPUR && versionLessThan 1.17; then
|
||||
patchLog4jConfig purpur_log4j2_1141-1165.xml https://purpurmc.org/docs/xml/purpur_log4j2_1141-1165.xml
|
||||
elif isType PURPUR && versionLessThan 1.18.1; then
|
||||
patchLog4jConfig purpur_log4j2_117.xml https://purpurmc.org/docs/xml/purpur_log4j2_117.xml
|
||||
elif versionLessThan 1.18.1; then
|
||||
useFallbackJvmFlag=true
|
||||
fi
|
||||
|
||||
if ${useFallbackJvmFlag}; then
|
||||
JVM_OPTS="-Dlog4j2.formatMsgNoLookups=true ${JVM_OPTS}"
|
||||
fi
|
||||
|
||||
if isTrue ${ENABLE_ROLLING_LOGS:-false}; then
|
||||
if ! ${canUseRollingLogs}; then
|
||||
log "ERROR: Using rolling logs is currently not possible in the selected version due to CVE-2021-44228"
|
||||
exit 1
|
||||
fi
|
||||
# Set up log configuration
|
||||
LOGFILE="/data/log4j2.xml"
|
||||
if [ ! -e "$LOGFILE" ]; then
|
||||
@@ -87,7 +70,7 @@ if versionLessThan 1.14 && [[ ${CONSOLE,,} = false ]]; then
|
||||
fi
|
||||
|
||||
# Optional disable GUI for headless servers
|
||||
if [[ ${GUI,,} = false ]]; then
|
||||
if [[ ${GUI} = false || ${GUI} = FALSE ]]; then
|
||||
EXTRA_ARGS+=" nogui"
|
||||
fi
|
||||
|
||||
@@ -102,6 +85,26 @@ if [ -n "$JVM_DD_OPTS" ]; then
|
||||
done
|
||||
fi
|
||||
|
||||
patchLog4jConfig() {
|
||||
file=${1?}
|
||||
url=${2?}
|
||||
if ! get -o "$file" "$url"; then
|
||||
log "ERROR: failed to download corrected log4j config"
|
||||
exit 1
|
||||
fi
|
||||
JVM_OPTS="-Dlog4j.configurationFile=${file} ${JVM_OPTS}"
|
||||
}
|
||||
|
||||
# Patch Log4j remote code execution vulnerability
|
||||
# NOTE: Paper, bukkit, and spigot are normalized to SPIGOT
|
||||
if [[ ${TYPE^^} != SPIGOT ]] && versionLessThan 1.12; then
|
||||
patchLog4jConfig log4j2_17-111.xml https://launcher.mojang.com/v1/objects/dd2b723346a8dcd48e7f4d245f6bf09e98db9696/log4j2_17-111.xml
|
||||
elif [[ ${TYPE^^} != SPIGOT ]] && versionLessThan 1.17; then
|
||||
patchLog4jConfig log4j2_112-116.xml https://launcher.mojang.com/v1/objects/02937d122c86ce73319ef9975b58896fc1b491d1/log4j2_112-116.xml
|
||||
elif versionLessThan 1.18.1; then
|
||||
JVM_OPTS="-Dlog4j2.formatMsgNoLookups=true ${JVM_OPTS}"
|
||||
fi
|
||||
|
||||
if isTrue ${ENABLE_JMX}; then
|
||||
: ${JMX_PORT:=7091}
|
||||
JVM_OPTS="${JVM_OPTS}
|
||||
@@ -159,6 +162,12 @@ if isTrue "${USE_AIKAR_FLAGS}"; then
|
||||
"
|
||||
fi
|
||||
|
||||
if isTrue "${USE_LARGE_PAGES}"; then
|
||||
JVM_XX_OPTS="${JVM_XX_OPTS}
|
||||
-XX:+UseLargePagesInMetaspace
|
||||
"
|
||||
fi
|
||||
|
||||
if isTrue "${USE_FLARE_FLAGS}"; then
|
||||
JVM_XX_OPTS="${JVM_XX_OPTS}
|
||||
-XX:+UnlockDiagnosticVMOptions
|
||||
@@ -246,14 +255,10 @@ EOF
|
||||
else
|
||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" "${finalArgs[@]}"
|
||||
fi
|
||||
elif [[ $SERVER =~ run.sh ]]; then
|
||||
elif [[ -x run.sh ]]; then
|
||||
log "Using Forge supplied run.sh script..."
|
||||
echo $JVM_XX_OPTS $JVM_OPTS $expandedDOpts > user_jvm_args.txt
|
||||
if isTrue ${SETUP_ONLY:=false}; then
|
||||
echo "SETUP_ONLY: bash ${SERVER}"
|
||||
exit
|
||||
fi
|
||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" --shell bash "${SERVER}"
|
||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" --shell bash run.sh
|
||||
else
|
||||
# If we have a bootstrap.txt file... feed that in to the server stdin
|
||||
if [ -f /data/bootstrap.txt ]; then
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
: "${REMOVE_OLD_DATAPACKS:=false}"
|
||||
: "${DATAPACKS_FILE:=}"
|
||||
: "${REMOVE_OLD_DATAPACKS_DEPTH:=1} "
|
||||
: "${REMOVE_OLD_DATAPACKS_INCLUDE:=*.zip}"
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
isDebugging && set -x
|
||||
|
||||
out_dir=/data/${LEVEL:-world}/datapacks
|
||||
|
||||
# Remove old datapacks
|
||||
if isTrue "${REMOVE_OLD_DATAPACKS}" && [ -z "${DATAPACKS_FILE}" ]; then
|
||||
if [ -d "$out_dir" ]; then
|
||||
find "$out_dir" -mindepth 1 -maxdepth ${REMOVE_OLD_DATAPACKS_DEPTH:-16} -wholename "${REMOVE_OLD_DATAPACKS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_DATAPACKS_EXCLUDE:-}" -delete
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$DATAPACKS" ]]; then
|
||||
mkdir -p "$out_dir"
|
||||
|
||||
for i in ${DATAPACKS//,/ }
|
||||
do
|
||||
if isURL "$i"; then
|
||||
log "Downloading datapack $i ..."
|
||||
if ! get -o "${out_dir}" "$i"; then
|
||||
log "ERROR: failed to download from $i into $out_dir"
|
||||
exit 2
|
||||
fi
|
||||
elif [[ -f "$i" && "$i" =~ .*\.zip ]]; then
|
||||
log "Copying datapack located at $i ..."
|
||||
out_file=$(basename "$i")
|
||||
if ! cp "$i" "${out_dir}/$out_file"; then
|
||||
log "ERROR: failed to copy from $i into $out_dir"
|
||||
exit 2
|
||||
fi
|
||||
elif [[ -d "$i" ]]; then
|
||||
log "Copying datapacks from $i ..."
|
||||
cp "$i"/*.zip "${out_dir}"
|
||||
else
|
||||
log "ERROR Invalid URL or path given in DATAPACKS: $i"
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
elif [[ "$DATAPACKS_FILE" ]]; then
|
||||
if [ ! -f "$DATAPACKS_FILE" ]; then
|
||||
log "ERROR: given DATAPACKS_FILE file does not exist"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
mkdir -p "$out_dir"
|
||||
|
||||
args=(
|
||||
-o "${out_dir}"
|
||||
--log-progress-each
|
||||
--skip-existing
|
||||
--uris-file "${DATAPACKS_FILE}"
|
||||
)
|
||||
if isTrue "${REMOVE_OLD_DATAPACKS}"; then
|
||||
args+=(
|
||||
--prune-others "${REMOVE_OLD_DATAPACKS_INCLUDE}"
|
||||
--prune-depth "${REMOVE_OLD_DATAPACKS_DEPTH}"
|
||||
)
|
||||
fi
|
||||
|
||||
if ! get "${args[@]}" ; then
|
||||
log "ERROR: failed to retrieve one or more datapacks"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupForgeApiMods" "$@"
|
||||
@@ -32,4 +32,4 @@ if [[ ${PATCH_DEFINITIONS} ]]; then
|
||||
"${PATCH_DEFINITIONS}"
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupRbac" "$@"
|
||||
exec "${SCRIPTS:-/}start-finalExec" "$@"
|
||||
|
||||
@@ -1,221 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
: "${MODS_FORGEAPI_KEY:=}"
|
||||
: "${REMOVE_OLD_FORGEAPI_MODS:=false}"
|
||||
: "${MODS_FORGEAPI_PROJECTIDS:=}"
|
||||
: "${MODS_FORGEAPI_FILE:=}"
|
||||
: "${MODS_FORGEAPI_RELEASES:=RELEASE}"
|
||||
: "${MODS_FORGEAPI_DOWNLOAD_DEPENDENCIES:=false}"
|
||||
: "${REMOVE_OLD_MODS_DEPTH:=1} "
|
||||
: "${REMOVE_OLD_MODS_INCLUDE:=*.jar}"
|
||||
|
||||
# FORGEAPI_BASE_URL used in manifest downloads below
|
||||
FORGEAPI_BASE_URL=${FORGEAPI_BASE_URL:-https://api.curseforge.com/v1}
|
||||
RELEASE_NUMBER_FILTER=1
|
||||
MINECRAFT_GAME_ID=432
|
||||
out_dir=/data/mods
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
isDebugging && set -x
|
||||
|
||||
# Remove old mods/plugins
|
||||
if isTrue "${REMOVE_OLD_FORGEAPI_MODS}" && [ -z "${MODS_FORGEAPI_FILE}" ]; then
|
||||
removeOldMods /data/mods
|
||||
fi
|
||||
|
||||
ensureModKey(){
|
||||
if [ -z "$MODS_FORGEAPI_KEY" ]; then
|
||||
log "ERROR: MODS_FORGEAPI_KEY REQUIRED to Connect to FORGE API, you supplied: ${MODS_FORGEAPI_KEY}"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
# Set the global release type per the text.
|
||||
# NOTE: downcasing release type for comparing types.
|
||||
updateReleaseNumber(){
|
||||
releaseType=$1
|
||||
if [ "release" = "${releaseType,,}" ] || [ 1 = "${releaseType,,}" ]; then
|
||||
RELEASE_NUMBER_FILTER=1
|
||||
elif [ "beta" = "${releaseType,,}" ] || [ 2 = "${releaseType,,}" ]; then
|
||||
RELEASE_NUMBER_FILTER=2
|
||||
elif [ "alpha" = "${releaseType,,}" ] || [ 3 = "${releaseType,,}" ]; then
|
||||
RELEASE_NUMBER_FILTER=3
|
||||
fi
|
||||
}
|
||||
|
||||
retrieveVersionTypeNumber(){
|
||||
VERSION_NAME="Minecraft ${VANILLA_VERSION%.*}"
|
||||
minecraft_types=$(curl -X GET -s \
|
||||
"${FORGEAPI_BASE_URL}/games/${MINECRAFT_GAME_ID}/version-types" \
|
||||
-H 'Accept: application/json' -H 'x-api-key: '${MODS_FORGEAPI_KEY}'')
|
||||
|
||||
if [ ! "$minecraft_types" ]; then
|
||||
log "ERROR: unable to retrieve version types for ${VERSION_NAME} from ForgeAPI. Check Forge API key or supplied Minecraft version"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
TYPE_ID=$(jq -n "$minecraft_types" | jq --arg VERSION_NAME "$VERSION_NAME" -jc '
|
||||
.data[]? | select(.name==$VERSION_NAME) | .id')
|
||||
|
||||
if [ ! "$TYPE_ID" ]; then
|
||||
log "ERROR: unable to retrieve version types for ${VERSION_NAME} from ForgeAPI"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
modFileByProjectID(){
|
||||
project_id=$(echo $1 | tr -d '"')
|
||||
project_id_release_type=$2
|
||||
project_id_file_name=$3
|
||||
unset PROJECT_FILE
|
||||
|
||||
# if Type id isn't defined use minecraft version to go get it.
|
||||
if [ ! "$TYPE_ID" ]; then
|
||||
retrieveVersionTypeNumber
|
||||
fi
|
||||
|
||||
# JQ is struggling with larger page sizes so having to pagination for mods with a lot of releases
|
||||
pageSize=42
|
||||
index=0
|
||||
total_count=1
|
||||
|
||||
while [ $index -lt $total_count ]; do
|
||||
project_files=$(curl -X GET -s \
|
||||
"${FORGEAPI_BASE_URL}/mods/${project_id}/files?gameVersionTypeId=${TYPE_ID}&index=${index}&pageSize=${pageSize}" \
|
||||
-H 'Accept: application/json' -H 'x-api-key: '${MODS_FORGEAPI_KEY}'')
|
||||
|
||||
if [ ! "$project_files" ]; then
|
||||
log "ERROR: unable to retrieve any project id files for ${project_id} from ForgeAPI"
|
||||
exit 2
|
||||
fi
|
||||
# Use project files to grab out the total count of mods.
|
||||
total_count=$(jq -n "$project_files" | jq -c '.pagination.totalCount' )
|
||||
|
||||
# Checking for a individual release type input, if not use global
|
||||
if [ $project_id_release_type ]; then
|
||||
updateReleaseNumber $project_id_release_type
|
||||
else
|
||||
updateReleaseNumber $MODS_FORGEAPI_RELEASES
|
||||
fi
|
||||
# grabs the highest ID of the releaseTypes selected.
|
||||
# Default is 1 for Release, Beta is 2, and Alpha is 3. Using less than we can validate highest release.
|
||||
if [ $project_id_file_name ]; then
|
||||
current_project_file=$(jq -n "$project_files" | jq --arg FILE_NAME "$project_id_file_name" -jc '
|
||||
.data | map(select(.fileName<=($FILE_NAME))) | .[0]')
|
||||
else
|
||||
current_project_file=$(jq -n "$project_files" | jq --arg RELEASE_FILTER "$RELEASE_NUMBER_FILTER" -jc '
|
||||
.data | sort_by(.id) | reverse | map(select(.releaseType<=($RELEASE_FILTER|tonumber))) | .[0]')
|
||||
fi
|
||||
# Logic to grab the latest release over the entire pagination
|
||||
if [ ! "$PROJECT_FILE" ]; then
|
||||
PROJECT_FILE=$current_project_file
|
||||
elif [ "$current_project_file" ]; then
|
||||
current_project_file_id=$(jq -n "$current_project_file" | jq -jc '.id' )
|
||||
PROJECT_FILE_ID=$(jq -n "$PROJECT_FILE" | jq -jc '.id' )
|
||||
if (( current_project_file_id > PROJECT_FILE_ID )); then
|
||||
PROJECT_FILE=$current_project_file
|
||||
fi
|
||||
fi
|
||||
|
||||
# check to see if we have gone to far or lost our index and exit with an error
|
||||
if [ -z "$index" ] || [ -z "$total_count" ] || [ $index -ge $total_count ]; then
|
||||
log "ERROR: Unable to retrieve any files for ${project_id} from ForgeAPI also Validate files have release type associated with no. ${RELEASE_NUMBER_FILTER}"
|
||||
exit 2
|
||||
fi
|
||||
# Increment start index to new set.
|
||||
index=$(($index + $pageSize))
|
||||
done
|
||||
}
|
||||
|
||||
downloadModPackfromModFile() {
|
||||
if [ ! "$PROJECT_FILE" ]; then
|
||||
log "ERROR: Project File not found from the ForgeAPI"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# grabs needed values from our json return
|
||||
file_name=$(jq -n "$PROJECT_FILE" | jq -jc '.fileName' )
|
||||
download_url=$(jq -n "$PROJECT_FILE" | jq -jc '.downloadUrl' )
|
||||
|
||||
# trys to make the output directory incase it doesnt exist.
|
||||
mkdir -p "$out_dir"
|
||||
echo "Downloading ${download_url}"
|
||||
if ! get -o "${out_dir}/${file_name}" $download_url ; then
|
||||
log "ERROR: failed to download from ${download_url}"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
downloadDependencies(){
|
||||
if [ "$PROJECT_FILE" ]; then
|
||||
dependencies=$(jq -n "$PROJECT_FILE" | jq -jc '.dependencies' )
|
||||
required_dependencies=$(jq -n "$dependencies" | jq --arg REQUIRED_FILTER "3" -jc '
|
||||
map(select(.relationType==($REQUIRED_FILTER|tonumber)))')
|
||||
if [ "$required_dependencies" ]; then
|
||||
jq -n "$required_dependencies" | jq -c '.[]?' | while read current_dependency; do
|
||||
mod_id=$(jq -n "$current_dependency" | jq -jc '.modId' )
|
||||
|
||||
# BROKEN: Example Voice mod keeps returning the voice mod file id instead of the mod file id.
|
||||
# file_id=$(jq -n "$current_dependency" | jq -jc '.fileId' )
|
||||
# dependency_data=$(curl -X GET -s \
|
||||
# "${FORGEAPI_BASE_URL}/mods/${mod_id}/files/${file_id}/download-url" \
|
||||
# -H 'Accept: application/json' -H 'x-api-key: '${MODS_FORGEAPI_KEY}'')
|
||||
# if [ ! "$dependency_data" ]; then
|
||||
# log "ERROR: unable to retrieve dependency data files for ${project_id} from ForgeAPI"
|
||||
# exit 2
|
||||
# fi
|
||||
# dependency_download_url=$(jq -n "$dependency_data" | jq -jc '.data' )
|
||||
# echo "Downloading dependency ${dependency_download_url}"
|
||||
# if ! get -o "${out_dir}/" $dependency_download_url ; then
|
||||
# log "ERROR: failed to download dependency from ${dependency_download_url}"
|
||||
# exit 2
|
||||
# fi
|
||||
|
||||
# Using current mod path and release to go get the REQUIRED DEPENDENCY
|
||||
# NOTE: we are ASUMING it will be release.
|
||||
modFileByProjectID $mod_id "release"
|
||||
downloadModPackfromModFile
|
||||
done
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Use forge api json file to filter and download the correct mods
|
||||
if [ "$MODS_FORGEAPI_FILE" ] && [ -z "$MODS_FORGEAPI_PROJECTIDS" ]; then
|
||||
ensureModKey
|
||||
if [ ! -f "$MODS_FORGEAPI_FILE" ]; then
|
||||
log "ERROR: given MODS_FORGEAPI_FILE file does not exist"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Needs loop here to look up release types befor calling download.
|
||||
jq -n "$required_dependencies" | jq -c '.[]?' | while read current_project; do
|
||||
# Per stack overflow we can use //empty to return empty string that works with -z
|
||||
project_id=$(jq -n "$current_project" | jq -jc '.projectId // empty' )
|
||||
current_release_type=$(jq -n "$current_project" | jq -jc '.releaseType // empty' )
|
||||
current_file_name=$(jq -n "$current_project" | jq -jc '.fileName // empty' )
|
||||
|
||||
modFileByProjectID $project_id $current_release_type $current_file_name
|
||||
downloadModPackfromModFile
|
||||
if isTrue "${MODS_FORGEAPI_DOWNLOAD_DEPENDENCIES}"; then
|
||||
downloadDependencies
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Use only project ids and global release data.
|
||||
if [ "$MODS_FORGEAPI_PROJECTIDS" ] && [ -z "$MODS_FORGEAPI_FILE" ]; then
|
||||
ensureModKey
|
||||
for project_id in ${MODS_FORGEAPI_PROJECTIDS//,/ }; do
|
||||
modFileByProjectID $project_id
|
||||
downloadModPackfromModFile
|
||||
if isTrue "${MODS_FORGEAPI_DOWNLOAD_DEPENDENCIES}"; then
|
||||
downloadDependencies
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupModpack" "$@"
|
||||
@@ -1,7 +1,6 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
# If supplied with a URL for a config (simple zip of configurations), download it and unpack
|
||||
if [[ "$MODCONFIG" ]]; then
|
||||
@@ -10,7 +9,7 @@ case "X$MODCONFIG" in
|
||||
log "Downloading mod/plugin configs via HTTP"
|
||||
log " from $MODCONFIG ..."
|
||||
curl -sSL -o /tmp/modconfig.zip "$MODCONFIG"
|
||||
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
mkdir -p /data/plugins
|
||||
unzip -o -d /data/plugins /tmp/modconfig.zip
|
||||
else
|
||||
@@ -25,4 +24,4 @@ case "X$MODCONFIG" in
|
||||
esac
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupMounts" "$@"
|
||||
exec ${SCRIPTS:-/}start-setupMounts $@
|
||||
|
||||
@@ -6,7 +6,6 @@ set -e -o pipefail
|
||||
: "${MODS_FILE:=}"
|
||||
: "${REMOVE_OLD_MODS_DEPTH:=1} "
|
||||
: "${REMOVE_OLD_MODS_INCLUDE:=*.jar}"
|
||||
sum_file=/data/.generic_pack.sum
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
@@ -19,17 +18,16 @@ CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
|
||||
if isTrue "${REMOVE_OLD_MODS}" && [ -z "${MODS_FILE}" ]; then
|
||||
removeOldMods /data/mods
|
||||
removeOldMods /data/plugins
|
||||
rm -f "$sum_file"
|
||||
fi
|
||||
|
||||
# If packwiz url passed, bootstrap packwiz and update mods before other modpack processing
|
||||
if [[ "${PACKWIZ_URL}" ]]; then
|
||||
# Ensure we have the latest packwiz bootstrap installer
|
||||
latestPackwiz=$(curl -fsSL https://api.github.com/repos/packwiz/packwiz-installer-bootstrap/releases/latest)
|
||||
latestPackwiz=$(curl -fsSL https://api.github.com/repos/comp500/packwiz-installer-bootstrap/releases/latest)
|
||||
if [[ -z "${latestPackwiz}" ]]; then
|
||||
log "WARNING: Could not retrieve Packwiz bootstrap installer release information"
|
||||
else
|
||||
isDebugging && log "Latest packwiz ${latestPackwiz}"
|
||||
isDebugging && log "Latest packwiz ${latestPackWiz}"
|
||||
latestPackwizVer=$(echo ${latestPackwiz} | jq --raw-output '.tag_name')
|
||||
latestPackwizUrl=$(echo ${latestPackwiz} | jq --raw-output '.assets[] | select(.name | match("packwiz-installer-bootstrap.jar")) | .url')
|
||||
: "${PACKWIZ_JAR:=packwiz-installer-bootstrap_${latestPackwizVer}.jar}"
|
||||
@@ -67,7 +65,7 @@ if [[ "$MODPACK" ]]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
mkdir -p /data/plugins
|
||||
if ! unzip -o -d /data/plugins /tmp/modpack.zip; then
|
||||
log "ERROR: failed to unzip the modpack from ${MODPACK}"
|
||||
@@ -81,7 +79,7 @@ if [[ "$MODPACK" ]]; then
|
||||
rm -f /tmp/modpack.zip
|
||||
|
||||
elif [[ "$MODS" ]]; then
|
||||
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
out_dir=/data/plugins
|
||||
else
|
||||
out_dir=/data/mods
|
||||
@@ -92,7 +90,7 @@ elif [[ "$MODS" ]]; then
|
||||
do
|
||||
if isURL "$i"; then
|
||||
log "Downloading mod/plugin $i ..."
|
||||
if ! get --skip-up-to-date -o "${out_dir}" "$i"; then
|
||||
if ! get -o "${out_dir}" "$i"; then
|
||||
log "ERROR: failed to download from $i into $out_dir"
|
||||
exit 2
|
||||
fi
|
||||
@@ -118,7 +116,7 @@ elif [[ "$MODS_FILE" ]]; then
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
out_dir=/data/plugins
|
||||
else
|
||||
out_dir=/data/mods
|
||||
@@ -128,7 +126,7 @@ elif [[ "$MODS_FILE" ]]; then
|
||||
args=(
|
||||
-o "${out_dir}"
|
||||
--log-progress-each
|
||||
--skip-up-to-date
|
||||
--skip-existing
|
||||
--uris-file "${MODS_FILE}"
|
||||
)
|
||||
if isTrue "${REMOVE_OLD_MODS}"; then
|
||||
@@ -188,19 +186,15 @@ esac
|
||||
fi
|
||||
|
||||
: "${GENERIC_PACKS:=${GENERIC_PACK}}"
|
||||
: "${GENERIC_PACKS_PREFIX:=}"
|
||||
: "${GENERIC_PACKS_SUFFIX:=}"
|
||||
|
||||
if [[ "${GENERIC_PACKS}" ]]; then
|
||||
IFS=',' read -ra packs <<< "${GENERIC_PACKS}"
|
||||
|
||||
packFiles=()
|
||||
for packEntry in "${packs[@]}"; do
|
||||
pack="${GENERIC_PACKS_PREFIX}${packEntry}${GENERIC_PACKS_SUFFIX}"
|
||||
if isURL "${pack}"; then
|
||||
for pack in "${packs[@]}"; do
|
||||
if isURL "$pack"; then
|
||||
mkdir -p /data/packs
|
||||
log "Downloading generic pack from $pack"
|
||||
if ! outfile=$(get -o /data/packs --output-filename --skip-up-to-date "$pack"); then
|
||||
if ! outfile=$(get -o /data/packs --output-filename --skip-existing "$pack"); then
|
||||
log "ERROR: failed to download $pack"
|
||||
exit 2
|
||||
fi
|
||||
@@ -210,19 +204,14 @@ if [[ "${GENERIC_PACKS}" ]]; then
|
||||
fi
|
||||
done
|
||||
|
||||
sum_file=/data/.generic_pack.sum
|
||||
isDebugging && [ -f "$sum_file}" ] && cat "$sum_file"
|
||||
|
||||
log "Checking if generic packs are up to date"
|
||||
if isTrue "${SKIP_GENERIC_PACK_UPDATE_CHECK:-false}" && [ -f "$sum_file" ]; then
|
||||
log "Skipping generic pack update check"
|
||||
elif isTrue "${FORCE_GENERIC_PACK_UPDATE}" || ! checkSum "${sum_file}"; then
|
||||
log "Generic pack(s) are out of date. Re-applying..."
|
||||
|
||||
if ! sha256sum -c "${sum_file}" --status 2> /dev/null; then
|
||||
base_dir=/tmp/generic_pack_base
|
||||
mkdir -p ${base_dir}
|
||||
for pack in "${packFiles[@]}"; do
|
||||
isDebugging && ls -l "${pack}"
|
||||
extract "${pack}" "${base_dir}"
|
||||
unzip -q -d ${base_dir} "${pack}"
|
||||
done
|
||||
|
||||
# recalculate the actual base directory of content
|
||||
@@ -250,8 +239,7 @@ if [[ "${GENERIC_PACKS}" ]]; then
|
||||
cp -R -f "${base_dir}"/* /data
|
||||
rm -rf /tmp/generic_pack_base
|
||||
|
||||
log "Saving generic pack(s) checksum"
|
||||
sha1sum "${packFiles[@]}" > "${sum_file}"
|
||||
sha256sum "${packFiles[@]}" > "${sum_file}"
|
||||
isDebugging && cat "$sum_file"
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
. ${SCRIPTS:-/}start-utils
|
||||
|
||||
: "${SYNC_SKIP_NEWER_IN_DESTINATION:=${PLUGINS_SYNC_UPDATE:-true}}"
|
||||
: "${REPLACE_ENV_DURING_SYNC:=true}"
|
||||
: "${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}"
|
||||
: "${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}"
|
||||
: "${REPLACE_ENV_VARIABLES_EXCLUDES:=}"
|
||||
: "${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}"
|
||||
: "${DEBUG:=false}"
|
||||
: ${SYNC_SKIP_NEWER_IN_DESTINATION:=${PLUGINS_SYNC_UPDATE:-true}}
|
||||
: ${REPLACE_ENV_DURING_SYNC:=true}
|
||||
: ${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}
|
||||
: ${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}
|
||||
: ${REPLACE_ENV_VARIABLES_EXCLUDES:=}
|
||||
: ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}
|
||||
: ${DEBUG:=false}
|
||||
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
@@ -25,8 +24,8 @@ else
|
||||
fi
|
||||
|
||||
if [ -d /plugins ]; then
|
||||
case ${FAMILY} in
|
||||
SPIGOT|HYBRID)
|
||||
case ${TYPE} in
|
||||
SPIGOT|BUKKIT|PAPER|MAGMA)
|
||||
mkdir -p /data/plugins
|
||||
log "Copying plugins over..."
|
||||
mc-image-helper \
|
||||
@@ -41,7 +40,7 @@ if [ -d /plugins ]; then
|
||||
fi
|
||||
|
||||
# If any modules have been provided, copy them over
|
||||
: "${COPY_MODS_DEST:="/data/mods"}"
|
||||
: ${COPY_MODS_DEST:="/data/mods"}
|
||||
|
||||
if [ -d /mods ]; then
|
||||
log "Copying any mods over..."
|
||||
@@ -54,7 +53,7 @@ if [ -d /mods ]; then
|
||||
/mods "${COPY_MODS_DEST}"
|
||||
fi
|
||||
|
||||
: "${COPY_CONFIG_DEST:="/data/config"}"
|
||||
: ${COPY_CONFIG_DEST:="/data/config"}
|
||||
|
||||
if [ -d /config ]; then
|
||||
log "Copying any configs from /config to ${COPY_CONFIG_DEST}"
|
||||
@@ -67,4 +66,4 @@ if [ -d /config ]; then
|
||||
/config "${COPY_CONFIG_DEST}"
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupServerProperties" "$@"
|
||||
exec ${SCRIPTS:-/}start-setupServerProperties $@
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
isDebugging && set -x
|
||||
|
||||
if versionLessThan 1.7.6; then
|
||||
opsFile=ops.txt
|
||||
whitelistFile=white-list.txt
|
||||
else
|
||||
opsFile=ops.json
|
||||
whitelistFile=whitelist.json
|
||||
fi
|
||||
|
||||
function process_user_file() {
|
||||
local output=$1
|
||||
local source=$2
|
||||
|
||||
if isURL "$source"; then
|
||||
log "Downloading $output from $source"
|
||||
if ! get -o "/data/$output" "$source"; then
|
||||
log "ERROR: failed to download from $source"
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
log "Copying $output from $source"
|
||||
if ! cp "$source" "/data/$output"; then
|
||||
log "ERROR: failed to copy from $source"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function process_user_csv() {
|
||||
local output=$1
|
||||
local list=$2
|
||||
local playerDataList
|
||||
|
||||
if [[ "$output" == *"ops"* ]]; then
|
||||
# Extra data for ops.json
|
||||
userData='{"uuid": .id, "name": .username, "level": 4}'
|
||||
else
|
||||
userData='{"uuid": .id, "name": .username}'
|
||||
fi
|
||||
|
||||
log "Updating ${output%.*}"
|
||||
for i in ${list//,/ }
|
||||
do
|
||||
if [ -e "$output" ] && grep -q "$i" "$output"; then
|
||||
log "$i already present in $output, skipping"
|
||||
continue
|
||||
fi
|
||||
if ! playerData=$(get "https://playerdb.co/api/player/minecraft/$i" | jq -re ".data.player"); then
|
||||
log "WARNING: Could not lookup user $i for ${output} addition"
|
||||
else
|
||||
playerDataList=$playerDataList$(echo "$playerData" | jq -r "$userData")
|
||||
fi
|
||||
done
|
||||
local newUsers=$(echo "$playerDataList" | jq -s .)
|
||||
if [[ $output =~ .*\.txt ]]; then
|
||||
# username list for txt config (Minecraft <= 1.7.5)
|
||||
echo $newUsers | jq -r '.[].name' >> "/data/${output}"
|
||||
sort -u /data/${output} -o /data/${output}
|
||||
elif [ -e /data/${output} ]; then
|
||||
# Merge with existing json file
|
||||
local currentUsers=$(cat "/data/${output}")
|
||||
jq --argjson current "$currentUsers" --argjson new "$newUsers" -n '$new + $current | unique_by(.uuid)' > "/data/${output}"
|
||||
else
|
||||
# New json file
|
||||
echo $newUsers > "/data/${output}"
|
||||
fi
|
||||
}
|
||||
|
||||
if isTrue "${OVERRIDE_OPS}"; then
|
||||
log "Recreating ${opsFile} file at server startup"
|
||||
rm -f /data/${opsFile}
|
||||
fi
|
||||
if [ -n "${OPS_FILE}" ] && [ ! -e "/data/${opsFile}" ]; then
|
||||
process_user_file ${opsFile} "$OPS_FILE"
|
||||
fi
|
||||
if [ -n "${OPS}" ]; then
|
||||
process_user_csv ${opsFile} "$OPS"
|
||||
fi
|
||||
|
||||
if isTrue "${OVERRIDE_WHITELIST}"; then
|
||||
log "Recreating ${whitelistFile} file at server startup"
|
||||
rm -f /data/${whitelistFile}
|
||||
fi
|
||||
if [ -n "${WHITELIST_FILE}" ] && [ ! -e "/data/${whitelistFile}" ]; then
|
||||
process_user_file ${whitelistFile} "$WHITELIST_FILE"
|
||||
fi
|
||||
if [ -n "${WHITELIST}" ]; then
|
||||
process_user_csv ${whitelistFile} "$WHITELIST"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
exec "${SCRIPTS:-/}start-finalExec" "$@"
|
||||
@@ -33,22 +33,19 @@ function setServerProp {
|
||||
}
|
||||
|
||||
function customizeServerProps {
|
||||
# Whitelist processing
|
||||
if [ -n "$WHITELIST" ] || [ -n "$WHITELIST_FILE" ] || isTrue "${ENABLE_WHITELIST:-false}"; then
|
||||
log "Enabling whitelist functionality"
|
||||
if [ -n "$WHITELIST" ] || isTrue "${ENABLE_WHITELIST:-false}"; then
|
||||
log "Creating whitelist"
|
||||
setServerPropValue "whitelist" "true"
|
||||
setServerPropValue "white-list" "true"
|
||||
else
|
||||
log "Disabling whitelist functionality"
|
||||
log "Disabling whitelist"
|
||||
setServerPropValue "whitelist" "false"
|
||||
setServerPropValue "white-list" "false"
|
||||
fi
|
||||
setServerProp "enforce-whitelist" ENFORCE_WHITELIST
|
||||
if [[ $(grep "enforce-whitelist" $SERVER_PROPERTIES) != *true ]]; then
|
||||
log "WARNING: whitelist enabled but not enforced. Set ENFORCE_WHITELIST=TRUE or update 'enforce-whitelist' in server.properties to enforce the whitelist."
|
||||
fi
|
||||
|
||||
# If not provided, generate a reasonable default message-of-the-day,
|
||||
# which shows up in the server listing in the client
|
||||
if ! [ -v MOTD ]; then
|
||||
if [ -z "$MOTD" ]; then
|
||||
# snapshot is the odd case where we have to look at version to identify that label
|
||||
if [[ ${ORIGINAL_TYPE} == "VANILLA" && ${VERSION} == "SNAPSHOT" ]]; then
|
||||
label=SNAPSHOT
|
||||
@@ -62,13 +59,6 @@ function customizeServerProps {
|
||||
MOTD="A ${label} Minecraft Server powered by Docker"
|
||||
fi
|
||||
|
||||
# normalize MOTD
|
||||
if [[ ${TYPE^^} = LIMBO ]]; then
|
||||
if [[ $MOTD ]] && ! [[ $MOTD =~ ^{ ]]; then
|
||||
MOTD="{\"text\":\"${MOTD}\"}"
|
||||
fi
|
||||
fi
|
||||
|
||||
setServerProp "server-name" SERVER_NAME
|
||||
setServerProp "server-ip" SERVER_IP
|
||||
setServerProp "server-port" SERVER_PORT
|
||||
@@ -114,6 +104,7 @@ function customizeServerProps {
|
||||
setServerProp "op-permission-level" OP_PERMISSION_LEVEL
|
||||
setServerProp "prevent-proxy-connections" PREVENT_PROXY_CONNECTIONS
|
||||
setServerProp "use-native-transport" USE_NATIVE_TRANSPORT
|
||||
setServerProp "enforce-whitelist" ENFORCE_WHITELIST
|
||||
setServerProp "simulation-distance" SIMULATION_DISTANCE
|
||||
setServerPropValue "motd" "$(echo "$MOTD" | mc-image-helper asciify)"
|
||||
[[ $LEVEL_TYPE ]] && setServerPropValue "level-type" "${LEVEL_TYPE^^}"
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -o pipefail
|
||||
|
||||
: "${REMOVE_OLD_VANILLATWEAKS:=false}"
|
||||
: "${VANILLATWEAKS_FILE:=}"
|
||||
: "${VANILLATWEAKS_SHARECODE:=}"
|
||||
: "${REMOVE_OLD_VANILLATWEAKS_DEPTH:=1} "
|
||||
: "${REMOVE_OLD_VANILLATWEAKS_INCLUDE:=*.zip}"
|
||||
|
||||
# shellcheck source=start-utils
|
||||
. "${SCRIPTS:-/}start-utils"
|
||||
isDebugging && set -x
|
||||
|
||||
VT_VERSION=""
|
||||
DATAPACKS_DIR="/data/${LEVEL:-world}/datapacks"
|
||||
RESOURCEPACKS_DIR="/data/resourcepacks"
|
||||
|
||||
# Remove old VANILLATWEAKS
|
||||
if isTrue "${REMOVE_OLD_VANILLATWEAKS}"; then
|
||||
# NOTE: datapacks include crafting tweaks.
|
||||
if [ -d "$DATAPACKS_DIR" ]; then
|
||||
find "$DATAPACKS_DIR" -mindepth 1 -maxdepth ${REMOVE_OLD_VANILLATWEAKS_DEPTH:-16} -wholename "${REMOVE_OLD_VANILLATWEAKS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_VANILLATWEAKS_EXCLUDE:-}" -delete
|
||||
fi
|
||||
if [ -d "$RESOURCEPACKS_DIR" ]; then
|
||||
find "$RESOURCEPACKS_DIR" -mindepth 1 -maxdepth ${REMOVE_OLD_VANILLATWEAKS_DEPTH:-16} -wholename "${REMOVE_OLD_VANILLATWEAKS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_VANILLATWEAKS_EXCLUDE:-}" -delete
|
||||
fi
|
||||
fi
|
||||
|
||||
# Gets the download url and downloads the actual files.
|
||||
getUrlAndDownload(){
|
||||
VT_FILE=$1
|
||||
URL_SUFFIX=$2
|
||||
OUTPUT_FILE=$3
|
||||
PACKS=$(jq -jc '.packs // empty' $VT_FILE)
|
||||
if [ ! "$PACKS" ]; then
|
||||
log "ERROR: unable to retrieve ${URL_SUFFIX} from ${VT_FILE}"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
ZIPDATA_URL="https://vanillatweaks.net/assets/server/zip${URL_SUFFIX}.php"
|
||||
DOWNLOAD_URL=$(curl -X POST -F "packs=${PACKS}" -F "version=${VT_VERSION}" $ZIPDATA_URL | jq -r '.link // empty')
|
||||
if [ ! "$DOWNLOAD_URL" ]; then
|
||||
log "ERROR: unable to retrieve ${URL_SUFFIX} packs from vanillatweaks.net!"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if ! get -o $OUTPUT_FILE "https://vanillatweaks.net${DOWNLOAD_URL}"; then
|
||||
log "ERROR: failed to download ${URL_SUFFIX} from ${DOWNLOAD_URL}"
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
# Datapacks Handler
|
||||
downloadDatapacks(){
|
||||
VT_FILE=$1
|
||||
URL_SUFFIX="datapacks"
|
||||
OUTPUT_FILE="/tmp/vanillatweaks.zip"
|
||||
getUrlAndDownload $VT_FILE $URL_SUFFIX $OUTPUT_FILE
|
||||
mkdir -p "$DATAPACKS_DIR"
|
||||
if ! unzip -o -d "$DATAPACKS_DIR" $OUTPUT_FILE; then
|
||||
log "ERROR: failed to unzip the datapacks ${DATAPACKS} from ${OUTPUT_FILE}"
|
||||
fi
|
||||
rm -f $OUTPUT_FILE
|
||||
}
|
||||
|
||||
# Crafting Tweaks Handler
|
||||
downloadCraftingtweaks(){
|
||||
VT_FILE=$1
|
||||
mkdir -p "$DATAPACKS_DIR"
|
||||
getUrlAndDownload $VT_FILE "craftingtweaks" "${DATAPACKS_DIR}/craftingtweaks.zip"
|
||||
}
|
||||
|
||||
# Resourcepacks Handler
|
||||
downloadResourcepacks(){
|
||||
VT_FILE=$1
|
||||
mkdir -p "$RESOURCEPACKS_DIR"
|
||||
getUrlAndDownload $VT_FILE "resourcepacks" "${RESOURCEPACKS_DIR}/resourcepacks.zip"
|
||||
}
|
||||
|
||||
# Example: VANILLATWEAKS_SHARECODE=MGr52E
|
||||
# Code generated from the UI website, typically a alphanumeric 6 digit code.
|
||||
if [[ "$VANILLATWEAKS_SHARECODE" ]]; then
|
||||
VANILLATWEAKS_FILE=()
|
||||
for SHARECODE in ${VANILLATWEAKS_SHARECODE//,/ }; do
|
||||
TMP_FILE="/tmp/${SHARECODE}.json"
|
||||
SHARECODE_LOOKUP_URL="https://vanillatweaks.net/assets/server/sharecode.php?code=${SHARECODE}"
|
||||
if ! get -o "$TMP_FILE" "$SHARECODE_LOOKUP_URL"; then
|
||||
log "ERROR: Unable to use ${SHARECODE} share code provided to retrieve vanillatweaks file"
|
||||
exit 2
|
||||
fi
|
||||
VANILLATWEAKS_FILE+="${TMP_FILE},"
|
||||
done
|
||||
fi
|
||||
|
||||
# Use vanillatweaks file to specify VT and datapacks and crafting tweaks
|
||||
if [[ "$VANILLATWEAKS_FILE" ]]; then
|
||||
for VT_FILE in ${VANILLATWEAKS_FILE//,/ }; do
|
||||
if [ ! -f "$VT_FILE" ]; then
|
||||
log "ERROR: given VANILLATWEAKS_FILE file does not exist"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
VT_VERSION=$(jq -jc '.version // empty' $VT_FILE)
|
||||
if [ ! "$VT_VERSION" ]; then
|
||||
log "ERROR: unable to retrieve version from $VT_FILE"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
TYPE=$(jq -jc '.type // empty' $VT_FILE)
|
||||
if [[ "$TYPE" = "datapacks" ]]; then
|
||||
downloadDatapacks $VT_FILE
|
||||
elif [[ "$TYPE" = "craftingtweaks" ]]; then
|
||||
downloadCraftingtweaks $VT_FILE
|
||||
elif [[ "$TYPE" = "resourcepacks" ]]; then
|
||||
downloadResourcepacks $VT_FILE
|
||||
fi
|
||||
|
||||
# cleans up temp vanilla tweaks file download to get stored packs
|
||||
if [[ "$VANILLATWEAKS_SHARECODE" ]]; then
|
||||
rm -f $VT_FILE
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupDatapack" "$@"
|
||||
@@ -5,7 +5,7 @@
|
||||
set -e
|
||||
isDebugging && set -x
|
||||
|
||||
if [ "$TYPE" = "CURSEFORGE" ]; then
|
||||
if [ $TYPE = "CURSEFORGE" ]; then
|
||||
worldDest=$FTB_DIR/${LEVEL:-world}
|
||||
else
|
||||
worldDest=/data/${LEVEL:-world}
|
||||
@@ -19,102 +19,49 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
|
||||
"${worldDest}_the_end"
|
||||
fi
|
||||
|
||||
if isURL "$WORLD"; then
|
||||
log "Downloading world from $WORLD"
|
||||
if ! get -o /tmp/world.bin "$WORLD"; then
|
||||
log "ERROR: failed to download world from $WORLD"
|
||||
exit 1
|
||||
fi
|
||||
WORLD=/tmp/world.bin
|
||||
if isURL $WORLD; then
|
||||
curl -fsSL "$WORLD" -o /tmp/world.zip
|
||||
zipSrc=/tmp/world.zip
|
||||
elif [[ "$WORLD" =~ .*\.zip ]]; then
|
||||
zipSrc="$WORLD"
|
||||
fi
|
||||
|
||||
if [ -f "$WORLD" ]; then
|
||||
log "Extracting world"
|
||||
if [[ "$zipSrc" ]]; then
|
||||
log "Unzipping world"
|
||||
|
||||
# Stage contents so that the correct subdirectory can be picked off
|
||||
mkdir -p /tmp/world-data
|
||||
if ! extract "$WORLD" /tmp/world-data; then
|
||||
exit 1
|
||||
fi
|
||||
(cd /tmp/world-data && unzip -o -q "$zipSrc")
|
||||
|
||||
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
|
||||
|
||||
if ! [[ $baseDirs ]]; then
|
||||
log "ERROR world content is not valid since level.dat could not be found"
|
||||
exit 2
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
baseDirs=$(find /tmp/world-data -name "level.dat" -not -path "*_nether*" -not -path "*_the_end*" -exec dirname "{}" \;)
|
||||
else
|
||||
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
|
||||
fi
|
||||
|
||||
count=$(echo "$baseDirs" | wc -l)
|
||||
if [[ $count -gt 1 ]]; then
|
||||
baseDirsNoSpigotSuffix=$(echo "$baseDirs" | sed -re 's:(_nether|_the_end)/?$::' | sort -u)
|
||||
if [ $(echo "$baseDirsNoSpigotSuffix" | wc -l) -eq 1 ]; then
|
||||
baseDir="$baseDirsNoSpigotSuffix"
|
||||
baseName=$(basename "$baseDir")
|
||||
log "Found Spigot naming conventions, taking $baseName as main dimension"
|
||||
else
|
||||
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
|
||||
baseName=$(basename "$baseDir")
|
||||
log "WARN multiple levels found, picking: $baseName"
|
||||
fi
|
||||
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
|
||||
baseName=$(basename "$baseDir")
|
||||
log "WARN multiple levels found, picking: $baseName"
|
||||
elif [[ $count -gt 0 ]]; then
|
||||
baseDir="$baseDirs"
|
||||
else
|
||||
log "ERROR invalid world content"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -d "${baseDir}_nether/DIM-1" ]; then
|
||||
if [ -d "$baseDir/DIM-1" ]; then
|
||||
log "WARN found Nether dimension in both $baseDir and ${baseDir}_nether, picking ${baseDir}_nether"
|
||||
rm -r "$baseDir/DIM-1"
|
||||
fi
|
||||
fi
|
||||
if [ -d "${baseDir}_the_end/DIM1" ]; then
|
||||
if [ -d "$baseDir/DIM1" ]; then
|
||||
log "WARN found End dimension in both $baseDir and ${baseDir}_the_end, picking ${baseDir}_the_end"
|
||||
rm -r "$baseDir/DIM1"
|
||||
fi
|
||||
fi
|
||||
|
||||
log "Copying world..."
|
||||
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest"
|
||||
|
||||
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||
if [ -d "${baseDir}_nether" ]; then
|
||||
log "Copying Spigot Nether..."
|
||||
rsync --remove-source-files --recursive --delete "${baseDir}_nether/" "${worldDest}_nether"
|
||||
elif [ -d "$worldDest/DIM-1" ]; then
|
||||
log "Moving Nether to Spigot location..."
|
||||
mkdir -p "${worldDest}_nether"
|
||||
mv -f "$worldDest/DIM-1" "${worldDest}_nether/"
|
||||
fi
|
||||
if [ -d "${baseDir}_the_end" ]; then
|
||||
log "Copying Spigot End..."
|
||||
rsync --remove-source-files --recursive --delete "${baseDir}_the_end/" "${worldDest}_the_end"
|
||||
elif [ -d "$worldDest/DIM1" ]; then
|
||||
log "Moving End to Spigot location..."
|
||||
mkdir -p "${worldDest}_the_end"
|
||||
mv -f "$worldDest/DIM1" "${worldDest}_the_end/"
|
||||
fi
|
||||
else
|
||||
if [ -d "${baseDir}_nether/DIM-1" ]; then
|
||||
log "Copying Spigot Nether to vanilla location..."
|
||||
rsync --remove-source-files --recursive --delete "${baseDir}_nether/DIM-1" "${worldDest}/"
|
||||
fi
|
||||
if [ -d "${baseDir}_the_end/DIM1" ]; then
|
||||
log "Copying Spigot End to vanilla location..."
|
||||
rsync --remove-source-files --recursive --delete "${baseDir}_the_end/DIM1" "${worldDest}/"
|
||||
fi
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
log "Copying end and nether ..."
|
||||
[ -d "${baseDir}_nether" ] && rsync --remove-source-files --recursive --delete "${baseDir}_nether/" "${worldDest}_nether"
|
||||
[ -d "${baseDir}_the_end" ] && rsync --remove-source-files --recursive --delete "${baseDir}_the_end/" "${worldDest}_the_end"
|
||||
fi
|
||||
elif [ -d "$WORLD" ]; then
|
||||
else
|
||||
log "Cloning world directory from $WORLD ..."
|
||||
rsync --recursive --delete "${WORLD%/}"/ "$worldDest"
|
||||
else
|
||||
log "ERROR: world file/directory $WORLD is missing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||
if [ "$TYPE" = "SPIGOT" ]; then
|
||||
# Reorganise if a Spigot server
|
||||
log "Moving End and Nether maps to Spigot location"
|
||||
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "${worldDest}_the_end"
|
||||
@@ -122,4 +69,4 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "${SCRIPTS:-/}start-setupVanillaTweaks" "$@"
|
||||
exec "${SCRIPTS:-/}start-setupModpack" "$@"
|
||||
|
||||
@@ -22,20 +22,6 @@ containsJars() {
|
||||
return 1
|
||||
}
|
||||
|
||||
containsPlugin() {
|
||||
file=${1?}
|
||||
|
||||
pat='plugin.yml$'
|
||||
|
||||
while read -r line; do
|
||||
if [[ $line =~ $pat ]]; then
|
||||
return 0
|
||||
fi
|
||||
done <<<$(unzip -l "$file")
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
getResourceFromSpiget() {
|
||||
resource=${1?}
|
||||
|
||||
@@ -95,12 +81,9 @@ downloadResourceFromSpiget() {
|
||||
log "Extracting contents of resource ${resource} into plugins"
|
||||
unzip -o -q -d /data/plugins "${tmpfile}"
|
||||
rm "${tmpfile}"
|
||||
elif containsPlugin "${tmpfile}"; then
|
||||
else
|
||||
log "Moving resource ${resource} into plugins"
|
||||
mv "${tmpfile}" "/data/plugins/${resource}.jar"
|
||||
else
|
||||
log "ERROR downloaded resource '${resource}' seems to be not a valid plugin"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
@@ -40,10 +40,6 @@ function getFilenameFromUrl() {
|
||||
}
|
||||
|
||||
function isTrue() {
|
||||
local oldState
|
||||
oldState=$(shopt -po xtrace)
|
||||
shopt -u -o xtrace
|
||||
|
||||
local value=${1,,}
|
||||
|
||||
result=
|
||||
@@ -57,7 +53,6 @@ function isTrue() {
|
||||
;;
|
||||
esac
|
||||
|
||||
eval "$oldState"
|
||||
return ${result}
|
||||
}
|
||||
|
||||
@@ -87,18 +82,7 @@ function logn() {
|
||||
}
|
||||
|
||||
function log() {
|
||||
local oldState
|
||||
# The return status when listing options is zero if all optnames are enabled, non- zero otherwise.
|
||||
oldState=$(shopt -po xtrace || true)
|
||||
shopt -u -o xtrace
|
||||
|
||||
if isDebugging || isTrue "${LOG_TIMESTAMP:-false}"; then
|
||||
ts=" $(date --rfc-2822)"
|
||||
else
|
||||
ts=
|
||||
fi
|
||||
echo "[init]${ts} $*"
|
||||
eval "$oldState"
|
||||
echo "[init] $*"
|
||||
}
|
||||
|
||||
function logAutopause() {
|
||||
@@ -109,14 +93,6 @@ function logAutopauseAction() {
|
||||
echo "[$(date -Iseconds)] [Autopause] $*"
|
||||
}
|
||||
|
||||
function logAutostop() {
|
||||
echo "[Autostop loop] $*"
|
||||
}
|
||||
|
||||
function logAutostopAction() {
|
||||
echo "[$(date -Iseconds)] [Autostop] $*"
|
||||
}
|
||||
|
||||
function normalizeMemSize() {
|
||||
local scale=1
|
||||
case ${1,,} in
|
||||
@@ -136,7 +112,34 @@ function normalizeMemSize() {
|
||||
}
|
||||
|
||||
function versionLessThan() {
|
||||
mc-image-helper compare-versions "${VANILLA_VERSION}" lt "${1?}"
|
||||
local activeParts
|
||||
version=${VANILLA_VERSION%%-*} # for snapshot/rc versions
|
||||
version=${version##b} # for versions like b1.7.3
|
||||
IFS=. read -ra activeParts <<<"${version}"
|
||||
|
||||
local givenParts
|
||||
IFS=. read -ra givenParts <<<"$1"
|
||||
|
||||
if ((${#activeParts[@]} < 2)); then
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ((${#activeParts[@]} == 2)); then
|
||||
if ((activeParts[0] < givenParts[0])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])); then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
if ((activeParts[0] < givenParts[0])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] < givenParts[1])) ||
|
||||
((activeParts[0] == givenParts[0] && activeParts[1] == givenParts[1] && activeParts[2] < givenParts[2])); then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
requireVar() {
|
||||
@@ -160,7 +163,7 @@ requireEnum() {
|
||||
fi
|
||||
done
|
||||
|
||||
log "ERROR: $var must be set to one of $*"
|
||||
log "ERROR: $var must be set to one of $@"
|
||||
# exit 1
|
||||
}
|
||||
|
||||
@@ -186,70 +189,4 @@ function get() {
|
||||
flags+=("--debug")
|
||||
fi
|
||||
mc-image-helper "${flags[@]}" get "$@"
|
||||
}
|
||||
|
||||
function isFamily() {
|
||||
for f in "${@}"; do
|
||||
if [[ $FAMILY == "$f" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
function isType() {
|
||||
for t in "${@}"; do
|
||||
# shellcheck disable=SC2153
|
||||
if [[ $TYPE == "$t" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
function evaluateJavaCompatibilityForForge() {
|
||||
javaRelease=$(mc-image-helper java-release)
|
||||
if versionLessThan 1.18 && (( javaRelease > 8 )); then
|
||||
log "**********************************************************************"
|
||||
log "WARNING: Some mods and modpacks may require Java 8."
|
||||
log " Please use itzg/minecraft-server:java8"
|
||||
log "**********************************************************************"
|
||||
sleep 5
|
||||
fi
|
||||
}
|
||||
|
||||
function extract() {
|
||||
src=${1?}
|
||||
destDir=${2?}
|
||||
|
||||
type=$(file -b --mime-type "${src}")
|
||||
case "${type}" in
|
||||
application/zip)
|
||||
unzip -q -d "${destDir}" "${src}"
|
||||
;;
|
||||
application/x-tar|application/gzip|application/x-gzip|application/x-bzip2|application/zstd|application/x-zstd)
|
||||
tar -C "${destDir}" -xf "${src}"
|
||||
;;
|
||||
*)
|
||||
log "ERROR: unsupported archive type: $type"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function checkSum() {
|
||||
local sum_file=${1?}
|
||||
|
||||
# Get distro
|
||||
distro=$(cat /etc/os-release | grep -E "^ID=" | cut -d= -f2 | sed -e 's/"//g')
|
||||
|
||||
if [ "${distro}" == "debian" ] && sha1sum -c "${sum_file}" --status 2> /dev/null; then
|
||||
return 0
|
||||
elif [ "${distro}" == "ubuntu" ] && sha1sum -c "${sum_file}" --status 2> /dev/null; then
|
||||
return 0
|
||||
elif [ "${distro}" == "alpine" ] && sha1sum -c "${sum_file}" -s 2> /dev/null; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
}
|
||||
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
data/
|
||||
@@ -1,4 +1,4 @@
|
||||
version: "3"
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
monitor:
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# go to script root directory
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
|
||||
# compose down function for reuse
|
||||
down() {
|
||||
docker-compose down -v --remove-orphans
|
||||
}
|
||||
|
||||
checkandExitOnFailure(){
|
||||
failed=$1
|
||||
# docker-compose logs outputs messages from the specified container
|
||||
if $failed; then
|
||||
docker-compose logs mc
|
||||
down
|
||||
cd ..
|
||||
exit 2
|
||||
fi
|
||||
}
|
||||
|
||||
# tests to completely spin up Minecraft and use the monitor to validate the service is running.
|
||||
fullMinecraftUpTest(){
|
||||
folder=$1
|
||||
cd "$folder"
|
||||
failed=false
|
||||
# run the monitor to validate the Minecraft image is healthy
|
||||
docker-compose run monitor || failed=true
|
||||
echo "${folder} Result: failed=$failed"
|
||||
checkandExitOnFailure $failed
|
||||
down
|
||||
cd ..
|
||||
}
|
||||
|
||||
# go through each folder in fulltests and run fullbuilds
|
||||
FOLDERS=$(ls)
|
||||
for folder in $FOLDERS; do
|
||||
# If folder is a directory
|
||||
if [ -d "$folder" ]; then
|
||||
echo "Starting Tests on ${folder}"
|
||||
fullMinecraftUpTest $folder
|
||||
fi
|
||||
done
|
||||
15
tests/generic-packs/docker-compose.test.yml
Normal file
15
tests/generic-packs/docker-compose.test.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
image: itzg/minecraft-server
|
||||
environment:
|
||||
EULA: "true"
|
||||
GENERIC_PACKS: https://github.com/itzg/mc-image-helper/releases/download/v1.9.5/mc-image-helper-1.9.5.zip,/packs/testing.zip
|
||||
DEBUG: "true"
|
||||
volumes:
|
||||
- ./packs:/packs
|
||||
- data:/data
|
||||
|
||||
volumes:
|
||||
data: {}
|
||||
@@ -1,15 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
TYPE: "PAPER"
|
||||
WORLD: /worlds/world-for-testing.zip
|
||||
volumes:
|
||||
- ./worlds:/worlds:ro
|
||||
- ./data:/data
|
||||
@@ -1,5 +0,0 @@
|
||||
mc-image-helper assert fileExists world/level.dat && \
|
||||
mc-image-helper assert fileExists world_nether/DIM-1/some_spigot_nether_file && \
|
||||
mc-image-helper assert fileExists world_the_end/DIM1/some_spigot_end_file && \
|
||||
! mc-image-helper assert fileExists world_nether/DIM-1/some_vanilla_nether_file && \
|
||||
! mc-image-helper assert fileExists world_the_end/DIM1/some_vanilla_end_file
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
WORLD: /worlds/world-for-testing.zip
|
||||
volumes:
|
||||
- ./worlds:/worlds:ro
|
||||
- ./data:/data
|
||||
@@ -1,5 +0,0 @@
|
||||
mc-image-helper assert fileExists world/level.dat && \
|
||||
mc-image-helper assert fileExists world/DIM-1/some_spigot_nether_file && \
|
||||
mc-image-helper assert fileExists world/DIM1/some_spigot_end_file && \
|
||||
! mc-image-helper assert fileExists world/DIM-1/some_vanilla_nether_file && \
|
||||
! mc-image-helper assert fileExists world/DIM1/some_vanilla_end_file
|
||||
Binary file not shown.
@@ -1,18 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
MODS_FORGEAPI_FILE: /config/forgeapi_mods.json
|
||||
# Key is defined in .github/workflows/pr.yml and ci.yml
|
||||
# This should be coming from github secrets.
|
||||
MODS_FORGEAPI_KEY: ${MODS_FORGEAPI_KEY}
|
||||
REMOVE_OLD_FORGEAPI_MODS: "TRUE"
|
||||
MODS_FORGEAPI_DOWNLOAD_DEPENDENCIES: "FALSE"
|
||||
volumes:
|
||||
- ./forgeapi_mods.json:/config/forgeapi_mods.json:ro
|
||||
@@ -1,17 +0,0 @@
|
||||
[{
|
||||
"name": "fabric api",
|
||||
"projectId": "306612",
|
||||
"releaseType": "release"
|
||||
},
|
||||
{
|
||||
"name": "Fabric Voice Mod",
|
||||
"projectId": "416089",
|
||||
"releaseType": "beta"
|
||||
},
|
||||
{
|
||||
"name": "Biomes o plenty",
|
||||
"projectId": "220318",
|
||||
"fileName": "BiomesOPlenty-1.18.1-15.0.0.100-universal.jar",
|
||||
"releaseType": "release"
|
||||
}
|
||||
]
|
||||
@@ -1 +0,0 @@
|
||||
[[ $MODS_FORGEAPI_KEY ]] || exit 1
|
||||
@@ -1,16 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
MODS_FORGEAPI_DOWNLOAD_DEPENDENCIES: "TRUE"
|
||||
MODS_FORGEAPI_PROJECTIDS: 306612,416089,220318
|
||||
# Allows for Beta releases of 416089 the Fabric Voice Mod
|
||||
MODS_FORGEAPI_RELEASES: BETA
|
||||
MODS_FORGEAPI_KEY: ${MODS_FORGEAPI_KEY}
|
||||
REMOVE_OLD_FORGEAPI_MODS: "TRUE"
|
||||
@@ -1 +0,0 @@
|
||||
[[ $MODS_FORGEAPI_KEY ]] || exit 1
|
||||
@@ -1,14 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "true"
|
||||
SETUP_ONLY: "TRUE"
|
||||
GENERIC_PACKS: testing
|
||||
GENERIC_PACKS_PREFIX: /packs/
|
||||
GENERIC_PACKS_SUFFIX: .zip
|
||||
volumes:
|
||||
- ./packs:/packs
|
||||
- ./data:/data
|
||||
@@ -1 +0,0 @@
|
||||
mc-image-helper assert fileExists one.txt mods/two.txt
|
||||
@@ -1,24 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
web:
|
||||
image: nginx
|
||||
volumes:
|
||||
- ./web:/usr/share/nginx/html
|
||||
mc:
|
||||
depends_on:
|
||||
- web
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "true"
|
||||
SETUP_ONLY: "true"
|
||||
GENERIC_PACKS: http://web/configs.zip,/packs/testing.zip
|
||||
LOG_TIMESTAMP: "true"
|
||||
# the following are only used to speed up test execution
|
||||
TYPE: CUSTOM
|
||||
CUSTOM_SERVER: /servers/fake.jar
|
||||
VERSION: 1.18.1
|
||||
volumes:
|
||||
- ./packs:/packs
|
||||
- ./data:/data
|
||||
- ./fake.jar:/servers/fake.jar
|
||||
Binary file not shown.
@@ -1,2 +0,0 @@
|
||||
mc-image-helper assert fileExists one.txt mods/two.txt
|
||||
mc-image-helper assert fileExists config/opt.yml
|
||||
Binary file not shown.
@@ -1,13 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
OPS: itzg
|
||||
volumes:
|
||||
- ./data:/data
|
||||
@@ -1,3 +0,0 @@
|
||||
mc-image-helper assert jsonPathEquals --file=ops.json --path='$[0].name' --expect=itzg
|
||||
mc-image-helper assert jsonPathEquals --file=ops.json --path='$[0].uuid' --expect=5cddfd26-fc86-4981-b52e-c42bb10bfdef
|
||||
mc-image-helper assert jsonPathEquals --file=ops.json --path='$[0].level' --expect=4
|
||||
@@ -1,15 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
TYPE: "PAPER"
|
||||
WORLD: /worlds/world-for-testing.zip
|
||||
volumes:
|
||||
- ./worlds:/worlds:ro
|
||||
- ./data:/data
|
||||
@@ -1,4 +0,0 @@
|
||||
mc-image-helper assert fileExists world/level.dat && \
|
||||
mc-image-helper assert fileExists world/some_overworld_file && \
|
||||
mc-image-helper assert fileExists world_nether/DIM-1/some_nether_file && \
|
||||
mc-image-helper assert fileExists world_the_end/DIM1/some_end_file
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
WORLD: /worlds/world-for-testing.zip
|
||||
volumes:
|
||||
- ./worlds:/worlds:ro
|
||||
- ./data:/data
|
||||
@@ -1,4 +0,0 @@
|
||||
mc-image-helper assert fileExists world/level.dat && \
|
||||
mc-image-helper assert fileExists world/some_overworld_file && \
|
||||
mc-image-helper assert fileExists world/DIM-1/some_nether_file && \
|
||||
mc-image-helper assert fileExists world/DIM1/some_end_file
|
||||
Binary file not shown.
@@ -1,61 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
IFS=$'\n\t'
|
||||
|
||||
# go to script root directory
|
||||
cd "$(dirname "$0")" || exit 1
|
||||
|
||||
# tests that only run the setup files for things like downloads and configuration.
|
||||
setupOnlyMinecraftTest(){
|
||||
folder=$1
|
||||
cd "$folder"
|
||||
result=0
|
||||
|
||||
if [ -f require.sh ]; then
|
||||
# require.sh scripts can check for environment variables, etc that are required for the test.
|
||||
# The script should exit with a non-zero status to indicate the test requirements are missing
|
||||
# and the test should be skipped
|
||||
if ! bash require.sh; then
|
||||
echo "${folder} SKIP"
|
||||
cd ..
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if ! logs=$(docker-compose run mc 2>&1); then
|
||||
echo "${folder} test scenario FAILED"
|
||||
echo ":::::::::::: LOGS ::::::::::::::::
|
||||
$logs
|
||||
::::::::::::::::::::::::::::::::::
|
||||
"
|
||||
result=1
|
||||
elif [ -f verify.sh ]; then
|
||||
if ! docker run --rm --entrypoint bash -v "${PWD}/data":/data -v "${PWD}/verify.sh":/verify "${IMAGE_TO_TEST:-itzg/minecraft-server}" -e /verify; then
|
||||
echo "${folder} verify FAILED"
|
||||
result=1
|
||||
else
|
||||
echo "${folder} verify PASS"
|
||||
fi
|
||||
else
|
||||
echo "${folder} PASS"
|
||||
fi
|
||||
|
||||
docker-compose down -v --remove-orphans
|
||||
cd ..
|
||||
|
||||
return $result
|
||||
}
|
||||
|
||||
# go through each folder in setuponly and test setups
|
||||
if (( $# > 0 )); then
|
||||
for folder in "$@"; do
|
||||
echo "Starting Tests in ${folder}"
|
||||
setupOnlyMinecraftTest "$folder"
|
||||
done
|
||||
else
|
||||
readarray -t folders < <(find . -maxdepth 2 -mindepth 2 -name docker-compose.yml -printf '%h\n')
|
||||
for folder in "${folders[@]}"; do
|
||||
echo "Starting Tests in ${folder}"
|
||||
setupOnlyMinecraftTest "$folder"
|
||||
done
|
||||
fi
|
||||
@@ -1,15 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
TYPE: "PAPER"
|
||||
WORLD: /worlds/world-for-testing.zip
|
||||
volumes:
|
||||
- ./worlds:/worlds:ro
|
||||
- ./data:/data
|
||||
@@ -1,3 +0,0 @@
|
||||
mc-image-helper assert fileExists world/level.dat && \
|
||||
mc-image-helper assert fileExists world_nether/DIM-1/some_nether_file && \
|
||||
mc-image-helper assert fileExists world_the_end/DIM1/some_end_file
|
||||
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
WORLD: /worlds/world-for-testing.zip
|
||||
volumes:
|
||||
- ./worlds:/worlds:ro
|
||||
- ./data:/data
|
||||
@@ -1,3 +0,0 @@
|
||||
mc-image-helper assert fileExists world/level.dat && \
|
||||
mc-image-helper assert fileExists world/DIM-1/some_nether_file && \
|
||||
mc-image-helper assert fileExists world/DIM1/some_end_file
|
||||
Binary file not shown.
@@ -1,17 +0,0 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
mc:
|
||||
restart: "no"
|
||||
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||
environment:
|
||||
EULA: "TRUE"
|
||||
SETUP_ONLY: "TRUE"
|
||||
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||
VANILLATWEAKS_FILE: /config/vt-datapacks.json,/config/vt-craftingtweaks.json,/config/vt-resourcepacks.json
|
||||
REMOVE_OLD_VANILLATWEAKS: "FALSE"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./vt-datapacks.json:/config/vt-datapacks.json:ro
|
||||
- ./vt-craftingtweaks.json:/config/vt-craftingtweaks.json:ro
|
||||
- ./vt-resourcepacks.json:/config/vt-resourcepacks.json:ro
|
||||
@@ -1,4 +0,0 @@
|
||||
mc-image-helper assert fileExists "/data/world/datapacks/afk*"
|
||||
mc-image-helper assert fileExists "/data/world/datapacks/graves*"
|
||||
mc-image-helper assert fileExists "/data/world/datapacks/craftingtweaks*"
|
||||
mc-image-helper assert fileExists "/data/resourcepacks/resourcepacks*"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user