Search Unity

  1. Check out our Unite Austin 2017 YouTube playlist to catch up on what you missed. More videos coming soon.
    Dismiss Notice
  2. Unity 2017.2 is now released.
    Dismiss Notice
  3. The Unity Gear Store is here to help you look great at your next meetup, user group or conference. With all new Unity apparel, stickers and more!
    Dismiss Notice
  4. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  5. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice
  6. Unity 2017.3 beta is now available for download.
    Dismiss Notice

PHP Master Server

Discussion in 'Made With Unity' started by duhprey, Oct 31, 2010.

  1. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    Hi,

    Here's a Master Server replacement I've been using that runs in PHP. I use dreamhost and can't easily run other servers, but I can easily run php stuff :)

    This still uses Unity's default NAT facilitator. You'll need to create an sql database and table called "MasterServer" with the columns like you see in RegisterHost.php or QueryMS.php. I've also put in "PHPMasterServerConnect.js" which more or less mimics the original interface. And then there's a "MainMenu.js" which uses it and shows a list of clients and lets you join them.

    Hopefully it's pretty straight forward how to use it, but if not and there's enough interest I'll make a tutorial. If you are using it, I'd be happy to hear about it.

    Good Luck.
     

    Attached Files:

  2. enyllief

    enyllief

    Joined:
    Oct 17, 2010
    Posts:
    36
    Seems OK and well done. ;-) Would be a pleasure to check it out in-game.
     
  3. defjr

    defjr

    Joined:
    Apr 27, 2009
    Posts:
    436
    Fantastic! I use dreamhost too so this should be very handy. Thanks!
     
  4. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    If you'd like to see an example of it. I have a project on facebook where I make use. http://apps.facebook.com/WhoCutTheDeck (and don't worry it's just for fun no ads or micropayments or anything).
     
  5. Asvarduil

    Asvarduil

    Joined:
    Nov 19, 2009
    Posts:
    3,807
    This looks like a pretty sweet piece of good tech. :) I'm looking into this more, thanks for posting this!
     
  6. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    I've tried everything to get this working ... unity keeps creashing when I try to join a game. Any insite on this??
     
  7. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    I've seen that too in the editor. Try running two instances (both the host and the join) not in the editor.

    I should add, I think it's actually a bug in the unity editor with the new GUID version of connecting. I haven't yet confirmed it enough for myself to submit a bug though.
     
    Last edited: Dec 4, 2010
  8. blueice

    blueice

    Joined:
    Dec 9, 2009
    Posts:
    51
    I have other problem, it seems to register the game in the database, but I can't see the game in the "Join Game" List
     
  9. blueice

    blueice

    Joined:
    Dec 9, 2009
    Posts:
    51
    btw, thanks this is Fantastic!
     
  10. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    Ok As you said duhprey it does have something to do with the GUID and running in the editor ... if I start a client and a server in the browser it works fine accept for one thing so far ... the server never removes the game when the browser window is closed, in this case a game with no players will always be listed in the DB ... is there a fix for this. Another issue I found may help you blueice ...

    In the file QueryMS.php have a look at line 19 ....

    if ($row[$cols - 1] > 30) { continue; }

    I have no idea what this line is supposed to do ... but it keeps the php file from returning data so your game list will always be empty. Comment out this line and you should see your games.

    I think this is a great setup and will continue to use it myself, its especially useful for facebook games ... thanks duhprey. One quick question ... I had a look at you facebook example ... how did you get the user pic to show up in unity ... I know about the facebook API and have used it often but you can't send data to the unity player ... did you send this info to the DB first then query it form unity??
     
    Last edited: Dec 4, 2010
  11. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    The final column in the database is supposed to be the timestamp when the host was registered. UpdateHost.php pings that time to keep it active while the host is up. The ping is RegistrationLoop() in PHPMasterServerConnect.js. I'm not too happy with it, but all of that is supposed to handle the case where the browser closes without properly removing the host entry in the database. Line 19 means hosts which haven't called RegistrationLoop for more than 30 seconds will be ignored as dead hosts.

    It doesn't always happen that the host leaves a dangling DB entry (there is a OnDisconnectedFromServer in PHPMasterServerConnect) but I haven't figured out what causes it.

    So, if removing that line fixes it then it means you might not have the timer and update setup correctly. Reply back if that doesn't help, blueice.

    Btw, I have a github for this here https://github.com/tosos/PHPMasterServer (no difference to the version I posted here)

    On how I did the facebook stuff, I wrote about it here: http://www.tosos.com/category/unity-game-development (I can't link directly to it for some reason... it's the second post down titled "Another Game and Facebook Woes (er… Tutorial)")
     
  12. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    blueice, one other thought... if you're making a webplayer build and access the php through that they need to be hosted on the same domain. There's extra security in the webplayer to not let you access domains other than the one that hosts the unity3d file. One way to test is make a desktop build and see if it works there.
     
  13. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    Ok now the if ($row[$cols - 1] > 30) { continue; } makes some sense. But still after un-commenting that line and starting a server the game still never shows up in the list. Maybe it has something to do with the type I selected for that field in th DB. You didn't specify types so I used what I thought was best for each field ... most are pretty self explanatory. I used "DATE" for "updated" field ... maybe I should use "DATETIME", TIMESTAMP", or just "TIME" ... I'll check this out in a bit I'm in the middle of a good read.
     
  14. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    One other thing ... maybe adding an "isDead" field to the table would be a good idea ... this way when some one connects the server could send a http://yourdomain/remove_dead.php in that php file could be something like ....

    $db = mysql_connect ("host", "name", "pass");
    if (!mysql_select_db ("DB")) {
    echo "Could not select database " . mysql_error ();
    exit;
    }
    $query = "DELETE FROM MasterServer WHERE isDead='true'";
    $res = mysql_query ($query);
    if (!$res) {
    echo "Could not execute query: " . mysql_error ();
    exit;
    }
    mysql_close ($db);
    ?>

    so if the if ($row[$cols - 1] > 30) { continue; } is true we could set the "isDead" field to true. Then a clean list could be loaded ... what do ya think?
     
  15. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    Yeah, that's right. I should be DATETIME (I think NOW() is only compatible with that). isDead might work. I think there also might be a way to do it without isDead with something like

    DELETE FROM MasterServer WHERE (NOW()-updated) > 30

    I suppose thinking about it, it could be done at the beginning of QueryMS.php to delete all the inactive rows before querying, then the if ($row[$col - 1] > 30) could go away entirely.
     
  16. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    Ok great ... I'm going to play around with this right now ... will change the field to DATETIME and implement the DELETE query for dead games ... be back with results later. Oh and thanks for the link to the facebook stuff ... I'll be needing that shortly ... :)
     
  17. Antitheory

    Antitheory

    Joined:
    Nov 14, 2010
    Posts:
    549
    Since you have Dreamhost you can use your phpMyAdmin account to export the database structure to a .sql file that can be uploaded onto other servers. It's a lot easier than setting up the whole thing and avoids a lot of potential errors. It just creates a text file with all the sql commands to recreate the database. You can export with or without the actual data.

    Oh and, thanks for making this available!
     
  18. blueice

    blueice

    Joined:
    Dec 9, 2009
    Posts:
    51
    well, I am testing it from the editor and a desktop build, it registers the host but I can't see the game in the "join list"..



    and here is the php code:

    Code (csharp):
    1. <?php
    2.     $db = mysql_connect ("localhost", "********", "********");
    3.     if (!mysql_select_db ("blueice_MServer")) {
    4.     echo "Could not select database " . mysql_error ();
    5.     exit;
    6.     }
    7.     $query = "SELECT externalIp,externalPort,internalIp,internalPort,useNat,guid,gameType,gameName,connectedPlayers,playerLimit,passwordProtected,comment,NOW()-updated FROM MServer WHERE gameType='".$_REQUEST["gameType"]."';";
    8.     // echo ($query);
    9.     $res = mysql_query ($query);
    10.     if (!$res) {
    11.     echo "Could not execute query: " . mysql_error ();
    12.     exit;
    13.     }
    14.     $rows = mysql_num_rows ($res);
    15.     $cols = mysql_num_fields ($res);
    16.     $show = 0;
    17.     for ($i = 0; $i < $rows; $i ++) {
    18.        $row = mysql_fetch_row ($res);
    19.        if ($row[$cols - 1] > 30) { continue; }
    20.        if ($show == 1) {
    21.          print ";";
    22.        } else {
    23.      $show = 1;
    24.        }
    25.        if ($row[4] == "1"  $row[0] == $_SERVER['REMOTE_ADDR']) {
    26.          print $row[2].",".$row[3].",0";
    27.        } else {
    28.          print $row[0].",".$row[1].",".$row[4];
    29.        }
    30.        for ($j = 5; $j < $cols; $j ++) {
    31.          print ",".$row[$j];
    32.        }
    33.     }
    34.     mysql_free_result ($res);
    35.     mysql_close ($db);
    36. ?>
    37.  

    here you can see that the game is actually registered:
     

    Attached Files:

  19. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    Like I had mentioned before ... line 19 (if ($row[$cols - 1] > 30) { continue; }) in the file you posted blueice has something to do with it, not sure why but it wont show your list if this line of code is not commented out. As duhprey said this line just checks to see if a game has not been updated for the given amount of time ... if it hasn't it won't be shown in the list. Not sure why its not working as he intended. And actually as I said above the DB is not cleaned up after the server closes. Anyway I came up with a fix for both ... with duhprey's help. Open up the QueryMS.php file ... go to line 19 and either delete it or comment it out ... then just before the $query = "SELECT ect. call add these two lines of code ...

    $query = "DELETE FROM MasterServer WHERE (NOW()-updated) > '30';";
    $res = mysql_query ($query);

    This will remove any old games that may still be hanging around and your games should now show up in your list ... :)
    Hope this helps.

    Actually now that I'm thinking about it, it might of had somthing to do with me having the wrong data type for the "update" field in the DB, it needs to be set for DATETIME. but in any event I like the fix we came up with as it keeps the DB clean and up to date. I'm going to keep it this way.
     
    Last edited: Dec 4, 2010
  20. blueice

    blueice

    Joined:
    Dec 9, 2009
    Posts:
    51
    thanks! that did the trick, it's working now
     
  21. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    great!!! glad I could help, I'll be using this from now on and may make some changes to the visuals ... if its ok with duhprey. I'll keep everyone in the loop.
     
  22. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    I'm happy to put any changes patches in (assuming they work of course :) When I get some time I'll put in that delete line and dump out the sql structure into the github.
     
  23. phmenard2012

    phmenard2012

    Joined:
    Sep 27, 2010
    Posts:
    26
    Ok, sounds great ... I just wanted to make some changes to th GUI for now. It would be nice if when a user wanted to host a game they had more parameters other than just the game name ... such as, max players and passwords. These details would of course have to be displayed in the game list as well.
     
  24. JTown

    JTown

    Joined:
    Jan 9, 2010
    Posts:
    984
    Hmm... I can't add a server from Unity (testing in editor). I'm building for web player but it still doesn't work if target platform is standalone. I have crossdomain.xml so me building for web player shouldn't be a problem. If I copy the url into my web browser, it adds an entry -- but I get nothing if I try to do it in-game.

    edit: ok, seems to only not work in editor. Compiled for web player and it worked :)
     
    Last edited: Jan 17, 2011
  25. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    In your editor settings (Edit->Project Settings->Editor) you may need to set your emulation to tell the webplayer where it should "Pretend the Unity file is hosted here" But I'm not sure. I can get hosting to work from within the editor, but i have problems connecting to and from the editor... tends to cause it to crash when I use Connect(guid)
     
  26. JTown

    JTown

    Joined:
    Jan 9, 2010
    Posts:
    984
    Ok so I have everything working except, I think, proper nat punchthrough/facilitation.

    Example: Friend started a game, successfully added it to the master server database -- I can see this game but cannot join. It was listed as useNat == 1 if that makes a difference.

    What can I do to ensure only connectible games show up in the list of servers...? Or am I misunderstanding what NAT punchthrough/facilitation can do? I'm confused about how this master server uses Unity's default facilitator, too.
     
    Last edited: Jan 18, 2011
  27. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    At this point, I don't know. Something about the switch to guid in unity 3 is creating this issue. I find that some people can host and others can't but almost everyone can connect.

    However, in general, code for the ConnectionTester needs to be part of the server registration to determine if it should bother registering with the MasterServer and also on the client to determine what it can connect to and filter out of the server list. I will add it at some point. I also need to push an update for the mainmenu that does error reporting.
     
  28. megmaltese

    megmaltese

    Joined:
    Mar 19, 2009
    Posts:
    1,940
    If I click START nothing happens.
     
  29. Silentcoast

    Silentcoast

    Joined:
    Mar 23, 2010
    Posts:
    140
    First off thanks for the post and sharing with the community!

    megmaltese that's pretty vague, maybe give some information on what you've tried, any error messages ect ect.
     
  30. Intertricity

    Intertricity

    Joined:
    Sep 27, 2010
    Posts:
    6
    This is an incredible concept duhprey, I'd say one of the more important ones in regards to indie networked games. The cost of a php-enabled webhost is far more feasible than the dedicated funding required to use a service that can run binaries. Host a networked game for less than it costs to go to Wendy's? Count me in!

    I hope you make a tutorial for this soon :D ty so much for making this!
     
  31. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,061
    You still need to host a facilitator and connection tester somewhere. You can however do that for far less money as the bandwidth/memory requirements will be very low.
     
  32. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
  33. megmaltese

    megmaltese

    Joined:
    Mar 19, 2009
    Posts:
    1,940
    Well, it's really how I wrote it: I click START here and nothing happens apart a small flicker down left.
     
  34. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    I've noticed it sometimes ignores a click to the start button. Try clicking and holding, you should see it depress. Also make sure your picture and name have shown up (although it won't stop the game from starting)
     
  35. megmaltese

    megmaltese

    Joined:
    Mar 19, 2009
    Posts:
    1,940
    Tried that too, still the same non reaction.
     
  36. psychicparrot

    psychicparrot

    Joined:
    Dec 10, 2007
    Posts:
    870
    Wow! Thats pretty darn sweet thanks :)
     
  37. DemonReinhardt

    DemonReinhardt

    Joined:
    Feb 2, 2011
    Posts:
    7
    I'm checking it out but to be honest I don't understand it 100% (i'm new to unity and facebook api, by the way). You got my vote for a tutorial :p

    I'm trying to integrate my game to facebook, I already did the Iframe steps of the other incomplete tutorial that you mentioned. Now I want to make some ranking system for the users of my game, and also to make my game to allow users to post in their walls.
    Any suggestions are appreciated
    Thanks
     
  38. ND

    ND

    Joined:
    Aug 3, 2012
    Posts:
    60
    In your code you're however using MasterServer.RegisterHost (conn.gameType, conn.gameName, ""); function which means you are using default only testing purpose MasterServer of Unity. So if that server goes down (which is common) this game goes down too. I didn't get the point here, why we would use this solution at all since that MasterServer gives us all theses perfectly?
     
  39. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    That code I still haven't figured out if its necessary or not. The point there is to set the external ip and external port values in Network.player so that they can register correctly in the phpmaster server. I've noticed though that sometimes its enough to have The web access also set those, so I'm not sure working backwards whether its necessary or not. That call will work whether or not the testing master server is up. But maybe won't properly set the external port when registering.
     
  40. ND

    ND

    Joined:
    Aug 3, 2012
    Posts:
    60
    I think this code does copy the structure of Unity MasterServer to a database. That's all. If you delete the MasterServer.RegisterHost (conn.gameType, conn.gameName, ""); line in the code, it wont work anymore. Because it's related to the main unity's MasterServer class. So why would it be useful? all the php requests and results exists in the original MasterServer class. The code is just a duplicate.
     
  41. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    Yes, that's right. This code copies the structure to a database, which is essentially what the original master server does. The queryms.php file then queries that db entry from a client side.
     
  42. shame

    shame

    Joined:
    Jun 25, 2012
    Posts:
    130
    at RegisterHost.php you forgot to replace stuff in this line for config file, according to version on github

    $db = mysql_connect ("server_name", "user_name", "password");
    ... etc
     
  43. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    Ah, good catch. Fixed, thanks.
     
  44. shame

    shame

    Joined:
    Jun 25, 2012
    Posts:
    130
    also you forgot to
    echo 'succeeded';
    at the same file, where query gets successfully executed.

    brilliant stuff anyway, thankies c:
     
  45. shame

    shame

    Joined:
    Jun 25, 2012
    Posts:
    130
    Code (csharp):
    1. $query = "SELECT externalIp,externalPort,internalIp,internalPort,useNat,guid,gameType,gameName, ...
    2. ...
    3. if ($row[4] == "1"  $row[0] == $_SERVER['REMOTE_ADDR']) {
    4.         print $row[2].",".$row[3].",0";
    5.     } else {
    6.         print $row[0].",".$row[1].",".$row[4];
    7.     }
    should swap code at the if condition, otherwise it doesn't work for me
     
  46. deve

    deve

    Joined:
    Dec 24, 2012
    Posts:
    3
    Hi all,

    I have a newbie question to this topic. Gamespy did drop the Deer Hunter 2005 servers. Noone can see there servers online now.
    My question is can I use this for to create a masterserver for this game and how ?

    ANy help whould be great , Thanks .
     
  47. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    Unfortunately without access to the deerhunter source code, no it wouldn't be possible to put this server up in place of the gamespy servers.
     
  48. DLGScript

    DLGScript

    Joined:
    Jul 15, 2012
    Posts:
    264
    What do i need to put in "Master Server URL"???
     
  49. duhprey

    duhprey

    Joined:
    Nov 13, 2009
    Posts:
    163
    Put the URL where you've place the php scripts.
     
  50. DLGScript

    DLGScript

    Joined:
    Jul 15, 2012
    Posts:
    264
    and how do i host a game and make him to be shown in the servers list?