GameQ Fix & Update

Provided by https://steamcommunity.com/id/0null1works/
(ဪTheLupi#5961)
This commit is contained in:
AEon-Jan 2022-01-06 21:41:48 +01:00
parent 26054f601c
commit 4236d48ae1
46 changed files with 1566 additions and 273 deletions

View File

@ -276,8 +276,8 @@ class Buffer
// Get position of delimiters
$pos = [];
foreach ($delims as $delim) {
if ($p = strpos($this->data, $delim, min($this->index, $this->length))) {
$pos[] = $p;
if ($index = strpos($this->data, $delim, min($this->index, $this->length))) {
$pos[] = $index;
}
}

View File

@ -104,6 +104,8 @@ class Secondstohuman extends Base
// Iterate and update the result
$result[$key] = $this->iterate($value);
} elseif (in_array($key, $this->options[self::OPTION_TIMEKEYS])) {
// Make sure the value is a float (throws E_WARNING in PHP 7.1+)
$value = floatval($value);
// We match one of the keys we are wanting to convert so add it and move on
$result[sprintf(self::RESULT_KEY, $key)] = sprintf(
"%02d:%02d:%02d",

View File

@ -33,6 +33,8 @@ class Stripcolors extends Base
/**
* Apply this filter
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @param array $result
* @param \GameQ\Server $server
*
@ -62,6 +64,9 @@ class Stripcolors extends Base
case 'gamespy2':
array_walk_recursive($result, [$this, 'stripUnreal']);
break;
case 'source':
array_walk_recursive($result, [$this, 'stripSource']);
break;
}
/*$data['filtered'][ $server->id() ] = $result;
@ -97,4 +102,14 @@ class Stripcolors extends Base
{
$string = preg_replace('/\x1b.../', '', $string);
}
/**
* Strip color codes from Source based games
*
* @param string $string
*/
protected function stripSource(&$string)
{
$string = strip_tags($string);
}
}

View File

@ -15,6 +15,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ;
use GameQ\Exception\Protocol as ProtocolException;
@ -43,6 +44,7 @@ class GameQ
/*
* Constants
*/
const PROTOCOLS_DIRECTORY = __DIR__ . '/Protocols';
/* Static Section */
@ -408,10 +410,10 @@ class GameQ
'server_id' => $server_id,
'socket' => $socket,
];
} catch (QueryException $e) {
} catch (QueryException $exception) {
// Check to see if we are in debug, if so bubble up the exception
if ($this->debug) {
throw new \Exception($e->getMessage(), $e->getCode(), $e);
throw new \Exception($exception->getMessage(), $exception->getCode(), $exception);
}
}
@ -509,13 +511,13 @@ class GameQ
'server_id' => $server_id,
'socket' => $socket,
];
} catch (QueryException $e) {
} catch (QueryException $exception) {
// Check to see if we are in debug, if so bubble up the exception
if ($this->debug) {
throw new \Exception($e->getMessage(), $e->getCode(), $e);
throw new \Exception($exception->getMessage(), $exception->getCode(), $exception);
}
break;
continue;
}
// Clean up the sockets, if any left over
@ -636,7 +638,7 @@ class GameQ
// Apply the filter to the data
$results = $filter->apply($results, $server);
} catch (\ReflectionException $e) {
} catch (\ReflectionException $exception) {
// Invalid, skip it
continue;
}

View File

@ -19,24 +19,25 @@
namespace GameQ\Protocols;
/**
* Class Aoc
* Class Arma
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*
* @author Wilson Jesus <>
*/
class Aoc extends Source
class Arma extends Gamespy2
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'aoc';
protected $name = 'arma';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Age of Chivalry";
protected $name_long = "ArmA Armed Assault";
}

View File

@ -1,4 +1,5 @@
<?php
/**
* This file is part of GameQ.
*
@ -18,35 +19,15 @@
namespace GameQ\Protocols;
use GameQ\Buffer;
use GameQ\Result;
/**
* Class Armed Assault 3
*
* Rules protocol reference: https://community.bistudio.com/wiki/Arma_3_ServerBrowserProtocol2
* Class Dayzmod
*
* @package GameQ\Protocols
* @author Marcel Bößendörfer <m.boessendoerfer@marbis.net>
* @author Austin Bischoff <austin@codebeard.com>
* @author Memphis017 <https://github.com/Memphis017>
*/
class Arma3 extends Source
class Arma3 extends Armedassault2oa
{
/**
* Defines the names for the specific game DLCs
*
* @var array
*/
protected $dlcNames = [
'Karts',
'Marksmen',
'Helicopters',
'Apex',
'Jets',
'Laws of War',
'Tac-Ops',
'Tanks',
];
/**
* String name of this protocol class
@ -61,127 +42,4 @@ class Arma3 extends Source
* @type string
*/
protected $name_long = "Arma3";
/**
* Query port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
/**
* Process the rules since Arma3 changed their response for rules
*
* @param Buffer $buffer
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
protected function processRules(Buffer $buffer)
{
// Total number of packets, burn it
$buffer->readInt16();
// Will hold the data string
$data = '';
// Loop until we run out of strings
while ($buffer->getLength()) {
// Burn the delimiters (i.e. \x01\x04\x00)
$buffer->readString();
// Add the data to the string, we are reassembling it
$data .= $buffer->readString();
}
// Restore escaped sequences
$data = str_replace(["\x01\x01", "\x01\x02", "\x01\x03"], ["\x01", "\x00", "\xFF"], $data);
// Make a new buffer with the reassembled data
$responseBuffer = new Buffer($data);
// Kill the old buffer, should be empty
unset($buffer, $data);
// Set the result to a new result instance
$result = new Result();
// Get results
$result->add('rules_protocol_version', $responseBuffer->readInt8());
$result->add('overflow', $responseBuffer->readInt8());
$dlcBit = $responseBuffer->readInt8(); // Grab DLC bit and use it later
$responseBuffer->skip(); // Reserved, burn it
// Grab difficulty so we can man handle it...
$difficulty = $responseBuffer->readInt8();
// Process difficulty
$result->add('3rd_person', $difficulty >> 7);
$result->add('advanced_flight_mode', ($difficulty >> 6) & 1);
$result->add('difficulty_ai', ($difficulty >> 3) & 3);
$result->add('difficulty_level', $difficulty & 3);
unset($difficulty);
// Crosshair
$result->add('crosshair', $responseBuffer->readInt8());
/*
* Due to a bug in the DLC byte response from the ARMA servers we end here until the DLC byte bug can be fixed
* or can code around the issue.
* See https://github.com/Austinb/GameQ/issues/420
*/
unset($dlcBit);
return $result->fetch();
//$dlcBit = 255;
/*// Loop over the DLC bit so we can pull in the infor for the DLC (if enabled)
for ($x = 0; $x < 8; $x++) {
if (($dlcBit >> $x) & 1) {
$result->addSub('dlcs', 'name', $this->dlcNames[$x]);
$result->addSub('dlcs', 'hash', dechex($responseBuffer->readInt32()));
}
}
// No longer needed
unset($dlcBit);
// Grab the mod count
$modCount = $responseBuffer->readInt8();
// Add mod count
$result->add('mod_count', $modCount);
// Loop the mod count and add them
for ($x = 0; $x < $modCount; $x++) {
// Add the mod to the list
$result->addSub('mods', 'hash', dechex($responseBuffer->readInt32()));
$result->addSub('mods', 'steam_id', hexdec($responseBuffer->readPascalString(0, true)));
$result->addSub('mods', 'name', $responseBuffer->readPascalString(0, true));
}
unset($modCount, $x);
// Burn the signatures count, we will just loop until we run out of strings
$responseBuffer->read();
// Make signatures array
$signatures = [];
// Loop until we run out of strings
while ($responseBuffer->getLength()) {
//$result->addSub('signatures', 0, $responseBuffer->readPascalString(0, true));
$signatures[] = $responseBuffer->readPascalString(0, true);
}
// Add as a simple array
$result->add('signatures', $signatures);
// Add signatures count
$result->add('signature_count', count($signatures));
unset($responseBuffer, $signatures);
return $result->fetch();*/
}
}

View File

@ -42,9 +42,9 @@ class Armedassault2oa extends Source
protected $name_long = "Armed Assault 2: Operation Arrowhead";
/**
* Query port = client_port - 1
* Query port = client_port + 1
*
* @type int
*/
protected $port_diff = -1;
protected $port_diff = 1;
}

View File

@ -105,12 +105,21 @@ class Ase extends Protocol
*/
public function processResponse()
{
// Create a new buffer
$buffer = new Buffer(implode('', $this->packets_response));
// Burn the header
$buffer->skip(4);
// Check for valid response
if ($buffer->getLength() < 4) {
throw new \GameQ\Exception\Protocol(sprintf('%s The response from the server was empty.', __METHOD__));
}
// Read the header
$header = $buffer->read(4);
// Verify header
if ($header !== 'EYE1') {
throw new \GameQ\Exception\Protocol(sprintf('%s The response header "%s" does not match expected "EYE1"', __METHOD__, $header));
}
// Create a new result
$result = new Result();

View File

@ -0,0 +1,55 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Class Atlas
*
* @package GameQ\Protocols
* @author Wilson Jesus <>
*/
class Atlas extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'atlas';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Atlas";
/**
* query_port = client_port + 51800
* 57561 = 5761 + 51800
*
* this is the default value for the stock game server, both ports
* can be independently changed from the stock ones,
* making the port_diff logic useless.
*
* @type int
*/
protected $port_diff = 51800;
}

View File

@ -0,0 +1,50 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Class Brink
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Brink extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'brink';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Brink";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
}

View File

@ -19,24 +19,25 @@
namespace GameQ\Protocols;
/**
* Class Fof
* Call of Duty Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*
* @author Wilson Jesus <>
*/
class Fof extends Source
class Cod extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'fof';
protected $name = 'cod';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Fistful of Frags";
protected $name_long = "Call of Duty";
}

View File

@ -19,24 +19,25 @@
namespace GameQ\Protocols;
/**
* Class Alienswarm
* Call of Duty United Offensive Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*
* @author Wilson Jesus <>
*/
class Alienswarm extends Source
class Coduo extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'alienswarm';
protected $name = 'coduo';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Alien Swarm";
protected $name_long = "Call of Duty: United Offensive";
}

View File

@ -0,0 +1,43 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Call of Duty World at War Class
*
* @package GameQ\Protocols
* @author naXe <naxeify@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Codwaw extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'codwaw';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Call of Duty: World at War";
}

View File

@ -19,25 +19,24 @@
namespace GameQ\Protocols;
/**
* Class Nmrih
* Class Contagion
*
* @package GameQ\Protocols
* @author Nikolay Ipanyuk <rostov114@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Nmrih extends Source
class Contagion extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'nmrih';
protected $name = 'contagion';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "No More Room in Hell";
protected $name_long = "Contagion";
}

View File

@ -19,24 +19,25 @@
namespace GameQ\Protocols;
/**
* Class Zps
* Class Crysis
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*
* @author Wilson Jesus <>
*/
class Zps extends Source
class Crysis extends Gamespy3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'zps';
protected $name = 'crysis';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Zombie Panic Source";
protected $name_long = "Crysis";
}

View File

@ -0,0 +1,43 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Class Crysis2
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Crysis2 extends Gamespy3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'crysis2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Crysis 2";
}

View File

@ -0,0 +1,263 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
use GameQ\Protocol;
use GameQ\Buffer;
use GameQ\Result;
use GameQ\Exception\Protocol as Exception;
/**
* Counter-Strike 2d Protocol Class
*
* Note:
* Unable to make player information calls work as the protocol does not like parallel requests
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Cs2d extends Protocol
{
/**
* Array of packets we want to query.
*
* @type array
*/
protected $packets = [
self::PACKET_STATUS => "\x01\x00\xFB\x01",
//self::PACKET_STATUS => "\x01\x00\x03\x10\x21\xFB\x01\x75\x00",
self::PACKET_PLAYERS => "\x01\x00\xFB\x05",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\x01\x00\xFB\x01" => "processDetails",
"\x01\x00\xFB\x05" => "processPlayers",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'cs2d';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'cs2d';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Counter-Strike 2d";
/**
* The client join link
*
* @type string
*/
protected $join_link = "cs2d://%s:%d/";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'game_mode',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'max_players',
'mod' => 'game_dir',
'numplayers' => 'num_players',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
'deaths' => 'deaths',
'score' => 'score',
],
];
/**
* Process the response for the Tibia server
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// We have a merged packet, try to split it back up
if (count($this->packets_response) == 1) {
// Temp buffer to make string manipulation easier
$buffer = new Buffer($this->packets_response[0]);
// Grab the header and set the packet we need to split with
$packet = (($buffer->lookAhead(4) === $this->packets[self::PACKET_PLAYERS]) ?
self::PACKET_STATUS : self::PACKET_PLAYERS);
// Explode the merged packet as the response
$responses = explode(substr($this->packets[$packet], 2), $buffer->getData());
// Try to rebuild the second packet to the same as if it was sent as two separate responses
$responses[1] = $this->packets[$packet] . ((count($responses) === 2) ? $responses[1] : "");
unset($buffer);
} else {
$responses = $this->packets_response;
}
// Will hold the packets after sorting
$packets = [];
// We need to pre-sort these for split packets so we can do extra work where needed
foreach ($responses as $response) {
$buffer = new Buffer($response);
// Pull out the header
$header = $buffer->read(4);
// Add the packet to the proper section, we will combine later
$packets[$header][] = $buffer->getBuffer();
}
unset($buffer);
$results = [];
// Now let's iterate and process
foreach ($packets as $header => $packetGroup) {
// Figure out which packet response this is
if (!array_key_exists($header, $this->responses)) {
throw new Exception(__METHOD__ . " response type '" . bin2hex($header) . "' is not valid");
}
// Now we need to call the proper method
$results = array_merge(
$results,
call_user_func_array([$this, $this->responses[$header]], [new Buffer(implode($packetGroup))])
);
}
unset($packets);
return $results;
}
/**
* 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();
// First int is the server flags
$serverFlags = $buffer->readInt8();
// Read server flags
$result->add('password', (int)$this->readFlag($serverFlags, 0));
$result->add('registered_only', (int)$this->readFlag($serverFlags, 1));
$result->add('fog_of_war', (int)$this->readFlag($serverFlags, 2));
$result->add('friendly_fire', (int)$this->readFlag($serverFlags, 3));
$result->add('bots_enabled', (int)$this->readFlag($serverFlags, 5));
$result->add('lua_scripts', (int)$this->readFlag($serverFlags, 6));
// Read the rest of the buffer data
$result->add('servername', utf8_encode($buffer->readPascalString(0)));
$result->add('mapname', utf8_encode($buffer->readPascalString(0)));
$result->add('num_players', $buffer->readInt8());
$result->add('max_players', $buffer->readInt8());
$result->add('game_mode', $buffer->readInt8());
$result->add('num_bots', (($this->readFlag($serverFlags, 5)) ? $buffer->readInt8() : 0));
$result->add('dedicated', 1);
unset($buffer);
return $result->fetch();
}
/**
* Handles processing the player data into a usable format
*
* @param Buffer $buffer
*
* @return array
* @throws Exception
*/
protected function processPlayers(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// First entry is the number of players in this list. Don't care
$buffer->read();
// Parse players
while ($buffer->getLength()) {
// Player id
if (($id = $buffer->readInt8()) !== 0) {
// Add the results
$result->addPlayer('id', $id);
$result->addPlayer('name', utf8_encode($buffer->readPascalString(0)));
$result->addPlayer('team', $buffer->readInt8());
$result->addPlayer('score', $buffer->readInt32());
$result->addPlayer('deaths', $buffer->readInt32());
}
}
unset($buffer, $id);
return $result->fetch();
}
/**
* Read flags from stored value
*
* @param $flags
* @param $offset
*
* @return bool
*/
protected function readFlag($flags, $offset)
{
return !!($flags & (1 << $offset));
}
}

View File

@ -19,12 +19,12 @@
namespace GameQ\Protocols;
/**
* Class Jc2
* Class Dark and Light
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Jc2 extends Source
class Dal extends Arkse
{
/**
@ -32,12 +32,12 @@ class Jc2 extends Source
*
* @type string
*/
protected $name = 'jc2';
protected $name = 'dal';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Just Cause 2 Multiplayer";
protected $name_long = "Dark and Light";
}

View File

@ -1,4 +1,5 @@
<?php
/**
* This file is part of GameQ.
*

View File

@ -0,0 +1,123 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
use GameQ\Exception\Protocol as Exception;
use GameQ\Result;
/**
* ECO Global Survival Protocol Class
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Eco extends Http
{
/**
* Packets to send
*
* @var array
*/
protected $packets = [
self::PACKET_STATUS => "GET /frontpage HTTP/1.0\r\nAccept: */*\r\n\r\n",
];
/**
* Http protocol is SSL
*
* @var string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The protocol being used
*
* @var string
*/
protected $protocol = 'eco';
/**
* String name of this protocol class
*
* @var string
*/
protected $name = 'eco';
/**
* Longer string name of this protocol class
*
* @var string
*/
protected $name_long = "ECO Global Survival";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
/**
* Normalize some items
*
* @var array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'hostname' => 'description',
'maxplayers' => 'totalplayers',
'numplayers' => 'onlineplayers',
'password' => 'haspassword',
],
];
/**
* Process the response
*
* @return array
* @throws Exception
*/
public function processResponse()
{
if (empty($this->packets_response)) {
return [];
}
// Implode and rip out the JSON
preg_match('/\{(.*)\}/ms', implode('', $this->packets_response), $matches);
// Return should be JSON, let's validate
if (!isset($matches[0]) || ($json = json_decode($matches[0])) === null) {
throw new Exception("JSON response from Eco server is invalid.");
}
$result = new Result();
// Server is always dedicated
$result->add('dedicated', 1);
foreach ($json->Info as $info => $setting) {
$result->add(strtolower($info), $setting);
}
return $result->fetch();
}
}

View File

@ -25,7 +25,7 @@ namespace GameQ\Protocols;
* @author Austin Bischoff <austin@codebeard.com>
* @author TacTicToe66 <https://github.com/TacTicToe66>
*/
class EgS extends Source
class Egs extends Source
{
/**

View File

@ -19,24 +19,25 @@
namespace GameQ\Protocols;
/**
* Class Aapg
* Wolfenstein Enemy Territory Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*
* @author Wilson Jesus <>
*/
class Aapg extends Aa3
class Et extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'aapg';
protected $name = 'et';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "America's Army: Proving Grounds";
protected $name_long = "Wolfenstein Enemy Territory";
}

View File

@ -140,7 +140,9 @@ class Gamespy extends Protocol
$itemCount = count($data);
// Now lets loop the array
// Check to make sure we have more than 1 item in the array before trying to loop
if (count($data) > 1) {
// Now lets loop the array since we have items
for ($x = 0; $x < $itemCount; $x += 2) {
// Set some local vars
$key = $data[$x];
@ -164,6 +166,7 @@ class Gamespy extends Protocol
$result->add($key, $val);
}
}
}
// Add the player and team count
$result->add('num_players', $numPlayers);

View File

@ -0,0 +1,269 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
use GameQ\Exception\Protocol as Exception;
use GameQ\Protocol;
use GameQ\Buffer;
use GameQ\Result;
/**
* GameSpy2 Protocol class
*
* Given the ability for non utf-8 characters to be used as hostnames, player names, etc... this
* version returns all strings utf-8 encoded (utf8_encode). To access the proper version of a
* string response you must use utf8_decode() on the specific response.
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Gamespy2 extends Protocol
{
/**
* Define the state of this class
*
* @type int
*/
protected $state = self::STATE_BETA;
/**
* 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_DETAILS => "\xFE\xFD\x00\x43\x4F\x52\x59\xFF\x00\x00",
self::PACKET_PLAYERS => "\xFE\xFD\x00\x43\x4F\x52\x58\x00\xFF\xFF",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\x00\x43\x4F\x52\x59" => "processDetails",
"\x00\x43\x4F\x52\x58" => "processPlayers",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'gamespy2';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'gamespy2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "GameSpy2 Server";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'gametype',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'maxplayers',
'mod' => 'mod',
'numplayers' => 'numplayers',
'password' => 'password',
],
];
/**
* Process the response
*
* @return array
* @throws Exception
*/
public function processResponse()
{
// Will hold the packets after sorting
$packets = [];
// We need to pre-sort these for split packets so we can do extra work where needed
foreach ($this->packets_response as $response) {
$buffer = new Buffer($response);
// Pull out the header
$header = $buffer->read(5);
// Add the packet to the proper section, we will combine later
$packets[$header][] = $buffer->getBuffer();
}
unset($buffer);
$results = [];
// Now let's iterate and process
foreach ($packets as $header => $packetGroup) {
// Figure out which packet response this is
if (!array_key_exists($header, $this->responses)) {
throw new Exception(__METHOD__ . " response type '" . bin2hex($header) . "' is not valid");
}
// Now we need to call the proper method
$results = array_merge(
$results,
call_user_func_array([$this, $this->responses[$header]], [new Buffer(implode($packetGroup))])
);
}
unset($packets);
return $results;
}
/*
* Internal methods
*/
/**
* Handles processing the details data into a usable format
*
* @param \GameQ\Buffer $buffer
*
* @return array
* @throws Exception
*/
protected function processDetails(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// We go until we hit an empty key
while ($buffer->getLength()) {
$key = $buffer->readString();
if (strlen($key) == 0) {
break;
}
$result->add($key, utf8_encode($buffer->readString()));
}
unset($buffer);
return $result->fetch();
}
/**
* Handles processing the players data into a usable format
*
* @param \GameQ\Buffer $buffer
*
* @return array
* @throws Exception
*/
protected function processPlayers(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Skip the header
$buffer->skip(1);
// Players are first
$this->parsePlayerTeam('players', $buffer, $result);
// Teams are next
$this->parsePlayerTeam('teams', $buffer, $result);
unset($buffer);
return $result->fetch();
}
/**
* Parse the player/team info returned from the player call
*
* @param string $dataType
* @param \GameQ\Buffer $buffer
* @param \GameQ\Result $result
*
* @throws Exception
*/
protected function parsePlayerTeam($dataType, Buffer &$buffer, Result &$result)
{
// Do count
$result->add('num_' . $dataType, $buffer->readInt8());
// Variable names
$varNames = [];
// Loop until we run out of length
while ($buffer->getLength()) {
$varNames[] = str_replace('_', '', $buffer->readString());
if ($buffer->lookAhead() === "\x00") {
$buffer->skip();
break;
}
}
// Check if there are any value entries
if ($buffer->lookAhead() == "\x00") {
$buffer->skip();
return;
}
// Get the values
while ($buffer->getLength() > 4) {
foreach ($varNames as $varName) {
$result->addSub($dataType, utf8_encode($varName), utf8_encode($buffer->readString()));
}
if ($buffer->lookAhead() === "\x00") {
$buffer->skip();
break;
}
}
return;
}
}

View File

@ -277,10 +277,15 @@ class Gamespy3 extends Protocol
// 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 = '';
// Save count as variable
$count = count($data);
// Loop through all of the $data for information and pull it out into the result
for ($x = 0; $x < count($data) - 1; $x++) {
for ($x = 0; $x < $count - 1; $x++) {
// Pull out the item
$item = $data[$x];
// If this is an empty item, move on
@ -330,6 +335,6 @@ class Gamespy3 extends Protocol
}
}
// Free up some memory
unset($data, $item, $item_group, $item_type, $val);
unset($count, $data, $item, $item_group, $item_type, $val);
}
}

View File

@ -0,0 +1,164 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
use GameQ\Exception\Protocol as Exception;
use GameQ\Result;
use GameQ\Server;
/**
* Grand Theft Auto Rage Protocol Class
* https://rage.mp/masterlist/
*
* Result from this call should be a header + JSON response
*
* @author K700 <admin@fianna.ru>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Gtar extends Http
{
/**
* Packets to send
*
* @var array
*/
protected $packets = [
self::PACKET_STATUS => "GET /master/ HTTP/1.0\r\nHost: cdn.rage.mp\r\nAccept: */*\r\n\r\n",
];
/**
* Http protocol is SSL
*
* @var string
*/
protected $transport = self::TRANSPORT_SSL;
/**
* The protocol being used
*
* @var string
*/
protected $protocol = 'gtar';
/**
* String name of this protocol class
*
* @var string
*/
protected $name = 'gtar';
/**
* Longer string name of this protocol class
*
* @var string
*/
protected $name_long = "Grand Theft Auto Rage";
/**
* Holds the real ip so we can overwrite it back
*
* @var string
*/
protected $realIp = null;
protected $realPortQuery = null;
/**
* Normalize some items
*
* @var array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'hostname' => 'hostname',
'mod' => 'mod',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
],
];
public function beforeSend(Server $server)
{
// Loop over the packets and update them
foreach ($this->packets as $packetType => $packet) {
// Fill out the packet with the server info
$this->packets[$packetType] = sprintf($packet, $server->ip . ':' . $server->port_query);
}
$this->realIp = $server->ip;
$this->realPortQuery = $server->port_query;
// Override the existing settings
$server->ip = 'cdn.rage.mp';
$server->port_query = 443;
}
/**
* Process the response
*
* @return array
* @throws Exception
*/
public function processResponse()
{
// No response, assume offline
if (empty($this->packets_response)) {
return [
'gq_address' => $this->realIp,
'gq_port_query' => $this->realPortQuery,
];
}
// Implode and rip out the JSON
preg_match('/\{(.*)\}/ms', implode('', $this->packets_response), $matches);
// Return should be JSON, let's validate
if (!isset($matches[0]) || ($json = json_decode($matches[0])) === null) {
throw new Exception("JSON response from Gtar protocol is invalid.");
}
$address = $this->realIp.':'.$this->realPortQuery;
$server = $json->$address;
if (empty($server)) {
return [
'gq_address' => $this->realIp,
'gq_port_query' => $this->realPortQuery,
];
}
$result = new Result();
// Server is always dedicated
$result->add('dedicated', 1);
$result->add('gq_address', $this->realIp);
$result->add('gq_port_query', $this->realPortQuery);
// Add server items
$result->add('hostname', $server->name);
$result->add('mod', $server->gamemode);
$result->add('numplayers', $server->players);
$result->add('maxplayers', $server->maxplayers);
return $result->fetch();
}
}

View File

@ -19,25 +19,24 @@
namespace GameQ\Protocols;
/**
* Class Projectcars
* Class Hurtworld
*
* @package GameQ\Protocols
* @author Nikolay Ipanyuk <rostov114@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Projectcars extends Source
class Hurtworld extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'projectcars';
protected $name = 'hurtworld';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Project Cars";
protected $name_long = "Hurtworld";
}

View File

@ -0,0 +1,49 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Insurgency Sandstorm Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Insurgencysand extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'insurgencysand';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Insurgency: Sandstorm";
/**
* query_port = client_port + 29
*
* @type int
*/
protected $port_diff = 29;
}

View File

@ -35,7 +35,7 @@ class Killingfloor extends Unreal2
*
* @type string
*/
protected $name = 'killing floor';
protected $name = 'killingfloor';
/**
* Longer string name of this protocol class

View File

@ -32,7 +32,7 @@ class Killingfloor2 extends Source
*
* @type string
*/
protected $name = 'killing floor 2';
protected $name = 'killingfloor2';
/**
* Longer string name of this protocol class

View File

@ -74,6 +74,6 @@ class Mohaa extends Gamespy
*/
public function findQueryPort($clientPort)
{
return $clientPort+97;
return $clientPort + 97;
}
}

View File

@ -19,12 +19,12 @@
namespace GameQ\Protocols;
/**
* Class Aa3
* Class MORDHAU
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
* @author Wilson Jesus <>
*/
class Aa3 extends Source
class Mordhau extends Source
{
/**
@ -32,22 +32,22 @@ class Aa3 extends Source
*
* @type string
*/
protected $name = 'aa3';
protected $name = 'mordhau';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "America's Army 3";
protected $name_long = "MORDHAU";
#protected $port = 7777;
/**
* Query port = client_port + 18243
*
* client_port default 8777
* query_port default 27020
* query_port = client_port + 19238
* 27015 = 7777 + 19238
*
* @type int
*/
protected $port_diff = 18243;
#protected $port_diff = 19238;
}

View File

@ -19,12 +19,12 @@
namespace GameQ\Protocols;
/**
* Class Tfc
* Class PixARK
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Tfc extends Source
class Pixark extends Arkse
{
/**
@ -32,12 +32,12 @@ class Tfc extends Source
*
* @type string
*/
protected $name = 'tfc';
protected $name = 'pixark';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Team Fortress Classic";
protected $name_long = "PixARK";
}

View File

@ -162,6 +162,7 @@ class Quake3 extends Protocol
* @param Buffer $buffer
*
* @return array
* @throws Exception
*/
protected function processPlayers(Buffer $buffer)
{
@ -173,24 +174,34 @@ class Quake3 extends Protocol
// Loop until we are out of data
while ($buffer->getLength()) {
// Make a new buffer with this block
$playerInfo = new Buffer($buffer->readString("\x0A"));
// Add player info
$result->addPlayer('frags', $playerInfo->readString("\x20"));
$result->addPlayer('ping', $playerInfo->readString("\x20"));
$result->addPlayer('frags', $buffer->readString("\x20"));
$result->addPlayer('ping', $buffer->readString("\x20"));
// Skip first "
$playerInfo->skip(1);
// Look ahead to see if we have a name or team
$checkTeam = $buffer->lookAhead(1);
// We have team info
if ($checkTeam != '' and $checkTeam != '"') {
$result->addPlayer('team', $buffer->readString("\x20"));
}
// Check to make sure we have player name
$checkPlayerName = $buffer->read();
// Bad response
if ($checkPlayerName !== '"') {
throw new Exception('Expected " but got ' . $checkPlayerName . ' for beginning of player name string!');
}
// Add player name, encoded
$result->addPlayer('name', utf8_encode(trim(($playerInfo->readString('"')))));
$result->addPlayer('name', utf8_encode(trim($buffer->readString('"'))));
// Burn ending delimiter
$buffer->read();
// Increment
$playerCount++;
// Clear
unset($playerInfo);
}
$result->add('clients', $playerCount);

View File

@ -0,0 +1,43 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Red Orchestra: Ostfront 41-45 Class
*
* @package GameQ\Protocols
* @author naXe <naxeify@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Redorchestraostfront extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'redorchestraostfront';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Red Orchestra: Ostfront 41-45";
}

View File

@ -86,6 +86,13 @@ class Samp extends Protocol
*/
protected $server_code = null;
/**
* The client join link
*
* @type string
*/
protected $join_link = "samp://%s:%d/";
/**
* Normalize settings for this protocol
*
@ -139,7 +146,7 @@ class Samp extends Protocol
{
// Results that will be returned
$results = [ ];
$results = [];
// Get the length of the server code so we can figure out how much to read later
$serverCodeLength = strlen($this->server_code);
@ -170,7 +177,7 @@ class Samp extends Protocol
// Now we need to call the proper method
$results = array_merge(
$results,
call_user_func_array([ $this, $this->responses[$response_type] ], [ $buffer ])
call_user_func_array([$this, $this->responses[$response_type]], [$buffer])
);
unset($buffer);
@ -206,7 +213,7 @@ class Samp extends Protocol
$result->add('max_players', $buffer->readInt16());
// These are read differently for these last 3
$result->add('servername', $buffer->read($buffer->readInt32()));
$result->add('servername', utf8_encode($buffer->read($buffer->readInt32())));
$result->add('gametype', $buffer->read($buffer->readInt32()));
$result->add('language', $buffer->read($buffer->readInt32()));
@ -234,7 +241,7 @@ class Samp extends Protocol
// Run until we run out of buffer
while ($buffer->getLength()) {
$result->addPlayer('id', $buffer->readInt8());
$result->addPlayer('name', $buffer->readPascalString());
$result->addPlayer('name', utf8_encode($buffer->readPascalString()));
$result->addPlayer('score', $buffer->readInt32());
$result->addPlayer('ping', $buffer->readInt32());
}

View File

@ -0,0 +1,75 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Serious Sam Protocol Class
*
* @author ZCaliptium <zcaliptium@gmail.com>
*/
class Serioussam extends Gamespy
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'serioussam';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Serious Sam";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'gametype',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'maxplayers',
'mod' => 'activemod',
'numplayers' => 'numplayers',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'player',
'ping' => 'ping',
'score' => 'frags',
],
];
}

View File

@ -0,0 +1,49 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Soldier of Fortune 2 Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Sof2 extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'sof2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Solder of Fortune II";
/**
* The client join link
*
* @type string
*/
protected $join_link = "sof2mp://%s:%d/";
}

View File

@ -50,7 +50,7 @@ class Source extends Protocol
*/
protected $packets = [
self::PACKET_CHALLENGE => "\xFF\xFF\xFF\xFF\x56\x00\x00\x00\x00",
self::PACKET_DETAILS => "\xFF\xFF\xFF\xFFTSource Engine Query\x00",
self::PACKET_DETAILS => "\xFF\xFF\xFF\xFFTSource Engine Query\x00%s",
self::PACKET_PLAYERS => "\xFF\xFF\xFF\xFF\x55%s",
self::PACKET_RULES => "\xFF\xFF\xFF\xFF\x56%s",
];

View File

@ -0,0 +1,50 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Class Swat4
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Swat4 extends Gamespy2
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'swat4';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "SWAT 4";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
}

View File

@ -1,4 +1,5 @@
<?php
/**
* This file is part of GameQ.
*
@ -122,7 +123,8 @@ class Teamspeak3 extends Protocol
{
// Check to make sure we have a query_port because it is required
if (!isset($this->options[Server::SERVER_OPTIONS_QUERY_PORT])
if (
!isset($this->options[Server::SERVER_OPTIONS_QUERY_PORT])
|| empty($this->options[Server::SERVER_OPTIONS_QUERY_PORT])
) {
throw new Exception(__METHOD__ . " Missing required setting '" . Server::SERVER_OPTIONS_QUERY_PORT . "'.");

View File

@ -0,0 +1,49 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Urban Terror Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Urbanterror extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'urbanterror';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Urban Terror";
/**
* The client join link
*
* @type string
*/
protected $join_link = "urt://%s:%d/";
}

View File

@ -0,0 +1,41 @@
<?php
/**
* This file is part of GameQ.
*
* GameQ is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* GameQ is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Class Valheim
*
* @package GameQ\Protocols
*
*/
class Valheim extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'valheim';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Valheim";
}

View File

@ -778,11 +778,11 @@ class Ventrilo extends Protocol
$characterCount = count($chars);
$key = 0;
for ($i = 1; $i <= $characterCount; $i++) {
$chars[$i] -= ($table[$a2] + (($i - 1) % 5)) & 0xFF;
for ($index = 1; $index <= $characterCount; $index++) {
$chars[$index] -= ($table[$a2] + (($index - 1) % 5)) & 0xFF;
$a2 = ($a2 + $a1) & 0xFF;
if (($i % 2) == 0) {
$short_array = unpack("n1", pack("C2", $chars[$i - 1], $chars[$i]));
if (($index % 2) == 0) {
$short_array = unpack("n1", pack("C2", $chars[$index - 1], $chars[$index]));
$header_items[$key] = $short_array[1];
++$key;
}
@ -818,10 +818,10 @@ class Ventrilo extends Protocol
$data = "";
$characterCount = count($chars);
for ($i = 1; $i <= $characterCount; $i++) {
$chars[$i] -= ($table[$a2] + (($i - 1) % 72)) & 0xFF;
for ($index = 1; $index <= $characterCount; $index++) {
$chars[$index] -= ($table[$a2] + (($index - 1) % 72)) & 0xFF;
$a2 = ($a2 + $a1) & 0xFF;
$data .= chr($chars[$i]);
$data .= chr($chars[$index]);
}
//@todo: Check CRC ???
$decrypted[$header_items['pck']] = $data;

View File

@ -112,6 +112,12 @@ class Native extends Core
// Set blocking mode
stream_set_blocking($this->socket, $this->blocking);
// Set the read buffer
stream_set_read_buffer($this->socket, 0);
// Set the write buffer
stream_set_write_buffer($this->socket, 0);
} else {
// Reset socket
$this->socket = null;
@ -193,7 +199,7 @@ class Native extends Core
/* @var $socket resource */
// See if we have a response
if (($response = fread($socket, 8192)) === false) {
if (($response = fread($socket, 32768)) === false) {
continue; // No response yet so lets continue.
}

View File

@ -38,7 +38,7 @@ class Result
* Adds variable to results
*
* @param string $name Variable name
* @param string $value Variable value
* @param string|array $value Variable value
*/
public function add($name, $value)
{
@ -87,7 +87,8 @@ class Result
// Find the first entry that doesn't have this variable
$found = false;
for ($i = 0; $i != count($this->result[$sub]); $i++) {
$count = count($this->result[$sub]);
for ($i = 0; $i != $count; $i++) {
if (!isset($this->result[$sub][$i][$key])) {
$this->result[$sub][$i][$key] = $value;
$found = true;
@ -99,6 +100,8 @@ class Result
if (!$found) {
$this->result[$sub][][$key] = $value;
}
unset($count);
}
/**