Moved the Agents into their own repo. Kept the agent.pl just for reference

This commit is contained in:
Frank Harris 2025-09-11 13:27:32 -04:00
parent 22381be29a
commit 8680a02b13
18132 changed files with 0 additions and 2569420 deletions

View file

@ -1,53 +0,0 @@
<?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 Aa3
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Aa3 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'aa3';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "America's Army 3";
/**
* Query port = client_port + 18243
*
* client_port default 8777
* query_port default 27020
*
* @type int
*/
protected $port_diff = 18243;
}

View file

@ -1,42 +0,0 @@
<?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 Aapg
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Aapg extends Aa3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'aapg';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "America's Army: Proving Grounds";
}

View file

@ -1,51 +0,0 @@
<?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 ARK: Survival Evolved
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Arkse extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'arkse';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "ARK: Survival Evolved";
/**
* query_port = client_port + 19238
* 27015 = 7777 + 19238
*
* @type int
*/
protected $port_diff = 19238;
}

View file

@ -1,43 +0,0 @@
<?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 Arma
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Arma extends Gamespy2
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'arma';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "ArmA Armed Assault";
}

View file

@ -1,181 +0,0 @@
<?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\Buffer;
use GameQ\Result;
/**
* Class Armed Assault 3
*
* Rules protocol reference: https://community.bistudio.com/wiki/Arma_3_ServerBrowserProtocol2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
* @author Memphis017 <https://github.com/Memphis017>
*/
class Arma3 extends Source
{
/**
* Defines the names for the specific game DLCs
*
* @var array
*/
protected $dlcNames = [
'af82811b' => 'Karts',
'94f76a1a' => 'Marksmen',
'd0356eec' => 'Helicopters',
'19984a71' => 'Zeus',
'7fb4b1f3' => 'Apex',
'49c2c12b' => 'Jets',
'7e766e18' => 'Laws of War',
'99d71f90' => 'Malden',
'a8b10cdf' => 'Tac-Ops',
'37680ce8' => 'Tanks',
'43f9c377' => 'Contact',
'c4979557' => 'Enoch',
];
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'arma3';
/**
* Longer string name of this protocol class
*
* @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 = decbin($responseBuffer->readInt8()); // Grab DLC bit 1 and use it later
$dlcBit2 = decbin($responseBuffer->readInt8()); // Grab DLC bit 2 and use it later
$dlcCount = substr_count($dlcBit, '1') + substr_count($dlcBit2, '1'); // Count the DLCs
// 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());
// Loop over the DLC bit so we can pull in the info for the DLC (if enabled)
for ($x = 0; $x < $dlcCount; $x++) {
$dlcHash = dechex($responseBuffer->readInt32());
isset($this->dlcNames[$dlcHash]) ?
$result->addSub('dlcs', 'name', $this->dlcNames[$dlcHash])
: $result->addSub('dlcs', 'name', 'Unknown');
$result->addSub('dlcs', 'hash', $dlcHash);
}
// No longer needed
unset($dlcBit, $dlcBit2, $dlcCount, $dlcHash);
// 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);
// Get the signatures count
$signatureCount = $responseBuffer->readInt8();
$result->add('signature_count', $signatureCount);
// Make signatures array
$signatures = [];
// Loop until we run out of signatures
for ($x = 0; $x < $signatureCount; $x++) {
$signatures[] = $responseBuffer->readPascalString(0, true);
}
// Add as a simple array
$result->add('signatures', $signatures);
unset($responseBuffer, $signatureCount, $signatures, $x);
return $result->fetch();
}
}

View file

@ -1,50 +0,0 @@
<?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 Armedassault2oa
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Armedassault2oa extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = "armedassault2oa";
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Armed Assault 2: Operation Arrowhead";
/**
* Query port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
}

View file

@ -1,32 +0,0 @@
<?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;
/**
* Armed assault 3 dummy Protocol Class
*
* Added for backward compatibility, please update to class arma3
*
* @deprecated v3.0.10
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Armedassault3 extends Arma3
{
}

View file

@ -1,208 +0,0 @@
<?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;
/**
* All-Seeing Eye Protocol class
*
* @author Marcel Bößendörfer <m.boessendoerfer@marbis.net>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Ase extends Protocol
{
/**
* 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_ALL => "s",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'ase';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'ase';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "All-Seeing Eye";
/**
* 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' => 'servername',
'mapname' => 'map',
'maxplayers' => 'max_players',
'mod' => 'game_dir',
'numplayers' => 'num_players',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
'score' => 'score',
'team' => 'team',
'ping' => 'ping',
'time' => 'time',
],
];
/**
* Process the response
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// Create a new buffer
$buffer = new Buffer(implode('', $this->packets_response));
// Burn the header
$buffer->skip(4);
// Create a new result
$result = new Result();
// Variables
$result->add('gamename', $buffer->readPascalString(1, true));
$result->add('port', $buffer->readPascalString(1, true));
$result->add('servername', $buffer->readPascalString(1, true));
$result->add('gametype', $buffer->readPascalString(1, true));
$result->add('map', $buffer->readPascalString(1, true));
$result->add('version', $buffer->readPascalString(1, true));
$result->add('password', $buffer->readPascalString(1, true));
$result->add('num_players', $buffer->readPascalString(1, true));
$result->add('max_players', $buffer->readPascalString(1, true));
$result->add('dedicated', 1);
// Offload the key/value pair processing
$this->processKeyValuePairs($buffer, $result);
// Offload processing player and team info
$this->processPlayersAndTeams($buffer, $result);
unset($buffer);
return $result->fetch();
}
/*
* Internal methods
*/
/**
* Handles processing the extra key/value pairs for server settings
*
* @param \GameQ\Buffer $buffer
* @param \GameQ\Result $result
*/
protected function processKeyValuePairs(Buffer &$buffer, Result &$result)
{
// Key / value pairs
while ($buffer->getLength()) {
$key = $buffer->readPascalString(1, true);
// If we have an empty key, we've reached the end
if (empty($key)) {
break;
}
// Otherwise, add the pair
$result->add(
$key,
$buffer->readPascalString(1, true)
);
}
unset($key);
}
/**
* 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)
{
// Players and team info
while ($buffer->getLength()) {
// Get the flags
$flags = $buffer->readInt8();
// Get data according to the flags
if ($flags & 1) {
$result->addPlayer('name', $buffer->readPascalString(1, true));
}
if ($flags & 2) {
$result->addPlayer('team', $buffer->readPascalString(1, true));
}
if ($flags & 4) {
$result->addPlayer('skin', $buffer->readPascalString(1, true));
}
if ($flags & 8) {
$result->addPlayer('score', $buffer->readPascalString(1, true));
}
if ($flags & 16) {
$result->addPlayer('ping', $buffer->readPascalString(1, true));
}
if ($flags & 32) {
$result->addPlayer('time', $buffer->readPascalString(1, true));
}
}
}
}

View file

@ -1,55 +0,0 @@
<?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

@ -1,68 +0,0 @@
<?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 Battalion 1944
*
* @package GameQ\Protocols
* @author TacTicToe66 <https://github.com/TacTicToe66>
*/
class Batt1944 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'batt1944';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Battalion 1944";
/**
* query_port = client_port + 3
*
* @type int
*/
protected $port_diff = 3;
/**
* Normalize main fields
*
* @var array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'bat_gamemode_s',
'hostname' => 'bat_name_s',
'mapname' => 'bat_map_s',
'maxplayers' => 'bat_max_players_i',
'numplayers' => 'bat_player_count_s',
'password' => 'bat_has_password_s',
],
];
}

View file

@ -1,88 +0,0 @@
<?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 Battlefield 1942
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Bf1942 extends Gamespy
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'bf1942';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Battlefield 1942";
/**
* query_port = client_port + 8433
* 23000 = 14567 + 8433
*
* @type int
*/
protected $port_diff = 8433;
/**
* The client join link
*
* @type string
*/
protected $join_link = "bf1942://%s:%d";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'gametype',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'playername',
'kills' => 'kills',
'deaths' => 'deaths',
'ping' => 'ping',
'score' => 'score',
],
'team' => [
'name' => 'teamname',
],
];
}

View file

@ -1,98 +0,0 @@
<?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 Battlefield 2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Bf2 extends Gamespy3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'bf2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Battlefield 2";
/**
* query_port = client_port + 8433
* 29900 = 16567 + 13333
*
* @type int
*/
protected $port_diff = 13333;
/**
* The client join link
*
* @type string
*/
protected $join_link = "bf2://%s:%d";
/**
* BF2 has a different query packet to send than "normal" Gamespy 3
*
* @var array
*/
protected $packets = [
self::PACKET_ALL => "\xFE\xFD\x00\x10\x20\x30\x40\xFF\xFF\xFF\x01",
];
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'gametype',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'player',
'kills' => 'score',
'deaths' => 'deaths',
'ping' => 'ping',
'score' => 'score',
],
'team' => [
'name' => 'team',
'score' => 'score',
],
];
}

View file

@ -1,348 +0,0 @@
<?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;
/**
* Battlefield 3 Protocol Class
*
* Good place for doc status and info is http://www.fpsadmin.com/forum/showthread.php?t=24134
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Bf3 extends Protocol
{
/**
* Array of packets we want to query.
*
* @type array
*/
protected $packets = [
self::PACKET_STATUS => "\x00\x00\x00\x21\x1b\x00\x00\x00\x01\x00\x00\x00\x0a\x00\x00\x00serverInfo\x00",
self::PACKET_VERSION => "\x00\x00\x00\x22\x18\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00version\x00",
self::PACKET_PLAYERS =>
"\x00\x00\x00\x23\x24\x00\x00\x00\x02\x00\x00\x00\x0b\x00\x00\x00listPlayers\x00\x03\x00\x00\x00\x61ll\x00",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
1627389952 => "processDetails", // a
1644167168 => "processVersion", // b
1660944384 => "processPlayers", // c
];
/**
* The transport mode for this protocol is TCP
*
* @type string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'bf3';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'bf3';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Battlefield 3";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* query_port = client_port + 22000
* 47200 = 25200 + 22000
*
* @type int
*/
protected $port_diff = 22000;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'hostname' => 'hostname',
'mapname' => 'map',
'maxplayers' => 'max_players',
'numplayers' => 'num_players',
'password' => 'password',
],
'player' => [
'name' => 'name',
'score' => 'score',
'ping' => 'ping',
],
'team' => [
'score' => 'tickets',
],
];
/**
* Process the response for the StarMade server
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// Holds the results sent back
$results = [];
// Holds the processed packets after having been reassembled
$processed = [];
// Start up the index for the processed
$sequence_id_last = 0;
foreach ($this->packets_response as $packet) {
// Create a new buffer
$buffer = new Buffer($packet);
// Each "good" packet begins with sequence_id (32-bit)
$sequence_id = $buffer->readInt32();
// Sequence id is a response
if (array_key_exists($sequence_id, $this->responses)) {
$processed[$sequence_id] = $buffer->getBuffer();
$sequence_id_last = $sequence_id;
} else {
// This is a continuation of the previous packet, reset the buffer and append
$buffer->jumpto(0);
// Append
$processed[$sequence_id_last] .= $buffer->getBuffer();
}
}
unset($buffer, $sequence_id_last, $sequence_id);
// Iterate over the combined packets and do some work
foreach ($processed as $sequence_id => $data) {
// Create a new buffer
$buffer = new Buffer($data);
// Get the length of the packet
$packetLength = $buffer->getLength();
// Check to make sure the expected length matches the real length
// Subtract 4 for the sequence_id pulled out earlier
if ($packetLength != ($buffer->readInt32() - 4)) {
throw new Exception(__METHOD__ . " packet length does not match expected length!");
}
// Now we need to call the proper method
$results = array_merge(
$results,
call_user_func_array([$this, $this->responses[$sequence_id]], [$buffer])
);
}
return $results;
}
/*
* Internal Methods
*/
/**
* 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;
}
/**
* Process the server details
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processDetails(Buffer $buffer)
{
// Decode into items
$items = $this->decode($buffer);
// Set the result to a new result instance
$result = new Result();
// Server is always dedicated
$result->add('dedicated', 1);
// These are the same no matter what mode the server is in
$result->add('hostname', $items[1]);
$result->add('num_players', (int)$items[2]);
$result->add('max_players', (int)$items[3]);
$result->add('gametype', $items[4]);
$result->add('map', $items[5]);
$result->add('roundsplayed', (int)$items[6]);
$result->add('roundstotal', (int)$items[7]);
$result->add('num_teams', (int)$items[8]);
// Set the current index
$index_current = 9;
// Pull the team count
$teamCount = $result->get('num_teams');
// Loop for the number of teams found, increment along the way
for ($id = 1; $id <= $teamCount; $id++, $index_current++) {
// Shows the tickets
$result->addTeam('tickets', $items[$index_current]);
// We add an id so we know which team this is
$result->addTeam('id', $id);
}
// Get and set the rest of the data points.
$result->add('targetscore', (int)$items[$index_current]);
$result->add('online', 1); // Forced true, it seems $words[$index_current + 1] is always empty
$result->add('ranked', (int)$items[$index_current + 2]);
$result->add('punkbuster', (int)$items[$index_current + 3]);
$result->add('password', (int)$items[$index_current + 4]);
$result->add('uptime', (int)$items[$index_current + 5]);
$result->add('roundtime', (int)$items[$index_current + 6]);
// Added in R9
$result->add('ip_port', $items[$index_current + 7]);
$result->add('punkbuster_version', $items[$index_current + 8]);
$result->add('join_queue', (int)$items[$index_current + 9]);
$result->add('region', $items[$index_current + 10]);
$result->add('pingsite', $items[$index_current + 11]);
$result->add('country', $items[$index_current + 12]);
// Added in R29, No docs as of yet
$result->add('quickmatch', (int)$items[$index_current + 13]); // Guessed from research
unset($items, $index_current, $teamCount, $buffer);
return $result->fetch();
}
/**
* Process the server version
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processVersion(Buffer $buffer)
{
// Decode into items
$items = $this->decode($buffer);
// Set the result to a new result instance
$result = new Result();
$result->add('version', $items[2]);
unset($buffer, $items);
return $result->fetch();
}
/**
* Process the players
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processPlayers(Buffer $buffer)
{
// Decode into items
$items = $this->decode($buffer);
// Set the result to a new result instance
$result = new Result();
// Number of data points per player
$numTags = $items[1];
// Grab the tags for each player
$tags = array_slice($items, 2, $numTags);
// Get the player count
$playerCount = $items[$numTags + 2];
// Iterate over the index until we run out of players
for ($i = 0, $x = $numTags + 3; $i < $playerCount; $i++, $x += $numTags) {
// Loop over the player tags and extract the info for that tag
foreach ($tags as $index => $tag) {
$result->addPlayer($tag, $items[($x + $index)]);
}
}
return $result->fetch();
}
}

View file

@ -1,114 +0,0 @@
<?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\Buffer;
use GameQ\Result;
/**
* Battlefield 4 Protocol class
*
* Good place for doc status and info is http://battlelog.battlefield.com/bf4/forum/view/2955064768683911198/
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Bf4 extends Bf3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'bf4';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Battlefield 4";
/**
* Handle processing details since they are different than BF3
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processDetails(Buffer $buffer)
{
// Decode into items
$items = $this->decode($buffer);
// Set the result to a new result instance
$result = new Result();
// Server is always dedicated
$result->add('dedicated', 1);
// These are the same no matter what mode the server is in
$result->add('hostname', $items[1]);
$result->add('num_players', (int) $items[2]);
$result->add('max_players', (int) $items[3]);
$result->add('gametype', $items[4]);
$result->add('map', $items[5]);
$result->add('roundsplayed', (int) $items[6]);
$result->add('roundstotal', (int) $items[7]);
$result->add('num_teams', (int) $items[8]);
// Set the current index
$index_current = 9;
// Pull the team count
$teamCount = $result->get('num_teams');
// Loop for the number of teams found, increment along the way
for ($id = 1; $id <= $teamCount; $id++, $index_current++) {
// Shows the tickets
$result->addTeam('tickets', $items[$index_current]);
// We add an id so we know which team this is
$result->addTeam('id', $id);
}
// Get and set the rest of the data points.
$result->add('targetscore', (int) $items[$index_current]);
$result->add('online', 1); // Forced true, it seems $words[$index_current + 1] is always empty
$result->add('ranked', (int) $items[$index_current + 2]);
$result->add('punkbuster', (int) $items[$index_current + 3]);
$result->add('password', (int) $items[$index_current + 4]);
$result->add('uptime', (int) $items[$index_current + 5]);
$result->add('roundtime', (int) $items[$index_current + 6]);
$result->add('ip_port', $items[$index_current + 7]);
$result->add('punkbuster_version', $items[$index_current + 8]);
$result->add('join_queue', (int) $items[$index_current + 9]);
$result->add('region', $items[$index_current + 10]);
$result->add('pingsite', $items[$index_current + 11]);
$result->add('country', $items[$index_current + 12]);
//$result->add('quickmatch', (int) $items[$index_current + 13]); Supposed to be here according to R42 but is not
$result->add('blaze_player_count', (int) $items[$index_current + 13]);
$result->add('blaze_game_state', (int) $items[$index_current + 14]);
unset($items, $index_current, $teamCount, $buffer);
return $result->fetch();
}
}

View file

@ -1,326 +0,0 @@
<?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;
/**
* Battlefield Bad Company 2 Protocol Class
*
* NOTE: There are no qualifiers to the response packets sent back from the server as to which response packet
* belongs to which query request. For now this class assumes the responses are in the same order as the order in
* which the packets were sent to the server. If this assumption turns out to be wrong there is easy way to tell which
* response belongs to which query. Hopefully this assumption will hold true as it has in my testing.
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Bfbc2 extends Protocol
{
/**
* Array of packets we want to query.
*
* @type array
*/
protected $packets = [
self::PACKET_VERSION => "\x00\x00\x00\x00\x18\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00version\x00",
self::PACKET_STATUS => "\x00\x00\x00\x00\x1b\x00\x00\x00\x01\x00\x00\x00\x0a\x00\x00\x00serverInfo\x00",
self::PACKET_PLAYERS => "\x00\x00\x00\x00\x24\x00\x00\x00\x02\x00\x00\x00\x0b\x00\x00\x00listPlayers\x00\x03\x00\x00\x00\x61ll\x00",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"processVersion",
"processDetails",
"processPlayers",
];
/**
* The transport mode for this protocol is TCP
*
* @type string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'bfbc2';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'bfbc2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Battlefield Bad Company 2";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* query_port = client_port + 29321
* 48888 = 19567 + 29321
*
* @type int
*/
protected $port_diff = 29321;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'hostname' => 'hostname',
'mapname' => 'map',
'maxplayers' => 'max_players',
'numplayers' => 'num_players',
'password' => 'password',
],
'player' => [
'name' => 'name',
'score' => 'score',
'ping' => 'ping',
],
'team' => [
'score' => 'tickets',
],
];
/**
* Process the response for the StarMade server
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
//print_r($this->packets_response);
// Holds the results sent back
$results = [];
// Iterate over the response packets
// @todo: This protocol has no packet ordering, ids or anyway to identify which packet coming back belongs to which initial call.
foreach ($this->packets_response as $i => $packet) {
// Create a new buffer
$buffer = new Buffer($packet);
// Burn first 4 bytes, same across all packets
$buffer->skip(4);
// Get the packet length
$packetLength = $buffer->getLength();
// Check to make sure the expected length matches the real length
// Subtract 4 for the header burn
if ($packetLength != ($buffer->readInt32() - 4)) {
throw new Exception(__METHOD__ . " packet length does not match expected length!");
}
// We assume the packets are coming back in the same order as sent, this maybe incorrect...
$results = array_merge(
$results,
call_user_func_array([$this, $this->responses[$i]], [$buffer])
);
}
unset($buffer, $packetLength);
return $results;
}
/*
* Internal Methods
*/
/**
* 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;
}
/**
* Process the server details
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processDetails(Buffer $buffer)
{
// Decode into items
$items = $this->decode($buffer);
// Set the result to a new result instance
$result = new Result();
// Server is always dedicated
$result->add('dedicated', 1);
// These are the same no matter what mode the server is in
$result->add('hostname', $items[1]);
$result->add('num_players', (int)$items[2]);
$result->add('max_players', (int)$items[3]);
$result->add('gametype', $items[4]);
$result->add('map', $items[5]);
$result->add('roundsplayed', (int)$items[6]);
$result->add('roundstotal', (int)$items[7]);
$result->add('num_teams', (int)$items[8]);
// Set the current index
$index_current = 9;
// Pull the team count
$teamCount = $result->get('num_teams');
// Loop for the number of teams found, increment along the way
for ($id = 1; $id <= $teamCount; $id++, $index_current++) {
// Shows the tickets
$result->addTeam('tickets', $items[$index_current]);
// We add an id so we know which team this is
$result->addTeam('id', $id);
}
// Get and set the rest of the data points.
$result->add('targetscore', (int)$items[$index_current]);
$result->add('online', 1); // Forced true, shows accepting players
$result->add('ranked', (($items[$index_current + 2] == 'true') ? 1 : 0));
$result->add('punkbuster', (($items[$index_current + 3] == 'true') ? 1 : 0));
$result->add('password', (($items[$index_current + 4] == 'true') ? 1 : 0));
$result->add('uptime', (int)$items[$index_current + 5]);
$result->add('roundtime', (int)$items[$index_current + 6]);
$result->add('mod', $items[$index_current + 7]);
$result->add('ip_port', $items[$index_current + 9]);
$result->add('punkbuster_version', $items[$index_current + 10]);
$result->add('join_queue', (($items[$index_current + 11] == 'true') ? 1 : 0));
$result->add('region', $items[$index_current + 12]);
unset($items, $index_current, $teamCount, $buffer);
return $result->fetch();
}
/**
* Process the server version
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processVersion(Buffer $buffer)
{
// Decode into items
$items = $this->decode($buffer);
// Set the result to a new result instance
$result = new Result();
$result->add('version', $items[2]);
unset($buffer, $items);
return $result->fetch();
}
/**
* Process the players
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processPlayers(Buffer $buffer)
{
// Decode into items
$items = $this->decode($buffer);
// Set the result to a new result instance
$result = new Result();
// Number of data points per player
$numTags = $items[1];
// Grab the tags for each player
$tags = array_slice($items, 2, $numTags);
// Get the player count
$playerCount = $items[$numTags + 2];
// Iterate over the index until we run out of players
for ($i = 0, $x = $numTags + 3; $i < $playerCount; $i++, $x += $numTags) {
// Loop over the player tags and extract the info for that tag
foreach ($tags as $index => $tag) {
$result->addPlayer($tag, $items[($x + $index)]);
}
}
return $result->fetch();
}
}

View file

@ -1,43 +0,0 @@
<?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;
/**
* Battlefield Hardline Protocol class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Bfh extends Bf4
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'bfh';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Battlefield Hardline";
}

View file

@ -1,50 +0,0 @@
<?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

@ -1,43 +0,0 @@
<?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 Protocol Class
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Cod extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'cod';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Call of Duty";
}

View file

@ -1,42 +0,0 @@
<?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 2 Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Cod2 extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'cod2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Call of Duty 2";
}

View file

@ -1,42 +0,0 @@
<?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 4 Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Cod4 extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'cod4';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Call of Duty 4";
}

View file

@ -1,50 +0,0 @@
<?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 Codmw3
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Codmw3 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'codmw3';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Call of Duty: Modern Warfare 3";
/**
* query_port = client_port + 2
*
* @type int
*/
protected $port_diff = 2;
}

View file

@ -1,43 +0,0 @@
<?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 United Offensive Class
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Coduo extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'coduo';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Call of Duty: United Offensive";
}

View file

@ -1,43 +0,0 @@
<?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

@ -1,42 +0,0 @@
<?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 Conanexiles
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Conanexiles extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'conanexiles';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Conan Exiles";
}

View file

@ -1,42 +0,0 @@
<?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 Contagion
*
* @package GameQ\Protocols
* @author Nikolay Ipanyuk <rostov114@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Contagion extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'contagion';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Contagion";
}

View file

@ -1,43 +0,0 @@
<?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 Crysis
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Crysis extends Gamespy3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'crysis';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Crysis";
}

View file

@ -1,43 +0,0 @@
<?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

@ -1,43 +0,0 @@
<?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 Crysiswars
*
* @package GameQ\Protocols
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Crysiswars extends Gamespy3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'crysiswars';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Crysis Wars";
}

View file

@ -1,45 +0,0 @@
<?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;
/**
* Counter-Strike 1.5 Protocol Class
*
* @author Nikolay Ipanyuk <rostov114@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*
* @package GameQ\Protocols
*/
class Cs15 extends Won
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'cs15';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Counter-Strike 1.5";
}

View file

@ -1,69 +0,0 @@
<?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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
/**
* Class Cs16
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Cs16 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'cs16';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Counter-Strike 1.6";
/**
* In the case of cs 1.6 we offload split packets here because the split packet response for rules is in
* the old gold source format
*
* @param $packet_id
* @param array $packets
*
* @return string
* @throws \GameQ\Exception\Protocol
*/
protected function processPackets($packet_id, array $packets = [])
{
// The response is gold source if the packets are split
$this->source_engine = self::GOLDSOURCE_ENGINE;
// Offload to the parent
$packs = parent::processPackets($packet_id, $packets);
// Reset the engine
$this->source_engine = self::SOURCE_ENGINE;
// Return the result
return $packs;
}
}

View file

@ -1,263 +0,0 @@
<?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

@ -1,45 +0,0 @@
<?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 Cscz
*
* Based off of CS 1.6
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Cscz extends Cs16
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'cscz';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Counter-Strike: Condition Zero";
}

View file

@ -1,43 +0,0 @@
<?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 Csgo
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Csgo extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'csgo';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Counter-Strike: Global Offensive";
}

View file

@ -1,42 +0,0 @@
<?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 Css
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Css extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'css';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Counter-Strike: Source";
}

View file

@ -1,43 +0,0 @@
<?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 Dark and Light
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Dal extends Arkse
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'dal';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Dark and Light";
}

View file

@ -1,66 +0,0 @@
<?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 Dayz
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Dayz extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'dayz';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "DayZ Standalone";
/**
* Overload the math used to guess at the Query Port
*
* @param int $clientPort
*
* @return int
*/
public function findQueryPort($clientPort)
{
/*
* Port layout:
* 2302 - 27016
* 2402 - 27017
* 2502 - 27018
* 2602 - 27019
* 2702 - 27020
* ...
*/
return 27016 + (($clientPort - 2302) / 100);
}
}

View file

@ -1,44 +0,0 @@
<?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 Dayzmod
*
* @package GameQ\Protocols
* @author Marcel Bößendörfer <m.boessendoerfer@marbis.net>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Dayzmod extends Armedassault2oa
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'dayzmod';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "DayZ Mod";
}

View file

@ -1,45 +0,0 @@
<?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 Dod
*
* Based off of CS 1.6
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Dod extends Cs16
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'dod';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Day of Defeat";
}

View file

@ -1,42 +0,0 @@
<?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 Dods
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Dods extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'dods';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Day of Defeat: Source";
}

View file

@ -1,69 +0,0 @@
<?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\Buffer;
/**
* Class Dow
*
* Apparently the player response is incomplete as there is no information being returned for that packet
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Dow extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'dow';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Days of War";
/**
* Normalize main fields
*
* @var array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'G_s',
'hostname' => 'ONM_s',
'mapname' => 'MPN_s',
'maxplayers' => 'P_i',
'numplayers' => 'N_i',
],
// Individual
'player' => [
'name' => 'name',
'score' => 'score',
'time' => 'time',
],
];
}

View file

@ -1,123 +0,0 @@
<?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

@ -1,51 +0,0 @@
<?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 Empyrion - Galactic Survival
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
* @author TacTicToe66 <https://github.com/TacTicToe66>
*/
class EgS extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'egs';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Empyrion - Galactic Survival";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
}

View file

@ -1,43 +0,0 @@
<?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;
/**
* Wolfenstein Enemy Territory Protocol Class
*
* @package GameQ\Protocols
*
* @author Wilson Jesus <>
*/
class Et extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'et';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Wolfenstein Enemy Territory";
}

View file

@ -1,234 +0,0 @@
<?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\Buffer;
use GameQ\Exception\Protocol as Exception;
use GameQ\Protocol;
use GameQ\Result;
/**
* Enemy Territory Quake Wars Protocol Class
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Etqw extends Protocol
{
/**
* 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_STATUS => "\xFF\xFFgetInfoEx\x00\x00\x00\x00",
//self::PACKET_STATUS => "\xFF\xFFgetInfo\x00\x00\x00\x00\x00",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\xFF\xFFinfoExResponse" => "processStatus",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'etqw';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'etqw';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Enemy Territory Quake Wars";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'campaign',
'hostname' => 'name',
'mapname' => 'map',
'maxplayers' => 'maxPlayers',
'mod' => 'gamename',
'numplayers' => 'numplayers',
'password' => 'privateClients',
],
// Individual
'player' => [
'name' => 'name',
'score' => 'score',
'time' => 'time',
],
];
/**
* Process the response
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// In case it comes back as multiple packets (it shouldn't)
$buffer = new Buffer(implode('', $this->packets_response));
// Figure out what packet response this is for
$response_type = $buffer->readString();
// Figure out which packet response this is
if (!array_key_exists($response_type, $this->responses)) {
throw new Exception(__METHOD__ . " response type '{$response_type}' is not valid");
}
// Offload the call
$results = call_user_func_array([$this, $this->responses[$response_type]], [$buffer]);
return $results;
}
/*
* Internal methods
*/
/**
* Handle processing the status response
*
* @param Buffer $buffer
*
* @return array
*/
protected function processStatus(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Defaults
$result->add('dedicated', 1);
// Now burn the challenge, version and size
$buffer->skip(16);
// Key / value pairs
while ($buffer->getLength()) {
$var = str_replace('si_', '', $buffer->readString());
$val = $buffer->readString();
if (empty($var) && empty($val)) {
break;
}
// Add the server prop
$result->add($var, $val);
}
// Now let's do the basic player info
$this->parsePlayers($buffer, $result);
// Now grab the rest of the server info
$result->add('osmask', $buffer->readInt32());
$result->add('ranked', $buffer->readInt8());
$result->add('timeleft', $buffer->readInt32());
$result->add('gamestate', $buffer->readInt8());
$result->add('servertype', $buffer->readInt8());
// 0: regular server
if ($result->get('servertype') == 0) {
$result->add('interested_clients', $buffer->readInt8());
} else {
// 1: tv server
$result->add('connected_clients', $buffer->readInt32());
$result->add('max_clients', $buffer->readInt32());
}
// Now let's parse the extended player info
$this->parsePlayersExtra($buffer, $result);
unset($buffer);
return $result->fetch();
}
/**
* Parse players out of the status ex response
*
* @param Buffer $buffer
* @param Result $result
*/
protected function parsePlayers(Buffer &$buffer, Result &$result)
{
// By default there are 0 players
$players = 0;
// Iterate over the players until we run out
while (($id = $buffer->readInt8()) != 32) {
$result->addPlayer('id', $id);
$result->addPlayer('ping', $buffer->readInt16());
$result->addPlayer('name', $buffer->readString());
$result->addPlayer('clantag_pos', $buffer->readInt8());
$result->addPlayer('clantag', $buffer->readString());
$result->addPlayer('bot', $buffer->readInt8());
$players++;
}
// Let's add in the current players as a result
$result->add('numplayers', $players);
// Free some memory
unset($id);
}
/**
* Handle parsing extra player data
*
* @param Buffer $buffer
* @param Result $result
*/
protected function parsePlayersExtra(Buffer &$buffer, Result &$result)
{
// Iterate over the extra player info
while (($id = $buffer->readInt8()) != 32) {
$result->addPlayer('total_xp', $buffer->readFloat32());
$result->addPlayer('teamname', $buffer->readString());
$result->addPlayer('total_kills', $buffer->readInt32());
$result->addPlayer('total_deaths', $buffer->readInt32());
}
// @todo: Add team stuff
// Free some memory
unset($id);
}
}

View file

@ -1,43 +0,0 @@
<?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 Ffe - Fortress Forever
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Ffe extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'ffe';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Fortress Forever";
}

View file

@ -1,243 +0,0 @@
<?php
namespace GameQ\Protocols;
use GameQ\Protocol;
use GameQ\Buffer;
use GameQ\Result;
use GameQ\Exception\Protocol as Exception;
/**
* Frontlines Fuel of War Protocol Class
*
* Handles processing ffow servers
*
* Class is incomplete due to lack of players to test against.
* http://wiki.hlsw.net/index.php/FFOW_Protocol
*
* @package GameQ\Protocols
*/
class Ffow extends Protocol
{
/**
* 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_CHALLENGE => "\xFF\xFF\xFF\xFF\x57",
self::PACKET_RULES => "\xFF\xFF\xFF\xFF\x56%s",
self::PACKET_PLAYERS => "\xFF\xFF\xFF\xFF\x55%s",
self::PACKET_INFO => "\xFF\xFF\xFF\xFF\x46\x4C\x53\x51",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\xFF\xFF\xFF\xFF\x49\x02" => 'processInfo', // I
"\xFF\xFF\xFF\xFF\x45\x00" => 'processRules', // E
"\xFF\xFF\xFF\xFF\x44\x00" => 'processPlayers', // D
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'ffow';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'ffow';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Frontlines Fuel of War";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* query_port = client_port + 2
*
* @type int
*/
protected $port_diff = 2;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'gamemode',
'hostname' => 'servername',
'mapname' => 'mapname',
'maxplayers' => 'max_players',
'mod' => 'modname',
'numplayers' => 'num_players',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
'ping' => 'ping',
'score' => 'frags',
],
];
/**
* Parse the challenge response and apply it to all the packet types
*
* @param \GameQ\Buffer $challenge_buffer
*
* @return bool
* @throws \GameQ\Exception\Protocol
*/
public function challengeParseAndApply(Buffer $challenge_buffer)
{
// Burn padding
$challenge_buffer->skip(5);
// Apply the challenge and return
return $this->challengeApply($challenge_buffer->read(4));
}
/**
* Handle response from the server
*
* @return mixed
* @throws Exception
*/
public function processResponse()
{
// Init results
$results = [];
foreach ($this->packets_response as $response) {
$buffer = new Buffer($response);
// Figure out what packet response this is for
$response_type = $buffer->read(6);
// Figure out which packet response this is
if (!array_key_exists($response_type, $this->responses)) {
throw new Exception(__METHOD__ . " response type '" . bin2hex($response_type) . "' is not valid");
}
// Now we need to call the proper method
$results = array_merge(
$results,
call_user_func_array([$this, $this->responses[$response_type]], [$buffer])
);
unset($buffer);
}
return $results;
}
/**
* Handle processing the server information
*
* @param Buffer $buffer
*
* @return array
*/
protected function processInfo(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
$result->add('servername', $buffer->readString());
$result->add('mapname', $buffer->readString());
$result->add('modname', $buffer->readString());
$result->add('gamemode', $buffer->readString());
$result->add('description', $buffer->readString());
$result->add('version', $buffer->readString());
$result->add('port', $buffer->readInt16());
$result->add('num_players', $buffer->readInt8());
$result->add('max_players', $buffer->readInt8());
$result->add('dedicated', $buffer->readInt8());
$result->add('os', $buffer->readInt8());
$result->add('password', $buffer->readInt8());
$result->add('anticheat', $buffer->readInt8());
$result->add('average_fps', $buffer->readInt8());
$result->add('round', $buffer->readInt8());
$result->add('max_rounds', $buffer->readInt8());
$result->add('time_left', $buffer->readInt16());
unset($buffer);
return $result->fetch();
}
/**
* Handle processing the server rules
*
* @param Buffer $buffer
*
* @return array
*/
protected function processRules(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Burn extra header
$buffer->skip(1);
// Read rules until we run out of buffer
while ($buffer->getLength()) {
$key = $buffer->readString();
// Check for map
if (strstr($key, "Map:")) {
$result->addSub("maplist", "name", $buffer->readString());
} else // Regular rule
{
$result->add($key, $buffer->readString());
}
}
unset($buffer);
return $result->fetch();
}
/**
* Handle processing of player data
*
* @todo: Build this out when there is a server with players to test against
*
* @param Buffer $buffer
*
* @return array
*/
protected function processPlayers(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
unset($buffer);
return $result->fetch();
}
}

View file

@ -1,181 +0,0 @@
<?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;
/**
* GameSpy Protocol class
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Gamespy extends Protocol
{
/**
* 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_STATUS => "\x5C\x73\x74\x61\x74\x75\x73\x5C",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'gamespy';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'gamespy';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "GameSpy Server";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* Process the response for this protocol
*
* @return array
* @throws Exception
*/
public function processResponse()
{
// Holds the processed packets so we can sort them in case they come in an unordered
$processed = [];
// Iterate over the packets
foreach ($this->packets_response as $response) {
// Check to see if we had a preg_match error
if (($match = preg_match("#^(.*)\\\\queryid\\\\([^\\\\]+)(\\\\|$)#", $response, $matches)) === false
|| $match != 1
) {
throw new Exception(__METHOD__ . " An error occurred while parsing the packets for 'queryid'");
}
// Multiply so we move the decimal point out of the way, if there is one
$key = (int)(floatval($matches[2]) * 1000);
// Add this packet to the processed
$processed[$key] = $matches[1];
}
// Sort the new array to make sure the keys (query ids) are in the proper order
ksort($processed, SORT_NUMERIC);
// Create buffer and offload processing
return $this->processStatus(new Buffer(implode('', $processed)));
}
/*
* Internal methods
*/
/**
* Handle processing the status buffer
*
* @param Buffer $buffer
*
* @return array
*/
protected function processStatus(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// By default dedicted
$result->add('dedicated', 1);
// Lets peek and see if the data starts with a \
if ($buffer->lookAhead(1) == '\\') {
// Burn the first one
$buffer->skip(1);
}
// Explode the data
$data = explode('\\', $buffer->getBuffer());
// No longer needed
unset($buffer);
// Init some vars
$numPlayers = 0;
$numTeams = 0;
$itemCount = count($data);
// 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];
$val = $data[$x + 1];
// Check for <variable>_<count> variable (i.e players)
if (($suffix = strrpos($key, '_')) !== false && is_numeric(substr($key, $suffix + 1))) {
// See if this is a team designation
if (substr($key, 0, $suffix) == 'teamname') {
$result->addTeam('teamname', $val);
$numTeams++;
} else {
// Its a player
if (substr($key, 0, $suffix) == 'playername') {
$numPlayers++;
}
$result->addPlayer(substr($key, 0, $suffix), utf8_encode($val));
}
} else {
// Regular variable so just add the value.
$result->add($key, $val);
}
}
}
// Add the player and team count
$result->add('num_players', $numPlayers);
$result->add('num_teams', $numTeams);
// Unset some stuff to free up memory
unset($data, $key, $val, $suffix, $x, $itemCount);
// Return the result
return $result->fetch();
}
}

View file

@ -1,269 +0,0 @@
<?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

@ -1,340 +0,0 @@
<?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;
/**
* GameSpy3 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 Gamespy3 extends Protocol
{
/**
* 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_CHALLENGE => "\xFE\xFD\x09\x10\x20\x30\x40",
self::PACKET_ALL => "\xFE\xFD\x00\x10\x20\x30\x40%s\xFF\xFF\xFF\x01",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'gamespy3';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'gamespy3';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "GameSpy3 Server";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* This defines the split between the server info and player/team info.
* This value can vary by game. This value is the default split.
*
* @var string
*/
protected $packetSplit = "/\\x00\\x00\\x01/m";
/**
* Parse the challenge response and apply it to all the packet types
*
* @param \GameQ\Buffer $challenge_buffer
*
* @return bool
* @throws \GameQ\Exception\Protocol
*/
public function challengeParseAndApply(Buffer $challenge_buffer)
{
// Pull out the challenge
$challenge = substr(preg_replace("/[^0-9\-]/si", "", $challenge_buffer->getBuffer()), 1);
// By default, no challenge result (see #197)
$challenge_result = '';
// Check for valid challenge (see #197)
if ($challenge) {
// Encode chellenge result
$challenge_result = sprintf(
"%c%c%c%c",
($challenge >> 24),
($challenge >> 16),
($challenge >> 8),
($challenge >> 0)
);
}
// Apply the challenge and return
return $this->challengeApply($challenge_result);
}
/**
* Process the response
*
* @return array
*/
public function processResponse()
{
// Holds the processed packets
$processed = [];
// Iterate over the packets
foreach ($this->packets_response as $response) {
// Make a buffer
$buffer = new Buffer($response, Buffer::NUMBER_TYPE_BIGENDIAN);
// Packet type = 0
$buffer->readInt8();
// Session Id
$buffer->readInt32();
// We need to burn the splitnum\0 because it is not used
$buffer->skip(9);
// Get the id
$id = $buffer->readInt8();
// Burn next byte not sure what it is used for
$buffer->skip(1);
// Add this packet to the processed
$processed[$id] = $buffer->getBuffer();
unset($buffer, $id);
}
// Sort packets, reset index
ksort($processed);
// Offload cleaning up the packets if they happen to be split
$packets = $this->cleanPackets(array_values($processed));
// Split the packets by type general and the rest (i.e. players & teams)
$split = preg_split($this->packetSplit, implode('', $packets));
// Create a new result
$result = new Result();
// Assign variable due to pass by reference in PHP 7+
$buffer = new Buffer($split[0], Buffer::NUMBER_TYPE_BIGENDIAN);
// First key should be server details and rules
$this->processDetails($buffer, $result);
// The rest should be the player and team information, if it exists
if (array_key_exists(1, $split)) {
$buffer = new Buffer($split[1], Buffer::NUMBER_TYPE_BIGENDIAN);
$this->processPlayersAndTeams($buffer, $result);
}
unset($buffer);
return $result->fetch();
}
/*
* Internal methods
*/
/**
* Handles cleaning up packets since the responses can be a bit "dirty"
*
* @param array $packets
*
* @return array
*/
protected function cleanPackets(array $packets = [])
{
// Get the number of packets
$packetCount = count($packets);
// 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 = $packetCount; $i < $x - 1; $i++) {
// First packet
$fst = substr($packets[$i], 0, -1);
// Second packet
$snd = $packets[$i + 1];
// Get last variable from first packet
$fstvar = substr($fst, strrpos($fst, "\x00") + 1);
// Get first variable from last packet
$snd = substr($snd, strpos($snd, "\x00") + 2);
$sndvar = substr($snd, 0, strpos($snd, "\x00"));
// Check if fstvar is a substring of sndvar
// If so, remove it from the first string
if (!empty($fstvar) && strpos($sndvar, $fstvar) !== false) {
$packets[$i] = preg_replace("#(\\x00[^\\x00]+\\x00)$#", "\x00", $packets[$i]);
}
}
// Now let's loop the return and remove any dupe prefixes
for ($x = 1; $x < $packetCount; $x++) {
$buffer = new Buffer($packets[$x], Buffer::NUMBER_TYPE_BIGENDIAN);
$prefix = $buffer->readString();
// Check to see if the return before has the same prefix present
if ($prefix != null && strstr($packets[($x - 1)], $prefix)) {
// Update the return by removing the prefix plus 2 chars
$packets[$x] = substr(str_replace($prefix, '', $packets[$x]), 2);
}
unset($buffer);
}
unset($x, $i, $snd, $sndvar, $fst, $fstvar);
// Return cleaned packets
return $packets;
}
/**
* Handles processing the details data into a usable format
*
* @param \GameQ\Buffer $buffer
* @param \GameQ\Result $result
*/
protected function processDetails(Buffer &$buffer, Result &$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()));
}
}
/**
* 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("\x00\x00", $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 = '';
// 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 - 1; $x++) {
// Pull out the item
$item = $data[$x];
// If this is an empty item, move on
if ($item == '' || $item == "\x00") {
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("\x01", '', $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(["\x00", "\x02"], '', $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($count, $data, $item, $item_group, $item_type, $val);
}
}

View file

@ -1,34 +0,0 @@
<?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;
/**
* GameSpy4 Protocol Class
*
* By all accounts GameSpy 4 seems to be GameSpy 3.
*
* References:
* http://www.deletedscreen.com/?p=951
* http://pastebin.com/2zZFDuTd
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Gamespy4 extends Gamespy3
{
}

View file

@ -1,42 +0,0 @@
<?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 Gmod
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Gmod extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'gmod';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Garry's Mod";
}

View file

@ -1,42 +0,0 @@
<?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;
/**
* Grav Online Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Grav extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'grav';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "GRAV Online";
}

View file

@ -1,173 +0,0 @@
<?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\Buffer;
use GameQ\Exception\Protocol as Exception;
use GameQ\Protocol;
use GameQ\Result;
/**
* GTA Five M Protocol Class
*
* Server base can be found at https://fivem.net/
*
* Based on code found at https://github.com/LiquidObsidian/fivereborn-query
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Gta5m extends Protocol
{
/**
* 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_STATUS => "\xFF\xFF\xFF\xFFgetinfo xxx",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\xFF\xFF\xFF\xFFinfoResponse" => "processStatus",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'gta5m';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'gta5m';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "GTA Five M";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'gametype',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'sv_maxclients',
'mod' => 'gamename',
'numplayers' => 'clients',
'password' => 'privateClients',
],
];
/**
* Process the response
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// In case it comes back as multiple packets (it shouldn't)
$buffer = new Buffer(implode('', $this->packets_response));
// Figure out what packet response this is for
$response_type = $buffer->readString(PHP_EOL);
// Figure out which packet response this is
if (empty($response_type) || !array_key_exists($response_type, $this->responses)) {
throw new Exception(__METHOD__ . " response type '{$response_type}' is not valid");
}
// Offload the call
$results = call_user_func_array([$this, $this->responses[$response_type]], [$buffer]);
return $results;
}
/*
* Internal methods
*/
/**
* Handle processing the status response
*
* @param Buffer $buffer
*
* @return array
*/
protected function processStatus(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Lets peek and see if the data starts with a \
if ($buffer->lookAhead(1) == '\\') {
// Burn the first one
$buffer->skip(1);
}
// Explode the data
$data = explode('\\', $buffer->getBuffer());
// No longer needed
unset($buffer);
$itemCount = count($data);
// Now lets loop the array
for ($x = 0; $x < $itemCount; $x += 2) {
// Set some local vars
$key = $data[$x];
$val = $data[$x + 1];
if (in_array($key, ['challenge'])) {
continue; // skip
}
// Regular variable so just add the value.
$result->add($key, $val);
}
/*var_dump($data);
var_dump($result->fetch());
exit;*/
return $result->fetch();
}
}

View file

@ -1,163 +0,0 @@
<?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 Network Protocol Class
* https://stats.gtanet.work/
*
* Result from this call should be a header + JSON response
*
* References:
* - https://master.gtanet.work/apiservers
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Gtan extends Http
{
/**
* Packets to send
*
* @var array
*/
protected $packets = [
//self::PACKET_STATUS => "GET /apiservers HTTP/1.0\r\nHost: master.gtanet.work\r\nAccept: */*\r\n\r\n",
self::PACKET_STATUS => "GET /gtan/api.php?ip=%s&raw HTTP/1.0\r\nHost: multiplayerhosting.info\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 = 'gtan';
/**
* String name of this protocol class
*
* @var string
*/
protected $name = 'gtan';
/**
* Longer string name of this protocol class
*
* @var string
*/
protected $name_long = "Grand Theft Auto Network";
/**
* 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',
'mapname' => 'map',
'mod' => 'mod',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
'password' => 'password',
],
];
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 = 'master.gtanet.work';
$server->ip = 'multiplayerhosting.info';
$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 Gtan protocol is invalid.");
}
$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', $json->ServerName);
$result->add('serverversion', $json->ServerVersion);
$result->add('map', ((!empty($json->Map)) ? $json->Map : 'Los Santos/Blaine Country'));
$result->add('mod', $json->Gamemode);
$result->add('password', (int)$json->Passworded);
$result->add('numplayers', $json->CurrentPlayers);
$result->add('maxplayers', $json->MaxPlayers);
return $result->fetch();
}
}

View file

@ -1,42 +0,0 @@
<?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 Hl2dm
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Hl2dm extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'hl2dm';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Half Life 2: Deathmatch";
}

View file

@ -1,42 +0,0 @@
<?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 L4d2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Homefront extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'homefront';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Homefront";
}

View file

@ -1,67 +0,0 @@
<?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;
/**
* Class Http
*
* Generic HTTP protocol class. Useful for making http based requests
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
abstract class Http extends Protocol
{
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'http';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'http';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Generic HTTP protocol";
/**
* Http protocol is TCP
*
* @var string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
}

View file

@ -1,42 +0,0 @@
<?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 Hurtworld
*
* @package GameQ\Protocols
* @author Nikolay Ipanyuk <rostov114@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Hurtworld extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'hurtworld';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Hurtworld";
}

View file

@ -1,42 +0,0 @@
<?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 Insurgency
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Insurgency extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'insurgency';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Insurgency";
}

View file

@ -1,49 +0,0 @@
<?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

@ -1,42 +0,0 @@
<?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;
/**
* Jedi Academy Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Jediacademy extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'jediacademy';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Star Wars Jedi Knight: Jedi Academy";
}

View file

@ -1,42 +0,0 @@
<?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;
/**
* Jedi Outcast Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Jedioutcast extends Quake3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'jedioutcast';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Star Wars Jedi Knight II: Jedi Outcast";
}

View file

@ -1,127 +0,0 @@
<?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\Buffer;
use GameQ\Result;
/**
* Just Cause 2 Multiplayer Protocol Class
*
* Special thanks to Woet for some insight on packing
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Justcause2 extends Gamespy4
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'justcause2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Just Cause 2 Multiplayer";
/**
* The client join link
*
* @type string
*/
protected $join_link = "steam://connect/%s:%d/";
/**
* Change the packets used
*
* @var array
*/
protected $packets = [
self::PACKET_CHALLENGE => "\xFE\xFD\x09\x10\x20\x30\x40",
self::PACKET_ALL => "\xFE\xFD\x00\x10\x20\x30\x40%s\xFF\xFF\xFF\x02",
];
/**
* Override the packet split
*
* @var string
*/
protected $packetSplit = "/\\x00\\x00\\x00/m";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'gametype',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
'ping' => 'ping',
],
];
/**
* Overload so we can add in some static data points
*
* @param Buffer $buffer
* @param Result $result
*/
protected function processDetails(Buffer &$buffer, Result &$result)
{
parent::processDetails($buffer, $result);
// Add in map
$result->add('mapname', 'Panau');
$result->add('dedicated', 'true');
}
/**
* Override the parent, this protocol is returned differently
*
* @param Buffer $buffer
* @param Result $result
*
* @see Gamespy3::processPlayersAndTeams()
*/
protected function processPlayersAndTeams(Buffer &$buffer, Result &$result)
{
// Loop until we run out of data
while ($buffer->getLength()) {
$result->addPlayer('name', $buffer->readString());
$result->addPlayer('steamid', $buffer->readString());
$result->addPlayer('ping', $buffer->readInt16());
}
}
}

View file

@ -1,50 +0,0 @@
<?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 Just Cause 3
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Justcause3 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'justcause3';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Just Cause 3";
/**
* Query port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
}

View file

@ -1,96 +0,0 @@
<?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\Buffer;
use GameQ\Result;
/**
* Class Killing floor
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Killingfloor extends Unreal2
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'killing floor';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Killing Floor";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
/**
* The client join link
*
* @type string
*/
protected $join_link = "steam://connect/%s:%d/";
/**
* 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();
}
}

View file

@ -1,51 +0,0 @@
<?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 Killing floor
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Killingfloor2 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'killing floor 2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Killing Floor 2";
/**
* query_port = client_port + 19238
* 27015 = 7777 + 19238
*
* @type int
*/
protected $port_diff = 19238;
}

View file

@ -1,42 +0,0 @@
<?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 L4d
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class L4d extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'l4d';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Left 4 Dead";
}

View file

@ -1,42 +0,0 @@
<?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 L4d2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class L4d2 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'l4d2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Left 4 Dead 2";
}

View file

@ -1,214 +0,0 @@
<?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;
/**
* Lost Heaven Protocol class
*
* Reference: http://lh-mp.eu/wiki/index.php/Query_System
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Lhmp extends Protocol
{
/**
* 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 => "LHMPo",
self::PACKET_PLAYERS => "LHMPp",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"LHMPo" => "processDetails",
"LHMPp" => "processPlayers",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'lhmp';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'lhmp';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Lost Heaven";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'gamemode',
'hostname' => 'servername',
'mapname' => 'mapname',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
],
];
/**
* Process the response
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
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 '{$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 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();
}
/**
* Handles processing the player data into a usable format
*
* @param Buffer $buffer
*
* @return array
*/
protected function processPlayers(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Get the number of players
$result->add('numplayers', $buffer->readInt16());
// Parse players
while ($buffer->getLength()) {
// Player id
if (($id = $buffer->readInt16()) !== 0) {
// Add the results
$result->addPlayer('id', $id);
$result->addPlayer('name', utf8_encode($buffer->readPascalString()));
}
}
unset($buffer, $id);
return $result->fetch();
}
}

View file

@ -1,87 +0,0 @@
<?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;
/**
* Minecraft Protocol Class
*
* Thanks to https://github.com/xPaw/PHP-Minecraft-Query for helping me realize this is
* Gamespy 3 Protocol. Make sure you enable the items below for it to work.
*
* Information from original author:
* Instructions
*
* Before using this class, you need to make sure that your server is running GS4 status listener.
*
* Look for those settings in server.properties:
*
* enable-query=true
* query.port=25565
*
* @package GameQ\Protocols
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Minecraft extends Gamespy3
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'minecraft';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Minecraft";
/**
* The client join link
*
* @type string
*/
protected $join_link = "minecraft://%s:%d/";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'game_id',
'hostname' => 'hostname',
'mapname' => 'map',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'player',
],
];
}

View file

@ -1,44 +0,0 @@
<?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;
/**
* Minecraft PE (BE) Protocol Class
*
* @package GameQ\Protocols
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Minecraftpe extends Minecraft
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'minecraftpe';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "MinecraftPE";
}

View file

@ -1,79 +0,0 @@
<?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;
/**
* Medal of honor: Allied Assault Protocol Class
*
* @package GameQ\Protocols
* @author Bram <https://github.com/Stormyy>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Mohaa extends Gamespy
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'mohaa';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Medal of honor: Allied Assault";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'gametype',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'maxplayers',
'numplayers' => 'numplayers',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'player',
'score' => 'frags',
'ping' => 'ping',
],
];
/**
* Query port is always the client port + 97 in MOHAA
*
* @param int $clientPort
*
* @return int
*/
public function findQueryPort($clientPort)
{
return $clientPort + 97;
}
}

View file

@ -1,53 +0,0 @@
<?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 MORDHAU
*
* @package GameQ\Protocols
* @author Wilson Jesus <>
*/
class Mordhau extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'mordhau';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "MORDHAU";
#protected $port = 7777;
/**
* query_port = client_port + 19238
* 27015 = 7777 + 19238
*
* @type int
*/
#protected $port_diff = 19238;
}

View file

@ -1,59 +0,0 @@
<?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 Multi Theft Auto
*
* @package GameQ\Protocols
*
* @author Marcel Bößendörfer <m.boessendoerfer@marbis.net>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Mta extends Ase
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'mta';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Multi Theft Auto";
/**
* query_port = client_port + 123
*
* @type int
*/
protected $port_diff = 123;
/**
* The client join link
*
* @type string
*/
protected $join_link = "mtasa://%s:%d/";
}

View file

@ -1,194 +0,0 @@
<?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\Result;
use GameQ\Exception\Protocol as Exception;
/**
* Mumble Protocol class
*
* References:
* https://github.com/edmundask/MurmurQuery - Thanks to skylord123
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Mumble extends Protocol
{
/**
* 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_ALL => "\x6A\x73\x6F\x6E", // JSON packet
];
/**
* The transport mode for this protocol is TCP
*
* @type string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'mumble';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'mumble';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Mumble Server";
/**
* The client join link
*
* @type string
*/
protected $join_link = "mumble://%s:%d/";
/**
* 27800 = 64738 - 36938
*
* @type int
*/
protected $port_diff = -36938;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
'dedicated' => 'dedicated',
'gametype' => 'gametype',
'hostname' => 'name',
'numplayers' => 'numplayers',
'maxplayers' => 'x_gtmurmur_max_users',
],
// Player
'player' => [
'name' => 'name',
'ping' => 'tcpPing',
'team' => 'channel',
'time' => 'onlinesecs',
],
// Team
'team' => [
'name' => 'name',
],
];
/**
* Process the response
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// Try to json_decode, make it into an array
if (($data = json_decode(implode('', $this->packets_response), true)) === null) {
throw new Exception(__METHOD__ . " Unable to decode JSON data.");
}
// Set the result to a new result instance
$result = new Result();
// Always dedicated
$result->add('dedicated', 1);
// Let's iterate over the response items, there are a lot
foreach ($data as $key => $value) {
// Ignore root for now, that is where all of the channel/player info is housed
if (in_array($key, ['root'])) {
continue;
}
// Add them as is
$result->add($key, $value);
}
// Offload the channel and user parsing
$this->processChannelsAndUsers($data['root'], $result);
unset($data);
// Manually set the number of players
$result->add('numplayers', count($result->get('players')));
return $result->fetch();
}
/*
* Internal methods
*/
/**
* Handles processing the the channels and user info
*
* @param array $data
* @param \GameQ\Result $result
*/
protected function processChannelsAndUsers(array $data, Result &$result)
{
// Let's add all of the channel information
foreach ($data as $key => $value) {
// We will handle these later
if (in_array($key, ['channels', 'users'])) {
// skip
continue;
}
// Add the channel property as a team
$result->addTeam($key, $value);
}
// Itereate over the users in this channel
foreach ($data['users'] as $user) {
foreach ($user as $key => $value) {
$result->addPlayer($key, $value);
}
}
// Offload more channels to parse
foreach ($data['channels'] as $channel) {
$this->processChannelsAndUsers($channel, $result);
}
}
}

View file

@ -1,49 +0,0 @@
<?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 Ns2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Ns2 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'ns2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Natural Selection 2";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
}

View file

@ -1,43 +0,0 @@
<?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 PixARK
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Pixark extends Arkse
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'pixark';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "PixARK";
}

View file

@ -1,45 +0,0 @@
<?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 Projectrealitybf2
*
* Based off of BF2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Projectrealitybf2 extends Bf2
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'projectrealitybf2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Project Reality: Battlefield 2";
}

View file

@ -1,219 +0,0 @@
<?php
namespace GameQ\Protocols;
use GameQ\Protocol;
use GameQ\Buffer;
use GameQ\Result;
use GameQ\Exception\Protocol as Exception;
/**
* Quake2 Protocol Class
*
* Handles processing Quake 3 servers
*
* @package GameQ\Protocols
*/
class Quake2 extends Protocol
{
/**
* 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_STATUS => "\xFF\xFF\xFF\xFFstatus\x00",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\xFF\xFF\xFF\xFF\x70\x72\x69\x6e\x74" => 'processStatus',
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'quake2';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'quake2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Quake 2 Server";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'gamename',
'hostname' => 'hostname',
'mapname' => 'mapname',
'maxplayers' => 'maxclients',
'mod' => 'g_gametype',
'numplayers' => 'clients',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
'ping' => 'ping',
'score' => 'frags',
],
];
/**
* Handle response from the server
*
* @return mixed
* @throws Exception
*/
public function processResponse()
{
// Make a buffer
$buffer = new Buffer(implode('', $this->packets_response));
// Grab the header
$header = $buffer->readString("\x0A");
// Figure out which packet response this is
if (empty($header) || !array_key_exists($header, $this->responses)) {
throw new Exception(__METHOD__ . " response type '" . bin2hex($header) . "' is not valid");
}
return call_user_func_array([$this, $this->responses[$header]], [$buffer]);
}
/**
* Process the status response
*
* @param Buffer $buffer
*
* @return array
*/
protected function processStatus(Buffer $buffer)
{
// We need to split the data and offload
$results = $this->processServerInfo(new Buffer($buffer->readString("\x0A")));
$results = array_merge_recursive(
$results,
$this->processPlayers(new Buffer($buffer->getBuffer()))
);
unset($buffer);
// Return results
return $results;
}
/**
* Handle processing the server information
*
* @param Buffer $buffer
*
* @return array
*/
protected function processServerInfo(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Burn leading \ if one exists
$buffer->readString('\\');
// Key / value pairs
while ($buffer->getLength()) {
// Add result
$result->add(
trim($buffer->readString('\\')),
utf8_encode(trim($buffer->readStringMulti(['\\', "\x0a"])))
);
}
$result->add('password', 0);
$result->add('mod', 0);
unset($buffer);
return $result->fetch();
}
/**
* Handle processing of player data
*
* @param Buffer $buffer
*
* @return array
*/
protected function processPlayers(Buffer $buffer)
{
// Some games do not have a number of current players
$playerCount = 0;
// 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("\x0A"));
// Add player info
$result->addPlayer('frags', $playerInfo->readString("\x20"));
$result->addPlayer('ping', $playerInfo->readString("\x20"));
// Skip first "
$playerInfo->skip(1);
// Add player name, encoded
$result->addPlayer('name', utf8_encode(trim(($playerInfo->readString('"')))));
// Skip first "
$playerInfo->skip(2);
// Add address
$result->addPlayer('address', trim($playerInfo->readString('"')));
// Increment
$playerCount++;
// Clear
unset($playerInfo);
}
$result->add('clients', $playerCount);
// Clear
unset($buffer, $playerCount);
return $result->fetch();
}
}

View file

@ -1,214 +0,0 @@
<?php
namespace GameQ\Protocols;
use GameQ\Protocol;
use GameQ\Buffer;
use GameQ\Result;
use GameQ\Exception\Protocol as Exception;
/**
* Quake3 Protocol Class
*
* Handles processing Quake 3 servers
*
* @package GameQ\Protocols
*/
class Quake3 extends Protocol
{
/**
* 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_STATUS => "\xFF\xFF\xFF\xFF\x67\x65\x74\x73\x74\x61\x74\x75\x73\x0A",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\xFF\xFF\xFF\xFFstatusResponse" => 'processStatus',
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'quake3';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'quake3';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Quake 3 Server";
/**
* The client join link
*
* @type string
*/
protected $join_link = null;
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'gametype' => 'gamename',
'hostname' => 'sv_hostname',
'mapname' => 'mapname',
'maxplayers' => 'sv_maxclients',
'mod' => 'g_gametype',
'numplayers' => 'clients',
'password' => ['g_needpass', 'pswrd'],
],
// Individual
'player' => [
'name' => 'name',
'ping' => 'ping',
'score' => 'frags',
],
];
/**
* Handle response from the server
*
* @return mixed
* @throws Exception
*/
public function processResponse()
{
// Make a buffer
$buffer = new Buffer(implode('', $this->packets_response));
// Grab the header
$header = $buffer->readString("\x0A");
// Figure out which packet response this is
if (empty($header) || !array_key_exists($header, $this->responses)) {
throw new Exception(__METHOD__ . " response type '" . bin2hex($header) . "' is not valid");
}
return call_user_func_array([$this, $this->responses[$header]], [$buffer]);
}
protected function processStatus(Buffer $buffer)
{
// We need to split the data and offload
$results = $this->processServerInfo(new Buffer($buffer->readString("\x0A")));
$results = array_merge_recursive(
$results,
$this->processPlayers(new Buffer($buffer->getBuffer()))
);
unset($buffer);
// Return results
return $results;
}
/**
* Handle processing the server information
*
* @param Buffer $buffer
*
* @return array
*/
protected function processServerInfo(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Burn leading \ if one exists
$buffer->readString('\\');
// Key / value pairs
while ($buffer->getLength()) {
// Add result
$result->add(
trim($buffer->readString('\\')),
utf8_encode(trim($buffer->readStringMulti(['\\', "\x0a"])))
);
}
unset($buffer);
return $result->fetch();
}
/**
* Handle processing of player data
*
* @param Buffer $buffer
*
* @return array
* @throws Exception
*/
protected function processPlayers(Buffer $buffer)
{
// Some games do not have a number of current players
$playerCount = 0;
// Set the result to a new result instance
$result = new Result();
// Loop until we are out of data
while ($buffer->getLength()) {
// Add player info
$result->addPlayer('frags', $buffer->readString("\x20"));
$result->addPlayer('ping', $buffer->readString("\x20"));
// 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($buffer->readString('"'))));
// Burn ending delimiter
$buffer->read();
// Increment
$playerCount++;
}
$result->add('clients', $playerCount);
// Clear
unset($buffer, $playerCount);
return $result->fetch();
}
}

View file

@ -1,42 +0,0 @@
<?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 Quake Live
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Quakelive extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'quakelive';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Quake Live";
}

View file

@ -1,50 +0,0 @@
<?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 Redorchestra2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Redorchestra2 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'redorchestra2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Red Orchestra 2";
/**
* query_port = client_port + 19238
* 27015 = 7777 + 19238
*
* @type int
*/
protected $port_diff = 19238;
}

View file

@ -1,43 +0,0 @@
<?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

@ -1,55 +0,0 @@
<?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 Rising Storm 2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Risingstorm2 extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'rising storm 2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Rising Storm 2";
/**
* Query port is always 27015
*
* @param int $clientPort
*
* @return int
*/
public function findQueryPort($clientPort)
{
return 27015;
}
}

View file

@ -1,43 +0,0 @@
<?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 Rust
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Rust extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'rust';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Rust";
}

View file

@ -1,279 +0,0 @@
<?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\Server;
use GameQ\Exception\Protocol as Exception;
/**
* San Andreas Multiplayer Protocol Class (samp)
*
* Note:
* Player information will not be returned if player count is over 256
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Samp extends Protocol
{
/**
* 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_STATUS => "SAMP%si",
self::PACKET_PLAYERS => "SAMP%sd",
self::PACKET_RULES => "SAMP%sr",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\x69" => "processStatus", // i
"\x64" => "processPlayers", // d
"\x72" => "processRules", // r
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'samp';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'samp';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "San Andreas Multiplayer";
/**
* Holds the calculated server code that is passed when querying for information
*
* @type string
*/
protected $server_code = null;
/**
* The client join link
*
* @type string
*/
protected $join_link = "samp://%s:%d/";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'hostname' => ['hostname', 'servername'],
'mapname' => 'mapname',
'maxplayers' => 'max_players',
'numplayers' => 'num_players',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
'score' => 'score',
'ping' => 'ping',
],
];
/**
* Handle some work before sending the packets out to the server
*
* @param \GameQ\Server $server
*/
public function beforeSend(Server $server)
{
// Build the server code
$this->server_code = implode('', array_map('chr', explode('.', $server->ip()))) .
pack("S", $server->portClient());
// 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, $this->server_code);
}
}
/**
* Process the response
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// Results that will be returned
$results = [];
// Get the length of the server code so we can figure out how much to read later
$serverCodeLength = strlen($this->server_code);
// We need to pre-sort these for split packets so we can do extra work where needed
foreach ($this->packets_response as $response) {
// Make new buffer
$buffer = new Buffer($response);
// Check the header, should be SAMP
if (($header = $buffer->read(4)) !== 'SAMP') {
throw new Exception(__METHOD__ . " header response '{$header}' is not valid");
}
// Check to make sure the server response code matches what we sent
if ($buffer->read($serverCodeLength) !== $this->server_code) {
throw new Exception(__METHOD__ . " code check failed.");
}
// Figure out what packet response this is for
$response_type = $buffer->read(1);
// Figure out which packet response this is
if (!array_key_exists($response_type, $this->responses)) {
throw new Exception(__METHOD__ . " response type '{$response_type}' is not valid");
}
// Now we need to call the proper method
$results = array_merge(
$results,
call_user_func_array([$this, $this->responses[$response_type]], [$buffer])
);
unset($buffer);
}
return $results;
}
/*
* Internal methods
*/
/**
* Handles processing the server status data
*
* @param \GameQ\Buffer $buffer
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
protected function processStatus(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Always dedicated
$result->add('dedicated', 1);
// Pull out the server information
$result->add('password', $buffer->readInt8());
$result->add('num_players', $buffer->readInt16());
$result->add('max_players', $buffer->readInt16());
// These are read differently for these last 3
$result->add('servername', utf8_encode($buffer->read($buffer->readInt32())));
$result->add('gametype', $buffer->read($buffer->readInt32()));
$result->add('language', $buffer->read($buffer->readInt32()));
unset($buffer);
return $result->fetch();
}
/**
* Handles processing the player data into a usable format
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processPlayers(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Number of players
$result->add('num_players', $buffer->readInt16());
// Run until we run out of buffer
while ($buffer->getLength()) {
$result->addPlayer('id', $buffer->readInt8());
$result->addPlayer('name', utf8_encode($buffer->readPascalString()));
$result->addPlayer('score', $buffer->readInt32());
$result->addPlayer('ping', $buffer->readInt32());
}
unset($buffer);
return $result->fetch();
}
/**
* Handles processing the rules data into a usable format
*
* @param \GameQ\Buffer $buffer
*
* @return array
*/
protected function processRules(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Number of rules
$result->add('num_rules', $buffer->readInt16());
// Run until we run out of buffer
while ($buffer->getLength()) {
$result->add($buffer->readPascalString(), $buffer->readPascalString());
}
unset($buffer);
return $result->fetch();
}
}

View file

@ -1,75 +0,0 @@
<?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

@ -1,49 +0,0 @@
<?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 7 Days to Die
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Sevendaystodie extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'sevendaystodie';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "7 Days to Die";
/**
* query_port = client_port + 1
*
* @type int
*/
protected $port_diff = 1;
}

View file

@ -1,95 +0,0 @@
<?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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace GameQ\Protocols;
use GameQ\Buffer;
use GameQ\Result;
/**
* Class Ship
*
* @package GameQ\Protocols
*
* @author Nikolay Ipanyuk <rostov114@gmail.com>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Ship extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'ship';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "The Ship";
/**
* 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();
}
}

View file

@ -1,49 +0,0 @@
<?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

@ -1,59 +0,0 @@
<?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 Soldat
*
* @package GameQ\Protocols
*
* @author Marcel Bößendörfer <m.boessendoerfer@marbis.net>
* @author Austin Bischoff <austin@codebeard.com>
*/
class Soldat extends Ase
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'soldat';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Soldat";
/**
* query_port = client_port + 123
*
* @type int
*/
protected $port_diff = 123;
/**
* The client join link
*
* @type string
*/
protected $join_link = "soldat://%s:%d/";
}

View file

@ -1,522 +0,0 @@
<?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\Buffer;
use GameQ\Exception\Protocol as Exception;
use GameQ\Protocol;
use GameQ\Result;
/**
* Valve Source Engine Protocol Class (A2S)
*
* This class is used as the basis for all other source based servers
* that rely on the source protocol for game querying.
*
* @SuppressWarnings(PHPMD.NumberOfChildren)
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Source extends Protocol
{
/*
* Source engine type constants
*/
const SOURCE_ENGINE = 0,
GOLDSOURCE_ENGINE = 1;
/**
* 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_CHALLENGE => "\xFF\xFF\xFF\xFF\x56\x00\x00\x00\x00",
self::PACKET_DETAILS => "\xFF\xFF\xFF\xFFTSource Engine Query\x00",
self::PACKET_PLAYERS => "\xFF\xFF\xFF\xFF\x55%s",
self::PACKET_RULES => "\xFF\xFF\xFF\xFF\x56%s",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\x49" => "processDetails", // I
"\x6d" => "processDetailsGoldSource", // m, goldsource
"\x44" => "processPlayers", // D
"\x45" => "processRules", // E
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'source';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'source';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Source Server";
/**
* Define the Source engine type. By default it is assumed to be Source
*
* @type int
*/
protected $source_engine = self::SOURCE_ENGINE;
/**
* The client join link
*
* @type string
*/
protected $join_link = "steam://connect/%s:%d/";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'gametype' => 'game_descr',
'hostname' => 'hostname',
'mapname' => 'map',
'maxplayers' => 'max_players',
'mod' => 'game_dir',
'numplayers' => 'num_players',
'password' => 'password',
],
// Individual
'player' => [
'name' => 'name',
'score' => 'score',
'time' => 'time',
],
];
/**
* Parse the challenge response and apply it to all the packet types
*
* @param \GameQ\Buffer $challenge_buffer
*
* @return bool
* @throws \GameQ\Exception\Protocol
*/
public function challengeParseAndApply(Buffer $challenge_buffer)
{
// Skip the header
$challenge_buffer->skip(5);
// Apply the challenge and return
return $this->challengeApply($challenge_buffer->read(4));
}
/**
* Process the response
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// Will hold the results when complete
$results = [];
// Holds sorted response packets
$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);
// Get the header of packet (long)
$header = $buffer->readInt32Signed();
// Single packet
if ($header == -1) {
// We need to peek and see what kind of engine this is for later processing
if ($buffer->lookAhead(1) == "\x6d") {
$this->source_engine = self::GOLDSOURCE_ENGINE;
}
$packets[] = $buffer->getBuffer();
continue;
} else {
// Split packet
// Packet Id (long)
$packet_id = $buffer->readInt32Signed() + 10;
// Add the buffer to the packet as another array
$packets[$packet_id][] = $buffer->getBuffer();
}
}
// Free up memory
unset($response, $packet_id, $buffer, $header);
// Now that we have the packets sorted we need to iterate and process them
foreach ($packets as $packet_id => $packet) {
// We first need to off load split packets to combine them
if (is_array($packet)) {
$buffer = new Buffer($this->processPackets($packet_id, $packet));
} else {
$buffer = new Buffer($packet);
}
// Figure out what packet response this is for
$response_type = $buffer->read(1);
// Figure out which packet response this is
if (!array_key_exists($response_type, $this->responses)) {
throw new Exception(__METHOD__ . " response type '{$response_type}' is not valid");
}
// Now we need to call the proper method
$results = array_merge(
$results,
call_user_func_array([$this, $this->responses[$response_type]], [$buffer])
);
unset($buffer);
}
// Free up memory
unset($packets, $packet, $packet_id, $response_type);
return $results;
}
/*
* Internal methods
*/
/**
* Process the split packets and decompress if necessary
*
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*
* @param $packet_id
* @param array $packets
*
* @return string
* @throws \GameQ\Exception\Protocol
*/
protected function processPackets($packet_id, array $packets = [])
{
// Init array so we can order
$packs = [];
// We have multiple packets so we need to get them and order them
foreach ($packets as $i => $packet) {
// Make a buffer so we can read this info
$buffer = new Buffer($packet);
// Gold source
if ($this->source_engine == self::GOLDSOURCE_ENGINE) {
// Grab the packet number (byte)
$packet_number = $buffer->readInt8();
// We need to burn the extra header (\xFF\xFF\xFF\xFF) on first loop
if ($i == 0) {
$buffer->read(4);
}
// Now add the rest of the packet to the new array with the packet_number as the id so we can order it
$packs[$packet_number] = $buffer->getBuffer();
} else {
// Number of packets in this set (byte)
$buffer->readInt8();
// The current packet number (byte)
$packet_number = $buffer->readInt8();
// Check to see if this is compressed
// @todo: Check to make sure these decompress correctly, new changes may affect this loop.
if ($packet_id & 0x80000000) {
// Check to see if we have Bzip2 installed
if (!function_exists('bzdecompress')) {
// @codeCoverageIgnoreStart
throw new Exception(
'Bzip2 is not installed. See http://www.php.net/manual/en/book.bzip2.php for more info.',
0
);
// @codeCoverageIgnoreEnd
}
// Get the length of the packet (long)
$packet_length = $buffer->readInt32Signed();
// Checksum for the decompressed packet (long), burn it - doesnt work in split responses
$buffer->readInt32Signed();
// Try to decompress
$result = bzdecompress($buffer->getBuffer());
// Now verify the length
if (strlen($result) != $packet_length) {
// @codeCoverageIgnoreStart
throw new Exception(
"Checksum for compressed packet failed! Length expected: {$packet_length}, length
returned: " . strlen($result)
);
// @codeCoverageIgnoreEnd
}
// We need to burn the extra header (\xFF\xFF\xFF\xFF) on first loop
if ($i == 0) {
$result = substr($result, 4);
}
} else {
// Get the packet length (short), burn it
$buffer->readInt16Signed();
// We need to burn the extra header (\xFF\xFF\xFF\xFF) on first loop
if ($i == 0) {
$buffer->read(4);
}
// Grab the rest of the buffer as a result
$result = $buffer->getBuffer();
}
// Add this packet to the list
$packs[$packet_number] = $result;
}
unset($buffer);
}
// Free some memory
unset($packets, $packet);
// Sort the packets by packet number
ksort($packs);
// Now combine the packs into one and return
return implode("", $packs);
}
/**
* Handles processing the details data into a usable format
*
* @param \GameQ\Buffer $buffer
*
* @return mixed
* @throws \GameQ\Exception\Protocol
*/
protected function processDetails(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
$result->add('protocol', $buffer->readInt8());
$result->add('hostname', $buffer->readString());
$result->add('map', $buffer->readString());
$result->add('game_dir', $buffer->readString());
$result->add('game_descr', $buffer->readString());
$result->add('steamappid', $buffer->readInt16());
$result->add('num_players', $buffer->readInt8());
$result->add('max_players', $buffer->readInt8());
$result->add('num_bots', $buffer->readInt8());
$result->add('dedicated', $buffer->read());
$result->add('os', $buffer->read());
$result->add('password', $buffer->readInt8());
$result->add('secure', $buffer->readInt8());
// Special result for The Ship only (appid=2400)
if ($result->get('steamappid') == 2400) {
$result->add('game_mode', $buffer->readInt8());
$result->add('witness_count', $buffer->readInt8());
$result->add('witness_time', $buffer->readInt8());
}
$result->add('version', $buffer->readString());
// Because of php 5.4...
$edfCheck = $buffer->lookAhead(1);
// Extra data flag
if (!empty($edfCheck)) {
$edf = $buffer->readInt8();
if ($edf & 0x80) {
$result->add('port', $buffer->readInt16Signed());
}
if ($edf & 0x10) {
$result->add('steam_id', $buffer->readInt64());
}
if ($edf & 0x40) {
$result->add('sourcetv_port', $buffer->readInt16Signed());
$result->add('sourcetv_name', $buffer->readString());
}
if ($edf & 0x20) {
$result->add('keywords', $buffer->readString());
}
if ($edf & 0x01) {
$result->add('game_id', $buffer->readInt64());
}
unset($edf);
}
unset($buffer);
return $result->fetch();
}
/**
* Handles processing the server details from goldsource response
*
* @param \GameQ\Buffer $buffer
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
protected function processDetailsGoldSource(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
$result->add('address', $buffer->readString());
$result->add('hostname', $buffer->readString());
$result->add('map', $buffer->readString());
$result->add('game_dir', $buffer->readString());
$result->add('game_descr', $buffer->readString());
$result->add('num_players', $buffer->readInt8());
$result->add('max_players', $buffer->readInt8());
$result->add('version', $buffer->readInt8());
$result->add('dedicated', $buffer->read());
$result->add('os', $buffer->read());
$result->add('password', $buffer->readInt8());
// Mod section
$result->add('ismod', $buffer->readInt8());
// We only run these if ismod is 1 (true)
if ($result->get('ismod') == 1) {
$result->add('mod_urlinfo', $buffer->readString());
$result->add('mod_urldl', $buffer->readString());
$buffer->skip();
$result->add('mod_version', $buffer->readInt32Signed());
$result->add('mod_size', $buffer->readInt32Signed());
$result->add('mod_type', $buffer->readInt8());
$result->add('mod_cldll', $buffer->readInt8());
}
$result->add('secure', $buffer->readInt8());
$result->add('num_bots', $buffer->readInt8());
unset($buffer);
return $result->fetch();
}
/**
* Handles processing the player data into a usable format
*
* @param \GameQ\Buffer $buffer
*
* @return mixed
*/
protected function processPlayers(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Pull out the number of players
$num_players = $buffer->readInt8();
// Player count
$result->add('num_players', $num_players);
// No players so no need to look any further
if ($num_players == 0) {
return $result->fetch();
}
// Players list
while ($buffer->getLength()) {
$result->addPlayer('id', $buffer->readInt8());
$result->addPlayer('name', $buffer->readString());
$result->addPlayer('score', $buffer->readInt32Signed());
$result->addPlayer('time', $buffer->readFloat32());
}
unset($buffer);
return $result->fetch();
}
/**
* 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();
}
}

View file

@ -1,42 +0,0 @@
<?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;
/**
* Space Engineers Protocol Class
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Spaceengineers extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'spaceengineers';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Space Engineers";
}

View file

@ -1,53 +0,0 @@
<?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 Squad
*
* Port reference: http://forums.joinsquad.com/topic/9559-query-ports/
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Squad extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'squad';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Squad";
/**
* query_port = client_port + 19378
* 27165 = 7787 + 19378
*
* @type int
*/
protected $port_diff = 19378;
}

View file

@ -1,42 +0,0 @@
<?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 L4d2
*
* @package GameQ\Protocols
* @author Austin Bischoff <austin@codebeard.com>
*/
class Starbound extends Source
{
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'starbound';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Starbound";
}

View file

@ -1,226 +0,0 @@
<?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;
/**
* StarMade Protocol Class
*
* StarMade server query protocol class
*
* Credit to Robin Promesberger <schema@star-made.org> for providing Java based querying as a roadmap
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Starmade extends Protocol
{
/**
* Array of packets we want to query.
*
* @type array
*/
protected $packets = [
self::PACKET_STATUS => "\x00\x00\x00\x09\x2a\xff\xff\x01\x6f\x00\x00\x00\x00",
];
/**
* The transport mode for this protocol is TCP
*
* @type string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'starmade';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'starmade';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "StarMade";
/**
* 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',
'hostname' => 'hostname',
'maxplayers' => 'max_players',
'numplayers' => 'num_players',
'password' => 'password',
],
];
/**
* Process the response for the StarMade server
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
public function processResponse()
{
// Implode the packets, not sure if there is any split logic for multiple packets
$buffer = new Buffer(implode('', $this->packets_response), Buffer::NUMBER_TYPE_BIGENDIAN);
// Get the passed length in the data side of the packet
$buffer->readInt32Signed();
// Read off the timestamp (in milliseconds)
$buffer->readInt64();
// Burn the check id == 42
$buffer->readInt8();
// Read packetId, unused
$buffer->readInt16Signed();
// Read commandId, unused
$buffer->readInt8Signed();
// Read type, unused
$buffer->readInt8Signed();
$parsed = $this->parseServerParameters($buffer);
// Set the result to a new result instance
$result = new Result();
// Best guess info version is the type of response to expect. As of this commit the version is "2".
$result->add('info_version', $parsed[0]);
$result->add('version', $parsed[1]);
$result->add('hostname', $parsed[2]);
$result->add('game_descr', $parsed[3]);
$result->add('start_time', $parsed[4]);
$result->add('num_players', $parsed[5]);
$result->add('max_players', $parsed[6]);
$result->add('dedicated', 1); // All servers are dedicated as far as I can tell
$result->add('password', 0); // Unsure if you can password servers, cant read that value
//$result->add('map', 'Unknown');
unset($parsed);
return $result->fetch();
}
/**
* Parse the server response parameters
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @param \GameQ\Buffer $buffer
*
* @return array
* @throws \GameQ\Exception\Protocol
*/
protected function parseServerParameters(Buffer &$buffer)
{
// Init the parsed data array
$parsed = [];
// Read the number of parameters to parse
$parameterSize = $buffer->readInt32Signed();
// Iterate over the parameter size
for ($i = 0; $i < $parameterSize; $i++) {
// Read the type of return this is
$dataType = $buffer->readInt8Signed();
switch ($dataType) {
// 32-bit int
case 1:
$parsed[$i] = $buffer->readInt32Signed();
break;
// 64-bit int
case 2:
$parsed[$i] = $buffer->readInt64();
break;
// Float
case 3:
$parsed[$i] = $buffer->readFloat32();
break;
// String
case 4:
// The first 2 bytes are the string length
$strLength = $buffer->readInt16Signed();
// Read the above length from the buffer
$parsed[$i] = $buffer->read($strLength);
unset($strLength);
break;
// Boolean
case 5:
$parsed[$i] = (bool)$buffer->readInt8Signed();
break;
// 8-bit int
case 6:
$parsed[$i] = $buffer->readInt8Signed();
break;
// 16-bit int
case 7:
$parsed[$i] = $buffer->readInt16Signed();
break;
// Array
case 8:
// Not implemented
throw new Exception("StarMade array parsing is not implemented!");
}
}
return $parsed;
}
}

View file

@ -1,50 +0,0 @@
<?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,290 +0,0 @@
<?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\Server;
use GameQ\Exception\Protocol as Exception;
/**
* Teamspeak 2 Protocol Class
*
* All values are utf8 encoded upon processing
*
* This code ported from GameQ v1/v2. Credit to original author(s) as I just updated it to
* work within this new system.
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Teamspeak2 extends Protocol
{
/**
* 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 => "sel %d\x0asi\x0a",
self::PACKET_CHANNELS => "sel %d\x0acl\x0a",
self::PACKET_PLAYERS => "sel %d\x0apl\x0a",
];
/**
* The transport mode for this protocol is TCP
*
* @type string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'teamspeak2';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'teamspeak2';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Teamspeak 2";
/**
* The client join link
*
* @type string
*/
protected $join_link = "teamspeak://%s:%d/";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
'dedicated' => 'dedicated',
'hostname' => 'server_name',
'password' => 'server_password',
'numplayers' => 'server_currentusers',
'maxplayers' => 'server_maxusers',
],
// Player
'player' => [
'id' => 'p_id',
'team' => 'c_id',
'name' => 'nick',
],
// Team
'team' => [
'id' => 'id',
'name' => 'name',
],
];
/**
* Before we send off the queries we need to update the packets
*
* @param \GameQ\Server $server
*
* @throws \GameQ\Exception\Protocol
*/
public function beforeSend(Server $server)
{
// Check to make sure we have a query_port because it is required
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 . "'.");
}
// Let's loop the packets and set the proper pieces
foreach ($this->packets as $packet_type => $packet) {
// Update with the client port for the server
$this->packets[$packet_type] = sprintf($packet, $server->portClient());
}
}
/**
* 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 [TS]
if (($header = trim($buffer->readString("\n"))) !== '[TS]') {
throw new Exception(__METHOD__ . " Expected header '{$header}' does not match expected '[TS]'.");
}
// Split this buffer as the data blocks are bound by "OK" and drop any empty values
$sections = array_filter(explode("OK", $buffer->getBuffer()), function ($value) {
$value = trim($value);
return !empty($value);
});
// Trim up the values to remove extra whitespace
$sections = array_map('trim', $sections);
// Set the result to a new result instance
$result = new Result();
// Now we need to iterate over the sections and off load the processing
foreach ($sections as $section) {
// Grab a snip of the data so we can figure out what it is
$check = substr($section, 0, 7);
// Offload to the proper method
if ($check == 'server_') {
// Server settings and info
$this->processDetails($section, $result);
} elseif ($check == "id\tcode") {
// Channel info
$this->processChannels($section, $result);
} elseif ($check == "p_id\tc_") {
// Player info
$this->processPlayers($section, $result);
}
}
unset($buffer, $sections, $section, $check);
return $result->fetch();
}
/*
* Internal methods
*/
/**
* Handles processing the details data into a usable format
*
* @param string $data
* @param \GameQ\Result $result
*/
protected function processDetails($data, Result &$result)
{
// Create a buffer
$buffer = new Buffer($data);
// Always dedicated
$result->add('dedicated', 1);
// Let's loop until we run out of data
while ($buffer->getLength()) {
// Grab the row, which is an item
$row = trim($buffer->readString("\n"));
// Split out the information
list($key, $value) = explode('=', $row, 2);
// Add this to the result
$result->add($key, utf8_encode($value));
}
unset($data, $buffer, $row, $key, $value);
}
/**
* Process the channel listing
*
* @param string $data
* @param \GameQ\Result $result
*/
protected function processChannels($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")), 9);
// 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, 9));
foreach ($data as $key => $value) {
// Now add the data to the result
$result->addTeam($key, utf8_encode($value));
}
}
unset($data, $buffer, $row, $columns, $key, $value);
}
/**
* 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);
}
}

View file

@ -1,328 +0,0 @@
<?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\Server;
use GameQ\Exception\Protocol as Exception;
/**
* Teamspeak 3 Protocol Class
*
* All values are utf8 encoded upon processing
*
* This code ported from GameQ v1/v2. Credit to original author(s) as I just updated it to
* work within this new system.
*
* @author Austin Bischoff <austin@codebeard.com>
*/
class Teamspeak3 extends Protocol
{
/**
* 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 => "use port=%d\x0Aserverinfo\x0A",
self::PACKET_PLAYERS => "use port=%d\x0Aclientlist\x0A",
self::PACKET_CHANNELS => "use port=%d\x0Achannellist -topic\x0A",
];
/**
* The transport mode for this protocol is TCP
*
* @type string
*/
protected $transport = self::TRANSPORT_TCP;
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'teamspeak3';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'teamspeak3';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Teamspeak 3";
/**
* The client join link
*
* @type string
*/
protected $join_link = "ts3server://%s?port=%d";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
'dedicated' => 'dedicated',
'hostname' => 'virtualserver_name',
'password' => 'virtualserver_flag_password',
'numplayers' => 'numplayers',
'maxplayers' => 'virtualserver_maxclients',
],
// Player
'player' => [
'id' => 'clid',
'team' => 'cid',
'name' => 'client_nickname',
],
// Team
'team' => [
'id' => 'cid',
'name' => 'channel_name',
],
];
/**
* Before we send off the queries we need to update the packets
*
* @param \GameQ\Server $server
*
* @throws \GameQ\Exception\Protocol
*/
public function beforeSend(Server $server)
{
// Check to make sure we have a query_port because it is required
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 . "'.");
}
// Let's loop the packets and set the proper pieces
foreach ($this->packets as $packet_type => $packet) {
// Update with the client port for the server
$this->packets[$packet_type] = sprintf($packet, $server->portClient());
}
}
/**
* 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(
[
'\\\\', // Translate escaped \
'\\/', // Translate escaped /
],
[
'\\',
'/',
],
$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();
}
/*
* Internal methods
*/
/**
* Process the properties of the data.
*
* Takes data in "key1=value1 key2=value2 ..." and processes it into a usable format
*
* @param $data
*
* @return array
*/
protected function processProperties($data)
{
// Will hold the properties we are sending back
$properties = [];
// All of these are split on space
$items = explode(' ', $data);
// Iterate over the items
foreach ($items as $item) {
// Explode and make sure we always have 2 items in the array
list($key, $value) = array_pad(explode('=', $item, 2), 2, '');
// Convert spaces and other character changes
$properties[$key] = utf8_encode(str_replace(
[
'\\s', // Translate spaces
],
[
' ',
],
$value
));
}
return $properties;
}
/**
* Handles processing the details data into a usable format
*
* @param string $data
* @param \GameQ\Result $result
*/
protected function processDetails($data, Result &$result)
{
// Offload the parsing for these values
$properties = $this->processProperties($data);
// Always dedicated
$result->add('dedicated', 1);
// Iterate over the properties
foreach ($properties as $key => $value) {
$result->add($key, $value);
}
// We need to manually figure out the number of players
$result->add(
'numplayers',
($properties['virtualserver_clientsonline'] - $properties['virtualserver_queryclientsonline'])
);
unset($data, $properties, $key, $value);
}
/**
* Process the channel listing
*
* @param string $data
* @param \GameQ\Result $result
*/
protected function processChannels($data, Result &$result)
{
// We need to split the data at the pipe
$channels = explode('|', $data);
// Iterate over the channels
foreach ($channels as $channel) {
// Offload the parsing for these values
$properties = $this->processProperties($channel);
// Iterate over the properties
foreach ($properties as $key => $value) {
$result->addTeam($key, $value);
}
}
unset($data, $channel, $channels, $properties, $key, $value);
}
/**
* Process the user listing
*
* @param string $data
* @param \GameQ\Result $result
*/
protected function processPlayers($data, Result &$result)
{
// We need to split the data at the pipe
$players = explode('|', $data);
// Iterate over the channels
foreach ($players as $player) {
// Offload the parsing for these values
$properties = $this->processProperties($player);
// Iterate over the properties
foreach ($properties as $key => $value) {
$result->addPlayer($key, $value);
}
}
unset($data, $player, $players, $properties, $key, $value);
}
}

View file

@ -1,181 +0,0 @@
<?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;
/**
* Teeworlds Protocol class
*
* Only supports versions > 0.5
*
* @author Austin Bischoff <austin@codebeard.com>
* @author Marcel Bößendörfer <m.boessendoerfer@marbis.net>
*/
class Teeworlds extends Protocol
{
/**
* 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_ALL => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x67\x69\x65\x33\x05",
// 0.5 Packet (not compatible, maybe some wants to implement "Teeworldsold")
//self::PACKET_STATUS => "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFFgief",
];
/**
* Use the response flag to figure out what method to run
*
* @type array
*/
protected $responses = [
"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffinf35" => "processAll",
];
/**
* The query protocol used to make the call
*
* @type string
*/
protected $protocol = 'teeworlds';
/**
* String name of this protocol class
*
* @type string
*/
protected $name = 'teeworlds';
/**
* Longer string name of this protocol class
*
* @type string
*/
protected $name_long = "Teeworlds Server";
/**
* The client join link
*
* @type string
*/
protected $join_link = "steam://connect/%s:%d/";
/**
* Normalize settings for this protocol
*
* @type array
*/
protected $normalize = [
// General
'general' => [
// target => source
'dedicated' => 'dedicated',
'hostname' => 'hostname',
'mapname' => 'map',
'maxplayers' => 'num_players_total',
],
// Individual
'player' => [
'name' => 'name',
'score' => 'score',
],
];
/**
* Process the response
*
* @return array
* @throws Exception
*/
public function processResponse()
{
// Holds the results
$results = [];
// Iterate over the packets
foreach ($this->packets_response as $response) {
// Make a buffer
$buffer = new Buffer($response);
// Grab the header
$header = $buffer->readString();
// 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]], [$buffer])
);
}
unset($buffer);
return $results;
}
/**
* Handle processing all of the data returned
*
* @param Buffer $buffer
*
* @return array
*/
protected function processAll(Buffer $buffer)
{
// Set the result to a new result instance
$result = new Result();
// Always dedicated
$result->add('dedicated', 1);
$result->add('version', $buffer->readString());
$result->add('hostname', $buffer->readString());
$result->add('map', $buffer->readString());
$result->add('game_descr', $buffer->readString());
$result->add('flags', $buffer->readString()); // not sure about that
$result->add('num_players', $buffer->readString());
$result->add('maxplayers', $buffer->readString());
$result->add('num_players_total', $buffer->readString());
$result->add('maxplayers_total', $buffer->readString());
// Players
while ($buffer->getLength()) {
$result->addPlayer('name', $buffer->readString());
$result->addPlayer('clan', $buffer->readString());
$result->addPlayer('flag', $buffer->readString());
$result->addPlayer('score', $buffer->readString());
$result->addPlayer('team', $buffer->readString());
}
unset($buffer);
return $result->fetch();
}
}

Some files were not shown because too many files have changed in this diff Show more