Mumble.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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\Result;
  21. use GameQ\Exception\Protocol as Exception;
  22. /**
  23. * Mumble Protocol class
  24. *
  25. * References:
  26. * https://github.com/edmundask/MurmurQuery - Thanks to skylord123
  27. *
  28. * @author Austin Bischoff <[email protected]>
  29. */
  30. class Mumble extends Protocol
  31. {
  32. /**
  33. * Array of packets we want to look up.
  34. * Each key should correspond to a defined method in this or a parent class
  35. *
  36. * @type array
  37. */
  38. protected $packets = [
  39. self::PACKET_ALL => "\x6A\x73\x6F\x6E", // JSON packet
  40. ];
  41. /**
  42. * The transport mode for this protocol is TCP
  43. *
  44. * @type string
  45. */
  46. protected $transport = self::TRANSPORT_TCP;
  47. /**
  48. * The query protocol used to make the call
  49. *
  50. * @type string
  51. */
  52. protected $protocol = 'mumble';
  53. /**
  54. * String name of this protocol class
  55. *
  56. * @type string
  57. */
  58. protected $name = 'mumble';
  59. /**
  60. * Longer string name of this protocol class
  61. *
  62. * @type string
  63. */
  64. protected $name_long = "Mumble Server";
  65. /**
  66. * The client join link
  67. *
  68. * @type string
  69. */
  70. protected $join_link = "mumble://%s:%d/";
  71. /**
  72. * 27800 = 64738 - 36938
  73. *
  74. * @type int
  75. */
  76. protected $port_diff = -36938;
  77. /**
  78. * Normalize settings for this protocol
  79. *
  80. * @type array
  81. */
  82. protected $normalize = [
  83. // General
  84. 'general' => [
  85. 'dedicated' => 'dedicated',
  86. 'gametype' => 'gametype',
  87. 'hostname' => 'name',
  88. 'numplayers' => 'numplayers',
  89. 'maxplayers' => 'x_gtmurmur_max_users',
  90. ],
  91. // Player
  92. 'player' => [
  93. 'name' => 'name',
  94. 'ping' => 'tcpPing',
  95. 'team' => 'channel',
  96. 'time' => 'onlinesecs',
  97. ],
  98. // Team
  99. 'team' => [
  100. 'name' => 'name',
  101. ],
  102. ];
  103. /**
  104. * Process the response
  105. *
  106. * @return array
  107. * @throws \GameQ\Exception\Protocol
  108. */
  109. public function processResponse()
  110. {
  111. // Try to json_decode, make it into an array
  112. if (($data = json_decode(implode('', $this->packets_response), true)) === null) {
  113. throw new Exception(__METHOD__ . " Unable to decode JSON data.");
  114. }
  115. // Set the result to a new result instance
  116. $result = new Result();
  117. // Always dedicated
  118. $result->add('dedicated', 1);
  119. // Let's iterate over the response items, there are a lot
  120. foreach ($data as $key => $value) {
  121. // Ignore root for now, that is where all of the channel/player info is housed
  122. if (in_array($key, ['root'])) {
  123. continue;
  124. }
  125. // Add them as is
  126. $result->add($key, $value);
  127. }
  128. // Offload the channel and user parsing
  129. $this->processChannelsAndUsers($data['root'], $result);
  130. unset($data);
  131. // Manually set the number of players
  132. $result->add('numplayers', count($result->get('players')));
  133. return $result->fetch();
  134. }
  135. /*
  136. * Internal methods
  137. */
  138. /**
  139. * Handles processing the the channels and user info
  140. *
  141. * @param array $data
  142. * @param \GameQ\Result $result
  143. */
  144. protected function processChannelsAndUsers(array $data, Result &$result)
  145. {
  146. // Let's add all of the channel information
  147. foreach ($data as $key => $value) {
  148. // We will handle these later
  149. if (in_array($key, ['channels', 'users'])) {
  150. // skip
  151. continue;
  152. }
  153. // Add the channel property as a team
  154. $result->addTeam($key, $value);
  155. }
  156. // Itereate over the users in this channel
  157. foreach ($data['users'] as $user) {
  158. foreach ($user as $key => $value) {
  159. $result->addPlayer($key, $value);
  160. }
  161. }
  162. // Offload more channels to parse
  163. foreach ($data['channels'] as $channel) {
  164. $this->processChannelsAndUsers($channel, $result);
  165. }
  166. }
  167. }