Multi-tick!

    Joined
    Aug 23, 2013
    Messages
    379
    Reaction score
    65
    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:

    ticks_left = currentTick - sector.lastUpdateTick;
    while( ticks_left > 0 )
    sector.update();
    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 ) {
    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.
     

    jayman38

    Precentor-Primus, pro-tempore
    Joined
    Jul 13, 2014
    Messages
    2,518
    Reaction score
    787
    • Purchased!
    • Thinking Positive
    • Legacy Citizen 4
    I fully agree. Any change similar to this would make the universe feel more alive. It doesn't have to be super-accurate for me to appreciate it.

    Example: If I have been gone for a time during which the sector should have received 10 updates, I'll still be happy if it only has enough change to simulate 3 updates. Anything is better than nothing.

    If you coded in random delays on various updates, you'll probably get all the updates, with less lag, before the player can notice the change. For example, if the player enters the sector with their factory, and that factory doesn't update until about 35 seconds after it is loaded, the player probably won't see the sudden shift, because it will take the player a minute to park their ship and enter the factory to check it out. Same thing with the shop, but maybe a little shorter, since the player only has to get into range before shopping.

    Example delays:
    shops: 15s + random * 15s
    factories, autominers, autorepair: 35s + random * 15s
    organic growth: 55s + random * 15s
    shipyards: 80s + random * 15s
     
    Joined
    Aug 23, 2014
    Messages
    427
    Reaction score
    137
    • Purchased!
    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?
    Yep, had that happen before. It's annoying for sure. I would consider it a bug though.
     
    Joined
    Jul 27, 2013
    Messages
    78
    Reaction score
    9
    This is a decent idea. I've seen other games work this way. However I think it needs a maximum number of updates, or a maximum time threshold to trigger updates. Otherwise someone on a server clips the edge of a sector that hasn't been visited in a few months and then lag city.
     
    Joined
    Aug 23, 2013
    Messages
    379
    Reaction score
    65
    This is a decent idea. I've seen other games work this way. However I think it needs a maximum number of updates, or a maximum time threshold to trigger updates. Otherwise someone on a server clips the edge of a sector that hasn't been visited in a few months and then lag city.
    Agreed - it would take a little refinement (like, not bothering to update shops until someone opens the shop interface, and not bothering to update factories until someone looks at a factory block's inventory). However; doing many ticks at once should be a lot faster than doing many ticks one at a time, and it therefore (without any refinements) shouldn't cause a huge amount of lag if someone clips the edge of a sector.
     
    Joined
    Aug 23, 2014
    Messages
    427
    Reaction score
    137
    • Purchased!
    It's not that hard to multiply 10*6*60*24*365... It should be a REALLY simple calculation. no lag should even be involved.
     
    Joined
    Jun 19, 2014
    Messages
    1,756
    Reaction score
    162
    • Purchased!
    • Top Forum Contributor
    • Legacy Citizen
    But a cap should be implemented for the sake of balance. And make that cap server configurable. Oh yes, the reason for the cap: You don't want this game to just be another game where you put something on and wait a while for it to happen. The cap should prevent people from leaving their stuff alone for too long.

    This should really be implemented though for the smaller time frames. Otherwise survival just has another reason in it why it shouldn't be played.

    Or at least have something which keeps a sector loaded, like the anchors in minecraft.
     

    jayman38

    Precentor-Primus, pro-tempore
    Joined
    Jul 13, 2014
    Messages
    2,518
    Reaction score
    787
    • Purchased!
    • Thinking Positive
    • Legacy Citizen 4
    Yes to multi-tick limits.

    No to keeping sectors loaded. Bad idea, especially since the devs want get a lot of people at once on a single server.
     
    Joined
    Jun 19, 2014
    Messages
    1,756
    Reaction score
    162
    • Purchased!
    • Top Forum Contributor
    • Legacy Citizen
    No to keeping sectors loaded. Bad idea, especially since the devs want get a lot of people at once on a single server.
    I said at least. As in if there is no other way to implement the function. It is far from desirable, but it would at least be something (and server configurable of course).
     
    Joined
    Jul 27, 2013
    Messages
    78
    Reaction score
    9
    It's not that hard to multiply 10*6*60*24*365... It should be a REALLY simple calculation. no lag should even be involved.
    Unfortunately with factory and storage linking, and other logic connections, you can't just do all the ticks at once per object. Otherwise once you come back the only thing that will have benefited is the very bottom of the factory chain. And that's assuming a straight line of connections. If you had a more convoluted factory chain it could throw your ratios all out of whack.
     
    Joined
    Aug 23, 2013
    Messages
    379
    Reaction score
    65
    Unfortunately with factory and storage linking, and other logic connections, you can't just do all the ticks at once per object. Otherwise once you come back the only thing that will have benefited is the very bottom of the factory chain. And that's assuming a straight line of connections. If you had a more convoluted factory chain it could throw your ratios all out of whack.
    Yes - for things like factories (including the new storage blocks and their filters), it would be more like:

    void update(ticks) {
    int ticks_left;

    ticks_left = ticks;

    if(ticks_left == 1) {
    do_ticks(1);​
    } else {
    while(ticks_left > 0) {
    n = determine_how_many_ticks_could_be_done_before_something_changes();
    if(n > ticks_left) {
    n = ticks_left;​
    }
    do_ticks(n);
    ticks_left = ticks_left - n;​
    }​
    }​

    The important part here is that "n" may be a lot higher than 1. For example, if one factory block can do 1000 ticks before it runs out of stuff and another can do 1500 ticks; then you'd get "n=1000" the first time through the loop and then "n=500" the second time (and wouldn't be doing 1500 individual ticks).

    Also note that the "ticks_left = ticks" part could be something more like "ticks_left = min(100000, pow(ticks, 0.95) );" to reduce overhead when "ticks" is large and limit it when ticks is extremely large.

    I'm not sure that it's worth doing logic with multi-tick - it'd be enough to say that logic and anything controlled by logic freezes when nobody is near (and avoid the extra complexity). It's mostly just shops, factories and storage that players notice (until we have potato farms!). ;)