mirror of
https://github.com/itzg/docker-minecraft-server.git
synced 2026-03-05 14:26:24 +00:00
Improved handling of MODS and PLUGINS lists (#2197)
This commit is contained in:
@@ -46,7 +46,7 @@ RUN easy-add --var os=${TARGETOS} --var arch=${TARGETARCH}${TARGETVARIANT} \
|
||||
--var version=0.1.1 --var app=maven-metadata-release --file {{.app}} \
|
||||
--from https://github.com/itzg/{{.app}}/releases/download/{{.version}}/{{.app}}_{{.version}}_{{.os}}_{{.arch}}.tar.gz
|
||||
|
||||
ARG MC_HELPER_VERSION=1.29.1
|
||||
ARG MC_HELPER_VERSION=1.29.2
|
||||
ARG MC_HELPER_BASE_URL=https://github.com/itzg/mc-image-helper/releases/download/${MC_HELPER_VERSION}
|
||||
# used for cache busting local copy of mc-image-helper
|
||||
ARG MC_HELPER_REV=1
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
|
||||
## Mod platforms
|
||||
|
||||
By far the easiest way to work with mod and plugins, especially large numbers of them, is to utilize [one of the supported mod platforms](../types-and-platforms/), such as Modrinth or CurseForge.
|
||||
By far the easiest way to work with mod and plugins, especially large numbers of them, is to utilize modpacks with [one of the supported mod platforms](../types-and-platforms/index.md).
|
||||
|
||||
The following are some supported mod platforms:
|
||||
- [Modrinth](../types-and-platforms/mod-platforms/modrinth-modpacks.md)
|
||||
- [CurseForge](../types-and-platforms/mod-platforms/auto-curseforge.md)
|
||||
- [Feed the Beast](../types-and-platforms/mod-platforms/ftb.md)
|
||||
|
||||
## Download automation
|
||||
|
||||
@@ -31,7 +36,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.
|
||||
|
||||
> For more flexibility with mods/plugins preparation, you can declare directories to use in [the `MODS` variable](#zip-file-modpack)
|
||||
> For more flexibility with mods/plugins preparation, you can declare directories to use in [the `MODS` variable](#modsplugins-list)
|
||||
|
||||
## Zip file modpack
|
||||
|
||||
@@ -48,15 +53,6 @@ docker run -d -e MODPACK=http://www.example.com/mods/modpack.zip ...
|
||||
top level of the zip archive. Make sure the jars are compatible with the
|
||||
particular `TYPE` of server you are running.
|
||||
|
||||
You may also download or copy over individual mods using the `MODS` environment variable. `MODS` contains a comma-separated list of
|
||||
- URL of a jar file
|
||||
- container path to a jar file
|
||||
- container path to a directory containing jar files
|
||||
|
||||
```shell
|
||||
docker run -d -e MODS=https://www.example.com/mods/mod1.jar,/plugins/common,/plugins/special/mod2.jar ...
|
||||
```
|
||||
|
||||
## Generic pack files
|
||||
|
||||
To install all the server content (jars, mods, plugins, configs, etc.) from a zip or tgz file, then set `GENERIC_PACK` to the container path or URL of the archive file. This can also be used to apply a CurseForge modpack that is missing a server start script and/or Forge installer.
|
||||
@@ -77,9 +73,27 @@ If applying large generic packs, the update can be time-consuming. To skip the u
|
||||
|
||||
The most time-consuming portion of the generic pack update is generating and comparing the SHA1 checksum. To skip the checksum generation, set `SKIP_GENERIC_PACK_CHECKSUM` to "true.
|
||||
|
||||
## Mods/plugins list
|
||||
|
||||
You may also download or copy over individual mods/plugins using the `MODS` or `PLUGINS` environment variables. Both are a comma or newline delimited list of
|
||||
- URL of a jar file
|
||||
- container path to a jar file
|
||||
- container path to a directory containing jar files
|
||||
|
||||
```shell
|
||||
docker run -d -e MODS=https://www.example.com/mods/mod1.jar,/plugins/common,/plugins/special/mod2.jar ...
|
||||
```
|
||||
|
||||
The newline delimiting allows for compose file usage like:
|
||||
```yaml
|
||||
PLUGINS: |
|
||||
https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/spigot
|
||||
https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot
|
||||
```
|
||||
|
||||
## 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
|
||||
As an alternative to `MODS`/`PLUGINS`, the variable `MODS_FILE` or `PLUGINS_FILE` can be set with the container path or URL of a text file listing a mod/plugin URLs on each line. For example, the following
|
||||
|
||||
-e MODS_FILE=/extras/mods.txt
|
||||
|
||||
@@ -100,8 +114,6 @@ https://edge.forgecdn.net/files/2871/647/ToastControl-1.15.2-3.0.1.jar
|
||||
|
||||
[This compose file](https://github.com/itzg/docker-minecraft-server/blob/master/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
|
||||
|
||||
When the `MODPACK` option above is specified you can also instruct script to 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.
|
||||
|
||||
17
examples/geyser/docker-compose.yml
Normal file
17
examples/geyser/docker-compose.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
mc:
|
||||
image: itzg/minecraft-server
|
||||
environment:
|
||||
EULA: "true"
|
||||
TYPE: "PAPER"
|
||||
DEBUG: true
|
||||
MODS: |
|
||||
https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/spigot
|
||||
https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot
|
||||
ports:
|
||||
- "25565:25565"
|
||||
- "19132:19132/udp"
|
||||
volumes:
|
||||
- ./data:/data
|
||||
@@ -40,58 +40,41 @@ function handleMissingVersion() {
|
||||
if [[ $PAPER_CUSTOM_JAR ]]; then
|
||||
export SERVER="$PAPER_CUSTOM_JAR"
|
||||
elif [[ $PAPER_DOWNLOAD_URL ]]; then
|
||||
export SERVER=$(getFilenameFromUrl "${PAPER_DOWNLOAD_URL}")
|
||||
SERVER=$(getFilenameFromUrl "${PAPER_DOWNLOAD_URL}")
|
||||
export SERVER
|
||||
|
||||
if [ -f "$SERVER" ]; then
|
||||
zarg=(-z "$SERVER")
|
||||
log "Downloading custom ${PAPER_NAME} jar from $PAPER_DOWNLOAD_URL"
|
||||
if ! mc-image-helper mcopy \
|
||||
--scope=papermc \
|
||||
--to=/data \
|
||||
"${PAPER_DOWNLOAD_URL}"; then
|
||||
echo "ERROR: failed to download ${PAPER_NAME} from $PAPER_DOWNLOAD_URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Preparing custom ${PAPER_NAME} jar from $PAPER_DOWNLOAD_URL"
|
||||
|
||||
curl -fsSL -o "$SERVER" "${zarg[@]}" "${PAPER_DOWNLOAD_URL}"
|
||||
else
|
||||
# Paper API v2 docs : https://papermc.io/api/docs/swagger-ui/index.html?configUrl=/api/openapi/swagger-config
|
||||
|
||||
build=${PAPERBUILD:=$(curl -fsSL "https://papermc.io/api/v2/projects/${PAPER_PROJECT}/versions/${VANILLA_VERSION}" -H "accept: application/json" \
|
||||
| jq '.builds[-1]')}
|
||||
case $? in
|
||||
0)
|
||||
;;
|
||||
22)
|
||||
handleMissingVersion
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown error while looking up ${PAPER_NAME} version=${VANILLA_VERSION}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
if ! build=${PAPERBUILD:=$(get --json-path=".builds[-1]" "https://papermc.io/api/v2/projects/${PAPER_PROJECT}/versions/${VANILLA_VERSION}")}; then
|
||||
log "ERROR: failed to lookup build number for ${PAPER_NAME} version=${VANILLA_VERSION}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $build = null ]]; then
|
||||
handleMissingVersion
|
||||
fi
|
||||
|
||||
export SERVER=$(curl -fsSL "https://papermc.io/api/v2/projects/${PAPER_PROJECT}/versions/${VANILLA_VERSION}/builds/${build}" -H "accept: application/json" \
|
||||
| jq -r '.downloads.application.name')
|
||||
if [ $? != 0 ]; then
|
||||
if ! SERVER=$(get --json-path=.downloads.application.name "https://papermc.io/api/v2/projects/${PAPER_PROJECT}/versions/${VANILLA_VERSION}/builds/${build}"); then
|
||||
echo "ERROR: failed to lookup ${PAPER_NAME} download file from version=${VANILLA_VERSION} build=${build}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -f "$SERVER" ]; then
|
||||
zarg=(-z "$SERVER")
|
||||
fi
|
||||
|
||||
log "Removing old ${PAPER_NAME} versions ..."
|
||||
shopt -s nullglob
|
||||
for f in paper-*.jar; do
|
||||
[[ $f != $SERVER ]] && rm $f
|
||||
done
|
||||
export SERVER
|
||||
|
||||
log "Downloading ${PAPER_NAME} $VANILLA_VERSION (build $build) ..."
|
||||
curl -fsSL -o "$SERVER" "${zarg[@]}" \
|
||||
"https://papermc.io/api/v2/projects/${PAPER_PROJECT}/versions/${VANILLA_VERSION}/builds/${build}/downloads/${SERVER}" \
|
||||
-H "accept: application/java-archive"
|
||||
if [ $? != 0 ]; then
|
||||
if ! mc-image-helper mcopy \
|
||||
--scope=papermc \
|
||||
--to=/data \
|
||||
"https://papermc.io/api/v2/projects/${PAPER_PROJECT}/versions/${VANILLA_VERSION}/builds/${build}/downloads/${SERVER}"; then
|
||||
echo "ERROR: failed to download ${PAPER_NAME} from version=${VANILLA_VERSION} build=${build} download=${SERVER}"
|
||||
exit 1
|
||||
fi
|
||||
@@ -100,4 +83,4 @@ fi
|
||||
# Normalize on Spigot for downstream operations
|
||||
export FAMILY=SPIGOT
|
||||
|
||||
exec ${SCRIPTS:-/}start-spiget "$@"
|
||||
exec "${SCRIPTS:-/}start-spiget" "$@"
|
||||
|
||||
@@ -3,7 +3,12 @@
|
||||
set -e -o pipefail
|
||||
|
||||
: "${REMOVE_OLD_MODS:=false}"
|
||||
: "${MODS:=}"
|
||||
: "${MODS_OUT_DIR:=/data/mods}"
|
||||
: "${MODS_FILE:=}"
|
||||
: "${PLUGINS:=}"
|
||||
: "${PLUGINS_OUT_DIR:=/data/plugins}"
|
||||
: "${PLUGINS_FILE:=}"
|
||||
: "${REMOVE_OLD_MODS_DEPTH:=1} "
|
||||
: "${REMOVE_OLD_MODS_INCLUDE:=*.jar,*-version.json}"
|
||||
sum_file=/data/.generic_pack.sum
|
||||
@@ -41,7 +46,7 @@ function handlePackwiz() {
|
||||
fi
|
||||
}
|
||||
|
||||
function handleModpackListOrFile() {
|
||||
function handleModpackZip() {
|
||||
# If supplied with a URL for a modpack (simple zip of jars), download it and unpack
|
||||
if [[ "$MODPACK" ]]; then
|
||||
if isURL "${MODPACK}"; then
|
||||
@@ -72,72 +77,65 @@ if [[ "$MODPACK" ]]; then
|
||||
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 --skip-up-to-date -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-up-to-date
|
||||
--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
|
||||
}
|
||||
|
||||
function handleListings() {
|
||||
if [[ "$MODS" ]]; then
|
||||
if usesMods; then
|
||||
mkdir -p "$MODS_OUT_DIR"
|
||||
mc-image-helper mcopy \
|
||||
--glob=*.jar \
|
||||
--scope=var-list \
|
||||
--to="$MODS_OUT_DIR" \
|
||||
"$MODS"
|
||||
else
|
||||
log "ERROR: TYPE=$TYPE does not support mods"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ "$PLUGINS" ]]; then
|
||||
if usesPlugins; then
|
||||
mkdir -p "$PLUGINS_OUT_DIR"
|
||||
mc-image-helper mcopy \
|
||||
--glob=*.jar \
|
||||
--scope=var-list \
|
||||
--to="$PLUGINS_OUT_DIR" \
|
||||
"$PLUGINS"
|
||||
else
|
||||
log "ERROR: TYPE=$TYPE does not support plugins"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "$MODS_FILE" ]]; then
|
||||
if usesMods; then
|
||||
mkdir -p "$MODS_OUT_DIR"
|
||||
mc-image-helper mcopy \
|
||||
--file-is-listing \
|
||||
--scope=file-list \
|
||||
--to="$MODS_OUT_DIR" \
|
||||
"$MODS_FILE"
|
||||
else
|
||||
log "ERROR: TYPE=$TYPE does not support mods"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [[ "$PLUGINS_FILE" ]]; then
|
||||
if usesPlugins; then
|
||||
mkdir -p "$PLUGINS_OUT_DIR"
|
||||
mc-image-helper mcopy \
|
||||
--file-is-listing \
|
||||
--scope=file-list \
|
||||
--to="$PLUGINS_OUT_DIR" \
|
||||
"$PLUGINS_FILE"
|
||||
else
|
||||
log "ERROR: TYPE=$TYPE does not support plugins"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function handleCurseForgeManifest() {
|
||||
if [[ "$MANIFEST" ]]; then
|
||||
if [[ -e "$MANIFEST" ]]; then
|
||||
@@ -293,7 +291,9 @@ function handleModrinthProjects() {
|
||||
|
||||
handlePackwiz
|
||||
|
||||
handleModpackListOrFile
|
||||
handleModpackZip
|
||||
|
||||
handleListings
|
||||
|
||||
handleCurseForgeManifest
|
||||
|
||||
|
||||
@@ -305,3 +305,19 @@ function checkSum() {
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function usesMods() {
|
||||
case "$FAMILY" in
|
||||
FORGE|FABRIC|HYBRID|SPONGE)
|
||||
return 0
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
function usesPlugins() {
|
||||
case "$FAMILY" in
|
||||
SPIGOT|HYBRID)
|
||||
return 0
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
Reference in New Issue
Block a user