GsValheimStatsEmitter
Server-side companion for the gs dashboard: world milestones, per-player boss damage, live online players + in-game day, and server-owned combat. Pairs with the gs client companion.
About this mod Author’s original text
GsValheimStatsEmitter (server-side)
A dedicated-server mod that posts the stats only the server can see to an HTTP endpoint - by default the self-hosted gs dashboard, but it'll POST to any URL.
Pairs with the GsValheimStatsClient companion (which each player installs for their personal stats). Both POST to the same endpoint; a receiver merges them by world + player name.
Full payload schema, key conventions, and merge rules are documented on the Data format & self-hosting wiki.
Why a server mod at all? Valheim hands creature simulation to whichever client is nearest, so most combat is captured client-side. The server still owns idle / distant creatures (e.g. a sleeping mob you sneak-attack), so this mod captures those - notably the true post-backstab hardest hit - plus world-progression milestones the server is authoritative for.
What it is
A BepInEx plugin for a Valheim dedicated server. It patches
Character.RPC_Damage and Character.OnDeath, polls the world's global keys,
and POSTs a cumulative JSON snapshot to the gs dashboard on a timer. Bosses are
identified with Character.IsBoss() rather than a hardcoded list, so new bosses
work without a code change. Cumulative counters persist to
BepInEx/config/net.cproudlock.gsvalheimstats.state.tsv and survive restarts.
What it tracks
- World milestones ("quests") - boss defeats, Hildir's Request bounties, first troll/surtling, etc. (from the world's global keys)
- Per-player boss damage for bosses the server owns
- Weapon damage + hardest hit for server-owned creatures (the sleeping-backstab case)
- Live presence - connected players + in-game day (onlinePlayers / worldDay), force-emitted on join/leave for near-instant "online now"
- Active mod list + world identity (name, host, uptime)
Setup
- Install on your dedicated server (depends on denikson-BepInExPack_Valheim). Drop the DLL in BepInEx/plugins.
- Launch once to generate BepInEx/config/net.cproudlock.gsvalheimstats.cfg, then set:
[General]
World = vhserver3 # your server's -world name
EmitIntervalSeconds = 120
[Ingest]
Url = # dashboard reachable from the server
Token =
- Restart the server. Cumulative counters persist to BepInEx/config.state.tsv.
Run it
dotnet build -c Release
There is no local dev loop. The build needs the Valheim dedicated-server
assemblies and BepInEx core, so it only compiles on the gameserver VM, where
GsValheimStatsEmitter.csproj points $(Managed) and $(BepInExCore). Nothing
in this repo builds on a workstation.
Success looks like Build succeeded. 0 Error(s), and the DeployToServer
target copying the DLL into BepInEx/plugins.
Deploy
The build deploys itself: the DeployToServer target runs after every
successful Release build and copies the DLL into $(DeployDir). So the whole
recipe is copy the source over, build there, restart.
scp src/Plugin.cs *.csproj manifest.json CHANGELOG.md \
cproudlock@10.9.50.213:/home/cproudlock/mod-valheim/
ssh cproudlock@10.9.50.213 'cd ~/mod-valheim && dotnet build -c Release'
Then restart the server. Use the safe-restart script, never vhserver restart,
which never returns through the qemu guest agent and leaves a stale
lgsm/lock/vhserver-stopping.lock that silently blocks every later start:
setsid /home/cproudlock/vhserver3/vh-safe-restart.sh >/dev/null 2>&1 &
then poll /tmp/vh-safe-restart.log for the RESULT: line
Afterwards confirm Loading [GsValheimStatsEmitter ] and
[gs] ingest status: 200 in BepInEx/LogOutput.log.
Note the version lives in three places that must agree: `` in the
csproj, version_number in manifest.json, and the VERSION constant in
src/Plugin.cs. The dashboard records the last of these, so a mismatch is
visible in the mod list.
Ingesting the stats yourself
Same contract as the client mod - an authenticated POST of a JSON snapshot (see that mod's README for a minimal receiver + curl test).
Payload (source: "server"):
{
"schemaVersion": 1,
"game": "valheim",
"source": "server
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: