Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
BeastheimServerMods
Valheim server management suite featuring server-authoritative characters, modpack enforcement, AFK management, Discord webhooks, and monitoring.
By Beasty
| Date uploaded | 2 days ago |
| Version | 1.4.1 |
| Download link | Beasty-BeastheimServerMods-1.4.1.zip |
| Downloads | 11 |
| Dependency string | Beasty-BeastheimServerMods-1.4.1 |
This mod requires the following mods to function
denikson-BepInExPack_Valheim
BepInEx pack for Valheim. Preconfigured with the correct entry point for mods and preferred defaults for the community.
Preferred version: 5.4.2350README
Beastheim Server Mods
Server management, character protection, mod enforcement, and community monitoring for Valheim dedicated servers.
Beastheim Server Mods is a collection of configurable server-management tools originally developed for the Beastheim Valheim community.
Built to help server administrators maintain fair progression, manage limited player slots, enforce modpack consistency, and monitor server activity, it combines several essential systems into one plugin.
Features
- Server-Authoritative Characters: Bind each player's character to your server, preventing the normal import of items, equipment, and progression from other worlds. Includes persistent saves, controlled character resets, revision history, backups, and administrative recovery.
- Modpack Enforcement: Check connecting players against the server's required and optional mods. Reject missing, modified, incompatible, or unauthorized plugins with clear, player-facing explanations.
- AFK Detection & Management (optional, off by default): Detect inactive players, issue configurable warnings, and disconnect idle players to free up limited server slots. Includes final-save handling to help protect character progress.
- Discord Webhooks & Monitoring (optional, off by default): Send server status, player connection activity, and administrative alerts to separate Discord channels without blocking gameplay.
- World Settings (new in 1.4.0): server-set day length and day/night split, sent to every client; new dungeons grow to their full size; optional strict boss progression gating (server-checked altars, admin commands
bh gates/bh gate, player commandbh progress) with Discord messages for boss summons, blocked summons and admin console commands. - Teleport Guard (new in 1.4.1): the server blocks a player from teleporting another player (a vanilla hole); admins may still do it, and blocked attempts are reported to Discord. It also checks that every network message a player sends carries that player's own id (log-only by default, can be switched to blocking).
- Connection Status & Integration: Provide connection-state information and a limited server-side identity API for other compatible mods.
Built for Beastheim. Available to the Community.
Although developed for Beastheim, the systems are configurable for other Valheim dedicated servers, from private groups to larger multiplayer communities.
Installation: Install on the dedicated server and on every client that connects. The plugin goes in BepInEx/plugins. The server is the authority; clients answer its questions and show its messages. A client without the plugin cannot join a server that enforces it. Requires BepInExPack for Valheim.
Compatibility: Built against Valheim 1.0.20 (build 25909357) with BepInExPack 5.4.2351; reads 1.0.20 characters (profile 47) and 1.0.16/1.0.17 characters (profile 46). The 1.0.17 live validation described below was done with BSM 1.2.0; for 1.3.0 the dedicated server loads and runs on 1.0.20, and the 1.0.20 character format is verified against real game-written files. A full real-client run on a 1.0.20 server is still to be recorded.
Status. Validated on Valheim 1.0.17 with a real client against a real dedicated server (BepInExPack 5.4.2350): first-join registration, mod-check admission, the character surviving logouts, reconnects and two server restarts byte for byte, a second character being refused with a readable message, and a clean character store afterwards. It has not yet had a long run on a public server, and it is built for modpacks that use the Jotunn library (as the Beastheim pack does). Please report problems with the
Beastheim Server Modslines of the log and what you were doing.
What players see
When the server turns a player away, the main menu shows a dialog titled Cannot join this server with the reason and an OK button (Enter also closes it). Examples:
- A second character on an account: Only one character is allowed per player on this server. Your registered character is <name>. Select that character and join again. Lost your character? Contact a server administrator.
- A mod problem: Beastheim mod check failed. followed by lines such as Install required: ..., Remove not allowed: ... or Update or reinstall: ... naming the mods, and Restart Valheim after changing mods, then try again.
The dialog is drawn by this mod with the game's own font, because the game's built-in connection-failed panel is shared with the game and other mods and can come out blank. A player without this mod installed cannot receive the reason and sees the game's stock "Incompatible version" message instead.
Quick start for server operators
- Install this mod on the server and give every player the same modpack that includes it.
- Put the original DLL of every mod players must run in
BepInEx/config/BeastheimServerMods/required/(one folder per mod is fine), and any mod players may add inoptional/. - In
BepInEx/config/beastheim.servermods.cfgset[Enforcement] Mode = Enforceand[Characters] Mode = Enforce, then start the server. - Join with a test client first. Check the server log for
Beastheim Server Mods ... loadedandPolicy loaded: N required. - Back up
BepInEx/BeastheimCharacters(see Backups below). It is not part of the world save.
Start with Mode = WarnOnly if you want to see what would be refused before refusing anyone.
1. The mod check
Policy is two folders of the mods' own DLL files on the server:
BepInEx/config/BeastheimServerMods/required/ every client must have these, identical
BepInEx/config/BeastheimServerMods/optional/ a client may have these, identical if present
Copy each mod's original, unmodified DLL from its Thunderstore download into the right folder. Do not copy files from a compatibility or shadow cache. Edits to the policy folders are picked up live; no restart is needed.
At connection time the client reports every plugin it has loaded with a hash of its file. The server compares that with the folders and decides:
| Situation | Result |
|---|---|
| Everything required is present and identical, nothing unlisted | Admitted |
| A required mod is missing, wrong version or modified | Refused, naming the mod |
| A mod that is in neither folder | Refused (BlockUnlistedPlugins) |
| No plugin report at all (no Beastheim Server Mods) | Refused (MissingManifestPolicy) |
| Anything unexpected inside the server | Refused (InternalErrorPolicy = Reject): it never waves players through on an error |
| Both policy folders empty or missing | Refused (EmptyPolicyBehavior = Reject, the default). Allow exists only for a throw-away test server that has no mod list yet |
Mode is Enforce (refuse), WarnOnly (log what would be refused, admit everyone) or Disabled. Server administrators listed in Valheim's adminlist.txt may be allowed through a failed check (AllowAdminBypass), and it is logged when they are.
The first time a client joins, hashing its mods takes some time. It runs on a background thread and its duration is logged, so a slow join can be measured rather than guessed at.
2. Server characters
Set Characters.Mode = Enforce on the server (restart required) and every player has exactly one character.
- A player's first join registers the character they selected. A brand-new character must really be new (default items and recognised mod data only); a stolen, edited or pre-played character cannot be enrolled as "new".
- Every later join must present that same character. A different character, or one that has gone backwards or sideways from what the server holds, is refused with a reason. The server never swaps or repairs a character.
- The server keeps every saved revision, so a client's bad day does not become your data loss.
- Character names are unique (case, accents and look-alike letters are normalised) and 15 characters or fewer.
- Reset. Players can start over from the Character button in the Esc menu. The screen shows whether a reset is allowed right now, the cooldown remaining and how many resets are left in the rolling window, before anything destructive is confirmed. Defaults: 3 resets per rolling 30 days, a 24 hour wait before registering the next character, and the old character archived for 30 days (its name stays reserved for that long; its character ID is retired permanently).
- Both local and Steam Cloud characters are supported; the server reads what the game actually loaded.
- Protocol limits and rate limits apply before a player is even logged in, so a hostile client cannot flood the server with uploads.
Administration
Dangerous recovery actions are not in-game commands. They are done offline by the server operator with the separate bsm-admin tool (distributed to server operators only, never part of this package, never needed by players) (adopt a different character, roll back, restore, archive, purge, hold, cooldown changes, backups, audit). Each shows a parsed diff of what would change, asks for an explicit typed confirmation, takes a backup first and writes an audit entry.
Backups: read this
The character store (BepInEx/BeastheimCharacters) is production data. A hosting panel's backup of the world may not include it. The mod writes verified snapshots on a schedule and after every enrollment, reset or restore (Characters.Backup), and can mirror them to a second folder (Backup.MirrorFolder). Put that folder somewhere that is backed up, and rehearse a restore.
3. Configuration
Everything is in BepInEx/config/beastheim.servermods.cfg (created on first start). The settings that matter most:
[Enforcement]
Mode = Enforce # Enforce | WarnOnly | Disabled
BlockUnlistedPlugins = true
MissingManifestPolicy = Reject
InternalErrorPolicy = Reject
EmptyPolicyBehavior = Reject # the default: an empty policy folder is a fault, not "allow all"
[Characters]
Mode = Enforce # Off (default) | Enforce; needs a restart
[Afk]
Enabled = false # the default: completely inert
TimeoutMinutes = 30
WarningMinutes = 5,1 # minutes REMAINING at which a warning is shown
Changes to the file are applied while the server runs, except Characters.Mode.
Idle players (optional, off by default)
With [Afk] Enabled = true a player who shows no sign of life for TimeoutMinutes is warned, then removed. Signs of life the server can see are movement beyond ActivityRadiusMeters, an emote change, a chat message, and (for up to SleepMaxMinutes) sleeping in a bed. Nothing counts while a player is loading, being admitted, or inside a character reset or final save, and a new player gets GraceSeconds before the clock starts. Admins (ExemptAdmins) and ExemptSteamIds are never removed.
When the timeout is reached the server asks the player's game for its character through the same path used for logout and reset, waits at most FinalSaveWaitSeconds for the save to be uploaded, validated, committed and acknowledged, tells the player, waits DrainSeconds so the message arrives, and disconnects. If the save is not confirmed in time the player is still removed, the last acknowledged revision is kept, the problem is logged (and published to the admin webhook), and the player is told the server could not confirm their latest progress was saved, so recent changes may be lost. Without Characters.Mode = Enforce nothing can be confirmed, so the notice always carries that warning. Other Beastheim mods can pause the clock briefly with BsmAfk.Suppress and BsmAfk.Release. Do not run it together with the separate AfkDetector mod.
[Afk]
Enabled = true
TimeoutMinutes = 30
WarningMinutes = 5,1
ActivityRadiusMeters = 3
GraceSeconds = 60
FinalSaveWaitSeconds = 15
DrainSeconds = 3
4. Discord webhooks (optional)
Webhook settings live in their own file, BepInEx/config/beastheim.servermods.webhooks.cfg (created on the server only), so the secret URLs never sit in the main config. Leave the URLs empty and the feature does not exist. Set Discord.PublicWebhookUrl and/or Discord.AdminWebhookUrl (two separate channels) and choose events in [Events].
- Delivery is asynchronous with a bounded queue, timeouts, retries with back-off, rate limiting and flood merging. A Discord outage, slow response or revoked webhook can never delay a login, a character save or the server.
- Messages contain no character contents, no credentials and no webhook addresses. Player-controlled text is sanitised and cannot ping anyone. Steam IDs go only to the admin channel.
- Only
httpsaddresses on Discord's own hosts are accepted. The URL is a secret: it is never logged.
5. For other mods
Beastheim.ServerMods.Status.BsmStatus is a read-only status surface (current connection state, safe rejection text). It reports discrete states only. It has no progress percentage because the game does not provide one.
Beastheim.ServerMods.BsmIdentity (server only, ApiVersion 1) lets other server-side plugins ask one question: which character did Server Characters verify this connection to be? TryGetCharacterId(connection, out id) and TryGetCharacterIdBySteam64(steam64, out id) return the character ID (the game's player ID, the number wards use) and nothing else. They return false unless Characters.Mode = Enforce and the connection is currently admitted with a validated character, so "unknown" can never be mistaken for "verified". The character store and its revisions are not exposed.
Known limits
- Every player needs this mod. Without it a player cannot be shown the reason for a refusal and, on an enforcing server, cannot join.
- The mod check trusts the files a client reports. It is a guard against mistakes and casual tampering, not a defence against a determined cheater.
- Built against Valheim 1.0.20 and BepInExPack 5.4.2351 (the 1.2.0 line was checked against 1.0.17 and BepInExPack 5.4.2350 and 5.4.2351). A Valheim update can change the game code this mod hooks; check the changelog before updating the game on a live server.
- Steam Cloud characters are supported by design but have had less real-world testing than local ones.
Support
When reporting a problem, include the Beastheim Server Mods lines of BepInEx/LogOutput.log (server or client). They are written not to contain character data or secrets.
CHANGELOG
Changelog
1.4.1
Security
- Teleport guard (server): vanilla lets any client teleport any other player (Character "RPC_TeleportTo" only checks that the receiving client owns the character). The server now drops a client's request to teleport ANOTHER connected player's character. A player's own portals, beds and NPC teleports are unaffected; creatures and tames keep vanilla behaviour; admins may still teleport players (TeleportAllowAdmins). Blocked attempts are logged and sent to the webhook ADMIN route as Teleport.Blocked (at most once per 30 s per player).
- Routed-message sender check (server): vanilla forwards the sender id written inside each routed network message without comparing it to the connection, so a modified client can pose as another player to mods that trust the sender id. [World] RoutedSenderCheck = LogOnly (default) records every mismatch in the server log and on the webhook ADMIN route as Routed.SenderMismatch and blocks nothing; Enforce drops them; Off. Run LogOnly first and switch to Enforce after clean logs.
- New settings in [World]: BlockPlayerTeleport (true), TeleportAllowAdmins (true), RoutedSenderCheck (LogOnly). Server-only: clients need no update for the guard, but update them with the server as usual.
1.4.0
World module (new, server side; clients need 1.4.0 to get the day length)
- Day and night: the server sets the day length and the day/night split (Beastheim: 30-minute day, 75% day) and sends it to every client, so sky, spawns and sleeping match. Set once before a world goes live; changing it on a running world moves the day counter.
- Dungeons: new dungeons grow to their full vanilla size (DungeonsFullSize). DungeonRoomMultiplier allows up to 1.5x, off by default. Dungeons already generated are unchanged.
- Boss gating (strict): bosses unlock by gate rules (time since ServerLaunchUtc, player counts, previous bosses). Altar summons are checked on the server in three layers, the Queen's door stays locked while her gate is closed, and game keys are guarded. Admin commands: bh gates, bh gate open/close/auto; players: bh progress. Empty ServerLaunchUtc = gating off with a warning; an unreadable date keeps every gate closed with an alert.
- Admin audit: admin console commands, kicks, bans and saves are posted to the Discord admin route; boss summons and blocked summons have their own Discord budget.
Unchanged
- Characters, admission, AFK, status API, the head API and the protocol version.
1.3.0
Valheim 1.0.20
- Reads 1.0.20 characters (profile 47 / player data 34 / item data 110) as well as 1.0.16 and 1.0.17 characters (46 / 33 / 109). The three version numbers are accepted only as a matching set; a mixed or future set is refused rather than guessed, and any extra bytes still fail closed. Player data 34 adds two small number tables that the parser now reads in full.
- Everything built on a character (ownership, enrollment, freshness, revisions, divergence protection, enforcement, the status API) behaves the same for 1.0.20 characters as for older ones.
Character-head API for other mods (new)
BsmCharacterHead(ApiVersion 1):IsReady,TryGetHead(the last acknowledged character state: revision, Coins, custom markers),RequestCheckpointandPollCheckpoint. A mod that moves Coins can ask the server for a verified, durable save before and after it acts, and can tell whether the character in the store matches what it expects. Read-only except for the checkpoint request; mods never write a character through it.
Clients
- A save that the server asks for (a checkpoint) is now uploaded by the client even when the character has not changed since its last save. A 1.3.0 server therefore needs 1.3.0 clients; the mod check already refuses a client whose mod file differs, so update the server and the modpack together.
Unchanged
- Admission rules, the registration and reset rules, the AFK module (still off by default), the status API and webhooks, the refusal messages and the protocol version.
1.2.0
Admission (mod check)
- Mod policy enforcement carried over from the internal 1.0.0 build, with fail-closed handling of every internal error and an empty-policy guard (
EmptyPolicyBehavior, which defaults toReject: an empty or missing policy folder never lets everyone in). - The server now holds a player's login until both the mod check and the character check have finished.
- Hashing a client's mods runs on a background thread and its duration is logged.
Server characters (new)
- One authoritative character per Steam account, exact selected-character validation, no substitution.
- Freshness-gated first enrollment; nothing is stored until the game's own password and ban checks succeed.
- Revision store with continuity enforcement, unique normalised names, permanent character-ID tombstones.
- In-game reset with eligibility, cooldown and allowance shown first (3 per rolling 30 days, 24 hour cooldown, 30 day archive).
- Pre-login upload limits, paced and hash-checked transfer, final-save acknowledgement on logout and shutdown.
- Verified snapshots, optional mirror folder, scheduled pruning.
- Offline
bsm-admintool for exceptional recovery: distributed separately to server operators, not part of this package.
Refusal messages
- Refusal screen fix (found in real-client validation): a client that runs this mod is now refused with the game's plain "disconnected" status instead of "incompatible version". Jotunn (present on every Beastheim client) replaces the connect-error screen for "incompatible version" and hid this mod's reason. Clients without this mod keep the stock "incompatible version" status.
- The reason is now shown in this mod's own "Cannot join this server" dialog (with an OK button) on the main menu. The game's built-in connection-failed panel is shared with the game and about ten mods and came out blank in real-client testing, so it is no longer relied on. The message is kept until the player presses OK.
- New wording when a second character is used on an account that already has one: "Only one character is allowed per player on this server. Your registered character is <name>. Select that character and join again. Lost your character? Contact a server administrator."
Idle-player handling (new, OFF by default)
- Optional native AFK module (
[Afk]): idle clock from movement beyond a radius, intentional actions the server can see and chat; warnings at configurable times; no clock during loading, admission, finalization or a reset. - Removal always goes through the character module's own final-save path: save request, upload, validation, durable commit, acknowledgement, a short network drain, then the disconnect. If the save is not confirmed in time the player is still removed, the last acknowledged revision stands, the failure is logged and published, and the player is warned that the server could not confirm their latest progress was saved (never told it was).
- Admins and listed Steam IDs are exempt. Messages, timeout, warnings, radius and grace period are configurable and apply live.
BsmAfk.Suppress/BsmAfk.Releaselet other Beastheim mods pause the clock for a bounded time (a transport, a cutscene).- Admin-channel webhook events for removal with and without a confirmed save.
Identity binding for other server plugins (new)
BsmIdentity: a read-only, narrow lookup of the character a connection was verified as (character ID only; false unless Server Characters is enforcing and the connection is admitted).
Also new
- Read-only connection status for other mods (discrete states, no percentages).
- Optional native Discord webhooks (public and admin channels), fully asynchronous and isolated from the server.