Advertisement
Guest User

MinecraftQuery.class.php

a guest
May 28th, 2014
305
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.53 KB | None | 0 0
  1. <?php
  2. class MinecraftQueryException extends Exception
  3. {
  4. // Exception thrown by MinecraftQuery class
  5. }
  6.  
  7. class MinecraftQuery
  8. {
  9. /*
  10. * Class written by xPaw
  11. *
  12. * Website: http://xpaw.ru
  13. * GitHub: https://github.com/xPaw/PHP-Minecraft-Query
  14. */
  15.  
  16. private $Socket;
  17. private $Challenge;
  18. private $Players;
  19. private $Info;
  20.  
  21. public function Connect( $Ip = '88.191.242.16', $Port = 10252, $Timeout = 3 )
  22. {
  23. if( $this->Socket = FSockOpen( 'udp://' . $Ip, (int)$Port ) )
  24. {
  25. Socket_Set_TimeOut( $this->Socket, $Timeout );
  26.  
  27. if( !$this->GetChallenge( ) )
  28. {
  29. FClose( $this->Socket );
  30. throw new MinecraftQueryException( "Failed to receive challenge." );
  31. }
  32.  
  33. if( !$this->GetStatus( ) )
  34. {
  35. FClose( $this->Socket );
  36. throw new MinecraftQueryException( "Failed to receive status." );
  37. }
  38.  
  39. FClose( $this->Socket );
  40. }
  41. else
  42. {
  43. throw new MinecraftQueryException( "Can't open connection." );
  44. }
  45. }
  46.  
  47. public function GetInfo( )
  48. {
  49. return isset( $this->Info ) ? $this->Info : false;
  50. }
  51.  
  52. public function GetPlayers( )
  53. {
  54. return isset( $this->Players ) ? $this->Players : false;
  55. }
  56.  
  57. private function GetChallenge( )
  58. {
  59. $Data = $this->WriteData( "\x09" );
  60.  
  61. if( !$Data )
  62. {
  63. return false;
  64. }
  65.  
  66. $this->Challenge = Pack( 'N', $Data );
  67.  
  68. return true;
  69. }
  70.  
  71. private function GetStatus( )
  72. {
  73. $Data = $this->WriteData( "\x00", $this->Challenge . "\x01\x02\x03\x04" );
  74.  
  75. if( !$Data )
  76. {
  77. return false;
  78. }
  79.  
  80. $Last = "";
  81. $Info = Array( );
  82.  
  83. $Data = SubStr( $Data, 11 ); // splitnum + 2 int
  84. $Data = Explode( "\x00\x00\x01player_\x00\x00", $Data );
  85. $Players = SubStr( $Data[ 1 ], 0, -2 );
  86. $Data = Explode( "\x00", $Data[ 0 ] );
  87.  
  88. // Array with known keys in order to validate the result
  89. // It can happen that server sends custom strings containing bad things (who can know!)
  90. $Keys = Array(
  91. 'hostname' => 'HostName',
  92. 'gametype' => 'GameType',
  93. 'version' => 'Version',
  94. 'map' => 'Map',
  95. 'numplayers' => 'Players',
  96. 'maxplayers' => 'MaxPlayers',
  97. 'hostport' => 'HostPort',
  98. 'hostip' => 'HostIp'
  99. );
  100.  
  101. foreach( $Data as $Key => $Value )
  102. {
  103. if( ~$Key & 1 )
  104. {
  105. if( !Array_Key_Exists( $Value, $Keys ) )
  106. {
  107. $Last = false;
  108. continue;
  109. }
  110.  
  111. $Last = $Keys[ $Value ];
  112. $Info[ $Last ] = "";
  113. }
  114. else if( $Last != false )
  115. {
  116. $Info[ $Last ] = $Value;
  117. }
  118. }
  119.  
  120. // Ints
  121. $Info[ 'Players' ] = IntVal( $Info[ 'Players' ] );
  122. $Info[ 'MaxPlayers' ] = IntVal( $Info[ 'MaxPlayers' ] );
  123. $Info[ 'HostPort' ] = IntVal( $Info[ 'HostPort' ] );
  124.  
  125. // Parse "plugins", if any
  126. if( $Info[ 'Plugins' ] )
  127. {
  128. $Data = Explode( ": ", $Info[ 'Plugins' ], 2 );
  129.  
  130. $Info[ 'RawPlugins' ] = $Info[ 'Plugins' ];
  131. $Info[ 'Software' ] = $Data[ 0 ];
  132.  
  133. if( Count( $Data ) == 2 )
  134. {
  135. $Info[ 'Plugins' ] = Explode( "; ", $Data[ 1 ] );
  136. }
  137. }
  138. else
  139. {
  140. $Info[ 'Software' ] = 'Vanilla';
  141. }
  142.  
  143. $this->Info = $Info;
  144.  
  145. if( $Players )
  146. {
  147. $this->Players = Explode( "\x00", $Players );
  148. }
  149.  
  150. return true;
  151. }
  152.  
  153. private function WriteData( $Command, $Append = "" )
  154. {
  155. $Command = "\xFE\xFD" . $Command . "\x01\x02\x03\x04" . $Append;
  156. $Length = StrLen( $Command );
  157.  
  158. if( $Length !== FWrite( $this->Socket, $Command, $Length ) )
  159. {
  160. return false;
  161. }
  162.  
  163. $Data = FRead( $this->Socket, 1440 );
  164.  
  165. if( StrLen( $Data ) < 5 || $Data[ 0 ] != $Command[ 2 ] )
  166. {
  167. return false;
  168. }
  169.  
  170. return SubStr( $Data, 5 );
  171. }
  172. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement