Advertisement
masa-

MC ping/query function in PHP, with player names

Aug 12th, 2019
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 3.34 KB | None | 0 0
  1. // A verbose version of server query. Requires enable-query=true in server.properties
  2. function full_stat($host, $port = 25565, $timeout_s = 0, $timeout_us = 50000)
  3. {
  4.     $errno = 0;
  5.     $errstr = "";
  6.  
  7.     //Set up our socket
  8.     $fp = @fsockopen("udp://" . $host, $port, $errno, $errstr);
  9.  
  10.     if (! $fp)
  11.     {
  12.         //echo "no socket!<br />\n";
  13.         return array();
  14.     }
  15.  
  16.     // Handshake:
  17.     // Get the challenge token; send 0xFE 0xFD 0x09 and a 4-byte session id
  18.     $str1 = "\xFE\xFD\x09\x00\x00\x00\x01"; // Arbitrary session id at the end (4 bytes) (we use 00 00 00 01 here)
  19.     fwrite($fp, $str1);
  20.  
  21.     // Set the time out limit
  22.     stream_set_timeout($fp, $timeout_s, $timeout_us);
  23.     $arr = stream_get_meta_data($fp);
  24.  
  25.     if ($arr['timed_out'])
  26.     {
  27.         //echo "timed out!<br />\n";
  28.         return array();
  29.     }
  30.  
  31.     $resp = fread($fp, 4096);
  32.  
  33.     // Check that we got something back
  34.     if (strlen($resp) == 0)
  35.     {
  36.         //echo "empty response!<br />\n";
  37.         return array();
  38.     }
  39.  
  40.     // Check for a valid response
  41.     if ($resp[0] != "\x09")
  42.     {
  43.         //echo "not a valid response!<br />\n";
  44.         return array();
  45.     }
  46.  
  47.     // Parse the challenge token from string to integer
  48.     $token = 0;
  49.     for ($i = 5; $i < (strlen($resp) - 1); $i++)
  50.     {
  51.         $token *= 10;
  52.         $token += $resp[$i];
  53.     }
  54.  
  55.     // Divide the int32 into 4 bytes
  56.     $token_arr = array( 0 => ($token / (256*256*256)) % 256,
  57.                 1 => ($token / (256*256)) % 256,
  58.                 2 => ($token / 256) % 256,
  59.                 3 => ($token % 256)
  60.             );
  61.  
  62.     // Note that the challenge token is bound to your IP and port (as opposed to the [session ID]), and
  63.     // lasts up to 30 seconds. You read that right, it's up to; it's not "your token will expire
  64.     // after 30 seconds", it's "every token ever" is expired every 30 seconds. This means it's entirely
  65.     // possible that you may get a token and use it within the same second and have it expire.
  66.  
  67.     // Get the full version of server status
  68.     // Session ID and challenge tokens appended to magic header 0xFE 0xFD and command byte 0x00
  69.     // Payload padded to 8 bytes
  70.     $str = "\xFE\xFD\x00\x00\x00\x00\x01"
  71.         . chr($token_arr[0]) . chr($token_arr[1]) . chr($token_arr[2]) . chr($token_arr[3])
  72.         . "\x00\x00\x00\x00";
  73.     fwrite($fp, $str);
  74.  
  75.     $data = fread($fp, 4096);
  76.     $full_stat = substr($data, 16);     // Strip the crap from the start
  77.  
  78.     $tmp = explode("\x00\x01player_\x00\x00", $full_stat);  // First, split the payload in two parts
  79.     $keysvalues = explode("\x00", $tmp[0]);         // Divide the first part from every NULL-terminated string end into key1 val1 key2 val2...
  80.     unset($keysvalues[count($keysvalues) - 1]);     // Unset the last entry, because the are two 0x00 bytes at the end
  81.  
  82.     // Strip all the NULL-bytes from the end of the player list
  83.     $tmp = $tmp[1];
  84.     $i = strlen($tmp) - 1;
  85.  
  86.     while ($i >= 0)
  87.     {
  88.         if (ord($tmp[$i]) != 0)
  89.         {
  90.             break;
  91.         }
  92.  
  93.         $i--;
  94.     }
  95.  
  96.     // Split the player information (if any)
  97.     if ($i > 0)
  98.     {
  99.         $tmp = substr($tmp, 0, $i + 1);
  100.         $players = explode("\x00", $tmp);   // Explode the player information from the NULL-byte positions
  101.     }
  102.     else
  103.     {
  104.         $tmp = FALSE;
  105.     }
  106.  
  107.     // Arrange the key => value pairs into an array
  108.     $info = array();
  109.  
  110.     for ($i = 0; $i < count($keysvalues); $i += 2)
  111.     {
  112.         if ($keysvalues[$i] == "")
  113.         {
  114.             break;
  115.         }
  116.  
  117.         $info[$keysvalues[$i]] = $keysvalues[$i + 1];
  118.     }
  119.  
  120.     // Collect all the information into one array
  121.     $full_stat = $info;
  122.     $full_stat['players'] = $players;
  123.  
  124.     return $full_stat;
  125. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement