Dyrr
A door policy: characters that have played elsewhere do not come in. Off until an admin turns it on.
About this mod Author’s original text
Dyrr
Dyrr is a join policy for Valheim servers. A character that has played on other worlds, that
has used cheats, or that arrives with mods the server does not permit can be refused when it
connects. Nothing is refused until an admin turns Enforce on.
It also kicks idle players on dedicated servers, reports when a character comes back carrying
something it did not leave with, and stops your own client from taking a character into a world
it does not belong to.
Features
- Six checks at the join: the character has spawned in another world, the game has flagged it
for cheats, it has run a console command the game classes as a cheat, its own records
disagree with each other, the client is running mods the server does not permit, or it did
not answer at all. Each can be switched off on its own.
- Enforce is off by default. Every connection is still judged and the verdict is written to
the log, so you can see who would be turned away before anyone actually is.
- A refused player is told which rule they broke, on their own screen if they have Longhouse
Core, and in their own log either way.
- Character protection on the client: a character is bound to the first world it plays in, and
the game refuses to start it anywhere else. This works whether or not the server runs Dyrr.
- Idle kick on dedicated servers, with a chat warning first.
- Inventory watch: a log line when a character's inventory changed while it was offline. This
only ever reports. It never refuses or kicks.
- A dyrr console command that prints the standing verdict for everyone currently connected.
How the join check works
Both ends register an RPC as soon as the connection object exists, before either side sends
PeerInfo. The client sends what it knows about its own character: the character name, the
cheats flag and its counter, the name of every console command the character has ever run, the
UIDs of every world it has spawned in, and the BepInEx plugin GUIDs loaded on that machine. The
server does the arithmetic in a prefix on ZNet.RPC_PeerInfo and refuses before the player
spawns, so a refused player never watches the world load first. All of it comes out of
PlayerProfile, which lives on the client's disk, so all of it is self-reported. See
Known limits.
Which console commands count as cheats is decided on the server, from the server's own
Terminal command table, so a cheat command added by some other mod on the server counts for
free. A dedicated server has no guarantee of having built that table when the first player
knocks, so there is a fallback list of the 73 vanilla commands registered with isCheat: true.
The mod check is the one that reaches cheating on a dedicated server.
Console.IsCheatsEnabled() returns ZNet.instance.IsServer(), so a client's own devcommands
does nothing on someone else's server. Anyone cheating there is running a mod that patched
around that line, which makes "what is this client running" the more useful question.
The tamper check does not need the client to be honest, only consistent. The game writes
the same facts in more than one place: m_usedCheats is a bool, PlayerStatType.Cheats is a
counter incremented on the next line, and m_knownWorlds records worlds by name at save time
where m_worldData records them by UID at spawn. A flag that is clear beside a counter above
zero, or more world names than world UIDs, is an edited save. Neither inequality can be
produced by playing the game.
Character protection
Refusing a character at the join arrives too late to help it. Loading a character into any world
writes that world into PlayerProfile.m_worldData permanently, and nothing in the game ever
removes the entry. So the client half refuses the trip instead.
Each character is bound to the first world it is seen in, recorded in
BepInEx/config/dyrr-home.txt. After that:
- Starting a local world with a character bound elsewhere is refused at
FejdStartup.OnWorldStart, with a popup naming both worlds and the file to edit.
- Joinin
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: