Valheim
Install with App

Details

Latest version
0.5.0
Last Updated
First Uploaded
Downloads
651
Likes
0
Size
163KB
Dependants
ADDatHost Valheim hosting
30% off

Changelog

0.5.0 — 2026-11-03

Death history (Raid Ledger ROK-1931). Needs 0.5.0 on the server and on every client: the server's enricher now holds back deaths stamped after a server-replaced capturedAt, so a 0.4.x server would not protect a 0.5.0 client's upload. Requires a Raid Ledger server with ROK-1931 (state: publish only after production has the Raid Ledger change; an older server rejects the whole character upload because every object in the contract is strict). A player with no recorded deaths omits the new fields and is unaffected.

Update order: Raid Ledger first, then the game server, then (or with) the clients. A Raid Ledger server without ROK-1931 rejects every character upload from a 0.5.0 client that has recorded deaths (400 schema_invalid on the unknown deaths/deathCount keys), and so does a game server still on 0.4.x (its strict pre-send validator drops the upload). Nothing flags the mismatch earlier, because modVersion is not matched by default. Those players' character data stops updating until the server side is on 0.5.0.

  • The client records each death of the local player: a Harmony prefix and postfix on Player.OnDeath (the prefix decides "local player") store the position and time in Player.m_customData (RlValheimLink.deaths), newest first, capped at 200, so the history travels with the character save. Client.OptOut is respected: nothing is recorded or sent.
  • character.deaths[] (position and time) and character.deathCount (the game's per-character Deaths stat) ride along with every character capture. The Deaths stat is read by reflection (PlayerProfile.GetStat); when the game build does not have it, deathCount is omitted.
  • The server's enricher drops deaths[] entries stamped after a capturedAt it replaced (client clock more than 60 s ahead), so a skewed clock cannot make the whole upload fail validation.
  • Pre-send validator and mock receiver enforce the new rules (unique at, at <= capturedAt, 200 cap, deathCount bounds). Contract pinned to the Raid Ledger ROK-1931 branch (additive, still v1; PIN.md says pre-merge until Raid Ledger main has it).

0.4.6 — 2026-11-01

Server-only config change. Clients and the modpack need nothing.

  • [Server] ItemsExportBy now defaults to anyone (was admins): a new game version's item catalogue and piece icons arrive on the first join of any player with the mod, not only an admin's. The groups this mod serves are small and do not forge item lists; admins and nobody remain available.
  • One-time migration of existing config files. BepInEx keeps a value already written to the file, so on first start of 0.4.6 a file that still says ItemsExportBy = admins (the old default) is rewritten to anyone and the log says so once (RLVL: config: [Server] ItemsExportBy changed from admins …). anyone and nobody are left as they are. The new internal [Server] ConfigRevision = 1 records that this ran, so it never runs again: to keep admins only, set ItemsExportBy = admins after the upgrade and it is kept.
  • No wire-format change.

0.4.5 — 2026-11-01

Client fix (Raid Ledger ROK-1881). Players update the mod for their own pins to be relabelled; the dedicated server needs nothing new.

  • Map pin labels on Raid Ledger's Map tab now read as they do in game. Names the game stores as translation tokens (location, boss and enemy pins, $hud_…) are translated with the player's language before sending, rich-text tags (<color=…>, <b>, <size=…>, <sprite…>, <#ff0000>) are removed while other text in angle brackets (<Home>) is kept as the game shows it, line breaks and other control characters become spaces and surrounding whitespace is trimmed; a label with nothing left is sent empty. The 64-character cap is applied after that, never in the middle of an emoji.
  • Which pins count as shared (from a cartography table) is unchanged and now confirmed against the game code: a pin is shared when another player wrote it to the table and you have not taken it as your own.
  • Pin types added by other mods (not in the game's list) are still sent as their number and shown with a generic icon; each such number is logged once per session (RLVL: pins: pin type <n> is outside …). Labels are never logged.
  • No wire-format change.

0.4.4 — 2026-11-01

Server-only feature (Raid Ledger ROK-1945). Clients and the modpack need nothing.

  • Portals now appear on the Raid Ledger map without anyone pinning them. The dedicated server's scan finds every portal in the world on the chest scan's interval (3 minutes after start, a minute after the chest scan so the two never walk the world on the same tick, then every Chests.IntervalMinutes) and sends a full portals snapshot (prefab, position, pairing tag; CONTRACT.md §5c), so a destroyed portal disappears at the next scan. Portal prefabs are every prefab with the game's portal component, which covers vanilla portal_wood / portal_stone and portals cloned from them (AdvancedPortals). XPortal appears to keep its name in the vanilla tag field (observed in the server log; unverified). The prefabs are logged once (RLVL: portal scan: <n> portal prefabs: …), each scan as RLVL: portal scan <n>: ….
  • New [Portals] Enabled (default true) switches it off independently of [Chests] Enabled; [Portals] ExtraPrefabs adds a modded portal without that component. Tags longer than the contract's 64 characters are clipped, a duplicate piece at one position is sent once, and above 4 096 portals the rest is counted in omitted. Tags and positions are never logged. If no portal prefab is found at all (broken discovery, not an empty world) nothing is sent, so Raid Ledger's portals are not wiped: one WARN (RLVL: portal scan: 0 portal prefabs found …) and a retry at each slot. [Portals] ExtraPrefabs entries that are not prefabs get one WARN.
  • No wire-format change (portals is already in the pinned contract v1).

0.4.3 — 2026-11-01

Server-only fix (Raid Ledger ROK-2059). Clients and the modpack need nothing.

  • The server counted an items export as done for (game version, mod set) as soon as it was spooled, before Raid Ledger answered. When the upload was then rejected for good (413 over the size cap, 422 schema, 400), no client was ever asked again and the item catalogue for that game version stayed missing until someone cleared the mod's state by hand. Now a spooled export is only queued: it becomes done when Raid Ledger accepts that upload (2xx, or 409 already have it), a permanent rejection logs one WARN (items|<game> was rejected for good …) and forgets it, so the next client allowed by Server.ItemsExportBy that joins is asked again once a cool-down has passed: 1 h after the first rejection of that (game version, mod set), doubling per further rejection up to 24 h, so a rejection that repeats every time (size cap, contract drift) no longer costs a client capture and upload on every join. The cool-down is kept in index.json (survives a restart), is logged once with the rejection, and is reset when an upload for that key is accepted or the Raid Ledger target changes. Transient failures (5xx, network, 429, 413 quota_exceeded) keep the export queued and retrying, and no client is asked again meanwhile.
  • On start the server forgets "done" markers left by 0.4.2 and older whose upload was never accepted (logged once), so a catalogue already stuck this way is requested again at the next eligible join.
  • An items message whose gameVersion differs from its client's hello is dropped (logged, the client is told), so the export marker and the spooled upload cannot end up under different game versions.
  • A queued export marker whose spooled file vanished is pruned at start instead of lingering in index.json.
  • No wire-format change.

0.4.2 — 2026-10-24

Client fix (players get it through the modpack; the server needs nothing new).

  • character.knownRecipes and character.knownItems now carry prefab ids, as the contract defines (CONTRACT.md §3), instead of the game's name tokens. Valheim stores what a player has discovered as tokens: Player.AddKnownRecipe stores the result item's m_shared.m_name ($item_sword_bronze), AddKnownPiece stores Piece.m_name ($piece_workbench), and AddKnownItem stores m_shared.m_name. The mod only sanitised them, so Raid Ledger received _item_sword_bronze and its Planner's "not yet discovered" filter (ROK-1862) matched nothing. The client now maps every token through a lookup built from the live ObjectDB (recipes → result prefab, build pieces of every tool → piece prefab, items → item prefab; modded content included). A token that names several prefabs sends all of them; a token with no match is dropped with one WARN (count and up to 5 examples). Sort, dedupe and the 8 192 cap are unchanged and apply after mapping. Trophies were already prefab ids (AddTrophy stores the drop prefab name).
  • No wire-format change.
  • Contract re-pinned to Raid Ledger 9b04a68 (additive, still v1): the new portals kind (ROK-1944, a server-side scan of every portal). The pre-send validator and the mock receiver now know its rules (unique (prefab, x, y, z), tag ≤ 64 chars, nullable height, ≤ 4 096 portals, 4 MiB body). The mod does not send it yet; the portal scan is a later release.

0.4.1 — 2026-10-21

Server-only fix (Raid Ledger ROK-1894). Clients and the modpack need nothing.

  • The recipes export's formula check now uses the Valheim 1.0.x per-quality cost rule, so custom again means "a mod changed this recipe". Measured on the production server (game 1.0.20): an upgrade item (Upgrader*Armor / Upgrader*Weapon) costs its amount at every quality step, and any other requirement costs amountPerLevel × 2^(q − 2) from quality 2 (×1, ×2, ×4), where 0.221.x charged (q − 1) × amountPerLevel. 0.4.0 compared against the 0.221 rule and flagged 272 of 479 vanilla recipes as custom; on vanilla 1.0.20 the log line now reads custom formula: 0. Station and station level are unchanged. 0.221.x servers keep the old rule.
  • No wire-format change: the message is the same; Raid Ledger applies the same rule in its Planner (ROK-1894).

0.4.0 — 2026-10-21

Piece and station icons in Raid Ledger's Planner. Needs 0.4.0 on the server and on at least one admin's client for the icons. Without it nothing breaks: a 0.4.0 server with older clients, or a 0.3.0 server with 0.4.0 clients, keeps sending recipes without icons, as in 0.3.0. The RPC protocol is unchanged.

  • Client: the hello now advertises features: ["pieceIcons"]. When the server asks (needPieceIcons), the client copies the icon of every build piece and crafting station into one atlas PNG (64 px, 32 per row, smaller when the PNG would exceed [Upload] MaxBlobBytes), the same way as the items export. It sends the PNG to the server, then the map of which rect belongs to which prefab (a new internal transfer kind, about 30 KB). rlvl export icons in the F5 console starts it by hand.
  • Server: asks one client for the atlas when it has none for this game version and server mod set. The client must advertise the feature, run the same game version and be allowed by [Server] ItemsExportBy (default: admins); one request at a time, a 10-minute lease. When the atlas and map arrive, the server keeps the map in spool/piece-icons.json and sends the recipes export again at once with an icon on every station and piece it covers. Later exports for the same game version reuse the map. The atlas PNG is uploaded to Raid Ledger before the recipes message that references it. The export's log line now says icons: <n> of <m> (atlas <sha>…), or why there are none.
  • No contract change: atlas icons and the recipes atlas ref are part of v1 (CONTRACT.md §5b).

0.3.0 — 2026-10-21

Server-only update (ROK-1879): install it on the dedicated server. Clients do not need it; the RPC protocol is unchanged, so 0.2.x clients keep working against it and a 0.3.0 client behaves exactly like 0.2.3.

  • Chest scan → containers (Raid Ledger ROK-1853, the hub's Materials tab). On a dedicated server, 2 minutes after start and then every 10 minutes on a fixed grid ([Chests] IntervalMinutes, 5–120), the server reads every player-built container from the world's ZDOs (chests, barrels, wardrobes, personal chests, carts and ships; no player needs to be online or nearby) and sends one containers snapshot for the world, every time, even when nothing changed. Per container: prefab, position (0.1 m), creator's playerId, privacy (personal chests stay private: owner and admins only on Raid Ledger), slots and used slots, stacks summed per (item, quality). World-generated chests (no creator), loot chests, tombstones and the obliterator ([Chests] ExcludePrefabs) are never sent; a chest the game cannot decode is sent as unreadable with no items; the contract's caps (256 entries per chest, 4 096 chests, 50 000 entries) are applied by dropping, never by sending an invalid message. Time-sliced: one ZDO query per server tick, then about 200 decoded stacks per tick (production world: busiest tick ~1.3 ms). Respects [Server] WorldAllowlist (an unlisted world is not scanned) and the upload budgets; a scan whose message failed the contract is logged and not sent. [Chests] Enabled = false switches it off.
  • Recipes export → recipes (Raid Ledger ROK-1854, the hub's Planner tab). About 90 s after start, once per game version and server mod set, the server sends its crafting recipes (raw requirement fields, upgradeOnly, 1.0.20 upgrade items, a custom flag where a mod changed the per-quality cost), build pieces of every build tool, crafting stations with their max level and the processing steps of smelters, kilns, the windmill, spinning wheel, eitr refinery, fermenter, cooking stations, oven and obliterator. Read on the server, so it needs no admin client. A dedicated server cannot render sprites, so this export carries no piece or station icons (atlas: null); item names and icons still come from the items catalogue. [Recipes] Enabled = false switches it off.
  • [Chests] Dump (the 0.2.1 spike diagnostic) is retired: it is now [Chests] DiagnosticDump, off by default; the old Dump key is ignored.
  • Log lines (exact text in docs/operator-checklist.md section H): RLVL: chest scan on: …, RLVL: chest scan <n>: <c> containers … → Accepted, RLVL: recipes export: <r> recipes, …, and the uploader's RLVL: POST containers containers|<world> → 202 accepted / POST recipes recipes|<game> → 202 accepted.

0.2.3 — 2026-10-20

  • No change to what the mod does in game or sends to Raid Ledger; the plugin code is the same as 0.2.2.
  • Development tooling: the mock Raid Ledger receiver (tools/mock-ingest) now enforces every rule Raid Ledger checks beyond schema.json, for all five kinds (character, map, items, containers, recipes), with Raid Ledger's issue paths and codes, so the upload tests catch any payload production would refuse.

0.2.2 — 2026-10-20

  • Contract re-pinned to Raid Ledger cef3748 (additive, still v1):
    • an items message may be up to 12 MiB (was 10 MiB; ROK-1855), so the largest item catalogue, with a file icon per item, now fits. Raid Ledger's reverse proxy still limits a request body to 10 MiB until ROK-1850, but that is the body on the wire: with [Upload] Gzip = true (the default) even the largest catalogue compresses to well under 1 MiB. Only with Gzip = false could an items POST over 10 MiB be refused (413, dropped with a log line). Typical catalogues are ~300 KB of JSON;
    • the new containers kind (ROK-1853): the pre-send validator knows its rules (unique container identity and (prefab, quality) stacks, usedSlots ≤ slots, unreadable ⇒ empty, creator never 0, ≤ 50 000 entries per message). The mod does not send it yet; the chest scanner is a later release;
    • the new recipes kind (ROK-1854): the validator knows it too (unique stations, recipe ids, pieces and processors; station and processor references resolve; atlas-only icons inside the atlas; raw requirement fields; ≤ 12 000 resources + inputs per message). Not sent yet either.
  • Server, chest dump diagnostic: the probe's rows: line reports the stack count as the game writes it (ZPackage.WriteNumItems), like the probe and totals lines since 0.2.1; it printed the int32 reading (header count 655360003 vs decoded 3). Logs only; nothing about uploads changes.
  • Docs: chest-capture design (docs/design-chests.md) gains the spike results, the production measurements from 0.2.1 (one prefab pass per tick: busiest tick 1.3 ms on a 361 143-ZDO world) and the Raid Ledger rulings 15–20 with their stories.

0.2.1 — 2026-10-20

  • [Server] WorldAllowlist (comma-separated world names, case-insensitive; empty = every world). When the loaded world is not listed the server half stays idle: no base-map render, every client's hello is answered with reject hello: world 'x' is not linked … so a 0.2.1 client sends nothing that session (an older client keeps sending and the server drops it), and nothing is spooled or uploaded. For one dedicated server that is sometimes booted into a test world: the character key has no world in it, so a test-world session would otherwise become the character's latest snapshot in Raid Ledger.
  • Client: a reject whose reason starts with hello: now stops the session's captures (older servers never send one).
  • [Chests] Dump (dedicated server only, default true): a diagnostic for the planned chest-inventory capture, on by default (operator ruling: nothing should need a flag; Dump = false skips it). Two minutes after every start, the server reads every container from the world's ZDOs with the game's own Inventory.Load and logs RLVL: chestdump[r<run>.c<check>] lines: the keys on a few known chests (items / itemData hashes), which data shape and which Inventory.Load variant decode a 1.0.20 chest (and whether the temporary inventory avoids instantiating item objects), milliseconds per stack, row counts, counts per prefab (duplicates, creator 0, gone, dropped), totals of DumpMaterials, creator / creatorIndex on personal chests, every container and processing-station prefab with its values, and the 1.0.20-only recipe and station fields. DumpRuns (default 2) and DumpRerunMinutes (default 10) repeat it and report what changed (freshness). Logs only: no upload, no new message kind, no ZDO string contents in the log; it does log chest positions and the player and Steam ids of chest creators and connected players. Each run (two by default, about 2 and about 12 minutes after start) can cause a short server hitch, longer on large worlds; discovery is spread at one prefab query per tick. It never runs in a player's single-player or self-hosted world. Because it uploads nothing it also runs on a world that is not in WorldAllowlist and without a Raid Ledger target. Run 1 logs how long its two single-frame steps took (setup tick, probe tick).
  • Members that are new in 1.0.20 are read by name through GameAccess, so a wrong guess shows up as a dump line, never as a failure of the captures.

0.2.0 — 2026-10-19

Bundled release after the first full in-game runs (operator ruling: fewer, better-tested iterations).

  • Compatibility by protocol, not version. The server accepts any client that speaks the same RPC protocol and logs the client's mod version; a server-side update no longer forces a modpack update. Server.RequireExactModVersion = true restores the strict check.
  • Equipment & Quick Slots rows named through its official API (API.IsSlotCell), so the extra inventory rows arrive as equipment / quickslot instead of other.
  • Progress lines at 25/50/75% for large transfers (the icon atlas is ~6 MB and Steam sends it at ~150 KB/s, about 40 s).
  • Includes 0.1.6: the logout flush sends only the small snapshots and leaves large transfers to a live session.

0.1.6 — 2026-10-19

  • Fix: logging out while an item-catalogue export was queued lost everything, including the character and map — the multi-megabyte atlas sat ahead of them and the connection closed before any of it drained. At logout/quit the client now sends only the small snapshots (character first, then map) and drops large transfers; the server asks for the catalogue again on the next join. Seen on the operator's second admin join.

0.1.5 — 2026-10-19

  • The server notices when its upload target changed (Raid Ledger instance rebuilt or moved, server id or token changed) and forgets its "already uploaded" markers, so the base map and the item catalogue are re-sent without any manual step; dedupe watermarks and pending messages are kept.
  • Operator instructions: server setup, item catalogue by admins, token rotation and rebuilt-instance behaviour on the Thunderstore page; docs/operations.md runbook.

0.1.4 — 2026-10-19

  • Fix: captures made on logout or quit were lost — the game saves the profile and closes the connection in the same frame, so chunks queued for later frames never left the client. The client now flushes every queued transfer synchronously (and flushes the socket) when the save is a logout/quit save.
  • Fix: the admin check for the items export accepts both Steam_<id> (Valheim 1.0 list format) and bare SteamID64 entries in adminlist.txt.

0.1.3 — 2026-10-19

  • Fix: the client never sent anything on Valheim 1.0.20 — the runtime enforces member visibility, and the build (compiled against publicized references) called the private ZRoutedRpc.GetServerPeerID() directly (MethodAccessException every tick, seen in the operator's client log). Every non-public game member the mod reads now goes through Harmony AccessTools in GameAccess.cs (equipment slots, trophies / known items / recipes, skills, minimap bitsets and pins); routed-RPC ids come from public API.
  • A startup self-check logs game member access ok|BROKEN, and CI scans the built DLL against an unpublicized reference assembly so a direct private access can never ship again.

0.1.2 — 2026-10-19

  • First version published to Thunderstore as GamerSaloon-ValheimLink, from main by release.yml.

  • Fix: a spooled blob with no message referencing it yet (the base map, rendered at world load) was never uploaded; blobs now go up on their own, oldest first, before messages. Found on the first real run.

  • No operator URLs in the repository or the built DLL: the BaseUrl config description and the design doc no longer carry an example instance URL (operator ruling). The pinned contract keeps Raid Ledger's own $id, which is theirs to change.

0.1.1 — 2026-10-19

  • Build against the game build the operator runs: Valheim 1.0.20 on Unity 6000.0.75 via the Digitalroot.Valheim.Common.References and UnityEngine.Modules packages (ValheimGameLibs stopped at 0.221.4).
  • Console command registration no longer binds one ConsoleCommand constructor signature (1.0.20 added a parameter and the old binding threw MissingMethodException at every Terminal init); it picks the ConsoleEvent overload by reflection.
  • Steam id read through reflection into the game's own Steamworks.NET; no Steamworks reference shipped.
  • First real-endpoint findings: the server half renders the 2048² base map in ~21 s on the dedicated server and queues it; error bodies are { code, message } (fixed in 0.1.0's PR 4).

0.1.0 — unreleased

  • Contract library (RlValheimLink.Contract): message model, JSON writer, pre-send validator covering schema.json and every CONTRACT.md §6 refinement, bitset/gzip/base64 encoder, PNG encoder; tests against the pinned golden and invalid fixtures.
  • Client half: character, map (explored + shared layer + pins) and items (ObjectDB + icon atlas) captures on Game.SavePlayerProfile, hello on spawn, per-player opt-out, rlvl console command.
  • Chunked routed-RPC transport (RLVL_Chunk / RLVL_Control) with caps and per-peer rate limits.
  • Server half: RlValheimLink.Core (enricher with socket identity + playerId cross-check + clock clamp, disk spool with latest-wins dedupe and content-addressed blobs, uploader state machine honouring Raid Ledger's codes, budgets, 429 Retry-After, backoff and 401/403 halts, HTTP client with gzip bodies) plus the game glue (peer identity cache, hello → needItems, base-map render once per world and game version). Tested end to end against the mock receiver.
  • Contract pin refreshed to Raid Ledger main after ROK-1833 (additive: optional blob on file icons); mock receiver matches the real routes, error codes, rate buckets and quotas.
  • Thunderstore package name decided: GamerSaloon-ValheimLink.
  • Tooling: mock ingest receiver, ajv + C# fixture validation, contract drift check, CI and release workflows, Thunderstore layout.
Thunderstore development is made possible with ads. Please consider making an exception to your adblock.