You are viewing a potentially older version of this package. View all versions.
RAGEmedia-AntTrails-1.2.2 icon

AntTrails

Footfall slowly wears dirt paths into the world; heavy traffic cobbles them to stone.

Date uploaded 2 weeks ago
Version 1.2.2
Download link RAGEmedia-AntTrails-1.2.2.zip
Downloads 1062
Dependency string RAGEmedia-AntTrails-1.2.2

This mod requires the following mods to function

denikson-BepInExPack_Valheim-5.4.2350 icon
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.2350
ValheimModding-Jotunn-2.30.2 icon
ValheimModding-Jotunn

Jötunn (/ˈjɔːtʊn/, 'giant'), the Valheim Library was created with the goal of making the lives of mod developers easier. It enables you to create mods for Valheim using an abstracted API so you can focus on the actual content creation.

Preferred version: 2.30.2

README

AntTrails

Walk somewhere often enough and the ground remembers.

AntTrails watches where players actually walk and slowly wears the terrain down into dirt paths — no hoe, no stamina, no materials. Routes that see heavy traffic over a long time have a small chance of cobbling over into stone. Routes that fall out of use fade back toward bare ground.

The result is a world that records how it has been lived in: desire lines between a base and the nearest copper vein, a worn ring around the smelter, a road to the boat that got wider the summer everyone was raiding.

Who needs to install this

Every player and the server, and this is enforced. This writes to the shared terrain paint mask, which is persisted in the world save and replicated to every peer. The server keeps every wear counter and decides what each tile should look like; clients report where they walked and paint the terrain they own, because on a dedicated server the server itself has no terrain loaded near a player. Both halves of that loop need the mod, so a peer without it is refused at connect rather than silently desyncing.

Config values that change behaviour are admin-only and pushed from the server, so everyone plays by the same numbers.

How it works

Terrain in Valheim carries a per-square-metre paint mask with separate dirt, cultivated and paved channels. The hoe slams the dirt channel to full in a 2 m circle. AntTrails instead nudges it upward a little at a time, so a path fades in rather than appearing:

Traffic on one 1×1 m tile What you see
A few crossings Faint scuffing, grass still there
Halfway to the threshold Grass clears; visible bare track
Threshold reached (StepsToPath, default 25) Full dirt path
Very heavy lifetime use (StoneSteps, default 400) Small per-crossing chance of stone

Crossings from all players pool together — four people walking a route wear it four times as fast.

Your position is sampled a few times a second and every tile on the line between two samples is credited too, so a route sprinted at full tilt wears exactly as evenly as one strolled. The trace follows where you actually put your feet, which means a route walked loosely spreads its wear over a corridor a couple of metres wide rather than concentrating it into one line.

Losing a path

Progress on an unfinished tile leaks away continuously, at a flat StepsToPath ÷ FormationWindowDays per in-game day — about two crossings a day at the defaults, one every quarter hour of real time.

That makes formation a contest of rate rather than of total. A tile crossed less often than it leaks never gains ground at all, however long you persist; a tile crossed twice that often wears through in eight or nine in-game days. So the route between your base and the copper vein you have been working all evening settles in, and the one-off detour you took to a swamp last week leaves nothing behind.

A finished path fades far more slowly, taking RevertDays (default 30) of neglect to sink to ResidualTrace (default 0.3) — a faint permanent scar, below the threshold where grass regrows. Old routes stay legible forever unless you set ResidualTrace to 0.

Stone is terminal. It never decays. Remove it with a hoe or pickaxe like any other terrain.

What it will not touch

  • Cultivated soil — walking through a turnip field never paves it.
  • Existing stone, whether a player laid it or AntTrails did.
  • Inside workbench and ward range, while RespectBuildPrivilege is on (the default). Turn it off if you want trails to form through your settlement too.
  • Anything you are swimming through, standing on a built floor over, or Ashlands lava.

Standing still costs nothing: a tile only counts when you enter it, so idling at a workbench does not bore a hole in the ground.

Configuration

BepInEx/config/com.ragemedia.anttrails.cfg. Gameplay values are admin-only and server-synced; sampling rate and logging are local to each client.

Key Default Meaning
Enabled true Master switch. Existing terrain is left as-is when off.
StepsToPath 25 Crossings to fully wear one tile.
FormationWindowDays 12 Days of neglect to lose all unfinished progress.
RevertDays 30 Days of neglect for a finished path to fade to the floor.
ResidualTrace 0.3 Permanent floor a faded path keeps. 0 lets paths vanish.
StoneSteps 400 Lifetime crossings before stone becomes possible.
StoneChance 0.01 Per-crossing chance of stone once eligible.
RespectBuildPrivilege true Skip tiles inside workbench/ward range.
FlushIntervalSeconds 5 How often paint changes are pushed to terrain.
DecaySweepSeconds 60 How often loaded tiles are re-checked for decay.
SampleIntervalSeconds 0.25 How often this client samples its own position. Local.

A note on the network

Valheim serialises a zone's entire terrain blob every time any part of it is painted, and replicates that to all peers. Painting once per footstep would be ruinous, so AntTrails accumulates changes and flushes them in batches, one message per zone per flush. Raising FlushIntervalSeconds trades responsiveness for bandwidth; lowering it does the reverse.

Wear data

Counters live in BepInEx/config/AntTrails/<worldname>.trails on the host, saved alongside the world. Deleting it resets progress but does not touch terrain — paths already painted stay painted.

Building from source

Requires the .NET SDK and a Valheim install. The mod compiles against the game's own assemblies plus the BepInEx and Jotunn DLLs from a mod-manager profile, so that what it is built against is exactly what loads at runtime.

cp Environment.props.example Environment.props   # then edit the paths
dotnet build -c Release

The DLL lands in bin/Release/AntTrails.dll. Copy it into your profile's BepInEx/plugins/AntTrails/ to test.

Environment.props is machine-specific and deliberately untracked.

Requirements

License

MIT.

Source

https://github.com/egaroib/Valheim-AntTrails

CHANGELOG

Changelog

1.2.2

  • Changed the required Jotunn version to 2.30.2, matching servers on the latest Jotunn

1.2.1

Arriving at a busy base no longer spawns a crowd of terrain compilers

Walking into someone else's base produced a burst of vanilla's "Found another terrain compiler in this area, removing it" warnings -- a hundred of them in eight seconds on a heavily built, heavily hoed base -- and lag to match.

Every zone is meant to hold exactly one terrain compiler. Vanilla's Heightmap.GetAndCreateTerrainCompiler finds the existing one through TerrainComp.s_instances, which a compiler joins in its own Awake. A zone's heightmap is built the moment the zone spawns, but the compiler ZDO that goes with it is instantiated by ZNetScene some frames later -- ten objects a frame outside a loading screen. AntTrails resolved a compiler for every tile in an incoming paint batch through that create-if-missing helper, so any tile resolved inside that window found nothing and spawned a second, empty compiler: a replicated ZDO plus five arrays of (m_width + 1) squared, including a 4225-entry colour mask. Vanilla then destroyed it when the real compiler awoke, which is what the warning was announcing. Arriving somewhere with a large backlog of pending tiles did this once per tile per heightmap.

The ownership check that was supposed to gate all of this ran nine lines too late -- the object had already been created by the time the mod decided it had no business writing there. Tiles are now resolved without creating anything, and a compiler is only made once ZNetScene reports every object in the area already has an instance. Zones that have genuinely never been terraformed -- where new trails form -- still get one made for them, because there is no compiler ZDO for them to be waiting on. Tiles skipped in the meantime are left unacked, stay the server's problem, and are offered again once the area settles.

This was most visible on bases with hand-laid hoe paths, which is a place with both a lot of built objects streaming in and a large backlog of tiles the server wants painted. Those tiles were then mostly no-ops at the paint stage, so the whole cost was being paid to change nothing.

Resolution is also now cached per heightmap for the duration of a batch, instead of rescanning every live compiler once per tile.

1.2.0

Hoe paths are no longer erased by walking on them

Walking a path a player had laid with a hoe wiped it out, and the grass and foliage came straight back — within a second or two, because the mod kicks the clutter system after every paint.

Vanilla decides whether grass may grow on a tile with Heightmap.IsCleared, which reads the paint mask's red channel as a hard threshold at 0.5 and ignores the vegetation alpha entirely. A hoed path is red 1.0. AntTrails tracked its own wear from zero and wrote the result over that channel unconditionally, so a few crossings of a fresh route replaced the player's 1.0 with something like 0.1 — under the threshold, so the tile stopped counting as cleared and the grass system reclaimed it. Nothing about this was specific to dedicated servers; it simply could not happen before 1.1.0, when servers painted nothing.

The server now tells each client what it last asked that tile for, so the client can tell its own paint apart from anyone else's. Ground darker than that was darkened by someone else — a hoe, or another mod — and is treated as a floor: AntTrails may darken a tile further, never lighten one it did not darken. Decay is unaffected, because on the mod's own trails the ground tracks what it last sent and no floor applies.

Player-laid paths now also take part in the simulation rather than fighting it. Crossings were always counted on them; what changes is that the count now leads somewhere, so a hoed road that genuinely gets used will eventually cobble itself to stone.

Also

  • A paint that would not change what is on the ground is skipped before it reaches TerrainComp.Save, so a tile held at a player's value no longer re-serializes the zone's terrain blob and resets the grass every time the wear model creeps past its epsilon.

Upgrading

The paint message carries one extra value per tile, so server and clients must both be on 1.2.0. This is a minor bump rather than a patch on purpose: version strictness is set to minor, which compares only major and minor, so a 1.1.x peer would have been let through the check and then misread every paint batch.

Existing .trails files load unchanged — the save format is untouched, so wear counters, formation progress and stone upgrades all carry over.

1.1.0

Trails now form on dedicated servers

On a dedicated server trails were counted but never appeared. The server owns the wear counters, and it was also trying to paint the terrain itself — which it cannot do. A dedicated server has no local player, so ZNet's reference position stays at the world origin, and ZoneSystem only builds live zones around that point. Peers get ghost zones, whose terrain objects are destroyed the moment they are generated. So the server had no Heightmap and no TerrainComp anywhere near a player, found nothing to paint, and deferred every tile silently, forever.

Painting has moved to the peer that actually has the zone loaded. The server still owns every counter and decides what each tile should look like; it now offers that to the clients near the tile, and each client paints the terrain it owns and reports back what it applied. A tile is recorded as painted only when a client confirms it — previously the server assumed a dispatch had succeeded, so a failed paint was indistinguishable from a painted trail.

Host-and-play sessions are unaffected in behaviour; the host simply plays both roles.

Decay now follows players, not the server

The decay sweep used ZoneSystem.IsZoneLoaded, which on a dedicated server describes the zones at the world origin rather than the ones anyone is standing in. It now sweeps zones near connected peers, which also catches a zone up after a player returns to it — work that TerrainComp.Awake does for a host but never does on a dedicated server.

Also

  • The dirty-tile backlog is capped, so a server with nobody in range no longer accumulates tiles for the life of the session.
  • Verbose logging now says when tiles are dirty but no peer can paint them, instead of going quiet — the exact condition that made the original bug invisible.

Upgrading

The wire protocol changed, so server and clients must both be on 1.1.0. Version strictness is set to minor, so a mismatched peer is refused at connect rather than misbehaving. Existing .trails files load unchanged.

1.0.0

Valheim 1.0 support

The 1.0 update renamed or reshaped three of the game APIs AntTrails depends on — the world name it keys save data on, the zone identifier used to decide which tiles are loaded, and the terrain rebuild call it makes after painting. Rebuilt against 1.0.7 (Unity 6). This release does not run on 0.221.x, and 0.2.x does not run on 1.0.

Existing trails survive the update. The world name the game hands out is unchanged in value despite the rename, so BepInEx/config/AntTrails/<worldname>.trails is found and loaded exactly as before. Wear counters, formation progress and stone upgrades all carry over.

Dependencies

BepInExPack 5.4.2350 and Jotunn 2.30.0.

Note for servers

The minor version is part of the mod's network compatibility check, so 0.2.x clients cannot join a 1.0.0 server or vice versa. Everyone updates together.

0.2.0

Retuned formation, so that paths actually form

The old defaults could not produce a path in ordinary play. Formation progress leaks at a flat StepsToPath / FormationWindowDays per in-game day, which at 60 and 4 meant a tile shed a crossing every two real minutes. Unless you re-crossed the same square metre more often than that, its progress sat at zero forever, however many hours you spent on the route — a five-minute round trip to a mine never stood a chance. Formation was a contest of rate, and the rate was set past what walking anywhere can produce.

Setting Old New
StepsToPath 60 25
FormationWindowDays 4 12
StoneSteps 1200 400
StoneChance 0.004 0.01

Break-even is now one crossing every quarter hour of real time rather than every two minutes, and a route you keep using wears through over a few hours of play. Stone needs roughly 500 lifetime crossings on a tile instead of about 1450, which no tile was ever going to reach — the busiest ground in any base sits inside a workbench radius the mod deliberately skips.

Updating will not change settings you already have. BepInEx writes the config file the first time the mod runs and never overwrites it afterwards, so an existing BepInEx/config/com.ragemedia.anttrails.cfg keeps the old values. To take up the new tuning, either edit those four keys to the values in the table or delete the file and let it regenerate. On a dedicated server, edit the server's copy: these keys are admin-only and pushed out to clients.

Wear is now traced between position samples

The client sampled its position four times a second and credited only the tile underfoot. At a run that is more than a metre of travel per sample, so consecutive credited tiles were not even adjacent: crossings went missing and trails came out dotted rather than continuous. Each sample now credits every tile on the line back to the previous sample, so a route wears the same whether you stroll it or sprint it. Eligibility — farmland, lava, build privilege — is checked at each tile's centre, where the wear actually lands.

Fixed

  • The fallback day length used when the game's own value is unavailable was 1200 seconds against an actual 1800, running decay 50% fast for as long as it applied.

Note for servers

The minor version is part of the mod's network compatibility check, so 0.1.x clients cannot join a 0.2.0 server or vice versa. Everyone updates together.

0.1.2

  • Added an MIT license.
  • Set website_url in the manifest so the Thunderstore listing links to the source repo.

No functional or behavioural changes; the plugin itself is identical to 0.1.1.

0.1.1

  • Widened the allowed range on StepsToPath, RevertDays, and StoneSteps. The previous minimums (5, 1 day, and 50 respectively) were arbitrary and sat above the values needed to observe path formation, decay, and the stone upgrade inside a single play session.

0.1.0

  • Initial release.