Pits Of Doom Update
Don’t think I’ve forgotten about the game tutorial!! I haven’t. I’ve been really busy at work and trying to get a new site ready for its BETA opening. Blah. Anyways, I’m almost done will lesson 7 where you’ll learn how to write a join, login, logout and lost password script for Pits of Doom.
Hey Greta. I don’t know what you’re talking about here and I don’t feel like going through the previous posts but does this Pits of Doom related to Plex? Are you still working on Plex anyways? Work…good time…..j/k. Alrightie ttyl, I’m just trying to waste time at work as I wait for my long commute through the storm.
The MySQL lessons have been great, I don’t want to preempt future tutorials but I would be really interested in your solution to the problem of interaction between clients while those clients are offline.
An example of this would be:
USER A wants USER B’s treasure so USER A issues a command to attack and pillage USER B’s castle however traveling to USER B will take time (say 5 hours). USER A issues the attack command and goes offline.
USER B logs on and seeing the impending attack from USER A decides to take all his treasure on a boat ride in the middle of the ocean. USER A attacks USER B’s empty castle and his forces start the long march home empty handed.
USER A then logs on to see that his attack was a success but he has no treasure!
The above example is simple however if you add in other variables such as trade + other earnings and expenditure there are many factors that determine the amount of treasure held by USER B at the time of USER A’s attack. Also if instead of 2 users you have 2000, your problems multiply.
How would you approach this problem?
That is indeed an excellent question. For this particular game tutorial I’m going to cover the only time two people can fight each other is if they’re both online.
All multiplayer games have this problem, whether they’re running in realtime like World of Warcraft of browser based. There are a few things you can do to try and prevent such things from happening but I wouldn’t say there is a 100% foolproof way to overcome it.
The technique that I’ve always used, and I believe is used in most big industry game is locking. Lets say you have two players A and B who are both going after the same treasure. If player A is the first to touch the treasure, the ability for anyone else to touch that treasure is removed. Once player A makes some kind of action, the lock on the treasure is released.
The biggest problem with this is still, what happens if player A leaves for 5 hours? In this case we can set a timeout on the treasure. If player A doesn’t do something with the treasure within a set period of time the lock on the treasure is removed, making it fair game again. Then if player A comes back from their siesta, they’ll be happily informed that player B has not only stolen their treasure but destroyed their castle.
One of the things down the road in this tutorial will be how to ensure if someone is still active and online on the game, that way once someone stops playing for an extended period of time their characters go inactive. This will try to prevent situations in which people walk away from their computer in the middle of what they were doing.
Great question by the way! I’m happy to know the tutorials I’ve written so far are being put to good use 🙂
Wow… thanks for the quick reply!
My knowledge of SQL and PHP is limited and I have not been able to find any books on SQL / PHP game techniques. I’m learning but need guidance on which approach is more suited to the capabilities of SQL and the PHP language.
One possible way to solve the problem I presented is for a dedicated client to process the queue’d interactions of the players (so that actions in the world are executed in order and at the correct time). For a real-time game this would be probably be unfeasible however for a game where the actions of the player are played out over hours not seconds, it may be valid.
This idea maybe completely inappropriate for SQL / PHP or there maybe aspects SQL / PHP that would provide a much better solution, I just don’t know and would like your advice before I go completely in the wrong direction ☺.
Well, I wouldn’t call it completely inappropriate (I could see it as a feasible solution to some problems) but I’m not sure that’s necessary for a php/mysql game.
When SQL looks at a row it locks the row for the thread. Once the changes/updates/etc have been done it unlocks the row again so another thread can have at it.
If you go back to the idea that 2 players are fighting each other, and player B wanders off and comes back 2 hours later, I’m not sure you’ll have a problem with the time lag. Think of it this way:
You have some kind of process running in the backend that’s constantly checking to see which players are active and which are inactive. When it finds an inactive player all of their characters/info, becomes inactive in the game. That way only active players can fight each other.
Now lets say player A and B are fighting. Player B wanders off but player A is still fighting player B’s characters. Now here comes our background process that see player B is no longer active, and it’s going to make player B’s thing’s inactive. Only we’ve set some kind of flag on player A and player B’s characters once the battle started. We can have this background process skip over these characters/items in this case. So it makes the rest of player B’s things inactive, except for those currently in battle. Even though player B has gone inactive player A can continue fighting.
But for some reason player A decides, hey this guy isn’t fighting back, I’m done here. They leave the fighting sequence before they kill player B’s character. Our process comes along, sees that player B is still inactive but has active characters/items still. Now that they’re no longer in a fight sequence the process can deactivate everything. Player B’s characters/items cannot be touched while they’re gone.
I’m not sure I see a need to make anything queue based. Whoever makes the fastest action will send their query off to SQL, it’ll lock the row, process it, and then go to the next query, and process it. I believe what you’re trying to prevent player A killing player B outright because they have a better internet connection. Even if you queue the two player’s actions I don’t see how that will make a difference here. But perhaps I’m still missing something of the question. If so, let me know.
I am extremely grateful for help… can’t wait for the next tutorial. 🙂
I believe we have been chatting at cross purposes lol. I’m not trying to prevent offline player interaction but positively promote it, I love the idea of the simulation / interaction being played out while players are offline – it allows for the play experience to be lengthened, reducing load / bandwidth and allowing more players to interact together (less realtime – more actual time 🙂 ).
Current planned approach:
i. PHP implementation (proven tech, available low cost servers)
ii. Separate simulation from player scripts (clean)
iii. Simulation triggered via cronjob (avoid 30 sec max execution time)
iv. Optimize using SQL stored procedures once up and running.
Now you know my crazy plan, any potential pitfalls?
Thanks again… SM:)
I potentially forsee 2 problems: a larger lag time then if you were running all the scripts in real time and potentially more querying then necessary.
For the first problem, lets say you have the players doing their things, you’re putting that into a queue, and once the cron runs those changes are put into effect. If you setup the cron so it doesn’t exceed a set amount of time you’ll have some backup in the queue. Of course you’ll always have some amount of backup in the queue, that’s the nature of queues, but if your game generates really heavy traffic you may have player A making a change on monday and not seeing the results until wednesday night.
My suggestion to you here would be to allow the player changes in real time, and take into account the current simulation conditions at the time of those changes. So, for instance, lets say it’s raining at the time one battle takes place. The cron runs, and the battle is still going on. Now the player’s battle can continue with the new conditions in place.
The second potential problem I see is querying the database more often then need be. If you’re constantly running the cron then each time you have to check for player actions, perform those player actions, and then do whatever else you need to. That means every time you run the cron you’re performing extra queries to check and see if you need to execute player actions. While this might not seem like a huge performance issue, times that by x number of players with y number of actions over z number of times the cron runs in a day. However if you’re not running the cron that often this may not end up being much of a problem.
Really the biggest thing is, how to balance the server load to get the best performance. My experience has been that people want results now. We’re not in the age where someone will wait more then 5-10 minutes for a burger, and they gun it through a yellow light (I’m guilty of both!). If you have a huge following of players load will always be an issue, especially at peak gameplay times. I’ve found a few ways to help with that:
1) Run crons at low traffic times. Reduces the changes of timeouts and row errors.
2) Reduce your queries to a bare minimum. I already spend a fortune in servers for my games and can’t afford dual xenons that I really want, however by reducing my queries I’ve nearly cut my load in half. I tend to do this with classes and objects because quite frankly, bandwidth is cheap and CPU power is not.
3) Proper indexing of your tables can be a lifesaver.
4) Cut any large computational queries into smaller sub queries, that way one query isn’t hogging everything all the time. This is especially a good idea for cron jobs. I tend to have 3-4 cron files to split the workload through the night.
As far as I can tell, there is no real “solution” to this problem. If you go with load balancing servers you run just as much problem as you then have to keep the databases current in two places. One thing I’m playing around with for future games is having different servers for different parts of the world. That way you’d literally have to log into one server or the other to play where you wanted to. So there you have it, my 2 cents for what it’s worth.
I’m trying to have the next tutorial up by the end of this week 🙂