예제 #1
0
 /**
  * Handle player info, different than quake3 base
  *
  * @param Buffer $buffer
  *
  * @return array
  * @throws \GameQ\Exception\Protocol
  */
 protected function processPlayers(Buffer $buffer)
 {
     // Set the result to a new result instance
     $result = new Result();
     // Loop until we are out of data
     while ($buffer->getLength()) {
         // Make a new buffer with this block
         $playerInfo = new Buffer($buffer->readString("\n"));
         // Add player info
         $result->addPlayer('frags', $playerInfo->readString(" "));
         $result->addPlayer('ping', $playerInfo->readString(" "));
         // Skip first "
         $playerInfo->skip(1);
         // Add player name, encoded
         $result->addPlayer('name', utf8_encode(trim($playerInfo->readString('"'))));
         // Skip space
         $playerInfo->skip(1);
         // Add team
         $result->addPlayer('team', $playerInfo->read());
         // Clear
         unset($playerInfo);
     }
     // Clear
     unset($buffer);
     return $result->fetch();
 }
예제 #2
0
 /**
  * Specific player parse for The Ship
  *
  * Player response has unknown data after the last real player
  *
  * @param \GameQ\Buffer $buffer
  *
  * @return array
  */
 protected function processPlayers(Buffer $buffer)
 {
     // Set the result to a new result instance
     $result = new Result();
     // We need to read the number of players because this response has other data at the end usually
     $num_players = $buffer->readInt8();
     // Player count
     $result->add('num_players', $num_players);
     // No players, no work
     if ($num_players == 0) {
         return $result->fetch();
     }
     // Players list
     for ($player = 0; $player < $num_players; $player++) {
         $result->addPlayer('id', $buffer->readInt8());
         $result->addPlayer('name', $buffer->readString());
         $result->addPlayer('score', $buffer->readInt32Signed());
         $result->addPlayer('time', $buffer->readFloat32());
     }
     // Extra data
     if ($buffer->getLength() > 0) {
         for ($player = 0; $player < $num_players; $player++) {
             $result->addPlayer('deaths', $buffer->readInt32Signed());
             $result->addPlayer('money', $buffer->readInt32Signed());
         }
     }
     unset($buffer);
     return $result->fetch();
 }
예제 #3
0
 /**
  * Overload the default detail process since this version is different
  *
  * @param \GameQ\Buffer $buffer
  *
  * @return array
  */
 protected function processDetails(Buffer $buffer)
 {
     // Set the result to a new result instance
     $result = new Result();
     $result->add('serverid', $buffer->readInt32());
     // 0
     $result->add('serverip', $buffer->readPascalString(1));
     // empty
     $result->add('gameport', $buffer->readInt32());
     $result->add('queryport', $buffer->readInt32());
     // 0
     // We burn the first char since it is not always correct with the hostname
     $buffer->skip(1);
     // Read as a regular string since the length is incorrect (what we skipped earlier)
     $result->add('servername', utf8_encode($buffer->readString()));
     // The rest is read as normal
     $result->add('mapname', utf8_encode($buffer->readPascalString(1)));
     $result->add('gametype', $buffer->readPascalString(1));
     $result->add('numplayers', $buffer->readInt32());
     $result->add('maxplayers', $buffer->readInt32());
     $result->add('currentwave', $buffer->readInt32());
     unset($buffer);
     return $result->fetch();
 }
예제 #4
0
 /**
  * Process the response
  *
  * @return array
  * @throws \GameQ\Exception\Protocol
  */
 public function processResponse()
 {
     // Make a new buffer out of all of the packets
     $buffer = new Buffer(implode('', $this->packets_response));
     // Check the header TS3
     if (($header = trim($buffer->readString("\n"))) !== 'TS3') {
         throw new Exception(__METHOD__ . " Expected header '{$header}' does not match expected 'TS3'.");
     }
     // Convert all the escaped characters
     $raw = str_replace(['\\\\', '\\/'], ['\\', '/'], $buffer->getBuffer());
     // Explode the sections and filter to remove empty, junk ones
     $sections = array_filter(explode("\n", $raw), function ($value) {
         $value = trim($value);
         // Not empty string or a message response for "error id=\d"
         return !empty($value) && substr($value, 0, 5) !== 'error';
     });
     // Trim up the values to remove extra whitespace
     $sections = array_map('trim', $sections);
     // Set the result to a new result instance
     $result = new Result();
     // Iterate over the sections and offload the parsing
     foreach ($sections as $section) {
         // Grab a snip of the data so we can figure out what it is
         $check = substr(trim($section), 0, 4);
         // Use the first part of the response to figure out where we need to go
         if ($check == 'virt') {
             // Server info
             $this->processDetails($section, $result);
         } elseif ($check == 'cid=') {
             // Channels
             $this->processChannels($section, $result);
         } elseif ($check == 'clid') {
             // Clients (players)
             $this->processPlayers($section, $result);
         }
     }
     unset($buffer, $sections, $section, $check);
     return $result->fetch();
 }
예제 #5
0
 /**
  * Handles processing the details data into a usable format
  *
  * @param Buffer $buffer
  *
  * @return array
  * @throws Exception
  */
 protected function processDetails(Buffer $buffer)
 {
     // Set the result to a new result instance
     $result = new Result();
     $result->add('protocol', $buffer->readString());
     $result->add('password', $buffer->readString());
     $result->add('numplayers', $buffer->readInt16());
     $result->add('maxplayers', $buffer->readInt16());
     $result->add('servername', utf8_encode($buffer->readPascalString()));
     $result->add('gamemode', $buffer->readPascalString());
     $result->add('website', utf8_encode($buffer->readPascalString()));
     $result->add('mapname', utf8_encode($buffer->readPascalString()));
     unset($buffer);
     return $result->fetch();
 }
예제 #6
0
 /**
  * Handles processing the player and team data into a usable format
  *
  * @param \GameQ\Buffer $buffer
  * @param \GameQ\Result $result
  */
 protected function processPlayersAndTeams(Buffer &$buffer, Result &$result)
 {
     /*
      * Explode the data into groups. First is player, next is team (item_t)
      * Each group should be as follows:
      *
      * [0] => item_
      * [1] => information for item_
      * ...
      */
     $data = explode("", $buffer->getBuffer());
     // By default item_group is blank, this will be set for each loop thru the data
     $item_group = '';
     // By default the item_type is blank, this will be set on each loop
     $item_type = '';
     // Loop through all of the $data for information and pull it out into the result
     for ($x = 0; $x < count($data) - 1; $x++) {
         // Pull out the item
         $item = $data[$x];
         // If this is an empty item, move on
         if ($item == '' || $item == "") {
             continue;
         }
         /*
          * Left as reference:
          *
          * Each block of player_ and team_t have preceding junk chars
          *
          * player_ is actually \x01player_
          * team_t is actually \x00\x02team_t
          *
          * Probably a by-product of the change to exploding the data from the original.
          *
          * For now we just strip out these characters
          */
         // Check to see if $item has a _ at the end, this is player info
         if (substr($item, -1) == '_') {
             // Set the item group
             $item_group = 'players';
             // Set the item type, rip off any trailing stuff and bad chars
             $item_type = rtrim(str_replace("", '', $item), '_');
         } elseif (substr($item, -2) == '_t') {
             // Check to see if $item has a _t at the end, this is team info
             // Set the item group
             $item_group = 'teams';
             // Set the item type, rip off any trailing stuff and bad chars
             $item_type = rtrim(str_replace(["", ""], '', $item), '_t');
         } else {
             // We can assume it is data belonging to a previously defined item
             // Make a temp buffer so we have easier access to the data
             $buf_temp = new Buffer($item, Buffer::NUMBER_TYPE_BIGENDIAN);
             // Get the values
             while ($buf_temp->getLength()) {
                 // No value so break the loop, end of string
                 if (($val = $buf_temp->readString()) === '') {
                     break;
                 }
                 // Add the value to the proper item in the correct group
                 $result->addSub($item_group, $item_type, utf8_encode(trim($val)));
             }
             // Unset our buffer
             unset($buf_temp);
         }
     }
     // Free up some memory
     unset($data, $item, $item_group, $item_type, $val);
 }
예제 #7
0
 /**
  * Decode the buffer into a usable format
  *
  * @param \GameQ\Buffer $buffer
  *
  * @return array
  */
 protected function decode(Buffer $buffer)
 {
     $items = [];
     // Get the number of words in this buffer
     $itemCount = $buffer->readInt32();
     // Loop over the number of items
     for ($i = 0; $i < $itemCount; $i++) {
         // Length of the string
         $buffer->readInt32();
         // Just read the string
         $items[$i] = $buffer->readString();
     }
     return $items;
 }
예제 #8
0
 /**
  * Handles processing the rules data into a usable format
  *
  * @param \GameQ\Buffer $buffer
  *
  * @return mixed
  */
 protected function processRules(Buffer $buffer)
 {
     // Set the result to a new result instance
     $result = new Result();
     // Count the number of rules
     $num_rules = $buffer->readInt16Signed();
     // Add the count of the number of rules this server has
     $result->add('num_rules', $num_rules);
     // Rules
     while ($buffer->getLength()) {
         $result->add($buffer->readString(), $buffer->readString());
     }
     unset($buffer);
     return $result->fetch();
 }
예제 #9
0
 /**
  * Process the user listing
  *
  * @param string        $data
  * @param \GameQ\Result $result
  */
 protected function processPlayers($data, Result &$result)
 {
     // Create a buffer
     $buffer = new Buffer($data);
     // The first line holds the column names, data returned is in column/row format
     $columns = explode("\t", trim($buffer->readString("\n")), 16);
     // Loop through the rows until we run out of information
     while ($buffer->getLength()) {
         // Grab the row, which is a tabbed list of items
         $row = trim($buffer->readString("\n"));
         // Explode and merge the data with the columns, then parse
         $data = array_combine($columns, explode("\t", $row, 16));
         foreach ($data as $key => $value) {
             // Now add the data to the result
             $result->addPlayer($key, utf8_encode($value));
         }
     }
     unset($data, $buffer, $row, $columns, $key, $value);
 }