0
\$\begingroup\$

I am developing a simple browser game, using ASP.NET, C# and SQL Server 2012. I need to implement build time of some unit or building. One way would be storing finish date to database and just fetch remaining time on refresh, but there is one problem. If user doesn't refresh in a long time and building finished days before, the dependent records in database won't get updated (e.g. I have finished building Iron Mine 3 days ago, but the production per hour wont get updated until user refreshes). How would you approach this problem ? Is there some sort of timed event in database, that will not ruin database server performance when there will be a lot of timers ?

\$\endgroup\$
0
\$\begingroup\$

While it is possible to use a stored procedure and have it be called from the database itself, I would recommend you deal with this from the application layer instead.

You have two basic options, the first is to have a background process that handle unit/building completion and makes the changes in the database. This is fairly straightforward and if your game is multiplayer it might be your best bet. The downside is that if your paying for a shared server your process might get shut down when there aren't any visitors to your site, resulting in that time stops occasionally (and from the players point of view, randomly).

A second option is to make it so your game logic receives the current time instead of looking at the system time Building.update(currentTime), this way you can look up if any buildings/units completed their orders at a time in the past, then update said units at that point in time.

void OnVisit(...) {
  var now = Date.Now;
  for (var event = DataBase.GetFirstUnprocessedEvent();
       event != null && event.DueTime <= now;
       event = DataBase.GetFirstUnprocessedEvent()) {

    event.Process(event.DueTime);
    event.Processed = now; // It's a good idea to mark when it actually happened
    DataBase.Update(event);

  }

Now time will keep on ticking normally even if the server gets rebooted, things just happen all at once when the player visits instead of over time like it normally would. By reading the first event until you can't find any more or they are in the future you allow the code to add new events in the past and things still work.

If you read all events that are due you need to make sure you process any newly added event (for instance, if the building will create a new unit after 3 hours you will want to make sure the unit gets created and their upkeep reduced before events that happen later).

Saving the current time is useful so you can find bugs or tweak algorithms, even if the game itself doesn't care about it. The downside with this approach is that a player who hasn't visited for a long time might cause a noticeable delay or lag when they suddenly remembers your game and comes back for a visit.

Of course, you can combine both options if you wish, by having a daily/weekly/monthly task update any outstanding build orders simply by acting like the player accessing the game.

\$\endgroup\$
  • \$\begingroup\$ Thank you for quick answer. The like idea of backround process, it solves the problem of refresh triggered updates. I will go for it. \$\endgroup\$ – Meyhem Feb 16 '15 at 10:13
  • \$\begingroup\$ You're welcome @user3136718, I expanded a bit on the second option in an edit, if you ever have issues with server downtime it might be worth a consideration \$\endgroup\$ – Daniel Carlsson Feb 16 '15 at 10:17
  • \$\begingroup\$ It seems very promising, I will try out both solutions! Thnka you againt, you saved me a lot of hours. \$\endgroup\$ – Meyhem Feb 16 '15 at 10:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.