commit f3f758c1633dd9a1a7c9b0c3f46ab3315e10ecc8 Author: Eagle517 <347708-Eagle517@users.noreply.gitlab.com> Date: Sun Feb 9 03:28:25 2025 -0600 Initial commit diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..5a61800 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,76 @@ +FROM debian:bookworm-slim + +ARG DEBIAN_FRONTEND=noninteractive \ + TINI_VERSION=0.19.0 \ + WINE_PGP_URL=https://dl.winehq.org/wine-builds/winehq.key \ + WINE_SRC_URL=https://dl.winehq.org/wine-builds/debian/dists/bookworm/winehq-bookworm.sources \ + WINE_FLAVOUR=stable \ + WINE_VERSION=8.0.2~bookworm-1 \ + USER_ID=1000 \ + GROUP_ID=1000 + +ADD https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini /tini + +RUN chmod +x /tini \ + && dpkg --add-architecture i386 \ + && apt-get update -y \ + && apt-get install -y --no-install-recommends \ + gnupg \ + ca-certificates \ + curl \ + xauth \ + xvfb \ + iproute2 \ + && mkdir -pm755 /etc/apt/keyrings \ + && curl -fsSL -o /etc/apt/keyrings/winehq-archive.key ${WINE_PGP_URL} \ + && curl -fsSL -o /etc/apt/sources.list.d/winehq.sources ${WINE_SRC_URL} \ + && apt-get update -y \ + && apt-get install -y --no-install-recommends \ + winehq-${WINE_FLAVOUR}=${WINE_VERSION} \ + wine-${WINE_FLAVOUR}=${WINE_VERSION} \ + wine-${WINE_FLAVOUR}-amd64=${WINE_VERSION} \ + wine-${WINE_FLAVOUR}-i386=${WINE_VERSION} \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# The volume folders need specified ahead of time, otherwise they will be owned by root when created via VOLUME. +RUN groupadd --gid $GROUP_ID blockland && useradd --uid $USER_ID --gid $GROUP_ID --create-home --shell /bin/bash blockland \ + && mkdir /data /data/Add-Ons /data/config /data/saves /data/modules /data/base \ + && chown blockland:blockland -R /data + +USER blockland + +COPY --chmod=0755 --chown=blockland:blockland bin/ /usr/local/bin/ + +ENV BL_DEDI_LAN=0 \ + BL_DTOKEN="" \ + BL_SERVER_NAME="Blockland_Server" \ + BL_MAX_PLAYERS=32 \ + BL_GAMEMODE="Custom" \ + BL_PORT=28000 \ + BL_EXTRA_ARGS="" \ + BL_INST_NUM_PROC=10 \ + BL_INST_FORCE=0 \ + BL_INST_OVERWRITE=0 \ + BL_PATCH_ENABLE=1 \ + BL_PATCH_EXE_URL=https://gitlab.com/-/project/19166101/uploads/7e9bc075056c3301fd1247975ecaa218/Blockland.exe \ + BL_PATCH_LOADER_URL=https://gitlab.com/-/project/19166101/uploads/2970aa2d8c23259f8becb0f49630efcc/RedBlocklandLoader.dll \ + BL_PATCH_WINEFIX_URL=https://gitlab.com/-/project/46964875/uploads/91958483cf78ffc270a09824336bd91a/WineFix.dll \ + WINEARCH=win32 \ + WINEDEBUG=-all + +WORKDIR /data + +VOLUME /data/Add-Ons \ + /data/config \ + /data/saves \ + /data/modules \ + /data/base + +# Dedi LANs force the port to be 28050, +# so I'm exposing both for documentation +EXPOSE 28000/udp +EXPOSE 28050/udp + +# -g is necessary so detaching works properly +ENTRYPOINT ["/tini", "-g", "--", "/bin/bash", "-c", "run-bl"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..eb1aaac --- /dev/null +++ b/README.md @@ -0,0 +1,40 @@ +# Blockland Docker +Because I'm tired of installing older versions of Wine on my systems. + +### How to use +I've provided an example `docker-compose.yml` file. If you grab it, just run `docker compose up -d` from the same directory as it and it will grab the image and run it. Use `docker attach blockland` to attach to the console, and `Ctrl+P Ctrl+Q` to detach from it. + +If you don't like docker compose, you can do `docker run -dit --name blockland --net=host -e BL_DTOKEN="your dtoken" eagle517/blockland-docker` for a similar experience. + +### Environment variables +| Name | Type | Default | Description | +| -------------------- | ------------- | ----------------- | ----------- | +| BL_DEDI_LAN | bool (0 or 1) | 0 | Launches the server as a Dedicated or Dedicated LAN type. Note that DedicatedLANs are forced into using 28050 as their port. Blame Badspot, not me +| BL_DTOKEN | string | "" | Your [DToken](https://blockland.us/steam-dToken.php) for authentication +| BL_SERVER_NAME | string | Blockland_Server | The name shown on the server list. Underscores will be replaced with spaces by Blockland +| BL_MAX_PLAYERS | int | 32 | The max number of players that can join the server +| BL_GAMEMODE | string | Custom | The name of the gamemode to launch with +| BL_PORT | int | 28000 | The port to bind to, see the Network section below +| BL_EXTRA_ARGS | string | "" | Additional parameters to pass to the game as you see fit +| BL_INST_NUM_PROC | int | 10 | Number of parallel processes used to download the game files during installation +| BL_INST_FORCE | bool (0 or 1) | 0 | Forcefully install the game each time you launch +| BL_INST_OVERWRITE | bool (0 or 1) | 0 | Overwrite existing files during installation +| BL_PATCH_ENABLE | bool (0 or 1) | 1 | Patches the game with RedBlocklandLoader and the WineFix DLL to make the console work with Wine 8.0.2 (See Wine section below) +| BL_PATCH_EXE_URL | string | See Dockerfile | URL to retrieve the patched Blockland.exe from for RedBlocklandLoader +| BL_PATCH_LOADER_URL | string | See Dockerfile | URL to retrieve RedBlocklandLoader.dll from +| BL_PATCH_WINEFIX_URL | string | See Dockerfile | URL to retrieve WineFix.dll from +| WINEARCH | string | win32 | Specifies the arch type Wine should create the prefix under +| WINEDEBUG | string | -all | Controls how much logging Wine does to the console (default hides everything) + +### Networking +Blockland uses UDP for its underlying communication. UDP can be tricky to get to work properly with Docker's bridge networks because it involves internal forwarding on the host to handle the IP masquerading properly. Blockland's Join IP check also does not play nicely with this network type. I recommend using the `host` network, which will cause the container to have no network isolation, but it removes all the issues. Note that the `host` network type is only supported on Linux. + +If you know how to reliably get Blockland working with a bridged network, let me know. + +### Volumes +The Dockerfile creates multiple volumes for the game's directories. My reasoning for this is so you can share certain directories between servers (i.e. have all your servers use the same Add-Ons directories) and avoid having to duplicate files. + +I also setup the container to be rootless, which can cause a hiccup with file permissions. By default the container is built with a UID and GUID of 1000, so make sure you assign that UID and GUID as the owner for your mounted volumes. Chances are your host user has that UID/GUID, so it should be a non-issue in most cases (I think). + +### Wine +Wine seems to be having less and less compatibility with Blockland as time goes on. Back when Wine 5.18 came out, we lost the Curses backend, and it stopped being possible to interact with Blockland's console. I eventually figured out what the issue with Wine was, and created [Wine Fix](https://gitlab.com/Eagle517/wine-fix) which allowed console interaction to work with Wine up to 8.0.2. With Wine 9 and later, it appears the console is just completely broken now. I don't have the time to figure out what shenanigans the Wine devs got up to, so we're stuck with 8.0.2 for now. diff --git a/bin/install-bl b/bin/install-bl new file mode 100644 index 0000000..eaf4a25 --- /dev/null +++ b/bin/install-bl @@ -0,0 +1,17 @@ +#!/bin/bash + +set -e + +cd /data + +echo "Installing Blockland..." + +curl -fsSL -A "blocklandWIN/2.0" -o /tmp/latest-manifest.dat http://update.blockland.us/latestVersion.php +download_url=$(head -n 1 /tmp/latest-manifest.dat | cut -f 2) + +tail -n +2 /tmp/latest-manifest.dat | tr '\r\n\t' '\0' | xargs -0 -n 2 -P $BL_INST_NUM_PROC sh -c \ +'file="./$2"; if [ "$BL_INST_OVERWRITE" -eq 1 ]; then zflag="-z $'$file'"; else zflag=; fi; curl -fsSL -A "blocklandWIN/2.0" --create-dirs $zflag -o "$file" $1/$3' _ $download_url + +if [[ "$BL_PATCH_ENABLE" -eq 1 ]]; then + source patch-bl +fi diff --git a/bin/patch-bl b/bin/patch-bl new file mode 100644 index 0000000..55f0184 --- /dev/null +++ b/bin/patch-bl @@ -0,0 +1,10 @@ +#!/bin/bash + +set -e + +cd /data + +echo "Patching Blockland..." +curl -fsSLJ --clobber -o Blockland.exe $BL_PATCH_EXE_URL +curl -fsSLJ --clobber -o RedBlocklandLoader.dll $BL_PATCH_LOADER_URL +curl -fsSLJ --clobber --output-dir ./modules/ --create-dirs -o WineFix.dll $BL_PATCH_WINEFIX_URL diff --git a/bin/run-bl b/bin/run-bl new file mode 100644 index 0000000..0f7b21b --- /dev/null +++ b/bin/run-bl @@ -0,0 +1,60 @@ +#!/bin/bash + +set -e + +cd /data + +if [[ "$BL_INST_FORCE" -eq 1 ]] || [ ! -f "Blockland.exe" ]; then + source "install-bl" +fi + +if [ -z "$BL_PORT" ]; then + echo "Please provide a port by setting BL_PORT" + exit -1 +fi + +if [ -z "$BL_GAMEMODE" ]; then + echo "Please provide a gamemode by setting BL_GAMEMODE" + exit -1 +fi + +if [ -z "$BL_SERVER_NAME" ]; then + echo "Please provide a server name by setting BL_SERVER_NAME" + exit -1 +fi + +if [[ "$BL_MAX_PLAYERS" -lt 1 ]]; then + echo "BL_MAX_PLAYERS must be greater than 0" + exit -1 +fi + +if [[ "$BL_DEDI_LAN" -eq 0 ]]; then + if [ -z "$BL_DTOKEN" ]; then + echo "Please provide a dtoken by setting BL_DTOKEN" + exit -1 + fi + + dedi=dedicated +else + dedi=dedicatedLAN +fi + +unset DISPLAY + +# If the wine prefix doesn't exist, create it using wineboot +# rather than having it be created by launching Blockland, +# as Blockland will hang otherwise. +if [ ! -d "$HOME/.wine" ]; then + echo "Creating wine prefix..." + wineboot -i + + # Annoyingly, if Blockland is launched too quickly after wineboot, + # CreateWindowExA fails which means winsockWindow in winNet.cc@184 + # in TGE is set to NULL. This causes all networking in Blockland + # to not function correctly, as WinsockProc will not be called. + echo "Waiting for wine to fully init..." + sleep 3 +fi + +echo "Launching Blockland..." +xvfb-run -a wine "Blockland.exe" ptlaaxobimwroe -${dedi} -port $BL_PORT -dtoken $BL_DTOKEN -gamemode $BL_GAMEMODE -serverName $BL_SERVER_NAME -maxPlayers $BL_MAX_PLAYERS $BL_EXTRA_ARGS diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3815166 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,20 @@ +services: + blockland: + container_name: blockland + image: eagle517/blockland-server + stdin_open: true + tty: true + restart: unless-stopped + network_mode: host + environment: + BL_DTOKEN: "" # Get your dtoken from https://blockland.us/steam-dToken.php + BL_SERVER_NAME: "Blockland_Server" # Blockland will replace underscores with spaces + BL_MAX_PLAYERS: 32 + BL_GAMEMODE: "Custom" + BL_PORT: 28000 + volumes: + - ./blockland/Add-Ons:/data/Add-Ons + - ./blockland/config:/data/config + - ./blockland/saves:/data/saves + - ./blockland/modules:/data/modules + - ./blockland/base:/data/base