The dedicated server (app 380870) and the client are packaged separately and have drifted. Base.Log_Stack_01 was removed from the client in 42.16, but the server package still ships entity_logstack.txt. The server registers every script it can see into a new world's WorldDictionary, so the entry lands in the save, and every client then fails at world load with: WorldDictionaryException: [SpriteConfigs] Missing dictionary script on client: Base.Log_Stack_01 Nothing in multiplayer can legitimately reference a script that no client has, so dropping it server-side costs nothing. The strip runs after the SteamCMD update rather than once at install time on purpose: validate restores the file on every boot, so it has to be removed on every boot too. Note this does not repair a world whose dictionary already records the entry -- that save still needs regenerating. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
130 lines
4.9 KiB
Django/Jinja
130 lines
4.9 KiB
Django/Jinja
#!/bin/bash
|
|
# Project Zomboid Build 42 Server Entrypoint
|
|
# Based on IndifferentBroccoli/projectzomboid-server-docker
|
|
set -e
|
|
|
|
# Configuration
|
|
INSTALL_DIR="/project-zomboid"
|
|
CONFIG_DIR="/project-zomboid-config"
|
|
STEAMCMD="/home/steam/steamcmd/steamcmd.sh"
|
|
SERVER_NAME="${SERVER_NAME:-zomboid}"
|
|
PUID="${PUID:-1000}"
|
|
PGID="${PGID:-1000}"
|
|
MIN_RAM="${MIN_RAM:-{{ zomboid_min_ram }}}"
|
|
MAX_RAM="${MAX_RAM:-{{ zomboid_max_ram }}}"
|
|
|
|
echo "=== Project Zomboid Build 42 Server ({{ zomboid_preset_version }}) ==="
|
|
echo "Server Name: ${SERVER_NAME}"
|
|
echo "RAM: ${MIN_RAM} - ${MAX_RAM}"
|
|
|
|
# Set user permissions (IndifferentBroccoli approach)
|
|
echo "=== Setting file permissions ==="
|
|
usermod -o -u "${PUID}" steam
|
|
groupmod -o -g "${PGID}" steam
|
|
for dir in "${INSTALL_DIR}" "${CONFIG_DIR}"; do
|
|
# Recursing is a full inode walk over the install tree -- with 256 workshop
|
|
# mods that is real SSD churn on every restart, and a no-op after the first.
|
|
if [ "$(stat -c %u "${dir}")" = "${PUID}" ]; then
|
|
echo "=== ${dir} already owned by ${PUID}, skipping recursive chown ==="
|
|
else
|
|
chown -R steam:steam "${dir}"
|
|
fi
|
|
done
|
|
# Only chown writable parts of /home/steam (not read-only mounts)
|
|
chown steam:steam /home/steam
|
|
chown -R steam:steam /home/steam/steamcmd 2>/dev/null || true
|
|
chown -R steam:steam /home/steam/Steam 2>/dev/null || true
|
|
|
|
# Create required directories
|
|
mkdir -p "${CONFIG_DIR}/Server"
|
|
mkdir -p "${CONFIG_DIR}/Saves"
|
|
mkdir -p "${CONFIG_DIR}/db"
|
|
|
|
# Update/Install PZ dedicated server from the default (stable) branch
|
|
if [ "${AUTO_UPDATE:-true}" = "true" ]; then
|
|
echo "=== Updating Project Zomboid Server (Build 42 stable) ==="
|
|
su -c "${STEAMCMD} +runscript /home/steam/install.scmd" steam
|
|
echo "=== Update complete ==="
|
|
fi
|
|
|
|
# Strip scripts the dedicated-server package ships but the client no longer has.
|
|
#
|
|
# The two Steam apps are packaged separately and have drifted. Base.Log_Stack_01
|
|
# was removed from the client in 42.16, but app 380870 still ships
|
|
# entity_logstack.txt. The server registers every script it can see into a new
|
|
# world's WorldDictionary, so the entry lands in the save, and then every client
|
|
# fails at world load with:
|
|
#
|
|
# WorldDictionaryException: [SpriteConfigs] Missing dictionary script on
|
|
# client: Base.Log_Stack_01
|
|
#
|
|
# Nothing in multiplayer can legitimately use a script no client has, so
|
|
# removing it server-side costs nothing. This runs after the SteamCMD update on
|
|
# purpose: validate restores the file on every boot, so it has to be stripped
|
|
# each time, not once.
|
|
#
|
|
# Removing the file does not fix a world whose dictionary already records the
|
|
# entry -- that save needs regenerating.
|
|
strip_client_missing_scripts() {
|
|
local stale="${INSTALL_DIR}/media/scripts/generated/entities/misc/entity_logstack.txt"
|
|
if [ -f "${stale}" ]; then
|
|
echo "=== Removing ${stale##*/} (shipped by server, absent from client) ==="
|
|
rm -f "${stale}"
|
|
fi
|
|
}
|
|
strip_client_missing_scripts
|
|
|
|
# Configure JVM memory settings in ProjectZomboid64.json (Build 42 uses JSON config)
|
|
configure_memory() {
|
|
local json_file="${INSTALL_DIR}/ProjectZomboid64.json"
|
|
|
|
if [ ! -f "$json_file" ]; then
|
|
echo "=== ProjectZomboid64.json not found, skipping memory config ==="
|
|
return 0
|
|
fi
|
|
|
|
echo "=== Configuring JVM memory: Xms=${MIN_RAM}, Xmx=${MAX_RAM} ==="
|
|
|
|
# Update Xmx
|
|
sed -i "s/-Xmx[0-9]*[gGmM]*/-Xmx${MAX_RAM}/g" "$json_file"
|
|
|
|
# Update or add Xms
|
|
if grep -q "\-Xms" "$json_file"; then
|
|
sed -i "s/-Xms[0-9]*[gGmM]*/-Xms${MIN_RAM}/g" "$json_file"
|
|
else
|
|
# Insert -Xms before -Xmx
|
|
sed -i "s/\"-Xmx/\"-Xms${MIN_RAM}\",\n\t\t\"-Xmx/g" "$json_file"
|
|
fi
|
|
|
|
echo "=== Memory configuration complete ==="
|
|
}
|
|
configure_memory
|
|
|
|
# Build server arguments
|
|
# Note: -modfolders is NOT used - mods are configured via INI only
|
|
# Reference: IndifferentBroccoli/projectzomboid-server-docker
|
|
SERVER_ARGS="-cachedir=${CONFIG_DIR} -servername ${SERVER_NAME}"
|
|
|
|
# Always pass the admin password when we have one.
|
|
#
|
|
# This used to be gated on the admin DB not existing yet, on the assumption that
|
|
# the file's presence meant the admin user was already set up. It does not: PZ
|
|
# creates the DB file in ServerWorldDatabase.create() *before* it creates the
|
|
# admin user, so any boot interrupted between those two steps leaves a database
|
|
# that exists but has no admin. From then on the guard withheld the flag, the
|
|
# server fell back to an interactive "Enter new administrator password:" prompt,
|
|
# read EOF because a detached container has no stdin, and died with
|
|
# NoSuchElementException -- on every restart, forever.
|
|
if [ -n "${ADMIN_PASSWORD}" ]; then
|
|
SERVER_ARGS="${SERVER_ARGS} -adminpassword ${ADMIN_PASSWORD}"
|
|
fi
|
|
|
|
# Note: Server password is set via INI file, not command line args
|
|
|
|
# Start server
|
|
cd "${INSTALL_DIR}"
|
|
echo "=== Starting Project Zomboid Server ==="
|
|
echo "Connect to: home.debyl.io:16261"
|
|
|
|
exec su -c "export LD_LIBRARY_PATH=${INSTALL_DIR}/jre64/lib:\${LD_LIBRARY_PATH} && ./start-server.sh ${SERVER_ARGS}" steam
|