mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-02-17 15:13:55 +00:00
Compare commits
204 Commits
2021.21.0-
...
java17
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aeae29046c | ||
|
|
cbbc817279 | ||
|
|
18d8aba20f | ||
|
|
09834c289a | ||
|
|
880dca1ae5 | ||
|
|
726c77537c | ||
|
|
b1e33d4049 | ||
|
|
284c260886 | ||
|
|
05bbb45046 | ||
|
|
d11fe229df | ||
|
|
854ac86bed | ||
|
|
b7801565c2 | ||
|
|
bd4760e504 | ||
|
|
edc25b216f | ||
|
|
79345d69c2 | ||
|
|
5499867ae8 | ||
|
|
e4c575c130 | ||
|
|
f29f098b26 | ||
|
|
1d751ab2bc | ||
|
|
7516b53e84 | ||
|
|
4f87662664 | ||
|
|
eafdf26d94 | ||
|
|
7e2937aa8d | ||
|
|
529781adda | ||
|
|
977d082638 | ||
|
|
984c969da2 | ||
|
|
c506cf11ac | ||
|
|
967d5159ea | ||
|
|
79f978359c | ||
|
|
4c7bb313be | ||
|
|
83d3555eab | ||
|
|
e93cc569c6 | ||
|
|
5c0cf03548 | ||
|
|
00cae995a7 | ||
|
|
4ba0a9c98c | ||
|
|
6520655d6c | ||
|
|
6bd722b11b | ||
|
|
4576882f07 | ||
|
|
224553f695 | ||
|
|
cc100fd8bb | ||
|
|
a7a0e54cb9 | ||
|
|
ce32eb8d4f | ||
|
|
39519427bb | ||
|
|
aff65b74ff | ||
|
|
2f1fed822c | ||
|
|
bf5824b6e5 | ||
|
|
52bf2ae094 | ||
|
|
fa4a0e92ce | ||
|
|
c15e231d7e | ||
|
|
cc885276f5 | ||
|
|
9dee47cb6d | ||
|
|
2ed5de68f9 | ||
|
|
39611fa9cb | ||
|
|
bb56de694a | ||
|
|
c4d4d2bcc1 | ||
|
|
4e44f33db9 | ||
|
|
58c085527f | ||
|
|
79fa4b95c3 | ||
|
|
d5f1660c77 | ||
|
|
a4b6ee6d3b | ||
|
|
6729ba462e | ||
|
|
3a3b5fc002 | ||
|
|
4b28d5e472 | ||
|
|
3a31ce757d | ||
|
|
eccc989887 | ||
|
|
c4aa105042 | ||
|
|
ffcb76f73f | ||
|
|
be2ef20fc1 | ||
|
|
3f2022da40 | ||
|
|
0f7464403c | ||
|
|
bee39343a6 | ||
|
|
e9326db933 | ||
|
|
dd1cc82fcd | ||
|
|
93825895b9 | ||
|
|
492aebc718 | ||
|
|
e66b2eda60 | ||
|
|
6020400d3b | ||
|
|
3bb21d8581 | ||
|
|
ae96adaeec | ||
|
|
fb6fa9b7d7 | ||
|
|
d34be9f20e | ||
|
|
0718a62007 | ||
|
|
529d92fa63 | ||
|
|
f7836abc06 | ||
|
|
64a02d28bc | ||
|
|
cd09a932f9 | ||
|
|
46d21f58cf | ||
|
|
3e63be9988 | ||
|
|
aaaf7796b0 | ||
|
|
aba10c1d99 | ||
|
|
c4dd0d2bae | ||
|
|
c446cb11da | ||
|
|
6c636c3d9c | ||
|
|
9098b198c3 | ||
|
|
927ec2a2c3 | ||
|
|
7aea5b593e | ||
|
|
07a251b544 | ||
|
|
b8e163d8b1 | ||
|
|
cd72acb6c6 | ||
|
|
24942a6f04 | ||
|
|
75dcc746f8 | ||
|
|
263a10848a | ||
|
|
91adfaa1d9 | ||
|
|
ff4d46d509 | ||
|
|
66ead9128a | ||
|
|
55ff76a85d | ||
|
|
e7b223f1c6 | ||
|
|
dca29dcbb5 | ||
|
|
84c577cc96 | ||
|
|
5e8fc43857 | ||
|
|
66a17c8d58 | ||
|
|
57f7ee50a6 | ||
|
|
f8ac58e200 | ||
|
|
71954edf75 | ||
|
|
597faa102a | ||
|
|
442fccfc41 | ||
|
|
784ec6104c | ||
|
|
817a01bbc3 | ||
|
|
45eff98011 | ||
|
|
66c0558174 | ||
|
|
9116be11ae | ||
|
|
b4111f0428 | ||
|
|
969f4c8db6 | ||
|
|
e6916e91e7 | ||
|
|
288bdf3804 | ||
|
|
9544aeaf7a | ||
|
|
babeac1693 | ||
|
|
5bc1ac672e | ||
|
|
130b067955 | ||
|
|
a503ad2ec2 | ||
|
|
df7d6c298a | ||
|
|
3042aa4909 | ||
|
|
a8a60264e9 | ||
|
|
721df8d32b | ||
|
|
2375a6796c | ||
|
|
e04e943e1c | ||
|
|
1bf75671f6 | ||
|
|
7d56de9d15 | ||
|
|
8882ae5f89 | ||
|
|
a8de790b57 | ||
|
|
cafddd3b12 | ||
|
|
fc958faf7b | ||
|
|
402894cd8d | ||
|
|
f97cea4b06 | ||
|
|
4149db7f11 | ||
|
|
0198c15b8c | ||
|
|
e813007f49 | ||
|
|
df2962bdb3 | ||
|
|
367f07b784 | ||
|
|
9de9ec2e34 | ||
|
|
6ad7773e2b | ||
|
|
8177dd9a5a | ||
|
|
81994ec3b3 | ||
|
|
666f538ad5 | ||
|
|
ecee4069f1 | ||
|
|
3713d9c4e8 | ||
|
|
c7f1d13f9b | ||
|
|
cc8d18d41f | ||
|
|
afd863ab89 | ||
|
|
46f6653b13 | ||
|
|
3237d1a996 | ||
|
|
386e34e05b | ||
|
|
4fd234e482 | ||
|
|
38fd0dac8b | ||
|
|
11ac111036 | ||
|
|
9803547967 | ||
|
|
1a0c7c4f85 | ||
|
|
7b7d5db796 | ||
|
|
145403ea54 | ||
|
|
34baf8a354 | ||
|
|
5392801ecd | ||
|
|
cc9e0fe1ef | ||
|
|
3dfd70d068 | ||
|
|
9c354d5775 | ||
|
|
2dce24c1bd | ||
|
|
6f80ce5584 | ||
|
|
c8df2d8e31 | ||
|
|
e5bc9b939f | ||
|
|
2e8f27a8ef | ||
|
|
e20dd63f76 | ||
|
|
3e62389325 | ||
|
|
f3c880f96a | ||
|
|
2c7796ea0b | ||
|
|
0daeeb70f7 | ||
|
|
86782865c4 | ||
|
|
ddcabb175a | ||
|
|
1b620d2d6d | ||
|
|
7b09e525e8 | ||
|
|
2eefb12e6b | ||
|
|
5777a248d4 | ||
|
|
97a6a4ba85 | ||
|
|
531d33af1c | ||
|
|
28d77853cb | ||
|
|
0618d690fa | ||
|
|
6aa3b1066f | ||
|
|
393544a194 | ||
|
|
4aea1753bd | ||
|
|
c42d8971ca | ||
|
|
ee7f2ee739 | ||
|
|
6008660a81 | ||
|
|
043d9778b8 | ||
|
|
8bf7c6cccd | ||
|
|
80d7efb365 | ||
|
|
32ed58692c |
40
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
40
.github/ISSUE_TEMPLATE/bug.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
name: Bug Report
|
||||||
|
description: File a bug report
|
||||||
|
labels:
|
||||||
|
- bug
|
||||||
|
- status/needs triage
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to report a bug.
|
||||||
|
|
||||||
|
Please double check some things first:
|
||||||
|
- Do you just have a question about something? If so, asking in the [Q&A Discussions](https://github.com/itzg/docker-minecraft-server/discussions/categories/q-a) or asking on [the Discord server](https://discord.gg/DXfKpjB) would be best.
|
||||||
|
- Is this bug happening after the `[init]` prefixed logs and after the log that says "Starting the Minecraft server"? If so, please report the bug with Mojang or the respective server provider.
|
||||||
|
- Are you seeing a performance problem? If so, that is typically outside the scope of the image setup mechanims. Ask a question as above or contact the respective server provider.
|
||||||
|
- type: textarea
|
||||||
|
id: problem
|
||||||
|
attributes:
|
||||||
|
label: Describe the problem
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: container
|
||||||
|
attributes:
|
||||||
|
label: Container definition
|
||||||
|
description: Please provide the compose file or run command used to create the container
|
||||||
|
value: |
|
||||||
|
```
|
||||||
|
Paste run command or compose file here
|
||||||
|
```
|
||||||
|
- type: textarea
|
||||||
|
id: logs
|
||||||
|
attributes:
|
||||||
|
label: Container logs
|
||||||
|
description: |
|
||||||
|
Please provide container logs from the start of the container, which will be the ones prefixed with `[init]`. It is even better if you can set the variable `DEBUG` to "true" and provide those debug container logs.
|
||||||
|
value: |
|
||||||
|
```
|
||||||
|
Paste logs here
|
||||||
|
```
|
||||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
7
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
contact_links:
|
||||||
|
- name: Ask a question in discussions
|
||||||
|
url: https://github.com/itzg/docker-minecraft-server/discussions
|
||||||
|
about: Please ask questions here
|
||||||
|
- name: Ask a question on Discord
|
||||||
|
url: https://discord.gg/DXfKpjB
|
||||||
|
about: Please ask questions here
|
||||||
29
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
29
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
name: Enhancement Request
|
||||||
|
description: Request an enhancement
|
||||||
|
labels:
|
||||||
|
- enhancement
|
||||||
|
- status/needs triage
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to request an enhancement.
|
||||||
|
|
||||||
|
Even if you plan on submitting a pull request with a contributed enhancement it is best to describe the enhancement here first. Somebody might already be working on a similar thing and could use your help.
|
||||||
|
- type: dropdown
|
||||||
|
id: type
|
||||||
|
attributes:
|
||||||
|
label: Enhancement Type
|
||||||
|
options:
|
||||||
|
- Improve an existing feature
|
||||||
|
- A completely new feature
|
||||||
|
- New server type
|
||||||
|
- Not sure
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: description
|
||||||
|
attributes:
|
||||||
|
label: Describe the enhancement
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
6
.github/no-response.yml
vendored
6
.github/no-response.yml
vendored
@@ -1,6 +0,0 @@
|
|||||||
daysUntilClose: 14
|
|
||||||
responseRequiredLabel: "status/waiting on feedback"
|
|
||||||
closeComment: >
|
|
||||||
This issue has been automatically closed because there has been no response
|
|
||||||
after requesting feedback. Please feel free to re-open this issue if the
|
|
||||||
scenario still exists and provide a comment with more information.
|
|
||||||
4
.github/release.yml
vendored
Normal file
4
.github/release.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
changelog:
|
||||||
|
exclude:
|
||||||
|
authors:
|
||||||
|
- dependabot
|
||||||
58
.github/workflows/build-multiarch.yml
vendored
58
.github/workflows/build-multiarch.yml
vendored
@@ -3,16 +3,15 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- "*-multiarch"
|
- java8-multiarch
|
||||||
- "multiarch*"
|
|
||||||
- java8-openj9
|
- java8-openj9
|
||||||
- java11*
|
- java11*
|
||||||
- java16*
|
- java16*
|
||||||
- test/*
|
- java17*
|
||||||
|
- test/**
|
||||||
tags:
|
tags:
|
||||||
- "[0-9]+.[0-9]+.[0-9]+"
|
- "[0-9]+.[0-9]+.[0-9]+"
|
||||||
- "[0-9]+.[0-9]+.[0-9]+-multiarch*"
|
- "[0-9]+.[0-9]+.[0-9]+-java8-multiarch"
|
||||||
- "[0-9]+.[0-9]+.[0-9]+-*multiarch"
|
|
||||||
- "[0-9]+.[0-9]+.[0-9]+-java8-openj9"
|
- "[0-9]+.[0-9]+.[0-9]+-java8-openj9"
|
||||||
- "[0-9]+.[0-9]+.[0-9]+-java11*"
|
- "[0-9]+.[0-9]+.[0-9]+-java11*"
|
||||||
- "[0-9]+.[0-9]+.[0-9]+-java16*"
|
- "[0-9]+.[0-9]+.[0-9]+-java16*"
|
||||||
@@ -21,13 +20,16 @@ on:
|
|||||||
- "docs/**"
|
- "docs/**"
|
||||||
- "examples/**"
|
- "examples/**"
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
docker-buildx:
|
build:
|
||||||
if: github.repository == 'itzg/docker-minecraft-server'
|
if: github.repository == 'itzg/docker-minecraft-server'
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2.3.4
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
@@ -44,14 +46,6 @@ jobs:
|
|||||||
- name: Setup Docker Buildx
|
- name: Setup Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Cache Docker layers
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache
|
|
||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-buildx-
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1.2.0
|
uses: docker/setup-qemu-action@v1.2.0
|
||||||
|
|
||||||
@@ -61,27 +55,39 @@ jobs:
|
|||||||
username: ${{ secrets.DOCKER_USER }}
|
username: ${{ secrets.DOCKER_USER }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build for test
|
||||||
|
uses: docker/build-push-action@v2.7.0
|
||||||
|
if: github.ref_name == 'master' || startsWith(github.ref_name, 'test/')
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64
|
||||||
|
tags: ${{ env.IMAGE_TO_TEST }}
|
||||||
|
# ensure latest base image is used
|
||||||
|
pull: true
|
||||||
|
load: true
|
||||||
|
push: false
|
||||||
|
cache-from: type=gha
|
||||||
|
# no cache-to to avoid cross-cache update from next build step
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
# It is assumed that image variants are merged from master and tested there
|
||||||
|
if: github.ref_name == 'master' || startsWith(github.ref_name, 'test/')
|
||||||
|
run: |
|
||||||
|
tests/test.sh
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v2.7.0
|
uses: docker/build-push-action@v2.7.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
platforms: linux/amd64,linux/arm/v7,linux/arm64
|
||||||
push: ${{ github.event_name != 'pull_request' }}
|
push: true
|
||||||
tags: ${{ steps.meta.outputs.tags }}
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
# ensure latest base image is used
|
# ensure latest base image is used
|
||||||
pull: true
|
pull: true
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
cache-from: type=gha
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new
|
cache-to: type=gha,mode=max
|
||||||
labels: ${{ steps.meta.outputs.labels }}
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
|
||||||
- # Temp fix
|
|
||||||
# https://github.com/docker/build-push-action/issues/252
|
|
||||||
# https://github.com/moby/buildkit/issues/1896
|
|
||||||
name: Move cache
|
|
||||||
run: |
|
|
||||||
rm -rf /tmp/.buildx-cache
|
|
||||||
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
|
||||||
43
.github/workflows/ci.yml
vendored
Normal file
43
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
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.7.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64
|
||||||
|
tags: ${{ env.IMAGE_TO_TEST }}
|
||||||
|
load: true
|
||||||
|
cache-from: type=gha
|
||||||
|
|
||||||
|
- name: Run Setup Only Tests
|
||||||
|
run: sh tests/setuponlytests/test.sh
|
||||||
|
|
||||||
|
# - name: Run Full Minecraft Service Tests
|
||||||
|
# run: |
|
||||||
|
# tests/fulltests/test.sh
|
||||||
26
.github/workflows/discord.yml
vendored
Normal file
26
.github/workflows/discord.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: discord
|
||||||
|
|
||||||
|
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 }} 💣💥"
|
||||||
4
.github/workflows/generate-toc.yml
vendored
4
.github/workflows/generate-toc.yml
vendored
@@ -11,11 +11,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 5
|
timeout-minutes: 5
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v2.4.0
|
||||||
- run: |
|
- run: |
|
||||||
curl https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc -o gh-md-toc
|
curl https://raw.githubusercontent.com/ekalinin/github-markdown-toc/master/gh-md-toc -o gh-md-toc
|
||||||
chmod a+x gh-md-toc
|
chmod a+x gh-md-toc
|
||||||
./gh-md-toc --insert --no-backup README.md
|
./gh-md-toc --insert --no-backup README.md
|
||||||
- uses: stefanzweifel/git-auto-commit-action@v4.12.0
|
- uses: stefanzweifel/git-auto-commit-action@v4.13.1
|
||||||
with:
|
with:
|
||||||
commit_message: "docs: Auto update markdown TOC"
|
commit_message: "docs: Auto update markdown TOC"
|
||||||
17
.github/workflows/issue-label.yml
vendored
Normal file
17
.github/workflows/issue-label.yml
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types: [labeled]
|
||||||
|
|
||||||
|
env:
|
||||||
|
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
labelNotify:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 5
|
||||||
|
steps:
|
||||||
|
- name: notify
|
||||||
|
if: github.event.label.name == 'enhancement' || github.event.label.name == 'bug'
|
||||||
|
uses: Ilshidur/action-discord@master
|
||||||
|
with:
|
||||||
|
args: "[${{ github.event.issue.title }}](<${{ github.event.issue.html_url }}>) added `${{ github.event.label.name }}` label"
|
||||||
57
.github/workflows/main.yml
vendored
57
.github/workflows/main.yml
vendored
@@ -15,23 +15,15 @@ on:
|
|||||||
- "[0-9]+.[0-9]+.[0-9]+-openj9-nightly"
|
- "[0-9]+.[0-9]+.[0-9]+-openj9-nightly"
|
||||||
- "[0-9]+.[0-9]+.[0-9]+-adopt11"
|
- "[0-9]+.[0-9]+.[0-9]+-adopt11"
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE_TO_TEST: itzg/minecraft-server:test-${{ github.repository_owner }}-${{ github.run_id }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
|
||||||
runs-on: ubuntu-20.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2.3.4
|
|
||||||
|
|
||||||
- name: Run tests
|
|
||||||
run: |
|
|
||||||
tests/test.sh
|
|
||||||
build:
|
build:
|
||||||
needs:
|
|
||||||
- test
|
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Prepare
|
- name: Prepare
|
||||||
id: prep
|
id: prep
|
||||||
@@ -54,20 +46,33 @@ jobs:
|
|||||||
- name: Setup Docker Buildx
|
- name: Setup Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
- name: Cache Docker layers
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: /tmp/.buildx-cache
|
|
||||||
key: ${{ runner.os }}-buildx-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ runner.os }}-buildx-
|
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v1
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USER }}
|
username: ${{ secrets.DOCKER_USER }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build for test
|
||||||
|
uses: docker/build-push-action@v2.7.0
|
||||||
|
if: github.ref_name == 'java8'
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64
|
||||||
|
tags: ${{ env.IMAGE_TO_TEST }}
|
||||||
|
# ensure latest base image is used
|
||||||
|
pull: true
|
||||||
|
load: true
|
||||||
|
push: false
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
|
||||||
|
- name: Run tests
|
||||||
|
if: github.ref_name == 'java8'
|
||||||
|
run: |
|
||||||
|
tests/test.sh
|
||||||
|
env:
|
||||||
|
MINECRAFT_VERSION: 1.12.2
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v2.7.0
|
uses: docker/build-push-action@v2.7.0
|
||||||
@@ -80,8 +85,8 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
# tags determined by prep step
|
# tags determined by prep step
|
||||||
tags: ${{ steps.prep.outputs.tags }}
|
tags: ${{ steps.prep.outputs.tags }}
|
||||||
cache-from: type=local,src=/tmp/.buildx-cache
|
cache-from: type=gha
|
||||||
cache-to: type=local,dest=/tmp/.buildx-cache-new
|
cache-to: type=gha,mode=max
|
||||||
labels: |
|
labels: |
|
||||||
org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server
|
org.opencontainers.image.documentation=https://github.com/itzg/docker-minecraft-server
|
||||||
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
|
org.opencontainers.image.version=${{ steps.prep.outputs.version }}
|
||||||
@@ -90,11 +95,3 @@ jobs:
|
|||||||
|
|
||||||
- name: Image digest
|
- name: Image digest
|
||||||
run: echo ${{ steps.docker_build.outputs.digest }}
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
||||||
|
|
||||||
- # Temp fix
|
|
||||||
# https://github.com/docker/build-push-action/issues/252
|
|
||||||
# https://github.com/moby/buildkit/issues/1896
|
|
||||||
name: Move cache
|
|
||||||
run: |
|
|
||||||
rm -rf /tmp/.buildx-cache
|
|
||||||
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
|
|
||||||
|
|||||||
54
.github/workflows/pr.yml
vendored
54
.github/workflows/pr.yml
vendored
@@ -1,16 +1,64 @@
|
|||||||
name: Validate PR
|
name: PullRequest
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ master ]
|
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:
|
jobs:
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2.3.4
|
- uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
|
- name: Setup Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
uses: docker/build-push-action@v2.7.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64
|
||||||
|
tags: ${{ env.IMAGE_TO_TEST }}
|
||||||
|
load: true
|
||||||
|
cache-from: type=gha
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: |
|
run: |
|
||||||
tests/test.sh
|
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.7.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 }}
|
||||||
|
|||||||
25
.github/workflows/stale-check.yml
vendored
Normal file
25
.github/workflows/stale-check.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
name: Stale Check
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: 0 2 * * *
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- name: Process Stale Issues
|
||||||
|
uses: actions/stale@v4.1.0
|
||||||
|
with:
|
||||||
|
stale-issue-label: status/stale
|
||||||
|
stale-pr-label: status/stale
|
||||||
|
stale-issue-message: >
|
||||||
|
This issue is stale because it has been open 30 days with no activity.
|
||||||
|
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'
|
||||||
|
|
||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,4 +1,5 @@
|
|||||||
|
.vscode
|
||||||
/data/
|
/data/
|
||||||
/.idea/
|
/.idea/
|
||||||
*.iml
|
*.iml
|
||||||
/gh-md-toc
|
/gh-md-toc
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
Adding a new server `TYPE` can vary due to the complexity of obtaining and configuring each type; however, the addition of any server type includes at least the following steps:
|
Adding a new server `TYPE` can vary due to the complexity of obtaining and configuring each type; however, the addition of any server type includes at least the following steps:
|
||||||
|
|
||||||
1. Copy an existing "start-deploy*" script, such as [start-deployMohist](start-deployMohist) and rename it accordingly making sure to retain the "start-deploy" prefix
|
1. Copy an existing "start-deploy*" script, such as [start-deployMohist](scripts/start-deployMohist) and rename it accordingly making sure to retain the "start-deploy" prefix
|
||||||
2. Modify the type-specific behavior between the "start-utils" preamble and the hand-off to `start-setupWorld` at the end of the script
|
2. Modify the type-specific behavior between the "start-utils" preamble and the hand-off to `start-setupWorld` at the end of the script
|
||||||
3. Develop and test the changes using the [iterative process described below](#iterative-script-development)
|
3. Develop and test the changes using the [iterative process described below](#iterative-script-development)
|
||||||
4. Add a case-entry to the `case "${TYPE^^}"` in [start-configuration](start-configuration)
|
4. Add a case-entry to the `case "${TYPE^^}"` in [start-configuration](scripts/start-configuration)
|
||||||
5. Add a section to the [README](README.md). It is recommended to copy-modify an existing section to retain a similar wording and level of detail
|
5. Add a section to the [README](README.md). It is recommended to copy-modify an existing section to retain a similar wording and level of detail
|
||||||
6. [Submit a pull request](https://github.com/itzg/docker-minecraft-server/pulls)
|
6. [Submit a pull request](https://github.com/itzg/docker-minecraft-server/pulls)
|
||||||
|
|
||||||
@@ -40,6 +40,29 @@ VANILLA_VERSION=1.12.2 /scripts/start-magma
|
|||||||
|
|
||||||
> NOTE: You may want to temporarily add an `exit` statement near the end of your script to isolate execution to just the script you're developing.
|
> NOTE: You may want to temporarily add an `exit` statement near the end of your script to isolate execution to just the script you're developing.
|
||||||
|
|
||||||
|
## Using development copy of mc-image-helper
|
||||||
|
|
||||||
|
In the cloned copy of [`mc-image-helper`](https://github.com/itzg/mc-image-helper), create an up-to-date snapshot build of the tgz distribution using:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
./gradlew distTar
|
||||||
|
```
|
||||||
|
|
||||||
|
Assuming [http-server](https://www.npmjs.com/package/http-server) is installed globally, start a static web server using:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
http-server ./build/distributions -p 0
|
||||||
|
```
|
||||||
|
|
||||||
|
Note the port that was selected by http-server and pass the build arguments, such as:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
--build-arg MC_HELPER_VERSION=1.8.1-SNAPSHOT \
|
||||||
|
--build-arg MC_HELPER_BASE_URL=http://host.docker.internal:8080
|
||||||
|
```
|
||||||
|
|
||||||
|
Now the image can be built like normal and it will install mc-image-helper from the locally built copy.
|
||||||
|
|
||||||
## Multi-base-image variants
|
## Multi-base-image variants
|
||||||
|
|
||||||
Several base-image variants are maintained in order to offer choices in JDK provider and version. The variants are maintained in their respective branches:
|
Several base-image variants are maintained in order to offer choices in JDK provider and version. The variants are maintained in their respective branches:
|
||||||
@@ -70,5 +93,27 @@ The multiarch images are built and published by [a Github action](https://github
|
|||||||
The following git command can be used to provide the bulk of release notes content:
|
The following git command can be used to provide the bulk of release notes content:
|
||||||
|
|
||||||
```shell script
|
```shell script
|
||||||
git log --invert-grep --grep "^ci:" --grep "^misc:" --grep "^docs:" --grep "^build(deps)" --pretty="- %s" 1.1.0..1.2.0
|
git log --invert-grep --grep "^ci:" --grep "^misc:" --grep "^docs:" --pretty="* %s" 1.1.0..1.2.0
|
||||||
```
|
```
|
||||||
|
## Tracking changes from master without content
|
||||||
|
|
||||||
|
The following script uses the [ours](https://git-scm.com/docs/merge-strategies#Documentation/merge-strategies.txt-ours) merging strategy to track the history from master into the other branches without actually bringing the changes over. It is useful when a change is specific to master only, such as bumping the base Java version for the `latest` image tag.
|
||||||
|
|
||||||
|
```shell
|
||||||
|
branches=(
|
||||||
|
java8
|
||||||
|
java8-multiarch
|
||||||
|
java8-openj9
|
||||||
|
java11
|
||||||
|
java11-openj9
|
||||||
|
java16
|
||||||
|
java16-openj9
|
||||||
|
java17
|
||||||
|
)
|
||||||
|
|
||||||
|
for b in "${branches[@]}"; do
|
||||||
|
git checkout "$b"
|
||||||
|
git merge -s ours -m "Track latest from master" master
|
||||||
|
git push origin
|
||||||
|
done
|
||||||
|
```
|
||||||
102
Dockerfile
102
Dockerfile
@@ -1,39 +1,41 @@
|
|||||||
FROM openjdk:8u212-jre-alpine
|
FROM eclipse-temurin:17-jdk
|
||||||
|
|
||||||
LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>"
|
LABEL org.opencontainers.image.authors="Geoff Bourne <itzgeoff@gmail.com>"
|
||||||
|
|
||||||
RUN apk add --no-cache -U \
|
RUN apt-get update \
|
||||||
openssl \
|
&& DEBIAN_FRONTEND=noninteractive \
|
||||||
imagemagick \
|
apt-get install -y \
|
||||||
lsof \
|
imagemagick \
|
||||||
su-exec \
|
file \
|
||||||
shadow \
|
gosu \
|
||||||
bash \
|
sudo \
|
||||||
curl iputils wget \
|
net-tools \
|
||||||
git \
|
iputils-ping \
|
||||||
jq \
|
curl \
|
||||||
mysql-client \
|
git \
|
||||||
tzdata \
|
jq \
|
||||||
rsync \
|
dos2unix \
|
||||||
nano \
|
mysql-client \
|
||||||
sudo \
|
tzdata \
|
||||||
knock \
|
rsync \
|
||||||
ttf-dejavu
|
nano \
|
||||||
|
unzip \
|
||||||
|
knockd \
|
||||||
|
ttf-dejavu \
|
||||||
|
&& apt-get clean
|
||||||
|
|
||||||
RUN addgroup -g 1000 minecraft \
|
RUN addgroup --gid 1000 minecraft \
|
||||||
&& adduser -Ss /bin/false -u 1000 -G minecraft -h /home/minecraft minecraft \
|
&& adduser --system --shell /bin/false --uid 1000 --ingroup minecraft --home /data minecraft
|
||||||
&& mkdir -m 777 /data \
|
|
||||||
&& chown minecraft:minecraft /data /home/minecraft
|
|
||||||
|
|
||||||
COPY files/sudoers* /etc/sudoers.d
|
COPY --chmod=644 files/sudoers* /etc/sudoers.d
|
||||||
|
|
||||||
EXPOSE 25565 25575
|
EXPOSE 25565 25575
|
||||||
|
|
||||||
# hook into docker BuildKit --platform support
|
# hook into docker BuildKit --platform support
|
||||||
# see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
|
# see https://docs.docker.com/engine/reference/builder/#automatic-platform-args-in-the-global-scope
|
||||||
ARG TARGETOS=linux
|
ARG TARGETOS
|
||||||
ARG TARGETARCH=amd64
|
ARG TARGETARCH
|
||||||
ARG TARGETVARIANT=""
|
ARG TARGETVARIANT
|
||||||
|
|
||||||
ARG EASY_ADD_VER=0.7.1
|
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
|
ADD https://github.com/itzg/easy-add/releases/download/${EASY_ADD_VER}/easy-add_${TARGETOS}_${TARGETARCH}${TARGETVARIANT} /usr/bin/easy-add
|
||||||
@@ -44,49 +46,49 @@ 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
|
--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} \
|
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||||
--var version=1.5.1 --var app=rcon-cli --file {{.app}} \
|
--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
|
--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} \
|
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||||
--var version=0.10.1 --var app=mc-monitor --file {{.app}} \
|
--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
|
--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} \
|
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||||
--var version=1.8.0 --var app=mc-server-runner --file {{.app}} \
|
--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
|
--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} \
|
RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||||
--var version=0.1.1 --var app=maven-metadata-release --file {{.app}} \
|
--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
|
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||||
|
|
||||||
ARG MC_HELPER_VERSION=1.6.1
|
ARG MC_HELPER_VERSION=1.16.0
|
||||||
RUN curl -fsSL https://github.com/itzg/mc-image-helper/releases/download/v${MC_HELPER_VERSION}/mc-image-helper-${MC_HELPER_VERSION}.tgz \
|
ARG MC_HELPER_BASE_URL=https://github.com/itzg/mc-image-helper/releases/download/v${MC_HELPER_VERSION}
|
||||||
| tar -C /usr/share -zxf - \
|
RUN curl -fsSL ${MC_HELPER_BASE_URL}/mc-image-helper-${MC_HELPER_VERSION}.tgz \
|
||||||
&& 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"]
|
VOLUME ["/data"]
|
||||||
COPY server.properties /tmp/server.properties
|
|
||||||
COPY log4j2.xml /tmp/log4j2.xml
|
|
||||||
WORKDIR /data
|
WORKDIR /data
|
||||||
|
|
||||||
STOPSIGNAL SIGTERM
|
STOPSIGNAL SIGTERM
|
||||||
|
|
||||||
ENV UID=1000 GID=1000 \
|
ENV UID=1000 GID=1000 \
|
||||||
JVM_XX_OPTS="-XX:+UseG1GC" MEMORY="1G" \
|
MEMORY="1G" \
|
||||||
TYPE=VANILLA VERSION=LATEST \
|
TYPE=VANILLA VERSION=LATEST \
|
||||||
ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
|
ENABLE_RCON=true RCON_PORT=25575 RCON_PASSWORD=minecraft \
|
||||||
SERVER_PORT=25565 ONLINE_MODE=TRUE SERVER_NAME="Dedicated Server" \
|
|
||||||
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 \
|
ENABLE_AUTOPAUSE=false AUTOPAUSE_TIMEOUT_EST=3600 AUTOPAUSE_TIMEOUT_KN=120 AUTOPAUSE_TIMEOUT_INIT=600 \
|
||||||
AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0
|
AUTOPAUSE_PERIOD=10 AUTOPAUSE_KNOCK_INTERFACE=eth0 \
|
||||||
|
ENABLE_AUTOSTOP=false AUTOSTOP_TIMEOUT_EST=3600 AUTOSTOP_TIMEOUT_INIT=1800 AUTOSTOP_PERIOD=10
|
||||||
|
|
||||||
COPY start* /
|
COPY --chmod=755 scripts/start* /
|
||||||
COPY bin/ /usr/local/bin/
|
COPY --chmod=755 bin/ /usr/local/bin/
|
||||||
COPY bin/mc-health /health.sh
|
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
|
||||||
|
|
||||||
ADD files/autopause /autopause
|
RUN dos2unix /start* /autopause/* /autostop/*
|
||||||
|
|
||||||
RUN dos2unix /start* && chmod +x /start* \
|
|
||||||
&& dos2unix /autopause/* && chmod +x /autopause/*.sh
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/start" ]
|
ENTRYPOINT [ "/start" ]
|
||||||
HEALTHCHECK --start-period=1m CMD mc-health
|
HEALTHCHECK --start-period=1m CMD mc-health
|
||||||
|
|||||||
416
README.md
416
README.md
@@ -24,6 +24,7 @@ By default, the container will download the latest version of the "vanilla" [Min
|
|||||||
**TABLE OF CONTENTS**
|
**TABLE OF CONTENTS**
|
||||||
|
|
||||||
<!--ts-->
|
<!--ts-->
|
||||||
|
* [Mitigated Log4jShell Vulnerability](#mitigated-log4jshell-vulnerability)
|
||||||
* [Looking for a Bedrock Dedicated Server](#looking-for-a-bedrock-dedicated-server)
|
* [Looking for a Bedrock Dedicated Server](#looking-for-a-bedrock-dedicated-server)
|
||||||
* [Interacting with the server](#interacting-with-the-server)
|
* [Interacting with the server](#interacting-with-the-server)
|
||||||
* [Data Directory](#data-directory)
|
* [Data Directory](#data-directory)
|
||||||
@@ -41,17 +42,19 @@ By default, the container will download the latest version of the "vanilla" [Min
|
|||||||
* [Troubleshooting](#troubleshooting)
|
* [Troubleshooting](#troubleshooting)
|
||||||
* [Server types](#server-types)
|
* [Server types](#server-types)
|
||||||
* [Running a Forge Server](#running-a-forge-server)
|
* [Running a Forge Server](#running-a-forge-server)
|
||||||
|
* [Running a Fabric Server](#running-a-fabric-server)
|
||||||
* [Running a Bukkit/Spigot server](#running-a-bukkitspigot-server)
|
* [Running a Bukkit/Spigot server](#running-a-bukkitspigot-server)
|
||||||
* [Running a Paper server](#running-a-paper-server)
|
* [Running a Paper server](#running-a-paper-server)
|
||||||
* [Running an Airplane server](#running-an-airplane-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 Purpur server](#running-a-purpur-server)
|
||||||
* [Running a Magma server](#running-a-magma-server)
|
* [Running a Magma server](#running-a-magma-server)
|
||||||
* [Running a Mohist server](#running-a-mohist-server)
|
* [Running a Mohist server](#running-a-mohist-server)
|
||||||
* [Running a Catserver type server](#running-a-catserver-type-server)
|
* [Running a Catserver type server](#running-a-catserver-type-server)
|
||||||
* [Running an Canyon server](#running-an-canyon-server)
|
* [Running a Canyon server](#running-a-canyon-server)
|
||||||
* [Running a SpongeVanilla server](#running-a-spongevanilla-server)
|
* [Running a SpongeVanilla server](#running-a-spongevanilla-server)
|
||||||
* [Running a Fabric Server](#running-a-fabric-server)
|
|
||||||
* [Running a Limbo server](#running-a-limbo-server)
|
* [Running a Limbo server](#running-a-limbo-server)
|
||||||
|
* [Running a Crucible server](#running-a-crucible-server)
|
||||||
* [Running a server with a Feed the Beast modpack](#running-a-server-with-a-feed-the-beast-modpack)
|
* [Running a server with a Feed the Beast modpack](#running-a-server-with-a-feed-the-beast-modpack)
|
||||||
* [Environment Variables:](#environment-variables)
|
* [Environment Variables:](#environment-variables)
|
||||||
* [Upgrading](#upgrading)
|
* [Upgrading](#upgrading)
|
||||||
@@ -60,15 +63,21 @@ By default, the container will download the latest version of the "vanilla" [Min
|
|||||||
* [Modpack data directory](#modpack-data-directory)
|
* [Modpack data directory](#modpack-data-directory)
|
||||||
* [Buggy start scripts](#buggy-start-scripts)
|
* [Buggy start scripts](#buggy-start-scripts)
|
||||||
* [Fixing "unable to launch forgemodloader"](#fixing-unable-to-launch-forgemodloader)
|
* [Fixing "unable to launch forgemodloader"](#fixing-unable-to-launch-forgemodloader)
|
||||||
|
* [Running a server with a packwiz modpack](#running-a-server-with-a-packwiz-modpack)
|
||||||
* [Working with mods and plugins](#working-with-mods-and-plugins)
|
* [Working with mods and plugins](#working-with-mods-and-plugins)
|
||||||
* [Optional plugins, mods, and config attach points](#optional-plugins-mods-and-config-attach-points)
|
* [Optional plugins, mods, and config attach points](#optional-plugins-mods-and-config-attach-points)
|
||||||
* [Auto-downloading SpigotMC/Bukkit/PaperMC plugins](#auto-downloading-spigotmcbukkitpapermc-plugins)
|
* [Auto-downloading SpigotMC/Bukkit/PaperMC plugins](#auto-downloading-spigotmcbukkitpapermc-plugins)
|
||||||
* [Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers](#downloadable-modplugin-pack-for-forge-bukkit-and-spigot-servers)
|
* [Downloadable mod/plugin pack for Forge, Fabric, and Bukkit-like Servers](#downloadable-modplugin-pack-for-forge-fabric-and-bukkit-like-servers)
|
||||||
|
* [<strong>ForgeAPI</strong> usage to use non-version specific projects](#forgeapi-usage-to-use-non-version-specific-projects)
|
||||||
|
* [Generic pack file](#generic-pack-file)
|
||||||
|
* [Mod/Plugin URL Listing File](#modplugin-url-listing-file)
|
||||||
* [Remove old mods/plugins](#remove-old-modsplugins)
|
* [Remove old mods/plugins](#remove-old-modsplugins)
|
||||||
* [Working with world data](#working-with-world-data)
|
* [Working with world data](#working-with-world-data)
|
||||||
* [Downloadable world](#downloadable-world)
|
* [Downloadable world](#downloadable-world)
|
||||||
* [Cloning world from a container path](#cloning-world-from-a-container-path)
|
* [Cloning world from a container path](#cloning-world-from-a-container-path)
|
||||||
* [Overwrite world on start](#overwrite-world-on-start)
|
* [Overwrite world on start](#overwrite-world-on-start)
|
||||||
|
* [Datapacks](#datapacks)
|
||||||
|
* [VanillaTweaks](#vanillatweaks)
|
||||||
* [Server configuration](#server-configuration)
|
* [Server configuration](#server-configuration)
|
||||||
* [Message of the Day](#message-of-the-day)
|
* [Message of the Day](#message-of-the-day)
|
||||||
* [Difficulty](#difficulty)
|
* [Difficulty](#difficulty)
|
||||||
@@ -124,15 +133,22 @@ By default, the container will download the latest version of the "vanilla" [Min
|
|||||||
* [Explicitly disable GUI](#explicitly-disable-gui)
|
* [Explicitly disable GUI](#explicitly-disable-gui)
|
||||||
* [Stop Duration](#stop-duration)
|
* [Stop Duration](#stop-duration)
|
||||||
* [Setup only](#setup-only)
|
* [Setup only](#setup-only)
|
||||||
|
* [Enable Flare Flags](#enable-flare-flags)
|
||||||
* [Autopause](#autopause)
|
* [Autopause](#autopause)
|
||||||
* [Description](#description)
|
* [Description](#description)
|
||||||
* [Enabling Autopause](#enabling-autopause)
|
* [Enabling Autopause](#enabling-autopause)
|
||||||
|
* [Autostop](#autostop)
|
||||||
* [Running on RaspberryPi](#running-on-raspberrypi)
|
* [Running on RaspberryPi](#running-on-raspberrypi)
|
||||||
|
* [Contributing](#contributing)
|
||||||
|
|
||||||
<!-- Added by: runner, at: Sat Oct 9 16:34:51 UTC 2021 -->
|
<!-- Added by: runner, at: Mon Jan 24 04:19:37 UTC 2022 -->
|
||||||
|
|
||||||
<!--te-->
|
<!--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
|
## Looking for a Bedrock Dedicated Server
|
||||||
|
|
||||||
For Minecraft clients running on consoles, mobile, or native Windows, you'll need to
|
For Minecraft clients running on consoles, mobile, or native Windows, you'll need to
|
||||||
@@ -220,6 +236,8 @@ services:
|
|||||||
- ./minecraft-data:/data
|
- ./minecraft-data:/data
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> NOTE: if you have SELinux enabled, then you might need to add `:Z` to the end of volume mount specifications, [as described here](https://prefetch.net/blog/2017/09/30/using-docker-volumes-on-selinux-enabled-servers/).
|
||||||
|
|
||||||
### Converting anonymous `/data` volume to named volume
|
### Converting anonymous `/data` volume to named volume
|
||||||
|
|
||||||
If you had used the commands in the first section, without the `-v` volume attachment, then an anonymous data volume was created by Docker. You can later bring over that content to a named or host attached volume using the following procedure.
|
If you had used the commands in the first section, without the `-v` volume attachment, then an anonymous data volume was created by Docker. You can later bring over that content to a named or host attached volume using the following procedure.
|
||||||
@@ -264,7 +282,7 @@ the server jar remain in the `/data` directory. It is safe to remove those._
|
|||||||
|
|
||||||
## Running Minecraft server on different Java version
|
## Running Minecraft server on different Java version
|
||||||
|
|
||||||
To use a different version of Java, please use a docker tag to run your Minecraft server.
|
When using the image `itzg:/minecraft-server` without a tag, the `latest` image tag is implied from the table below. To use a different version of Java, please use an alternate tag to run your Minecraft server container.
|
||||||
|
|
||||||
| Tag name | Java version | Linux | JVM Type | Architecture |
|
| Tag name | Java version | Linux | JVM Type | Architecture |
|
||||||
| -------------- | -------------|--------|----------|-------------------|
|
| -------------- | -------------|--------|----------|-------------------|
|
||||||
@@ -274,15 +292,16 @@ To use a different version of Java, please use a docker tag to run your Minecraf
|
|||||||
| java8-openj9 | 8 | Debian | OpenJ9 | amd64 |
|
| java8-openj9 | 8 | Debian | OpenJ9 | amd64 |
|
||||||
| java11 | 11 | Debian | Hotspot | amd64,arm64,armv7 |
|
| java11 | 11 | Debian | Hotspot | amd64,arm64,armv7 |
|
||||||
| java11-openj9 | 11 | Debian | OpenJ9 | amd64 |
|
| java11-openj9 | 11 | Debian | OpenJ9 | amd64 |
|
||||||
| java16 | 16 | Debian | Hotspot | amd64,arm64,armv7 |
|
| java17 | 17 | Ubuntu | Hotspot | amd64,arm64,armv7 |
|
||||||
| java16-openj9 | 16 | Debian | OpenJ9 | amd64 |
|
| java17-openj9 | 17 | Debian | OpenJ9 | amd64 |
|
||||||
| multiarch-latest | 15+ | Debian | Hotspot | amd64,arm64,armv7 |
|
|
||||||
|
|
||||||
For example, to use Java version 16 on any supported architecture:
|
For example, to use Java version 8 on any supported architecture:
|
||||||
|
|
||||||
docker run --name mc itzg/minecraft-server:java16
|
docker run --name mc itzg/minecraft-server:java8-multiarch
|
||||||
|
|
||||||
> Keep in mind that some versions of Minecraft server can't work on the newest versions of Java. Also, FORGE doesn't support openj9 JVM implementation.
|
> Keep in mind that some versions of Minecraft server, such as Forge before 1.17, can't work on the newest versions of Java. Instead, one of the Java 8 images should be used. Also, FORGE doesn't support openj9 JVM implementation.
|
||||||
|
>
|
||||||
|
> Some versions of vanilla Minecraft, such as 1.10, also do not run correctly with Java 17. If in doubt, use `java8-multiarch` for any version less than 1.17.
|
||||||
|
|
||||||
### Deprecated Image Tags
|
### Deprecated Image Tags
|
||||||
|
|
||||||
@@ -291,6 +310,8 @@ The following image tags have been deprecated and are no longer receiving update
|
|||||||
- adopt14
|
- adopt14
|
||||||
- adopt15
|
- adopt15
|
||||||
- openj9-nightly
|
- openj9-nightly
|
||||||
|
- multiarch-latest
|
||||||
|
- java16/java16-openj9
|
||||||
|
|
||||||
## Healthcheck
|
## Healthcheck
|
||||||
|
|
||||||
@@ -393,6 +414,30 @@ the URL with `FORGE_INSTALLER_URL`, such as:
|
|||||||
|
|
||||||
In both of the cases above, there is no need for the `VERSION` or `FORGEVERSION` variables.
|
In both of the cases above, there is no need for the `VERSION` or `FORGEVERSION` variables.
|
||||||
|
|
||||||
|
### Running a Fabric Server
|
||||||
|
|
||||||
|
Enable [Fabric server](https://fabricmc.net/) mode by adding a `-e TYPE=FABRIC` to your command-line. By default, the container will install the latest [fabric-loader](https://fabricmc.net/wiki/documentation:fabric_loader) using the latest [fabric-installer](https://fabricmc.net/use/), against the minecraft server version you have defined with `VERSION` (defaulting to the latest vanilla release of the game).
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -d -v /path/on/host:/data \
|
||||||
|
-e TYPE=FABRIC \
|
||||||
|
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
||||||
|
```
|
||||||
|
|
||||||
|
See the [Working with mods and plugins](#working-with-mods-and-plugins) section to set up Fabric mods and configuration.
|
||||||
|
|
||||||
|
A specific loader version other than the latest can be requested using `FABRIC_LOADER_VERSION`, such as:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker run -d -v /path/on/host:/data ... \
|
||||||
|
-e FABRIC_LOADER_VERSION=0.12.8
|
||||||
|
```
|
||||||
|
|
||||||
|
If you wish to use an alternative installer you can:
|
||||||
|
* Specify an alternative version using `FABRIC_INSTALLER_VERSION` (such as `-e FABRIC_INSTALLER_VERSION=0.10.2`)
|
||||||
|
* Provide the path to a custom installer jar available to the container with `FABRIC_INSTALLER`, relative to `/data` (such as `-e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar`)
|
||||||
|
* Provide the URL to a custom installer jar with `FABRIC_INSTALLER_URL` (such as `-e FABRIC_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar`)
|
||||||
|
|
||||||
### Running a Bukkit/Spigot server
|
### Running a Bukkit/Spigot server
|
||||||
|
|
||||||
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT` or `-e TYPE=SPIGOT` to your command-line.
|
Enable Bukkit/Spigot server mode by adding a `-e TYPE=BUKKIT` or `-e TYPE=SPIGOT` to your command-line.
|
||||||
@@ -408,7 +453,7 @@ If you are hosting your own copy of Bukkit/Spigot you can override the download
|
|||||||
|
|
||||||
You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true`
|
You can build spigot from source by adding `-e BUILD_FROM_SOURCE=true`
|
||||||
|
|
||||||
Plugins can either be managed within the `plugins` subdirectory of the [data directory](#data-directory) or you can also [attach a `/plugins` volume](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up.
|
Plugins can either be managed within the `plugins` subdirectory of the [data directory](#data-directory) or 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.
|
||||||
|
|
||||||
[You can also auto-download plugins using `SPIGET_RESOURCES`.](#auto-downloading-spigotmcbukkitpapermc-plugins)
|
[You can also auto-download plugins using `SPIGET_RESOURCES`.](#auto-downloading-spigotmcbukkitpapermc-plugins)
|
||||||
|
|
||||||
@@ -418,21 +463,15 @@ 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.
|
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)
|
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`.
|
||||||
but you can also choose to run a specific build with `-e PAPERBUILD=205`.
|
|
||||||
|
|
||||||
docker run -d -v /path/on/host:/data \
|
docker run -d -v /path/on/host:/data \
|
||||||
-e TYPE=PAPER \
|
-e TYPE=PAPER \
|
||||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
-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:
|
If you are hosting your own copy of Paper you can override the download URL with `PAPER_DOWNLOAD_URL=<url>`.
|
||||||
|
|
||||||
- -e PAPER_DOWNLOAD_URL=<url>
|
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.
|
||||||
|
|
||||||
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](#deploying-plugins-from-attached-volume). If you add plugins while the container is running, you'll need to restart it to pick those up.
|
|
||||||
|
|
||||||
[You can also auto-download plugins using `SPIGET_RESOURCES`.](#auto-downloading-spigotmcbukkitpapermc-plugins)
|
[You can also auto-download plugins using `SPIGET_RESOURCES`.](#auto-downloading-spigotmcbukkitpapermc-plugins)
|
||||||
|
|
||||||
@@ -442,12 +481,24 @@ An [Airplane](https://airplane.gg) server, which is "a stable, optimized, well s
|
|||||||
|
|
||||||
-e TYPE=AIRPLANE
|
-e TYPE=AIRPLANE
|
||||||
|
|
||||||
> 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"
|
> 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.
|
||||||
|
|
||||||
Extra variables:
|
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
|
- `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 [Flare](https://blog.airplane.gg/flare) profiler
|
- `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
|
||||||
|
|
||||||
### Running a Purpur server
|
### Running a Purpur server
|
||||||
|
|
||||||
@@ -460,7 +511,7 @@ A [Purpur](https://purpur.pl3x.net/) server, which is "drop-in replacement for P
|
|||||||
Extra variables:
|
Extra variables:
|
||||||
- `PURPUR_BUILD=LATEST` : set a specific Purpur build to use
|
- `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
|
- `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 [Flare](https://blog.airplane.gg/flare) profiler
|
- `USE_FLARE_FLAGS=false` : set to true to add appropriate flags for the built-in [Flare](https://blog.airplane.gg/flare) profiler
|
||||||
|
|
||||||
### Running a Magma server
|
### Running a Magma server
|
||||||
|
|
||||||
@@ -493,28 +544,29 @@ A [Catserver](http://catserver.moe/) type server can be used with
|
|||||||
|
|
||||||
> **NOTE** Catserver only provides a single release stream, so `VERSION` is ignored
|
> **NOTE** Catserver only provides a single release stream, so `VERSION` is ignored
|
||||||
|
|
||||||
### Running an Canyon server
|
### Running a Canyon server
|
||||||
|
|
||||||
[Canyon](https://github.com/canyonmodded/canyon) is a fork of CraftBukkit for Minecraft Beta 1.7.3. It includes multiple enhancements whilst also retaining compatibility with old Bukkit plugins and mods as much as possible.
|
[Canyon](https://github.com/canyonmodded/canyon) is a fork of CraftBukkit for Minecraft Beta 1.7.3. It includes multiple enhancements whilst also retaining compatibility with old Bukkit plugins and mods as much as possible.
|
||||||
|
|
||||||
-e VERSION=b1.7.3 -e TYPE=CANYON
|
-e VERSION=b1.7.3 -e TYPE=CANYON
|
||||||
|
|
||||||
> **NOTE** only `VERSION=b1.7.3` is supported
|
> **NOTE** only `VERSION=b1.7.3` is supported. Since that version pre-dates the health check mechanism used by this image, that will need to be disabled by setting `DISABLE_HEALTHCHECK=true`.
|
||||||
|
|
||||||
> **NOTE** only Java 8 is supported
|
By default, the latest build will be used; however, a specific build number can be selected by setting `CANYON_BUILD`, such as
|
||||||
|
|
||||||
By default the latest build will be used; however, a specific build number can be selected by setting `CANYON_BUILD`, such as
|
|
||||||
|
|
||||||
-e CANYON_BUILD=11
|
-e CANYON_BUILD=11
|
||||||
|
|
||||||
### Running a SpongeVanilla server
|
### Running a SpongeVanilla server
|
||||||
|
|
||||||
Enable SpongeVanilla server mode by adding a `-e TYPE=SPONGEVANILLA` to your command-line.
|
Enable SpongeVanilla server mode by adding a `-e TYPE=SPONGEVANILLA` to your command-line.
|
||||||
|
|
||||||
By default the container will run the latest `STABLE` version.
|
By default the container will run the latest `STABLE` version.
|
||||||
If you want to run a specific version, you can add `-e SPONGEVERSION=1.11.2-6.1.0-BETA-19` to your command-line.
|
If you want to run a specific version, you can add `-e SPONGEVERSION=1.11.2-6.1.0-BETA-19` to your command-line.
|
||||||
|
|
||||||
|
Beware that current [Sponge](https://www.spongepowered.org) `STABLE` versions for Minecraft 1.12 require using [the Java 8 tag](#running-minecraft-server-on-different-java-version):
|
||||||
|
|
||||||
docker run -d -v /path/on/host:/data -e TYPE=SPONGEVANILLA \
|
docker run -d -v /path/on/host:/data -e TYPE=SPONGEVANILLA \
|
||||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server:java8-multiarch
|
||||||
|
|
||||||
You can also choose to use the `EXPERIMENTAL` branch.
|
You can also choose to use the `EXPERIMENTAL` branch.
|
||||||
Just change it with `SPONGEBRANCH`, such as:
|
Just change it with `SPONGEBRANCH`, such as:
|
||||||
@@ -522,34 +574,6 @@ Just change it with `SPONGEBRANCH`, such as:
|
|||||||
$ docker run -d -v /path/on/host:/data ... \
|
$ docker run -d -v /path/on/host:/data ... \
|
||||||
-e TYPE=SPONGEVANILLA -e SPONGEBRANCH=EXPERIMENTAL ...
|
-e TYPE=SPONGEVANILLA -e SPONGEBRANCH=EXPERIMENTAL ...
|
||||||
|
|
||||||
### Running a Fabric Server
|
|
||||||
|
|
||||||
Enable [Fabric server](http://fabricmc.net/use/) mode by adding a `-e TYPE=FABRIC` to your command-line. By default, the container will run the latest version, but you can also choose to run a specific version with `VERSION`.
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -d -v /path/on/host:/data \
|
|
||||||
-e TYPE=FABRIC \
|
|
||||||
-p 25565:25565 -e EULA=TRUE --name mc itzg/minecraft-server
|
|
||||||
```
|
|
||||||
|
|
||||||
A specific installer version can be requested using `FABRIC_INSTALLER_VERSION`.
|
|
||||||
|
|
||||||
To use a pre-downloaded Fabric installer, place it in a directory attached into the container, such as the `/data` volume and specify the name of the installer file with `FABRIC_INSTALLER`, such as:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -d -v /path/on/host:/data ... \
|
|
||||||
-e FABRIC_INSTALLER=fabric-installer-0.5.0.32.jar ...
|
|
||||||
```
|
|
||||||
|
|
||||||
To download a Fabric installer from a custom location, such as your own file repository, specify the URL with `FABRIC_INSTALLER_URL`, such as:
|
|
||||||
|
|
||||||
```
|
|
||||||
docker run -d -v /path/on/host:/data ... \
|
|
||||||
-e FABRIC_INSTALLER_URL=http://HOST/fabric-installer-0.5.0.32.jar ...
|
|
||||||
```
|
|
||||||
|
|
||||||
In order to add mods, you have two options:
|
|
||||||
|
|
||||||
### Running a Limbo server
|
### Running a Limbo server
|
||||||
|
|
||||||
A [Limbo](https://github.com/LOOHP/Limbo) server can be run by setting `TYPE` to `LIMBO`.
|
A [Limbo](https://github.com/LOOHP/Limbo) server can be run by setting `TYPE` to `LIMBO`.
|
||||||
@@ -564,6 +588,18 @@ Configuration options with defaults:
|
|||||||
- `LIMBO_SCHEMA_FILENAME`=default.schem
|
- `LIMBO_SCHEMA_FILENAME`=default.schem
|
||||||
- `LEVEL`="Default;${LIMBO_SCHEMA_FILENAME}"
|
- `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`.
|
||||||
|
|
||||||
|
Configuration options with defaults:
|
||||||
|
|
||||||
|
- `CRUCIBLE_RELEASE`=latest
|
||||||
|
|
||||||
|
Crucible is only available for 1.7.10, so be sure to set `VERSION=1.7.10`.
|
||||||
|
|
||||||
## Running a server with a Feed the Beast modpack
|
## Running a server with a Feed the Beast modpack
|
||||||
|
|
||||||
> **NOTE** requires one of the Debian based images listed in [the Java versions section](#running-minecraft-server-on-different-java-version).
|
> **NOTE** requires one of the Debian based images listed in [the Java versions section](#running-minecraft-server-on-different-java-version).
|
||||||
@@ -635,6 +671,20 @@ then you apply a workaround by adding this to the run invocation:
|
|||||||
|
|
||||||
-e FTB_LEGACYJAVAFIXER=true
|
-e FTB_LEGACYJAVAFIXER=true
|
||||||
|
|
||||||
|
## Running a server with a packwiz modpack
|
||||||
|
|
||||||
|
[packwiz](https://packwiz.infra.link/) is a CLI tool for maintaining and providing modpack definitions, with support for both CurseForge and Modrinth as sources. See the [packwiz tutorial](https://packwiz.infra.link/tutorials/getting-started/) for more information.
|
||||||
|
|
||||||
|
To configure server mods using a packwiz modpack, set the `PACKWIZ_URL` environment variable to the location of your `pack.toml` modpack definition:
|
||||||
|
|
||||||
|
docker run -d -v /path/on/host:/data -e TYPE=FABRIC \
|
||||||
|
-e "PACKWIZ_URL=https://example.com/modpack/pack.toml" \
|
||||||
|
itzg/minecraft-server
|
||||||
|
|
||||||
|
packwiz modpack defitions are processed before other mod definitions (`MODPACK`, `MODS`, etc.) to allow for additional processing/overrides you may want to perform (in case of mods not available via Modrinth/CurseForge, or you do not maintain the pack).
|
||||||
|
|
||||||
|
> packwiz is pre-configured to only download server mods. If client-side mods are downloaded and cause issues, check your pack.toml configuration, and make sure any client-only mods are not set to `"both"`, but rather `"client"` for the side configuration item.
|
||||||
|
|
||||||
## Working with mods and plugins
|
## Working with mods and plugins
|
||||||
|
|
||||||
### Optional plugins, mods, and config attach points
|
### Optional plugins, mods, and config attach points
|
||||||
@@ -645,7 +695,7 @@ There are optional volume paths that can be attached to supply content to be cop
|
|||||||
: contents are synchronized into `/data/plugins` for Bukkit related server types. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/plugins` to take precedence over newer files in `/data/plugins`.
|
: contents are synchronized into `/data/plugins` for Bukkit related server types. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/plugins` to take precedence over newer files in `/data/plugins`.
|
||||||
|
|
||||||
`/mods`
|
`/mods`
|
||||||
: contents are synchronized into `/data/mods` for Forge related server types. The destination can be changed by setting `COPY_MODS_DEST`.
|
: contents are synchronized into `/data/mods` for Fabric and Forge related server types. The destination can be changed by setting `COPY_MODS_DEST`.
|
||||||
|
|
||||||
`/config`
|
`/config`
|
||||||
: contents are synchronized into `/data/config` by default, but can be changed with `COPY_CONFIG_DEST`. For example, `-v ./config:/config -e COPY_CONFIG_DEST=/data` will allow you to copy over files like `bukkit.yml` and so on directly into the server directory. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/config` to take precedence over newer files in `/data/config`.
|
: contents are synchronized into `/data/config` by default, but can be changed with `COPY_CONFIG_DEST`. For example, `-v ./config:/config -e COPY_CONFIG_DEST=/data` will allow you to copy over files like `bukkit.yml` and so on directly into the server directory. Set `SYNC_SKIP_NEWER_IN_DESTINATION=false` if you want files from `/config` to take precedence over newer files in `/data/config`.
|
||||||
@@ -658,7 +708,7 @@ For example: `-e REMOVE_OLD_MODS=TRUE -e REMOVE_OLD_MODS_INCLUDE="*.jar" -e REMO
|
|||||||
|
|
||||||
These paths work well if you want to have a common set of modules in a separate location, but still have multiple worlds with different server requirements in either persistent volumes or a downloadable archive.
|
These paths work well if you want to have a common set of modules in a separate location, but still have multiple worlds with different server requirements in either persistent volumes or a downloadable archive.
|
||||||
|
|
||||||
> For more flexibility with mods/plugins preparation, you can declare directories to use in [the `MODS` variable](#downloadable-modplugin-pack-for-forge-bukkit-and-spigot-servers)
|
> For more flexibility with mods/plugins preparation, you can declare directories to use in [the `MODS` variable](#downloadable-modplugin-pack-for-forge-fabric-and-bukkit-like-servers)
|
||||||
|
|
||||||
### Auto-downloading SpigotMC/Bukkit/PaperMC plugins
|
### Auto-downloading SpigotMC/Bukkit/PaperMC plugins
|
||||||
|
|
||||||
@@ -675,10 +725,10 @@ For example, the following will auto-download the [EssentialsX](https://www.spig
|
|||||||
|
|
||||||
-e SPIGET_RESOURCES=9089,34315
|
-e SPIGET_RESOURCES=9089,34315
|
||||||
|
|
||||||
### Downloadable mod/plugin pack for Forge, Bukkit, and Spigot Servers
|
### Downloadable mod/plugin pack for Forge, Fabric, and Bukkit-like Servers
|
||||||
|
|
||||||
Like the `WORLD` option above, you can specify the URL or path of a "mod pack"
|
Like the `WORLD` option above, you can specify the URL or path of a "mod pack"
|
||||||
to download and install into `mods` for Forge or `plugins` for Bukkit/Spigot.
|
to download and install into `mods` for Forge/Fabric or `plugins` for Bukkit/Spigot.
|
||||||
To use this option pass the environment variable `MODPACK`, such as
|
To use this option pass the environment variable `MODPACK`, such as
|
||||||
|
|
||||||
docker run -d -e MODPACK=http://www.example.com/mods/modpack.zip ...
|
docker run -d -e MODPACK=http://www.example.com/mods/modpack.zip ...
|
||||||
@@ -694,14 +744,83 @@ 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 ...
|
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
|
||||||
|
|
||||||
|
**NOTE:** This potentially could lead to unexpected behavior if the Mod recieves an update with unexpected behavior.
|
||||||
|
|
||||||
|
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]
|
||||||
|
* `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: **Note**: name is currently unused, but can be used to document each entry.
|
||||||
|
|
||||||
|
```json
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "fabric api",
|
||||||
|
"projectId": "306612",
|
||||||
|
"releaseType": "release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fabric voice mod",
|
||||||
|
"projectId": "416089",
|
||||||
|
"releaseType": "beta"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generic pack file
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
As an alternative to `MODS`, the variable `MODS_FILE` can be set with the path to a text file listing a mod/plugin URL on each line. For example, the following
|
||||||
|
|
||||||
|
-e MODS_FILE=/extras/mods.txt
|
||||||
|
|
||||||
|
would load from a file mounted into the container at `/extras/mods.txt`. That file might look like:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://edge.forgecdn.net/files/2965/233/Bookshelf-1.15.2-5.6.40.jar
|
||||||
|
https://edge.forgecdn.net/files/2926/27/ProgressiveBosses-2.1.5-mc1.15.2.jar
|
||||||
|
# This and next line are ignored
|
||||||
|
#https://edge.forgecdn.net/files/3248/905/goblintraders-1.3.1-1.15.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3272/32/jei-1.15.2-6.0.3.16.jar
|
||||||
|
https://edge.forgecdn.net/files/2871/647/ToastControl-1.15.2-3.0.1.jar
|
||||||
|
```
|
||||||
|
> Blank lines and lines that start with a `#` will be ignored
|
||||||
|
|
||||||
|
> [This compose file](examples/docker-compose-mods-file.yml) shows another example of using this feature.
|
||||||
|
|
||||||
|
> It is recommended to combine this option with `REMOVE_OLD_MODS=TRUE` to ensure the mods/plugins remain consistent with the file's listing.
|
||||||
|
|
||||||
### Remove old mods/plugins
|
### Remove old mods/plugins
|
||||||
|
|
||||||
When the option above is specified (`MODPACK`) you can also instruct script to
|
When the option above is specified (`MODPACK`) you can also instruct script to
|
||||||
delete old mods/plugins prior to installing new ones. This behaviour is desirable
|
delete old mods/plugins prior to installing new ones. This behaviour is desirable
|
||||||
in case you want to upgrade mods/plugins from downloaded zip file.
|
in case you want to upgrade mods/plugins from downloaded zip file.
|
||||||
To use this option pass the environment variable `REMOVE_OLD_MODS="TRUE"`, such as
|
To use this option pass the environment variable `REMOVE_OLD_MODS=TRUE`, such as
|
||||||
|
|
||||||
docker run -d -e REMOVE_OLD_MODS="TRUE" -e MODPACK=http://www.example.com/mods/modpack.zip ...
|
docker run -d -e REMOVE_OLD_MODS=TRUE -e MODPACK=http://www.example.com/mods/modpack.zip ...
|
||||||
|
|
||||||
**WARNING:** All content of the `mods` or `plugins` directory will be deleted
|
**WARNING:** All content of the `mods` or `plugins` directory will be deleted
|
||||||
before unpacking new content from the MODPACK or MODS.
|
before unpacking new content from the MODPACK or MODS.
|
||||||
@@ -710,23 +829,19 @@ before unpacking new content from the MODPACK or MODS.
|
|||||||
|
|
||||||
### Downloadable world
|
### Downloadable world
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
docker run -d -e WORLD=http://www.example.com/worlds/MySave.zip ...
|
docker run -d -e WORLD=http://www.example.com/worlds/MySave.zip ...
|
||||||
|
|
||||||
**NOTE:** This URL must be accessible from inside the container. Therefore,
|
**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.
|
||||||
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.
|
**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
|
### Cloning world from a container path
|
||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
For example, the following would initially clone the world's content
|
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.
|
||||||
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
|
docker run ... -v $HOME/worlds:/worlds:ro -e WORLD=/worlds/basic
|
||||||
@@ -739,20 +854,70 @@ The following diagram shows how this option can be used in a compose deployment
|
|||||||
### Overwrite world on start
|
### 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.
|
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.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
VANILLATWEAKS_SHARECODE: MGr52E
|
||||||
|
```
|
||||||
|
|
||||||
|
Example of expected Vanillatweaks file format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"version": "1.18",
|
||||||
|
"packs": {
|
||||||
|
"survival": [
|
||||||
|
"graves",
|
||||||
|
"multiplayer sleep",
|
||||||
|
"afk display",
|
||||||
|
"armor statues",
|
||||||
|
"unlock all recipes",
|
||||||
|
"fast leaf decay",
|
||||||
|
"coordinates hud"
|
||||||
|
],
|
||||||
|
"items": ["armored elytra"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Datapacks will be placed in `/data/$LEVEL/datapacks`
|
||||||
|
|
||||||
## Server configuration
|
## Server configuration
|
||||||
|
|
||||||
By default the server configuration will be created and set based on the following
|
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.
|
||||||
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.
|
|
||||||
|
|
||||||
If you would like to override the server configuration each time the container
|
If you would like to override the server configuration each time the container starts up, you can set the `OVERRIDE_SERVER_PROPERTIES` environment variable like:
|
||||||
starts up, you can set the OVERRIDE_SERVER_PROPERTIES environment variable like:
|
|
||||||
|
|
||||||
docker run -d -e OVERRIDE_SERVER_PROPERTIES=true ...
|
docker run -d -e OVERRIDE_SERVER_PROPERTIES=true ...
|
||||||
|
|
||||||
This will reset any manual configuration of the `server.properties` file, so if
|
This will reset any manual configuration of the `server.properties` file, so if you want to make any persistent configuration changes you will need to make sure you have properly set the proper environment variables in your container configuration.
|
||||||
you want to make any persistent configuration changes you will need to make sure
|
|
||||||
you have properly set the proper environment variables in your docker run command (described below).
|
In the opposite case, you can skip the startup script's creation of `server.properties`, by setting `SKIP_SERVER_PROPERTIES` to "true".
|
||||||
|
|
||||||
|
> NOTE: to clear a server property, set the variable to an empty string, such as `-e RESOURCE_PACK=""`. A variables that maps to a server property that is unset, is ignored and the existing `server.property` is left unchanged.
|
||||||
|
|
||||||
### Message of the Day
|
### Message of the Day
|
||||||
|
|
||||||
@@ -788,24 +953,35 @@ values.
|
|||||||
|
|
||||||
> **NOTE** it is very important to set this with servers exposed to the internet where you want only limited players to join.
|
> **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, pass the Minecraft usernames separated by commas via the `WHITELIST` environment variable, such as
|
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 ...`
|
||||||
|
|
||||||
docker run -d -e WHITELIST=user1,user2 ...
|
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.
|
||||||
|
|
||||||
If the `WHITELIST` environment variable is not used, any user can join your Minecraft server if it's publicly accessible.
|
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.
|
||||||
|
|
||||||
> NOTE: When `WHITELIST` is used the server properties `white-list` and `whitelist` will automatically get set to `true`.
|
> NOTE: You can provide both `WHITELIST_FILE` and `WHITELIST`, which are processed in that order.
|
||||||
|
|
||||||
> 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.
|
> NOTE: UUIDs passed via `WHITELIST` need to be the dashed variant, otherwise it not be recognised and instead added as a username.
|
||||||
|
|
||||||
|
> 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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
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
|
### Op/Administrator Players
|
||||||
|
|
||||||
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
|
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 ...`
|
||||||
|
|
||||||
docker run -d -e OPS=user1,user2 ...
|
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.
|
||||||
|
|
||||||
> 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.
|
> 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`.
|
||||||
|
|
||||||
### Server icon
|
### Server icon
|
||||||
|
|
||||||
@@ -821,6 +997,7 @@ The server icon which has been set doesn't get overridden by default. It can be
|
|||||||
### Rcon
|
### Rcon
|
||||||
|
|
||||||
To use rcon use the `ENABLE_RCON` and `RCON_PASSWORD` variables.
|
To use rcon use the `ENABLE_RCON` and `RCON_PASSWORD` variables.
|
||||||
|
The default RCON password is _"minecraft",_ but it's **highly** recommended to override that.
|
||||||
By default rcon port will be `25575` but can easily be changed with the `RCON_PORT` variable.
|
By default rcon port will be `25575` but can easily be changed with the `RCON_PORT` variable.
|
||||||
|
|
||||||
docker run -d -e ENABLE_RCON=true -e RCON_PASSWORD=testing
|
docker run -d -e ENABLE_RCON=true -e RCON_PASSWORD=testing
|
||||||
@@ -1002,9 +1179,9 @@ In Minecraft 1.13+ you need to pass json ([generator site](https://misode.github
|
|||||||
|
|
||||||
You can set a link to a custom resource pack and set it's checksum using the `RESOURCE_PACK` and `RESOURCE_PACK_SHA1` options respectively, the default is blank:
|
You can set a link to a custom resource pack and set it's checksum using the `RESOURCE_PACK` and `RESOURCE_PACK_SHA1` options respectively, the default is blank:
|
||||||
|
|
||||||
docker run -d -e 'RESOURCE_PACK=http\://link.com/to/pack.zip?\=1' -e 'RESOURCE_PACK_SHA1=d5db29cd03a2ed055086cef9c31c252b4587d6d0'
|
docker run -d -e 'RESOURCE_PACK=http://link.com/to/pack.zip?=1' -e 'RESOURCE_PACK_SHA1=d5db29cd03a2ed055086cef9c31c252b4587d6d0'
|
||||||
|
|
||||||
**NOTE:** `:` and `=` must be escaped using `\`. The checksum plain-text hexadecimal.
|
You can enforce the resource pack on clients by setting `RESOURCE_PACK_ENFORCE` to `TRUE` (default: `FALSE`).
|
||||||
|
|
||||||
### Level / World Save Name
|
### Level / World Save Name
|
||||||
|
|
||||||
@@ -1233,13 +1410,16 @@ The values of all three are passed directly to the JVM and support format/units
|
|||||||
|
|
||||||
-e MEMORY=2G
|
-e MEMORY=2G
|
||||||
|
|
||||||
> NOTE: the settings above only set the Java **heap** limits. Memory resource requests and limits on the overall container should also account for non-heap memory usage. An extra 25% is [a general best practice](https://dzone.com/articles/best-practices-java-memory-arguments-for-container).
|
To let the JVM calculate the heap size from the container declared memory limit, unset `MEMORY` with an empty value, such as `-e MEMORY=""`. By default, the JVM will use 25% of the container memory limit as the heap limit; however, as an example the following would tell the JVM to use 75% of the container limit of 2GB of memory:
|
||||||
|
|
||||||
|
-e MEMORY="" -e JVM_XX_OPTS="-XX:MaxRAMPercentage=75" -m 2000M
|
||||||
|
|
||||||
|
> The settings above only set the Java **heap** limits. Memory resource requests and limits on the overall container should also account for non-heap memory usage. An extra 25% is [a general best practice](https://dzone.com/articles/best-practices-java-memory-arguments-for-container).
|
||||||
|
|
||||||
### JVM Options
|
### JVM Options
|
||||||
|
|
||||||
General JVM options can be passed to the Minecraft Server invocation by passing a `JVM_OPTS`
|
General JVM options can be passed to the Minecraft Server invocation by passing a `JVM_OPTS`
|
||||||
environment variable. Options like `-X` that need to proceed general JVM options can be passed
|
environment variable. The JVM requires `-XX` options to precede `-X` options, so those can be declared in `JVM_XX_OPTS`. Both variables are space-delimited, raw JVM arguments.
|
||||||
via a `JVM_XX_OPTS` environment variable.
|
|
||||||
|
|
||||||
For some cases, if e.g. after removing mods, it could be necessary to startup minecraft with an additional `-D` parameter like `-Dfml.queryResult=confirm`. To address this you can use the environment variable `JVM_DD_OPTS`, which builds the params from a given list of values separated by space, but without the `-D` prefix. To make things running under systems (e.g. Plesk), which doesn't allow `=` inside values, a `:` (colon) could be used instead. The upper example would look like this:
|
For some cases, if e.g. after removing mods, it could be necessary to startup minecraft with an additional `-D` parameter like `-Dfml.queryResult=confirm`. To address this you can use the environment variable `JVM_DD_OPTS`, which builds the params from a given list of values separated by space, but without the `-D` prefix. To make things running under systems (e.g. Plesk), which doesn't allow `=` inside values, a `:` (colon) could be used instead. The upper example would look like this:
|
||||||
`JVM_DD_OPTS=fml.queryResult:confirm`, and will be converted to `-Dfml.queryResult=confirm`.
|
`JVM_DD_OPTS=fml.queryResult:confirm`, and will be converted to `-Dfml.queryResult=confirm`.
|
||||||
@@ -1259,6 +1439,8 @@ 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.
|
> 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.
|
> 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
|
### Server Shutdown Options
|
||||||
|
|
||||||
@@ -1313,16 +1495,12 @@ To enable remote JMX, such as for profiling with VisualVM or JMC, add the enviro
|
|||||||
|
|
||||||
### Enable Aikar's Flags
|
### Enable Aikar's Flags
|
||||||
|
|
||||||
[Aikar has does some research](https://mcflags.emc.gs/) into finding the optimal JVM flags for GC tuning, which becomes more important as more users are connected concurrently. The set of flags documented there can be added using
|
[Aikar has does some research](https://aikar.co/2018/07/02/tuning-the-jvm-g1gc-garbage-collector-flags-for-minecraft/) into finding the optimal JVM flags for GC tuning, which becomes more important as more users are connected concurrently. The set of flags documented there can be added using
|
||||||
|
|
||||||
-e USE_AIKAR_FLAGS=true
|
-e USE_AIKAR_FLAGS=true
|
||||||
|
|
||||||
When `MEMORY` is greater than or equal to 12G, then the Aikar flags will be adjusted according to the article.
|
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
|
### HTTP Proxy
|
||||||
|
|
||||||
You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL via the `PROXY`
|
You may configure the use of an HTTP/HTTPS proxy by passing the proxy's URL via the `PROXY`
|
||||||
@@ -1347,6 +1525,14 @@ When the container is signalled to stop, the Minecraft process wrapper will atte
|
|||||||
### Setup only
|
### 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`.
|
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.
|
||||||
|
|
||||||
## Autopause
|
## Autopause
|
||||||
|
|
||||||
@@ -1376,6 +1562,10 @@ Enable the Autopause functionality by setting:
|
|||||||
-e ENABLE_AUTOPAUSE=TRUE
|
-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:
|
The following environment variables define the behaviour of auto-pausing:
|
||||||
* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds)
|
* `AUTOPAUSE_TIMEOUT_EST`, default `3600` (seconds)
|
||||||
describes the time between the last client disconnect and the pausing of the process (read as timeout established)
|
describes the time between the last client disconnect and the pausing of the process (read as timeout established)
|
||||||
@@ -1388,6 +1578,28 @@ The following environment variables define the behaviour of auto-pausing:
|
|||||||
* `AUTOPAUSE_KNOCK_INTERFACE`, default `eth0`
|
* `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.
|
<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
|
## 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`.
|
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`.
|
||||||
@@ -1395,3 +1607,7 @@ To run this image on a RaspberryPi 3 B+, 4, or newer, use any of the image tags
|
|||||||
> NOTE: you may need to lower the memory allocation, such as `-e MEMORY=750m`
|
> NOTE: you may need to lower the memory allocation, such as `-e MEMORY=750m`
|
||||||
|
|
||||||
> If experiencing issues such as "sleep: cannot read realtime clock: Operation not permitted", ensure `libseccomp` is up to date on your host. In some cases adding `:Z` flag to the `/data` mount may be needed, [but use cautiously](https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label).
|
> If experiencing issues such as "sleep: cannot read realtime clock: Operation not permitted", ensure `libseccomp` is up to date on your host. In some cases adding `:Z` flag to the `/data` mount may be needed, [but use cautiously](https://docs.docker.com/storage/bind-mounts/#configure-the-selinux-label).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See [Development](DEVELOPMENT.md) and [Building](BUILDING.md).
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# shellcheck source=../start-utils
|
# shellcheck source=../scripts/start-utils
|
||||||
. ${SCRIPTS:-/}start-utils
|
. "${SCRIPTS:-/}start-utils"
|
||||||
|
if [ -f /data/.mc-health.env ]; then
|
||||||
|
. /data/.mc-health.env
|
||||||
|
fi
|
||||||
|
|
||||||
if isTrue "${DISABLE_HEALTHCHECK}"; then
|
if isTrue "${DISABLE_HEALTHCHECK}"; then
|
||||||
echo "Healthcheck disabled"
|
echo "Healthcheck disabled"
|
||||||
@@ -10,6 +13,6 @@ elif isTrue "${ENABLE_AUTOPAUSE}" && [[ "$( ps -ax -o stat,comm | grep 'java' |
|
|||||||
echo "Java process suspended by Autopause function"
|
echo "Java process suspended by Autopause function"
|
||||||
exit 0
|
exit 0
|
||||||
else
|
else
|
||||||
mc-monitor status --host localhost --port $SERVER_PORT
|
mc-monitor status "${MC_HEALTH_EXTRA_ARGS[@]}" --host localhost --port "${SERVER_PORT:-25565}"
|
||||||
exit $?
|
exit $?
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -12,4 +12,4 @@ if [ ! -p "${CONSOLE_IN_NAMED_PIPE}" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "$@" > "${CONSOLE_IN_NAMED_PIPE:-/tmp/minecraft-console-in}"
|
gosu minecraft bash -c "echo $* > '${CONSOLE_IN_NAMED_PIPE:-/tmp/minecraft-console-in}'"
|
||||||
@@ -7,9 +7,8 @@ branches_list=(
|
|||||||
'java8-openj9'
|
'java8-openj9'
|
||||||
'java11'
|
'java11'
|
||||||
'java11-openj9'
|
'java11-openj9'
|
||||||
'java16'
|
'java17'
|
||||||
'java16-openj9'
|
'java17-openj9'
|
||||||
'multiarch-latest'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
function TrapExit {
|
function TrapExit {
|
||||||
@@ -131,3 +130,28 @@ EOL
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
done
|
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
examples/.gitignore
vendored
Normal file
1
examples/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/data/
|
||||||
20
examples/docker-compose-autostop.yml
Normal file
20
examples/docker-compose-autostop.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
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: {}
|
||||||
@@ -2,12 +2,18 @@ version: '3.8'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
mc:
|
mc:
|
||||||
image: itzg/minecraft-server:java8
|
image: itzg/minecraft-server:${IMAGE_TAG:-java8}
|
||||||
volumes:
|
volumes:
|
||||||
- ./modpacks:/modpacks:ro
|
- ./modpacks:/modpacks:ro
|
||||||
|
- data:/data
|
||||||
environment:
|
environment:
|
||||||
EULA: "true"
|
EULA: "true"
|
||||||
TYPE: CURSEFORGE
|
TYPE: CURSEFORGE
|
||||||
CF_SERVER_MOD: /modpacks/SkyFactory_4_Server_4.1.0.zip
|
CF_SERVER_MOD: https://media.forgecdn.net/files/3482/169/Valhelsia+3-3.4.4-SERVER.zip
|
||||||
|
# CF_SERVER_MOD: https://media.forgecdn.net/files/3012/800/SkyFactory-4_Server_4.2.2.zip
|
||||||
|
# CF_SERVER_MOD: /modpacks/${MODPACK:-SkyFactory_4_Server_4.1.0.zip}
|
||||||
ports:
|
ports:
|
||||||
- 25565:25565
|
- "25565:25565"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data: {}
|
||||||
@@ -2,15 +2,16 @@ version: "3.8"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
mc:
|
mc:
|
||||||
image: itzg/minecraft-server:java8
|
image: itzg/minecraft-server
|
||||||
ports:
|
ports:
|
||||||
# expose the Minecraft server port outside of container
|
# expose the Minecraft server port outside of container
|
||||||
- 25565:25565
|
- "25565:25565"
|
||||||
environment:
|
environment:
|
||||||
# REQUIRED for all types
|
# REQUIRED for all types
|
||||||
EULA: "TRUE"
|
EULA: "TRUE"
|
||||||
# Set server type (vs the default of vanilla)
|
# Set server type (vs the default of vanilla)
|
||||||
TYPE: FORGE
|
TYPE: FORGE
|
||||||
|
DEBUG: "true"
|
||||||
volumes:
|
volumes:
|
||||||
# use a named, managed volume for data volume
|
# use a named, managed volume for data volume
|
||||||
- mc_forge:/data
|
- mc_forge:/data
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
mc:
|
mc:
|
||||||
# FTBA support is only available in non-Alpine images
|
# FTBA support is only available in non-Alpine images
|
||||||
image: itzg/minecraft-server:java8-multiarch
|
image: itzg/minecraft-server:${IMAGE_TAG:-java8-multiarch}
|
||||||
ports:
|
ports:
|
||||||
# expose the Minecraft server port outside of container
|
# expose the Minecraft server port outside of container
|
||||||
- 25565:25565
|
- 25565:25565
|
||||||
@@ -14,10 +14,11 @@ services:
|
|||||||
TYPE: FTBA
|
TYPE: FTBA
|
||||||
# Use Pack ID from https://ftb.neptunepowered.org/pack/ftb-presents-direwolf20-1-12/
|
# Use Pack ID from https://ftb.neptunepowered.org/pack/ftb-presents-direwolf20-1-12/
|
||||||
FTB_MODPACK_ID: "31"
|
FTB_MODPACK_ID: "31"
|
||||||
|
FTB_MODPACK_VERSION_ID: ""
|
||||||
volumes:
|
volumes:
|
||||||
# use a named, managed volume for data volume
|
# use a named, managed volume for data volume
|
||||||
- mc_ftb:/data
|
- ftba:/data
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
# declared the named volume, but use default/local storage engine
|
# declared the named volume, but use default/local storage engine
|
||||||
mc_ftb: {}
|
ftba: {}
|
||||||
|
|||||||
21
examples/docker-compose-generic-pack.yml
Normal file
21
examples/docker-compose-generic-pack.yml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
mc:
|
||||||
|
image: itzg/minecraft-server:${IMAGE_TAG:-latest}
|
||||||
|
volumes:
|
||||||
|
- data:/data
|
||||||
|
- ./modpacks:/modpacks:ro
|
||||||
|
environment:
|
||||||
|
EULA: "true"
|
||||||
|
TYPE: FORGE
|
||||||
|
DEBUG: "${DEBUG:-false}"
|
||||||
|
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"
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data: {}
|
||||||
19
examples/docker-compose-mods-file.yml
Normal file
19
examples/docker-compose-mods-file.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
mc:
|
||||||
|
image: itzg/minecraft-server
|
||||||
|
environment:
|
||||||
|
EULA: "true"
|
||||||
|
TYPE: FORGE
|
||||||
|
VERSION: 1.15.2
|
||||||
|
MODS_FILE: /extras/mods.txt
|
||||||
|
REMOVE_OLD_MODS: "true"
|
||||||
|
ports:
|
||||||
|
- 25565:25565
|
||||||
|
volumes:
|
||||||
|
- data:/data
|
||||||
|
- ./mods.txt:/extras/mods.txt:ro
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data:
|
||||||
17
examples/docker-compose-mohist.yml
Normal file
17
examples/docker-compose-mohist.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
mc:
|
||||||
|
image: itzg/minecraft-server
|
||||||
|
ports:
|
||||||
|
- "25565:25565"
|
||||||
|
environment:
|
||||||
|
EULA: "TRUE"
|
||||||
|
TYPE: MOHIST
|
||||||
|
VERSION: 1.12.2
|
||||||
|
DEBUG: "true"
|
||||||
|
volumes:
|
||||||
|
- data:/data
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
data: {}
|
||||||
@@ -1,18 +1,19 @@
|
|||||||
version: '3.8'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
mc:
|
mc:
|
||||||
image: itzg/minecraft-server
|
image: itzg/minecraft-server
|
||||||
|
container_name: paper
|
||||||
environment:
|
environment:
|
||||||
EULA: "true"
|
EULA: "true"
|
||||||
|
ENABLE_RCON: "true"
|
||||||
TYPE: PAPER
|
TYPE: PAPER
|
||||||
VERSION: 1.9.4
|
VIEW_DISTANCE: 10
|
||||||
# needed for Paper versions before 1.14
|
MEMORY: 2G
|
||||||
CONSOLE: "false"
|
CONSOLE: "false"
|
||||||
ports:
|
ports:
|
||||||
- 25565:25565
|
- 25565:25565
|
||||||
volumes:
|
volumes:
|
||||||
- mc-paper:/data
|
- mc-paper:/data
|
||||||
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
mc-paper:
|
mc-paper:
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ apiVersion: apps/v1
|
|||||||
kind: StatefulSet
|
kind: StatefulSet
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: example
|
app: mc-example
|
||||||
name: example
|
name: mc-example
|
||||||
spec:
|
spec:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
serviceName: example
|
serviceName: mc-example
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: example
|
app: mc-example
|
||||||
template:
|
template:
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
app: example
|
app: mc-example
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: mc
|
- name: mc
|
||||||
@@ -25,6 +25,18 @@ spec:
|
|||||||
volumeMounts:
|
volumeMounts:
|
||||||
- mountPath: /data
|
- mountPath: /data
|
||||||
name: data
|
name: data
|
||||||
|
readinessProbe:
|
||||||
|
exec:
|
||||||
|
command:
|
||||||
|
- mc-monitor
|
||||||
|
- status
|
||||||
|
- --host
|
||||||
|
- localhost
|
||||||
|
- --port
|
||||||
|
- "25565"
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
periodSeconds: 5
|
||||||
|
failureThreshold: 18
|
||||||
volumeClaimTemplates:
|
volumeClaimTemplates:
|
||||||
- metadata:
|
- metadata:
|
||||||
name: data
|
name: data
|
||||||
@@ -39,12 +51,12 @@ apiVersion: v1
|
|||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
labels:
|
labels:
|
||||||
service: example
|
service: mc-example
|
||||||
name: example
|
name: mc-example
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- port: 25565
|
- port: 25565
|
||||||
targetPort: 25565
|
targetPort: 25565
|
||||||
selector:
|
selector:
|
||||||
app: example
|
app: mc-example
|
||||||
type: LoadBalancer
|
type: NodePort
|
||||||
|
|||||||
80
examples/mods.txt
Normal file
80
examples/mods.txt
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
https://edge.forgecdn.net/files/2965/233/Bookshelf-1.15.2-5.6.40.jar
|
||||||
|
https://edge.forgecdn.net/files/2926/27/ProgressiveBosses-2.1.5-mc1.15.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3248/905/goblintraders-1.3.1-1.15.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3272/32/jei-1.15.2-6.0.3.16.jar
|
||||||
|
https://edge.forgecdn.net/files/2871/647/ToastControl-1.15.2-3.0.1.jar
|
||||||
|
https://edge.forgecdn.net/files/3101/903/Druidcraft-1.15-0.4.45.jar
|
||||||
|
https://edge.forgecdn.net/files/2880/426/DefaultOptions_1.15.2-11.0.1.jar
|
||||||
|
https://edge.forgecdn.net/files/2996/535/MekanismAdditions-1.15.2-9.10.9.422.jar
|
||||||
|
https://edge.forgecdn.net/files/3147/275/blockcarpentry-1.15-0.8.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3005/715/refinedstorageaddons-0.6.3.jar
|
||||||
|
https://edge.forgecdn.net/files/3140/146/rftoolsbase-1.15-1.1.10.jar
|
||||||
|
https://edge.forgecdn.net/files/3236/649/cc-tweaked-1.15.2-1.95.3.jar
|
||||||
|
https://edge.forgecdn.net/files/3048/970/light-overlay-4.7.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3015/904/randompatches-1.15.2-1.22.1.1.jar
|
||||||
|
https://edge.forgecdn.net/files/3131/439/engineersdecor-1.15.2-1.1.4.jar
|
||||||
|
https://edge.forgecdn.net/files/3051/255/carryon-1.15.2-1.13.0.5.jar
|
||||||
|
https://edge.forgecdn.net/files/3175/752/EnderStorage-1.15.2-2.5.2.164-universal.jar
|
||||||
|
https://edge.forgecdn.net/files/2997/84/Savage-and-Ravage-1.15.2-1.1.4.jar
|
||||||
|
https://edge.forgecdn.net/files/3053/840/PackMenu-1.15.2-1.2.8.jar
|
||||||
|
https://edge.forgecdn.net/files/3003/397/JEITweaker-1.15.2-1.0.1.3.jar
|
||||||
|
https://edge.forgecdn.net/files/3069/489/absentbydesign-1.15.2-1.1.1.jar
|
||||||
|
https://edge.forgecdn.net/files/2997/601/Upgrade-Aquatic-1.15.2-1.7.1.jar
|
||||||
|
https://edge.forgecdn.net/files/2950/766/ReAuth-1.14-1.15-3.8.1.jar
|
||||||
|
https://edge.forgecdn.net/files/3024/179/Powah-1.15.2-1.1.15.jar
|
||||||
|
https://edge.forgecdn.net/files/3092/975/StorageDrawers-1.15.2-7.0.3.jar
|
||||||
|
https://edge.forgecdn.net/files/2853/267/furniture-7.0.0-pre16-1.15.1.jar
|
||||||
|
https://edge.forgecdn.net/files/2987/251/AppleSkin-mc1.15.2-forge-1.0.14.jar
|
||||||
|
https://edge.forgecdn.net/files/2980/323/industrial-foregoing-1.15.2-2.3.3-e356e61.jar
|
||||||
|
https://edge.forgecdn.net/files/3024/178/Lollipop-1.15.2-1.0.16.jar
|
||||||
|
https://edge.forgecdn.net/files/3210/106/tablechair-1.4.jar
|
||||||
|
https://edge.forgecdn.net/files/3047/358/xercapaint-1.15.2-3.3.jar
|
||||||
|
https://edge.forgecdn.net/files/2873/657/BonsaiTrees-2.1.2.6.jar
|
||||||
|
https://edge.forgecdn.net/files/2938/583/config-2-3.0.jar
|
||||||
|
https://edge.forgecdn.net/files/2991/235/Waystones_1.15.2-6.0.2.jar
|
||||||
|
https://edge.forgecdn.net/files/2957/23/OpenLoader-1.15.2-4.0.5.jar
|
||||||
|
https://edge.forgecdn.net/files/3275/718/XaerosWorldMap_1.13.2_Forge_1.15.2.jar
|
||||||
|
https://edge.forgecdn.net/files/2876/104/AI-Improvements-1.15.2-0.3.0.jar
|
||||||
|
https://edge.forgecdn.net/files/3005/515/mysticallib-1.15.2-2.0.1.jar
|
||||||
|
https://edge.forgecdn.net/files/3008/867/WAWLA-1.15.2-3.0.4.jar
|
||||||
|
https://edge.forgecdn.net/files/2964/474/WailaHarvestability-mc1.15.2-1.1.12.jar
|
||||||
|
https://edge.forgecdn.net/files/3103/508/Kiwi-1.15.2-2.8.5.jar
|
||||||
|
https://edge.forgecdn.net/files/3128/662/Atum-1.15.2-2.1.12.jar
|
||||||
|
https://edge.forgecdn.net/files/2988/910/Buzzier-Bees-1.15.2-1.5.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3030/627/u_team_core-1.15.2-3.0.2.169.jar
|
||||||
|
https://edge.forgecdn.net/files/3003/984/SilentLib-1.15.2-4.6.6+59.jar
|
||||||
|
https://edge.forgecdn.net/files/2968/353/refinedpipes-0.4.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3140/149/rftoolsbuilder-1.15-2.1.16.jar
|
||||||
|
https://edge.forgecdn.net/files/3067/203/mightyarchitect-mc1.15.2_v0.5.jar
|
||||||
|
https://edge.forgecdn.net/files/2980/153/EquipmentTooltips-1.15.2-1.4.3+14.jar
|
||||||
|
https://edge.forgecdn.net/files/3103/510/FruitTrees-1.15.2-1.7.0.jar
|
||||||
|
https://edge.forgecdn.net/files/2989/38/Atmospheric-1.15.2-1.4.1.jar
|
||||||
|
https://edge.forgecdn.net/files/3096/836/rftoolscontrol-1.15-3.0.9.jar
|
||||||
|
https://edge.forgecdn.net/files/2989/662/Enhanced-Mushrooms-1.15.2-v1.2.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3227/891/SimpleStorageNetwork-1.15.2-1.0.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3217/290/minecolonies-0.13.645-RELEASE-universal.jar
|
||||||
|
https://edge.forgecdn.net/files/2935/384/SnowRealMagic-1.15.2-1.7.5.jar
|
||||||
|
https://edge.forgecdn.net/files/2988/584/aiotbotania-1.15.2-1.2.3.jar
|
||||||
|
https://edge.forgecdn.net/files/3255/408/mowziesmobs-1.5.15.jar
|
||||||
|
https://edge.forgecdn.net/files/3062/510/HealthOverlay-1.15.2-1.0.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3023/121/neoncraft-1.1.jar
|
||||||
|
https://edge.forgecdn.net/files/2997/617/Swamp-Expansion-1.15.2-1.7.3.jar
|
||||||
|
https://edge.forgecdn.net/files/2980/252/titanium-1.15.2-2.4.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3152/946/rftoolsutility-1.15-2.1.20.jar
|
||||||
|
https://edge.forgecdn.net/files/3083/277/swingthroughgrass-1.15.2-1.4.1.jar
|
||||||
|
https://edge.forgecdn.net/files/3138/530/SilentGear-1.15.2-1.11.4+187.jar
|
||||||
|
https://edge.forgecdn.net/files/3105/429/DarkUtilities-1.15.2-3.1.9.jar
|
||||||
|
https://edge.forgecdn.net/files/3099/23/ImmersiveEngineering-1.15.2-4.1.1-125.jar
|
||||||
|
https://edge.forgecdn.net/files/2856/529/FastFurnace-1.15.1-3.0.0.jar
|
||||||
|
https://edge.forgecdn.net/files/2988/999/BiomesOPlenty-1.15.2-10.0.0.366-universal.jar
|
||||||
|
https://edge.forgecdn.net/files/2989/95/The-Endergetic-Expansion-1.15.2-v1.3.2.jar
|
||||||
|
https://edge.forgecdn.net/files/2993/960/FluxNetworks-1.15.2-5.0.3-4.jar
|
||||||
|
https://edge.forgecdn.net/files/3028/611/ServerTabInfo-1.15.2-1.2.8.jar
|
||||||
|
https://edge.forgecdn.net/files/3134/277/fairylights-3.0.15-1.15.2.jar
|
||||||
|
https://edge.forgecdn.net/files/3048/54/useful_backpacks-1.15.2-1.10.3.77.jar
|
||||||
|
https://edge.forgecdn.net/files/3273/515/mcw-trapdoors-1.0.2-mc1.15.2.jar
|
||||||
|
https://edge.forgecdn.net/files/2986/639/CraftingTweaks_1.15.2-11.0.1.jar
|
||||||
|
https://edge.forgecdn.net/files/3261/454/create-mc1.15.2_v0.3.1a.jar
|
||||||
|
https://edge.forgecdn.net/files/3211/10/supermartijn642configlib-1.0.5-mc1.15.jar
|
||||||
|
https://edge.forgecdn.net/files/2995/786/TerraForged-1.15.2-0.0.15.jar
|
||||||
|
https://edge.forgecdn.net/files/2892/562/leavesdecayonotherleaves-1.1.jar
|
||||||
27
examples/vanilla-tweaks/docker-compose.yml
Normal file
27
examples/vanilla-tweaks/docker-compose.yml
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
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"
|
||||||
15
examples/vanilla-tweaks/vanillatweaks-datapacks.json
Normal file
15
examples/vanilla-tweaks/vanillatweaks-datapacks.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"version": "1.18",
|
||||||
|
"packs": {
|
||||||
|
"survival": [
|
||||||
|
"graves",
|
||||||
|
"multiplayer sleep",
|
||||||
|
"afk display",
|
||||||
|
"armor statues",
|
||||||
|
"unlock all recipes",
|
||||||
|
"fast leaf decay",
|
||||||
|
"coordinates hud"
|
||||||
|
],
|
||||||
|
"items": ["armored elytra"]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,31 +1,31 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
current_uptime() {
|
current_uptime() {
|
||||||
echo $(awk '{print $1}' /proc/uptime | cut -d . -f 1)
|
awk '{print $1}' /proc/uptime | cut -d . -f 1
|
||||||
}
|
}
|
||||||
|
|
||||||
java_running() {
|
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() {
|
java_process_exists() {
|
||||||
[[ -n "$(ps -a -o comm | grep 'java')" ]]
|
[[ -n "$(ps -ax -o comm | grep 'java')" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
rcon_client_exists() {
|
rcon_client_exists() {
|
||||||
[[ -n "$(ps -a -o comm | grep 'rcon-cli')" ]]
|
[[ -n "$(ps -ax -o comm | grep 'rcon-cli')" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
mc_server_listening() {
|
mc_server_listening() {
|
||||||
mc-monitor status --host localhost --port $SERVER_PORT --timeout 10s >& /dev/null
|
mc-monitor status --host localhost --port "$SERVER_PORT" --timeout 10s >& /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
java_clients_connected() {
|
java_clients_connected() {
|
||||||
local connections
|
local connections
|
||||||
if java_running ; then
|
if java_running ; then
|
||||||
connections=$(mc-monitor status --host localhost --port $SERVER_PORT --show-player-count)
|
connections=$(mc-monitor status --host localhost --port "$SERVER_PORT" --show-player-count)
|
||||||
else
|
else
|
||||||
connections=0
|
connections=0
|
||||||
fi
|
fi
|
||||||
(( $connections > 0 ))
|
(( connections > 0 ))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
[unpauseMCServer-server]
|
[unpauseMCServer-server]
|
||||||
sequence = 25565
|
sequence = 25565
|
||||||
seq_timeout = 1
|
seq_timeout = 1
|
||||||
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
|
command = /usr/sbin/gosu minecraft:minecraft /autopause/resume.sh
|
||||||
tcpflags = syn
|
tcpflags = syn
|
||||||
[unpauseMCServer-rcon]
|
[unpauseMCServer-rcon]
|
||||||
sequence = 25575
|
sequence = 25575
|
||||||
seq_timeout = 1
|
seq_timeout = 1
|
||||||
command = /sbin/su-exec minecraft:minecraft /autopause/resume.sh
|
command = /usr/sbin/gosu minecraft:minecraft /autopause/resume.sh
|
||||||
tcpflags = syn
|
tcpflags = syn
|
||||||
[unpauseMCServer-bedrock]
|
[unpauseMCServer-bedrock]
|
||||||
sequence = 19132:udp
|
sequence = 19132:udp
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
. /start-utils
|
. /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
|
# save world
|
||||||
rcon-cli save-all >/dev/null
|
rcon-cli save-all >/dev/null
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
. /start-utils
|
. /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"
|
logAutopauseAction "Knocked, resuming Java process"
|
||||||
pkill -CONT java
|
pkill -CONT java
|
||||||
fi
|
fi
|
||||||
|
|||||||
69
files/autostop/autostop-daemon.sh
Executable file
69
files/autostop/autostop-daemon.sh
Executable file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/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
|
||||||
6
files/autostop/stop.sh
Executable file
6
files/autostop/stop.sh
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
. /start-utils
|
||||||
|
|
||||||
|
logAutostopAction "Stopping Java process"
|
||||||
|
kill -SIGTERM 1
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<Console name="SysOut" target="SYSTEM_OUT">
|
<Console name="SysOut" target="SYSTEM_OUT">
|
||||||
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
|
<PatternLayout pattern="[%d{HH:mm:ss}] [%t/%level]: %msg%n" />
|
||||||
</Console>
|
</Console>
|
||||||
<Queue name="ServerGuiConsole">
|
<Queue name="TerminalConsole">
|
||||||
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
<PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg%n" />
|
||||||
</Queue>
|
</Queue>
|
||||||
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
<RollingRandomAccessFile name="File" fileName="logs/latest.log" filePattern="logs/%d{yyyy-MM-dd}-%i.log.gz">
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
</filters>
|
</filters>
|
||||||
<AppenderRef ref="SysOut"/>
|
<AppenderRef ref="SysOut"/>
|
||||||
<AppenderRef ref="File"/>
|
<AppenderRef ref="File"/>
|
||||||
<AppenderRef ref="ServerGuiConsole"/>
|
<AppenderRef ref="TerminalConsole"/>
|
||||||
</Root>
|
</Root>
|
||||||
</Loggers>
|
</Loggers>
|
||||||
</Configuration>
|
</Configuration>
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Moved to top-level
|
|
||||||
|
|
||||||
The contents of this directory have now been moved to the top level of
|
|
||||||
[itzg/docker-minecraft-server](https://github.com/itzg/docker-minecraft-server).
|
|
||||||
@@ -40,7 +40,7 @@ if ! isTrue "${SKIP_SUDO:-false}" && [ $(id -u) = 0 ]; then
|
|||||||
echo 'hosts: files dns' > /etc/nsswitch.conf
|
echo 'hosts: files dns' > /etc/nsswitch.conf
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec su-exec ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration $@
|
exec gosu ${runAsUser}:${runAsGroup} ${SCRIPTS:-/}start-configuration "$@"
|
||||||
else
|
else
|
||||||
exec ${SCRIPTS:-/}start-configuration $@
|
exec ${SCRIPTS:-/}start-configuration "$@"
|
||||||
fi
|
fi
|
||||||
@@ -1,9 +1,15 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
|
|
||||||
|
: "${SERVER_PORT:=25565}"
|
||||||
|
export SERVER_PORT
|
||||||
|
|
||||||
log "Autopause functionality enabled"
|
log "Autopause functionality enabled"
|
||||||
|
|
||||||
|
isDebugging && set -x
|
||||||
|
|
||||||
cp /autopause/knockd-config.cfg /tmp/knockd-config.cfg
|
cp /autopause/knockd-config.cfg /tmp/knockd-config.cfg
|
||||||
|
|
||||||
# update server port to listen to
|
# update server port to listen to
|
||||||
34
scripts/start-autostop
Executable file
34
scripts/start-autostop
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/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 &
|
||||||
@@ -32,6 +32,15 @@ if [ ! -e /data/eula.txt ]; then
|
|||||||
writeEula
|
writeEula
|
||||||
fi
|
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
|
if [[ $PROXY ]]; then
|
||||||
export http_proxy="$PROXY"
|
export http_proxy="$PROXY"
|
||||||
@@ -59,7 +68,7 @@ fi
|
|||||||
|
|
||||||
if ! which java > /dev/null; then
|
if ! which java > /dev/null; then
|
||||||
log "Fixing PATH to include java"
|
log "Fixing PATH to include java"
|
||||||
PATH="${PATH}:/usr/bin"
|
PATH="${PATH}:/opt/java/openjdk/bin"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
|
export VERSIONS_JSON=https://launchermeta.mojang.com/mc/game/version_manifest.json
|
||||||
@@ -92,6 +101,18 @@ if isTrue "${ENABLE_AUTOPAUSE}"; then
|
|||||||
${SCRIPTS:-/}start-autopause
|
${SCRIPTS:-/}start-autopause
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if isTrue "${ENABLE_AUTOSTOP}"; then
|
||||||
|
${SCRIPTS:-/}start-autostop
|
||||||
|
fi
|
||||||
|
|
||||||
|
if versionLessThan 1.7; then
|
||||||
|
echo "
|
||||||
|
MC_HEALTH_EXTRA_ARGS=(
|
||||||
|
--use-server-list-ping
|
||||||
|
)
|
||||||
|
" > /data/.mc-health.env
|
||||||
|
fi
|
||||||
|
|
||||||
log "Resolving type given ${TYPE}"
|
log "Resolving type given ${TYPE}"
|
||||||
case "${TYPE^^}" in
|
case "${TYPE^^}" in
|
||||||
*BUKKIT|SPIGOT)
|
*BUKKIT|SPIGOT)
|
||||||
@@ -103,6 +124,14 @@ case "${TYPE^^}" in
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
FORGE)
|
FORGE)
|
||||||
|
if versionLessThan 1.17; then
|
||||||
|
log "**********************************************************************"
|
||||||
|
log "WARNING: The image tag itzg/minecraft-server:java8 is recommended"
|
||||||
|
log " since some mods require Java 8"
|
||||||
|
log " Exception traces reporting ClassCastException: class jdk.internal.loader.ClassLoaders\$AppClassLoader"
|
||||||
|
log " can be fixed with java8"
|
||||||
|
log "**********************************************************************"
|
||||||
|
fi
|
||||||
exec ${SCRIPTS:-/}start-deployForge "$@"
|
exec ${SCRIPTS:-/}start-deployForge "$@"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -110,7 +139,15 @@ case "${TYPE^^}" in
|
|||||||
exec ${SCRIPTS:-/}start-deployFabric "$@"
|
exec ${SCRIPTS:-/}start-deployFabric "$@"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
FTBA)
|
||||||
|
exec ${SCRIPTS:-/}start-deployFTBA "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
FTB|CURSEFORGE)
|
FTB|CURSEFORGE)
|
||||||
|
log "**********************************************************************"
|
||||||
|
log "NOTE: Some mods and modpacks may require Java 8."
|
||||||
|
log " If so, use itzg/minecraft-server:java8"
|
||||||
|
log "**********************************************************************"
|
||||||
exec ${SCRIPTS:-/}start-deployCF "$@"
|
exec ${SCRIPTS:-/}start-deployCF "$@"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
@@ -126,10 +163,6 @@ case "${TYPE^^}" in
|
|||||||
exec ${SCRIPTS:-/}start-deployCustom "$@"
|
exec ${SCRIPTS:-/}start-deployCustom "$@"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
CURSE_INSTANCE)
|
|
||||||
exec ${SCRIPTS:-/}start-validateCurseInstance "$@"
|
|
||||||
;;
|
|
||||||
|
|
||||||
MAGMA)
|
MAGMA)
|
||||||
exec ${SCRIPTS:-/}start-deployMagma "$@"
|
exec ${SCRIPTS:-/}start-deployMagma "$@"
|
||||||
;;
|
;;
|
||||||
@@ -150,6 +183,10 @@ case "${TYPE^^}" in
|
|||||||
exec ${SCRIPTS:-/}start-deployAirplane "$@"
|
exec ${SCRIPTS:-/}start-deployAirplane "$@"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
PUFFERFISH)
|
||||||
|
exec ${SCRIPTS:-/}start-deployPufferfish "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
CANYON)
|
CANYON)
|
||||||
exec ${SCRIPTS:-/}start-deployCanyon "$@"
|
exec ${SCRIPTS:-/}start-deployCanyon "$@"
|
||||||
;;
|
;;
|
||||||
@@ -158,11 +195,21 @@ case "${TYPE^^}" in
|
|||||||
exec ${SCRIPTS:-/}start-deployLimbo "$@"
|
exec ${SCRIPTS:-/}start-deployLimbo "$@"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
CRUCIBLE)
|
||||||
|
log "**********************************************************************"
|
||||||
|
log "WARNING: The image tag itzg/minecraft-server:java8 is recommended"
|
||||||
|
log " since some mods require Java 8"
|
||||||
|
log " Exception traces reporting ClassCastException: class jdk.internal.loader.ClassLoaders\$AppClassLoader"
|
||||||
|
log " can be fixed with java8"
|
||||||
|
log "**********************************************************************"
|
||||||
|
exec "${SCRIPTS:-/}start-deployCrucible" "$@"
|
||||||
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
log "Invalid type: '$TYPE'"
|
log "Invalid type: '$TYPE'"
|
||||||
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
|
log "Must be: VANILLA, FORGE, BUKKIT, SPIGOT, PAPER, FTBA (multiarch-only),"
|
||||||
log " CURSE_INSTANCE, CURSEFORGE, SPONGEVANILLA, PURPUR, CUSTOM,"
|
log " CURSEFORGE, SPONGEVANILLA, PURPUR, CUSTOM,"
|
||||||
log " MAGMA, MOHIST, CATSERVER, AIRPLANE, CANYON, LIMBO"
|
log " MAGMA, MOHIST, CATSERVER, AIRPLANE, PUFFERFISH, CANYON, LIMBO, CRUCIBLE"
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
|
|
||||||
47
scripts/start-deployAirplane
Executable file
47
scripts/start-deployAirplane
Executable file
@@ -0,0 +1,47 @@
|
|||||||
|
#!/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."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
: ${AIRPLANE_TYPE:=airplane}
|
||||||
|
|
||||||
|
if [ "${VERSION}" = "LATEST" ] ; then
|
||||||
|
AIRPLANE_TYPE="airplane"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${VERSION}" = "PURPUR" ]; then
|
||||||
|
AIRPLANE_TYPE="airplanepurpur"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Using ${AIRPLANE_TYPE} 1.17.1 (1.18 unsupported - use Paper/Pufferfish/Purpur for newer versions)"
|
||||||
|
|
||||||
|
export SERVER=${AIRPLANE_TYPE}-1.17.1.jar
|
||||||
|
|
||||||
|
log "Removing old Airplane versions ..."
|
||||||
|
shopt -s nullglob
|
||||||
|
for f in airplane*.jar; do
|
||||||
|
[[ $f != $SERVER ]] && rm $f
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ! -f "$SERVER" ] || isTrue "${FORCE_REDOWNLOAD:-false}"; then
|
||||||
|
downloadUrl="https://airplane.gg/dl/launcher-${AIRPLANE_TYPE}1.17.1.jar"
|
||||||
|
log "Downloading Airplane 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
|
||||||
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
|
exec "${SCRIPTS:-/}start-spiget" "$@"
|
||||||
@@ -64,7 +64,7 @@ function downloadSpigot {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -z $downloadUrl ]]; then
|
if [[ -z $downloadUrl ]]; then
|
||||||
if versionLessThan 1.16.5; then
|
if versionLessThan 1.16.5 || ([[ ${getbukkitFlavor} = "craftbukkit" ]] && [[ ${VANILLA_VERSION} = "1.16.5" ]]); then
|
||||||
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
downloadUrl="https://cdn.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
||||||
else
|
else
|
||||||
downloadUrl="https://download.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
downloadUrl="https://download.getbukkit.org/${getbukkitFlavor}/${getbukkitFlavor}-${VANILLA_VERSION}.jar"
|
||||||
@@ -126,7 +126,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Normalize on Spigot for operations below
|
# Normalize on Spigot for operations below
|
||||||
export TYPE=SPIGOT
|
export FAMILY=SPIGOT
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
|
|
||||||
loadForgeVars() {
|
loadForgeVars() {
|
||||||
cfgFile=${1?}
|
cfgFile=${1?}
|
||||||
@@ -23,7 +24,7 @@ loadForgeVars() {
|
|||||||
|
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
|
|
||||||
: ${FTB_BASE_DIR:=${CF_BASE_DIR:-/data/FeedTheBeast}}
|
: "${FTB_BASE_DIR:=${CF_BASE_DIR:-/data/FeedTheBeast}}"
|
||||||
export FTB_BASE_DIR
|
export FTB_BASE_DIR
|
||||||
|
|
||||||
legacyJavaFixerUrl=https://ftb.forgecdn.net/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
|
legacyJavaFixerUrl=https://ftb.forgecdn.net/FTB2/maven/net/minecraftforge/lex/legacyjavafixer/1.0/legacyjavafixer-1.0.jar
|
||||||
@@ -34,11 +35,37 @@ FTB_SERVER_MOD=${FTB_SERVER_MOD:-$CF_SERVER_MOD}
|
|||||||
log "Looking for Feed-The-Beast / CurseForge server modpack."
|
log "Looking for Feed-The-Beast / CurseForge server modpack."
|
||||||
requireVar FTB_SERVER_MOD
|
requireVar FTB_SERVER_MOD
|
||||||
|
|
||||||
if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
|
downloadModpack() {
|
||||||
if ! [ -f "${FTB_SERVER_MOD}" ]; then
|
srv_modpack=${FTB_SERVER_MOD}
|
||||||
log "ERROR unable to find requested modpack file ${FTB_SERVER_MOD}"
|
if isURL "${srv_modpack}"; then
|
||||||
exit 2
|
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
|
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
|
||||||
|
|
||||||
needsInstall=true
|
needsInstall=true
|
||||||
installMarker=/data/.curseforge-installed
|
installMarker=/data/.curseforge-installed
|
||||||
@@ -46,9 +73,9 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
|
|||||||
if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then
|
if [ "$(cat $installMarker)" != "${FTB_SERVER_MOD}" ]; then
|
||||||
log "Upgrading modpack"
|
log "Upgrading modpack"
|
||||||
|
|
||||||
serverJar=$(find ${FTB_BASE_DIR} -not -name "forge*installer.jar" -name "forge*.jar")
|
serverJar=$(find "${FTB_BASE_DIR}" -type f \( -path "*/libraries/*" -o -path "*/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||||
if [[ "${serverJar}" ]]; then
|
if [[ "${serverJar}" ]]; then
|
||||||
rm -rf $(dirname "${serverJar}")/{mods,*.jar,libraries,resources,scripts,config}
|
rm -rf "$(dirname "${serverJar}")"/{mods,*.jar,libraries,resources,scripts,config}
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
needsInstall=false
|
needsInstall=false
|
||||||
@@ -57,10 +84,10 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
|
|||||||
|
|
||||||
if $needsInstall; then
|
if $needsInstall; then
|
||||||
log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..."
|
log "Unpacking FTB server modpack ${FTB_SERVER_MOD} ..."
|
||||||
mkdir -p ${FTB_BASE_DIR}
|
mkdir -p "${FTB_BASE_DIR}"
|
||||||
unzip -o "${FTB_SERVER_MOD}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
|
unzip -o "${FTB_SERVER_MOD}" -d "${FTB_BASE_DIR}" | awk '{printf "."} END {print ""}'
|
||||||
|
|
||||||
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}" -type f \( -path "*/libraries/*" -o -path "*/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||||
if [[ -z "$serverJar" ]]; then
|
if [[ -z "$serverJar" ]]; then
|
||||||
|
|
||||||
if [ -f "${FTB_BASE_DIR}/settings.cfg" ]; then
|
if [ -f "${FTB_BASE_DIR}/settings.cfg" ]; then
|
||||||
@@ -84,26 +111,26 @@ if ! isTrue ${USE_MODPACK_START_SCRIPT:-true}; then
|
|||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
forgeInstallerJar=$(ls -t "${forgeInstallerJar}" | head -1)
|
|
||||||
|
|
||||||
log "Installing forge server"
|
log "Installing forge server"
|
||||||
dirOfInstaller=$(dirname "${forgeInstallerJar}")
|
dirOfInstaller=$(dirname "${forgeInstallerJar}")
|
||||||
(cd "${dirOfInstaller}"; java -jar $(basename "${forgeInstallerJar}") --installServer)
|
(cd "${dirOfInstaller}"; java -jar "$(basename "${forgeInstallerJar}")" --installServer)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "${FTB_SERVER_MOD}" > $installMarker
|
echo "${FTB_SERVER_MOD}" > $installMarker
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export SERVER=$(find ${FTB_BASE_DIR} -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -maxdepth 2 -print)
|
SERVER=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||||
if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then
|
if [[ -z "${SERVER}" || ! -f "${SERVER}" ]]; then
|
||||||
log "ERROR unable to locate installed forge server jar"
|
log "ERROR unable to locate installed forge server jar"
|
||||||
isDebugging && find ${FTB_BASE_DIR} -name "forge*.jar"
|
isDebugging && find "${FTB_BASE_DIR}" -name "forge*.jar"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
export SERVER
|
||||||
|
|
||||||
export FTB_DIR=$(dirname "${SERVER}")
|
FTB_DIR=$(dirname "${SERVER}")
|
||||||
|
export FTB_DIR
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
entryScriptExpr="
|
entryScriptExpr="
|
||||||
@@ -118,8 +145,8 @@ entryScriptExpr="
|
|||||||
"
|
"
|
||||||
|
|
||||||
if [[ -d ${FTB_BASE_DIR} ]]; then
|
if [[ -d ${FTB_BASE_DIR} ]]; then
|
||||||
startScriptCount=$(find ${FTB_BASE_DIR} $entryScriptExpr |wc -l)
|
startScriptCount=$(find "${FTB_BASE_DIR}" $entryScriptExpr |wc -l)
|
||||||
if [[ $startScriptCount > 1 ]]; then
|
if (( startScriptCount > 1 )); then
|
||||||
log "Conflicting FTB/CurseForge packages have been installed. Please cleanup ${FTB_BASE_DIR}"
|
log "Conflicting FTB/CurseForge packages have been installed. Please cleanup ${FTB_BASE_DIR}"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
@@ -131,46 +158,12 @@ fi
|
|||||||
# also check for the start script rather than just the folder
|
# 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
|
# this allows saving just the world separate from the rest of the data directory
|
||||||
if [[ $startScriptCount = 0 ]]; then
|
if [[ $startScriptCount = 0 ]]; then
|
||||||
|
downloadModpack
|
||||||
srv_modpack=${FTB_SERVER_MOD}
|
srv_modpack=${FTB_SERVER_MOD}
|
||||||
if isURL "${srv_modpack}"; then
|
|
||||||
case $srv_modpack in
|
|
||||||
https://www.feed-the-beast.com/*/download|https://www.curseforge.com/minecraft/modpacks/*/download/*/file)
|
|
||||||
;;
|
|
||||||
https://www.curseforge.com/minecraft/modpacks/*/download/*)
|
|
||||||
srv_modpack=${srv_modpack}/file;;
|
|
||||||
https://www.feed-the-beast.com/*)
|
|
||||||
srv_modpack=${srv_modpack}/download;;
|
|
||||||
esac
|
|
||||||
file=$(basename $(dirname $srv_modpack))
|
|
||||||
downloaded=/data/${file}.zip
|
|
||||||
if [ ! -e $downloaded ]; then
|
|
||||||
log "Downloading FTB modpack...
|
|
||||||
$srv_modpack -> $downloaded"
|
|
||||||
curl -sSL -o $downloaded $srv_modpack
|
|
||||||
fi
|
|
||||||
srv_modpack=$downloaded
|
|
||||||
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} ..."
|
log "Unpacking FTB server modpack ${srv_modpack} ..."
|
||||||
mkdir -p ${FTB_BASE_DIR}
|
mkdir -p "${FTB_BASE_DIR}"
|
||||||
unzip -o "${srv_modpack}" -d ${FTB_BASE_DIR} | awk '{printf "."} END {print ""}'
|
unzip -o "${srv_modpack}" -d "${FTB_BASE_DIR}" | awk '{printf "."} END {print ""}'
|
||||||
|
|
||||||
installScript=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f -name install.sh)
|
installScript=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f -name install.sh)
|
||||||
if [[ "$installScript" ]]; then
|
if [[ "$installScript" ]]; then
|
||||||
@@ -183,13 +176,14 @@ if [[ $startScriptCount = 0 ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $(find ${FTB_BASE_DIR} $entryScriptExpr | wc -l) = 0 ]]; then
|
if [[ $(find "${FTB_BASE_DIR}" $entryScriptExpr | wc -l) = 0 ]]; then
|
||||||
|
|
||||||
# Allow up to 2 levels since some modpacks have a top-level directory named
|
# Allow up to 2 levels since some modpacks have a top-level directory named
|
||||||
# for the modpack
|
# for the modpack
|
||||||
forgeJar=$(find ${FTB_BASE_DIR} -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -maxdepth 2 -print)
|
forgeJar=$(find "${FTB_BASE_DIR}" -maxdepth 2 -type f \( -path "/libraries/*" -o -path "/mods/*" \) -prune -o -name "forge*.jar" -not -name "forge*installer.jar" -print)
|
||||||
if [[ "$forgeJar" ]]; then
|
if [[ "$forgeJar" ]]; then
|
||||||
export FTB_BASE_DIR=$(dirname "${forgeJar}")
|
FTB_BASE_DIR=$(dirname "${forgeJar}")
|
||||||
|
export FTB_BASE_DIR
|
||||||
log "No entry script found, so building one for ${forgeJar}"
|
log "No entry script found, so building one for ${forgeJar}"
|
||||||
cat > "${FTB_BASE_DIR}/ServerStart.sh" <<EOF
|
cat > "${FTB_BASE_DIR}/ServerStart.sh" <<EOF
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
@@ -207,25 +201,29 @@ scriptCount=$(find "${FTB_BASE_DIR}" $entryScriptExpr | wc -l)
|
|||||||
if [[ $scriptCount = 0 ]]; then
|
if [[ $scriptCount = 0 ]]; then
|
||||||
log "Please make sure you are using the server version of the FTB modpack!"
|
log "Please make sure you are using the server version of the FTB modpack!"
|
||||||
exit 2
|
exit 2
|
||||||
elif [[ $scriptCount > 1 ]]; then
|
elif (( scriptCount > 1 )); then
|
||||||
log "Ambigous startup scripts in FTB modpack!"
|
log "Ambiguous startup scripts in FTB modpack! Found:"
|
||||||
log "found:"
|
find "${FTB_BASE_DIR}" $entryScriptExpr
|
||||||
find ${FTB_BASE_DIR} $entryScriptExpr
|
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr)
|
FTB_SERVER_START=$(find "${FTB_BASE_DIR}" $entryScriptExpr)
|
||||||
|
export FTB_SERVER_START
|
||||||
|
|
||||||
export FTB_DIR=$(dirname "${FTB_SERVER_START}")
|
FTB_DIR=$(dirname "${FTB_SERVER_START}")
|
||||||
|
export FTB_DIR
|
||||||
chmod a+x "${FTB_SERVER_START}"
|
chmod a+x "${FTB_SERVER_START}"
|
||||||
grep fml.queryResult=confirm "${FTB_SERVER_START}" > /dev/null || \
|
grep fml.queryResult=confirm "${FTB_SERVER_START}" > /dev/null || \
|
||||||
sed -i 's/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}"
|
sed -i 's/-jar/-Dfml.queryResult=confirm -jar/' "${FTB_SERVER_START}"
|
||||||
sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}"
|
sed -i 's/.*read.*Restart now/#\0/' "${FTB_SERVER_START}"
|
||||||
legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar"
|
legacyJavaFixerPath="${FTB_DIR}/mods/legacyjavafixer.jar"
|
||||||
|
|
||||||
if isTrue ${FTB_LEGACYJAVAFIXER} && [ ! -e "${legacyJavaFixerPath}" ]; then
|
if isTrue "${FTB_LEGACYJAVAFIXER}" && [ ! -e "${legacyJavaFixerPath}" ]; then
|
||||||
log "Installing legacy java fixer to ${legacyJavaFixerPath}"
|
log "Installing legacy java fixer to ${legacyJavaFixerPath}"
|
||||||
curl -sSL -o "${legacyJavaFixerPath}" ${legacyJavaFixerUrl}
|
if ! get -o "${legacyJavaFixerPath}" ${legacyJavaFixerUrl}; then
|
||||||
|
log "ERROR failed to download legacy java fixer from ${legacyJavaFixerUrl}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -e "${FTB_DIR}/FTBInstall.sh" ]; then
|
if [ -e "${FTB_DIR}/FTBInstall.sh" ]; then
|
||||||
@@ -238,4 +236,5 @@ elif [ -e "${FTB_DIR}/Install.sh" ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
export FAMILY=FORGE
|
||||||
|
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||||
@@ -2,16 +2,11 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
IFS=$'\n\t'
|
IFS=$'\n\t'
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
|
|
||||||
: ${CANYON_BUILD:=lastSuccessfulBuild}
|
: "${CANYON_BUILD:=lastSuccessfulBuild}"
|
||||||
JAVA_VER=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
|
|
||||||
|
|
||||||
if [ "${JAVA_VER}" != "8" ]; then
|
|
||||||
log "ERROR: Canyon server type only supports Java version 8"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "${VERSION}" != "b1.7.3" ]; then
|
if [ "${VERSION}" != "b1.7.3" ]; then
|
||||||
log "ERROR: Canyon server type only supports VERSION=b1.7.3"
|
log "ERROR: Canyon server type only supports VERSION=b1.7.3"
|
||||||
@@ -48,7 +43,7 @@ if [ ! -f "$SERVER" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Normalize on Spigot for later operations
|
# Normalize on Spigot for later operations
|
||||||
export TYPE=SPIGOT
|
export FAMILY=SPIGOT
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||||
@@ -28,5 +28,6 @@ fi
|
|||||||
|
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
|
export FAMILY=HYBRID
|
||||||
# Continue to Final Setup
|
# Continue to Final Setup
|
||||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||||
61
scripts/start-deployCrucible
Executable file
61
scripts/start-deployCrucible
Executable file
@@ -0,0 +1,61 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-$(dirname "$0")}/start-utils"
|
||||||
|
set -o pipefail
|
||||||
|
set -e
|
||||||
|
isDebugging && set -x
|
||||||
|
|
||||||
|
requireVar VANILLA_VERSION
|
||||||
|
: "${CRUCIBLE_RELEASE:=latest}"
|
||||||
|
|
||||||
|
crucibleReleasesUrl=https://api.github.com/repos/CrucibleMC/Crucible/releases
|
||||||
|
if [[ ${CRUCIBLE_RELEASE^^} = LATEST ]]; then
|
||||||
|
crucibleReleaseUrl=${crucibleReleasesUrl}/latest
|
||||||
|
else
|
||||||
|
crucibleReleaseUrl=${crucibleReleasesUrl}/tags/${CRUCIBLE_RELEASE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! downloadUrl=$(get --json-path "$.assets[?(@.name =~ /Crucible-${VANILLA_VERSION}-.*\.jar/)].browser_download_url" \
|
||||||
|
--accept "application/vnd.github.v3+json" "$crucibleReleaseUrl"); then
|
||||||
|
log "ERROR: failed to access ${CRUCIBLE_RELEASE} release of Crucible"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $downloadUrl = null ]]; then
|
||||||
|
log "ERROR: failed to locate Crucible jar for $VANILLA_VERSION from ${CRUCIBLE_RELEASE}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Downloading Crucible from $downloadUrl"
|
||||||
|
if ! SERVER=$(get --skip-existing --output-filename -o /data "$downloadUrl"); then
|
||||||
|
log "ERROR: failed to download Crucible jar from $downloadUrl"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
librariesDir=/data/libraries
|
||||||
|
if [ ! -d "$librariesDir" ]; then
|
||||||
|
if ! librariesUrl=$(get --json-path "$.assets[?(@.name == 'libraries.zip')].browser_download_url" \
|
||||||
|
--accept "application/vnd.github.v3+json" "$crucibleReleaseUrl"); then
|
||||||
|
log "ERROR: failed to access ${CRUCIBLE_RELEASE} release of Crucible for libraries"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Downloading Crucible libraries"
|
||||||
|
if ! get -o /tmp/libraries.zip "$librariesUrl"; then
|
||||||
|
log "ERROR: failed to download Crucible libraries from $librariesUrl"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! unzip /tmp/libraries.zip -d "$librariesDir"; then
|
||||||
|
log "ERROR: failed to unzip Crucible libraries"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
rm /tmp/libraries.zip
|
||||||
|
fi
|
||||||
|
|
||||||
|
export SERVER
|
||||||
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
export FAMILY=HYBRID
|
||||||
|
|
||||||
|
exec "${SCRIPTS:-$(dirname "$0")}/start-setupWorld" "$@"
|
||||||
@@ -31,5 +31,5 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
export FAMILY=HYBRID
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||||
@@ -16,7 +16,7 @@ if ! [[ ${FTB_MODPACK_ID} =~ [0-9]+ ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [[ -v FTB_MODPACK_VERSION_ID ]]; then
|
if [[ ! $FTB_MODPACK_VERSION_ID ]]; then
|
||||||
if ! FTB_MODPACK_VERSION_ID=$(curl -fsSL https://api.modpacks.ch/public/modpack/${FTB_MODPACK_ID} | jq -r '.versions | sort_by(.updated)[-1].id'); then
|
if ! FTB_MODPACK_VERSION_ID=$(curl -fsSL https://api.modpacks.ch/public/modpack/${FTB_MODPACK_ID} | jq -r '.versions | sort_by(.updated)[-1].id'); then
|
||||||
log "ERROR unable to resolve latest modpack version ID for modpack ${FTB_MODPACK_ID}"
|
log "ERROR unable to resolve latest modpack version ID for modpack ${FTB_MODPACK_ID}"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -67,7 +67,7 @@ variants=(
|
|||||||
forge-${mcVersion}-${forgeVersion}-${mcVersion}-universal.jar
|
forge-${mcVersion}-${forgeVersion}-${mcVersion}-universal.jar
|
||||||
fabric-${mcVersion}-${fabricVersion}-server-launch.jar
|
fabric-${mcVersion}-${fabricVersion}-server-launch.jar
|
||||||
)
|
)
|
||||||
for f in ${variants[@]}; do
|
for f in "${variants[@]}"; do
|
||||||
if [ -f $f ]; then
|
if [ -f $f ]; then
|
||||||
export SERVER=$f
|
export SERVER=$f
|
||||||
break
|
break
|
||||||
@@ -79,4 +79,5 @@ if ! [ -v SERVER ]; then
|
|||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export FAMILY=FORGE
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||||
81
scripts/start-deployFabric
Executable file
81
scripts/start-deployFabric
Executable file
@@ -0,0 +1,81 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# shellcheck source=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}"
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
export SERVER=fabric-server-${VANILLA_VERSION}-${FABRIC_INSTALLER_VERSION}.jar
|
||||||
|
|
||||||
|
if [ ! \( -e ${SERVER} -a -e "server-${VANILLA_VERSION}.jar" \) ]; then
|
||||||
|
|
||||||
|
if [[ -z $FABRIC_INSTALLER && -z $FABRIC_INSTALLER_URL ]]; then
|
||||||
|
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
|
||||||
|
FABRIC_INSTALLER="fabric-installer.jar"
|
||||||
|
elif [[ ! -e $FABRIC_INSTALLER ]]; then
|
||||||
|
log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $FABRIC_LOADER_VERSION || ${FABRIC_LOADER_VERSION^^} = LATEST ]]; then
|
||||||
|
log "Checking Fabric Loader version information."
|
||||||
|
|
||||||
|
FABRIC_LOADER_VERSION=$(maven-metadata-release https://maven.fabricmc.net/net/fabricmc/fabric-loader/maven-metadata.xml)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -e $FABRIC_INSTALLER ]]; then
|
||||||
|
log "Downloading $FABRIC_INSTALLER_URL ..."
|
||||||
|
if ! get -o "$FABRIC_INSTALLER" "$FABRIC_INSTALLER_URL"; then
|
||||||
|
log "Failed to download from given location $FABRIC_INSTALLER_URL"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Installing Fabric ${VANILLA_VERSION} using $FABRIC_INSTALLER with loader version $FABRIC_LOADER_VERSION"
|
||||||
|
|
||||||
|
tries=3
|
||||||
|
set +e
|
||||||
|
while ((--tries >= 0)); do
|
||||||
|
java -jar $FABRIC_INSTALLER server \
|
||||||
|
-mcversion $VANILLA_VERSION \
|
||||||
|
-loader $FABRIC_LOADER_VERSION \
|
||||||
|
-downloadMinecraft \
|
||||||
|
-dir /data
|
||||||
|
if [[ $? == 0 ]]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
set -e
|
||||||
|
if (($tries < 0)); then
|
||||||
|
log "Fabric failed to install after several tries." >&2
|
||||||
|
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" "$@"
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
: "${FORGEVERSION:=RECOMMENDED}"
|
||||||
: ${FORGEVERSION:=RECOMMENDED}
|
|
||||||
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-$(dirname "$0")}/start-utils"
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
|
|
||||||
get_installer() {
|
get_installer() {
|
||||||
@@ -9,14 +11,14 @@ get_installer() {
|
|||||||
log "Downloading $normForgeVersion"
|
log "Downloading $normForgeVersion"
|
||||||
|
|
||||||
forgeFileNames="
|
forgeFileNames="
|
||||||
$normForgeVersion/forge-$normForgeVersion-installer.jar
|
|
||||||
$shortForgeVersion/forge-$shortForgeVersion-installer.jar
|
$shortForgeVersion/forge-$shortForgeVersion-installer.jar
|
||||||
|
$normForgeVersion/forge-$normForgeVersion-installer.jar
|
||||||
"
|
"
|
||||||
|
|
||||||
for fn in $forgeFileNames; do
|
for fn in $forgeFileNames; do
|
||||||
downloadUrl=https://maven.minecraftforge.net/net/minecraftforge/forge/$fn
|
downloadUrl=https://maven.minecraftforge.net/net/minecraftforge/forge/$fn
|
||||||
log "...trying $downloadUrl"
|
log "...trying $downloadUrl"
|
||||||
if curl -o $FORGE_INSTALLER -fsSL $downloadUrl; then
|
if get -o "$FORGE_INSTALLER" "$downloadUrl"; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
@@ -24,7 +26,7 @@ get_installer() {
|
|||||||
exit 2
|
exit 2
|
||||||
else
|
else
|
||||||
log "Downloading $FORGE_INSTALLER_URL ..."
|
log "Downloading $FORGE_INSTALLER_URL ..."
|
||||||
if ! curl -o $FORGE_INSTALLER -fsSL $FORGE_INSTALLER_URL; then
|
if ! get -o "$FORGE_INSTALLER" "$FORGE_INSTALLER_URL"; then
|
||||||
log "Failed to download from given location $FORGE_INSTALLER_URL"
|
log "Failed to download from given location $FORGE_INSTALLER_URL"
|
||||||
exit 2
|
exit 2
|
||||||
fi
|
fi
|
||||||
@@ -32,33 +34,38 @@ get_installer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
if [ ! -e $FORGE_INSTALLER ]; then
|
if [ ! -e "$FORGE_INSTALLER" ]; then
|
||||||
get_installer $normForgeVersion $shortForgeVersion
|
get_installer "$normForgeVersion" "$shortForgeVersion"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log "Installing Forge $shortForgeVersion using $FORGE_INSTALLER"
|
log "Installing Forge $shortForgeVersion using $FORGE_INSTALLER"
|
||||||
mkdir -p mods
|
mkdir -p mods
|
||||||
tries=3
|
tries=3
|
||||||
while ((--tries >= 0)); do
|
while ((--tries >= 0)); do
|
||||||
java -jar $FORGE_INSTALLER --installServer
|
if java -jar "$FORGE_INSTALLER" --installServer; then
|
||||||
if [ $? == 0 ]; then
|
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if (($tries < 0)); then
|
if ((tries < 0)); then
|
||||||
log "Forge failed to install after several tries." >&2
|
log "Forge failed to install after several tries." >&2
|
||||||
exit 10
|
exit 10
|
||||||
fi
|
fi
|
||||||
# NOTE $shortForgeVersion will be empty if installer location was given to us
|
# NOTE $shortForgeVersion will be empty if installer location was given to us
|
||||||
log "Finding installed server jar..."
|
log "Finding installed server jar..."
|
||||||
unset -v latest
|
unset -v latest
|
||||||
for file in *forge*.jar; do
|
# 1.17+ ?
|
||||||
if ! [[ $file =~ installer ]]; then
|
if [ -f /data/run.sh ]; then
|
||||||
if [[ -z $latest ]] || [[ $file -nt $latest ]]; then
|
latest=/data/run.sh
|
||||||
latest=$file
|
# else pre 1.17
|
||||||
|
else
|
||||||
|
for file in *forge*.jar; do
|
||||||
|
if ! [[ $file =~ installer ]]; then
|
||||||
|
if [[ -z $latest ]] || [[ $file -nt $latest ]]; then
|
||||||
|
latest=$file
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
done
|
||||||
done
|
fi
|
||||||
if [[ -z $latest ]]; then
|
if [[ -z $latest ]]; then
|
||||||
log "Unable to derive server jar for Forge"
|
log "Unable to derive server jar for Forge"
|
||||||
exit 2
|
exit 2
|
||||||
@@ -66,7 +73,8 @@ install() {
|
|||||||
|
|
||||||
export SERVER=$latest
|
export SERVER=$latest
|
||||||
log "Using server $SERVER"
|
log "Using server $SERVER"
|
||||||
echo $SERVER > $installMarker
|
debug "Writing install marker at $installMarker"
|
||||||
|
echo "$SERVER" > "$installMarker"
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_versions() {
|
resolve_versions() {
|
||||||
@@ -81,15 +89,21 @@ resolve_versions() {
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
#################################################################################
|
#################################################################################
|
||||||
|
promosUrl=http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json
|
||||||
|
|
||||||
log "Checking Forge version information."
|
log "Checking Forge version information."
|
||||||
case $FORGEVERSION in
|
case $FORGEVERSION in
|
||||||
|
LATEST)
|
||||||
|
if ! FORGE_VERSION=$(get --json-path ".promos['$VANILLA_VERSION-latest']" "$promosUrl"); then
|
||||||
|
log "ERROR: Version $VANILLA_VERSION is not supported by Forge"
|
||||||
|
log " Refer to http://files.minecraftforge.net/ for supported versions"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
RECOMMENDED)
|
RECOMMENDED)
|
||||||
curl -fsSL -o /tmp/forge.json http://files.minecraftforge.net/maven/net/minecraftforge/forge/promotions_slim.json
|
if ! FORGE_VERSION=$(get -s --json-path ".promos['$VANILLA_VERSION-recommended']" "$promosUrl"); then
|
||||||
FORGE_VERSION=$(cat /tmp/forge.json | jq -r ".promos[\"$VANILLA_VERSION-recommended\"]")
|
if ! FORGE_VERSION=$(get --json-path ".promos['$VANILLA_VERSION-latest']" "$promosUrl"); then
|
||||||
if [ $FORGE_VERSION = null ]; then
|
|
||||||
FORGE_VERSION=$(cat /tmp/forge.json | jq -r ".promos[\"$VANILLA_VERSION-latest\"]")
|
|
||||||
if [ $FORGE_VERSION = null ]; then
|
|
||||||
log "ERROR: Version $VANILLA_VERSION is not supported by Forge"
|
log "ERROR: Version $VANILLA_VERSION is not supported by Forge"
|
||||||
log " Refer to http://files.minecraftforge.net/ for supported versions"
|
log " Refer to http://files.minecraftforge.net/ for supported versions"
|
||||||
exit 2
|
exit 2
|
||||||
@@ -122,14 +136,16 @@ resolve_versions
|
|||||||
|
|
||||||
installMarker="/data/.forge-installed-$shortForgeVersion"
|
installMarker="/data/.forge-installed-$shortForgeVersion"
|
||||||
|
|
||||||
if [ ! -e $installMarker ]; then
|
if [ ! -e "$installMarker" ] || isTrue "${FORCE_REINSTALL:-false}"; then
|
||||||
install
|
install
|
||||||
else
|
else
|
||||||
export SERVER=$(cat $installMarker)
|
SERVER=$(cat "$installMarker")
|
||||||
if [ ! -e "$SERVER" ] && versionLessThan 1.17; then
|
export SERVER
|
||||||
|
if [ ! -e "$SERVER" ]; then
|
||||||
rm "$installMarker"
|
rm "$installMarker"
|
||||||
install
|
install
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
export FAMILY=FORGE
|
||||||
|
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||||
@@ -60,4 +60,5 @@ export LEVEL
|
|||||||
|
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
|
export FAMILY=LIMBO
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
exec ${SCRIPTS:-/}start-setupWorld $@
|
||||||
@@ -89,4 +89,5 @@ else
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
export FAMILY=HYBRID
|
||||||
|
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-$(dirname "$0")}/start-utils"
|
||||||
set -o pipefail
|
set -o pipefail
|
||||||
set -e
|
set -e
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
|
|
||||||
requireVar VANILLA_VERSION
|
requireVar VANILLA_VERSION
|
||||||
: ${MOHIST_BUILD:=lastSuccessfulBuild}
|
: "${MOHIST_BUILD:=lastSuccessfulBuild}"
|
||||||
|
|
||||||
mohistJobs=https://ci.codemc.io/job/MohistMC/job/
|
mohistJobs=https://ci.codemc.io/job/MohistMC/job/
|
||||||
mohistJob=${mohistJobs}Mohist-${VANILLA_VERSION}/
|
mohistJob=${mohistJobs}Mohist-${VANILLA_VERSION}/
|
||||||
|
|
||||||
if ! curl -X HEAD -o /dev/null -fsSL "${mohistJob}"; then
|
if ! get --exists "${mohistJob}"; then
|
||||||
log "ERROR: mohist builds do not exist for ${VANILLA_VERSION}"
|
log "ERROR: mohist builds do not exist for ${VANILLA_VERSION}"
|
||||||
log " check https://ci.codemc.io/job/MohistMC/ for available versions"
|
log " check https://ci.codemc.io/job/MohistMC/ for available versions"
|
||||||
log " and set VERSION accordingly"
|
log " and set VERSION accordingly"
|
||||||
@@ -19,8 +20,7 @@ if ! curl -X HEAD -o /dev/null -fsSL "${mohistJob}"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
buildRelPath=$(
|
buildRelPath=$(
|
||||||
curl -fsSL "${mohistJob}${MOHIST_BUILD}/api/json" |
|
get --json-path '$.artifacts[0].relativePath' "${mohistJob}${MOHIST_BUILD}/api/json"
|
||||||
jq -r '.artifacts[0].relativePath'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
baseName=$(basename "${buildRelPath}")
|
baseName=$(basename "${buildRelPath}")
|
||||||
@@ -33,11 +33,12 @@ fi
|
|||||||
|
|
||||||
export SERVER="/data/${baseName}"
|
export SERVER="/data/${baseName}"
|
||||||
|
|
||||||
if [ ! -f ${SERVER} ]; then
|
if [ ! -f "${SERVER}" ]; then
|
||||||
log "Downloading ${baseName}"
|
log "Downloading ${baseName}"
|
||||||
curl -o "${SERVER}" -fsSL "${mohistJob}${MOHIST_BUILD}/artifact/${buildRelPath}"
|
get -o "${SERVER}" "${mohistJob}${MOHIST_BUILD}/artifact/${buildRelPath}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
export FAMILY=HYBRID
|
||||||
|
exec "${SCRIPTS:-$(dirname "$0")}/start-setupWorld" "$@"
|
||||||
@@ -73,7 +73,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Normalize on Spigot for downstream operations
|
# Normalize on Spigot for downstream operations
|
||||||
export TYPE=SPIGOT
|
export FAMILY=SPIGOT
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||||
45
scripts/start-deployPufferfish
Executable file
45
scripts/start-deployPufferfish
Executable file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/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
|
||||||
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
|
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
IFS=$'\n\t'
|
IFS=$'\n\t'
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
|
|
||||||
: ${VANILLA_VERSION:?}
|
: ${VANILLA_VERSION:?}
|
||||||
@@ -10,28 +11,26 @@ isDebugging && set -x
|
|||||||
: ${FORCE_REDOWNLOAD:=false}
|
: ${FORCE_REDOWNLOAD:=false}
|
||||||
|
|
||||||
if [[ ${PURPUR_BUILD} == LATEST ]]; then
|
if [[ ${PURPUR_BUILD} == LATEST ]]; then
|
||||||
PURPUR_BUILD=$(curl -fsSL "https://api.pl3x.net/v2/purpur/${VANILLA_VERSION}" |
|
if ! PURPUR_BUILD=$(get --json-path=".builds.latest" "https://api.purpurmc.org/v2/purpur/${VANILLA_VERSION}"); then
|
||||||
jq -r '.builds.latest' || echo "")
|
|
||||||
if [[ -z ${PURPUR_BUILD} ]]; then
|
|
||||||
log "ERROR: Failed to locate a Purpur build for ${VANILLA_VERSION}."
|
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/"
|
log " Please check if a download is available at https://purpur.pl3x.net/downloads/"
|
||||||
exit 3
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export SERVER="purpur-${VANILLA_VERSION}-${PURPUR_BUILD}.jar"
|
export SERVER="purpur-${VANILLA_VERSION}-${PURPUR_BUILD}.jar"
|
||||||
|
|
||||||
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
|
if [ ! -f "$SERVER" ] || isTrue "$FORCE_REDOWNLOAD"; then
|
||||||
downloadUrl="https://api.pl3x.net/v2/purpur/${VANILLA_VERSION}/${PURPUR_BUILD}/download"
|
downloadUrl="https://api.purpurmc.org/v2/purpur/${VANILLA_VERSION}/${PURPUR_BUILD}/download"
|
||||||
log "Downloading Purpur from $downloadUrl ..."
|
log "Downloading Purpur from $downloadUrl ..."
|
||||||
if ! curl -fsSL -o "$SERVER" "$downloadUrl"; then
|
if ! get -o "$SERVER" "$downloadUrl"; then
|
||||||
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
log "ERROR: failed to download from $downloadUrl (status=$?)"
|
||||||
exit 3
|
exit 3
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Normalize on Spigot for later operations
|
# Normalize on Spigot for later operations
|
||||||
export TYPE=SPIGOT
|
export FAMILY=SPIGOT
|
||||||
export SKIP_LOG4J_CONFIG=true
|
export SKIP_LOG4J_CONFIG=true
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
exec "${SCRIPTS:-/}start-spiget" "$@"
|
||||||
@@ -37,4 +37,5 @@ if [ ! -e $SERVER ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
|||||||
curl -sSL -o $SERVER https://repo.spongepowered.org/maven/org/spongepowered/$TYPE/$SPONGEVERSION/$SERVER
|
curl -sSL -o $SERVER https://repo.spongepowered.org/maven/org/spongepowered/$TYPE/$SPONGEVERSION/$SERVER
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld $@
|
export FAMILY=SPONGE
|
||||||
|
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
||||||
@@ -41,6 +41,16 @@ if [ ! -e "$SERVER" ] || [ -n "$FORCE_REDOWNLOAD" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
isDebugging && ls -l
|
if versionLessThan 1.6; then
|
||||||
|
if ! [[ -L /data/minecraft_server.jar && /data/minecraft_server.jar -ef "/data/$SERVER" ]]; then
|
||||||
|
rm -f /data/minecraft_server.jar
|
||||||
|
ln -s "/data/$SERVER" /data/minecraft_server.jar
|
||||||
|
fi
|
||||||
|
SERVER=minecraft_server.jar
|
||||||
|
elif [[ -L /data/minecraft_server.jar ]]; then
|
||||||
|
rm -f /data/minecraft_server.jar
|
||||||
|
fi
|
||||||
|
|
||||||
|
isDebugging && ls -l
|
||||||
|
export FAMILY=VANILLA
|
||||||
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
exec "${SCRIPTS:-/}start-setupWorld" "$@"
|
||||||
@@ -3,24 +3,93 @@
|
|||||||
. ${SCRIPTS:-/}start-utils
|
. ${SCRIPTS:-/}start-utils
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
|
|
||||||
if [ -n "$OPS" ]; then
|
if versionLessThan 1.7.6; then
|
||||||
log "Updating ops"
|
opsFile=ops.txt
|
||||||
rm -f /data/ops.txt.converted
|
whitelistFile=white-list.txt
|
||||||
echo $OPS | awk -v RS=, '{print}' > /data/ops.txt
|
else
|
||||||
fi
|
opsFile=ops.json
|
||||||
if isTrue "${OVERRIDE_OPS}"; then
|
whitelistFile=whitelist.json
|
||||||
log "Recreating ops.json file at server startup"
|
|
||||||
rm -f /data/ops.json
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$WHITELIST" ]; then
|
function process_user_file() {
|
||||||
log "Updating whitelist"
|
local output=$1
|
||||||
rm -f /data/white-list.txt.converted
|
local source=$2
|
||||||
echo $WHITELIST | awk -v RS=, '{print}' > /data/white-list.txt
|
|
||||||
|
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
|
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
|
if isTrue "${OVERRIDE_WHITELIST}"; then
|
||||||
log "Recreating whitelist.json file at server startup"
|
log "Recreating ${whitelistFile} file at server startup"
|
||||||
rm -f /data/whitelist.json
|
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
|
fi
|
||||||
|
|
||||||
if [ -n "$ICON" ]; then
|
if [ -n "$ICON" ]; then
|
||||||
@@ -38,7 +107,41 @@ if [ -n "$ICON" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
canUseRollingLogs=true
|
||||||
|
|
||||||
|
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}"
|
||||||
|
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
|
||||||
|
JVM_OPTS="-Dlog4j2.formatMsgNoLookups=true ${JVM_OPTS}"
|
||||||
|
fi
|
||||||
|
|
||||||
if isTrue ${ENABLE_ROLLING_LOGS:-false}; then
|
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
|
# Set up log configuration
|
||||||
LOGFILE="/data/log4j2.xml"
|
LOGFILE="/data/log4j2.xml"
|
||||||
if [ ! -e "$LOGFILE" ]; then
|
if [ ! -e "$LOGFILE" ]; then
|
||||||
@@ -70,8 +173,8 @@ if [[ ${GUI} = false || ${GUI} = FALSE ]]; then
|
|||||||
EXTRA_ARGS+=" nogui"
|
EXTRA_ARGS+=" nogui"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# put these prior JVM_OPTS at the end to give any memory settings there higher precedence
|
: "${INIT_MEMORY:=${MEMORY}}"
|
||||||
log "Setting initial memory to ${INIT_MEMORY:=${MEMORY}} and max to ${MAX_MEMORY:=${MEMORY}}"
|
: "${MAX_MEMORY:=${MEMORY}}"
|
||||||
|
|
||||||
expandedDOpts=
|
expandedDOpts=
|
||||||
if [ -n "$JVM_DD_OPTS" ]; then
|
if [ -n "$JVM_DD_OPTS" ]; then
|
||||||
@@ -138,12 +241,6 @@ if isTrue "${USE_AIKAR_FLAGS}"; then
|
|||||||
"
|
"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if isTrue "${USE_LARGE_PAGES}"; then
|
|
||||||
JVM_XX_OPTS="${JVM_XX_OPTS}
|
|
||||||
-XX:+UseLargePagesInMetaspace
|
|
||||||
"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if isTrue "${USE_FLARE_FLAGS}"; then
|
if isTrue "${USE_FLARE_FLAGS}"; then
|
||||||
JVM_XX_OPTS="${JVM_XX_OPTS}
|
JVM_XX_OPTS="${JVM_XX_OPTS}
|
||||||
-XX:+UnlockDiagnosticVMOptions
|
-XX:+UnlockDiagnosticVMOptions
|
||||||
@@ -157,7 +254,15 @@ if isTrue "${DEBUG_MEMORY}"; then
|
|||||||
free -m
|
free -m
|
||||||
fi
|
fi
|
||||||
|
|
||||||
JVM_OPTS="-Xms${INIT_MEMORY} -Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
if [[ ${INIT_MEMORY} || ${MAX_MEMORY} ]]; then
|
||||||
|
log "Setting initial memory to ${INIT_MEMORY:=${MEMORY}} and max to ${MAX_MEMORY:=${MEMORY}}"
|
||||||
|
if [[ ${INIT_MEMORY} ]]; then
|
||||||
|
JVM_OPTS="-Xms${INIT_MEMORY} ${JVM_OPTS}"
|
||||||
|
fi
|
||||||
|
if [[ ${MAX_MEMORY} ]]; then
|
||||||
|
JVM_OPTS="-Xmx${MAX_MEMORY} ${JVM_OPTS}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
function copyFilesForCurseForge() {
|
function copyFilesForCurseForge() {
|
||||||
# copy player modification files unconditionally since their
|
# copy player modification files unconditionally since their
|
||||||
@@ -180,14 +285,7 @@ if [[ ${STOP_SERVER_ANNOUNCE_DELAY} ]]; then
|
|||||||
mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s")
|
mcServerRunnerArgs+=(--stop-server-announce-delay "${STOP_SERVER_ANNOUNCE_DELAY}s")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${TYPE} == "CURSE_INSTANCE" ]]; then
|
if [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then
|
||||||
if isTrue ${DEBUG_EXEC}; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" \
|
|
||||||
--cf-instance-file "${CURSE_INSTANCE_JSON}" \
|
|
||||||
java $JVM_XX_OPTS $JVM_OPTS $expandedDOpts -jar _SERVERJAR_ "$@" $EXTRA_ARGS
|
|
||||||
elif [[ ${TYPE} == "CURSEFORGE" && "${SERVER}" ]]; then
|
|
||||||
copyFilesForCurseForge
|
copyFilesForCurseForge
|
||||||
|
|
||||||
cd "${FTB_DIR}" || (log "ERROR: can't go into ${FTB_DIR}"; exit 1)
|
cd "${FTB_DIR}" || (log "ERROR: can't go into ${FTB_DIR}"; exit 1)
|
||||||
@@ -204,11 +302,11 @@ elif [[ ${TYPE} == "CURSEFORGE" ]]; then
|
|||||||
cat > "${FTB_DIR}/settings-local.sh" <<EOF
|
cat > "${FTB_DIR}/settings-local.sh" <<EOF
|
||||||
export MIN_RAM="${INIT_MEMORY}"
|
export MIN_RAM="${INIT_MEMORY}"
|
||||||
export MAX_RAM="${MAX_MEMORY}"
|
export MAX_RAM="${MAX_MEMORY}"
|
||||||
export JAVA_PARAMETERS="${JVM_XX_OPTS} -Xms${INIT_MEMORY} ${JVM_OPTS} $expandedDOpts"
|
export JAVA_PARAMETERS="${JVM_XX_OPTS} ${JVM_OPTS} $expandedDOpts"
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# patch CurseForge cfg file, if present
|
# patch CurseForge cfg file, if present
|
||||||
if [ -f "${FTB_DIR}/settings.cfg" ]; then
|
if [ -f "${FTB_DIR}/settings.cfg" ] && [[ ${MAX_MEMORY} ]]; then
|
||||||
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
|
sed -i "s/MAX_RAM=[^;]*/MAX_RAM=${MAX_MEMORY}/" "${FTB_DIR}/settings.cfg"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -217,7 +315,7 @@ EOF
|
|||||||
|
|
||||||
finalArgs="${FTB_SERVER_START}"
|
finalArgs="${FTB_SERVER_START}"
|
||||||
|
|
||||||
if isTrue ${SETUP_ONLY:=false}; then
|
if isTrue "${SETUP_ONLY:=false}"; then
|
||||||
echo "SETUP_ONLY: ${finalArgs}"
|
echo "SETUP_ONLY: ${finalArgs}"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
@@ -230,10 +328,10 @@ EOF
|
|||||||
else
|
else
|
||||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" "${finalArgs[@]}"
|
exec mc-server-runner "${mcServerRunnerArgs[@]}" "${finalArgs[@]}"
|
||||||
fi
|
fi
|
||||||
elif [[ -x run.sh ]]; then
|
elif [[ $SERVER =~ run.sh ]]; then
|
||||||
log "Using Forge supplied run.sh script..."
|
log "Using Forge supplied run.sh script..."
|
||||||
echo $JVM_XX_OPTS $JVM_OPTS $expandedDOpts > user_jvm_args.txt
|
echo $JVM_XX_OPTS $JVM_OPTS $expandedDOpts > user_jvm_args.txt
|
||||||
exec mc-server-runner "${mcServerRunnerArgs[@]}" --shell bash run.sh
|
exec mc-server-runner "${mcServerRunnerArgs[@]}" --shell bash "${SERVER}"
|
||||||
else
|
else
|
||||||
# If we have a bootstrap.txt file... feed that in to the server stdin
|
# If we have a bootstrap.txt file... feed that in to the server stdin
|
||||||
if [ -f /data/bootstrap.txt ]; then
|
if [ -f /data/bootstrap.txt ]; then
|
||||||
@@ -255,11 +353,11 @@ else
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if isTrue ${DEBUG_EXEC}; then
|
if isTrue "${DEBUG_EXEC}"; then
|
||||||
set -x
|
set -x
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if isTrue ${EXEC_DIRECTLY:-false}; then
|
if isTrue "${EXEC_DIRECTLY:-false}"; then
|
||||||
exec java "${finalArgs[@]}"
|
exec java "${finalArgs[@]}"
|
||||||
else
|
else
|
||||||
exec mc-server-runner ${bootstrapArgs} "${mcServerRunnerArgs[@]}" java "${finalArgs[@]}"
|
exec mc-server-runner ${bootstrapArgs} "${mcServerRunnerArgs[@]}" java "${finalArgs[@]}"
|
||||||
77
scripts/start-setupDatapack
Executable file
77
scripts/start-setupDatapack
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/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" "$@"
|
||||||
@@ -1,17 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
: ${REPLACE_ENV_IN_PLACE:=${REPLACE_ENV_VARIABLES:-false}}
|
: "${REPLACE_ENV_IN_PLACE:=${REPLACE_ENV_VARIABLES:-false}}"
|
||||||
: ${REPLACE_ENV_PATHS:=/data}
|
: "${REPLACE_ENV_PATHS:=/data}"
|
||||||
: ${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}
|
: "${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}"
|
||||||
: ${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}
|
: "${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}"
|
||||||
: ${REPLACE_ENV_VARIABLES_EXCLUDES:=}
|
: "${REPLACE_ENV_VARIABLES_EXCLUDES:=}"
|
||||||
: ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}
|
: "${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}"
|
||||||
: ${PATCH_DEFINITIONS:=}
|
: "${PATCH_DEFINITIONS:=}"
|
||||||
: ${DEBUG:=false}
|
: "${DEBUG:=false}"
|
||||||
|
|
||||||
if isTrue "${REPLACE_ENV_IN_PLACE}"; then
|
if isTrue "${REPLACE_ENV_IN_PLACE}"; then
|
||||||
log "Replacing env variables in ${REPLACE_ENV_PATHS} that match the prefix $REPLACE_ENV_VARIABLE_PREFIX ..."
|
log "Replacing env variables in ${REPLACE_ENV_PATHS} that match the prefix $REPLACE_ENV_VARIABLE_PREFIX ..."
|
||||||
@@ -20,15 +21,15 @@ if isTrue "${REPLACE_ENV_IN_PLACE}"; then
|
|||||||
--replace-env-file-suffixes="${REPLACE_ENV_SUFFIXES}" \
|
--replace-env-file-suffixes="${REPLACE_ENV_SUFFIXES}" \
|
||||||
--replace-env-excludes="${REPLACE_ENV_VARIABLES_EXCLUDES}" \
|
--replace-env-excludes="${REPLACE_ENV_VARIABLES_EXCLUDES}" \
|
||||||
--replace-env-exclude-paths="${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS}" \
|
--replace-env-exclude-paths="${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS}" \
|
||||||
--replace-env-prefix=${REPLACE_ENV_VARIABLE_PREFIX} \
|
--replace-env-prefix="${REPLACE_ENV_VARIABLE_PREFIX}" \
|
||||||
"${REPLACE_ENV_PATHS[@]}"
|
"${REPLACE_ENV_PATHS[@]}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${PATCH_DEFINITIONS} ]]; then
|
if [[ ${PATCH_DEFINITIONS} ]]; then
|
||||||
log "Applying patch definitions from ${PATCH_DEFINITIONS}"
|
log "Applying patch definitions from ${PATCH_DEFINITIONS}"
|
||||||
mc-image-helper --debug=${DEBUG} patch \
|
mc-image-helper --debug=${DEBUG} patch \
|
||||||
--patch-env-prefix=${REPLACE_ENV_VARIABLE_PREFIX} \
|
--patch-env-prefix="${REPLACE_ENV_VARIABLE_PREFIX}" \
|
||||||
"${PATCH_DEFINITIONS}"
|
"${PATCH_DEFINITIONS}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-finalExec $@
|
exec "${SCRIPTS:-/}start-finalExec" "$@"
|
||||||
177
scripts/start-setupForgeApiMods
Normal file
177
scripts/start-setupForgeApiMods
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e -o pipefail
|
||||||
|
|
||||||
|
: "${MODS_FORGEAPI_KEY:=}"
|
||||||
|
: "${REMOVE_OLD_FORGEAPI_MODS:=false}"
|
||||||
|
: "${MODS_FORGEAPI_PROJECTIDS:=}"
|
||||||
|
: "${MODS_FORGEAPI_FILE:=}"
|
||||||
|
: "${MODS_FORGEAPI_RELEASES:=RELEASE}"
|
||||||
|
: "${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,,}" ]; then
|
||||||
|
RELEASE_NUMBER_FILTER=1
|
||||||
|
elif [ "beta" = "${releaseType,,}" ]; then
|
||||||
|
RELEASE_NUMBER_FILTER=2
|
||||||
|
elif [ "alpha" = "${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"
|
||||||
|
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
|
||||||
|
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.
|
||||||
|
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]')
|
||||||
|
|
||||||
|
# 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
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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
|
||||||
|
MODS_FORGEAPI_PROJECTIDS=$(jq --raw-output '[.[] | .projectId] | join(",")' $MODS_FORGEAPI_FILE)
|
||||||
|
if [ ! "$MODS_FORGEAPI_PROJECTIDS" ]; then
|
||||||
|
log "ERROR: unable to retrieve packs from $MODS_FORGEAPI_FILE"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Needs loop here to look up release types befor calling download.
|
||||||
|
for project_id in ${MODS_FORGEAPI_PROJECTIDS//,/ }; do
|
||||||
|
current_release_type=$(jq --arg PROJECT_ID "$project_id" -jc '
|
||||||
|
.[] | select(.projectId==$PROJECT_ID) | .releaseType' "$MODS_FORGEAPI_FILE")
|
||||||
|
modFileByProjectID $project_id $current_release_type
|
||||||
|
downloadModPackfromModFile
|
||||||
|
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
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "${SCRIPTS:-/}start-setupModpack" "$@"
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
|
|
||||||
# If supplied with a URL for a config (simple zip of configurations), download it and unpack
|
# If supplied with a URL for a config (simple zip of configurations), download it and unpack
|
||||||
if [[ "$MODCONFIG" ]]; then
|
if [[ "$MODCONFIG" ]]; then
|
||||||
@@ -9,7 +10,7 @@ case "X$MODCONFIG" in
|
|||||||
log "Downloading mod/plugin configs via HTTP"
|
log "Downloading mod/plugin configs via HTTP"
|
||||||
log " from $MODCONFIG ..."
|
log " from $MODCONFIG ..."
|
||||||
curl -sSL -o /tmp/modconfig.zip "$MODCONFIG"
|
curl -sSL -o /tmp/modconfig.zip "$MODCONFIG"
|
||||||
if [ "$TYPE" = "SPIGOT" ]; then
|
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||||
mkdir -p /data/plugins
|
mkdir -p /data/plugins
|
||||||
unzip -o -d /data/plugins /tmp/modconfig.zip
|
unzip -o -d /data/plugins /tmp/modconfig.zip
|
||||||
else
|
else
|
||||||
@@ -24,4 +25,4 @@ case "X$MODCONFIG" in
|
|||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupMounts $@
|
exec "${SCRIPTS:-/}start-setupMounts" "$@"
|
||||||
248
scripts/start-setupModpack
Executable file
248
scripts/start-setupModpack
Executable file
@@ -0,0 +1,248 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e -o pipefail
|
||||||
|
|
||||||
|
: "${REMOVE_OLD_MODS:=false}"
|
||||||
|
: "${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"
|
||||||
|
isDebugging && set -x
|
||||||
|
|
||||||
|
# CURSE_URL_BASE used in manifest downloads below
|
||||||
|
CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
|
||||||
|
|
||||||
|
# Remove old mods/plugins
|
||||||
|
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)
|
||||||
|
if [[ -z "${latestPackwiz}" ]]; then
|
||||||
|
log "WARNING: Could not retrieve Packwiz bootstrap installer release information"
|
||||||
|
else
|
||||||
|
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}"
|
||||||
|
if [[ ! -e $PACKWIZ_JAR ]]; then
|
||||||
|
log "Downloading Packwiz ${latestPackwizVer}"
|
||||||
|
curl -H "Accept:application/octet-stream" -o "$PACKWIZ_JAR" -fsSL ${latestPackwizUrl}
|
||||||
|
ln -sf "${PACKWIZ_JAR}" packwiz-installer-bootstrap.jar
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ ! -e packwiz-installer-bootstrap.jar ]]; then
|
||||||
|
log "ERROR: Packwiz not available or could not be downloaded from Github!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if isURL "${PACKWIZ_URL}"; then
|
||||||
|
log "Running packwiz against URL: ${PACKWIZ_URL}"
|
||||||
|
java -jar packwiz-installer-bootstrap.jar -g -s server "${PACKWIZ_URL}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack
|
||||||
|
if [[ "$MODPACK" ]]; then
|
||||||
|
if isURL "${MODPACK}"; then
|
||||||
|
log "Downloading mod/plugin pack"
|
||||||
|
if ! get -o /tmp/modpack.zip "${MODPACK}"; then
|
||||||
|
log "ERROR: failed to download from ${MODPACK}"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
elif [[ "$MODPACK" =~ .*\.zip ]]; then
|
||||||
|
if ! cp "$MODPACK" /tmp/modpack.zip; then
|
||||||
|
log "ERROR: failed to copy from $MODPACK"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "ERROR Invalid URL or Path given for MODPACK: $MODPACK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$FAMILY" = "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}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mkdir -p /data/mods
|
||||||
|
if ! unzip -o -d /data/mods /tmp/modpack.zip; then
|
||||||
|
log "ERROR: failed to unzip the modpack from ${MODPACK}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
rm -f /tmp/modpack.zip
|
||||||
|
|
||||||
|
elif [[ "$MODS" ]]; then
|
||||||
|
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||||
|
out_dir=/data/plugins
|
||||||
|
else
|
||||||
|
out_dir=/data/mods
|
||||||
|
fi
|
||||||
|
mkdir -p "$out_dir"
|
||||||
|
|
||||||
|
for i in ${MODS//,/ }
|
||||||
|
do
|
||||||
|
if isURL "$i"; then
|
||||||
|
log "Downloading mod/plugin $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" =~ .*\.jar ]]; then
|
||||||
|
log "Copying plugin 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 plugin jars from $i ..."
|
||||||
|
cp "$i"/*.jar "${out_dir}"
|
||||||
|
else
|
||||||
|
log "ERROR Invalid URL or path given in MODS: $i"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
elif [[ "$MODS_FILE" ]]; then
|
||||||
|
if [ ! -f "$MODS_FILE" ]; then
|
||||||
|
log "ERROR: given MODS_FILE file does not exist"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||||
|
out_dir=/data/plugins
|
||||||
|
else
|
||||||
|
out_dir=/data/mods
|
||||||
|
fi
|
||||||
|
mkdir -p "$out_dir"
|
||||||
|
|
||||||
|
args=(
|
||||||
|
-o "${out_dir}"
|
||||||
|
--log-progress-each
|
||||||
|
--skip-existing
|
||||||
|
--uris-file "${MODS_FILE}"
|
||||||
|
)
|
||||||
|
if isTrue "${REMOVE_OLD_MODS}"; then
|
||||||
|
args+=(
|
||||||
|
--prune-others "${REMOVE_OLD_MODS_INCLUDE}"
|
||||||
|
--prune-depth "${REMOVE_OLD_MODS_DEPTH}"
|
||||||
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! get "${args[@]}" ; then
|
||||||
|
log "ERROR: failed to retrieve one or more mods"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$MANIFEST" ]]; then
|
||||||
|
if [[ -e "$MANIFEST" ]]; then
|
||||||
|
EFFECTIVE_MANIFEST_FILE=$MANIFEST
|
||||||
|
elif isURL "$MANIFEST"; then
|
||||||
|
EFFECTIVE_MANIFEST_FILE=/tmp/manifest.json
|
||||||
|
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{effective_url} $MANIFEST)
|
||||||
|
curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL"
|
||||||
|
else
|
||||||
|
log "MANIFEST='$MANIFEST' is not a valid manifest url or location"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "X$EFFECTIVE_MANIFEST_FILE" in
|
||||||
|
X*.json)
|
||||||
|
if [ -f "${EFFECTIVE_MANIFEST_FILE}" ]; then
|
||||||
|
MOD_DIR=${FTB_BASE_DIR:-/data}/mods
|
||||||
|
if [ ! -d "$MOD_DIR" ]
|
||||||
|
then
|
||||||
|
log "Creating mods dir $MOD_DIR"
|
||||||
|
mkdir -p "$MOD_DIR"
|
||||||
|
fi
|
||||||
|
log "Starting manifest download..."
|
||||||
|
cat "${EFFECTIVE_MANIFEST_FILE}" | jq -r '.files[] | (.projectID|tostring) + " " + (.fileID|tostring)'| while read -r p f
|
||||||
|
do
|
||||||
|
if [ ! -f $MOD_DIR/${p}_${f}.jar ]
|
||||||
|
then
|
||||||
|
redirect_url="$(curl -Ls -o /dev/null -w %{effective_url} ${CURSE_URL_BASE}/${p})"
|
||||||
|
url="$redirect_url/download/${f}/file"
|
||||||
|
log Downloading curseforge mod $url
|
||||||
|
# Manifest usually doesn't have mod names. Using id should be fine, tho
|
||||||
|
curl -sSL "${url}" -o $MOD_DIR/${p}_${f}.jar
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
else
|
||||||
|
log "Could not find manifest file, insufficient privileges, or malformed path."
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "Invalid manifest file for modpack. Please make sure it is a .json file."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
: "${GENERIC_PACKS:=${GENERIC_PACK}}"
|
||||||
|
|
||||||
|
if [[ "${GENERIC_PACKS}" ]]; then
|
||||||
|
IFS=',' read -ra packs <<< "${GENERIC_PACKS}"
|
||||||
|
|
||||||
|
packFiles=()
|
||||||
|
for pack in "${packs[@]}"; do
|
||||||
|
if isURL "$pack"; then
|
||||||
|
mkdir -p /data/packs
|
||||||
|
if ! outfile=$(get -o /data/packs --output-filename --skip-existing "$pack"); then
|
||||||
|
log "ERROR: failed to download $pack"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
packFiles+=("$outfile")
|
||||||
|
else
|
||||||
|
packFiles+=("$pack")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
isDebugging && [ -f "$sum_file}" ] && cat "$sum_file"
|
||||||
|
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}"
|
||||||
|
unzip -q -d ${base_dir} "${pack}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# recalculate the actual base directory of content
|
||||||
|
base_dir=$(find "$base_dir" -type d \( -name mods -o -name plugins -o -name config \) -printf '%h' -quit)
|
||||||
|
if [[ ! $base_dir ]]; then
|
||||||
|
log "ERROR: Unable to find content base of generic packs ${GENERIC_PACKS}. Directories:"
|
||||||
|
find /tmp/generic_pack_base -type d -printf ' - %P\n'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f /data/manifest.txt ]; then
|
||||||
|
log "Manifest exists from older generic pack, cleaning up ..."
|
||||||
|
while read -r f; do
|
||||||
|
rm -rf "/data/${f}"
|
||||||
|
done < /data/manifest.txt
|
||||||
|
# prune empty dirs
|
||||||
|
find /data -mindepth 1 -depth -type d -empty -delete
|
||||||
|
rm -f /data/manifest.txt
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Writing generic pack manifest ... "
|
||||||
|
find "${base_dir}" -type f -printf "%P\n" > /data/manifest.txt
|
||||||
|
|
||||||
|
log "Applying generic pack ..."
|
||||||
|
cp -R -f "${base_dir}"/* /data
|
||||||
|
rm -rf /tmp/generic_pack_base
|
||||||
|
|
||||||
|
sha256sum "${packFiles[@]}" > "${sum_file}"
|
||||||
|
isDebugging && cat "$sum_file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "${SCRIPTS:-/}start-setupModconfig" "$@"
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
|
|
||||||
: ${SYNC_SKIP_NEWER_IN_DESTINATION:=${PLUGINS_SYNC_UPDATE:-true}}
|
: "${SYNC_SKIP_NEWER_IN_DESTINATION:=${PLUGINS_SYNC_UPDATE:-true}}"
|
||||||
: ${REPLACE_ENV_DURING_SYNC:=true}
|
: "${REPLACE_ENV_DURING_SYNC:=true}"
|
||||||
: ${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}
|
: "${REPLACE_ENV_SUFFIXES:=yml,yaml,txt,cfg,conf,properties,hjson,json,tml,toml}"
|
||||||
: ${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}
|
: "${REPLACE_ENV_VARIABLE_PREFIX:=${ENV_VARIABLE_PREFIX:-CFG_}}"
|
||||||
: ${REPLACE_ENV_VARIABLES_EXCLUDES:=}
|
: "${REPLACE_ENV_VARIABLES_EXCLUDES:=}"
|
||||||
: ${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}
|
: "${REPLACE_ENV_VARIABLES_EXCLUDE_PATHS:=}"
|
||||||
: ${DEBUG:=false}
|
: "${DEBUG:=false}"
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
@@ -24,8 +25,8 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -d /plugins ]; then
|
if [ -d /plugins ]; then
|
||||||
case ${TYPE} in
|
case ${FAMILY} in
|
||||||
SPIGOT|BUKKIT|PAPER|MAGMA)
|
SPIGOT|HYBRID)
|
||||||
mkdir -p /data/plugins
|
mkdir -p /data/plugins
|
||||||
log "Copying plugins over..."
|
log "Copying plugins over..."
|
||||||
mc-image-helper \
|
mc-image-helper \
|
||||||
@@ -40,7 +41,7 @@ if [ -d /plugins ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# If any modules have been provided, copy them over
|
# If any modules have been provided, copy them over
|
||||||
: ${COPY_MODS_DEST:="/data/mods"}
|
: "${COPY_MODS_DEST:="/data/mods"}"
|
||||||
|
|
||||||
if [ -d /mods ]; then
|
if [ -d /mods ]; then
|
||||||
log "Copying any mods over..."
|
log "Copying any mods over..."
|
||||||
@@ -53,7 +54,7 @@ if [ -d /mods ]; then
|
|||||||
/mods "${COPY_MODS_DEST}"
|
/mods "${COPY_MODS_DEST}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
: ${COPY_CONFIG_DEST:="/data/config"}
|
: "${COPY_CONFIG_DEST:="/data/config"}"
|
||||||
|
|
||||||
if [ -d /config ]; then
|
if [ -d /config ]; then
|
||||||
log "Copying any configs from /config to ${COPY_CONFIG_DEST}"
|
log "Copying any configs from /config to ${COPY_CONFIG_DEST}"
|
||||||
@@ -66,4 +67,4 @@ if [ -d /config ]; then
|
|||||||
/config "${COPY_CONFIG_DEST}"
|
/config "${COPY_CONFIG_DEST}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupServerProperties $@
|
exec "${SCRIPTS:-/}start-setupServerProperties" "$@"
|
||||||
240
scripts/start-setupServerProperties
Executable file
240
scripts/start-setupServerProperties
Executable file
@@ -0,0 +1,240 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
|
|
||||||
|
: "${SERVER_PROPERTIES:=/data/server.properties}"
|
||||||
|
|
||||||
|
# FUNCTIONS
|
||||||
|
function setServerPropValue {
|
||||||
|
local prop=$1
|
||||||
|
local value=$2
|
||||||
|
# normalize booleans
|
||||||
|
case ${value^^} in
|
||||||
|
TRUE|FALSE)
|
||||||
|
value=${value,,} ;;
|
||||||
|
esac
|
||||||
|
if grep "${prop}" "$SERVER_PROPERTIES" > /dev/null; then
|
||||||
|
log "Setting ${prop} to '${value}' in ${SERVER_PROPERTIES}"
|
||||||
|
sed -i "/^${prop}\s*=/ c ${prop}=${value//\\/\\\\}" "$SERVER_PROPERTIES"
|
||||||
|
else
|
||||||
|
log "Adding ${prop} with '${value}' in ${SERVER_PROPERTIES}"
|
||||||
|
echo "${prop}=${value}" >> "$SERVER_PROPERTIES"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function setServerProp {
|
||||||
|
local prop=$1
|
||||||
|
local varName=$2
|
||||||
|
|
||||||
|
if [ -v $varName ]; then
|
||||||
|
setServerPropValue "$prop" "${!varName}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function customizeServerProps {
|
||||||
|
# Whitelist processing
|
||||||
|
if [ -n "$WHITELIST" ] || [ -n "$WHITELIST_FILE" ] || isTrue "${ENABLE_WHITELIST:-false}"; then
|
||||||
|
log "Enabling whitelist functionality"
|
||||||
|
setServerPropValue "white-list" "true"
|
||||||
|
else
|
||||||
|
log "Disabling whitelist functionality"
|
||||||
|
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
|
||||||
|
# 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
|
||||||
|
else
|
||||||
|
label=${ORIGINAL_TYPE}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert label to title-case
|
||||||
|
label=${label,,}
|
||||||
|
label=${label^}
|
||||||
|
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
|
||||||
|
setServerProp "allow-nether" ALLOW_NETHER
|
||||||
|
setServerProp "announce-player-achievements" ANNOUNCE_PLAYER_ACHIEVEMENTS
|
||||||
|
setServerProp "enable-command-block" ENABLE_COMMAND_BLOCK
|
||||||
|
setServerProp "spawn-animals" SPAWN_ANIMALS
|
||||||
|
setServerProp "spawn-monsters" SPAWN_MONSTERS
|
||||||
|
setServerProp "spawn-npcs" SPAWN_NPCS
|
||||||
|
setServerProp "spawn-protection" SPAWN_PROTECTION
|
||||||
|
setServerProp "generate-structures" GENERATE_STRUCTURES
|
||||||
|
setServerProp "view-distance" VIEW_DISTANCE
|
||||||
|
setServerProp "hardcore" HARDCORE
|
||||||
|
setServerProp "snooper-enabled" SNOOPER_ENABLED
|
||||||
|
setServerProp "max-build-height" MAX_BUILD_HEIGHT
|
||||||
|
setServerProp "force-gamemode" FORCE_GAMEMODE
|
||||||
|
setServerProp "max-tick-time" MAX_TICK_TIME
|
||||||
|
setServerProp "enable-query" ENABLE_QUERY
|
||||||
|
setServerProp "query.port" QUERY_PORT
|
||||||
|
setServerProp "enable-rcon" ENABLE_RCON
|
||||||
|
setServerProp "rcon.password" RCON_PASSWORD
|
||||||
|
setServerProp "rcon.port" RCON_PORT
|
||||||
|
setServerProp "max-players" MAX_PLAYERS
|
||||||
|
setServerProp "max-world-size" MAX_WORLD_SIZE
|
||||||
|
setServerProp "level-name" LEVEL
|
||||||
|
setServerProp "level-seed" SEED
|
||||||
|
setServerProp "pvp" PVP
|
||||||
|
setServerProp "generator-settings" GENERATOR_SETTINGS
|
||||||
|
setServerProp "online-mode" ONLINE_MODE
|
||||||
|
setServerProp "allow-flight" ALLOW_FLIGHT
|
||||||
|
setServerProp "resource-pack" RESOURCE_PACK
|
||||||
|
setServerProp "resource-pack-sha1" RESOURCE_PACK_SHA1
|
||||||
|
setServerProp "require-resource-pack" RESOURCE_PACK_ENFORCE
|
||||||
|
setServerProp "player-idle-timeout" PLAYER_IDLE_TIMEOUT
|
||||||
|
setServerProp "broadcast-console-to-ops" BROADCAST_CONSOLE_TO_OPS
|
||||||
|
setServerProp "broadcast-rcon-to-ops" BROADCAST_RCON_TO_OPS
|
||||||
|
setServerProp "enable-jmx-monitoring" ENABLE_JMX
|
||||||
|
setServerProp "sync-chunk-writes" SYNC_CHUNK_WRITES
|
||||||
|
setServerProp "enable-status" ENABLE_STATUS
|
||||||
|
setServerProp "entity-broadcast-range-percentage" ENTITY_BROADCAST_RANGE_PERCENTAGE
|
||||||
|
setServerProp "function-permission-level" FUNCTION_PERMISSION_LEVEL
|
||||||
|
setServerProp "network-compression-threshold" NETWORK_COMPRESSION_THRESHOLD
|
||||||
|
setServerProp "op-permission-level" OP_PERMISSION_LEVEL
|
||||||
|
setServerProp "prevent-proxy-connections" PREVENT_PROXY_CONNECTIONS
|
||||||
|
setServerProp "use-native-transport" USE_NATIVE_TRANSPORT
|
||||||
|
setServerProp "simulation-distance" SIMULATION_DISTANCE
|
||||||
|
setServerPropValue "motd" "$(echo "$MOTD" | mc-image-helper asciify)"
|
||||||
|
[[ $LEVEL_TYPE ]] && setServerPropValue "level-type" "${LEVEL_TYPE^^}"
|
||||||
|
|
||||||
|
if [ -n "$DIFFICULTY" ]; then
|
||||||
|
case ${DIFFICULTY,,} in
|
||||||
|
peaceful|0)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
DIFFICULTY=0
|
||||||
|
else
|
||||||
|
DIFFICULTY=peaceful
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
easy|1)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
DIFFICULTY=1
|
||||||
|
else
|
||||||
|
DIFFICULTY=easy
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
normal|2)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
DIFFICULTY=2
|
||||||
|
else
|
||||||
|
DIFFICULTY=normal
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
hard|3)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
DIFFICULTY=3
|
||||||
|
else
|
||||||
|
DIFFICULTY=hard
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "DIFFICULTY must be peaceful, easy, normal, or hard."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
setServerPropValue "difficulty" "$DIFFICULTY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$MODE" ]; then
|
||||||
|
log "Setting mode"
|
||||||
|
case ${MODE,,} in
|
||||||
|
su*|0)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
MODE=0
|
||||||
|
else
|
||||||
|
MODE=survival
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
c*|1)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
MODE=1
|
||||||
|
else
|
||||||
|
MODE=creative
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
a*|2)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
MODE=2
|
||||||
|
else
|
||||||
|
MODE=adventure
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
sp*|3)
|
||||||
|
if versionLessThan 1.13; then
|
||||||
|
MODE=3
|
||||||
|
else
|
||||||
|
MODE=spectator
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "ERROR: Invalid game mode: $MODE"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
setServerPropValue "gamemode" "$MODE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deploy server.properties file
|
||||||
|
if [[ ${TYPE} == "CURSEFORGE" ]]; then
|
||||||
|
export SERVER_PROPERTIES="${FTB_DIR}/server.properties"
|
||||||
|
log "detected FTB, changing properties path to ${SERVER_PROPERTIES}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! isTrue "${SKIP_SERVER_PROPERTIES:-false}"; then
|
||||||
|
if [ ! -e "$SERVER_PROPERTIES" ]; then
|
||||||
|
log "Creating server.properties in ${SERVER_PROPERTIES}"
|
||||||
|
cp /tmp/server.properties "$SERVER_PROPERTIES"
|
||||||
|
customizeServerProps
|
||||||
|
elif [ -n "${OVERRIDE_SERVER_PROPERTIES}" ]; then
|
||||||
|
case ${OVERRIDE_SERVER_PROPERTIES^^} in
|
||||||
|
TRUE|1)
|
||||||
|
customizeServerProps
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
log "server.properties already created, skipping"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
log "server.properties already created, skipping"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
log "Skipping setup of server.properties"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
||||||
|
current_max_tick=$( grep 'max-tick-time' "$SERVER_PROPERTIES" | sed -r 's/( )+//g' | awk -F= '{print $2}' )
|
||||||
|
if (( current_max_tick > 0 && current_max_tick < 86400000 )); then
|
||||||
|
log "Warning: The server.properties for the server doesn't have the Server Watchdog (effectively) disabled."
|
||||||
|
log "Warning (cont): Autopause functionality resuming the process might trigger the Watchdog and restart the server completely."
|
||||||
|
log "Warning (cont): Set the max-tick-time property to a high value (or disable the Watchdog with value -1 for versions 1.8.1+)."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if isDebugging && [ -f "${SERVER_PROPERTIES}" ]; then
|
||||||
|
log "DEBUG Dumping server.properties"
|
||||||
|
cat "${SERVER_PROPERTIES}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "${SCRIPTS:-/}start-setupEnvVariables" "$@"
|
||||||
84
scripts/start-setupVanillaTweaks
Normal file
84
scripts/start-setupVanillaTweaks
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#!/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
|
||||||
|
|
||||||
|
out_dir=/data/${LEVEL:-world}/datapacks
|
||||||
|
|
||||||
|
# Remove old VANILLATWEAKS
|
||||||
|
if isTrue "${REMOVE_OLD_VANILLATWEAKS}" && [ -z "${VANILLATWEAKS_FILE}" ]; then
|
||||||
|
if [ -d "$out_dir" ]; then
|
||||||
|
find "$out_dir" -mindepth 1 -maxdepth ${REMOVE_OLD_VANILLATWEAKS_DEPTH:-16} -wholename "${REMOVE_OLD_VANILLATWEAKS_INCLUDE:-*}" -not -wholename "${REMOVE_OLD_VANILLATWEAKS_EXCLUDE:-}" -delete
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Example: VANILLATWEAKS_SHARECODE=MGr52E
|
||||||
|
# Code generated from the UI website, typically a alphanumeric 6 digit code.
|
||||||
|
if [[ "$VANILLATWEAKS_SHARECODE" ]]; then
|
||||||
|
VANILLATWEAKS_FILE=/tmp/vanillatweaksfile.json
|
||||||
|
SHARECODE_LOOKUP_URL="https://vanillatweaks.net/assets/server/sharecode.php?code=${VANILLATWEAKS_SHARECODE}"
|
||||||
|
curl -f $SHARECODE_LOOKUP_URL -o $VANILLATWEAKS_FILE
|
||||||
|
if [ ! -f "$VANILLATWEAKS_FILE" ]; then
|
||||||
|
log "ERROR: Unable to use share code provided to retreive vanillatweaks file"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use vanillatweaks file to specify VT and datapacks
|
||||||
|
if [[ "$VANILLATWEAKS_FILE" ]]; then
|
||||||
|
if [ ! -f "$VANILLATWEAKS_FILE" ]; then
|
||||||
|
log "ERROR: given VANILLATWEAKS_FILE file does not exist"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
PACKS=$(jq -jc '.packs' $VANILLATWEAKS_FILE)
|
||||||
|
if [ ! "$PACKS" ]; then
|
||||||
|
log "ERROR: unable to retrieve packs from $VANILLATWEAKS_FILE"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
VT_VERSION=$(jq -jc '.version' $VANILLATWEAKS_FILE)
|
||||||
|
if [ ! "$VT_VERSION" ]; then
|
||||||
|
log "ERROR: unable to retrieve version from $VANILLATWEAKS_FILE"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download and unzip packs
|
||||||
|
if [[ "$PACKS" ]] && [[ "$VT_VERSION" ]]; then
|
||||||
|
VT_ZIPDATA_URL=https://vanillatweaks.net/assets/server/zipdatapacks.php
|
||||||
|
DOWNLOAD_URL=$(curl -X POST -F "packs=${PACKS}" -F "version=${VT_VERSION}" $VT_ZIPDATA_URL | jq -r '.link')
|
||||||
|
if [ ! "$DOWNLOAD_URL" ]; then
|
||||||
|
log "ERROR: unable to retrieve DOWNLOAD_URL from vanillatweaks.net!"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
TEMPZIP=/tmp/vanillatweaks.zip
|
||||||
|
if ! get -o $TEMPZIP "https://vanillatweaks.net${DOWNLOAD_URL}"; then
|
||||||
|
log "ERROR: failed to download from ${DOWNLOAD_URL}"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$out_dir"
|
||||||
|
if ! unzip -o -d "$out_dir" $TEMPZIP; then
|
||||||
|
log "ERROR: failed to unzip the ${PACKS} from ${$TEMPZIP}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# clean up files time!
|
||||||
|
rm -f $TEMPZIP
|
||||||
|
# cleans up temp vanilla tweaks file download to get stored packs
|
||||||
|
if [[ "$VANILLATWEAKS_SHARECODE" ]]; then
|
||||||
|
rm -f $VANILLATWEAKS_FILE
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "${SCRIPTS:-/}start-setupDatapack" "$@"
|
||||||
@@ -1,16 +1,14 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
# shellcheck source=start-utils
|
||||||
|
. "${SCRIPTS:-/}start-utils"
|
||||||
set -e
|
set -e
|
||||||
isDebugging && set -x
|
isDebugging && set -x
|
||||||
|
|
||||||
: ${LEVEL:=world}
|
if [ "$TYPE" = "CURSEFORGE" ]; then
|
||||||
export LEVEL
|
worldDest=$FTB_DIR/${LEVEL:-world}
|
||||||
|
|
||||||
if [ $TYPE = "CURSEFORGE" ]; then
|
|
||||||
worldDest=$FTB_DIR/$LEVEL
|
|
||||||
else
|
else
|
||||||
worldDest=/data/$LEVEL
|
worldDest=/data/${LEVEL:-world}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then
|
if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] ); then
|
||||||
@@ -21,26 +19,35 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
|
|||||||
"${worldDest}_the_end"
|
"${worldDest}_the_end"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if isURL $WORLD; then
|
if isURL "$WORLD"; then
|
||||||
curl -fsSL "$WORLD" -o /tmp/world.zip
|
log "Downloading world from $WORLD"
|
||||||
zipSrc=/tmp/world.zip
|
if ! get -o /tmp/world.bin "$WORLD"; then
|
||||||
elif [[ "$WORLD" =~ .*\.zip ]]; then
|
log "ERROR: failed to download world from $WORLD"
|
||||||
zipSrc="$WORLD"
|
exit 1
|
||||||
|
fi
|
||||||
|
WORLD=/tmp/world.bin
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "$zipSrc" ]]; then
|
if [ -f "$WORLD" ]; then
|
||||||
log "Unzipping world"
|
log "Extracting world"
|
||||||
|
|
||||||
# Stage contents so that the correct subdirectory can be picked off
|
# Stage contents so that the correct subdirectory can be picked off
|
||||||
mkdir -p /tmp/world-data
|
mkdir -p /tmp/world-data
|
||||||
(cd /tmp/world-data && unzip -o -q "$zipSrc")
|
if ! extract "$WORLD" /tmp/world-data; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$TYPE" = "SPIGOT" ]; then
|
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||||
baseDirs=$(find /tmp/world-data -name "level.dat" -not -path "*_nether*" -not -path "*_the_end*" -exec dirname "{}" \;)
|
baseDirs=$(find /tmp/world-data -name "level.dat" -not -path "*_nether*" -not -path "*_the_end*" -exec dirname "{}" \;)
|
||||||
else
|
else
|
||||||
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
|
baseDirs=$(find /tmp/world-data -name "level.dat" -exec dirname "{}" \;)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! [[ $baseDirs ]]; then
|
||||||
|
log "ERROR world content is not valid since level.dat could not be found"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
count=$(echo "$baseDirs" | wc -l)
|
count=$(echo "$baseDirs" | wc -l)
|
||||||
if [[ $count -gt 1 ]]; then
|
if [[ $count -gt 1 ]]; then
|
||||||
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
|
baseDir="$(echo "$baseDirs" | sed -n ${WORLD_INDEX:-1}p)"
|
||||||
@@ -53,17 +60,20 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest"
|
rsync --remove-source-files --recursive --delete "$baseDir/" "$worldDest"
|
||||||
if [ "$TYPE" = "SPIGOT" ]; then
|
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||||
log "Copying end and nether ..."
|
log "Copying end and nether ..."
|
||||||
[ -d "${baseDir}_nether" ] && rsync --remove-source-files --recursive --delete "${baseDir}_nether/" "${worldDest}_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"
|
[ -d "${baseDir}_the_end" ] && rsync --remove-source-files --recursive --delete "${baseDir}_the_end/" "${worldDest}_the_end"
|
||||||
fi
|
fi
|
||||||
else
|
elif [ -d "$WORLD" ]; then
|
||||||
log "Cloning world directory from $WORLD ..."
|
log "Cloning world directory from $WORLD ..."
|
||||||
rsync --recursive --delete "${WORLD%/}"/ "$worldDest"
|
rsync --recursive --delete "${WORLD%/}"/ "$worldDest"
|
||||||
|
else
|
||||||
|
log "ERROR: world file/directory $WORLD is missing"
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$TYPE" = "SPIGOT" ]; then
|
if [ "$FAMILY" = "SPIGOT" ]; then
|
||||||
# Reorganise if a Spigot server
|
# Reorganise if a Spigot server
|
||||||
log "Moving End and Nether maps to Spigot location"
|
log "Moving End and Nether maps to Spigot location"
|
||||||
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "${worldDest}_the_end"
|
[ -d "$worldDest/DIM1" ] && mv -f "$worldDest/DIM1" "${worldDest}_the_end"
|
||||||
@@ -71,4 +81,4 @@ if [[ "$WORLD" ]] && ( isTrue "${FORCE_WORLD_COPY}" || [ ! -d "$worldDest" ] );
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupModpack $@
|
exec "${SCRIPTS:-/}start-setupVanillaTweaks" "$@"
|
||||||
@@ -22,6 +22,20 @@ containsJars() {
|
|||||||
return 1
|
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() {
|
getResourceFromSpiget() {
|
||||||
resource=${1?}
|
resource=${1?}
|
||||||
|
|
||||||
@@ -81,9 +95,12 @@ downloadResourceFromSpiget() {
|
|||||||
log "Extracting contents of resource ${resource} into plugins"
|
log "Extracting contents of resource ${resource} into plugins"
|
||||||
unzip -o -q -d /data/plugins "${tmpfile}"
|
unzip -o -q -d /data/plugins "${tmpfile}"
|
||||||
rm "${tmpfile}"
|
rm "${tmpfile}"
|
||||||
else
|
elif containsPlugin "${tmpfile}"; then
|
||||||
log "Moving resource ${resource} into plugins"
|
log "Moving resource ${resource} into plugins"
|
||||||
mv "${tmpfile}" "/data/plugins/${resource}.jar"
|
mv "${tmpfile}" "/data/plugins/${resource}.jar"
|
||||||
|
else
|
||||||
|
log "ERROR downloaded resource '${resource}' seems to be not a valid plugin"
|
||||||
|
exit 2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -93,6 +93,14 @@ function logAutopauseAction() {
|
|||||||
echo "[$(date -Iseconds)] [Autopause] $*"
|
echo "[$(date -Iseconds)] [Autopause] $*"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function logAutostop() {
|
||||||
|
echo "[Autostop loop] $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
function logAutostopAction() {
|
||||||
|
echo "[$(date -Iseconds)] [Autostop] $*"
|
||||||
|
}
|
||||||
|
|
||||||
function normalizeMemSize() {
|
function normalizeMemSize() {
|
||||||
local scale=1
|
local scale=1
|
||||||
case ${1,,} in
|
case ${1,,} in
|
||||||
@@ -112,32 +120,7 @@ function normalizeMemSize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function versionLessThan() {
|
function versionLessThan() {
|
||||||
local activeParts
|
mc-image-helper compare-versions "${VANILLA_VERSION}" lt "${1?}"
|
||||||
IFS=. read -ra activeParts <<<"${VANILLA_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() {
|
requireVar() {
|
||||||
@@ -161,7 +144,7 @@ requireEnum() {
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
log "ERROR: $var must be set to one of $@"
|
log "ERROR: $var must be set to one of $*"
|
||||||
# exit 1
|
# exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,4 +170,37 @@ function get() {
|
|||||||
flags+=("--debug")
|
flags+=("--debug")
|
||||||
fi
|
fi
|
||||||
mc-image-helper "${flags[@]}" get "$@"
|
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
|
||||||
|
if [[ $TYPE == "$t" ]]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function extract() {
|
||||||
|
src=${1?}
|
||||||
|
destDir=${2?}
|
||||||
|
|
||||||
|
type=$(file -b --mime-type "${src}")
|
||||||
|
if [[ $type == application/zip ]]; then
|
||||||
|
unzip -q -d "${destDir}" "${src}"
|
||||||
|
elif [[ $type == application/x-tar ]]; then
|
||||||
|
tar -C "${destDir}" -xf "${src}"
|
||||||
|
else
|
||||||
|
log "ERROR: unsupported archive type: $type"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -euo pipefail
|
|
||||||
IFS=$'\n\t'
|
|
||||||
|
|
||||||
. ${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" ] || [ "${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
|
|
||||||
|
|
||||||
if [ "${VERSION}" = "PURPUR-1.16" ]; then
|
|
||||||
AIRPLANE_BRANCH="Purpur-1.16"
|
|
||||||
AIRPLANE_TYPE="airplanepurpur"
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Using Airplane-${AIRPLANE_BRANCH} branch"
|
|
||||||
|
|
||||||
export SERVER=airplane-${AIRPLANE_BRANCH}-${AIRPLANE_BUILD}.jar
|
|
||||||
|
|
||||||
if [ ! -f "$SERVER" ] || isTrue "${FORCE_REDOWNLOAD:-false}"; then
|
|
||||||
downloadUrl="https://ci.tivy.ca/job/Airplane-${AIRPLANE_BRANCH}/${AIRPLANE_BUILD}/artifact/launcher-${AIRPLANE_TYPE}.jar"
|
|
||||||
log "Downloading Airplane from $downloadUrl ..."
|
|
||||||
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 TYPE=SPIGOT
|
|
||||||
export SKIP_LOG4J_CONFIG=true
|
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -eu
|
|
||||||
|
|
||||||
# shellcheck source=start-utils
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
|
||||||
|
|
||||||
requireVar VANILLA_VERSION
|
|
||||||
export TYPE=FABRIC
|
|
||||||
export SERVER=fabric-server-${VANILLA_VERSION}.jar
|
|
||||||
|
|
||||||
isDebugging && set -x
|
|
||||||
|
|
||||||
if [[ ! -e ${SERVER} ]]; then
|
|
||||||
|
|
||||||
: ${FABRIC_INSTALLER:=}
|
|
||||||
: ${FABRIC_INSTALLER_URL:=}
|
|
||||||
: ${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
|
|
||||||
FABRIC_INSTALLER="fabric-installer.jar"
|
|
||||||
elif [[ ! -e $FABRIC_INSTALLER ]]; then
|
|
||||||
log "ERROR: the given Fabric installer doesn't exist : $FABRIC_INSTALLER"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -e $FABRIC_INSTALLER ]]; then
|
|
||||||
log "Downloading $FABRIC_INSTALLER_URL ..."
|
|
||||||
if ! get -o "$FABRIC_INSTALLER" "$FABRIC_INSTALLER_URL"; then
|
|
||||||
log "Failed to download from given location $FABRIC_INSTALLER_URL"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Installing Fabric ${VANILLA_VERSION} using $FABRIC_INSTALLER"
|
|
||||||
|
|
||||||
tries=3
|
|
||||||
set +e
|
|
||||||
while ((--tries >= 0)); do
|
|
||||||
java -jar $FABRIC_INSTALLER server \
|
|
||||||
-mcversion $VANILLA_VERSION \
|
|
||||||
-downloadMinecraft \
|
|
||||||
-dir /data
|
|
||||||
if [[ $? == 0 ]]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
set -e
|
|
||||||
if (($tries < 0)); then
|
|
||||||
log "Fabric failed to install after several tries." >&2
|
|
||||||
exit 10
|
|
||||||
fi
|
|
||||||
|
|
||||||
mv fabric-server-launch.jar "${SERVER}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
set -e -o pipefail
|
|
||||||
|
|
||||||
# shellcheck source=start-utils
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
|
||||||
if isDebugging; then
|
|
||||||
set -x
|
|
||||||
fi
|
|
||||||
|
|
||||||
# CURSE_URL_BASE used in manifest downloads below
|
|
||||||
CURSE_URL_BASE=${CURSE_URL_BASE:-https://minecraft.curseforge.com/projects}
|
|
||||||
|
|
||||||
# Remove old mods/plugins
|
|
||||||
if isTrue ${REMOVE_OLD_MODS:-false}; then
|
|
||||||
removeOldMods /data/mods
|
|
||||||
removeOldMods /data/plugins
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack
|
|
||||||
if [[ "$MODPACK" ]]; then
|
|
||||||
if isURL "${MODPACK}"; then
|
|
||||||
if [[ "${MODPACK}" == *.zip ]]; then
|
|
||||||
downloadUrl="${MODPACK}"
|
|
||||||
else
|
|
||||||
downloadUrl=$(curl -Ls -o /dev/null -w %{url_effective} $MODPACK)
|
|
||||||
if ! [[ $downloadUrl == *.zip ]]; then
|
|
||||||
log "ERROR Invalid URL given for MODPACK: $downloadUrl resolved from $MODPACK"
|
|
||||||
log " Must be HTTP, HTTPS or FTP and a ZIP file"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Downloading mod/plugin pack"
|
|
||||||
log " from $downloadUrl ..."
|
|
||||||
if ! curl -sSL -o /tmp/modpack.zip "$downloadUrl"; then
|
|
||||||
log "ERROR: failed to download from $downloadUrl"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
elif [[ "$MODPACK" =~ .*\.zip ]]; then
|
|
||||||
if ! cp $MODPACK /tmp/modpack.zip; then
|
|
||||||
log "ERROR: failed to copy from $MODPACK"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
log "ERROR Invalid URL or Path given for MODPACK: $MODPACK"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
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 $downloadUrl"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
mkdir -p /data/mods
|
|
||||||
if ! unzip -o -d /data/mods /tmp/modpack.zip; then
|
|
||||||
log "ERROR: failed to unzip the modpack from $downloadUrl"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
rm -f /tmp/modpack.zip
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If supplied with a URL for a plugin download it.
|
|
||||||
if [[ "$MODS" ]]; then
|
|
||||||
if [ "$TYPE" = "SPIGOT" ]; then
|
|
||||||
out_dir=/data/plugins
|
|
||||||
else
|
|
||||||
out_dir=/data/mods
|
|
||||||
fi
|
|
||||||
mkdir -p "$out_dir"
|
|
||||||
|
|
||||||
for i in ${MODS//,/ }
|
|
||||||
do
|
|
||||||
if isURL "$i"; then
|
|
||||||
log "Downloading mod/plugin $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" =~ .*\.jar ]]; then
|
|
||||||
log "Copying plugin 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 plugin jars from $i ..."
|
|
||||||
cp "$i"/*.jar "${out_dir}"
|
|
||||||
else
|
|
||||||
log "ERROR Invalid URL or path given in MODS: $i"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "$MANIFEST" ]]; then
|
|
||||||
if [[ -e "$MANIFEST" ]]; then
|
|
||||||
EFFECTIVE_MANIFEST_FILE=$MANIFEST
|
|
||||||
elif isURL "$MANIFEST"; then
|
|
||||||
EFFECTIVE_MANIFEST_FILE=/tmp/manifest.json
|
|
||||||
EFFECTIVE_MANIFEST_URL=$(curl -Ls -o /dev/null -w %{effective_url} $MANIFEST)
|
|
||||||
curl -Ls -o $EFFECTIVE_MANIFEST_FILE "$EFFECTIVE_MANIFEST_URL"
|
|
||||||
else
|
|
||||||
log "MANIFEST='$MANIFEST' is not a valid manifest url or location"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
case "X$EFFECTIVE_MANIFEST_FILE" in
|
|
||||||
X*.json)
|
|
||||||
if [ -f "${EFFECTIVE_MANIFEST_FILE}" ]; then
|
|
||||||
MOD_DIR=${FTB_BASE_DIR:-/data}/mods
|
|
||||||
if [ ! -d "$MOD_DIR" ]
|
|
||||||
then
|
|
||||||
log "Creating mods dir $MOD_DIR"
|
|
||||||
mkdir -p "$MOD_DIR"
|
|
||||||
fi
|
|
||||||
log "Starting manifest download..."
|
|
||||||
cat "${EFFECTIVE_MANIFEST_FILE}" | jq -r '.files[] | (.projectID|tostring) + " " + (.fileID|tostring)'| while read -r p f
|
|
||||||
do
|
|
||||||
if [ ! -f $MOD_DIR/${p}_${f}.jar ]
|
|
||||||
then
|
|
||||||
redirect_url="$(curl -Ls -o /dev/null -w %{effective_url} ${CURSE_URL_BASE}/${p})"
|
|
||||||
url="$redirect_url/download/${f}/file"
|
|
||||||
log Downloading curseforge mod $url
|
|
||||||
# Manifest usually doesn't have mod names. Using id should be fine, tho
|
|
||||||
curl -sSL "${url}" -o $MOD_DIR/${p}_${f}.jar
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
else
|
|
||||||
log "Could not find manifest file, unsufficient privs, or malformed path."
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log "Invalid manifest file for modpack. Please make sure it is a .json file."
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${GENERIC_PACK}" ]]; then
|
|
||||||
if isURL "${GENERIC_PACK}"; then
|
|
||||||
log "Downloading generic pack ..."
|
|
||||||
if ! curl -fsSL -o /tmp/generic_pack.zip "${GENERIC_PACK}"; then
|
|
||||||
log "ERROR: failed to download ${GENERIC_PACK}"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
GENERIC_PACK=/tmp/generic_pack.zip
|
|
||||||
fi
|
|
||||||
|
|
||||||
sum_file=/data/.generic_pack.sum
|
|
||||||
if ! sha256sum -c ${sum_file} -s 2> /dev/null; then
|
|
||||||
base_dir=/tmp/generic_pack_base
|
|
||||||
mkdir -p ${base_dir}
|
|
||||||
isDebugging && ls -l "${GENERIC_PACK}"
|
|
||||||
unzip -q -d ${base_dir} "${GENERIC_PACK}"
|
|
||||||
if [ -f /data/manifest.txt ]; then
|
|
||||||
log "Manifest exists from older generic pack, cleaning up ..."
|
|
||||||
while read f; do
|
|
||||||
rm -rf "/data/${f}"
|
|
||||||
done < /data/manifest.txt
|
|
||||||
find /data/* -type d -exec rmdir --ignore-fail-on-non-empty {} +
|
|
||||||
rm -f /data/manifest.txt
|
|
||||||
fi
|
|
||||||
log "Writing generic pack manifest ... "
|
|
||||||
find ${base_dir} -type f -print0 | xargs -0 -I {} echo "{}" | sed "s#${base_dir}/##" > /data/manifest.txt
|
|
||||||
log "Applying generic pack ..."
|
|
||||||
IFS='
|
|
||||||
'
|
|
||||||
set -f
|
|
||||||
for d in $(find ${base_dir} -type d); do mkdir -p "$(sed "s#${base_dir}#/data#" <<< $d)"; done
|
|
||||||
for f in $(find ${base_dir} -type f); do cp -f "$f" "$(sed "s#${base_dir}#/data#" <<< $f)"; done
|
|
||||||
rm -rf ${base_dir}
|
|
||||||
sha256sum "${GENERIC_PACK}" > ${sum_file}
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupModconfig $@
|
|
||||||
@@ -1,221 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
|
||||||
|
|
||||||
: ${SERVER_PROPERTIES:=/data/server.properties}
|
|
||||||
|
|
||||||
# FUNCTIONS
|
|
||||||
function setServerProp {
|
|
||||||
local prop=$1
|
|
||||||
local var=$2
|
|
||||||
if [ -n "$var" ]; then
|
|
||||||
# normalize booleans
|
|
||||||
case ${var^^} in
|
|
||||||
TRUE|FALSE)
|
|
||||||
var=${var,,} ;;
|
|
||||||
esac
|
|
||||||
if grep "${prop}" "$SERVER_PROPERTIES" > /dev/null; then
|
|
||||||
log "Setting ${prop} to '${var}' in ${SERVER_PROPERTIES}"
|
|
||||||
sed -i "/^${prop}\s*=/ c ${prop}=${var//\\/\\\\}" "$SERVER_PROPERTIES"
|
|
||||||
else
|
|
||||||
log "Adding ${prop} with '${var}' in ${SERVER_PROPERTIES}"
|
|
||||||
echo "${prop}=${var}" >> "$SERVER_PROPERTIES"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
isDebugging && log "Skip setting ${prop}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function customizeServerProps {
|
|
||||||
if [ -n "$WHITELIST" ] || isTrue ${ENABLE_WHITELIST:-false}; then
|
|
||||||
log "Creating whitelist"
|
|
||||||
setServerProp "whitelist" "true"
|
|
||||||
setServerProp "white-list" "true"
|
|
||||||
else
|
|
||||||
log "Disabling whitelist"
|
|
||||||
setServerProp "whitelist" "false"
|
|
||||||
setServerProp "white-list" "false"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If not provided, generate a reasonable default message-of-the-day,
|
|
||||||
# which shows up in the server listing in the client
|
|
||||||
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
|
|
||||||
else
|
|
||||||
label=${ORIGINAL_TYPE}
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Convert label to title-case
|
|
||||||
label=${label,,}
|
|
||||||
label=${label^}
|
|
||||||
MOTD="A ${label} Minecraft Server powered by Docker"
|
|
||||||
fi
|
|
||||||
|
|
||||||
setServerProp "server-name" "$SERVER_NAME"
|
|
||||||
setServerProp "server-ip" "$SERVER_IP"
|
|
||||||
setServerProp "server-port" "$SERVER_PORT"
|
|
||||||
setServerProp "motd" "$(echo $MOTD | mc-image-helper asciify)"
|
|
||||||
setServerProp "allow-nether" "$ALLOW_NETHER"
|
|
||||||
setServerProp "announce-player-achievements" "$ANNOUNCE_PLAYER_ACHIEVEMENTS"
|
|
||||||
setServerProp "enable-command-block" "$ENABLE_COMMAND_BLOCK"
|
|
||||||
setServerProp "spawn-animals" "$SPAWN_ANIMALS"
|
|
||||||
setServerProp "spawn-monsters" "$SPAWN_MONSTERS"
|
|
||||||
setServerProp "spawn-npcs" "$SPAWN_NPCS"
|
|
||||||
setServerProp "spawn-protection" "$SPAWN_PROTECTION"
|
|
||||||
setServerProp "generate-structures" "$GENERATE_STRUCTURES"
|
|
||||||
setServerProp "view-distance" "$VIEW_DISTANCE"
|
|
||||||
setServerProp "hardcore" "$HARDCORE"
|
|
||||||
setServerProp "snooper-enabled" "$SNOOPER_ENABLED"
|
|
||||||
setServerProp "max-build-height" "$MAX_BUILD_HEIGHT"
|
|
||||||
setServerProp "force-gamemode" "$FORCE_GAMEMODE"
|
|
||||||
setServerProp "max-tick-time" "$MAX_TICK_TIME"
|
|
||||||
setServerProp "enable-query" "$ENABLE_QUERY"
|
|
||||||
setServerProp "query.port" "$QUERY_PORT"
|
|
||||||
setServerProp "enable-rcon" "$ENABLE_RCON"
|
|
||||||
setServerProp "rcon.password" "$RCON_PASSWORD"
|
|
||||||
setServerProp "rcon.port" "$RCON_PORT"
|
|
||||||
setServerProp "max-players" "$MAX_PLAYERS"
|
|
||||||
setServerProp "max-world-size" "$MAX_WORLD_SIZE"
|
|
||||||
setServerProp "level-name" "$LEVEL"
|
|
||||||
setServerProp "level-seed" "$SEED"
|
|
||||||
setServerProp "pvp" "${PVP}"
|
|
||||||
setServerProp "generator-settings" "$GENERATOR_SETTINGS"
|
|
||||||
setServerProp "online-mode" "$ONLINE_MODE"
|
|
||||||
setServerProp "allow-flight" "$ALLOW_FLIGHT"
|
|
||||||
setServerProp "level-type" "${LEVEL_TYPE^^}"
|
|
||||||
setServerProp "resource-pack" "$RESOURCE_PACK"
|
|
||||||
setServerProp "resource-pack-sha1" "$RESOURCE_PACK_SHA1"
|
|
||||||
setServerProp "player-idle-timeout" "$PLAYER_IDLE_TIMEOUT"
|
|
||||||
setServerProp "broadcast-console-to-ops" "$BROADCAST_CONSOLE_TO_OPS"
|
|
||||||
setServerProp "broadcast-rcon-to-ops" "$BROADCAST_RCON_TO_OPS"
|
|
||||||
setServerProp "enable-jmx-monitoring" "$ENABLE_JMX"
|
|
||||||
setServerProp "sync-chunk-writes" "$SYNC_CHUNK_WRITES"
|
|
||||||
setServerProp "enable-status" "$ENABLE_STATUS"
|
|
||||||
setServerProp "entity-broadcast-range-percentage" "$ENTITY_BROADCAST_RANGE_PERCENTAGE"
|
|
||||||
setServerProp "function-permission-level" "$FUNCTION_PERMISSION_LEVEL"
|
|
||||||
setServerProp "network-compression-threshold" "$NETWORK_COMPRESSION_THRESHOLD"
|
|
||||||
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"
|
|
||||||
|
|
||||||
if [ -n "$DIFFICULTY" ]; then
|
|
||||||
case $DIFFICULTY in
|
|
||||||
peaceful|0)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
DIFFICULTY=0
|
|
||||||
else
|
|
||||||
DIFFICULTY=peaceful
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
easy|1)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
DIFFICULTY=1
|
|
||||||
else
|
|
||||||
DIFFICULTY=easy
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
normal|2)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
DIFFICULTY=2
|
|
||||||
else
|
|
||||||
DIFFICULTY=normal
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
hard|3)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
DIFFICULTY=3
|
|
||||||
else
|
|
||||||
DIFFICULTY=hard
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log "DIFFICULTY must be peaceful, easy, normal, or hard."
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
setServerProp "difficulty" "$DIFFICULTY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$MODE" ]; then
|
|
||||||
log "Setting mode"
|
|
||||||
MODE_LC=$( echo $MODE | tr '[:upper:]' '[:lower:]' )
|
|
||||||
case $MODE_LC in
|
|
||||||
su*|0)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
MODE=0
|
|
||||||
else
|
|
||||||
MODE=survival
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
c*|1)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
MODE=1
|
|
||||||
else
|
|
||||||
MODE=creative
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
a*|2)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
MODE=2
|
|
||||||
else
|
|
||||||
MODE=adventure
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
sp*|3)
|
|
||||||
if versionLessThan 1.13; then
|
|
||||||
MODE=3
|
|
||||||
else
|
|
||||||
MODE=spectator
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log "ERROR: Invalid game mode: $MODE"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
setServerProp "gamemode" "$MODE"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Deploy server.properties file
|
|
||||||
if [[ ${TYPE} == "CURSEFORGE" ]]; then
|
|
||||||
export SERVER_PROPERTIES="${FTB_DIR}/server.properties"
|
|
||||||
log "detected FTB, changing properties path to ${SERVER_PROPERTIES}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -e "$SERVER_PROPERTIES" ]; then
|
|
||||||
log "Creating server.properties in ${SERVER_PROPERTIES}"
|
|
||||||
cp /tmp/server.properties "$SERVER_PROPERTIES"
|
|
||||||
customizeServerProps
|
|
||||||
elif [ -n "${OVERRIDE_SERVER_PROPERTIES}" ]; then
|
|
||||||
case ${OVERRIDE_SERVER_PROPERTIES^^} in
|
|
||||||
TRUE|1)
|
|
||||||
customizeServerProps
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
log "server.properties already created, skipping"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
else
|
|
||||||
log "server.properties already created, skipping"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if isTrue "${ENABLE_AUTOPAUSE}"; then
|
|
||||||
current_max_tick=$( grep 'max-tick-time' "$SERVER_PROPERTIES" | sed -r 's/( )+//g' | awk -F= '{print $2}' )
|
|
||||||
if (( $current_max_tick > 0 && $current_max_tick < 86400000 )); then
|
|
||||||
log "Warning: The server.properties for the server doesn't have the Server Watchdog (effectively) disabled."
|
|
||||||
log "Warning (cont): Autopause functionality resuming the process might trigger the Watchdog and restart the server completely."
|
|
||||||
log "Warning (cont): Set the max-tick-time property to a high value (or disable the Watchdog with value -1 for versions 1.8.1+)."
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if isDebugging; then
|
|
||||||
log "DEBUG Dumping server.properties"
|
|
||||||
cat "${SERVER_PROPERTIES}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupEnvVariables $@
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
. ${SCRIPTS:-/}start-utils
|
|
||||||
|
|
||||||
if ! [[ -v CURSE_INSTANCE_JSON ]]; then
|
|
||||||
log "ERROR: CURSE_INSTANCE_JSON needs to be set"
|
|
||||||
exit 2
|
|
||||||
elif ! [ -f "${CURSE_INSTANCE_JSON}" ] && [ -f "${CURSE_INSTANCE_JSON}/minecraftinstance.json" ]; then
|
|
||||||
CURSE_INSTANCE_JSON="${CURSE_INSTANCE_JSON}/minecraftinstance.json"
|
|
||||||
elif ! [ -f "${CURSE_INSTANCE_JSON}" ]; then
|
|
||||||
log "ERROR: CURSE_INSTANCE_JSON file does not exist: ${CURSE_INSTANCE_JSON}"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
||||||
|
|
||||||
log "Resolved CURSE_INSTANCE_JSON as ${CURSE_INSTANCE_JSON}"
|
|
||||||
|
|
||||||
exec ${SCRIPTS:-/}start-setupWorld "$@"
|
|
||||||
1
tests/.gitignore
vendored
Normal file
1
tests/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
data/
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
|
||||||
sut:
|
|
||||||
depends_on:
|
|
||||||
- mc
|
|
||||||
image: itzg/mc-monitor:0.6.0
|
|
||||||
command: status --host mc --retry-interval 1s --retry-limit 120
|
|
||||||
mc:
|
|
||||||
restart: "no"
|
|
||||||
build:
|
|
||||||
context: ..
|
|
||||||
args:
|
|
||||||
TARGETOS: linux
|
|
||||||
TARGETARCH: amd64
|
|
||||||
cache_from:
|
|
||||||
- itzg/minecraft-server:latest
|
|
||||||
environment:
|
|
||||||
EULA: "TRUE"
|
|
||||||
VERSION: "1.16.5"
|
|
||||||
|
|
||||||
43
tests/fulltests/test.sh
Normal file
43
tests/fulltests/test.sh
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#!/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/fulltests/vanilla-latest/docker-compose.yml
Normal file
15
tests/fulltests/vanilla-latest/docker-compose.yml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
monitor:
|
||||||
|
depends_on:
|
||||||
|
- mc
|
||||||
|
image: itzg/mc-monitor:${MC_MONITOR_VERSION:-0.10.4}
|
||||||
|
command: status --host mc --retry-interval 1s --timeout 1s --retry-limit 240
|
||||||
|
mc:
|
||||||
|
restart: "no"
|
||||||
|
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||||
|
environment:
|
||||||
|
EULA: "TRUE"
|
||||||
|
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
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/example.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"
|
||||||
|
volumes:
|
||||||
|
- ./example.json:/config/example.json:ro
|
||||||
11
tests/setuponlytests/forgeapimods_file/example.json
Normal file
11
tests/setuponlytests/forgeapimods_file/example.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
[{
|
||||||
|
"name": "fabric api",
|
||||||
|
"projectId": "306612",
|
||||||
|
"releaseType": "release"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fabric Voice Mod",
|
||||||
|
"projectId": "416089",
|
||||||
|
"releaseType": "beta"
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
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_PROJECTIDS: 306612,416089
|
||||||
|
# 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"
|
||||||
12
tests/setuponlytests/generic-packs/docker-compose.yml
Normal file
12
tests/setuponlytests/generic-packs/docker-compose.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
mc:
|
||||||
|
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||||
|
environment:
|
||||||
|
EULA: "true"
|
||||||
|
SETUP_ONLY: "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
|
||||||
|
volumes:
|
||||||
|
- ./packs:/packs
|
||||||
|
- ./data:/data
|
||||||
BIN
tests/setuponlytests/generic-packs/packs/testing.zip
Normal file
BIN
tests/setuponlytests/generic-packs/packs/testing.zip
Normal file
Binary file not shown.
1
tests/setuponlytests/generic-packs/verify.sh
Normal file
1
tests/setuponlytests/generic-packs/verify.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mc-image-helper assert fileExists one.txt mods/two.txt
|
||||||
50
tests/setuponlytests/test.sh
Normal file
50
tests/setuponlytests/test.sh
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#!/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 ! logs=$(docker compose run --quiet-pull mc 2>&1); then
|
||||||
|
echo "${folder} setup 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}" /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
|
||||||
14
tests/setuponlytests/vanillatweaks_file/docker-compose.yml
Normal file
14
tests/setuponlytests/vanillatweaks_file/docker-compose.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
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/vanillatweaks-datapacks.json
|
||||||
|
REMOVE_OLD_VANILLATWEAKS: "TRUE"
|
||||||
|
volumes:
|
||||||
|
- ./vanillatweaks-datapacks.json:/config/vanillatweaks-datapacks.json:ro
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"type": "datapacks",
|
||||||
|
"version": "1.18",
|
||||||
|
"packs": {
|
||||||
|
"survival": [
|
||||||
|
"graves",
|
||||||
|
"multiplayer sleep",
|
||||||
|
"afk display",
|
||||||
|
"armor statues",
|
||||||
|
"unlock all recipes",
|
||||||
|
"fast leaf decay",
|
||||||
|
"coordinates hud"
|
||||||
|
],
|
||||||
|
"items": ["armored elytra"]
|
||||||
|
},
|
||||||
|
"result": "ok"
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
version: "3"
|
||||||
|
|
||||||
|
services:
|
||||||
|
mc:
|
||||||
|
restart: "no"
|
||||||
|
image: ${IMAGE_TO_TEST:-itzg/minecraft-server}
|
||||||
|
environment:
|
||||||
|
EULA: "TRUE"
|
||||||
|
SETUP_ONLY: "TRUE"
|
||||||
|
VERSION: ${MINECRAFT_VERSION:-LATEST}
|
||||||
|
VANILLATWEAKS_SHARECODE: MGr52E
|
||||||
|
REMOVE_OLD_VANILLATWEAKS: "TRUE"
|
||||||
14
tests/setuponlytests/world_from_tgz/docker-compose.yml
Normal file
14
tests/setuponlytests/world_from_tgz/docker-compose.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
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.tgz
|
||||||
|
volumes:
|
||||||
|
- ./worlds:/worlds:ro
|
||||||
|
- ./data:/data
|
||||||
1
tests/setuponlytests/world_from_tgz/verify.sh
Normal file
1
tests/setuponlytests/world_from_tgz/verify.sh
Normal file
@@ -0,0 +1 @@
|
|||||||
|
mc-image-helper assert fileExists world/level.dat
|
||||||
BIN
tests/setuponlytests/world_from_tgz/worlds/world-for-testing.tgz
Normal file
BIN
tests/setuponlytests/world_from_tgz/worlds/world-for-testing.tgz
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user