Valheim
Install

Details

Last Updated
First Uploaded
Downloads
42
Likes
1
Size
184KB
Dependency string
Balrond-balrond_better_build-0.1.0
Dependants
ADDatHost Valheim hosting
30% off!

πŸ—οΈ Balrond Better Build

Balrond Better Build is an experimental performance and scalability mod for Valheim's structural integrity system.

Valheim normally recalculates structural support by repeatedly scanning nearby physics colliders for individual WearNTear objects. Balrond Better Build builds a cached, event-driven structural graph and updates only the parts of a construction affected by placement, destruction, terrain changes, streaming, teleportation, or ownership changes.

The mod is intended to reduce the CPU cost of large buildings and heavily populated generated locations while keeping Valheim-compatible support behavior.

Important: Structural replacement is a low-level gameplay change. Back up important worlds before testing a new version. Start with VanillaCompatible, keep the safety options enabled, and test large constructions on a copied world first.


Features

  • Event-driven cached structural graph
  • Supports player buildings, vanilla generated locations, and modded WearNTear prefabs
  • Budgeted work spread across frames
  • Active-area lifecycle management for travel and teleportation
  • Safe fallback to Valheim while a node is not ready
  • Session circuit breaker on replacement errors
  • Server-synchronized gameplay configuration
  • Optional Observe mode for comparing the graph against Valheim
  • Optional profiling of WearNTear.UpdateSupport and WearNTearUpdater.Update
  • Bounded list pools to reduce GC without permanently retaining unlimited memory
  • Anchor input-link compression for terrain- and world-supported pieces
  • Separate budgeted ownership and ZDO maintenance outside the replacement hot path
  • Optional delayed vanilla support-cache release with cooldown and per-frame limits
  • Information logging and runtime diagnostics can be completely disabled

How It Works

Each managed WearNTear object becomes a graph node.

The graph stores:

  • Structural colliders
  • Cached bounds
  • Direct support contacts
  • Reverse dependent links
  • Terrain or static-world anchor state
  • Material support properties
  • Last committed graph support

A normal replacement lookup is intentionally small:

  1. Find the node by Unity instance ID
  2. Verify that its cached result is ready and valid
  3. Return the committed support value

Physics scans, topology rebuilding, ownership checks, ZDO writes, cache release, and island solving are performed by separate budgeted queues. They are not performed on every successful UpdateSupport lookup.

Anchored nodes

A piece directly supported by terrain or eligible static world geometry always resolves to its material's maximum support. Version 0.3.7 stops scanning the remaining colliders after a valid anchor is found and removes unnecessary inbound support links from that anchored node. The piece still keeps its outgoing dependent relationships, so it can support the rest of the structure normally.

Active areas

On a client or local host, nodes outside Valheim's active area are removed from the active graph. Returning to the location registers and rebuilds them again. This prevents previously visited bases and ruins from remaining in the local structural graph indefinitely.

Dedicated servers do not prune the world using one player's reference position. They rely primarily on runtime object lifecycle events and low-frequency safety reconciliation.


Installation

Compiled release

  1. Install BepInEx for Valheim.

  2. Place the compiled BalrondBetterBuild.dll in:

    BepInEx/plugins/BalrondBetterBuild/
    
  3. Start the game once to generate the configuration file.

  4. Edit:

    BepInEx/config/balrond.astafaraios.BalrondBetterBuild.cfg
    

Building the included source project

  1. Open BalrondBetterBuild.sln in Visual Studio.

  2. Add or copy the required references into Libs.

  3. Select:

    Release | Any CPU
    
  4. Rebuild the solution.

  5. Copy the resulting DLL to the BepInEx plugins folder.

ServerSync.d is included as a project. Config file is provided

Integrity Modes

Mode Behavior Recommended use
Vanilla Balrond Better Build does not replace structural support. Valheim's original solver controls gameplay. Baseline benchmark, troubleshooting, compatibility testing
Observe Both systems calculate support, but Valheim remains authoritative. Comparison diagnostics are available when enabled. Validation and development
Replace The event-driven graph supplies cached support when a node is ready. Unready nodes safely fall back to Valheim. Normal optimized operation after validation

Replace states

  • Warming β€” the initial active graph is still preparing or solving. Valheim remains active where necessary.
  • Armed β€” the graph passed validation and may replace ready nodes.
  • Faulted β€” the session circuit breaker opened. Valheim is used until the world is reloaded or the graph is rebuilt.

Configuration Reference

Values marked Server synchronized are enforced by the server when Lock Configuration is enabled. Values marked Local affect only local memory use, logging, or diagnostics.

[0 General]

Lock Configuration

  • Default: true
  • Scope: Server synchronized

When enabled, the server controls synchronized Balrond Better Build settings. Clients joining the server receive the server's gameplay configuration.

Disable this only for controlled development or local testing. Different structural settings between peers can produce inconsistent support results.

Integrity Mode

  • Default: Replace
  • Scope: Server synchronized
  • Values: Vanilla, Observe, Replace

Selects the structural runtime mode described above.

For the first test on an important mod list, use Observe. After the graph reports no meaningful stability mismatch, use Replace on a copied world.


[1 Performance]

Work Budget Milliseconds

  • Default: 2
  • Scope: Server synchronized

Maximum time budget used by graph preparation, contact refresh, island solving, reconciliation, and maintenance during one frame.

Lower values reduce individual frame spikes but may make large streamed locations take longer to settle. Higher values complete work faster but allow larger frame-time spikes.

Recommended range:

  • 1–2 ms for normal clients
  • 2–4 ms for powerful hosts or dedicated servers

Values that are too low can increase temporary Vanilla fallbacks because graph results remain unready for longer.

Spatial Cell Size

  • Default: 4
  • Scope: Server synchronized

Size in meters of each structural spatial-hash cell.

Smaller cells reduce the number of unrelated candidates returned by local queries but create more cells and lists. Larger cells use fewer cells but increase candidate counts.

Recommended value: 4. Change this only after profiling a specific building set.

Maximum Island Nodes

  • Default: 100000
  • Scope: Server synchronized

Safety limit for one connected structural island. It prevents a malformed or unexpectedly huge graph from growing without a bound during one solve.

This is not a recommended building-size limit. Keep it comfortably above the largest expected connected construction.

Solve Debounce Milliseconds

  • Default: 150
  • Scope: Server synchronized

Delay after topology changes before solving begins.

Streaming and mass placement can emit many changes over several frames. Debouncing combines them into fewer solves. Lower values react sooner but may repeatedly solve a location that is still loading. Higher values reduce duplicate work but delay visible collapse or color updates.

Recommended range: 100–250 ms.

Active Area Reconcile Seconds

  • Default: 180
  • Scope: Server synchronized

Interval for the low-frequency stale-reference safety sweep.

Zone changes, teleportation, Awake, OnDestroy, and lifecycle requests still trigger immediate work. This interval is only a safety net for objects whose expected lifecycle notification was missed.

Higher values reduce periodic scans. Lower values remove stale references sooner but perform more global instance checks.

Recommended values:

  • Single-player/client: 180–300
  • Dedicated server: 180–300

The runtime applies minimum safety clamps.

Require Initial Stable Graph Before Replace

  • Default: true
  • Scope: Server synchronized

Keeps Valheim active until the initial active-area graph has completed preparation, contact refresh, solving, and validation.

Disabling this can reduce warm-up time but increases the chance of using incomplete data during initial location streaming. Leave it enabled.

Maximum Pooled Node Lists

  • Default: 2048
  • Scope: Local

Maximum number of cleared link lists and maximum number of cleared dependent lists retained for reuse after nodes are removed.

Higher values reduce allocations when repeatedly moving between large locations. Lower values release more memory after teleportation.

The limit is applied separately to link lists and dependent lists.

Recommended range:

  • Memory-sensitive client: 512–1024
  • Balanced default: 2048
  • Repeated large-location stress testing: 4096

Set to 0 to disable retention of node lists.

Maximum Retained Node List Capacity

  • Default: 16
  • Scope: Local

Maximum internal capacity retained by a pooled per-node list. Lists that grew larger are trimmed before being pooled.

A larger value reduces reallocations for dense nodes but can preserve more unused memory after leaving a complex location.

Recommended range: 12–32.

Maximum Pooled Spatial Cell Lists

  • Default: 2048
  • Scope: Local

Maximum number of empty spatial-hash cell lists kept for reuse.

This prevents a visit to a very large location from permanently retaining thousands of spare cell lists for the remainder of the session.

Set to 0 to disable spatial-cell list pooling.


[2 Contacts]

Support Probe Expansion

  • Default: 0.15
  • Scope: Server synchronized

Expansion added to each structural collider probe. Valheim uses approximately 0.15 m on each side of the support probe.

Increasing this value can connect pieces that are visually close but not physically touching. Decreasing it can miss expected connections. Keep 0.15 for Vanilla-compatible behavior.

Maximum Overlap Results

  • Default: 4096
  • Scope: Server synchronized

Maximum capacity to which the shared Physics.OverlapBoxNonAlloc buffer may grow in extremely dense locations.

This is a capacity ceiling, not an immediate allocation. The buffer begins smaller and grows only when required.

If overlapOverflows appears in diagnostics, increase this value. Very large values permit a larger retained array after a worst-case query.


[3 Materials]

Material Balance Preset

  • Default: VanillaCompatible
  • Scope: Server synchronized
  • Values: VanillaCompatible, Forgiving, Generous, Custom

Controls material support profiles.

  • VanillaCompatible reads the current game's material properties and is the recommended performance-only option.
  • Forgiving reduces structural losses moderately.
  • Generous allows substantially larger spans and heights.
  • Custom uses the four multipliers below.

Changing this setting changes gameplay, not only performance.

Custom Max Support Multiplier

  • Default: 1
  • Scope: Server synchronized
  • Used only by: Custom

Multiplies maximum support. Values above 1 increase the amount of support available from a material.

Custom Minimum Support Multiplier

  • Default: 1
  • Scope: Server synchronized
  • Used only by: Custom

Multiplies the minimum support required for stability. Values below 1 are more forgiving.

Custom Horizontal Loss Multiplier

  • Default: 1
  • Scope: Server synchronized
  • Used only by: Custom

Multiplies support loss across horizontal distance. Values below 1 allow longer unsupported spans.

Custom Vertical Loss Multiplier

  • Default: 1
  • Scope: Server synchronized
  • Used only by: Custom

Multiplies support loss across vertical distance. Values below 1 allow taller structures.


[4 Networking]

Write Support To ZDO

  • Default: true
  • Scope: Server synchronized

Allows the current ZDO owner to write committed support into Valheim's original support field.

This keeps remote peers and Valheim systems synchronized while avoiding writes for insignificant changes. Leave enabled for multiplayer.

Network Absolute Write Epsilon

  • Default: 0.01
  • Scope: Server synchronized

Absolute minimum support change considered for a non-critical ZDO write.

The normalized threshold below is also calculated. The larger effective threshold is used. Stability-threshold crossings are always written.

Network Normalized Write Epsilon

  • Default: 0.0025
  • Scope: Server synchronized

Minimum support change as a fraction of the material's support range.

0.0025 equals 0.25%. This prevents high-support materials from generating writes for numerically tiny changes that are irrelevant to stability or visible integrity color.

Ownership Recheck Seconds

  • Default: 15
  • Scope: Server synchronized

Interval between budgeted ownership-maintenance sweeps.

Ownership checks are no longer performed in every successful replacement lookup. Structural changes still queue immediate synchronization. Lower values detect ownership changes sooner but perform more ZNetView checks.

Recommended values:

  • Single-player: 15–30
  • Multiplayer host/server: 5–15

Maximum Support ZDO Writes Per Frame

  • Default: 32
  • Scope: Server synchronized

Maximum number of non-critical support writes in one frame.

Stability crossings and ownership changes bypass the budget. Excess non-critical writes are deferred. This limits network bursts when one placement changes support across a large connected construction.

Release Vanilla Support Cache (Experimental)

  • Default: false
  • Scope: Server synchronized

Enables delayed release of redundant Vanilla support caches after a node has remained stable.

This can reduce memory retained by the original support system, but a later Vanilla fallback may need to rebuild those caches. Version 0.3.7 adds a stability delay, fallback cooldown, and per-frame release budget to reduce rebuild/allocation thrashing.

Keep this disabled until normal Replace behavior has been tested successfully on the current mod list.

Vanilla Cache Release Stable Seconds

  • Default: 60
  • Scope: Server synchronized
  • Used only when experimental cache release is enabled

A node must remain solved, valid, ready, and unchanged for this duration before its Vanilla support cache can be released.

Longer delays are safer and avoid releasing caches from actively edited structures.

Vanilla Cache Release Fallback Cooldown Seconds

  • Default: 60
  • Scope: Server synchronized
  • Used only when experimental cache release is enabled

After a node falls back to Vanilla, its caches will not be released again until this cooldown expires.

This prevents repeated cycles of release, Vanilla rebuild, release, and rebuild.

Maximum Vanilla Cache Releases Per Frame

  • Default: 16
  • Scope: Server synchronized
  • Used only when experimental cache release is enabled

Limits cache-release operations in one frame. Eligible nodes are processed by a low-frequency maintenance sweep.

Lower values reduce release spikes. Higher values reclaim a large stable location faster.

Fallback To Vanilla On Error

  • Default: true
  • Scope: Server synchronized

If replacement processing throws an exception, the local world-session circuit breaker opens and Valheim remains active.

Leave enabled. Disabling it is intended only for development where a hard failure is preferred for debugging.


[9 Diagnostics]

All diagnostic settings are Local. They do not need to match the server.

Runtime Diagnostics Level

  • Default: Off

  • Values: Off, Summary, Profiling

  • Off disables periodic graph reports and hot-path diagnostic counters.

  • Summary records compact graph, replacement, pool, and lifecycle statistics.

  • Profiling also times replacement lookup, Vanilla support, WearNTearUpdater, work stages, managed memory, and GC collections.

Use Off for normal gameplay.

Enable Information Logging

  • Default: false

Master switch for Balrond Better Build informational messages and statistics.

Errors and safety warnings remain enabled. This setting cannot suppress logs written by Valheim or other mods, such as Placed, Spawned, or location-generation messages.

For the lowest normal-play overhead use:

Runtime Diagnostics Level = Off
Enable Information Logging = false
Statistics Interval Seconds = 0

Statistics Interval Seconds

  • Default: 0

Interval between reports when diagnostics and information logging are enabled. Set to 0 to disable periodic reports.

Recommended profiling value: 10.

Difference Warning

  • Default: 15

Raw Observe-mode support difference threshold used by verbose warnings.

Normalized Difference Warning

  • Default: 0.20

Observe-mode warning threshold after normalizing support to the material range.

Visual Difference Threshold

  • Default: 0.20

Threshold used to count a likely visible difference in Valheim's integrity color.

Top Differences Per Report

  • Default: 5

Maximum number of unique pieces listed in the Observe-mode top-difference report. Set to 0 to omit the list.

Log Material Breakdown

  • Default: true

Adds a compact per-material comparison summary in Observe mode.

Comparison Change Epsilon

  • Default: 0.001

Observe mode records a new sample only after Vanilla or graph support changes by at least this amount. This prevents repeated identical comparisons from inflating lifetime statistics.

Log Idle Statistics

  • Default: false

When disabled, unchanged idle reports are suppressed.

Idle Heartbeat Seconds

  • Default: 0

Maximum interval between idle heartbeat reports when idle logging is disabled. Set to 0 to suppress idle heartbeats entirely.

Detailed Stage Timing

  • Default: false

In Profiling mode, records maximum time for:

  • Prepare
  • Refresh
  • Solve
  • Reconciliation
  • Maintenance

This adds timing calls around individual work steps. Disable during normal play.

Verbose Logging

  • Default: false

Enables detailed per-piece Observe-mode warnings. This can produce significant log volume in large locations and should remain disabled outside targeted debugging.


Recommended Profiles

Normal gameplay

[0 General]
Integrity Mode = Replace
Lock Configuration = true

[1 Performance]
Work Budget Milliseconds = 2
Spatial Cell Size = 4
Maximum Island Nodes = 100000
Solve Debounce Milliseconds = 150
Active Area Reconcile Seconds = 180
Require Initial Stable Graph Before Replace = true
Maximum Pooled Node Lists = 2048
Maximum Retained Node List Capacity = 16
Maximum Pooled Spatial Cell Lists = 2048

[2 Contacts]
Support Probe Expansion = 0.15
Maximum Overlap Results = 4096

[3 Materials]
Material Balance Preset = VanillaCompatible

[4 Networking]
Write Support To ZDO = true
Network Absolute Write Epsilon = 0.01
Network Normalized Write Epsilon = 0.0025
Ownership Recheck Seconds = 15
Maximum Support ZDO Writes Per Frame = 32
Release Vanilla Support Cache (Experimental) = false
Fallback To Vanilla On Error = true

[9 Diagnostics]
Runtime Diagnostics Level = Off
Enable Information Logging = false
Statistics Interval Seconds = 0
Log Idle Statistics = false
Idle Heartbeat Seconds = 0
Detailed Stage Timing = false
Verbose Logging = false

Observe validation

Use the normal profile, then change:

Integrity Mode = Observe
Runtime Diagnostics Level = Summary
Enable Information Logging = true
Statistics Interval Seconds = 10

CPU benchmark

Use the included BENCHMARK-CONFIG-0.3.7.ini and the same world save, position, camera direction, weather conditions, and location for each run.

Perform separate full game restarts for:

  1. Vanilla
  2. Replace with cache release disabled
  3. Replace with diagnostics disabled for real gameplay overhead
  4. Optional memory test with delayed cache release enabled

Benchmarking Large Locations

A visually large building is not automatically a useful benchmark. Record the graph size from profiling diagnostics:

  • nodes
  • edges
  • anchors
  • active spatial cells
  • replacement hit rate

A generated Ashlands ruin with several thousand nodes and tens of thousands of edges is a suitable stress location.

Static test

  1. Finish location generation.
  2. Stand in the same place and face the same direction.
  3. Wait at least 60 seconds for warm-up.
  4. Record 120 seconds.
  5. Compare wearUpdater, vanillaSupport, and lookup timings.

Dynamic test

Repeat the same sequence in each mode:

  1. Place 50 mixed stone and wood pieces.
  2. Wait 30 seconds.
  3. Remove the same supporting pieces.
  4. Allow the same section to collapse.
  5. Wait for all queues to settle.
  6. Teleport away and return.

Whole-game FPS can be limited by the GPU, rendering, AI, particles, or world generation. The most direct CPU comparison is the time spent in WearNTearUpdater and UpdateSupport.


Compatibility and Safety

Balrond Better Build patches:

  • WearNTear.Awake
  • WearNTear.OnPlaced
  • WearNTear.OnDestroy
  • WearNTear.ClearCachedSupport
  • WearNTear.UpdateSupport
  • WearNTearUpdater.Update
  • ZNetScene.Awake

Mods patching the same methods can affect patch order or suppress expected lifecycle notifications. The periodic reconciliation exists as a safety net, but complete compatibility cannot be guaranteed with every structural, building, or networking overhaul.

When reporting compatibility problems, include:

  • Valheim version
  • Balrond Better Build version
  • BepInEx log
  • Full mod list
  • Current config
  • Whether the problem occurs in Vanilla, Observe, or Replace
  • Whether experimental cache release is enabled

FAQ

Does the mod change building limits?

With VanillaCompatible, the goal is to preserve current material behavior while replacing how support is calculated and cached. Forgiving, Generous, and Custom intentionally change building limits.

Why does a piece sometimes use Vanilla in Replace mode?

A node falls back while it is being prepared, refreshed, or solved. This avoids returning stale support during placement, destruction, streaming, or terrain changes. Once ready, replacement resumes automatically.

Why does Replace say Armed when there are zero nodes?

An empty graph has no unready nodes and is therefore safely armed. Nodes will be registered when a relevant WearNTear object enters the active area.

Will disabling logs improve performance?

Yes, especially in large locations. Formatting large reports, enumerating nodes for summaries, timing hot paths, and writing console output all add overhead. Normal gameplay should use diagnostics Off, information logging false, and interval 0.

Does the mod currently reduce memory?

The graph itself uses memory, but bounds the largest reusable list pools and trims oversized pooled lists. Leaving a world clears those pools. Experimental delayed Vanilla cache release can reclaim additional support-cache memory, but should be tested carefully because a later fallback may rebuild that data.

Should I enable experimental cache release?

Not immediately. First validate ordinary Replace through building, collapse, teleportation, save/reload, and multiplayer ownership changes. Then test cache release on a copied world with profiling enabled. Start with the default 60-second stability delay and cooldown.

Does every client need the mod?

For synchronized multiplayer behavior and predictable structural results, install the same version on the server and all clients. ServerSync enforces synchronized gameplay settings when configuration locking is enabled.

Why does a generated location create many anchors?

Generated ruins often overlap terrain or static world geometry. Anchored nodes receive maximum support. Version 0.3.7 compresses their inbound graph data and stops scanning once a valid anchor is found.


Community and Support

Thunderstore development is made possible with ads. Please consider making an exception to your adblock.