Guest User

Untitled

a guest
Jan 2nd, 2017
69
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2. /**
  3. * This API connects directly to the server, without any need for any
  4. * middlemen connections.
  5. * Your server must have fsockopen enabled in order to access the
  6. * functions that have been made available from this.
  7. *
  8. * @package sampAPI
  9. * @version 1.2
  10. * @author David Weston <westie@typefish.co.uk>
  11. * @copyright 2010; http://www.typefish.co.uk/licences/
  12. */
  13.  
  14.  
  15. class SampQueryAPI
  16. {
  17. /**
  18. * @ignore
  19. */
  20. private $rSocket = false;
  21.  
  22.  
  23. /**
  24. * @ignore
  25. */
  26. private $aServer = array();
  27.  
  28.  
  29. /**
  30. * Creation of the server class.
  31. *
  32. * @param string $sServer Server IP, or hostname.
  33. * @param integer $iPort Server port
  34. */
  35. public function __construct($sServer, $iPort = 7777)
  36. {
  37. /* Fill some arrays. */
  38. $this->aServer[0] = gethostbyname($sServer);
  39. $this->aServer[1] = $iPort;
  40.  
  41. /* Start the connection. */
  42. if(!filter_var($this->aServer[0], FILTER_VALIDATE_IP)) {
  43. $this->aServer[4] = false;
  44. return;
  45. }
  46. $this->rSocket = fsockopen('udp://'.$this->aServer[0], $this->aServer[1], $iError, $sError, 2);
  47.  
  48. if(!$this->rSocket)
  49. {
  50. $this->aServer[4] = false;
  51. return;
  52. }
  53.  
  54. socket_set_timeout($this->rSocket, 2);
  55.  
  56. $sPacket = 'SAMP';
  57. $sPacket .= chr(strtok($this->aServer[0], '.'));
  58. $sPacket .= chr(strtok('.'));
  59. $sPacket .= chr(strtok('.'));
  60. if(strtok('.') !== FALSE)
  61. $sPacket .= chr(strtok('.'));
  62. $sPacket .= chr($this->aServer[1] & 0xFF);
  63. $sPacket .= chr($this->aServer[1] >> 8 & 0xFF);
  64. $sPacket .= 'p4150';
  65.  
  66. fwrite($this->rSocket, $sPacket);
  67.  
  68. if(fread($this->rSocket, 10))
  69. {
  70. if(fread($this->rSocket, 5) == 'p4150')
  71. {
  72. $this->aServer[4] = true;
  73. return;
  74. }
  75. }
  76.  
  77. $this->aServer[4] = false;
  78. }
  79.  
  80.  
  81. /**
  82. * @ignore
  83. */
  84. public function __destruct()
  85. {
  86. @fclose($this->rSocket);
  87. }
  88.  
  89.  
  90. /**
  91. * Used to tell if the server is ready to accept queries.
  92. *
  93. * If false is returned, then it is suggested that you remove the
  94. * class from active use, so that you can reload the class if needs
  95. * be.
  96. *
  97. * @return bool true if success, false if failure.
  98. */
  99. public function isOnline()
  100. {
  101. return isset($this->aServer[4]) ? $this->aServer[4] : false;
  102. }
  103.  
  104.  
  105. /**
  106. * This function is used to get the server information.
  107. *
  108. * <code>
  109. * Array
  110. * (
  111. * [password] => 0
  112. * [players] => 9
  113. * [maxplayers] => 500
  114. * [hostname] => Everystuff Tr3s [MAD]oshi (03a Final) [FIXED]
  115. * [gamemode] => Stunt/Race/DM/FR Everystuff
  116. * [mapname] => Everystuff
  117. * )
  118. * </code>
  119. *
  120. * @return array Array of server information.
  121. */
  122. public function getInfo()
  123. {
  124. @fwrite($this->rSocket, $this->createPacket('i'));
  125.  
  126. fread($this->rSocket, 11);
  127.  
  128. $aDetails['password'] = (integer) ord(fread($this->rSocket, 1));
  129.  
  130. $aDetails['players'] = (integer) $this->toInteger(fread($this->rSocket, 2));
  131.  
  132. $aDetails['maxplayers'] = (integer) $this->toInteger(fread($this->rSocket, 2));
  133.  
  134. $iStrlen = ord(fread($this->rSocket, 4));
  135. if(!$iStrlen) return -1;
  136.  
  137. $aDetails['hostname'] = (string) fread($this->rSocket, $iStrlen);
  138.  
  139. $iStrlen = ord(fread($this->rSocket, 4));
  140. $aDetails['gamemode'] = (string) fread($this->rSocket, $iStrlen);
  141.  
  142. // $iStrlen = ord(fread($this->rSocket, 4));
  143. // $aDetails['mapname'] = (string) fread($this->rSocket, $iStrlen);
  144.  
  145. return $aDetails;
  146. }
  147.  
  148.  
  149. /**
  150. * This function gets a basic list of all the players on the server.
  151. *
  152. * Note as of 0.3.0, the amount of players that can be retrieved is
  153. * limited to 100. This means if there are more players than 100,
  154. * then no data will be returned, and it will be a blank array.
  155. *
  156. * <code>
  157. * Array
  158. * (
  159. * [0] => Array
  160. * (
  161. * [nickname] => K1nNngO
  162. * [score] => 72
  163. * )
  164. *
  165. * [1] => Array
  166. * (
  167. * [nickname] => [kikOo]
  168. * [score] => 150
  169. * )
  170. *
  171. * [and so on...]
  172. * )
  173. * </code>
  174. *
  175. * @return array Array of player information.
  176. */
  177. public function getBasicPlayers()
  178. {
  179. @fwrite($this->rSocket, $this->createPacket('c'));
  180. fread($this->rSocket, 11);
  181.  
  182. $iPlayerCount = ord(fread($this->rSocket, 2));
  183. $aDetails = array();
  184.  
  185. if($iPlayerCount > 0)
  186. {
  187. for($iIndex = 0; $iIndex < $iPlayerCount; ++$iIndex)
  188. {
  189. $iStrlen = ord(fread($this->rSocket, 1));
  190. $aDetails[] = array
  191. (
  192. "nickname" => (string) fread($this->rSocket, $iStrlen),
  193. "score" => (integer) $this->toInteger(fread($this->rSocket, 4)),
  194. );
  195. }
  196. }
  197.  
  198. return $aDetails;
  199. }
  200.  
  201.  
  202. /**
  203. * This function gets a detailed list of all the players on the server.
  204. *
  205. * Note as of 0.3.0, the amount of players that can be retrieved is
  206. * limited to 100. This means if there are more players than 100,
  207. * then no data will be returned, and it will be a blank array.
  208. *
  209. * <code>
  210. * Array
  211. * (
  212. * [0] => Array
  213. * (
  214. * [playerid] => 0
  215. * [nickname] => K1nNngO
  216. * [score] => 72
  217. * [ping] => 195
  218. * )
  219. *
  220. * [1] => Array
  221. * (
  222. * [playerid] => 1
  223. * [nickname] => [kikOo]
  224. * [score] => 150
  225. * [ping] => 375
  226. * )
  227. *
  228. * [and so on...]
  229. * )
  230. * </code>
  231. *
  232. * @return array Array of player information.
  233. */
  234. public function getDetailedPlayers()
  235. {
  236. @fwrite($this->rSocket, $this->createPacket('d'));
  237. fread($this->rSocket, 11);
  238.  
  239. $iPlayerCount = ord(fread($this->rSocket, 2));
  240. $aDetails = array();
  241.  
  242. for($iIndex = 0; $iIndex < $iPlayerCount; ++$iIndex)
  243. {
  244. $aPlayer['playerid'] = (integer) ord(fread($this->rSocket, 1));
  245.  
  246. $iStrlen = ord(fread($this->rSocket, 1));
  247. $aPlayer['nickname'] = (string) fread($this->rSocket, $iStrlen);
  248.  
  249. $aPlayer['score'] = (integer) $this->toInteger(fread($this->rSocket, 4));
  250. $aPlayer['ping'] = (integer) $this->toInteger(fread($this->rSocket, 4));
  251.  
  252. $aDetails[] = $aPlayer;
  253. unset($aPlayer);
  254. }
  255.  
  256. return $aDetails;
  257. }
  258.  
  259.  
  260. /**
  261. * This function gets all the server rules from the server.
  262. *
  263. * Rules in this context are not player rules, they are client rules,
  264. * like the weather of the server, time, and so on. (Custom rules,
  265. * when supported by a SA-MP plugin, will be included here.)
  266. *
  267. * <code>
  268. * Array
  269. * (
  270. * [gravity] => 0.007900
  271. * [mapname] => Everystuff
  272. * [version] => 0.3a
  273. * [weather] => 0
  274. * [weburl] => samp.madoshi.net
  275. * [worldtime] => 12:00
  276. * )
  277. * </code>
  278. *
  279. * @return array Array of server rules.
  280. */
  281. public function getRules()
  282. {
  283. @fwrite($this->rSocket, $this->createPacket('r'));
  284. fread($this->rSocket, 11);
  285.  
  286. $iRuleCount = ord(fread($this->rSocket, 2));
  287. $aReturn = array();
  288.  
  289. for($iIndex = 0; $iIndex < $iRuleCount; ++$iIndex)
  290. {
  291. $iStrlen = ord(fread($this->rSocket, 1));
  292. $sRulename = (string) fread($this->rSocket, $iStrlen);
  293.  
  294. $iStrlen = ord(fread($this->rSocket, 1));
  295. $aDetails[$sRulename] = (string) fread($this->rSocket, $iStrlen);
  296. }
  297.  
  298. return $aDetails;
  299. }
  300.  
  301.  
  302. /**
  303. * @ignore
  304. */
  305. private function toInteger($sData)
  306. {
  307. if($sData === "")
  308. {
  309. return null;
  310. }
  311.  
  312. $iInteger = 0;
  313. $iInteger += (ord($sData[0]));
  314.  
  315. if(isset($sData[1]))
  316. {
  317. $iInteger += (ord($sData[1]) << 8);
  318. }
  319.  
  320. if(isset($sData[2]))
  321. {
  322. $iInteger += (ord($sData[2]) << 16);
  323. }
  324.  
  325. if(isset($sData[3]))
  326. {
  327. $iInteger += (ord($sData[3]) << 24);
  328. }
  329.  
  330. if($iInteger >= 4294967294)
  331. {
  332. $iInteger -= 4294967296;
  333. }
  334.  
  335. return $iInteger;
  336. }
  337.  
  338.  
  339. /**
  340. * @ignore
  341. */
  342. private function createPacket($sPayload)
  343. {
  344. $sPacket = 'SAMP';
  345. $sPacket .= chr(strtok($this->aServer[0], '.'));
  346. $sPacket .= chr(strtok('.'));
  347. $sPacket .= chr(strtok('.'));
  348. $sPacket .= chr(strtok('.'));
  349. $sPacket .= chr($this->aServer[1] & 0xFF);
  350. $sPacket .= chr($this->aServer[1] >> 8 & 0xFF);
  351. $sPacket .= $sPayload;
  352.  
  353. return $sPacket;
  354. }
  355. }
RAW Paste Data