better defaults + update readme
This commit is contained in:
148
README.md
148
README.md
@@ -1,70 +1,98 @@
|
||||
# Zomboid client-hosted → dedicated server
|
||||
# AI Disclosure
|
||||
|
||||
Convert a locally **hosted** Project Zomboid multiplayer world into a **dedicated** server layout, then run it with Docker.
|
||||
yeah, 100%. I read the code, should be fine.
|
||||
|
||||
Zomboid savefiles are a mess IMHO, this was the quickest way to get to the goal.
|
||||
|
||||
If you don't like it, don't use it, idk.
|
||||
|
||||
----
|
||||
|
||||
# Zomboid Converter
|
||||
## client-hosted → dedicated server
|
||||
|
||||
Rust CLI that converts a locally **hosted** Project Zomboid multiplayer world into a **dedicated** server layout.
|
||||
|
||||
The world save format is the same (B42 `Saves/Multiplayer/…`). Conversion is packaging + naming + `players.db` world rename + mod recovery — not a binary rewrite.
|
||||
|
||||
## Layout
|
||||
This repository is **only** the converter. Sibling folders next to a checkout (e.g. `original/`, `server/`) are optional local testing aids and are not part of the git tree.
|
||||
|
||||
Paths below are relative to the **repo root** (parent of this `converter/` folder):
|
||||
## Build
|
||||
|
||||
| Path | Role |
|
||||
|------|------|
|
||||
| `original/` | Source saves / zips (**do not edit the zips**) |
|
||||
| `converter/` | This crate — Rust CLI (`zomboid-converter`) |
|
||||
| `server/` | Docker dedicated server (`docker-compose.yml`, `.env`) |
|
||||
| `server/server-data/` | Zomboid userdir (Saves, Server, db, Logs) |
|
||||
| `server/server-files/` | Game install (Steam download target) |
|
||||
```bash
|
||||
cargo build --release
|
||||
# binary: target/release/zomboid-converter
|
||||
```
|
||||
|
||||
Copy the binary wherever you run the dedicated server (example below: `~/docker/zomboid/bin/`).
|
||||
|
||||
## Inputs / outputs
|
||||
|
||||
Typical source pair from a host:
|
||||
|
||||
- `Saves/Multiplayer/<WorldName>/` — authoritative world (**use this**)
|
||||
- `Saves/Multiplayer/<WorldName>_player/` — client cache (**ignore**)
|
||||
|
||||
Server settings live separately under `Zomboid/Server/<WorldName>.*` on the host machine. They are **not** inside the world folder.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Rust toolchain (for the converter)
|
||||
- Docker + Docker Compose
|
||||
- Optional: local Steam workshop cache for app `108600` (to resolve `WorkshopItems`)
|
||||
|
||||
## Converter
|
||||
|
||||
```bash
|
||||
cd converter
|
||||
cargo build --release
|
||||
|
||||
cargo run --release -- \
|
||||
--input ../original/serverb42stable \
|
||||
--output ../server/server-data \
|
||||
--server-name pzserver \
|
||||
--workshop-dir /path/to/steamapps/workshop/content/108600 \
|
||||
--force
|
||||
```
|
||||
Server settings live separately under `Zomboid/Server/<WorldName>.*` on the host. They are **not** inside the world folder. Pass the directory that contains those files with `--server-config`.
|
||||
|
||||
`--input` may be a world **directory** or a **`.zip`** (opened read-only; extracted to a temp dir). Paths ending in `_player` are rejected.
|
||||
|
||||
### Arguments
|
||||
`--output` is the dedicated **server-data** root (writes `Saves/Multiplayer/<server-name>/` and patches `Server/<server-name>.ini`).
|
||||
|
||||
## Example (Hetzner / Docker layout)
|
||||
|
||||
Assumes:
|
||||
|
||||
| Path | Role |
|
||||
|------|------|
|
||||
| `~/docker/zomboid/` | Dedicated server (`docker-compose.yml`, `.env`) |
|
||||
| `~/docker/zomboid/server-data/` | Zomboid userdir (Saves, Server, db, …) |
|
||||
| `~/docker/zomboid/server-files/` | Game install (Steam download target) |
|
||||
| `~/docker/zomboid/bin/zomboid-converter` | This binary |
|
||||
| `~/docker/copyparty/data/zomboid/…` | Uploaded host world + configs |
|
||||
|
||||
```bash
|
||||
# stop the server first if it is running
|
||||
cd ~/docker/zomboid
|
||||
docker compose stop
|
||||
|
||||
./bin/zomboid-converter \
|
||||
--input ~/docker/copyparty/data/zomboid/alt/serverb42stable \
|
||||
--output ~/docker/zomboid/server-data \
|
||||
--server-name pzserver \
|
||||
--server-config ~/docker/copyparty/data/zomboid/alt \
|
||||
--force
|
||||
|
||||
docker compose up -d
|
||||
docker compose logs -f
|
||||
```
|
||||
|
||||
Or edit and run `~/docker/zomboid/convert-and-start.sh` (config block at the top).
|
||||
|
||||
`--server-name` (default `pzserver`) must match `SERVER_NAME` in the server `.env`. It is only a basename for the dedicated world and `Server/*.ini` files.
|
||||
|
||||
`--workshop-dir` defaults to `<output>/../server-files/steamapps/workshop/content/108600` when that directory exists (fills `WorkshopItems=`). Until Steam has downloaded mods once, re-run after the first install if needed.
|
||||
|
||||
## Arguments
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-i`, `--input` | Hosted world dir or zip |
|
||||
| `-o`, `--output` | Dedicated `server-data` root |
|
||||
| `-n`, `--server-name` | World + config basename (default: `pzserver`) |
|
||||
| `--workshop-dir` | `…/workshop/content/108600` — fills `WorkshopItems=` |
|
||||
| `--server-config` | Optional host `Server/` dir to copy/rename configs |
|
||||
| `--server-config` | Dir with host `<WorldName>.ini`, `_SandboxVars.lua`, spawn files |
|
||||
| `--workshop-dir` | `…/workshop/content/108600` — fills `WorkshopItems=` (auto if present next to `server-data`) |
|
||||
| `--password` | Server join password (`Password=` in ini); overrides `.env` |
|
||||
| `--env-file` | `.env` for password (default: `<output>/../.env`) |
|
||||
| `--force` | Replace existing `Saves/Multiplayer/<server-name>/` |
|
||||
|
||||
### What it does
|
||||
## What it does
|
||||
|
||||
1. Copies the world into `output/Saves/Multiplayer/<server-name>/`
|
||||
2. Skips syncthing conflict sidecars (`*-ZwS1g3qi*`), `*.db-journal`, and player-cache junk
|
||||
3. Sets `networkPlayers.world` in `players.db` to `<server-name>`
|
||||
4. Recovers mod IDs from `WorldDictionaryReadable.lua` into `Server/<name>.ini` (`Mods=`)
|
||||
5. If `--workshop-dir` is set, resolves Steam workshop IDs (`WorkshopItems=`)
|
||||
5. Resolves Steam workshop IDs into `WorkshopItems=` when a workshop dir is available
|
||||
6. Optionally sets `Password=` from `--password` or `SERVER_PASSWORD` / `PASSWORD` in `.env`
|
||||
|
||||
It does **not** overwrite `db/<server-name>.db` (accounts / whitelist stay managed by the server).
|
||||
@@ -73,51 +101,41 @@ It does **not** overwrite `db/<server-name>.db` (accounts / whitelist stay manag
|
||||
|
||||
Characters bind to the **account username** in `players.db` (`networkPlayers.username`), not Steam display name. Players must log in with that exact username (or you rename the column before they join).
|
||||
|
||||
## Dedicated server (Docker)
|
||||
## Dedicated server notes
|
||||
|
||||
```bash
|
||||
cd ../server
|
||||
cp .env.example .env # if needed; set passwords / SERVER_NAME
|
||||
docker compose up -d
|
||||
docker compose logs -f
|
||||
```
|
||||
Use any Project Zomboid dedicated image/layout you like. With Docker next to `server-data`:
|
||||
|
||||
Important `.env` keys:
|
||||
|
||||
- `SERVER_NAME` — must match converter `--server-name` (default `pzserver`)
|
||||
- `ADMIN_USERNAME` / `ADMIN_PASSWORD` — admin account
|
||||
- `RCON_PASSWORD` — RCON
|
||||
- `SERVER_PASSWORD` — optional join password for the converter (`Password=` in ini)
|
||||
|
||||
Ports: `16261/udp`, `16262/udp`, `27015/tcp`.
|
||||
|
||||
Stop the container before re-running the converter with `--force`.
|
||||
- `SERVER_NAME` must match converter `--server-name`
|
||||
- Optional: `SERVER_PASSWORD` in `.env` for the converter’s `Password=` patch
|
||||
- Also typical: `ADMIN_USERNAME` / `ADMIN_PASSWORD`, `RCON_PASSWORD`, memory, ports
|
||||
- Ports: `16261/udp`, `16262/udp`, `27015/tcp` (RCON)
|
||||
- Stop the container before re-running the converter with `--force`
|
||||
- After first start, wait until workshop items finish installing (`Workshop: … Installed` in logs)
|
||||
|
||||
## Recommended migration flow
|
||||
|
||||
1. Stop the dedicated server.
|
||||
2. Copy the host world into `original/` (keep zips untouched as backups).
|
||||
3. Ideally also copy the host’s `Zomboid/Server/<WorldName>.ini` (+ `_SandboxVars.lua`, spawn files) and pass `--server-config`.
|
||||
4. Run the converter with `--workshop-dir` and `--force`.
|
||||
5. Start Docker; wait until workshop items finish installing (`Workshop: … Installed` in logs).
|
||||
6. Join with the **same username** as in the hosted `players.db`.
|
||||
2. Upload/copy the host world (not the `_player` folder) and ideally the host `Server/<WorldName>.*` configs.
|
||||
3. Run the converter with `--server-config` pointing at the config directory.
|
||||
4. Start the dedicated server; wait for workshop installs if needed.
|
||||
5. Join with the **same username** as in the hosted `players.db`.
|
||||
|
||||
## Known gaps / caveats
|
||||
|
||||
| Item | Notes |
|
||||
|------|--------|
|
||||
| Host `SandboxVars` / spawn / `Map=` | Not in the world save. Without `--server-config`, the dedicated defaults remain. |
|
||||
| Host `SandboxVars` / spawn / `Map=` | Not in the world save. Without `--server-config`, dedicated defaults remain. |
|
||||
| Mods with no WorldDictionary entries | Pure Lua/QoL mods may not appear in recovered `Mods=`. |
|
||||
| Workshop **versions** | IDs are resolved from your local workshop cache; newer mod builds than the host used can cause chunk `LENGTH mismatch` / `blam` errors and odd world state (e.g. zombies in cleared bases). |
|
||||
| Workshop **versions** | IDs come from the workshop cache on disk; newer mod builds than the host used can cause chunk `LENGTH mismatch` / `blam` errors. |
|
||||
| `ZombieMigrate` | Dedicated sandbox may allow migration even when respawn is off; align sandbox with the host when possible. |
|
||||
| Running without mods first | Can rewrite `WorldDictionary` and map chunks. Re-import from `original/` if that happened. |
|
||||
| Running without mods first | Can rewrite `WorldDictionary` and map chunks. Re-import from the original host world if that happened. |
|
||||
|
||||
## Example passwords
|
||||
|
||||
```bash
|
||||
# ../server/.env (next to docker-compose)
|
||||
# next to docker-compose (.env)
|
||||
SERVER_PASSWORD=hunter2
|
||||
|
||||
# or CLI override (from this directory)
|
||||
cargo run --release -- … --password 'hunter2'
|
||||
# or CLI override
|
||||
zomboid-converter … --password 'hunter2'
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user