Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pinsanity

Resource Finder Gone Berserk

"If it's worth doing, it's worth overdoing!"

Current version: 1.0.0

Pinsanity finds nearby resources and pins them on the Valheim minimap. Food, wood, metals, dungeon entrances, spawners, Dvergr bases, valuables inside buried treasure chests ... even the amount of honey contained in player-built beehives ... over 160 different things are tracked, configurable (on or off), and labeled however players prefer. Includes a GUI to make it all super-easy.


Features

On top of a host of things players care about...

  • Showing "the actual icon" for each resource
  • Loading icons directly from the game's assets, instead of fiddling with folders and image files
  • Incredible configurability (turning things on/off, customizing labels)
  • Wrapped in a GUI for maximum convenience
  • Various performance optimizations
  • (See more, including screenshots, on the Nexus Mods page)

...there's a verbose pile of things that I didn't mention elsewhere.

Some things that you, the skeptical coder or could-be contributor, might be interested to know:

Metal Resources

  • Finds every type of deposit, including the ones that shatter into fragments
  • Helps players find every last fragment of copper, silver, etc.
  • Each fragment pin is placed at the visual center of the mesh for perfect accuracy
  • Automatically detects mined-out fragments and removes their pins

Dynamic Labels

  • Shows treasure chests with specific items (silver necklaces, onion seeds, etc).
  • Empty treasure chests show an "EMPTY" label to save time
  • Player-made beehives show how much honey is available for picking (if empty, pins do not display)

GUI Settings Window

  • GUI window is resizable and persists between sessions, so the layout stays how players left it
  • Various pains have been taken to ensure "things you type" don't get lost without being saved (label edits are always saved when players leave a field or close the window)
  • Numerous forms of input are suppressed while the settings window is open, so players won't accidentally declare war on a Dvergr while tweaking settings
  • Players can close the GUI window via their own configured hotkey or ESC (and not accidentally pause the game at the same time)
  • After they're done making changes, the scanner will fire immediately (rather than waiting a full interval)

Input Suppression & Lifecycle

  • Numerous gameplay inputs and minimap interactions are suppressed (along with camera rotation and cursor recapture) while the window is open, to prevent unintended in-game actions while the player is adjusting settings
  • All suppression flags reset on each open/close cycle, ensuring suppression state never carries over between sessions
  • GUI window opening is blocked if not in-game, the ESC menu is open, or the player object isn't fully loaded
  • _weDidPause prevents unpausing a game that was already paused by a third-party mod before the window opened
  • Int fields are buffered during typing, preventing half-entered values from being committed prematurely
  • Int fields are also flushed on window close, since focus-loss doesn't reliably fire in the same frame as a button click
  • _isRebuildPending defers scanner rebuild until window close rather than triggering on every individual toggle, avoiding redundant restarts during multi-setting changes

Icon Management

  • Different object types store their icon data in different places, so five separate lookup strategies are used to find the right icon for each resource (Pickable component, PickableItem component, DropOnDestroyed component, ZNetScene/ObjectDB name lookup, or generic map icon (dot, house, etc.))
  • ZNetScene is tried before ObjectDB for speed since it's a scene-level lookup rather than a search across the full item database
  • A clean-name fallback strips Pickable_ prefixes and (Clone) suffixes, recovering icon matches that would otherwise fail due to naming inconsistencies

World Object Identification

  • Flametal spires are re-validated against ZNetView on every scan to filter out phantom LOD meshes with no network identity, preventing false pins; a transform.position fallback also handles renderers not yet fully initialized
  • A three-stage name lookup ensures dungeon variants (like Crypt1(Clone) and Crypt4(Clone)) are found automatically, including potential new variants added by future game updates (Crypt5(Clone), etc).

Performance & Efficiency

  • Filtering discards up to 90% of scene objects before expensive lookup operations to minimize CPU cost
  • Scan collections are pre-allocated and reused every pass to avoid per-scan GC pressure
  • A reentrancy guard (_isScanning) prevents a slow scan from overlapping the next one
  • Scanning is skipped entirely when the game is paused or the settings window is open
  • unscaledDeltaTime drives the scan timer so scan interval is consistent regardless of game speed

Caching & Pin Management

  • Numerous object types and icons are cached, eliminating redundant lookups and hierarchy traversals on subsequent scans
  • All caches are invalidated on scene load, preventing stale references from causing incorrect behaviour or crashes after a world change
  • Dungeon loot icons are never cached since objects with identical names (ie. Pickable_ForestCryptRandom) can yield different items
  • Two collections of resource pins (a dictionary for fast lookup and a list for iteration) are kept in sync, with snapshot copies on read to prevent exceptions when pins are removed mid-scan
  • Default pin sprites are captured once from the first pin created and reused when a custom icon is no longer needed, ensuring pins always have a valid fallback appearance

Error Handling & Doomsday Scenarios

  • All scan steps wrapped in try/finally so _isScanning is always cleared even on exception
  • GUI exceptions trigger a force-close with up to 3 auto-reopen attempts (deferred one frame to let IMGUI settle); a permanent error overlay is shown after repeated failures, making persistent problems visible rather than silent
  • Reflection access to Valheim's private m_picked field fails gracefully with a one-time warning, so a game update that renames the field produces a visible notice rather than silently pinning already-picked objects

Config & Diagnostics

  • To reduce future maintenance overhead, config setters are generated via reflection for GeneralConfig properties, so adding a new setting requires no parser changes
  • Per-property bounds and defaults are stored in a lookup table to keep the reflection loop generic
  • DebugLogger checks debug state internally so callers never need to write if (IsDebug) themselves
  • Three logging tiers: Debug (state changes), Trace (per-object firehose), and Benchmark
  • Benchmark mode logs a 14-bucket per-scan timing table to nanosecond precision, including a separate measurement of Minimap.AddPin() overhead
  • Suppression-once logic avoids per-frame log spam while still providing diagnostic detail when needed
  • Custom labels with special characters (like #) won't break the mod
  • Future updates (ie. Deep North) won't break player customizations: missing or invalid settings are detected on load and the file is resaved automatically with corrected values

Oh, and the whole thing is "well-commented."

Did I overdo it? Yes, I did.

Sorry, make that "obsessively commented."


And then what?

View the roadmap of future updates here.


Installation

  1. Install BepInEx if you haven't already.
  2. Download the latest DLL from the Releases page.
  3. Drop it into your BepInEx plugins folder: \SteamLibrary\steamapps\common\Valheim\BepInEx\plugins
  4. Launch Valheim. The mod creates a config file automatically on first run with sensible defaults.
  5. Press F8 in-game to open the settings window. (The hotkey is configurable in the config file.)

Configuration

Pinsanity can be configured in two ways: the in-game settings window (recommended) and the config file (for anything the window doesn't cover, like the hotkey).

The in-game window lets players toggle resources on or off, customize labels, switch entire categories on or off, adjust scan radius and interval, and enable various debug modes: all live, with changes saving instantly.

A config file is created automatically at \SteamLibrary\steamapps\common\Valheim\BepInEx\config\FoobyScroobs.Pinsanity.cfg.

Players who prefer to manually edit config files will see organized sections with headers, inline comments, and notes for certain resources, instead of the usual wall of auto-generated BepInEx boilerplate.

General settings:

Setting Default Range Description
Enabled true true/false Master on/off switch for the entire mod
ShowLabels true true/false Show or hide all pin labels globally
ScanRadius 100 1–500 How far from the player to scan, in meters
ScanInterval 5000 500–30000 How often to scan, in milliseconds
Hotkey F8 any KeyCode Key to open/close the settings window

Each resource also has two config entries: Enable{Name} (true/false) and {Name}Label (display text). These are all managed automatically by the in-game window, but can be hand-edited if preferred.

A note on Configuration Managers

Pinsanity uses its own hand-rolled config format and its own in-game settings UI. This may not be compatible with the BepInEx ConfigurationManager mod.

Honest confession: I built the entire in-game settings window before I even knew BepInEx ConfigurationManager existed. In hindsight, that might have saved a few weeks and a few hundred lines of IMGUI code. On the other hand, the settings window is pretty awesome, so I choose not to think about it.


Compatibility

No known conflicts at this time.

All patches are prefixes that only fire while the settings window is open. The game is paused during this time, so even if another mod patches the same methods, conflicts are unlikely to affect normal gameplay.

The patched methods are:

  • GameCamera.LateUpdate
  • GameCamera.UpdateMouseCapture
  • ZInput.GetButtonDown
  • ZInput.GetKeyDown
  • Minimap.Update
  • Minimap.OnMapLeftClick
  • Minimap.OnMapRightClick
  • Minimap.OnMapDblClick
  • Minimap.SelectIcon
  • Minimap.ToggleIconFilter

If Valheim updates and something breaks, check the GitHub Issues page.

Known limitations

Not tested in multiplayer -- wanna check it and let me know?


How It Works

Periodically, Pinsanity scans all active GameObjects within the configured radius, discards all the ones that aren't immediately interesting, matches the remaining candidates against a list of known resource definitions, and places minimap pins for everything the player wants to see. Pins are removed automatically when resources go out of range, are picked up, or are mined out.

Fragment-based ore deposits (copper, silver, etc.) are handled specially: Valheim replaces the original deposit with up to 130 individual fragment meshes when first struck, and Pinsanity tracks each fragment independently so players can see exactly what's left underground.

The scan runs on a configurable timer (default: every 5 seconds).


Known Issues

None currently! If you encounter problems:

  1. Set IsDebug = true in the config file (and optionally IsTrace = true for extreme detail).
  2. Reproduce the issue.
  3. Find your log file at \SteamLibrary\steamapps\common\Valheim\BepInEx\LogOutput.log
  4. Open a GitHub Issue and attach the log.

Contributing and Support

Pull requests are accepted case-by-case: please open an issue first to discuss.

Maintenance: Gaming is an occasional hobby. This mod does what I need. If you want to extend it, fork away!


This is not AI slop.

This mod is a labor of love, painstakingly built over the course of 10 months.

It was built from scratch by analyzing the game's decompiled code, not by copying or modifying existing mods.

I definitely used AI assistance (Claude) to create this mod -- and I definitely did not do it with a single prompt.

Pinsanity was built iteratively, tested, debugged, audited against a 17-point checklist, and then in true OCD fashion: it was audited again.

Every line of code has been read, understood(ish 😉), and approved by a human.

No memory leaks. No thread safety issues. No lifecycle problems. No hot-path concerns.

That said, I am not a career programmer, and while everything in this mod makes sense to me, it might not make sense to someone who's been doing it for 20 years.

Audit it yourself: it's all here.


Changelog

See CHANGELOG.md.


License

MIT License: see LICENSE

Free to use, modify, and distribute.

About

Pinsanity finds nearby resources and pins them on the Valheim minimap. Food, wood, metals, dungeon entrances, spawners, Dvergr bases, valuables inside buried treasure chests ... over 160 different things are tracked, configurable (on or off), and labeled however players prefer. Includes a GUI to make it all super-easy.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages