Teeworlds.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. /**
  3. * This file is part of GameQ.
  4. *
  5. * GameQ is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GameQ is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. namespace GameQ\Protocols;
  19. use GameQ\Protocol;
  20. use GameQ\Buffer;
  21. use GameQ\Result;
  22. use GameQ\Exception\Protocol as Exception;
  23. /**
  24. * Teeworlds Protocol class
  25. *
  26. * Only supports versions > 0.5
  27. *
  28. * @author Austin Bischoff <[email protected]>
  29. * @author Marcel Bößendörfer <[email protected]>
  30. */
  31. class Teeworlds extends Protocol
  32. {
  33. /**
  34. * Array of packets we want to look up.
  35. * Each key should correspond to a defined method in this or a parent class
  36. *
  37. * @type array
  38. */
  39. protected $packets = [
  40. self::PACKET_ALL => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x67\x69\x65\x33\x05",
  41. // 0.5 Packet (not compatible, maybe some wants to implement "Teeworldsold")
  42. //self::PACKET_STATUS => "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFgief",
  43. ];
  44. /**
  45. * Use the response flag to figure out what method to run
  46. *
  47. * @type array
  48. */
  49. protected $responses = [
  50. "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffinf35" => "processAll",
  51. ];
  52. /**
  53. * The query protocol used to make the call
  54. *
  55. * @type string
  56. */
  57. protected $protocol = 'teeworlds';
  58. /**
  59. * String name of this protocol class
  60. *
  61. * @type string
  62. */
  63. protected $name = 'teeworlds';
  64. /**
  65. * Longer string name of this protocol class
  66. *
  67. * @type string
  68. */
  69. protected $name_long = "Teeworlds Server";
  70. /**
  71. * The client join link
  72. *
  73. * @type string
  74. */
  75. protected $join_link = "steam://connect/%s:%d/";
  76. /**
  77. * Normalize settings for this protocol
  78. *
  79. * @type array
  80. */
  81. protected $normalize = [
  82. // General
  83. 'general' => [
  84. // target => source
  85. 'dedicated' => 'dedicated',
  86. 'hostname' => 'hostname',
  87. 'mapname' => 'map',
  88. 'maxplayers' => 'num_players_total',
  89. ],
  90. // Individual
  91. 'player' => [
  92. 'name' => 'name',
  93. 'score' => 'score',
  94. ],
  95. ];
  96. /**
  97. * Process the response
  98. *
  99. * @return array
  100. * @throws Exception
  101. */
  102. public function processResponse()
  103. {
  104. // Holds the results
  105. $results = [];
  106. // Iterate over the packets
  107. foreach ($this->packets_response as $response) {
  108. // Make a buffer
  109. $buffer = new Buffer($response);
  110. // Grab the header
  111. $header = $buffer->readString();
  112. // Figure out which packet response this is
  113. if (!array_key_exists($header, $this->responses)) {
  114. throw new Exception(__METHOD__ . " response type '" . bin2hex($header) . "' is not valid");
  115. }
  116. // Now we need to call the proper method
  117. $results = array_merge(
  118. $results,
  119. call_user_func_array([$this, $this->responses[$header]], [$buffer])
  120. );
  121. }
  122. unset($buffer);
  123. return $results;
  124. }
  125. /**
  126. * Handle processing all of the data returned
  127. *
  128. * @param Buffer $buffer
  129. *
  130. * @return array
  131. */
  132. protected function processAll(Buffer $buffer)
  133. {
  134. // Set the result to a new result instance
  135. $result = new Result();
  136. // Always dedicated
  137. $result->add('dedicated', 1);
  138. $result->add('version', $buffer->readString());
  139. $result->add('hostname', $buffer->readString());
  140. $result->add('map', $buffer->readString());
  141. $result->add('game_descr', $buffer->readString());
  142. $result->add('flags', $buffer->readString()); // not sure about that
  143. $result->add('num_players', $buffer->readString());
  144. $result->add('maxplayers', $buffer->readString());
  145. $result->add('num_players_total', $buffer->readString());
  146. $result->add('maxplayers_total', $buffer->readString());
  147. // Players
  148. while ($buffer->getLength()) {
  149. $result->addPlayer('name', $buffer->readString());
  150. $result->addPlayer('clan', $buffer->readString());
  151. $result->addPlayer('flag', $buffer->readString());
  152. $result->addPlayer('score', $buffer->readString());
  153. $result->addPlayer('team', $buffer->readString());
  154. }
  155. unset($buffer);
  156. return $result->fetch();
  157. }
  158. }