diff --git a/Dockerfile b/Dockerfile index 06383167..28f01780 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 diff --git a/docs/mods-and-plugins/index.md b/docs/mods-and-plugins/index.md index 23b3d9d4..699f5964 100644 --- a/docs/mods-and-plugins/index.md +++ b/docs/mods-and-plugins/index.md @@ -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. diff --git a/examples/geyser/docker-compose.yml b/examples/geyser/docker-compose.yml new file mode 100644 index 00000000..f773a6aa --- /dev/null +++ b/examples/geyser/docker-compose.yml @@ -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 \ No newline at end of file diff --git a/scripts/start-deployPaper b/scripts/start-deployPaper index b2655f37..b4fa1fe3 100755 --- a/scripts/start-deployPaper +++ b/scripts/start-deployPaper @@ -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" "$@" diff --git a/scripts/start-setupModpack b/scripts/start-setupModpack index 8257e292..7956a58f 100755 --- a/scripts/start-setupModpack +++ b/scripts/start-setupModpack @@ -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 diff --git a/scripts/start-utils b/scripts/start-utils index 4eed6368..b568ee67 100755 --- a/scripts/start-utils +++ b/scripts/start-utils @@ -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 +} \ No newline at end of file