Valheim
Install with App

Details

Latest version
0.4.2
Last Updated
First Uploaded
Downloads
660
Likes
0
Size
198KB
Dependants
ADDatHost Valheim hosting
30% off

๐Ÿ”ญ Dvergr Astrolabe

DVERGR ASTROLABE VERSION SERVER AND CLIENTS

The dvergr do not ask the sun when it will rise. They cut the answer into brass, turn three rings, and the sun โ€” grumbling โ€” keeps the appointment. Every step of the reckoning is written down, because a dvergr who cannot show his working is no dvergr at all.

How long a day takes. How much of it is daylight. How fast the world works.

A vanilla Valheim day is 30 real minutes โ€” 21 of daylight, 9 of night โ€” and everything that grows, smelts, ferments or burns runs at vanilla pace. Dvergr Astrolabe gives you each of those as a dial: the length of a full day in real minutes, how many of them the sun is up and how many it is down, and, separately, how fast production runs.

It works out the day length, the sunrise and sunset points and the clock rate that give exactly what you typed, sets them on the server and on every player's game, and prints every step of the working to the log. The defaults are vanilla, so installing it changes nothing until you turn a dial.


NEW IN 0.4.0

Long days no longer mean a slow world โ€” or a fast one. You choose both.

You It
Set CycleMinutes a full day, sunrise to sunrise, takes that many real minutes
Set DaytimeMinutes and NightMinutes the sun is up and down for exactly that long
Pick a LengthRule decides which length gives way when the three don't add up
Turn ProductionScale crops, smelters, fermenters, fuel and the rest run at that multiple of vanilla โ€” the sun never moves faster for it
Pick a ProductionBasis vanilla pace per real minute whatever the day length, or per game day
Type astrolabe in the F5 console the full working and the live clock of the machine you are on

๐ŸŒŠ WaveSpeed keeps the sea at vanilla pace whatever the clock does ยท ๐Ÿ›ก๏ธ A self-check confirms the game answers with Astrolabe's sunrise and sunset, and names a mod that interferes ยท ๐Ÿ“ Every cfg line explains itself with worked examples ยท โ†ช An older cfg migrates itself, keeping your world's day counter where it is.


BEFORE YOU INSTALL

Ifโ€ฆ Thenโ€ฆ
๐Ÿ”’ you run a server install it on the server and every player's game (a hosted world: the host and every guest). The server and every client must run the same version โ€” the handshake refuses a vanilla client and one on another version. Update everyone together.
๐ŸŽฎ you have Xbox, PlayStation or other crossplay players they cannot install mods, so they cannot join. For them, the older server-only line of Astrolabe is the one to run โ€” with its limits (below).
๐Ÿ“… you change the day length on an existing world the day counter and the time of day jump once. ProductionBasis = GameDays with ProductionScale = 1 never does this.
๐ŸŒ— you run Gamma of Night Lights or another day/night mod turn its day/night cycle off. Astrolabe owns the cycle; two owners flicker the clock.
โœ… you install it and change nothing nothing changes. The defaults are vanilla.

I

Type the day you want, in minutes on the wall clock.

Feel CycleMinutes DaytimeMinutes NightMinutes ProductionScale
Vanilla 30 21 9 1
Long lazy days 60 45 15 1
Long days, busy world 60 45 15 2
Builders' server 120 100 20 1
Horror server 30 10 20 1
Quick test 2 1 1 1

All with LengthRule = FitToCycle and ProductionBasis = RealTime. Edits are picked up within 5 seconds, no restart, and pushed to every connected player.

๐Ÿ“– Read the saga โ€” when the lengths don't add up, and what each one does

CycleMinutes is the full day, sunrise to sunrise (vanilla 30; 0.5 to 1440). DaytimeMinutes is sunrise to sunset โ€” the stretch the game counts as day, when the Day N banner fires and, halfway through, sleeping opens (vanilla 21). NightMinutes is sunset to sunrise, through dusk, the midnight day-counter tick and dawn (vanilla 9). Both from 0.25 to 1440.

LengthRule decides which gives way when daytime + night is not the cycle. Agreeing values give the same answer under every rule.

Rule Cycle Daytime Night
FitToCycle (default) T T x D / (D + N) T x N / (D + N)
DaytimePlusNight D + N D N
CycleMinusNight T T - N N
CycleMinusDaytime T D T - D

FitToCycle keeps the cycle exact and scales the other two, keeping their ratio. A rule that would leave a segment under 15 seconds floors it there and stretches the cycle instead, and the log warns.

The sun's pace depends on the two lengths alone: 180 / DaytimeMinutes degrees a real minute by day (vanilla 8.57) and 180 / NightMinutes by night (vanilla 20). The vanilla night is faster than the vanilla day and stays so at any setting that keeps the 70/30 split; a 45/15 split makes it 12 against 4.

Sleeping still opens in the afternoon โ€” the middle of daytime โ€” and through the night, and still skips to the next sunrise in 12 real seconds whatever the lengths, now aimed at your sunrise, so a pre-dawn sleep never skips an extra day or rewinds the clock.


II

How fast the world works โ€” a dial of its own, never tied to the sun.

Runs at ProductionScale ร— vanilla Runs on the wall clock, untouched
crops and trees ยท smelters, kilns, furnaces, cooking stations ยท fermenters ยท beehives and sap collectors ยท fuel ยท item despawn ยท berry and pickable respawn ยท creature spawners ยท taming hunger, breeding and growing up ยท creature and tame health regeneration ยท trap and ballista rearm ยท snow damage ยท weather and wind changes ยท the short lockout between two sleep attempts raids and random events ยท Rested ยท food ยท comfort
๐Ÿ“– Read the saga โ€” RealTime against GameDays

ProductionScale is a multiple of vanilla: 1 vanilla, 2 twice as fast, 0.5 half (0.01 to 100). ProductionBasis says what 1 means:

  • RealTime (default) โ€” vanilla production per real minute, whatever the cycle length. A crop that took 30 real minutes in vanilla still takes 30 real minutes; on a 60-minute day that is half a day. The game day is stretched to fit.
  • GameDays โ€” vanilla production per game day, the economy of the older server-only line. The day stays 1800 game-seconds and the clock slows or speeds to fit, so on a 45-minute day a crop still takes one day, which is now 45 real minutes.

Raids, events, Rested, food and comfort run on real time, so a longer day gets more raids per game day and a shorter one fewer.


III

The server, the host and every player agree to the game-second.

๐Ÿ”’ Server-synced, locked the server's cfg is the only one that counts; every player adopts it on joining and whenever it changes
โฑ๏ธ One rate everywhere every machine runs the clock at the same speed, so the server's time pushes carry nothing but network jitter โ€” no corrections, at any rate
โ›ต Boats sail untouched at any setting โ€” no pausing near ships, no slams from a jumping sea
๐ŸŒŠ WaveSpeed Vanilla (default): the sea runs on real time and looks and hits exactly as in vanilla ยท FollowClock: the sea follows the game clock, as an unmodded game has it
๐ŸŒ™ Smooth sleep skip SleepSkipPushInterval decides how many steps players see the 12-second night skip in
๐Ÿ•ฐ๏ธ Timestamps stay valid the world clock is never rewound or re-based, so every planted crop, lit fire and running smelter carries on
๐Ÿ“– Read the saga โ€” where it meets the game, and why the sea has its own setting

On every machine, from the same synced settings and the same solver:

  • EnvMan.m_dayLengthSec is set to L when the world loads and whenever the settings change.
  • EnvMan.RescaleDayFraction is replaced by the same function with s and e for its knees.
  • EnvMan.GetMorningStartSec returns day x L + L x s, and EnvMan.SkipToMorning uses s where vanilla hard-codes 0.15. The night is still skipped in 12 real seconds.
  • ZNet.UpdateNetTime adds dt x R to the world clock instead of dt โ€” on the server while anyone is connected, and on each client between the server's pushes.
  • ZNet.GetWrappedDayTimeSeconds, which only the water and the fish read, returns the clock divided by R while WaveSpeed = Vanilla.

The sea. Water time is the game clock, so at ProductionScale = 3 the waves would roll three times as fast, and a storm would move the surface under a hull fast enough for the game to count it as a slam. WaveSpeed = Vanilla feeds the water real time instead, identical on every machine. While the clock runs at vanilla rate the two are the same; changing the rate with Vanilla selected moves the wave pattern once, on every machine at the same moment.

When the day length changes on a running world. The day number is clock / L and the time of day is clock mod L, and the clock is never re-based โ€” doing that would make every timestamp in the world jump by hours. So the first time a world runs with a different L, both shift once: a world on day 277 of 1800-second days reads day 138 at L = 3600. After that everything is consistent again, and the log prints exactly what happened. L changes when CycleMinutes or ProductionScale change under RealTime, or ProductionScale under GameDays; changing only DaytimeMinutes or NightMinutes moves where the sun is right now, not the day number.

New worlds start with the clock at 2040 game-seconds: on an 1800-second day that is day 1, just before sunrise; on a 3600-second day, day 0, just past noon. Cosmetic.


IV

Six steps, with your numbers in, printed every time the settings apply.

Quantity Symbol Where the game keeps it Vanilla
Game-seconds in one day L EnvMan.m_dayLengthSec 1800
Raw day-fraction of sunrise and sunset s, e the knees of EnvMan.RescaleDayFraction 0.15, 0.85
Game-seconds the clock grows per real second R the dt in ZNet.UpdateNetTime 1
๐Ÿ“– Read the saga โ€” the solver, what follows from it, and worked examples

Raw day-fraction is (clock mod L) / L; RescaleDayFraction maps the stretch from s to e onto the visual 0.25..0.75 in which the sun is up and EnvMan.IsDay is true. So daylight lasts (e - s) x L / R real seconds and a whole day L / R.

Given T (cycle), D (daytime), N (night) in real minutes and the production scale P:

  1. Reconcile the lengths so that D + N = T, by LengthRule (table in chapter I).
  2. Daylight share f = D / T. Vanilla 0.7.
  3. Requested clock rate: RealTime: R0 = P ยท GameDays: R0 = P x 1800 / (60 x T).
  4. Day length L = round(R0 x 60 x T) game-seconds โ€” a whole number, because the game stores it as one.
  5. Exact clock rate R = L / (60 x T), recomputed from the rounded L so a day takes exactly T real minutes; the rounding lands on R, by at most 0.5 / L relative, and the log prints the production scale actually realised.
  6. Sunrise and sunset s = 0.5 - f / 2, e = 0.5 + f / 2. Noon stays at raw 0.5 and midnight at raw 0, as in vanilla.

What follows, on every machine:

daylight            =  f x L / R          real seconds  =  60 x D       (exactly D minutes)
night               =  (1 - f) x L / R    real seconds  =  60 x N
full day            =  L / R              real seconds  =  60 x T
production          =  R                  x vanilla, per real minute
                    =  L / 1800           x vanilla, per game day
a vanilla day of work (1800 game-seconds of growth, smelting, fuel)
                    =  30 / R             real minutes  =  1800 / L game days
sun, by day         =  180 / D            degrees per real minute   (vanilla 8.57)
sun, by night       =  180 / N            degrees per real minute   (vanilla 20)

P changes R and L together and in the same ratio โ€” which is why production is a dial of its own: the sky looks identical at ProductionScale = 1 and = 3; only the crops, the smelters and the weather know the difference.

T / D / N / P / basis f R0 L R s / e Per real min Per game day Sun day / night
Vanilla 30 / 21 / 9 / 1 / RealTime 0.7 1 1800 1 0.15 / 0.85 1x 1x 8.57 / 20
Long days 60 / 45 / 15 / 1 / RealTime 0.75 1 3600 1 0.125 / 0.875 1x 2x 4 / 12
Long days, busy 60 / 45 / 15 / 2 / RealTime 0.75 2 7200 2 0.125 / 0.875 2x 4x 4 / 12
Per-day economy 45 / 40 / 5 / 1 / GameDays 0.889 0.667 1800 0.667 0.056 / 0.944 0.667x 1x 4.5 / 36
Horror 30 / 10 / 20 / 1 / RealTime 0.333 1 1800 1 0.333 / 0.667 1x 1x 18 / 9
Rounding 33.3 / 20 / 13.3 / 1.37 / RealTime 0.6 1.37 2737 1.36987 0.2 / 0.8 1.37x 1.52x 9 / 13.5

The last row is step 5 at work: 1.37 x 60 x 33.3 = 2737.26 rounds to 2737, the cycle stays exactly 33.3 minutes, and the realised production scale is 1.36987.

Vanilla is a fixed point. At the defaults the solver returns L = 1800, R = 1, s = 0.15, e = 0.85, and the patched RescaleDayFraction is bit-for-bit the vanilla function. The mod then changes nothing at all โ€” checked by its own test suite and by the self-check in the log.


THE TOOLBOX

First ten minutes: install with a mod manager, or unzip into BepInEx/plugins, on the server and every player โ†’ start the server once โ†’ set CycleMinutes, DaytimeMinutes, NightMinutes and ProductionScale in its cfg โ†’ wait five seconds โ†’ type astrolabe in the F5 console and read the working.

Command Where
astrolabe the settings, every step of the maths, and the live clock F5 console, or the server console a player sees exactly what the server runs them on
๐Ÿ› ๏ธ Check it works

BepInEx/LogOutput.log โ€” on the server at startup and after every edit, on each player's game as the values arrive (their lines say client instead of dedicated server). A 60 / 45 / 15 server:

[Message:DvergrAstrolabe] cycle (startup, no world loaded):
  settings   : CycleMinutes = 60, DaytimeMinutes = 45, NightMinutes = 15, LengthRule = FitToCycle, ProductionScale = 1, ProductionBasis = RealTime
  1 lengths  : FitToCycle: daytime + night as typed = 45 + 15 = 60 = CycleMinutes, nothing to adjust -> cycle 60 real min = daytime 45 + night 15
  2 share    : daylight share f = daytime / cycle = 45 / 60 = 0.75 (vanilla 0.7)
  3 rate     : ProductionBasis RealTime: requested clock rate R0 = ProductionScale = 1 game-seconds per real second (vanilla 1)
  4 day      : day length L = round(R0 x 60 x cycle) = round(1 x 60 x 60) = 3600 game-seconds (vanilla 1800) -> EnvMan.m_dayLengthSec on every machine
  5 clock    : exact clock rate R = L / (60 x cycle) = 3600 / 3600 = 1 game-seconds per real second -> ZNet.UpdateNetTime adds dt x R on every machine
  6 band     : sunrise at raw day-fraction 0.5 - f/2 = 0.125, sunset at 0.5 + f/2 = 0.875 (vanilla 0.15 / 0.85) -> EnvMan.RescaleDayFraction, GetMorningStartSec and SkipToMorning on every machine
  check      : daylight = f x L = 2700 game-s, at R that is 45 real min; night = 900 game-s = 15 real min; full day = 3600 game-s = 60 real min
  production : 1x vanilla per real minute (= R; a vanilla day of work, 1800 game-s, takes 30 real min); 2x vanilla per game day (= L / 1800; one game day holds 2 vanilla days of growth); realised ProductionScale 1 (requested 1)
  sun        : 4 degrees per real minute by day (180 / daytime; vanilla 8.57), 12 by night (180 / night; vanilla 20); the sun's pace depends on the lengths only, never on ProductionScale
[Info   :DvergrAstrolabe] self-check: EnvMan.RescaleDayFraction answers with sunrise at raw 0.125 and sunset at 0.875, as set (1000 samples); EnvMan.m_dayLengthSec = 3600.

With VerboseLogging on, every sunrise and sunset is measured against its schedule, so the log proves the lengths by itself:

[Info   :DvergrAstrolabe] sunset, day 12 (dedicated server): daylight ran 45.00 real min (45 scheduled); night for the next 15 real min.
[Info   :DvergrAstrolabe] sleep: skipping from 46500 to the sunrise of day 13 at 47250 game-s (750 game-s in 12 real s).
๐Ÿ› ๏ธ Long days on an existing world, with no jump

Set ProductionBasis = GameDays and keep ProductionScale = 1. The day stays 1800 game-seconds forever, so the day counter and the time of day never move โ€” at the price of production tracking game days instead of real minutes. Switch to RealTime whenever you want vanilla real-time production; the counter shifts once, and the log says by how much.

๐Ÿ› ๏ธ Coming from the older server-only line
  • Players need the mod now. That is the whole change for them.
  • Your settings carry over. On first start, an old DayMinutes + NightMinutes become CycleMinutes (their sum), DaytimeMinutes and NightMinutes, with ProductionBasis = GameDays โ€” which keeps the 1800-second day, the per-day economy and your world's day counter. The log says so. The old keys stay in the file, ignored; delete them when you like.
  • One visible difference: the old line paced daylight and night at two different clock rates inside vanilla's sunrise and sunset; this one moves sunrise and sunset and runs one flat rate. Production is the same per day and now even across it. The sun's position shifts once.
  • The old limits are gone: no pausing near boats, no catch-up afterwards, no schedule slip on a server where someone is always sailing, no fast-day/slow-night contrast, no 0.2x floor. The settings that managed them are gone with them.
  • Crossplay players still need the server-only line; the CHANGELOG lists its last version.

MULTIPLAYER

Set on the server, for everyone Each machine decides Needs Astrolabe on both ends
the lengths ยท the length rule ยท production ยท the sea ยท the master switch extra logging ยท the self-check ยท on the server, the sleep-skip push rate everything โ€” a vanilla client is refused at the door

โš ๏ธ Versions must match. The handshake compares versions on connection: a vanilla client, or one on another version, gets the game's own "incompatible version" message; a player with Astrolabe joining a server without it is told "DvergrAstrolabe is not installed on the server". In single player your own cfg is the authority; on a player-hosted world, the host's cfg is the server's for everyone who joins. Players need no cfg of their own.


COMPATIBILITY

Mod
โ›” Gamma of Night Lights (shudnal) Turn off its [Day night cycle] section (Enabled = false). Its luminance, fog, sun and moon sections are pure lighting and get on fine. Left on, it writes its own day length every frame and Astrolabe puts its value back every 5 seconds, which flickers the clock โ€” the log names it once per foreign value.
โ›” Any mod that patches EnvMan.RescaleDayFraction or writes EnvMan.m_dayLengthSec The same: a conflict, not a partner, and the log says so. On sunrise and sunset Astrolabe's patch runs last and wins; the self-check confirms it, or reports the other mod's values.
Let It Grow (time flows while empty) Agrees โ€” its patch receives Astrolabe's already-scaled time.
Clock and HUD mods Show the right time: they read the day length and day fraction Astrolabe sets.
Xbox, PlayStation and other crossplay players Cannot join: they cannot install mods.

PatchSelfCheck = false turns both checks off if a mod you trust takes over part of the cycle on purpose.


SETTINGS

BepInEx/config/wubarrk.dvergrastrolabe.cfg on the server (on the host's game for a hosted world, your own for single player). Every line carries a plain-language comment with worked examples โ€” "60 = each day takes one real hour".

๐Ÿ”’ Server-synced โ€” set on the server, the only values that count
Section Setting What it does
1 โ€“ General Enabled master switch; off = vanilla on every machine
1 โ€“ General LockConfiguration the server's values are the only ones that count โ€” keep it on
2 โ€“ Cycle CycleMinutes real minutes in a full day (30)
2 โ€“ Cycle DaytimeMinutes real minutes the sun is up (21)
2 โ€“ Cycle NightMinutes real minutes the sun is down (9)
2 โ€“ Cycle LengthRule which length gives way (FitToCycle)
3 โ€“ Production ProductionScale how fast the world works, ร— vanilla (1)
3 โ€“ Production ProductionBasis RealTime or GameDays (RealTime)
4 โ€“ Clock WaveSpeed Vanilla or FollowClock (Vanilla)
๐Ÿ–ฅ๏ธ Local to each machine โ€” the server and each player decide for themselves
Section Settings
1 โ€“ General VerboseLogging โ€” every sunrise, sunset and sleep skip measured in the log
4 โ€“ Clock SleepSkipPushInterval โ€” seconds between clock pushes during the sleep skip (0.5; vanilla 2). Matters on the server only.
5 โ€“ Compatibility PatchSelfCheck ยท SelfCheckSteps โ€” the self-check, and how finely it samples the day (1000)

CREDITS

Needs: BepInExPack Valheim 5.4.2360. ServerSync is compiled in; nothing else to install.

A Valheim mod by Wubarrk โ€” ravenirongames.com. Bug reports welcome on Discord. License: MIT โ€” keep the copyright notice. Full text in LICENSE.md.

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