. */ namespace GameQ\Protocols; use GameQ\Protocol; use GameQ\Result; use GameQ\Exception\Protocol as Exception; /** * Mumble Protocol class * * References: * https://github.com/edmundask/MurmurQuery - Thanks to skylord123 * * @author Austin Bischoff */ class Mumble extends Protocol { /** * Array of packets we want to look up. * Each key should correspond to a defined method in this or a parent class * * @type array */ protected $packets = [ self::PACKET_ALL => "\x6A\x73\x6F\x6E", // JSON packet ]; /** * The transport mode for this protocol is TCP * * @type string */ protected $transport = self::TRANSPORT_TCP; /** * The query protocol used to make the call * * @type string */ protected $protocol = 'mumble'; /** * String name of this protocol class * * @type string */ protected $name = 'mumble'; /** * Longer string name of this protocol class * * @type string */ protected $name_long = "Mumble Server"; /** * The client join link * * @type string */ protected $join_link = "mumble://%s:%d/"; /** * 27800 = 64738 - 36938 * * @type int */ protected $port_diff = -36938; /** * Normalize settings for this protocol * * @type array */ protected $normalize = [ // General 'general' => [ 'dedicated' => 'dedicated', 'gametype' => 'gametype', 'hostname' => 'name', 'numplayers' => 'numplayers', 'maxplayers' => 'x_gtmurmur_max_users', ], // Player 'player' => [ 'name' => 'name', 'ping' => 'tcpPing', 'team' => 'channel', 'time' => 'onlinesecs', ], // Team 'team' => [ 'name' => 'name', ], ]; /** * Process the response * * @return array * @throws \GameQ\Exception\Protocol */ public function processResponse() { // Try to json_decode, make it into an array if (($data = json_decode(implode('', $this->packets_response), true)) === null) { throw new Exception(__METHOD__ . " Unable to decode JSON data."); } // Set the result to a new result instance $result = new Result(); // Always dedicated $result->add('dedicated', 1); // Let's iterate over the response items, there are a lot foreach ($data as $key => $value) { // Ignore root for now, that is where all of the channel/player info is housed if (in_array($key, ['root'])) { continue; } // Add them as is $result->add($key, $value); } // Offload the channel and user parsing $this->processChannelsAndUsers($data['root'], $result); unset($data); // Manually set the number of players $result->add('numplayers', count($result->get('players'))); return $result->fetch(); } /* * Internal methods */ /** * Handles processing the the channels and user info * * @param array $data * @param \GameQ\Result $result */ protected function processChannelsAndUsers(array $data, Result &$result) { // Let's add all of the channel information foreach ($data as $key => $value) { // We will handle these later if (in_array($key, ['channels', 'users'])) { // skip continue; } // Add the channel property as a team $result->addTeam($key, $value); } // Itereate over the users in this channel foreach ($data['users'] as $user) { foreach ($user as $key => $value) { $result->addPlayer($key, $value); } } // Offload more channels to parse foreach ($data['channels'] as $channel) { $this->processChannelsAndUsers($channel, $result); } } }