protected function parsePlayers(GameQ_Buffer &$buf, GameQ_Result &$result) { while (($id = $buf->readInt8()) != 32) { $result->addPlayer('id', $id); $result->addPlayer('ping', $buf->readInt16()); $result->addPlayer('rate', $buf->readInt32()); $result->addPlayer('name', $buf->readString()); $result->addPlayer('clantag', $buf->readString()); } return true; }
/** * Handles processing the status data into a usable format * * @throws GameQ_ProtocolsException */ protected function process_status() { // Make sure we have a valid response if (!$this->hasValidResponse(self::PACKET_STATUS)) { return array(); } // Set the result to a new result instance $result = new GameQ_Result(); // Let's preprocess the rules $data = $this->preProcess_status($this->packets_response[self::PACKET_STATUS]); // Create a new buffer $buf = new GameQ_Buffer($data); // Skip the header $buf->skip(6); $result->add('mod', $buf->readPascalString()); $result->add('gametype', $buf->readPascalString()); $result->add('map', $buf->readPascalString()); // Grab the flag $flag = $buf->read(); $bit = 1; foreach (array('dedicated', 'password', 'linux', 'tournament', 'no_alias') as $var) { $value = $flag & $bit ? 1 : 0; $result->add($var, $value); $bit *= 2; } $result->add('num_players', $buf->readInt8()); $result->add('max_players', $buf->readInt8()); $result->add('num_bots', $buf->readInt8()); $result->add('cpu', $buf->readInt16()); $result->add('info', $buf->readPascalString()); $buf->skip(2); // Do teams $num_teams = $buf->read(); $result->add('num_teams', $num_teams); $buf->skip(); for ($i = 0; $i < $num_teams; $i++) { $result->addTeam('name', $buf->readString("\t")); $result->addTeam('score', $buf->readString("\n")); } // Do players // @todo: No code here to do players, no docs either, need example server with players unset($buf, $data); return $result->fetch(); }
protected function process_all() { if (!$this->hasValidResponse(self::PACKET_ALL)) { return array(); } $data = $this->packets_response[self::PACKET_ALL][0]; $buf = new GameQ_Buffer($data); $result = new GameQ_Result(); // Grab the header $header = $buf->read(4); // Header does not match if ($header !== 'EYE1') { throw new GameQException("Exepcted header to be 'EYE1' but got '{$header}' instead."); } // Variables $result->add('gamename', $buf->readPascalString(1, true)); $result->add('port', $buf->readPascalString(1, true)); $result->add('servername', $buf->readPascalString(1, true)); $result->add('gametype', $buf->readPascalString(1, true)); $result->add('map', $buf->readPascalString(1, true)); $result->add('version', $buf->readPascalString(1, true)); $result->add('password', $buf->readPascalString(1, true)); $result->add('num_players', $buf->readPascalString(1, true)); $result->add('max_players', $buf->readPascalString(1, true)); // Key / value pairs while ($buf->getLength()) { // If we have an empty key, we've reached the end $key = $buf->readPascalString(1, true); if (empty($key)) { break; } // Otherwise, add the pair $result->add($key, $buf->readPascalString(1, true)); } // Players while ($buf->getLength()) { // Get the flags $flags = $buf->readInt8(); // Get data according to the flags if ($flags & 1) { $result->addPlayer('name', $buf->readPascalString(1, true)); } if ($flags & 2) { $result->addPlayer('team', $buf->readPascalString(1, true)); } if ($flags & 4) { $result->addPlayer('skin', $buf->readPascalString(1, true)); } if ($flags & 8) { $result->addPlayer('score', $buf->readPascalString(1, true)); } if ($flags & 16) { $result->addPlayer('ping', $buf->readPascalString(1, true)); } if ($flags & 32) { $result->addPlayer('time', $buf->readPascalString(1, true)); } } return $result->fetch(); }
/** * Read an Unreal Engine 2 string * * Adapted from original GameQ code * * @param GameQ_Buffer $buf * @return string <string, mixed> */ private function _readUnrealString(GameQ_Buffer &$buf) { // Normal pascal string if (ord($buf->lookAhead(1)) < 129) { return $buf->readPascalString(1); } // UnrealEngine2 color-coded string $length = ($buf->readInt8() - 128) * 2 - 3; $encstr = $buf->read($length); $buf->skip(3); // Remove color-code tags $encstr = preg_replace('~\\x5e\\0\\x23\\0..~s', '', $encstr); // Remove every second character // The string is UCS-2, this approximates converting to latin-1 $str = ''; for ($i = 0, $ii = strlen($encstr); $i < $ii; $i += 2) { $str .= $encstr[$i]; } return $str; }
/** * Process the server details * * @throws GameQ_ProtocolsException */ protected function process_all() { // Make sure we have a valid response if (!$this->hasValidResponse(self::PACKET_ALL)) { return array(); } // Set the result to a new result instance $result = new GameQ_Result(); // Always dedicated $result->add('dedicated', TRUE); // Preprocess and make buffer $buf = new GameQ_Buffer($this->preProcess($this->packets_response[self::PACKET_ALL])); // Pull out the server information // Note the length information is incorrect, we correct using offset options in pascal method $result->add('servername', $buf->readPascalString(1, TRUE)); $result->add('num_players', $buf->readPascalString(1, TRUE)); $result->add('max_players', $buf->readPascalString(1, TRUE)); $result->add('gamemode', $buf->readPascalString(1, TRUE)); $result->add('password', (bool) $buf->readInt8()); // Read the player info, it's in the same query response for some odd reason. while ($buf->getLength()) { // Check to see if we ran out of info if ($buf->getLength() <= 1) { break; } // Only player information is available $result->addPlayer('name', $buf->readPascalString(1, TRUE)); } unset($buf); return $result->fetch(); }
/** * Process the players * * NOTE: There is a restriction on the SAMP server side that if there are too many players * the player return will be empty. Nothing can really be done about this unless you bug * the game developers to fix it. */ protected function process_players() { // Make sure we have a valid response if (!$this->hasValidResponse(self::PACKET_PLAYERS)) { return array(); } // Set the result to a new result instance $result = new GameQ_Result(); // Preprocess and make buffer $buf = new GameQ_Buffer($this->preProcess($this->packets_response[self::PACKET_PLAYERS])); // Number of players $result->add('num_players', $buf->readInt16()); // Run until we run out of buffer while ($buf->getLength()) { $result->addPlayer('id', $buf->readInt8()); $result->addPlayer('name', $buf->readPascalString()); $result->addPlayer('score', $buf->readInt32()); $result->addPlayer('ping', $buf->readInt32()); } // Free some memory unset($buf); // Return the result return $result->fetch(); }