About GsValheimStatsEmitter
From ThunderstoreServer-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.
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 inBepInEx/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 = http://localhost:3001/api/valheim/ingest # dashboard reachable from the server
Token = <bearer token>
- Restart the server. Cumulative counters persist to
BepInEx/config/<guid>.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 <version>] and [gs] ingest status: 200 in BepInEx/LogOutput.log.
Note the version lives in three places that must agree: <Version> 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",
"world": "vhserver3",
"hostName": "Proudlock VH Server 3",
"serverStartedAtUtc": "2026-06-09T11:32:00Z",
"onlinePlayers": ["Erebus", "Pridetoes"],
"worldDay": 12,
"emittedAtUtc": "2026-06-09T18:00:00Z",
"snapshotIdLocal": "9a6b...",
"players": [{
"name": "Erebus",
"boss": [{ "boss": "Eikthyr", "kills": 1, "damageDealt": 1450, "fightSec": 95 }],
"weapons": [{ "weapon": "Knives", "damageDealt": 80, "kills": 2, "hardestHit": 79 }]
}],
"bossKillEvents": [{ "boss": "Eikthyr", "fightSec": 95, "firstBlood": "Erebus", "topDamagePlayer": "Erebus", "topDamage": 1450, "participants": 2, "tsUtc": "..." }],
"milestones": [{ "key": "defeated_eikthyr", "label": "Eikthyr defeated", "kind": "boss", "tsUtc": "..." }],
"mods": [{ "guid": "Azumatt.AzuCraftyBoxes", "name": "AzuCraftyBoxes", "version": "1.8.14", "author": "Azumatt", "folder": "Azumatt-AzuCraftyBoxes-1.8.14" }]
}
Merging client + server feeds
Each feed reports the creatures it simulates, so they're disjoint. A receiver should:
- sum
damageDealt/killsper(player, weapon)across the twosources (exact total, no double-count, since a single hit is only ever processed by one side), and - take the max of
hardestHit.
The gs dashboard does this with per-source rows + SUM / MAX(...) at read time.
Highlights
From source dataLoaders
Runs on BepInEx.
Footprint
Rated a light load on a server.
Last update
Its author last shipped an update 54d ago.
GsValheimStatsEmitter on Nxeon
From our catalogue- One-click install
- Supported on Nxeon Valheim servers, for BepInEx servers. We download it from Thunderstore, place it, and restart the server.
- Server side
- Required on the server
- Server type needed
- BepInEx
- Server load
- light
- Smallest plan we suggest
- Valheim — 4 GB (4 GB RAM). This follows our own load rating above, not a benchmark.
- Latest build
- 0.2.6, released 2026-09-12
Game versions by loader
| Loader | Game versions | Newest |
|---|---|---|
| BepInEx |
From 8 recorded builds of GsValheimStatsEmitter.
Recent builds
| Build | Released | Game versions | Loaders |
|---|---|---|---|
| 0.2.6 | 2026-09-12 | n/a | BepInEx |
| 0.2.5 | 2026-09-12 | n/a | BepInEx |
| 0.2.4 | 2026-06-10 | n/a | BepInEx |
| 0.2.3 | 2026-06-10 | n/a | BepInEx |
| 0.2.2 | 2026-06-10 | n/a | BepInEx |
| 0.2.1 | 2026-06-10 | n/a | BepInEx |
Dependencies
- Required: BepInExPack Valheim
Declared by the newest build that lists any. Required ones are installed with it on one-click installs.
Run GsValheimStatsEmitter on a Valheim server
Pick a server or deploy a new one above; it is installed in one click.
What kind of mod it is
From the catalogCreatures & NPCs
Adds or changes creatures, NPCs and how they behave.
Runs on your server
From source side supportThunderstore lists GsValheimStatsEmitter as required on the server. Check its Thunderstore page to see whether players need it too.
Compatibility
- Game
- Valheim
- Loaders
- BepInEx
- Runs on
- Serverrequired on the server
- Requires
- One-click install needs a BepInEx server.
Verified at the source
- ✓ThunderstoreOfficial listing, checked 2026-10-02Open ↗
- ✓AuthorProudlock_Technology, as published on Thunderstore
- ✓LicenseNot published by the sourceFree






