add readme

This commit is contained in:
2026-08-08 11:57:50 +02:00
parent c2309e3ccf
commit a9153ed2bc

123
README.md Normal file
View File

@@ -0,0 +1,123 @@
# Zomboid client-hosted → dedicated server
Convert a locally **hosted** Project Zomboid multiplayer world into a **dedicated** server layout, then run it with Docker.
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
Paths below are relative to the **repo root** (parent of this `converter/` folder):
| 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) |
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
```
`--input` may be a world **directory** or a **`.zip`** (opened read-only; extracted to a temp dir). Paths ending in `_player` are rejected.
### 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 |
| `--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
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=`)
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).
### Characters / login
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)
```bash
cd ../server
cp .env.example .env # if needed; set passwords / SERVER_NAME
docker compose up -d
docker compose logs -f
```
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`.
## 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 hosts `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`.
## Known gaps / caveats
| Item | Notes |
|------|--------|
| Host `SandboxVars` / spawn / `Map=` | Not in the world save. Without `--server-config`, the 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). |
| `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. |
## Example passwords
```bash
# ../server/.env (next to docker-compose)
SERVER_PASSWORD=hunter2
# or CLI override (from this directory)
cargo run --release -- … --password 'hunter2'
```