php & mySQL - character slots... how?
First of all, I am very new to PHP/mySQL. I have gone through the tutorials over at w3schools.com and I am also following along with the tutorials over HERE.
I have a working account creation, email activation, and session login scripts working, but I wanted to take it a step further and separate the 'user' from their characters, such that one user could have up to x number of character tied to their user id.
For my initial test, I was planning on using 3 character slots. The thing I am having a hard time with, is how to tie the character slots in with the database structure.
The 'base' table is 'account'. In the account table, I have the auto-increment int as the .id, and there is a 'user' field which is the persons long in name.
Right now I want there to be only 3 character slots per account, but I would like the option to scale this for the future, just to keep that in mind.
Would I just create a table of 'characters' and reference the account_id in the table? The problem I see here is how do I limit the rule of only having 3 characters per account? Would I create a 'chr_count' field in the 'account' and store the number of characters belonging to the account?
I just don't see an obvious solution to this. Would I just have to do a COUNT check when I go to create a character, to make sure there are less than 3 made?
If anyone has any great tutorials they can link me to, that would be great too.
BUnzaga
Quote:Original post by BUnzaga
Would I just create a table of 'characters' and reference the account_id in the table?
Yes, exactly.
Quote:The problem I see here is how do I limit the rule of only having 3 characters per account? Would I create a 'chr_count' field in the 'account' and store the number of characters belonging to the account?
No. The proper solution is below.
Quote:Would I just have to do a COUNT check when I go to create a character, to make sure there are less than 3 made?
Yes. [lol]
If MySQL supported the CHECK constraint, you could enforce it at schema level, even.
Note that, if you want to guard against multiple simultaneous creates, you need a transaction around the check and update. Else you'd get this:
1) User logs in, and has 2 characters.
2) User submits "create character" request.
3) User simultaneously submits second "create character" request from second browser window.
4) First submit gets to the "count" verification, which works.
5) Second submit gets to the "count" verification, which works.
6) First submit gets to create the character.
7) Second submit gets to create the character.
And now the user has 4 characters, because you had a race in your logic.
Note that, if you want to guard against multiple simultaneous creates, you need a transaction around the check and update. Else you'd get this:
1) User logs in, and has 2 characters.
2) User submits "create character" request.
3) User simultaneously submits second "create character" request from second browser window.
4) First submit gets to the "count" verification, which works.
5) Second submit gets to the "count" verification, which works.
6) First submit gets to create the character.
7) Second submit gets to create the character.
And now the user has 4 characters, because you had a race in your logic.
Hmm, that is a good point. Do you have any suggestions on how to work around that? I am sure other people have come across this issue at one time or another.
Also thanks for confirming my random ramblings hplus0603.
Also thanks for confirming my random ramblings hplus0603.
Yes, that's what transactions are for:
1) Begin transaction
2) Count characters
3) If already at 3, roll back transaction and return error
4) Create next character
5) Commit transaction
6) If commit somehow fails, return error
1) Begin transaction
2) Count characters
3) If already at 3, roll back transaction and return error
4) Create next character
5) Commit transaction
6) If commit somehow fails, return error
Ahh, I had never heard of transactions before. Thanks for pointing me in the right direction.
After doing some research and thinking about this issue, how do people prevent multiple logins of the same account on multiple computers? Take for example Adventure Quest or Fable. Do I put a 'loggedIn' flag and set it to 1 if the user logs in, and 0 if they are not logged in?
Would I also have to make some kind of 'clean up' function to process every 10 mins or so to log out anyone who has been inactive for a set amount of time? Is this what sessions are for?
Thanks again if anyone can help with this.
After doing some research and thinking about this issue, how do people prevent multiple logins of the same account on multiple computers? Take for example Adventure Quest or Fable. Do I put a 'loggedIn' flag and set it to 1 if the user logs in, and 0 if they are not logged in?
Would I also have to make some kind of 'clean up' function to process every 10 mins or so to log out anyone who has been inactive for a set amount of time? Is this what sessions are for?
Thanks again if anyone can help with this.
Quote:Original post by BUnzaga
After doing some research and thinking about this issue, how do people prevent multiple logins of the same account on multiple computers?
Do you need to worry about them being logged in on multiple computers? If this is a browser game (I'm assuming that it is), then you typically don't need to worry about this sort of thing. When I say browser game, I mean a game that actually utilizes the browser (sending HTTP requests, HTML forms, etc), not a Java Applet/Silverlight/Flash game hosted in a browser.
Quote:Original post by BUnzaga
Is this what sessions are for?
Yes. When the user connects to your server, you'd have a session created. When he or she logs in, you'd store the account that they logged into in their session.
Quote:Original post by BUnzaga
Take for example Adventure Quest or Fable. Do I put a 'loggedIn' flag and set it to 1 if the user logs in, and 0 if they are not logged in?
Would I also have to make some kind of 'clean up' function to process every 10 mins or so to log out anyone who has been inactive for a set amount of time?
Whether or not you want to store session information in the database depends on your design (ex: can your sessions migrate across servers?) Typically, sessions have a time-to-live, and if the server does not get a request within that time, it will kill the session or mark it as invalid the next time it is used.
Actual implementations of sessions depends on your design and how your system is communicating with users. A statefull MMORPG communicating over TCP/IP is going to have a different system than a web-based browser game using HTTP GET and POST requests.
If you're building a web game, then you will want to use a pre-built session system, as there are security concerns that your session has to address. Session hijacking, for example.
Well its not a 'browser game' per say, but it is 'like' a browser game. In the engine I am using, I am utilizing postToURL and post responses to manage the game.
So for a user name / password, I have two text boxes, and when both are not empty, etc, the user can press 'login'. Then when they press the button, I use a command:
system.postToURL("websitename.com/login.php", "name="+name+"&pass="+pass, "login");
Then on my web site, I use a php script to check the sql database against the user name and password, and create a session, then progress the game to the character selection screen based on the response from the post.
So it is sort of like a browser game, but the driver is not a web browser, but a 3d engine.
This is where the thought occurred to me, a person could run the game on one computer, then run the game on another computer sitting next to them. So I figured there would have to be a way to force only one instance of the account to be logged in at a time.
Any thoughts?
EDIT: I also just wanted to say thanks to everyone who has helped me so far. I have been able to create an account creation, and login screen so far. Next I'm planning on how to work out areas and monsters, etc.
[Edited by - BUnzaga on January 6, 2010 1:14:13 AM]
So for a user name / password, I have two text boxes, and when both are not empty, etc, the user can press 'login'. Then when they press the button, I use a command:
system.postToURL("websitename.com/login.php", "name="+name+"&pass="+pass, "login");
Then on my web site, I use a php script to check the sql database against the user name and password, and create a session, then progress the game to the character selection screen based on the response from the post.
So it is sort of like a browser game, but the driver is not a web browser, but a 3d engine.
This is where the thought occurred to me, a person could run the game on one computer, then run the game on another computer sitting next to them. So I figured there would have to be a way to force only one instance of the account to be logged in at a time.
Any thoughts?
EDIT: I also just wanted to say thanks to everyone who has helped me so far. I have been able to create an account creation, and login screen so far. Next I'm planning on how to work out areas and monsters, etc.
[Edited by - BUnzaga on January 6, 2010 1:14:13 AM]
If you really need to implement something like that, you could store the session id and the last time the user made request in the database.
You could then do this (pseudocode) for login:
boolean login_expired() {
return current_time - last_accessed_time > time_to_live;
}
if(current_session_id != stored_session_id && login_expired()) {
login_user();
} else {
deny_login();
}
You could do this (pseudocode) on other pages to deny logins from other sessions:
if(current_session_id != stored_session_id || login_expired()) {
require_login();
} else {
update_last_accessed();
}
Of course, you'd want to make sure that your custom TTL doesn't exceed your session's. If it does, you might end up having a logged-in user with a new session id but still inside your TTL window, meaning that he'll be kicked to the login screen, and won't be able to log in until his previous login expires.
This is also assuming that PHP doesn't move around session IDs behind your back, and you don't have any issues with session migration.
I thought I'd just add this. Something like that is very insecure. That password is going to be sent in plain-text, and may end up stored in your server logs. At the very least, you need to hash it, although your users accounts can still be broken by replay attacks should someone get access to their network or your server.
You could then do this (pseudocode) for login:
boolean login_expired() {
return current_time - last_accessed_time > time_to_live;
}
if(current_session_id != stored_session_id && login_expired()) {
login_user();
} else {
deny_login();
}
You could do this (pseudocode) on other pages to deny logins from other sessions:
if(current_session_id != stored_session_id || login_expired()) {
require_login();
} else {
update_last_accessed();
}
Of course, you'd want to make sure that your custom TTL doesn't exceed your session's. If it does, you might end up having a logged-in user with a new session id but still inside your TTL window, meaning that he'll be kicked to the login screen, and won't be able to log in until his previous login expires.
This is also assuming that PHP doesn't move around session IDs behind your back, and you don't have any issues with session migration.
Quote:
system.postToURL("websitename.com/login.php", "name="+name+"&pass="+pass, "login");
I thought I'd just add this. Something like that is very insecure. That password is going to be sent in plain-text, and may end up stored in your server logs. At the very least, you need to hash it, although your users accounts can still be broken by replay attacks should someone get access to their network or your server.
One thing I was thinking I could try. Keep in mind, I am new to this, so this might be a dumb idea. I was thinking I could generate a sha1(microtime()) session ID and then check this after every command. If the user trys to login again, then the session ID won't match.
Is this already done in some way? Am I just making it too hard?
Is this already done in some way? Am I just making it too hard?
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement