You are viewing a potentially older version of this package. View all versions.
Sarkastic_gg-Resource_Regrowth-0.8.3 icon

Resource Regrowth

Server-side BepInEx plugin for Valheim 1.0 servers: brings back surtling cores, chest loot, monsters, beehives, crypt iron, cave items, terrain and whole zones in areas left alone. Vanilla clients. Recommended with Dedicated_Simulation.

Date uploaded 3 days ago
Version 0.8.3
Download link Sarkastic_gg-Resource_Regrowth-0.8.3.zip
Downloads 38
Dependency string Sarkastic_gg-Resource_Regrowth-0.8.3

This mod requires the following mods to function

denikson-BepInExPack_Valheim-5.4.2351 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.2351

README

Sarkastic.gg Resource Regrowth

version: 0.8.3 players: vanilla clients Valheim: 1.0 BepInEx: 5.4.2351

Source code · Report a bug · Changelog · Dedicated Simulation

Join us on Discord Support us on Patreon

A server-side BepInEx plugin for Valheim 1.0 dedicated servers. It brings one-time world content back once an area has been left alone for a while:

  • Surtling core stands get their core back.
  • Treasure chests (never player-built ones, and never one holding something of a player's) are restocked with fresh loot, whatever was left in them replaced.
  • One-time creature spawners (dungeons, camps, caves) spawn their creature again.
  • A location regrows as a whole: a dungeon with its entrance, a camp, a village or a ruin comes back all at once -- every core, every creature and every chest in it.
  • Terrain that players dug, raised, levelled or paved slowly returns to the land's own shape, except around player bases and wards.
  • Location objects (off by default): destroyed objects a location or village generated -- wild beehives in abandoned houses, for example -- are put back exactly where they stood. A muddy scrap pile in a sunken crypt (mudpile2, add it to Prefabs) is one too: the iron comes back with the crypt's chests and creatures, and what is left of the pile that was hit goes with it.
  • Zones (off by default): a zone players have been in is generated again by the game itself once nobody has been near it for three days -- trees, rocks and ore deposits, bushes, pickables, the location with its buildings, chests, creatures and dungeon, and the ground -- as if no player had ever been there. Never at a base (a workbench); players' things stay as they are.

Players need nothing: vanilla clients work. The plugin depends on BepInEx and nothing else. It patches one game method, and only with Zones switched on (see Zones).

Recommended with Dedicated Simulation (Sarkastic_gg/Dedicated_Simulation, GitHub), a fork of Serverside Simulations by ddormer that keeps the world simulated on the server. This plugin works on its own, but the two are made to run together: the zone reset generates a zone the way Dedicated Simulation does.

How it works

Everything handled here stays in the world when it is used up, so regrowing it only changes the object's data. The plugin deletes and creates no objects.

What Depleted when Regrown by
Surtling core stand the core was taken (picked) setting picked back to false
Treasure chest vanilla filled it once, and it is now empty or a player has been near it since it was last restocked replacing its contents with fresh loot from the chest's own loot table, as vanilla fills it when the chest is first generated
One-time spawner its creature is gone clearing the spawned link; vanilla spawns again the next time a player loads the area
Terrain (a zone's _TerrainCompiler) any vertex of the zone's heightmap is modified or painted a step every StepHours: every height change outside a protected area is divided by Divider (1.7) and dropped once below MinDelta; paint goes back to nothing once the height under it is back, except paved and cultivated ground. The data is written in the game's own format; loaded terrain reloads it and every client rebuilds the ground.

Location objects are the one exception to "no object is created": a destroyed beehive is gone from the world, so it is created again. Where it stood is known exactly, not guessed:

  • every location the world generated keeps a record of its position, rotation and seed, and every village or camp keeps the position and rotation of each of its buildings;
  • the object's place follows from the location's or building's layout, the way the game placed it;
  • objects that only spawn by chance are decided by replaying the game's own roll from that seed, so only places that really had one count.

Checked on a live world: of 169 beehive places the replay said 47 had a hive, and all 29 hives still standing were on exactly those places (same height to the centimetre), none anywhere else. A hive hangs under the roof of its house; when the pieces of the house that held it are gone (pulled down by players), the hive is not put back, so nothing floats in the air.

A pile or rock that is hit does not vanish at once: the game replaces it with its fractured remains (<name>_frac), which are what is mined. So when an object is put back, the remains of it within 1.5 m go (ClearRemains), or it would stand twice. Checked on a live world copy: a sunken crypt had 301 pile places, the replay said 174 had a pile, 162 stood whole, 12 were gone -- and there were exactly 12 fractured remains; 11 were put back at their own places (the twelfth had lost a gate that held it) and 11 remains went, none of the new piles on another. A base on the surface does not hold back what comes back inside a dungeon (5000 m up), nor does a tombstone down there hold back the surface above it.

Whether a player took everything from a chest, some of it or nothing cannot be told from the chest, so a chest counts as used once a player has been near it; when its time comes it is emptied and filled afresh, partly looted or not.

A location regrows as a whole ([Locations] Together). Every object belongs to the location the world generated it with: inside a dungeon (5000 m up) to the dungeon its generator built -- rooms lie within about 60 m of it -- and to the location at the same spot on the surface, so a burial chamber's interior and its entrance are one; a cave whose interior comes whole with the location (troll and bear caves) by its interior radius; on the surface to the location whose ground it stands on. Each used-up object keeps its own clock, and as soon as one of them has waited its category's AfterHours, everything used up in the location comes back together, and every chest in it is restocked: a burial chamber whose cores were taken 10 hours ago returns whole, chests and draugr included. With Together = false each object regrows on its own.

Every CheckIntervalMinutes the plugin scans the world. A location (or a lone object) regrows only when all of these hold:

  • one of its objects has been used up for its category's AfterHours;
  • no player has been near any of it for IdleHours;
  • none of it lies within PlayerBuildRadius of a player-built piece or tombstone;
  • none of it is in use: no connected player owns it, and the server does not have it loaded. Dedicated Simulation, for example, loads the zones around players on the server.

A scan of a large world (165,000 objects) takes about 15 ms of work, spread over about 40 frames.

Zones

Vanilla never brings back a felled tree, a mined copper or tin deposit, a stone tower or a house players pulled down. With [Zones] Enabled, a zone (64 m square) that a player has been in or next to is, once nobody has been near it (PresenceRadiusZones) for IdleHours (72), generated again by the game's own zone generation, the way Dedicated Simulation generates the zones around players (ZoneSystem.SpawnZone, ghost mode). Every object the game makes takes the place of the old one of its kind standing there, which goes; what is left over of what only the zone itself makes -- vegetation, stumps and logs, wild creatures, items lying about, the record of what was done to the ground -- goes too. So trees, rocks and ore deposits, bushes, pickables, the location with its buildings, chests, spawners and dungeon come back. Measured on a copy of a live world against a fresh world with the same seed: 860 of 916 zones without a location came out exactly as first generated, the rest with a few trees or rocks elsewhere (the game decides placement partly by what colliders are around at that moment).

A location comes back the way round it was: the game draws its rotation from an unseeded random number when it first places it, so the rotation is read from the location's own record before the zone is cleared and given back when it is placed again (a patch of ZoneSystem.SpawnLocation, the only game method this plugin touches). With the same rotation its dungeon gets the same seed and the same rooms. Because old objects are matched to what the game made object by object, a location or dungeon that reaches over the zone's edge (a boar runestone's spawners, a crypt's rooms) is replaced there too, and a neighbour's objects reaching into the zone stay.

Players' things stay exactly where they are: pieces they built (also portals, beds, crops), tombstones, ships and carts, items a player has carried (an item remembers having been in a bag), tamed creatures, and the world's chests, barrels and stands holding something of theirs (the old one stays, the game's new copy goes). Beside a piece they built or a tombstone nothing changes -- within 4 m for trees, rocks, buildings and chests, 2 m for smaller things, and wherever the colliders of a big rock, deposit or tree reach within 2 m of one, the game's new copies go and the old ones stay -- so no tree grows through a wall, nothing they kept by their walls goes, and a mountain rock (its stone covers the ground up to 23 m from its centre) does not come back over a chest built where it was mined out. A zone with their pieces in it keeps its ground record (Terrain regrowth deals with it, with its own protections).

Never generated again:

  • a zone with a workbench in it or within PlayerBuildRadius (48 m) of it: someone's base. Of players' things only a workbench keeps a zone as it is;
  • a protected location (ProtectedLocations: the start temple with the guardian stones, boss altars, traders, Hildir's dungeons) and every location the game places only once; nothing left over within a protected location's reach in a neighbouring zone goes, and no trader;
  • a zone the server has loaded or next to one it has, or anything in it a connected player owns;
  • anything in the first GraceMinutes (30) after a start: who was near while the server was off is not known.

Fields, paved roads, dirt paths, dug and raised ground and the trees players planted go with the reset unless a workbench is near: whoever wants a road or a field kept puts a workbench by it. A zone with players' pieces in it (crops are pieces) keeps its ground record, so a field with crops on it stays a field.

If the game cannot generate the zone now, or throws while doing it, nothing old has been deleted yet: whatever the attempt made is removed, the zone is marked generated and its location placed again, and after an exception zone resets stop until the next start.

At its first run every zone generated so far counts as visited -- what players did there before cannot be told -- and no zone is generated again before IdleHours from then. Presence is kept for the longer of the two idle times, also while Zones are off, and a zone without a record counts as seen at the time from which presence is known completely, so switching Zones on later or raising IdleHours never makes a recently visited zone due. At most PerPass zones per pass, longest idle first, one per frame (each a few milliseconds to a few tens); a zone that cannot be done now waits an hour. DryRun (on by default) only logs which zones would be generated again and what they hold.

Terrain protection

Ground within the radius of a player base object -- anything the game itself treats as a base when it decides where creatures may not spawn (a PlayerBase effect area: workbench, forge, stonecutter, beds, fires ...) -- or of a ward is left as it is; the radius is the object's own (ProtectMultiplier scales it). A base that is gone, say a workbench broken by creatures, protects nothing any more, and the land returns. ProtectPiecesRadius (0) adds a radius around every player-built piece and tombstone for those who want roads and fields kept whole; paved and cultivated paint is kept anyway (KeepPaved, KeepCultivated), only its height returns. The log lists the protecting kinds and their radii at start.

Time

All times are real hours (wall clock, UTC). They keep counting while nobody is online and while the server is stopped. The world clock would not work here: on a dedicated server it only runs while a player is online.

The plugin cannot know what happened before it was installed. Both clocks start at its first run on a world, so nothing regrows until IdleHours and AfterHours have passed since then.

After a pass that regrew anything the world is saved right away (the same call as the autosave), so a crash cannot lose the regrowth while keeping the reset clocks.

What it remembers is kept in <world>.regrowth.txt next to the world save. That file records when players were last near each zone, and since when each object has been depleted.

Objects are identified by prefab and position, because the game hands out new object ids on every world load.

Limitations

  • On a server where players own the objects around them (no server-side simulation), a spawner reset may not reach a player who stays connected the whole time and already had that area loaded in the same session. The game only sends a link, never its removal, so that player's game still thinks the creature exists. The creature appears once they reconnect. With Dedicated Simulation the server owns these objects, so this does not happen there.
  • A core stand or chest that some machine currently has loaded is left for a later pass.
  • Location objects: the first scan after a start reads the layouts of the locations and village buildings the world has (a few hundred prefabs, loaded in the background through the game's own loader: measured about 0.3 s of work over 45 s, no frame over 100 ms); later scans only read new ones. A location object's own zone must not be loaded, like everything else.

Install

Copy SarkasticGG_Resource_Regrowth.dll to BepInEx/plugins/ on the server and start it once. That creates BepInEx/config/sarkasticeu.resource_regrowth.cfg.

It starts in dry run: it only logs what it would regrow. Watch the log for a few passes, then set DryRun = false. The config file is re-read before every pass, so DryRun, the delays and the logging amount change without a restart; Enabled, the prefab lists and the exclusions are applied at startup.

Configuration

Section Key Default Meaning
General Enabled true
General DryRun true only log, change nothing
General CheckIntervalMinutes 10 real minutes between scans
General LogDetailsPerPass 20 objects logged individually per category and scan
Safety IdleHours 5 real hours since a player was near the zone
Safety PresenceRadiusZones 2 a player counts as near all zones (64 m) within this many of their own
Safety PlayerBuildRadius 48 metres around player-built pieces and tombstones that are never touched
Locations Together true a location regrows as a whole: once one thing in it is due, every core, creature and chest in it comes back
SurtlingCores Enabled / AfterHours true / 10
SurtlingCores Prefabs Pickable_SurtlingCoreStand hide-when-picked, non-respawning pickables to restore
TreasureChests Enabled / AfterHours true / 24 hours after a player was first near the chest (or it was seen empty) since it was last restocked
TreasureChests ExcludePrefabs chest prefabs never to refill, e.g. TreasureChest_meadows_buried
DungeonMonsters Enabled / AfterHours true / 24
DungeonMonsters ExcludePrefabs spawner prefabs never to reset
LocationObjects Enabled / AfterHours false / 48 put back destroyed objects of locations and villages (needs a restart)
LocationObjects Prefabs Beehive which ones; only world-generated objects are ever put back
Zones Enabled false generate visited zones again as the world first made them (needs a restart)
Zones DryRun true only log which zones would be generated again
Zones IdleHours 72 real hours with nobody near before a zone is generated again
Zones PerPass 8 most zones per pass
Zones GraceMinutes 30 minutes after a start before any zone is generated again
Zones ProtectedLocations StartTemple, boss altars, traders, Hildir's dungeons never generated again (also every location placed only once)

Build

Requires the .NET SDK and a Valheim dedicated server with BepInEx installed (for the reference assemblies). Point VALHEIM_DEDI_INSTALL at it, or pass -p:ValheimServerDir=...:

VALHEIM_DEDI_INSTALL=/path/to/valheim_server dotnet build src/ResourceRegrowth.csproj -c Release

The DLL ends up in bin/Release/.

CHANGELOG

Changelog

[0.8.5] - 2026-10-13

Added

  • [Zones] RefreshNow (off): a one-off, for when the owner wants everything that nothing protects back at once. In the first pass after a start every visited zone nobody has been near for the last 30 minutes is generated again -- without IdleHours, GraceMinutes and the PerPass limit -- and the ground of every modified zone is brought back at once, paint too, whatever KeepPaved and KeepCultivated say. What a workbench or a ward protects, protected locations and the 4 m around players' pieces stay as they are. The setting switches itself off in the config when the pass is done, so the usual clocks apply again; it needs [Zones] Enabled and no DryRun.

[0.8.4] - 2026-10-12

Changed

  • Thunderstore package only: the plugin is licensed under the MIT licence (LICENSE, in the repository and in the package); the README says so. The plugin is the 0.8.0 DLL, unchanged.

[0.8.3] - 2026-10-12

Changed

  • Thunderstore package only (Sarkastic_gg/Resource_Regrowth): the README has badges and links (Discord, Patreon) and the package is listed in the "Deep North Update" section. The plugin is the 0.8.0 DLL, unchanged.

[0.8.2] - 2026-10-12

Changed

  • Thunderstore package only: the README and the description say that the plugin is recommended with Sarkastic_gg/Dedicated_Simulation. The plugin is the 0.8.0 DLL, unchanged.

[0.8.1] - 2026-10-12

Changed

  • Thunderstore package only (Sarkastic_gg/Resource_Regrowth): a new pixel art icon. The plugin is the 0.8.0 DLL, unchanged; a package's icon can only change with a new version number.

[0.8.0] - 2026-10-11

Added

  • [LocationObjects] ClearRemains (on): when a wanted object is put back, its fractured remains (<name>_frac, what the game leaves when a pile or rock is hit) within 1.5 m go with it. With Prefabs = Beehive,mudpile2 the iron scrap piles of sunken crypts come back where they stood, with the crypt's chests and creatures; without the cleanup the pile would stand twice (whole and as pieces to mine).

Changed

  • A player's building or tombstone holds back (PlayerBuildRadius) only what is on the same level: a base on the surface no longer holds back chests, creatures, cores and objects inside the dungeon below it (interiors lie 5000 m up), nor a tombstone inside a dungeon what comes back on the surface above it. Zones with a workbench are still never generated again.

[0.7.2] - 2026-10-10

Fixed

  • [Zones]: a big rock, ore deposit or tree the game makes again no longer comes back over a player's piece standing where it was mined out or felled. Besides the 4 m around every piece (2 m for small things), an object whose colliders' bounds reach within 2 m of a piece now counts as beside it: the game's new copy goes and the old state stays. Measured in the game with rays: of 329 rocks around one mountain spot, 38 cover the ground farther than 4 m from where they stand, a mountain rock up to 23 m. Tested on a copy of a live world with players' things far from any workbench (a chest with items, a sign, a cart, a tombstone, a carried sword on the ground, a tamed wolf, a tagged portal, a chest put 4.9 m from a mined-out mountain rock's centre, inside its collider's bounds): after the reset every one stood where it was with its data unchanged, the zone's ground record kept its bytes, and the rock 0.7.1 brought back there stayed away.

[0.7.1] - 2026-10-10

Changed

  • [Zones]: only a workbench (in the zone or within PlayerBuildRadius) keeps a zone as it is. Cultivated ground, paved ground and the trees players planted no longer do: away from a workbench they go with the reset like the rest of the ground. A zone with players' pieces in it (crops among them) still keeps its ground record.

[0.7.0] - 2026-10-10

Changed

  • A treasure chest holding anything that has been in a player's bag is someone's storage and is never restocked (it used to be emptied and filled afresh like any chest a player had been near).

Added

  • [Zones] (off by default, DryRun on by default): a zone players have been in is generated again by the game itself once nobody has been near it for IdleHours (72): trees, rocks and ore deposits, bushes, pickables, the location with its buildings, chests, spawners and dungeon, and the ground -- as if no player had ever been there. Vanilla never brings back a felled tree, a mined deposit or a house pulled down. In one frame the zone is marked not generated, its location not placed, and ZoneSystem.SpawnZone runs again in ghost mode; every object the game makes then replaces the old one of its prefab standing in its place (within half a metre), in the zone or over its edge, and what is left over of what only the zone itself makes (vegetation, stumps, logs, fractured rocks, wild creatures, birds, fish, items lying about, the ground's record) goes. A location gets back the rotation it had: the game draws it from an unseeded random number, so it is read from the location's proxy (rounded to the game's 22.5-degree step, as the save truncates Euler angles to half a degree) and given back by a prefix on ZoneSystem.SpawnLocation -- the plugin's first game patch, applied only with Zones switched on. Players' things are never deleted and stay where they are (pieces incl. portals, ships, carts and crops; tombstones; items a player has carried; tamed creatures; the world's chests, barrels and stands holding something of theirs -- the old one stays, the new copy goes); beside their pieces and tombstones nothing changes (4 m, 2 m for small things), and a zone with their pieces keeps its ground record. Never generated again: zones with a workbench in them or within PlayerBuildRadius (a base), cultivated ground or paved ground outside the location, zones where players planted saplings, protected locations (ProtectedLocations, plus every location the game places only once, and what of them reaches into a neighbour), zones loaded on the server or next to one that is, and the first GraceMinutes (30) after a start. A generation that fails or throws is undone: nothing old is deleted before the game has made the zone again. At its first run every zone generated so far counts as visited, and nothing is generated again before IdleHours from then; presence is now kept for the longer idle time (also with Zones off) and only moves forward (presencesince in the state); at most PerPass zones per pass, one per frame, a zone that cannot be done now waiting an hour.

Tested on a copy of the live world (9 October) with every zone due at once: 1156 of 1190 zones were generated again, 0 exceptions, about 8 ms of work per zone; 34 were kept (19 at a workbench, 8 fields, 6 protected locations, 1 with players' saplings); all 663 objects of players' stayed exactly where they were (prefab and position to the centimetre); all 263 locations came back with the same rotation and position and all 27 dungeons with the same rooms (the first tries lost five crypts and a troll cave's interior to guessed ownership and reused ZDO objects, and changed three dungeons' rooms through the half-degree truncation -- all fixed before release); zones without a location matched a fresh world of the same seed in 41 of 45 changed cases; objects players had removed came back (rocks, trees, obsidian and copper deposits, beehives, bone piles). A dungeon generation made to throw was undone: the zone and its neighbours stayed as they were and resets stopped. With the defaults, the first run counted all 1190 zones as visited and generated none (72 h to go). A review by three independent readers found that the world's chests holding players' things, trees grown from players' saplings, a failed generation (no undo), a trader reaching into a neighbouring zone, items the world placed but nobody loaded yet (read as carried), presence forgotten while Zones were off, wasted per-pass slots and switching Zones on without the patch were not handled; all fixed above.

[0.6.0] - 2026-10-09

Changed

  • A location regrows as a whole ([Locations] Together, on by default). Players found that a burial chamber gave its surtling cores back after 10 hours while its chests and draugr stayed gone (24 hours, each on its own clock). Every object now belongs to its location -- inside a dungeon to the dungeon its generator built and the location above it, so interior and entrance are one; a troll or bear cave by its interior radius; on the surface the location it stands in -- and as soon as one object's clock has run its category's AfterHours, everything used up in the location comes back at once and every chest in it is restocked. The safety conditions apply to the whole location: nobody near any of it for IdleHours, none of it near a player's build, none of it loaded.
  • Treasure chests are restocked whether they were emptied, partly looted or not touched: whatever is left in them is replaced by fresh loot from their own table. A chest left with a few feathers never came back before. What a player took cannot be told from a chest, so a chest's clock starts when a player is first near it after it was last restocked (or when it is seen empty). Player-built chests are never touched, as before.
  • Dry runs also list the locations still waiting, with what is used up in them and when they are due.

Tested on a copy of the live world (9 October, 19:21) with the live state: the 37 locations with something used up grouped correctly -- burial chambers with their cores, chests and skeletons inside, troll caves, ruins, farms, houses -- and with every wait set to zero 24 locations came back whole: 14 cores, 45 spawners and 33 chests, 14 of them empty and 19 with leftovers, all with fresh loot; the 3 empty chests within 48 m of a player's build stayed empty.

[0.5.1] - 2026-10-07

Changed

  • Renamed to Sarkastic.gg Resource Regrowth: the community moved from sarkastic.eu to sarkastic.gg. The DLL is now SarkasticGG_Resource_Regrowth.dll; delete SarkasticEU_Resource_Regrowth.dll from BepInEx/plugins when upgrading. The plugin GUID, the config file sarkasticeu.resource_regrowth.cfg and the state file are unchanged, and nothing else is.

[0.5.0] - 2026-09-28

Added

  • [LocationObjects] (off by default): destroyed objects that a location or a village generated are put back where they stood -- Prefabs = Beehive, the wild beehives of abandoned houses, bear caves, ruined towers and meadow villages. Unlike the other categories this creates objects. The place is exact: every generated location leaves a proxy with its position, rotation and seed, and every village or camp generator keeps its buildings' positions and rotations; objects that spawn by chance are decided by replaying the game's roll from that seed. Checked on a copy of the live world: 169 hive places, 47 of them with a hive by the replay, all 29 standing hives on those places (0.00 m apart in height too) and none elsewhere. Of the 18 missing, 14 would be put back, 3 lie near player builds and 1 has lost the house that held it -- such a hive is not put back, so nothing hangs in the air (pulling down another house for the test kept that one out too). The put-back hives survived a restart and the server instantiated them where the originals hang, 4.08 m above the floor under the roof. Same rules as the rest: AfterHours (48) since first seen missing, IdleHours, PlayerBuildRadius, and the zone must not be loaded.
  • The first scan after a start reads the layouts of the world's locations and village buildings through the game's own asynchronous loader: about 0.3 s of work over 45 s, no frame over 100 ms (loading them directly cost 9.9 s and frames up to 440 ms). Later scans only read new ones.

[0.4.0] - 2026-09-13

Added

  • [Terrain]: dug, raised, levelled and paved ground slowly returns to the land's own shape once the area has been left alone (IdleHours, then AfterHours after the zone's ground was first seen modified, then a step every StepHours). Each step divides the remaining height change by Divider and drops it below MinDelta; paint goes back to nothing once the height under it is back, paved and cultivated ground excepted. Ground around player base objects (the game's own PlayerBase areas: workbench, forge, beds, fires ...) and wards is left alone by the object's own radius, so a base that creatures broke protects nothing any more. The data is written in the game's format (TerrainComp.Save); verified on a local 1.0.12 server: all 38 modified zones of a copied live world round-trip byte-identically, and a step reduced e.g. 242 to 230 modified vertices with 587 to 230 painted ones, 60 vertices near a base left untouched.