示例#1
0
 /**
  * Overload the parse players because the data coming back is different
  * @see GameQ_Protocols_Quake3::parsePlayers()
  */
 protected function parsePlayers(GameQ_Result &$result, $players_info)
 {
     // Explode the arrays out
     $players = explode("\n", $players_info);
     // Remove the last array item as it is junk
     array_pop($players);
     // Add total number of players
     $result->add('num_players', count($players));
     // Loop the players
     foreach ($players as $player_info) {
         $buf = new GameQ_Buffer($player_info);
         // Add player info
         $result->addPlayer('frags', $buf->readString(" "));
         $result->addPlayer('ping', $buf->readString(" "));
         // Skip first "
         $buf->skip(1);
         // Add player name
         $result->addPlayer('name', trim($buf->readString('"')));
         // Skip space
         $buf->skip(1);
         // Add team
         $result->addPlayer('team', $buf->read());
     }
     // Free some memory
     unset($buf, $players, $player_info);
 }
示例#2
0
 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();
 }
示例#3
0
 /**
  * Pre-process the server details data that was returned.
  *
  * @param array $packets
  */
 protected function preProcess($packets)
 {
     // Make buffer so we can check this out
     $buf = new GameQ_Buffer(implode('', $packets));
     // Grab the header
     $header = $buf->read(4);
     // Now lets verify the header
     if ($header != "M2MP") {
         throw new GameQ_ProtocolsException('Unable to match M2MP response header. Header: ' . $header);
         return FALSE;
     }
     // Return the data with the header stripped, ready to go.
     return $buf->getBuffer();
 }
示例#4
0
 /**
  * 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();
 }
示例#5
0
 /**
  * Decode words from the response
  *
  * @param GameQ_Buffer $buf
  */
 protected function decodeWords(GameQ_Buffer &$buf)
 {
     $result = array();
     $num_words = $buf->readInt32();
     for ($i = 0; $i < $num_words; $i++) {
         $len = $buf->readInt32();
         $result[] = $buf->read($len);
         $buf->read(1);
         /* 0x00 string ending */
     }
     return $result;
 }
示例#6
0
 /**
  * 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;
 }
示例#7
0
 /**
  * Process the server status
  *
  * @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();
     // Always dedicated
     $result->add('dedicated', TRUE);
     // Preprocess and make buffer
     $buf = new GameQ_Buffer($this->preProcess($this->packets_response[self::PACKET_STATUS]));
     // Pull out the server information
     $result->add('password', (bool) $buf->readInt8());
     $result->add('num_players', $buf->readInt16());
     $result->add('max_players', $buf->readInt16());
     // These are read differently for these last 3
     $result->add('servername', $buf->read($buf->readInt32()));
     $result->add('gametype', $buf->read($buf->readInt32()));
     $result->add('map', $buf->read($buf->readInt32()));
     // Free some memory
     unset($buf);
     // Return the result
     return $result->fetch();
 }
示例#8
0
 /**
  * Process the status result.  This result is different from the parent
  *
  * @see GameQ_Protocols_Cube2::process_status()
  */
 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);
     // Check the header, should be the same response as the packet we sent
     if ($buf->read(6) != $this->packets[self::PACKET_STATUS]) {
         throw new GameQ_ProtocolsException("Data for " . __METHOD__ . " does not have the proper header type (should be {$this->packets[self::PACKET_STATUS]}).");
         return array();
     }
     /**
      * Reference chart for ints by position
      *
      * 0 - Num players
      * 1 - Number of items to follow (i.e. 8), not used yet
      * 2 - Version
      * 3 - gamemode (dm, ctf, etc...)
      * 4 - mutators (sum of power of 2)
      * 5 - Time remaining
      * 6 - max players
      * 7 - Mastermode (open, password, etc)
      * 8 - variable count
      * 9 - modification count
      */
     $result->add('num_players', $this->readInt($buf));
     $items = $this->readInt($buf);
     // We dump this as we dont use it for now
     $result->add('version', $this->readInt($buf));
     $result->add('gamemode', $this->gamemodes[$this->readInt($buf)]);
     // This is a sum of power's of 2 (2^1, 1 << 1)
     $mutators_number = $this->readInt($buf);
     $mutators = array();
     foreach ($this->mutators as $mutator => $flag) {
         if ($flag & $mutators_number) {
             $mutators[] = $mutator;
         }
     }
     $result->add('mutators', $mutators);
     $result->add('mutators_number', $mutators_number);
     $result->add('time_remaining', $this->readInt($buf));
     $result->add('max_players', $this->readInt($buf));
     $mastermode = $this->readInt($buf);
     $result->add('mastermode', $this->mastermodes[$mastermode]);
     $result->add('password', in_array($mastermode, array(4)) ? TRUE : FALSE);
     // @todo: No idea what these next 2 are used for
     $result->add('variableCount', $this->readInt($buf));
     $result->add('modificationCount', $this->readInt($buf));
     $result->add('map', $buf->readString());
     $result->add('servername', $buf->readString());
     // The rest from here is player information, we read until we run out of strings (\x00)
     while ($raw = $buf->readString()) {
         // Items seem to be seperated by \xc
         $items = explode("\f", $raw);
         // Indexes 0, 1 & 5 seem to be junk
         // Indexes 2, 3, 4 seem to have something of use, not sure about #3
         $result->addPlayer('guid', (int) trim($items[2], "[]"));
         // Index 4 has the player name with some kind int added on to the front, icon or something?
         // Anyway remove it for now...
         if (preg_match('/(\\[[0-9]+\\])(.*)/i', $items[4], $name)) {
             $result->addPlayer('name', $name[2]);
         }
     }
     unset($buf, $data);
     return $result->fetch();
 }