The one clock the whole world runs on: what the server sends, how the client converges its own copy on it, and the astronomy blob that carries the time of day, the moon and the season.
| What | Where |
|---|---|
| The clock a caller reads | Glob.globtime() — game-world seconds, and the only public read. It answers the client’s interpolated gtime, never the server figure directly |
| The three numbers behind it | Glob.gtime (the client’s own clock), sgtime (the last figure the server sent) and epoch (the Utils.rtime() at which that figure arrived), plus the two rates ctimefac and stimefac, both starting at itimefac = 3.0 |
| Advancing it, every ctick | Glob.tickgtime(now, dt), called from Glob.ctick before the object and map ticks |
| Taking a server figure | Glob.updgtime(sgtime, inc), from the "tm" branch of Glob.blob |
| Reading the convergence live | Glob.gtimestats() — gtime, sgtime, epoch, the projected server time, the gap, and the two rates |
| Astronomy | Glob.ast, an Astronomy record built whole by the "astro" branch of Glob.blob: dt (the fraction through the day), night, mp (the moon phase), yt (the fraction through the year), is, sp, sd, years, ym, md, and the moon colour |
| The world’s light | the "light" branch of Glob.blob writes tlightamb/tlightdif/tlightspc under the Glob monitor |
The server does not tick the client’s clock; it publishes its own figure now and then and the client
chases it. tickgtime runs every ctick and does three things: it projects where the server’s clock has
got to (sgtime + (now - epoch) * stimefac), advances its own by dt * ctimefac, and then nudges
ctimefac towards whichever side is behind — by at most 0.02 * dt, and only while the two rates are
within 10% of each other, so the clock never jumps and never runs more than a tenth off real speed. A
final term pulls ctimefac back towards stimefac at 0.002 * dt, which is what stops it from settling
at a permanent offset once the gap has closed.
updgtime is the other half. It records how long it has been since the last figure, and then either
re-bases or learns:
gtime and sgtime are both set to the server’s figure outright, with no convergence at
all, when this is the first figure (sgtime == 0), when the blob is not incremental (inc false), or
when the figure is more than 500 seconds from the last one. That last case is the one to know: a
jump of any size lands instantly rather than being converged towards, so a reader that was
interpolating sees the clock move by minutes in one tick.(sgtime - this.sgtime) / delta) into stimefac with a weight of min(delta * 0.01, 0.5). So
the client’s idea of how fast the server’s clock runs is an exponential average over the updates, and
it takes several of them to move.inc is the first byte of the blob, so both branches of that decision come off the wire.
Astronomy.is is a season index the engine never names. Cal is its only reader, and it uses the
index to pick one of four calendar textures (gfx/hud/calendar/dayscape-<i> and nightscape-<i>), so
the domain is 0..3. The "astro" branch defaults the field to 1 when the server omits it, which is
a hint that 1 is the neutral season and not proof. Which index is which season appears nowhere in
src/haven: read it off the calendar the client draws.Astronomy.dt is 0 at midnight and 0.5 at noon. Cal draws the sun on its dial at the angle
(dt + 0.75) * 2π and the moon at (dt + 0.25) * 2π, through Coord.sc, which turns the angle’s y
upward (-sin): so the sun stands at the top at dt == 0.5 and the moon at dt == 0. Nothing else in src/haven reads dt: the night flag is the only other word the
server gives on the time of day, and it is a separate field, not a range of dt.Cal always puts it across the dial from the sun, whatever
mp says; mp only picks which frame of gfx/hud/calendar/moon is drawn.Glob.ast is null until the first "astro" blob lands, which is a beat after login, while
globtime() answers from the first tick. Any reader of the astronomy half guards for it.Glob.ast is replaced wholesale, a new Astronomy per blob, so nothing may hold a field of it across a
tick and expect it to move; hold the Glob and re-read.The calendar window that draws all this (Cal), the seasonal art itself, the server’s own clock, and the
rest of Glob.blob’s branches beyond "tm", "astro" and "light".
Glob itself, and the rest of what hangs off it