Let me start by describing a problem...
You dock at your factory and unload a lot of ores, etc; then go exploring (or collecting more ores) for a few hours while the factory does its thing. You return to the factory several hours later hoping it's finished processing everything you dropped off last time, and find that nothing happened. What went wrong?
What happens is that if you get far enough away from your factory, your factory is "unloaded" from the server to save RAM and CPU time; and when you come back to your factory it's "loaded" again. This makes it seem like time is frozen when you're away. It breaks immersion.
It's not the only problem. The same happens to trade guild shops. They're supposed to be updated regularly by the trade guild, but unless you spend hours waiting nearby the updates don't happen because the shop isn't in RAM when it should've been updated.
Also (maybe, hopefully) future versions of the game will introduce other things; like grass and trees that grow (but only if a player is nearby), and AI factions that claim territory (but only when a player is nearby).
All of this can be fixed.
Well, actually it can't be fixed. You can't really have the entire universe in RAM all the time, with everything being updated when it actually should be (even when there's no players nearby at the time). No computer is powerful enough to handle an infinite sized universe.
All of this can be "fixed".
What I mean is that the game can create the illusion that time passed while a player wasn't there. The basic idea is very simple - every sector is given a "time when last updated" time-stamp, and when the sector is "unloaded" this time-stamp is saved to disk. When the sector is needed again the server loads it from disk and uses the "time when last updated" time-stamp to determine how much time should have passed for that sector (but didn't); and then advances the sector to the right time to create the illusion that time passed when it didn't.
The simplest way would be to calculate the number of ticks missed, and update the sector that many times when it's loaded; sort of like this:
That is bad (it'd add a massive amount of lag when sectors are loaded). Fortunately there's a smarter way, like this:
This is what I'm calling "multi-tick" - instead of an update only doing one tick, an update does one or more ticks.
For things like trading guild shop updates, this would be easy to do - you'd just multiple the amounts you're adding to shop credits and adding to shop stock by the number of updates the shop has missed - e.g. "shop_credits = max( shop_credits + updates_missed * amount_per_update, shop_max_credits )".
For factories it's a little harder because of power consumption. Essentially you'd determine how many ticks you can do before power consumption changes (before a factory would run out of input resources needed to continue production); then determine how much power the factory could consume and how much power regen is available (e.g. power regen - shield power consumption) until that change occurs, and calculate a scaling factor, like this:
Then you'd update each factory by "number of ticks until change", and do "ticks_left -= ticks_until_change * scaling_factor". You'd repeat this until the "ticks_left" reaches zero.
Note 1: this isn't 100% accurate and there would be minor differences between "time passing when player nearby" and "pretending time passed when nobody was around". However, it's more than good enough to sustain the illusion of time passing when nobody is around; which is the only thing that really matters.
Note 2: If your name is Schema, you'll probably realise I simplified a little. However, if your name is Schema then you're smart enough to see what I'm saying and extrapolate from my simplified example, and implement actual code that does (e.g.) take care of shop stock limits, determine the amount of power remaining after all updating is done, etc.
Overhead!
This will add a little overhead when a sector is loaded from disk. It shouldn't be very much, but there will be a little.
However; once you've got support for "multi-tick", it's simple to use it for other things. Specifically, if the server happens to be under heavy load, then instead of updating factories every tick you could just do it every 3 ticks (or every 10 ticks, or whatever you need to reduce server load). For a populated multi-player server (e.g. many different factories/stations with players nearby) you'd be able to significantly reduce the overhead of updating factories when the server is under load and most players wouldn't even notice. More interesting would be updating a sector's factories every tick when a player is actually looking at a factory's contents or the station's power; but if the player is only nearby and not looking then update the factory far less often.
You dock at your factory and unload a lot of ores, etc; then go exploring (or collecting more ores) for a few hours while the factory does its thing. You return to the factory several hours later hoping it's finished processing everything you dropped off last time, and find that nothing happened. What went wrong?
What happens is that if you get far enough away from your factory, your factory is "unloaded" from the server to save RAM and CPU time; and when you come back to your factory it's "loaded" again. This makes it seem like time is frozen when you're away. It breaks immersion.
It's not the only problem. The same happens to trade guild shops. They're supposed to be updated regularly by the trade guild, but unless you spend hours waiting nearby the updates don't happen because the shop isn't in RAM when it should've been updated.
Also (maybe, hopefully) future versions of the game will introduce other things; like grass and trees that grow (but only if a player is nearby), and AI factions that claim territory (but only when a player is nearby).
All of this can be fixed.
Well, actually it can't be fixed. You can't really have the entire universe in RAM all the time, with everything being updated when it actually should be (even when there's no players nearby at the time). No computer is powerful enough to handle an infinite sized universe.
All of this can be "fixed".
What I mean is that the game can create the illusion that time passed while a player wasn't there. The basic idea is very simple - every sector is given a "time when last updated" time-stamp, and when the sector is "unloaded" this time-stamp is saved to disk. When the sector is needed again the server loads it from disk and uses the "time when last updated" time-stamp to determine how much time should have passed for that sector (but didn't); and then advances the sector to the right time to create the illusion that time passed when it didn't.
The simplest way would be to calculate the number of ticks missed, and update the sector that many times when it's loaded; sort of like this:
ticks_left = currentTick - sector.lastUpdateTick;
while( ticks_left > 0 )
while( ticks_left > 0 )
sector.update();
ticks_left--;
}ticks_left--;
That is bad (it'd add a massive amount of lag when sectors are loaded). Fortunately there's a smarter way, like this:
ticks_left = currentTick - sector.lastUpdateTick;
if( ticks_left > 0 ) {
if( ticks_left > 0 ) {
sector.update(ticks_left);
}This is what I'm calling "multi-tick" - instead of an update only doing one tick, an update does one or more ticks.
For things like trading guild shop updates, this would be easy to do - you'd just multiple the amounts you're adding to shop credits and adding to shop stock by the number of updates the shop has missed - e.g. "shop_credits = max( shop_credits + updates_missed * amount_per_update, shop_max_credits )".
For factories it's a little harder because of power consumption. Essentially you'd determine how many ticks you can do before power consumption changes (before a factory would run out of input resources needed to continue production); then determine how much power the factory could consume and how much power regen is available (e.g. power regen - shield power consumption) until that change occurs, and calculate a scaling factor, like this:
if( power_consumption < power_available ) {
scaling_factor = 1;
} else {scaling_factor = power_available / power_consumption;
}Then you'd update each factory by "number of ticks until change", and do "ticks_left -= ticks_until_change * scaling_factor". You'd repeat this until the "ticks_left" reaches zero.
Note 1: this isn't 100% accurate and there would be minor differences between "time passing when player nearby" and "pretending time passed when nobody was around". However, it's more than good enough to sustain the illusion of time passing when nobody is around; which is the only thing that really matters.
Note 2: If your name is Schema, you'll probably realise I simplified a little. However, if your name is Schema then you're smart enough to see what I'm saying and extrapolate from my simplified example, and implement actual code that does (e.g.) take care of shop stock limits, determine the amount of power remaining after all updating is done, etc.
Overhead!
This will add a little overhead when a sector is loaded from disk. It shouldn't be very much, but there will be a little.
However; once you've got support for "multi-tick", it's simple to use it for other things. Specifically, if the server happens to be under heavy load, then instead of updating factories every tick you could just do it every 3 ticks (or every 10 ticks, or whatever you need to reduce server load). For a populated multi-player server (e.g. many different factories/stations with players nearby) you'd be able to significantly reduce the overhead of updating factories when the server is under load and most players wouldn't even notice. More interesting would be updating a sector's factories every tick when a player is actually looking at a factory's contents or the station's power; but if the player is only nearby and not looking then update the factory far less often.