Advertisement
masa-

Minecraft server query in PHP

Mar 18th, 2012
880
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 4.94 KB | None | 0 0
  1. <?php
  2.  
  3. function ping($host, $port = 25565, $timeout = 1)
  4. {
  5.  
  6.     //Set up our socket
  7.     $fp = fsockopen("tcp://" . $host, $port, $errno, $errstr, $timeout);
  8.     stream_set_timeout($fp, 1);
  9.     $arr = stream_get_meta_data($fp);
  10.  
  11.     if($arr['timed_out'] == TRUE)
  12.         return array();
  13.  
  14.     if(!$fp)
  15.         return array();
  16.  
  17.     //Send 0xFE: Server list ping
  18.     fwrite($fp, "\xFE");
  19.  
  20.     //Read as much data as we can (max packet size: 241 bytes)
  21.     $d = fread($fp, 256);
  22.  
  23.     //Check we've got a 0xFF Disconnect
  24.     if($d[0] != "\xFF")
  25.         return array();
  26.  
  27.     //Remove the packet ident (0xFF) and the short containing the length of the string
  28.     $d = substr($d, 3);
  29.  
  30.     //Decode UCS-2 string
  31.     $d = mb_convert_encoding($d, 'auto', 'UCS-2');
  32.  
  33.     //Split into array
  34.     $d = explode("\xA7", $d);
  35.  
  36.     //Return an associative array of values
  37.     return array(
  38.             'motd'      => $d[0],
  39.             'players'   => intval($d[1]),
  40.             'max_players'   => intval($d[2])
  41.         );
  42. }
  43.  
  44.  
  45.  
  46. function full_stat($host, $port = 25565, $timeout = 1)
  47. {
  48.     //Set up our socket
  49.     $fp = fsockopen("udp://" . $host, $port, $errno, $errstr, $timeout);
  50.  
  51.     stream_set_timeout($fp, 1);
  52.     $arr = stream_get_meta_data($fp);
  53.  
  54.     if($arr['timed_out'] == TRUE)
  55.         return array();
  56.  
  57.     if(!$fp)
  58.         return array();
  59.  
  60.     // Get the challenge token; send 0xFE 0xFD 0x09 and a 4-byte session id
  61.     $str1 = "\xFE\xFD\x09\x01\x02\x03\x04"; // Arbitrary session id at the end (4 bytes)
  62.     fwrite($fp, $str1);
  63.     $resp1 = fread($fp, 256);
  64.  
  65.     if(strlen($resp1) > 0)
  66.     {
  67.         if($resp1[0] != "\x09") // Check for a valid response
  68.             return array();
  69.     }
  70.     else
  71.         return array();
  72.  
  73.     // Parse the challenge token from string to integer
  74.     $token = 0;
  75.     for($i = 5; $i < (strlen($resp1) - 1); $i++)
  76.     {
  77.         $token *= 10;
  78.         $token += $resp1[$i];
  79.     }
  80.  
  81.     // Divide the int32 into 4 bytes
  82.     $token_arr = array( 0 => ($token / (256*256*256)) % 256,
  83.                 1 => ($token / (256*256)) % 256,
  84.                 2 => ($token / 256) % 256,
  85.                 3 => ($token % 256)
  86.             );
  87. /*
  88.     // Get the short version of server status. ID and challenge tokens are appended to the command 0x00.
  89.     $str = "\xFE\xFD\x00\x01\x02\x03\x04"
  90.         . chr($token_arr[0]) . chr($token_arr[1]) . chr($token_arr[2]) . chr($token_arr[3]);
  91.     fwrite($fp, $str);
  92.     $data1 = fread($fp, 4096);
  93.     $short_stat = substr($data1, 5);    // Strip the crap from the start
  94.  
  95.     $short_stat = explode("\x00", $short_stat); // Explode the payload from the NULL-terminated string ends
  96.     $port = ord($short_stat[5][1]) * 256 + ord($short_stat[5][0]);  // Big-endian short
  97.  
  98.     $short_stat = array(    'motd'      => $short_stat[0],
  99.                 'gametype'  => $short_stat[1],
  100.                 'map'       => $short_stat[2],
  101.                 'numplayers'    => $short_stat[3],
  102.                 'maxplayers'    => $short_stat[4],
  103.                 'portnum'   => $port,
  104.                 'hostname'  => substr($short_stat[5], 2)    // Host IP after the port number
  105.             );
  106. */
  107.  
  108.     // Get the full version of server status. ID and challenge tokens appended to command 0x00, payload padded to 8 bytes.
  109.     $str = "\xFE\xFD\x00\x01\x02\x03\x04"
  110.         . chr($token_arr[0]) . chr($token_arr[1]) . chr($token_arr[2]) . chr($token_arr[3])
  111.         . "\x00\x00\x00\x00";
  112.     fwrite($fp, $str);
  113.     $data2 = fread($fp, 4096);
  114.     $full_stat = substr($data2, 11);    // Strip the crap from the start
  115.  
  116.     $tmp = explode("\x00\x01player_\x00\x00", $full_stat);  // First, split the payload in two parts
  117.     $t = explode("\x00", $tmp[0]);      // Divide the first part from every NULL-terminated string end into key1 val1 key2 val2...
  118.     unset($t[count($t) - 1]);       // Unset the last entry, because the are two 0x00 bytes at the end
  119.     $t2 = explode("\x00", $tmp[1]);     // Explode the player information from the second part
  120.  
  121.     $info = array();
  122.     for($i = 0; $i < count($t); $i += 2)
  123.     {
  124.         if($t[$i] == "")
  125.             break;
  126.  
  127.         $info[$t[$i]] = $t[$i + 1];
  128.     }
  129.  
  130.     $players = array();
  131.     foreach($t2 as $one)
  132.     {
  133.         if($one == "")
  134.             break;
  135.  
  136.         $players[] = $one;
  137.     }
  138.  
  139.     $full_stat = $info;
  140.     $full_stat['players'] = $players;
  141.  
  142.     return $full_stat;
  143. }
  144.  
  145. /*
  146. $arr = ping("localhost", 25565, 2);
  147.  
  148. echo "<pre>\n";
  149. print_r($arr);
  150. echo "</pre>\n";
  151. */
  152.  
  153. $arr = full_stat("localhost", 25565, 1);
  154.  
  155. echo "<pre>\n";
  156. print_r($arr);
  157. echo "</pre>\n";
  158.  
  159. /*
  160. echo "<pre>\n";
  161. echo "token (resp1): ";
  162. for($i = 0; $i < strlen($resp1); $i++)
  163. {
  164.     printf("0x%02X ", ord($resp1[$i]));
  165.  
  166. }
  167.  
  168. echo "\nstr: ";
  169. for($i = 0; $i < strlen($str); $i++)
  170. {
  171.     printf("0x%02X ", ord($str[$i]));
  172. }
  173.  
  174. echo "\ndata1: ";
  175. for($i = 0; $i < strlen($data1); $i++)
  176. {
  177.     printf("0x%02X ", ord($data1[$i]));
  178. }
  179.  
  180. echo "\ndata2: ";
  181. for($i = 0; $i < strlen($data2); $i++)
  182. {
  183.     printf("0x%02X ", ord($data2[$i]));
  184. }
  185.  
  186. echo "\ntoken (int32): $token\ntoken_arr: ";
  187.  
  188. print_r($token_arr);
  189.  
  190.     for($i = 0; $i < 4; $i++)
  191.         printf("0x%02X ", $token_arr[$i]);
  192.  
  193. echo "\n\nshort_stat:\n";
  194. print_r($short_stat);
  195.  
  196. echo "\n\nfull_stat:\n";
  197. print_r($full_stat);
  198.  
  199. echo "</pre>\n";
  200.  
  201. echo "<br />errno:\n";
  202. print_r($errno);
  203. echo "<br />errstr:\n";
  204. print_r($errstr);
  205. echo "<br />data1:\n";
  206. for($i = 0; $i < strlen($data1); $i++)
  207. {
  208.     printf("0x%02X ", ord($data1[$i]));
  209. }
  210. echo "</pre>\n";
  211. */
  212.  
  213. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement