The Pulse — World Tick Engine
The Pulse is the server-side tick service that advances world time and drives every other Living World subsystem. All simulation work — Wild population updates, Flow resource regeneration, Veil weather progression, Age faction logic — happens on a Pulse tick.
World time vs real time
The Pulse operates on a world clock that is separate from wall-clock time. The compression ratio controls how fast world time advances relative to real time.
The default ratio is 1 real second = 1 game-minute. At this rate:
- A game day (24 hours) takes 24 real minutes
- A game month (30 days) takes 12 real hours
- A game year (12 months) takes 6 real days
You can configure the ratio per zone or per world in the World Settings panel in the editor. Common alternatives:
| Ratio | Description |
|---|---|
| 1s = 1 game-minute (default) | Fast enough for meaningful daily cycles |
| 1s = 10 game-minutes | Suitable for long-running persistent servers |
| 1s = 1 game-second | Real-time (useful for testing) |
Zone partitioning
The world is divided into zones — discrete geographical regions, each advancing independently. Zone boundaries are rectangular by default but can be arbitrary polygons authored in the Zone Editor.
Each zone has:
- A unique
ZoneId - A biome type (determines Veil defaults, Wild species affinity, Flow resource types)
- Adjacent zone references (used by Veil storm propagation and Wild migration)
- Active/dormant state
Zone partitioning allows the simulation to scale horizontally. The Root can assign different zones to different computation shards. Zones with no connected players consume far less computation per tick (see dormant mode below).
Dormant mode
A zone enters dormant mode when no players have been connected to it for a configurable duration (default: 5 minutes). In dormant mode:
- The Pulse slows tick frequency from the full rate to once per real minute
- Wild populations and Flow levels advance in coarser steps using a fast-forward approximation
- Veil weather states transition based on probability tables rather than full propagation simulation
- Age faction logic advances by a single accumulated step per dormant tick
When a player connects to a dormant zone, the Root applies a catch-up pass: the zone is fast-forwarded from its last full-rate tick to the current world time at full fidelity, then switches back to full-rate ticking. The catch-up typically completes in under 500ms for zones dormant for less than a week.
This design ensures the world continues to change even when no players are present, without burning full simulation budget on empty zones.
WorldCalendar
The WorldCalendar provides the current world time as a structured value with year, month, day, hour, minute, and season:
var worldState = Services.Get<IWorldStateQuery>();WorldTime now = worldState.GetCurrentTime(zoneId);
Logger.Info($"World date: Year {now.Year}, {now.Season}, Day {now.DayOfMonth}, {now.Hour:00}:{now.Minute:00}");// "World date: Year 4, Summer, Day 15, 08:30"The Season enum is Spring, Summer, Autumn, Winter. The year length in days, month names, and seasonal thresholds are all configurable in the World Settings panel. Custom calendars (for fantasy or sci-fi settings) can define any number of months with custom names.
// Subscribe to a new day starting in a zoneworldState.OnNewDay += (sender, args) =>{ if (args.ZoneId == myZoneId) { // Trigger daily NPC dialogue refresh NpcDialogueCache.Invalidate(); }};
// Subscribe to a season changeworldState.OnSeasonChanged += (sender, args) =>{ Logger.Info($"Season changed to {args.NewSeason} in zone {args.ZoneId}");};Season-change events fire once per zone per season transition, regardless of how many clients are connected to the zone. The event is reliable — if your client was offline during a season change, it is replayed on reconnect.