ut3 Global Player Stats API

My ut3 Global Player Stats Projects relies on the Stats aquired by GameSpy. It looks like the have changed their Authentication scheme recently and this resulted in a nonworking Stats Application.

I Updated the Code and fixed some minor Bugs to make it work again!

Please Notice: You need to use the UT3 Account now, not an Account from login.gamespy.com. I know it was confusing before and now it should be more logical!

Hope you enjoy the possibillities!

Comments (14)

  1. Guest

    Hi apoohis!

    The first example webpage looks really great, but I can't see no details (like kills, weapons stats etc) if I click a player's name.After some time this strange field pops up: "Key -> Server" and "Value -> was".

    Can you tell me how to proceed with the console program to get to some results? Do I need a .net application server or can I test the tool locally, where have I to add my gamespy data etc.?

    Big thx & greets, Tom

    • Guest

      Hi apophis,

      After some trying around I made a .txt file and put this text in it

      ut3playerStats.exe -g MYUSERNAME MYUSERPASSWORS -q Nick PlayerDM_ELO Pure_PlayerDM_ELO

      I renamed the .txt to .bat and ran it in the same folder. It created a file named ticket.cache, which contains a code like this DsB2rOi73ukwFllMbv5lAv__.

      Still I can't figure out what I shall do exactly. Is there some kind of FAQ for dummies like me?

      Greets, Tom

    • apophis

      Obviously the program is running for you, obviously --q-all is timing out at the moment, I dont know exactly what GameSpy has changed again. Obviously its not possible to query all the fields at the same time anymore. (maybe I change it so the details will show up on the page again)

      The Commandline tool can be executed via a bat file if you want. You need to redirect the output to a file if you want to see it. Make a bat file with the following to see the top ten.

      Your example would look like this:

      ut3playerStats.exe -g MYUSERNAME MYUSERPASSWORS -q Nick PlayerDM_ELO Pure_PlayerDM_ELO > output.txt

      Now the result is in the File output.txt, the ticket.cache file is not for users, the program can reuse its Ticket that way.

      Hope this helps a bit! (BTW have you looked at the Project Page -> HERE)
       

      • Guest

        Thanks for replying!

        Obviously the program is running for you, obviously --q-all is timing out at the moment, I dont know exactly what GameSpy has changed again.

        Ok, I saw that the details didn't work on your ProjectX Example Website either. Just strange that the stats on Enemydown and on the DFB Clan weren't affected. I thought I made the mistake. =/

        The Commandline tool can be executed via a bat file if you want.
        ut3playerStats.exe -g MYUSERNAME MYUSERPASSWORS -q Nick PlayerDM_ELO Pure_PlayerDM_ELO > output.txt

        Learned something new, thanks for the output to txt code! I made a screenshot of the window as it was computing, so I could see that it worked for example for the "player using the tank the most" code.

        Hope this helps a bit! (BTW have you looked at the Project Page -> HERE)

        Have seen it, but I'm not capable to insert the app to a php site or build something similar like this: http://www.dfbgaming.com/ut3_stats/index.php?game_name=ut3pc&stat_type=pure
        I would like just the actual stats of some player accounts... would there be a possibility to wireshark their code? Sry that I'm so unexperienced with all this! :(

        Grüße ;), Tom

        • apophis

          Well you can get the deatails just not in one query which queries all the fields (-q-all) ... to retrieve only the turret stats or only the vehicle stats is no problem.

          Here is some PHP example code I am using, this code is working, you need mono installed on the webserver, or you can drop "mono" if you run the PHP on Windows:

          $gamespy = "mono ./ut3ps -g "; // Linux / mono
          // pure servers or not
          if ($pure) {
          exec($gamespy." -u ".$idx." --q-general -p", $output);
          } else {
          exec($gamespy." -u ".$idx." --q-general -p --custom", $output);
          }
          foreach($output as $line)
          {
          if($line != "") {
          $value = explode(" ",$line);
          echo '
          '.$value[0].' '.$value[1].'

          ';
          }
          }
          ?>

          • Guest

            Thanks man!

            I got to get more familiar with php and than I'll try to set up  some stats for a bounch of people =)

            Greets, Tom

  2. Guest

    Strange, I still use ticket derived from login.gamespy.com on my site (written on Python while using your app as reference, then rewritten again on PHP) without any problems. I've rerequested ticket and it still works.

    • apophis

      Maybe you already did it right in your rewrite? ... The ID depends on different other IDs I had to change them to the correct UT3 IDs.

      I definitly stopped working for me locally and on the server. And I fixed it with the change of the call!

      • Guest

        My ticket query looks like this: "\\login\\\\challenge\\%s\\uniquenick\\%s\\response\\%s\\port\\%s\\namespaceid\\1\\id\\1\\final\\". So it has nothing related with UT3 at all. And it still works with the SakeStorage.

        I also noted that one ticket can be used indefinitely if you don't log off. Even if you getting another ticket with the same login credentials, the older ones would still work.

        By the way, do you know what cacheFlag does? I was unable to see any difference.

        • apophis

          I havent checked how long a ticket is valid, however I thought they lose validity after some time.

          I dont know what cacheFlag does, but I am pretty sure that it is a db thing, some "RealTime" data aginst some "cached" snapshot.

          The only thing I know is, I got an error message after my login, which was gone after I changed some id's. I used the values directly from ut3. Maybe you have som other id's which work too. (I havent used 1/1 before).

  3. Guest

    Thanks for the help. I was absolutely confused and was looking in the wrong place for the fix. Appreciate it!

  4. Guest

    Battlefield 2142 uses Gamespy also. I have been trying to implement this in PHP. TcpClient is basically a wrapper for the fsock set of functions in PHP. I can provide that also. I am getting the following output:

    \error\\err\265\fatal\\errmsg\The uniquenick provided is incorrect.\id\1\final\

    The PHP:

    <?php
    require('tcp.class.php');

    class bf2142_stats {
        public $host = "gpcm.gamespy.com", $port = 29900, $buffer = 2048,$c,$spaces48 = "                                                ";
        private $alphanumeric = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
                            'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
                            'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
       
        public function __construct ($nick = 'usernameIuseToLoginToBF2142', $pass = 'MYSECRETPASSWORD') {
            $this->c = new TcpClient($this->host, $this->port);
            $this->c->Connect();
            $first_response = $this->c->Read($this->buffer);
            $serverChallenge = $this->getParamVal($first_response, 'challenge');
            $clientChallenge = $this->createRandStr(32);
            $response = $this->getResponseValue($nick, $pass, $clientChallenge, $serverChallenge);
            $login = "\\login\\" .
                               "\\challenge\\" . $clientChallenge .
                               "\\uniquenick\\" . $nick .
                               "\\partnerid\\0" .
                               "\\response\\" . $response .
                               "\\port\\" . rand(1,32768) .
                               "\\productid\\10871" .
                               "\\gamename\\stella" .
                               "\\namespaceid\\64" .
                               "\\sdkrevision\\3" .
                               "\\id\\1" .
                               "\\final\\";
            $this->c->Write($login);
            $second_response = $this->c->Read($this->buffer);
            echo $second_response;
        }
        private function createRandStr($length) {
            $s = "";
            while ($length > 0) {
                $length--;
                $s .= $this->alphanumeric[rand(0,61)];
            }
            return s;
        }
        private function getParamVal($message, $parameter) {
            $arr = explode("\\",$message);
            $next = false;
            foreach ($arr as $part) {
                if ($next) { return $part; }
                if ($part == $parameter) { $next = true; }
            }
            return "";
        }
        private $BtoH = array( "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
                                      "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
                                      "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
                                      "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
                                      "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
                                      "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
                                      "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
                                      "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
                                      "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
                                      "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
                                      "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
                                      "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
                                      "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
                                      "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
                                      "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
                                      "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff" );
       
        private function getResponseValue($nickname, $password, $clientChallenge, $serverChallenge) {
            $passwordHash = md5($password);
            $passwordSplit = str_split($passwordHash);
            $pwmd5 = "";
            foreach ($passwordSplit as $b) {
                $pwmd5 .= $this->BtoH[$b];
            }
            $finalHash = md5($pwmd5 . $this->spaces48 . $nickname . $clientChallenge . $serverChallenge . $pwmd5);
            $finalSplit = str_split($finalHash);
            $result = "";
            foreach ($finalSplit as $b) {
                $result .= $this->BtoH[$b];
            }
            return $result;
        }
    }
    $bf = new bf2142_stats();

    ?>

    • apophis

      Sorry, forgot to check the Comment Queue (damn spammers)

      I have not found any obvious errors, The namespaceid could be wrong since its another game. The best way to get a result is to try to see the stats in your game and look what your game sends to the server.

      Wireshark can do that pretty well and its also the way I have debugged the protocol.

      Try to build the packets exactly the way your game does, its a simple way to make sure you don't do something wrong. Well besides the challenge obviously.

      Greets
      Apophis

  5. Transporter

    The downloads are not working. I'm still interested in your stats tool.

Write a comment

Comments appear once they have been approved.