The following are some important notes about the technical implementation described here; each fact is described in the document, but are key points to understanding how the system intends to distribute and reduce the workload of thousands of agents.
-
Entities schedule updates based on TPS, ie if an NPC is performing a job that lasts 12s, and has its next moodle expiring in 8s, we take the minimum of that and multiply by 60. The NPC schedules an update for 480 ticks later. The NPC is updated in exactly 480 ticks regardless of true latency.
-
Entities track resource consumption in terms of ticks, but do not update values every tick. For example, an NPC based on its current moodles and activity should have an oxygen consumption rate of some integer value per tick, which it will check against its lung capacity to determine when it must schedule its next breath. In between the decision tick and the scheduled tick, we can safely derive what the oxygen level in its lungs would be, without the NPC updating its state.
-
The same interpolation can easily be done on entity positions. At most a navigating entity should only need a handful of actual updates in a second. We should probably place an upper limit on this to prevent bogging the game down, as well.
-
We can run independent environmental sims at a fixed speed as well, and some such as fluid sims might be fine with very reduced TPS. Being able to put such sims to sleep when activity reduces below a noise threshold would also be very useful.
-
Interrupt-style events are triggered on an entity by some outside force. For example if an NPC scheduled it’s next update for 480 ticks from now while working on some task, but a missile blew out the wall 120 ticks after that, an event is triggered at 120 ticks on the room, the NPC is subscribed to room events, and is notified at 120 ticks instead of 480. The NPC can decide whether to cancel the update that would have otherwise occurred in 360 ticks. If it does, it will need to apply it’s deltas at 120 ticks and schedule new updates.
-
Spacial threading is a term describing a job scheduling system. Tick events will need a scheduler to iterate them. At a basic level this is iterating an array of event listeners, where the listeners have a tick number instead of just a callback closure, but we can of course multi-thread the iteration of the array. If we choose an arbitrary split of the work for a given tick, we would introduce contention over things like which NPC is standing in which cell in a given frame. This contention can be solved with locks, but that reduces throughput and kills determinism. Instead we divide work by region. Supposing we want to simulate a planet, the entire surface need not be simulated, only specific points of interest. Say a small cabin in the woods, or a spaceport. Each of these POIs could hypothetically be run on separate threads with much less contention on overall game state. We can use message passing to solve that remaining contention efficiently. This means a 1 tick delay transferring state between POIs, but that isn’t a major issue. Loss of determinism can be addressed by ranking the message senders for a given tick, and processing the messages in that order.