ServerInfo
Exposes a small HTTP JSON API with a Valheim server's world name, connected players (with Steam avatars), and installed mods - built for live status pages that read it directly from the browser.Changelog
All notable changes to this project are documented here.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning (with the BepInEx-safe caveat in CONTRIBUTING.md — no prerelease suffixes).
Unreleased
2.2.7 - 2026-09-13
Fixed
- Stopping the server no longer logs a spurious
ObjectDisposedExceptionerror fromHandleLoop—StopServerclosing theHttpListenerwhile a request is pending is expected during shutdown, not a real failure.
2.2.6 - 2026-09-13
Added
- Licensed under GPL-3.0-or-later (see
LICENSE, full official text). GPL-3.0 requires forks/redistributions to keep this project's copyright and license notices intact — those notices point back to https://github.com/odin-sons/serverinfo. Added the matching SPDX header to every source file and aLicensesection to the README. LICENSEis now included in the published package zip.
Changed
manifest.json's andthunderstore.toml'swebsite_urlnow point to the repository instead of being empty.
2.2.5 - 2026-09-13
Added
- VirusTotal scan of the built package before publishing to either
platform, gated on the
VIRUSTOTAL_API_KEYrepository secret. A malicious/suspicious verdict fails the release before anything ships; the scan report link is added to the GitHub Release notes either way. - A VirusTotal badge in the README, linking to the latest release (where that release's own scan report is linked).
2.2.4 - 2026-09-13
Fixed
- Removed the em dash from
manifest.json'sdescription— Thunderstore's manifest validator rejects it (confirmed by hand, undocumented). Uses a plain hyphen now; a test guards against it coming back. CHANGELOG.mdis now actually included in the published package zip.tcli buildonly copiesicon/readmeautomatically; the changelog needed its own[[build.copy]]entry inthunderstore.toml.
2.2.3 - 2026-09-12
Fixed
- Hexium publish uploaded a corrupted package (
"Invalid ZIP file."from the server). PowerShell's$array[$a..$b]range-index isn't guaranteed to stay a[byte[]]— it silently decayed to a genericobject[], whichInvoke-WebRequest -Bodysent as something other than raw bytes. Switched to[Array]::Copyinto a realbyte[].
2.2.2 - 2026-09-12
Fixed
tcli publishin the release pipeline now tolerates Thunderstore's "already exists" response instead of failing the job — a version that publishes there successfully but fails at a later step (e.g. Hexium) can now be safely re-run without the Thunderstore step blocking it.
2.2.1 - 2026-09-12
Added
- Automated Hexium publishing in the release pipeline, alongside
Thunderstore. Reverse engineered from
Kesomannen/gale's open-source
client against Hexium's own (undocumented) submission API:
initiate a multipart upload,
PUTthe package bytes, finish the upload, then submit. No plugin code changes — release tooling only.
2.2.0 - 2026-09-12
Added
- Unit test project (
ServerInfo.Tests) covering the reflection helpers, ID/path parsing, and config parsing, plus packaging validation (manifest.jsonfields,icon.pngdimensions, and version consistency acrossProgram.cs/AssemblyInfo.cs/manifest.json/thunderstore.toml). - CI (
.github/workflows/ci.yml): builds and runs the full test suite on every push and pull request. - Automated release pipeline (
.github/workflows/publish.yml): pushing av*.*.*tag builds, tests, and — only if that passes — publishes to Thunderstore and attaches the package zip to a GitHub Release for a manual Hexium upload (Hexium has no public upload API yet). manifest.json,icon.png,thunderstore.toml, andpackage.ps1for publishing to Thunderstore and Hexium (see CONTRIBUTING.md).
Changed
- Breaking: no longer bundles its own copy of Newtonsoft.Json.
Declares a dependency on the shared
ValheimModding-JsonDotNETlibrary instead, to avoid two copies of the same assembly being loaded at once. Installs through a mod manager pull this in automatically; a manual DLL-only install now needs that library present too. - Packaged files no longer sit under a
plugins/subfolder in the release zip — they ship flat at the package root instead, somanifest.jsonends up next to the installed DLL (the plugin reads its own neighboring manifest.json at runtime;plugins/gets flattened straight intoBepInEx/plugins/on install, separating the two).
[2.1.0] - 2026-09-12
Added
Domainconfig ([Server]section) — this server's public domain or IP. It's purely a readiness flag for the plugin: theAccess-Control-Allow-Originheader is now only sent onceDomainis set, so a fresh install doesn't advertise a CORS policy before the server is actually meant to be reachable from the outside.AllowedOriginitself is unchanged (*by default).
[2.0.0] - 2026-09-12
Changed
- Breaking: renamed the project from PublicWebLink to Server
Info: plugin GUID changed to
Odin_Sons.ServerInfo, display name toServer Info, assembly toServerInfo.dll, namespace toServerInfo. BepInEx treats the new GUID as a different plugin and generates a freshOdin_Sons.ServerInfo.cfg; the oldMaddy.Publicweblink.cfgis not migrated.
[1.6.0] - 2026-09-12
Added
MetadataSourcesconfig ([Mods]section) — a comma-separated order of precedence (Manifest,Assembly) admins can set to control where a mod'sdescription/websiteUrl/dependenciescome from, down to disabling one source entirely or reversing the default priority.
[1.5.0] - 2026-09-12
Added
LogLevelconfig ([Logging]section) — a BepInExLogLevelflags value controlling which message levels this plugin writes to the log, defaulting toError, Warning; addInfoto also get startup/diagnostic messages.- Mods without a
manifest.jsonnow fall back to whatever their own assembly carries fordescription(AssemblyDescription),websiteUrl(an embeddedRepositoryUrl), anddependencies(their BepInEx dependency GUIDs), instead of always returningnull.
Changed
- Documented that the plugin works fully without
SteamApiKeyset —playersis still returned, just withoutAvatarUrl.
Fixed
- The "SteamApiKey is not set" warning is now logged once instead of on every refresh.
[1.4.0] - 2026-09-12
Added
- Numeric settings (
Port,RequestTimeoutSeconds,CacheIntervalSeconds,AvatarCacheMinutes) now declare an acceptable range, so BepInEx clamps an out-of-range value in the.cfgfile instead of accepting it as-is, and config-editor mods render them as a bounded slider.
Changed
- Config settings split into
[Server],[Cache], and[Steam]sections instead of one flat[General]. - Documented in README: how the avatar cache is keyed and expires, and that installing is just "drop the DLL" — BepInEx generates the config file with defaults on first run.
[1.3.1] - 2026-09-12
Changed
- The Windows URL-ACL access-denied message no longer suggests
user=Everyoneas the primary fix — it now points at finding and using the actual account running the server (whoami), withEveryonedocumented as a fallback rather than the default: it lets any local account on the machine claim the same URL reservation, not just the one that needs it.
[1.3.0] - 2026-09-12
Added
ServerInfoPathconfig option — the endpoint path no longer has to be/serverinfo.- CORS support (
AllowedOriginconfig,*by default) so a status page on another domain can call the endpoint directly from the browser. - A startup log line confirming the port and path the server is listening on.
- Startup now detects a Windows URL-ACL access-denied error specifically
and logs the exact
netshcommand to fix it.
Changed
- Errors while handling a request are now logged server-side (with the full exception), not just returned in the response body.
[1.2.0] - 2026-09-12
Added
- Avatar URLs are cached (
AvatarCacheMinutesconfig, default 60) and pruned once entries go stale, instead of being fetched fresh on every refresh for every connected player.
Changed
- Steam avatar lookups for all connected players are batched into a
single
GetPlayerSummariescall instead of one request per player. CacheIntervalSecondsandRequestTimeoutSecondsare now configurable instead of hardcoded.- Code reorganized from a single file into
GameReflection.cs,GameServerInfoProvider.cs,PackageManifestReader.cs,SteamAvatarService.cs, andModels.cs. - Renamed internal
Thunderstore*types/methods to be format-agnostic (PackageManifest,ParseNamespace) — Hexium uses the same namespace/name convention, so nothing here was Thunderstore-specific.
Security
- Steam avatar requests now use HTTPS instead of HTTP.
[1.1.1] - 2026-09-12
Fixed
namespacecoming backnullfor mods whose package folder has no version suffix (some mod managers update packages in place).
[1.1.0] - 2026-09-12
Changed
modsin/serverinfochanged from a plain string array to objects enriched with each mod's ownmanifest.json:description,websiteUrl,dependencies,namespace,packageName.- Build no longer requires a local Valheim or BepInEx install — moved to
NuGet-only dependencies (
BepInEx.Core,UnityEngine.Modules), withZNet/Peeraccess rewritten to use reflection instead of a direct assembly reference.
Removed
- The unused Harmony dependency.


