public function preprocess($packets) { $result = array(); // Get packet index, remove header foreach ($packets as $packet) { $p = new GameQ_Buffer($packet); $p->skip(14); $cur_packet = $p->readInt16(); $result[$cur_packet] = $p->getBuffer(); } // Sort packets, reset index ksort($result); $result = array_values($result); // Compare last var of current packet with first var of next packet // On a partial match, remove last var from current packet, // variable header from next packet for ($i = 0, $x = count($result); $i < $x - 1; $i++) { // First packet $fst = substr($result[$i], 0, -1); // Second packet $snd = $result[$i + 1]; // Get last variable from first packet $fstvar = substr($fst, strrpos($fst, "") + 1); // Get first variable from last packet $snd = substr($snd, strpos($snd, "") + 2); $sndvar = substr($snd, 0, strpos($snd, "")); // Check if fstvar is a substring of sndvar // If so, remove it from the first string if (strpos($sndvar, $fstvar) !== false) { $result[$i] = preg_replace("#(\\x00[^\\x00]+\\x00)\$#", "", $result[$i]); } } // Join packets return implode("", $result); }
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(); }
/** * 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(); }