ClientGhostWatchdog
Client-side watchdog mod for players connecting to Valheim servers that detects dropped connections and disconnects cleanly to prevent ghost desyncs.
About this mod Author’s original text
ClientGhostWatchdog
A standalone, 100% client-side watchdog mod for players connecting to remote/dedicated Valheim servers that prevents "Zombie Client" / "Ghost Connection" desync states.
[!NOTE]
Client-Side Only: This mod is installed locally on your PC. It does not need to be installed on the server and works when connecting to any dedicated or community server.
The Problem
When playing on a dedicated or remote server, if the server drops your client's connection (for example, during daily scheduled server restarts, network glitches, or ISP timeouts with a ClosedByPeer status), vanilla Valheim has a critical client-side bug:
- ZNet.UpdatePeers() ignores disconnection error codes reported by ZRpc.Update().
- ZSteamSocket.IsConnected() only checks pointer validity, remaining "connected" even after the socket closed.
- The client's ZNet.m_connectionStatus remains Connected.
- The client continues running in an empty, desynced world without realizing it was disconnected. Any structures built, items moved, or actions taken while desynced are lost or result in desync rollbacks.
The Solution
ClientGhostWatchdog runs an independent background coroutine on your game client when connecting to a remote server:
- No Game.Update Overhead: Runs completely via a dedicated Unity coroutine with real-time sleep intervals, executing zero per-frame checks in Game.Update.
- Disabled on Local Worlds: Strictly inactive on singleplayer worlds or local server hosts (ZNet.instance.IsServer()). No coroutine is started and no checks run.
- Two-Stage Detection:
- Stage 1 (Halfway Warning): When server silence reaches halfway through the configured timeout period (e.g. 15s at the default 30s timeout), a prominent on-screen center notice warns the player: "Server connection lost, attempting to reconnect... ({0}s)". The {0} placeholder dynamically updates with the countdown until disconnect.
- Auto-Recovery: If server communication resumes during the warning stage, the warning is dismissed and an on-screen notice confirms: "Server connection restored."
- Stage 2 (Timeout & Clean Logout): If silence reaches the full timeout, the server socket closes, or the server peer drops, the mod displays "Server connection lost. Disconnecting...", pauses for the configured notice delay (DisconnectDelaySeconds, default 5s) so the notice is readable, and triggers Game.instance.Logout().
- Severed Peer & badly behaved Mod Protection: Catches scenarios where a third-party mod (such as ServerCharacters inventory sync timeout) or network failure drops the server peer without an engine logout, preventing players from being trapped in desync limbo.
- Preserves Native Disconnect Reasons: If an admin kicks or bans a player, or the server shuts down, the watchdog defers to native Valheim, allowing players to see the genuine error dialog instead of generic watchdog notices.
- Portal & Teleport Hang Guard: Resumes health checks after a configurable ceiling (TeleportTimeoutSeconds, default 30s) if a player gets stuck in an indefinite portal desync.
- Preserves Player Progress: Calling Game.instance.Logout() ensures the client cleanly saves their character profile (SavePlayerProfile(setLogoutPoint: true)) before returning to the main menu.
- Informs the Player: Displays an informative dialog on the main menu informing the player why they were returned to the menu and that their local save was preserved.
- Defensive Lifecycle & State Safety: Centralized state machine (WatchdogManager) with atomic, TTL-backed disconnect reasons (DisconnectReasonManager) to prevent stale error dialogs across scene transitions.
Design Philosophy & Tradeoffs
This mod intentionally enforces a fail-safe disconnect policy:
- Why fail-safe disconnect?: In vanilla Valheim, hanging onto an unacknowledged dead connection risks losing valuable building, harvesting, or combat progress. By forcing a clean logout via Game.instance.Logout(), the mod saves the player's local inventory and state immediately
Install & use Install: BepInEx plugin
- The archive from playbuff is the mod itself — usually a BepInEx plugin (a .dll or a plugin folder once unzipped).
- Recommended: use a community mod manager (such as r2modman) — pick this game, import the mod, and the manager sets up BepInEx and its dependencies for you.
- Manual route: install the BepInEx loader in the game folder, then drop the unzipped .dll or plugin folder into BepInEx/plugins/.
- Launch the game — the BepInEx console logs every plugin it loads; seeing this mod in the log means it is installed.
Mods with listed dependencies need those installed too, or they will not load. Options are usually changed in-game or in the plugin's config file. In multiplayer, the host and every client need the same mods installed.
Install these first, or the mod will not work: