0

While thinking about making browser games i met a disturbing trouble. Many games has something called 'event queue' that works like this. I have an "army" and send it to my opponent. I takes some amount of time. When my "army" gets oponent "army's" location there is a fight calculated so my "army" looses or wins. Everything is fine when me or my oponent is in the game. Some kind of ajax work can manage php script to be called and calculate fight - then save it's result to database. But how can it work if neither me, nor opponent is logged in when battle occurs? The good example of such game is Ogame when you are sending ships to another planet and it can meet it's destination when you are logged out, perform fight, get sources of your enemy and comeback, so it caluculates not only starships on planet but also amount of resources in that particular moment.

I've been thinking that i can save time of attack both attacker and his opponent in database rows and calculate the fight while any of player logs into the game, but this solution has many disadvantages. For example if there is third player that will attack before i will attack my oponent it will change hist army statistics (because he can kill part of his army) and i has many consequences. Also if none of the players would logout for a long time they would appear in game as they were not fighting and that would not be true..

Do you have any idea how to make such event queue? I guess using cron is also not good idea - it can be sometimes used to rarely and if there is thousands of players thousands of cron instances could be a killer for performance. Any concept would be appreciated - hope i described my problem good enough :)

Kalreg
  • 931
  • 3
  • 12
  • 31
  • it probably uses cron jobs? – Yanick Rochon Dec 30 '12 at 03:06
  • i dont think so - check http://code.google.com/p/ogame-opensource/ - there is written 'cron-less event queue' but the source code has so many files and is described in russian language that i will take days before i find the way it works there – Kalreg Dec 30 '12 at 03:08
  • Then what it does is queuing events and whatever user requests something, it process the event queue, then. Simple enough. – Yanick Rochon Dec 30 '12 at 03:11
  • i dont think it's simple.. it doesnt matter that you queue anything in the script or database if noone is calling that script or updates the database ie 2 days later when event occurs. I found a loophp library on github but havent it tried yet... maybe it is the solution.. – Kalreg Dec 30 '12 at 03:14
  • If there is *no* cron job (or background process), and *no* one request *anything*, then *nothing* well get processed. It's as simple as that. – Yanick Rochon Dec 30 '12 at 03:16
  • so how can it be done in ogame game? i send my army to attack, and logout. my oponent isnt logged in. But my army go for 2 days to oponent, attacks him (here comes calculations) and when i log in again i see the results of fight that happend in the past. i would try to understand how it's done and any concept would be helpful – Kalreg Dec 30 '12 at 03:19
  • 1
    There are other players in that game, no? Any time someone requests something, the event queue is checked for something to process, even if that something does not belong to that someone; it just process the events in queue that needs to be processed. If no one requests anything, then it would get processed when *you* log in again. – Yanick Rochon Dec 30 '12 at 03:22
  • that one is good idea but i am afraid that it can be a killer for performance in some times... but that's a good start for optimizing. thanks.. If anybody has any other ideas you are welcome to share it with me :) – Kalreg Dec 30 '12 at 03:25

2 Answers2

1

In your database, create a "job" table (whatever contents you need, plus an EXPIRE date - which is when the job is finished) and everytime a user causes a job creation (e.g. moving ships from one cluster to another), make a new entry in this table with EXPIRE set to the time when the ships have arrived in the target cluster.

Then, everytime anyone (!) loads any site (even the startpage), the script checks for jobs in the queue which should have been done by now. If there are any jobs where EXPIRE is lower than NOW, then it does the job (or, for larger jobs, forks off a php cli process to do the job).

Assuming the case that it is 2012-12-28 12:00, the game has two players A and B, where A launches an attack on B that takes 6 hours. A job is created with EXPIRE=2012-12-28 18:00 and the content "Fleet foobar attacks B".

Case A: Now, A logs out and nothing happens until 19:00. B logs in, and before anything other happens (this is important to ensure that "notifications" or inboxes don't appear out of sync), the script sees that a job is in the table and overdue. The script executes the jobs and creates the notification to B that he got overrun by a huge fleet from A. Job done, all is fine (except the mood of B).

Case B: A logs out. At 18:30, an anonymous user visits the startpage. The script again looks in the jobtable and executes the job. B logs in at 19:00 and sees the notification of his loss. Job done.

Skynet
  • 558
  • 3
  • 16
  • and thats the solution i've been looking for (same as Yanick proposed). thank you both and +1 for you for a good explanation :) – Kalreg Dec 30 '12 at 03:27
  • You're welcome. Good luck for your project. I'd advise you to introduce an external endpoint (like "game-cron.php") which processes the job queue. This endpoint can then be called from a web-cron service (google "web cron service", there are hundreds of free ones on the web). In this way, the load-times of users are not affected. – Skynet Dec 30 '12 at 03:32
0

The idea behind CRON-less event queue in my project is simply following:

  1. All events have "end" time. I'm using raw UNIX time() timestamps for easy compare operations.

  2. When user "clicks" (open any game page) queue engine fetches all events which are "ended" <= current time(), according to priority. Events which are happened at same second are executed from high priority to low.

  3. If there are no users in game - no one need events. Just that simple :) Game sleeps until someone login the game and roll-back event queue, as described in second step.

You can add the same functionality on any web-site, which has periodic events and decent daily site traffic.

(Actually I also made cron.php backend by demand)