diff --git a/.env.example b/.env.example index 7bcc165af..cdf496b1c 100644 --- a/.env.example +++ b/.env.example @@ -38,6 +38,7 @@ PLAYER_LOGGING_POLL_PERIOD=5 LOG_FILTER_ENABLED=true LOG_LEVEL=INFO LOG_FORMAT_TYPE=default +UE4SS_ENABLED=false DIFFICULTY=None RANDOMIZER_TYPE= diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index d30171298..93a7d2c85 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -84,7 +84,9 @@ jobs: -p 27015:27015/udp \ -p 25575:25575/tcp \ -v ./palworld:/palworld/ \ + -v ./tests/fixtures/ue4ss-mods:/palworld/Pal/Binaries/Linux/Mods \ --env-file .env.example \ + -e UE4SS_ENABLED=true \ --restart unless-stopped \ --stop-timeout 30 \ ${{ github.run_id }} @@ -128,6 +130,16 @@ jobs: done ' + - name: Test UE4SS Lua mod loading + run: | + docker exec palworld-server bash -c ' + pal_pid="$(pidof PalServer-Linux-Shipping)" + pal_pid="${pal_pid%% *}" + grep -Fq "/palworld/Pal/Binaries/Linux/libUE4SS.so" "/proc/${pal_pid}/maps" + ' + docker logs palworld-server 2>&1 | grep -Fq "UE4SS enabled; loading mods from /palworld/Pal/Binaries/Linux/Mods." + docker logs palworld-server 2>&1 | grep -Fq "[UE4SSStatus] Lua test mod loaded" + # - name: Test if rcon.yaml is valid # run: | # printf "\e[0;32m%s\e[0m\n" "*****RCON.YAML*****" diff --git a/Dockerfile b/Dockerfile index 62338168c..a7763195f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,6 +44,8 @@ ARG SUPERCRONIC_SHA1SUM_AMD64="5bcefed628e32adc08e32634db2d10e9230dbca0" ARG SUPERCRONIC_VERSION="0.2.46" ARG DEPOT_DOWNLOADER_VERSION="3.4.0" ARG KNOCK_VERSION="0.8.1" +ARG UE4SS_VERSION="3.0.2" +ARG UE4SS_TGZ_SHA256="bbc85d0d0288afa5475f9eab871f28066b758f24e9a9e45472764cb3abc1df02" # update and install dependencies # hadolint ignore=DL3008 @@ -95,6 +97,14 @@ RUN case "${TARGETARCH}" in \ && chmod +x DepotDownloader \ && mv DepotDownloader /usr/local/bin/DepotDownloader +RUN if [ "${TARGETARCH}" = "amd64" ]; then \ + wget --progress=dot:giga "https://github.com/XarminaEu/ue4ss-linux/releases/download/v${UE4SS_VERSION}/ue4ss-linux-v${UE4SS_VERSION}.tar.gz" -O ue4ss.tar.gz \ + && echo "${UE4SS_TGZ_SHA256} ue4ss.tar.gz" | sha256sum -c - \ + && mkdir -p /opt/ue4ss \ + && tar -xzf ue4ss.tar.gz -C /opt/ue4ss \ + && rm ue4ss.tar.gz; \ + fi + # install patched knockd (as same as https://github.com/itzg/docker-minecraft-server/blob/master/build/ubuntu/install-packages.sh) RUN wget --progress=dot:giga https://github.com/Metalcape/knock/releases/download/0.8.1/knock-${KNOCK_VERSION}-${TARGETARCH}.tar.gz -O /tmp/knock.tar.gz && \ tar -xf /tmp/knock.tar.gz -C /usr/local/ && rm /tmp/knock.tar.gz && \ @@ -188,7 +198,8 @@ ENV HOME=/home/steam \ INSTALL_BETA_INSIDER=false \ LOG_FILTER_ENABLED=true \ LOG_LEVEL=INFO \ - LOG_FORMAT_TYPE=default + LOG_FORMAT_TYPE=default \ + UE4SS_ENABLED=false # Sane Box64 config defaults # hadolint ignore=DL3044 diff --git a/README.md b/README.md index 5b4283fb3..fab474451 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,8 @@ services: CROSSPLAY_PLATFORMS: "(Steam,Xbox,PS5,Mac)" volumes: - ./palworld:/palworld/ + - ./mods:/palworld/Pal/Binaries/Linux/Mods + - ./paks:/palworld/Pal/Content/Paks/~mods ``` As an alternative, you can copy the [.env.example](.env.example) file to a new file called **.env** file. @@ -120,6 +122,8 @@ services: - .env volumes: - ./palworld:/palworld/ + - ./mods:/palworld/Pal/Binaries/Linux/Mods + - ./paks:/palworld/Pal/Content/Paks/~mods ``` ### Docker Run @@ -132,6 +136,8 @@ docker run -d \ -p 8211:8211/udp \ -p 27015:27015/udp \ -v ./palworld:/palworld/ \ + -v ./mods:/palworld/Pal/Binaries/Linux/Mods \ + -v ./paks:/palworld/Pal/Content/Paks/~mods \ -e PUID=1000 \ -e PGID=1000 \ -e PORT=8211 \ @@ -160,6 +166,8 @@ docker run -d \ -p 8211:8211/udp \ -p 27015:27015/udp \ -v ./palworld:/palworld/ \ + -v ./mods:/palworld/Pal/Binaries/Linux/Mods \ + -v ./paks:/palworld/Pal/Content/Paks/~mods \ --env-file .env \ --restart unless-stopped \ --stop-timeout 30 \ @@ -220,6 +228,7 @@ It is highly recommended you set the following environment values before startin | ENABLE_PERF_THREADING_ARGS | Enables performance-related threading startup arguments (`-useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS`). | false | true/false | 2.1.0 | | WORKER_THREADS_SERVER | Sets `-NumberOfWorkerThreadsServer`. Leave empty to use the game's default. When using deprecated MULTITHREADING=true, this defaults to all CPUs. | | Positive integer | 2.1.0 | | PALWORLD_ALLOW_NEGATIVE_DELTA_TIME | Enables Palworld's built-in recovery for negative DeltaTime through an Engine ini override. This opt-in mitigation does not correct or synchronize the host or VM clock. | false | true/false | 2.7.0 | +| UE4SS_ENABLED | Enables the bundled x86-64 UE4SS Linux loader and preloads it when Palworld starts. ARM64 requires a patched Box64 (in progress). | false | true/false | 2.7.0 | | COMMUNITY | Whether or not the server shows up in the community server browser (USE WITH SERVER_PASSWORD) | false | true/false | 0.1.0 | | PUBLIC_IP | You can manually specify the global IP address of the network on which the server running. If not specified, it will be detected automatically. If it does not work well, try manual configuration. | | x.x.x.x | 0.1.0 | | PUBLIC_PORT | You can manually specify the port number of the network on which the server running. If not specified, it will be detected automatically. If it does not work well, try manual configuration. | | 1024-65535 | 0.1.0 | diff --git a/compose.yaml b/compose.yaml index dbeace160..5ecfed8e9 100644 --- a/compose.yaml +++ b/compose.yaml @@ -24,5 +24,8 @@ services: SERVER_DESCRIPTION: "palworld-server-docker by Thijs van Loef" CROSSPLAY_PLATFORMS: "(Steam,Xbox,PS5,Mac)" LOG_LEVEL: "INFO" # DEBUG/INFO/WARN/ERROR. Please be aware that DEBUG will log all command arguments, including secrets, to the logs. Share with caution. + UE4SS_ENABLED: false volumes: - ./palworld:/palworld/ + - ./mods:/palworld/Pal/Binaries/Linux/Mods + - ./paks:/palworld/Pal/Content/Paks/~mods diff --git a/docusaurus/docs/advanced/ue4ss.md b/docusaurus/docs/advanced/ue4ss.md new file mode 100644 index 000000000..195db734c --- /dev/null +++ b/docusaurus/docs/advanced/ue4ss.md @@ -0,0 +1,116 @@ +--- +sidebar_position: 2 +--- + +# Modding + +This image supports two types of Palworld mods: **resource `.pak` mods** and **UE4SS Lua/LogicMod mods**. + +## Resource `.pak` mods + +Resource `.pak` mods replace or add cooked assets (textures, models, audio, data tables). +They load via Palworld's native pak system and **do not require UE4SS**. + +Mount your `.pak` files at `/palworld/Pal/Content/Paks/~mods`: + +```yaml +volumes: + - ./paks:/palworld/Pal/Content/Paks/~mods +``` + +Drop `.pak` files into the `./paks` directory. If the mod ships `.ucas` and `.utoc` +companion files alongside the `.pak`, keep all three together — splitting them breaks +the package. + +:::tip +Resource `.pak` mods are the simplest to install. No loader or framework required. +::: + +### Known resource `.pak` mods + +| Mod | Description | +|-----|-------------| +| [MapUnlocker](https://www.nexusmods.com/palworld/mods/16) | Unlocks the full map (~592k downloads) | +| [2x-5x-10x-100x Palsphere & Ammo Crafting](https://www.nexusmods.com/palworld/mods/3132) | Multiplies craft output — pick one variant only | +| [Enhanced Palworld Visuals](https://www.nexusmods.com/palworld/mods/) | Disables/enables post-processing effects | + +## UE4SS mods + +This image bundles the x86-64 Linux build of [UE4SS](https://github.com/XarminaEu/ue4ss-linux). +Enable it with `UE4SS_ENABLED=true` on an amd64 host. ARM64 support requires a patched Box64 build which is currently in progress. + +Mount your mods at `/palworld/Pal/Binaries/Linux/Mods`. The included Compose example uses `./mods`: + +```yaml +environment: + UE4SS_ENABLED: true +volumes: + - ./palworld:/palworld/ + - ./mods:/palworld/Pal/Binaries/Linux/Mods +``` + +UE4SS reads `mods.txt` and each Lua mod must be placed at +`Mods//scripts/main.lua`; directory names are case-sensitive. A minimal mod is: + +```text +mods/ +├── mods.txt +└── MyMod/ + └── scripts/ + └── main.lua +``` + +```text +MyMod : 1 +``` + +At startup, the container logs that UE4SS is enabled and the loader writes its `[UE4SS]` messages to the server log. + +### LogicMods + +LogicMods are Blueprint-based mods packaged as `.pak` files. They **require UE4SS** with +LogicMod support. Place them at: + +``` +Pal/Content/Paks/LogicMods/YourMod.pak +``` + +:::tip +A file ending in `.pak` is not always a resource mod. Check the mod author's description — +if it says "LogicMod", it needs UE4SS. +::: + +### PalSchema mods + +Some mods use [PalSchema](https://www.nexusmods.com/palworld/mods/) for data-driven +changes (stats, recipes, passive skills). These require UE4SS + PalSchema and install to: + +``` +Pal/Binaries/Linux/Mods/PalSchema/Mods// +``` + +### Known UE4SS mods + +| Mod | Type | Description | +|-----|------|-------------| +| [Mounted Overhaul](https://www.nexusmods.com/palworld/mods/2317) | PalSchema + Pak | Reworks mount stats, adds new mounts | +| [Complete Game Rebalance](https://www.nexusmods.com/palworld/mods/2166) | PalSchema | Full gameplay overhaul | +| [New Skill Fruits](https://www.nexusmods.com/palworld/mods/2309) | PalSchema | Plantable skill fruits from vendors | +| [RakLogistics](https://www.nexusmods.com/palworld/mods/1225) | LogicMod | Logistics optimization, FPS boost | +| [BasicMiniMap](https://www.nexusmods.com/palworld/mods/336) | LogicMod | Configurable mini-map overlay | + +::::warning +Only Lua mods and Linux-native C++ `.so` mods are supported. Windows `.dll` mods cannot load. +:::: + +## General modding notes + +- **Always restart** the server after adding, removing, or updating mods. Palworld only scans at startup. +- **Client sync:** Most `.pak` mods must be installed on **both server and every client**. + Mismatched mods cause invisible objects, missing textures, or connection failures. +- **Don't stack conflicting mods** — two resource `.pak` files replacing the same asset + will silently conflict. One wins, or both fail. +- **`-NoMods`** launch flag disables all mods without removing files — useful for debugging. +- **Palworld 1.0** broke most mod loaders. Use the + [Palworld-specific RE-UE4SS build](https://github.com/Okaetsu/re-ue4ss/releases) + (Okaetsu fork), not the generic UE4SS release. diff --git a/docusaurus/docs/getting-started/configuration/server-settings.md b/docusaurus/docs/getting-started/configuration/server-settings.md index b2ed9d121..a2178364b 100644 --- a/docusaurus/docs/getting-started/configuration/server-settings.md +++ b/docusaurus/docs/getting-started/configuration/server-settings.md @@ -32,6 +32,7 @@ It is highly recommended you set the following environment values before startin | ENABLE_PERF_THREADING_ARGS | Enables performance-related threading startup arguments (`-useperfthreads -NoAsyncLoadingThread -UseMultithreadForDS`). | false | true/false | 2.1.0 | | WORKER_THREADS_SERVER | Sets `-NumberOfWorkerThreadsServer`. Leave empty to use the game's default. When using deprecated MULTITHREADING=true, this defaults to all CPUs. | | Positive integer | 2.1.0 | | PALWORLD_ALLOW_NEGATIVE_DELTA_TIME | Enables Palworld's built-in recovery for negative DeltaTime through an Engine ini override. This opt-in mitigation does not correct or synchronize the host or VM clock. | false | true/false | 2.7.0 | +| UE4SS_ENABLED | Enables the bundled x86-64 UE4SS Linux loader. ARM64 requires a patched Box64 (in progress). See [UE4SS Linux mods](/advanced/ue4ss). | false | true/false | 2.7.0 | | COMMUNITY | Whether or not the server shows up in the community server browser (USE WITH SERVER_PASSWORD) | false | true/false | 0.1.0 | | PUBLIC_IP | You can manually specify the global IP address of the network on which the server running. If not specified, it will be detected automatically. If it does not work well, try manual configuration. | | x.x.x.x | 0.1.0 | | PUBLIC_PORT | You can manually specify the port number of the network on which the server running. If not specified, it will be detected automatically. If it does not work well, try manual configuration. | | 1024-65535 | 0.1.0 | diff --git a/kubernetes/configmap.yaml b/kubernetes/configmap.yaml index 347d53973..34f6e6ebf 100644 --- a/kubernetes/configmap.yaml +++ b/kubernetes/configmap.yaml @@ -11,6 +11,7 @@ data: REST_API_PORT: "8212" PUID: "1000" PGID: "1000" + UE4SS_ENABLED: "false" MULTITHREADING: "false" COMMUNITY: "false" diff --git a/kubernetes/pvc.yaml b/kubernetes/pvc.yaml index baaa623f3..b7f01bd64 100644 --- a/kubernetes/pvc.yaml +++ b/kubernetes/pvc.yaml @@ -11,3 +11,29 @@ spec: resources: requests: storage: 12Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app: palworld-server + name: palworld-server-mods +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + app: palworld-server + name: palworld-server-paks +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi diff --git a/kubernetes/readme.md b/kubernetes/readme.md index 3466e9b37..0daaa3ffe 100644 --- a/kubernetes/readme.md +++ b/kubernetes/readme.md @@ -2,6 +2,10 @@ Please make sure to configure the configmap.yaml and secret.yaml files to your needs before applying the configuration. +The default manifests create separate persistent volumes for Palworld data, UE4SS mods, and `.pak` mods. +To use UE4SS, set `UE4SS_ENABLED: "true"` in `configmap.yaml` on an amd64 node, then add `mods.txt` and mod folders to the mods PVC. +Drop `.pak` files into the paks PVC for resource mods that don't need UE4SS. + [Read more about the configuration options here.](https://palworld-server-docker.loef.dev/getting-started/configuration/server-settings) Files: diff --git a/kubernetes/statefulset.yaml b/kubernetes/statefulset.yaml index bb26fc754..3530edc33 100644 --- a/kubernetes/statefulset.yaml +++ b/kubernetes/statefulset.yaml @@ -49,6 +49,10 @@ spec: volumeMounts: - name: datadir mountPath: /palworld + - name: mods + mountPath: /palworld/Pal/Binaries/Linux/Mods + - name: paks + mountPath: /palworld/Pal/Content/Paks/~mods startupProbe: exec: command: ["sh", "-c", "pgrep PalServer-Linux >/dev/null"] @@ -66,3 +70,9 @@ spec: - name: datadir persistentVolumeClaim: claimName: palworld-server-datadir + - name: mods + persistentVolumeClaim: + claimName: palworld-server-mods + - name: paks + persistentVolumeClaim: + claimName: palworld-server-paks diff --git a/scripts/start.sh b/scripts/start.sh index 03c751a6c..8fa1160f5 100644 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -54,6 +54,15 @@ if [ "$architecture" == "arm64" ]; then sed -i "s|\(\"\$UE_PROJECT_ROOT\/Pal\/Binaries\/Linux\/PalServer-Linux-Shipping\" Pal \"\$@\"\)|LD_LIBRARY_PATH=/home/steam/steamcmd/linux64:\$LD_LIBRARY_PATH /usr/local/bin/box64 \1|" ./PalServer-arm64.sh chmod +x ./PalServer-arm64.sh STARTCOMMAND=("./PalServer-arm64.sh") + + if [ "${UE4SS_ENABLED,,}" = true ]; then + LogWarn "UE4SS mod loader is disabled on arm64; the bundled loader is x86-64 only. Continuing to boot." + fi +elif [ "${UE4SS_ENABLED,,}" = true ]; then + ue4ss_library="/palworld/Pal/Binaries/Linux/libUE4SS.so" + install -m 755 /opt/ue4ss/libUE4SS.so "${ue4ss_library}" || exit + export LD_PRELOAD="${ue4ss_library}${LD_PRELOAD:+:${LD_PRELOAD}}" + LogInfo "UE4SS enabled; loading mods from /palworld/Pal/Binaries/Linux/Mods." fi isReadable "${STARTCOMMAND[0]}" || exit diff --git a/tests/fixtures/ue4ss-mods/UE4SSStatus/scripts/main.lua b/tests/fixtures/ue4ss-mods/UE4SSStatus/scripts/main.lua new file mode 100644 index 000000000..03d416236 --- /dev/null +++ b/tests/fixtures/ue4ss-mods/UE4SSStatus/scripts/main.lua @@ -0,0 +1 @@ +print("[UE4SSStatus] Lua test mod loaded") diff --git a/tests/fixtures/ue4ss-mods/mods.txt b/tests/fixtures/ue4ss-mods/mods.txt new file mode 100644 index 000000000..f5bf48f23 --- /dev/null +++ b/tests/fixtures/ue4ss-mods/mods.txt @@ -0,0 +1 @@ +UE4SSStatus : 1