What time is it?

Started by
5 comments, last by humanapp 16 years, 11 months ago
Not strictly multiplayer question, but deals with persistent worlds which are tied to multiplayer. How could one represent persistent in-game time? Assuming an item expires in 6 hours. But after 3 hours server goes down for 8 hours. Does the item expire in between? Or does it still have 3 hours left? Tying this time to real-world time can have devastating consequences in case of time mismatch. For example, clock jumping a year ahead, invalidating all timed objects in one tick (server reset/hardware upgrade/CMOS battery running out). Would a compromise be an external service, which persists the in-game time, and also takes care of ticking? This still leaves the problem of what happens if this time-stamp is suddenly changed or corrupted. Or is there some other way to handle persistent timers? Possibly with a queue, in which the timed elements are given a TTL, and are decremented on each tick? Or rely on external time service and make sure it's always correct? This applies to all general timer related issues (trade auctions, buffs, weather/seasons, daily/nightly mobs, ...).
Advertisement
If the server goes down during a certain time interval, no in-game time should progress during that period (imho). And have the server itself keep track of in-game time, sending a sort of game-time-stamp downstream to the clients with appropriate data packets. That will prevent time-distortion or something like it due to client errors.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
I suggest making game time progress only during uptime. This can be implemented, for example, through the server checkpointing the current time once a minute (real time). When the server starts up, it reads the last checkpoint, then advances time by one minute and establishes a new relationship between real world and server time. Thus, in the event of a crash, the most you can lose is one minute.

Another consideration is the rate of advance between real time and game time. Some games do an entire day in an hour; other games take longer; yet other games don't advance time at all, tieing a specific time-of-day to each individual game zone/level.
enum Bool { True, False, FileNotFound };
If your server-side implementation consists of dynamically load-balanced zones so that inactive zones unspawn and can later respawn, possibly on another host, you would want time to progress in both the active and inactive zones equally. In this scenario, I'd think that storing an absolute timestamp on the object such as "when I expire expressed in seconds since 2006" is the best you can do, and of course have all your hosts synchronize to the same NTP server. If you experience a failure that corrupts a timestamp or a server's clock, well, that's what backups are for :)
I would agree with that except that would require the client to have a secondary software clock with the ability to sync with said NTP server. That would slow down the client app somewhat, and add an extra level of complexity to the coding... on the other hand, sending timestamps from the server could also slow performance and connection problems could potentially cause errors. I suppose it is really just a matter of perspective.
There was a saying we had in college: Those who walk into the engineering building are never quite the same when they walk out.
Just to clear the confusion, this isn't for client-side, it's for persisting temporal data on the server.

Consider a simple WoW example. You put an item on auction for 24h, and you have a something buff on you that lasts 17 minutes.

If you log out, those two will be stored in database until you log back in. But: Auction will expire in 24 hours game time, but your buff will expire in 17 minutes session time.

In addition, there's also real-time, which represents player responses (movement limites, button timers), which isn't related to world time (1 h = 6 hours game-time) and so on.

I think that I'll need 3 distinct types. Real-time, for process and command synchronization, session time (possibly just session specific times with TTL parameter, which gets updated frequently, allowing for 1 sec resolution), and world time, which takes care of long tasks (the auction example).

This last one might be tricky, unless I choose to update it via DB query or some stored procedure ( basically an arbitrary number of these timers can exist, and they need to be processed whenever server is alive, regardless of players).

This last example is the biggest problem I see, since the way I see it would require a full DB pass on each update looking for expired objects. Guess I'll profile a bit to see how much load such pass puts on DB.

In reference to auctions: I'd recommend building an auction server to manage the active ones in memory instead of scanning over the db. At startup, this server would pull the set of active auctions from the db, adding them to a queue sorted by expiration time (a priority queue). Then just process the queue on a timer callback (set to call back exactly when the next auction expires; no unnecessary polling of the queue). New auctions would be added to the queue as they're created (as well as written to the db).

HTH

This topic is closed to new replies.

Advertisement