phpeventsmmo

php - how to make event queue working in offline mode in browser games


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 :)


Solution

  • 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.