+ */
+ public static function hashes(array $array): array
+ {
+ $hashes = [];
+
+ // Process the provided array
+ foreach ($array as $key => $value) {
+ // Serialze and hash each value individually
+ $hashes[$key] = md5(serialize($value));
+ }
+
+ // Return array containing the hashes
+ return $hashes;
+ }
+
+ /**
+ * This helper is intended to set a value inside the provided array.
+ */
+ public static function set(array &$array, array $path, $value): array
+ {
+ $current = &$array;
+
+ // Process the path until the last element
+ foreach ($path as $i => $element) {
+ // Remove the element from the path
+ unset($path[$i]);
+
+ // Create missing key
+ if (! isset($current[$element])) {
+ $current[$element] = [];
+ }
+
+ // Set current to a reference of next
+ $current = &$current[$element];
+ }
+
+ // Finally set the value using the last key
+ $current = $value;
+
+ // Return the current, modified array (level)
+ return $array;
+ }
+
+ /**
+ * This helper method is intended to shift the provided arguments to the left.
+ *
+ * **Example:** foo, bar, baz becomes bar, baz, baz
+ */
+ public static function shift(&...$args): void
+ {
+ // Get the array keys to ensure numeric index
+ $keys = array_keys($args);
+
+ // Iterate the provided arguments keys in order
+ foreach ($keys as $i => $key) {
+ // Process until the last argument
+ if ($i < count($keys) - 1) {
+ // Shift next into current
+ $args[$key] = $args[$keys[$i + 1]];
+ }
+ }
+ }
+}
diff --git a/src/GameQ/Helpers/Str.php b/src/GameQ/Helpers/Str.php
new file mode 100644
index 00000000..6899ec84
--- /dev/null
+++ b/src/GameQ/Helpers/Str.php
@@ -0,0 +1,49 @@
+.
+ */
+
+namespace GameQ\Helpers;
+
+/**
+ * This helper contains functions to work with strings.
+ *
+ * @package GameQ\Helpers
+ */
+class Str
+{
+ /**
+ * This helper method re-encodes an ISO 8859-1 string to UTF-8.
+ *
+ * @see https://en.wikipedia.org/wiki/ISO/IEC_8859-1
+ * @see https://en.wikipedia.org/wiki/UTF-8
+ */
+ public static function isoToUtf8(string $value): string
+ {
+ return iconv('ISO-8859-1', 'UTF-8', $value);
+ }
+
+ /**
+ * This helper method re-encodes an UTF-8 string to ISO 8859-1.
+ *
+ * @see https://en.wikipedia.org/wiki/ISO/IEC_8859-1
+ * @see https://en.wikipedia.org/wiki/UTF-8
+ */
+ public static function utf8ToIso(string $value): string
+ {
+ return iconv('UTF-8', 'ISO-8859-1', $value);
+ }
+}
diff --git a/src/GameQ/Protocol.php b/src/GameQ/Protocol.php
index 26ac92aa..fef648d8 100644
--- a/src/GameQ/Protocol.php
+++ b/src/GameQ/Protocol.php
@@ -29,7 +29,6 @@
*/
abstract class Protocol
{
-
/**
* Constants for class states
*/
@@ -165,7 +164,6 @@ abstract class Protocol
public function __construct(array $options = [])
{
-
// Set the options for this specific instance of the class
$this->options = $options;
}
@@ -175,7 +173,6 @@ public function __construct(array $options = [])
*/
public function __toString(): string
{
-
return $this->name;
}
@@ -184,7 +181,6 @@ public function __toString(): string
*/
public function portDiff(): int
{
-
return $this->port_diff;
}
@@ -195,7 +191,6 @@ public function portDiff(): int
*/
public function findQueryPort(int $clientPort): int
{
-
return $clientPort + $this->port_diff;
}
@@ -204,7 +199,6 @@ public function findQueryPort(int $clientPort): int
*/
public function joinLink(): ?string
{
-
return $this->join_link;
}
@@ -213,7 +207,6 @@ public function joinLink(): ?string
*/
public function name(): string
{
-
return $this->name;
}
@@ -222,7 +215,6 @@ public function name(): string
*/
public function nameLong(): string
{
-
return $this->name_long;
}
@@ -231,7 +223,6 @@ public function nameLong(): string
*/
public function state(): int
{
-
return $this->state;
}
@@ -240,7 +231,6 @@ public function state(): int
*/
public function getProtocol(): string
{
-
return $this->protocol;
}
@@ -261,7 +251,6 @@ public function transport(?string $type = null): ?string
*/
public function options(array $options = []): array
{
-
if (!empty($options)) {
$this->options = $options;
}
@@ -270,9 +259,7 @@ public function options(array $options = []): array
}
- /*
- * Packet Section
- */
+ // Packet Section
/**
* Return specific packet(s)
@@ -323,9 +310,7 @@ public function packetResponse(?array $response = null): array
}
- /*
- * Challenge section
- */
+ // Challenge section
/**
* Determine whether or not this protocol has a challenge needed before querying
@@ -341,7 +326,6 @@ public function hasChallenge(): bool
*/
public function challengeParseAndApply(Buffer $challenge_buffer): bool
{
-
return true;
}
@@ -350,7 +334,6 @@ public function challengeParseAndApply(Buffer $challenge_buffer): bool
*/
protected function challengeApply(string $challenge_string): bool
{
-
// Let's loop through all the packets and append the challenge where it is needed
foreach ($this->packets as $packet_type => $packet) {
$this->packets[$packet_type] = sprintf($packet, $challenge_string);
@@ -359,52 +342,15 @@ protected function challengeApply(string $challenge_string): bool
return true;
}
- /**
- * Converts a string from ISO-8859-1 to UTF-8.
- * This is a replacement for PHP's utf8_encode function that was deprecated with PHP 8.2.
- *
- * Source: symfony/polyfill-php72
- * See https://github.com/symfony/polyfill-php72/blob/bf44a9fd41feaac72b074de600314a93e2ae78e2/Php72.php#L24-L38
- *
- * @author Nicolas Grekas
- * @author Dariusz RumiĆski > 1, $j = 0; $i < $len; ++$i, ++$j) {
- switch (true) {
- case $s[$i] < "\x80":
- $s[$j] = $s[$i];
- break;
- case $s[$i] < "\xC0":
- $s[$j] = "\xC2";
- $s[++$j] = $s[$i];
- break;
- default:
- $s[$j] = "\xC3";
- $s[++$j] = \chr(\ord($s[$i]) - 64);
- break;
- }
- }
-
- return substr($s, 0, $j);
- }
-
/**
* Get the normalize settings for the protocol
*/
public function getNormalize(): array
{
-
return $this->normalize;
}
- /*
- * General
- */
+ // General
/**
* Generic method to allow protocol classes to do work right before the query is sent
diff --git a/src/GameQ/Protocols/Aa3.php b/src/GameQ/Protocols/Aa3.php
index 2ad70c16..d7d3d4da 100644
--- a/src/GameQ/Protocols/Aa3.php
+++ b/src/GameQ/Protocols/Aa3.php
@@ -26,7 +26,6 @@
*/
class Aa3 extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Arksa.php b/src/GameQ/Protocols/Arksa.php
new file mode 100644
index 00000000..62f2ff82
--- /dev/null
+++ b/src/GameQ/Protocols/Arksa.php
@@ -0,0 +1,113 @@
+.
+ */
+
+namespace GameQ\Protocols;
+
+use GameQ\Exception\ProtocolException;
+use GameQ\Result;
+
+/**
+ * ARK: Survival Ascended Protocol Class
+ *
+ * Extends the EOS protocol and adds ARK-specific server response processing.
+ *
+ * @package GameQ\Protocols
+ * @author H.Rouatbi
+ */
+class Arksa extends Eos
+{
+ /**
+ * The protocol being used
+ */
+ protected string $protocol = 'arksa';
+
+ /**
+ * Longer string name of this protocol class
+ */
+ protected string $name_long = 'ARK: Survival Ascended';
+
+ /**
+ * String name of this protocol class
+ */
+ protected string $name = 'arksa';
+
+ /**
+ * Grant type used for authentication
+ */
+ protected string $grant_type = 'client_credentials';
+
+ /**
+ * Deployment ID for the game or application
+ */
+ protected ?string $deployment_id = 'ad9a8feffb3b4b2ca315546f038c3ae2';
+
+ /**
+ * User ID for authentication
+ */
+ protected ?string $user_id = 'xyza7891muomRmynIIHaJB9COBKkwj6n';
+
+ /**
+ * User secret key for authentication
+ */
+ protected ?string $user_secret = 'PP5UGxysEieNfSrEicaD1N2Bb3TdXuD7xHYcsdUHZ7s';
+
+ /**
+ * Process the response from the EOS API and filter ARK-specific server data
+ *
+ * @throws ProtocolException
+ */
+ public function processResponse(): array
+ {
+ $serverData = parent::processResponse();
+
+ // Filter by port to match server sessions
+ $filtered = array_filter($serverData, function ($session) {
+ return $session['attributes']['ADDRESSBOUND_s'] === "{$this->serverIp}:{$this->serverPortQuery}" ||
+ $session['attributes']['ADDRESSBOUND_s'] === "0.0.0.0:{$this->serverPortQuery}";
+ });
+
+ if (!$filtered) {
+ throw new ProtocolException('No matching sessions found for the specified port.');
+ }
+
+ $session = reset($filtered);
+
+ $result = new Result();
+
+ // Add server items to the result object
+ $result->add('hostname', $this->getAttribute($session['attributes'], 'CUSTOMSERVERNAME_s', 'Unknown'));
+ $result->add('mapname', $this->getAttribute($session['attributes'], 'MAPNAME_s', 'Unknown'));
+ $result->add('password', $this->getAttribute($session['attributes'], 'SERVERPASSWORD_b', false));
+ $result->add('numplayers', $this->getAttribute($session, 'totalPlayers', 0));
+ $result->add('maxplayers', $this->getAttribute($session['settings'], 'maxPublicPlayers', 0));
+ $result->add('anticheat', $this->getAttribute($session['attributes'], 'SERVERUSESBATTLEYE_b', false));
+ $result->add('allowJoinInProgress', $this->getAttribute($session['settings'], 'allowJoinInProgress', false));
+ $result->add('day', $this->getAttribute($session['attributes'], 'DAYTIME_s', ''));
+ $result->add(
+ 'version',
+ "v" . $this->getAttribute($session['attributes'], 'BUILDID_s', '0') . "." .
+ $this->getAttribute($session['attributes'], 'MINORBUILDID_s', '0')
+ );
+ $result->add('pve', (bool) $this->getAttribute($session['attributes'], 'SESSIONISPVE_l', false));
+ $result->add('officialserver', (bool) $this->getAttribute($session['attributes'], 'OFFICIALSERVER_s', false));
+
+ // Return the final result
+ return $result->fetch();
+ }
+}
diff --git a/src/GameQ/Protocols/Arkse.php b/src/GameQ/Protocols/Arkse.php
index 75c82288..ee7bd6ee 100644
--- a/src/GameQ/Protocols/Arkse.php
+++ b/src/GameQ/Protocols/Arkse.php
@@ -26,7 +26,6 @@
*/
class Arkse extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Armedassault2oa.php b/src/GameQ/Protocols/Armedassault2oa.php
index 7b08c28a..c27201d9 100644
--- a/src/GameQ/Protocols/Armedassault2oa.php
+++ b/src/GameQ/Protocols/Armedassault2oa.php
@@ -26,7 +26,6 @@
*/
class Armedassault2oa extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Ase.php b/src/GameQ/Protocols/Ase.php
index c2e16bce..4f3f9669 100644
--- a/src/GameQ/Protocols/Ase.php
+++ b/src/GameQ/Protocols/Ase.php
@@ -31,7 +31,6 @@
*/
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
@@ -136,9 +135,7 @@ public function processResponse(): mixed
return $result->fetch();
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handles processing the extra key/value pairs for server settings
diff --git a/src/GameQ/Protocols/Atlas.php b/src/GameQ/Protocols/Atlas.php
index 64c6d4a0..cec6716a 100644
--- a/src/GameQ/Protocols/Atlas.php
+++ b/src/GameQ/Protocols/Atlas.php
@@ -26,7 +26,6 @@
*/
class Atlas extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Batt1944.php b/src/GameQ/Protocols/Batt1944.php
index 539e0a99..3b74dcd8 100644
--- a/src/GameQ/Protocols/Batt1944.php
+++ b/src/GameQ/Protocols/Batt1944.php
@@ -26,7 +26,6 @@
*/
class Batt1944 extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Bf1942.php b/src/GameQ/Protocols/Bf1942.php
index f48f5b64..0fd50813 100644
--- a/src/GameQ/Protocols/Bf1942.php
+++ b/src/GameQ/Protocols/Bf1942.php
@@ -26,7 +26,6 @@
*/
class Bf1942 extends Gamespy
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Bf2.php b/src/GameQ/Protocols/Bf2.php
index ca107d2c..711188f7 100644
--- a/src/GameQ/Protocols/Bf2.php
+++ b/src/GameQ/Protocols/Bf2.php
@@ -26,7 +26,6 @@
*/
class Bf2 extends Gamespy3
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Bf3.php b/src/GameQ/Protocols/Bf3.php
index 8802011d..80a80858 100644
--- a/src/GameQ/Protocols/Bf3.php
+++ b/src/GameQ/Protocols/Bf3.php
@@ -33,7 +33,6 @@
*/
class Bf3 extends Protocol
{
-
/**
* Array of packets we want to query.
*/
@@ -117,7 +116,6 @@ class Bf3 extends Protocol
*/
public function processResponse(): mixed
{
-
// Holds the results sent back
$results = [];
@@ -173,9 +171,7 @@ public function processResponse(): mixed
return $results;
}
- /*
- * Internal Methods
- */
+ // Internal Methods
/**
* Decode the buffer into a usable format
@@ -185,7 +181,6 @@ public function processResponse(): mixed
*/
protected function decode(Buffer $buffer)
{
-
$items = [];
// Get the number of words in this buffer
@@ -211,7 +206,6 @@ protected function decode(Buffer $buffer)
*/
protected function processDetails(Buffer $buffer)
{
-
// Decode into items
$items = $this->decode($buffer);
@@ -276,7 +270,6 @@ protected function processDetails(Buffer $buffer)
*/
protected function processVersion(Buffer $buffer)
{
-
// Decode into items
$items = $this->decode($buffer);
@@ -298,7 +291,6 @@ protected function processVersion(Buffer $buffer)
*/
protected function processPlayers(Buffer $buffer)
{
-
// Decode into items
$items = $this->decode($buffer);
diff --git a/src/GameQ/Protocols/Bf4.php b/src/GameQ/Protocols/Bf4.php
index f65a91b5..f3701893 100644
--- a/src/GameQ/Protocols/Bf4.php
+++ b/src/GameQ/Protocols/Bf4.php
@@ -19,6 +19,7 @@
namespace GameQ\Protocols;
use GameQ\Buffer;
+use GameQ\Exception\ProtocolException;
use GameQ\Result;
/**
@@ -31,7 +32,6 @@
*/
class Bf4 extends Bf3
{
-
/**
* String name of this protocol class
*/
@@ -46,10 +46,10 @@ class Bf4 extends Bf3
* Handle processing details since they are different than BF3
*
* @return array
+ * @throws ProtocolException
*/
protected function processDetails(Buffer $buffer)
{
-
// Decode into items
$items = $this->decode($buffer);
diff --git a/src/GameQ/Protocols/Bfbc2.php b/src/GameQ/Protocols/Bfbc2.php
index 7b661556..0e4f8c1b 100644
--- a/src/GameQ/Protocols/Bfbc2.php
+++ b/src/GameQ/Protocols/Bfbc2.php
@@ -36,7 +36,6 @@
*/
class Bfbc2 extends Protocol
{
-
/**
* Array of packets we want to query.
*/
@@ -152,9 +151,7 @@ public function processResponse(): mixed
return $results;
}
- /*
- * Internal Methods
- */
+ // Internal Methods
/**
* Decode the buffer into a usable format
@@ -164,7 +161,6 @@ public function processResponse(): mixed
*/
protected function decode(Buffer $buffer)
{
-
$items = [];
// Get the number of words in this buffer
@@ -186,10 +182,10 @@ protected function decode(Buffer $buffer)
* Process the server details
*
* @return array
+ * @throws ProtocolException
*/
protected function processDetails(Buffer $buffer)
{
-
// Decode into items
$items = $this->decode($buffer);
@@ -247,6 +243,7 @@ protected function processDetails(Buffer $buffer)
* Process the server version
*
* @return array
+ * @throws ProtocolException
*/
protected function processVersion(Buffer $buffer)
{
@@ -267,10 +264,10 @@ protected function processVersion(Buffer $buffer)
* Process the players
*
* @return array
+ * @throws ProtocolException
*/
protected function processPlayers(Buffer $buffer)
{
-
// Decode into items
$items = $this->decode($buffer);
diff --git a/src/GameQ/Protocols/Bfh.php b/src/GameQ/Protocols/Bfh.php
index 5e8d47ff..bc38936c 100644
--- a/src/GameQ/Protocols/Bfh.php
+++ b/src/GameQ/Protocols/Bfh.php
@@ -26,7 +26,6 @@
*/
class Bfh extends Bf4
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Cfx.php b/src/GameQ/Protocols/Cfx.php
index eaa898d6..d0162c23 100644
--- a/src/GameQ/Protocols/Cfx.php
+++ b/src/GameQ/Protocols/Cfx.php
@@ -38,7 +38,6 @@
*/
class Cfx extends Protocol
{
-
/**
* Array of packets we want to look up.
* Each key should correspond to a defined method in this or a parent class
@@ -94,6 +93,8 @@ class Cfx extends Protocol
/**
* Get FiveM players list using a sub query
+ *
+ * @throws \Exception
*/
public function beforeSend(Server $server): void
{
@@ -129,9 +130,7 @@ public function processResponse(): mixed
return $this->{$this->responses[$response_type]}($buffer);
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handle processing the status response
diff --git a/src/GameQ/Protocols/Codmw2.php b/src/GameQ/Protocols/Codmw2.php
index abf1c89b..e6d23e03 100644
--- a/src/GameQ/Protocols/Codmw2.php
+++ b/src/GameQ/Protocols/Codmw2.php
@@ -19,6 +19,8 @@
namespace GameQ\Protocols;
use GameQ\Buffer;
+use GameQ\Exception\ProtocolException;
+use GameQ\Helpers\Str;
use GameQ\Result;
/**
@@ -39,6 +41,10 @@ class Codmw2 extends Quake3
*/
protected string $name_long = "Call of Duty: Modern Warfare 2";
+ /**
+ * @return array
+ * @throws ProtocolException
+ */
protected function processPlayers(Buffer $buffer)
{
// Temporarily cache players in order to remove last
@@ -59,7 +65,7 @@ protected function processPlayers(Buffer $buffer)
$playerInfo->skip();
// Add player name, encoded
- $player['name'] = $this->convertToUtf8(trim(($playerInfo->readString('"'))));
+ $player['name'] = Str::isoToUtf8(trim(($playerInfo->readString('"'))));
// Add player
$players[] = $player;
diff --git a/src/GameQ/Protocols/Codmw3.php b/src/GameQ/Protocols/Codmw3.php
index 603cac1c..05b5f24c 100644
--- a/src/GameQ/Protocols/Codmw3.php
+++ b/src/GameQ/Protocols/Codmw3.php
@@ -26,7 +26,6 @@
*/
class Codmw3 extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Cs15.php b/src/GameQ/Protocols/Cs15.php
index 8769b456..f70cf9cd 100644
--- a/src/GameQ/Protocols/Cs15.php
+++ b/src/GameQ/Protocols/Cs15.php
@@ -28,7 +28,6 @@
*/
class Cs15 extends Won
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Cs16.php b/src/GameQ/Protocols/Cs16.php
index 041e2590..0e748443 100644
--- a/src/GameQ/Protocols/Cs16.php
+++ b/src/GameQ/Protocols/Cs16.php
@@ -28,7 +28,6 @@
*/
class Cs16 extends Source
{
-
/**
* String name of this protocol class
*/
@@ -51,7 +50,6 @@ class Cs16 extends Source
*/
protected function processPackets($packet_id, array $packets = [])
{
-
// The response is gold source if the packets are split
$this->source_engine = self::GOLDSOURCE_ENGINE;
diff --git a/src/GameQ/Protocols/Cs2d.php b/src/GameQ/Protocols/Cs2d.php
index 3e78d924..c63f7088 100644
--- a/src/GameQ/Protocols/Cs2d.php
+++ b/src/GameQ/Protocols/Cs2d.php
@@ -19,7 +19,6 @@
namespace GameQ\Protocols;
use GameQ\Exception\ProtocolException;
-use GameQ\Protocol;
use GameQ\Buffer;
use GameQ\Result;
@@ -33,7 +32,6 @@
*/
class Cs2d extends Protocol
{
-
/**
* Array of packets we want to query.
*/
@@ -104,7 +102,6 @@ class Cs2d extends Protocol
*/
public function processResponse(): mixed
{
-
// We have a merged packet, try to split it back up
if (count($this->packets_response) === 1) {
// Temp buffer to make string manipulation easier
@@ -185,8 +182,8 @@ protected function processDetails(Buffer $buffer)
$result->add('lua_scripts', (int)$this->readFlag($serverFlags, 6));
// Read the rest of the buffer data
- $result->add('servername', $this->convertToUtf8($buffer->readPascalString()));
- $result->add('mapname', $this->convertToUtf8($buffer->readPascalString()));
+ $result->add('servername', Str::isoToUtf8($buffer->readPascalString()));
+ $result->add('mapname', Str::isoToUtf8($buffer->readPascalString()));
$result->add('num_players', $buffer->readInt8());
$result->add('max_players', $buffer->readInt8());
$result->add('game_mode', $buffer->readInt8());
@@ -204,7 +201,6 @@ protected function processDetails(Buffer $buffer)
*/
protected function processPlayers(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -217,7 +213,7 @@ protected function processPlayers(Buffer $buffer)
if (($id = $buffer->readInt8()) !== 0) {
// Add the results
$result->addPlayer('id', $id);
- $result->addPlayer('name', $this->convertToUtf8($buffer->readPascalString()));
+ $result->addPlayer('name', Str::isoToUtf8($buffer->readPascalString()));
$result->addPlayer('team', $buffer->readInt8());
$result->addPlayer('score', $buffer->readInt32());
$result->addPlayer('deaths', $buffer->readInt32());
diff --git a/src/GameQ/Protocols/Cscz.php b/src/GameQ/Protocols/Cscz.php
index e3de7037..db8951cc 100644
--- a/src/GameQ/Protocols/Cscz.php
+++ b/src/GameQ/Protocols/Cscz.php
@@ -28,7 +28,6 @@
*/
class Cscz extends Cs16
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Csgo.php b/src/GameQ/Protocols/Csgo.php
index ea37ddae..6ca6bbf6 100644
--- a/src/GameQ/Protocols/Csgo.php
+++ b/src/GameQ/Protocols/Csgo.php
@@ -26,7 +26,6 @@
*/
class Csgo extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Dal.php b/src/GameQ/Protocols/Dal.php
index 4e518b65..9117793b 100644
--- a/src/GameQ/Protocols/Dal.php
+++ b/src/GameQ/Protocols/Dal.php
@@ -26,7 +26,6 @@
*/
class Dal extends Arkse
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Dayz.php b/src/GameQ/Protocols/Dayz.php
index 13de9655..97b4eaad 100644
--- a/src/GameQ/Protocols/Dayz.php
+++ b/src/GameQ/Protocols/Dayz.php
@@ -26,7 +26,6 @@
*/
class Dayz extends Source
{
-
/**
* String name of this protocol class
*/
@@ -42,7 +41,6 @@ class Dayz extends Source
*/
public function findQueryPort(int $clientPort): int
{
-
/*
* Port layout:
* 2302 - 27016
diff --git a/src/GameQ/Protocols/Dayzmod.php b/src/GameQ/Protocols/Dayzmod.php
index 07be900e..6c7a8a69 100644
--- a/src/GameQ/Protocols/Dayzmod.php
+++ b/src/GameQ/Protocols/Dayzmod.php
@@ -27,7 +27,6 @@
*/
class Dayzmod extends Armedassault2oa
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Dod.php b/src/GameQ/Protocols/Dod.php
index d99287e2..d5d1cc3a 100644
--- a/src/GameQ/Protocols/Dod.php
+++ b/src/GameQ/Protocols/Dod.php
@@ -28,7 +28,6 @@
*/
class Dod extends Cs16
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Doom3.php b/src/GameQ/Protocols/Doom3.php
index 4127efe9..bf96203e 100644
--- a/src/GameQ/Protocols/Doom3.php
+++ b/src/GameQ/Protocols/Doom3.php
@@ -146,7 +146,7 @@ protected function processServerInfo(Buffer $buffer)
// Key / value pairs, delimited by an empty pair
while ($buffer->getLength()) {
$key = trim($buffer->readString());
- $val = $this->convertToUtf8(trim($buffer->readString()));
+ $val = Str::isoToUtf8(trim($buffer->readString()));
// Something is empty so we are done
if (empty($key) && empty($val)) {
@@ -181,7 +181,7 @@ protected function processPlayers(Buffer $buffer)
$result->addPlayer('ping', $buffer->readInt16());
$result->addPlayer('rate', $buffer->readInt32());
// Add player name, encoded
- $result->addPlayer('name', $this->convertToUtf8(trim($buffer->readString())));
+ $result->addPlayer('name', Str::isoToUtf8(trim($buffer->readString())));
// Increment
$playerCount++;
diff --git a/src/GameQ/Protocols/Egs.php b/src/GameQ/Protocols/Egs.php
index d7b6c60d..a3c4fce5 100644
--- a/src/GameQ/Protocols/Egs.php
+++ b/src/GameQ/Protocols/Egs.php
@@ -27,7 +27,6 @@
*/
class Egs extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Eos.php b/src/GameQ/Protocols/Eos.php
new file mode 100644
index 00000000..1f1d4c8a
--- /dev/null
+++ b/src/GameQ/Protocols/Eos.php
@@ -0,0 +1,241 @@
+.
+ */
+
+namespace GameQ\Protocols;
+
+use GameQ\Exception\ProtocolException;
+use GameQ\Server;
+
+/**
+ * Epic Online Services Protocol Class
+ *
+ * Serves as a base class for EOS-powered games.
+ *
+ * @package GameQ\Protocols
+ * @author H.Rouatbi
+ */
+class Eos extends Http
+{
+ /**
+ * The protocol being used
+ */
+ protected string $protocol = 'eos';
+
+ /**
+ * Longer string name of this protocol class
+ */
+ protected string $name_long = 'Epic Online Services';
+
+ /**
+ * String name of this protocol class
+ */
+ protected string $name = 'eos';
+
+ /**
+ * Grant type used for authentication
+ */
+ protected string $grant_type = 'client_credentials';
+
+ /**
+ * Deployment ID for the game or application
+ */
+ protected ?string $deployment_id = null;
+
+ /**
+ * User ID for authentication
+ */
+ protected ?string $user_id = null;
+
+ /**
+ * User secret key for authentication
+ */
+ protected ?string $user_secret = null;
+
+ /**
+ * Holds the server ip so we can overwrite it back
+ */
+ protected ?string $serverIp = null;
+
+ /**
+ * Holds the server port query so we can overwrite it back
+ */
+ protected ?string $serverPortQuery = null;
+
+ /**
+ * Normalize some items
+ */
+ protected array $normalize = [
+ // General
+ 'general' => [
+ // target => source
+ 'hostname' => 'hostname',
+ 'mapname' => 'mapname',
+ 'maxplayers' => 'maxplayers',
+ 'numplayers' => 'numplayers',
+ 'password' => 'password',
+ ]
+ ];
+
+ /**
+ * Process the response from the EOS API
+ *
+ * @throws ProtocolException
+ */
+ public function processResponse(): array
+ {
+ $index = ($this->grant_type === 'external_auth') ? 2 : 1;
+ $server_data = isset($this->packets_response[$index]) ? json_decode($this->packets_response[$index], true) : null;
+
+ $server_data = isset($server_data['sessions']) ? $server_data['sessions'] : null;
+
+ // If no server data, throw an exception
+ if (empty($server_data)) {
+ throw new ProtocolException('No server data found. Server might be offline.');
+ }
+
+ return $server_data;
+ }
+
+ /**
+ * Called before sending the request
+ */
+ public function beforeSend(Server $server): void
+ {
+ $this->serverIp = $server->ip();
+ $this->serverPortQuery = $server->portQuery();
+
+ // Authenticate and get the access token
+ $auth_token = $this->authenticate();
+
+ if (!$auth_token) {
+ return;
+ }
+
+ // Query for server data
+ $this->queryServers($auth_token);
+ }
+
+ /**
+ * Authenticate to get the access token
+ */
+ protected function authenticate(): ?string
+ {
+ $auth_url = "https://api.epicgames.dev/auth/v1/oauth/token";
+ $auth_headers = [
+ 'Authorization: Basic ' . base64_encode("{$this->user_id}:{$this->user_secret}"),
+ 'Accept-Encoding: deflate, gzip',
+ 'Content-Type: application/x-www-form-urlencoded',
+ ];
+
+ $auth_postfields = "grant_type={$this->grant_type}&deployment_id={$this->deployment_id}";
+
+ if ($this->grant_type === 'external_auth') {
+ // Perform device authentication if necessary
+ $device_auth = $this->deviceAuthentication();
+ if (!$device_auth) {
+ return null;
+ }
+ $auth_postfields .= "&external_auth_type=deviceid_access_token"
+ . "&external_auth_token={$device_auth['access_token']}"
+ . "&nonce=ABCHFA3qgUCJ1XTPAoGDEF&display_name=User";
+ }
+
+ // Make the request to get the access token
+ $response = $this->httpRequest($auth_url, $auth_headers, $auth_postfields);
+
+ return isset($response['access_token']) ? $response['access_token'] : null;
+ }
+
+ /**
+ * Query the EOS server for matchmaking data
+ */
+ protected function queryServers(string $auth_token): ?array
+ {
+ $server_query_url = "https://api.epicgames.dev/matchmaking/v1/{$this->deployment_id}/filter";
+ $query_headers = [
+ "Authorization: Bearer {$auth_token}",
+ 'Accept: application/json',
+ 'Content-Type: application/json',
+ ];
+
+ $query_body = json_encode([
+ 'criteria' => [
+ [
+ 'key' => 'attributes.ADDRESS_s',
+ 'op' => 'EQUAL',
+ 'value' => $this->serverIp,
+ ],
+ ],
+ 'maxResults' => 200,
+ ]);
+
+ $response = $this->httpRequest($server_query_url, $query_headers, $query_body);
+
+ return isset($response['sessions']) ? $response['sessions'] : null;
+ }
+
+ /**
+ * Handle device authentication for external auth type
+ */
+ protected function deviceAuthentication(): ?array
+ {
+ $device_auth_url = "https://api.epicgames.dev/auth/v1/accounts/deviceid";
+ $device_auth_headers = [
+ 'Authorization: Basic ' . base64_encode("{$this->user_id}:{$this->user_secret}"),
+ 'Accept-Encoding: deflate, gzip',
+ 'Content-Type: application/x-www-form-urlencoded',
+ ];
+
+ $device_auth_postfields = "deviceModel=PC";
+
+ return $this->httpRequest($device_auth_url, $device_auth_headers, $device_auth_postfields);
+ }
+
+ /**
+ * Execute an HTTP request
+ */
+ protected function httpRequest(string $url, array $headers, string $postfields): ?array
+ {
+ $ch = curl_init();
+
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
+
+ $response = curl_exec($ch);
+
+ if (!$response) {
+ return null;
+ }
+
+ $this->packets_response[] = $response;
+
+ return json_decode($response, true);
+ }
+
+ /**
+ * Safely retrieves an attribute from an array or returns a default value.
+ */
+ protected function getAttribute(array $attributes, string $key, $default = null): mixed
+ {
+ return isset($attributes[$key]) ? $attributes[$key] : $default;
+ }
+}
diff --git a/src/GameQ/Protocols/Etqw.php b/src/GameQ/Protocols/Etqw.php
index 731210ef..015239d3 100644
--- a/src/GameQ/Protocols/Etqw.php
+++ b/src/GameQ/Protocols/Etqw.php
@@ -30,7 +30,6 @@
*/
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
@@ -109,9 +108,7 @@ public function processResponse(): mixed
return $this->{$this->responses[$response_type]}($buffer);
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handle processing the status response
diff --git a/src/GameQ/Protocols/Ffe.php b/src/GameQ/Protocols/Ffe.php
index f91d3dd7..68b93b4e 100644
--- a/src/GameQ/Protocols/Ffe.php
+++ b/src/GameQ/Protocols/Ffe.php
@@ -26,7 +26,6 @@
*/
class Ffe extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Ffow.php b/src/GameQ/Protocols/Ffow.php
index 4921dba7..a14be6a9 100644
--- a/src/GameQ/Protocols/Ffow.php
+++ b/src/GameQ/Protocols/Ffow.php
@@ -189,8 +189,7 @@ protected function processRules(Buffer $buffer)
// Check for map
if (str_contains($key, "Map:")) {
$result->addSub("maplist", "name", $buffer->readString());
- } else // Regular rule
- {
+ } else { // Regular rule
$result->add($key, $buffer->readString());
}
}
diff --git a/src/GameQ/Protocols/Gamespy.php b/src/GameQ/Protocols/Gamespy.php
index a092534f..4fef389e 100644
--- a/src/GameQ/Protocols/Gamespy.php
+++ b/src/GameQ/Protocols/Gamespy.php
@@ -21,6 +21,7 @@
use GameQ\Exception\ProtocolException;
use GameQ\Protocol;
use GameQ\Buffer;
+use GameQ\Helpers\Str;
use GameQ\Result;
/**
@@ -30,7 +31,6 @@
*/
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
@@ -92,9 +92,7 @@ public function processResponse(): mixed
return $this->processStatus(new Buffer(implode('', $processed)));
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handle processing the status buffer
@@ -143,7 +141,7 @@ protected function processStatus(Buffer $buffer)
if (str_starts_with($key, 'playername')) {
$numPlayers++;
}
- $result->addPlayer(substr($key, 0, $suffix), $this->convertToUtf8($val));
+ $result->addPlayer(substr($key, 0, $suffix), Str::isoToUtf8($val));
}
} else {
// Regular variable so just add the value.
diff --git a/src/GameQ/Protocols/Gamespy2.php b/src/GameQ/Protocols/Gamespy2.php
index 6a718f20..26657951 100644
--- a/src/GameQ/Protocols/Gamespy2.php
+++ b/src/GameQ/Protocols/Gamespy2.php
@@ -21,20 +21,20 @@
use GameQ\Exception\ProtocolException;
use GameQ\Protocol;
use GameQ\Buffer;
+use GameQ\Helpers\Str;
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.
+ * version returns all strings utf-8 encoded. To access the proper version of a
+ * string response you must use Str::utf8ToIso() on the specific response.
*
* @author Austin Bischoff
*/
class Gamespy2 extends Protocol
{
-
/**
* Define the state of this class
*/
@@ -105,7 +105,6 @@ class Gamespy2 extends Protocol
*/
public function processResponse(): mixed
{
-
// Will hold the packets after sorting
$packets = [];
@@ -143,9 +142,7 @@ public function processResponse(): mixed
return $results;
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handles processing the details data into a usable format
@@ -156,7 +153,6 @@ public function processResponse(): mixed
*/
protected function processDetails(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -166,7 +162,7 @@ protected function processDetails(Buffer $buffer)
if ($key === '') {
break;
}
- $result->add($key, $this->convertToUtf8($buffer->readString()));
+ $result->add($key, Str::isoToUtf8($buffer->readString()));
}
return $result->fetch();
@@ -181,7 +177,6 @@ protected function processDetails(Buffer $buffer)
*/
protected function processPlayers(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -204,7 +199,6 @@ protected function processPlayers(Buffer $buffer)
*/
protected function parsePlayerTeam(string $dataType, Buffer $buffer, Result $result)
{
-
// Do count
$result->add('num_' . $dataType, $buffer->readInt8());
@@ -231,7 +225,7 @@ protected function parsePlayerTeam(string $dataType, Buffer $buffer, Result $res
// Get the values
while ($buffer->getLength() > 4) {
foreach ($varNames as $varName) {
- $result->addSub($dataType, $this->convertToUtf8($varName), $this->convertToUtf8($buffer->readString()));
+ $result->addSub($dataType, Str::isoToUtf8($varName), Str::isoToUtf8($buffer->readString()));
}
if ($buffer->lookAhead() === "\x00") {
$buffer->skip();
diff --git a/src/GameQ/Protocols/Gamespy3.php b/src/GameQ/Protocols/Gamespy3.php
index 71a7fb28..315f9c08 100644
--- a/src/GameQ/Protocols/Gamespy3.php
+++ b/src/GameQ/Protocols/Gamespy3.php
@@ -21,20 +21,20 @@
use GameQ\Exception\ProtocolException;
use GameQ\Protocol;
use GameQ\Buffer;
+use GameQ\Helpers\Str;
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.
+ * version returns all strings utf-8 encoded. To access the proper version of a
+ * string response you must use Str::utf8ToIso() on the specific response.
*
* @author Austin Bischoff
*/
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
@@ -103,7 +103,6 @@ public function challengeParseAndApply(Buffer $challenge_buffer): bool
*/
public function processResponse(): mixed
{
-
// Holds the processed packets
$processed = [];
@@ -162,16 +161,13 @@ public function processResponse(): mixed
return $result->fetch();
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handles cleaning up packets since the responses can be a bit "dirty"
*/
protected function cleanPackets(array $packets = []): array
{
-
// Get the number of packets
$packetCount = count($packets);
@@ -230,7 +226,7 @@ protected function processDetails(Buffer $buffer, Result $result): void
if ($key === '') {
break;
}
- $result->add($key, $this->convertToUtf8($buffer->readString()));
+ $result->add($key, Str::isoToUtf8($buffer->readString()));
}
}
@@ -304,7 +300,7 @@ protected function processPlayersAndTeams(Buffer $buffer, Result $result): void
break;
}
// Add the value to the proper item in the correct group
- $result->addSub($item_group, $item_type, $this->convertToUtf8(trim($val)));
+ $result->addSub($item_group, $item_type, Str::isoToUtf8(trim($val)));
}
// Unset our buffer
unset($buf_temp);
diff --git a/src/GameQ/Protocols/Had2.php b/src/GameQ/Protocols/Had2.php
index e65bcd4e..c1fb3d6c 100644
--- a/src/GameQ/Protocols/Had2.php
+++ b/src/GameQ/Protocols/Had2.php
@@ -25,7 +25,6 @@
*/
class Had2 extends Gamespy2
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Halo.php b/src/GameQ/Protocols/Halo.php
index d1baf0be..adee9e3e 100644
--- a/src/GameQ/Protocols/Halo.php
+++ b/src/GameQ/Protocols/Halo.php
@@ -25,7 +25,6 @@
*/
class Halo extends Gamespy2
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Justcause3.php b/src/GameQ/Protocols/Justcause3.php
index cdc48409..2729fea7 100644
--- a/src/GameQ/Protocols/Justcause3.php
+++ b/src/GameQ/Protocols/Justcause3.php
@@ -26,7 +26,6 @@
*/
class Justcause3 extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Killingfloor.php b/src/GameQ/Protocols/Killingfloor.php
index b5660884..3827f30b 100644
--- a/src/GameQ/Protocols/Killingfloor.php
+++ b/src/GameQ/Protocols/Killingfloor.php
@@ -30,7 +30,6 @@
*/
class Killingfloor extends Unreal2
{
-
/**
* String name of this protocol class
*/
@@ -59,7 +58,6 @@ class Killingfloor extends Unreal2
*/
protected function processDetails(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -72,10 +70,10 @@ protected function processDetails(Buffer $buffer)
$buffer->skip();
// Read as a regular string since the length is incorrect (what we skipped earlier)
- $result->add('servername', $this->convertToUtf8($buffer->readString()));
+ $result->add('servername', Str::isoToUtf8($buffer->readString()));
// The rest is read as normal
- $result->add('mapname', $this->convertToUtf8($buffer->readPascalString(1)));
+ $result->add('mapname', Str::isoToUtf8($buffer->readPascalString(1)));
$result->add('gametype', $buffer->readPascalString(1));
$result->add('numplayers', $buffer->readInt32());
$result->add('maxplayers', $buffer->readInt32());
diff --git a/src/GameQ/Protocols/Killingfloor2.php b/src/GameQ/Protocols/Killingfloor2.php
index c3203841..44324f71 100644
--- a/src/GameQ/Protocols/Killingfloor2.php
+++ b/src/GameQ/Protocols/Killingfloor2.php
@@ -26,7 +26,6 @@
*/
class Killingfloor2 extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Lhmp.php b/src/GameQ/Protocols/Lhmp.php
index 488385b0..11d794cb 100644
--- a/src/GameQ/Protocols/Lhmp.php
+++ b/src/GameQ/Protocols/Lhmp.php
@@ -32,7 +32,6 @@
*/
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
@@ -136,9 +135,7 @@ public function processResponse(): mixed
return $results;
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handles processing the details data into a usable format
@@ -148,7 +145,6 @@ public function processResponse(): mixed
*/
protected function processDetails(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -156,10 +152,10 @@ protected function processDetails(Buffer $buffer)
$result->add('password', $buffer->readString());
$result->add('numplayers', $buffer->readInt16());
$result->add('maxplayers', $buffer->readInt16());
- $result->add('servername', $this->convertToUtf8($buffer->readPascalString()));
+ $result->add('servername', Str::isoToUtf8($buffer->readPascalString()));
$result->add('gamemode', $buffer->readPascalString());
- $result->add('website', $this->convertToUtf8($buffer->readPascalString()));
- $result->add('mapname', $this->convertToUtf8($buffer->readPascalString()));
+ $result->add('website', Str::isoToUtf8($buffer->readPascalString()));
+ $result->add('mapname', Str::isoToUtf8($buffer->readPascalString()));
return $result->fetch();
}
@@ -172,7 +168,6 @@ protected function processDetails(Buffer $buffer)
*/
protected function processPlayers(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -185,7 +180,7 @@ protected function processPlayers(Buffer $buffer)
if (($id = $buffer->readInt16()) !== 0) {
// Add the results
$result->addPlayer('id', $id);
- $result->addPlayer('name', $this->convertToUtf8($buffer->readPascalString()));
+ $result->addPlayer('name', Str::isoToUtf8($buffer->readPascalString()));
}
}
diff --git a/src/GameQ/Protocols/M2mp.php b/src/GameQ/Protocols/M2mp.php
index bc436273..d9c58df3 100644
--- a/src/GameQ/Protocols/M2mp.php
+++ b/src/GameQ/Protocols/M2mp.php
@@ -124,6 +124,7 @@ public function processResponse(): mixed
* Process the status response
*
* @return array
+ * @throws ProtocolException
*/
protected function processStatus(Buffer $buffer)
{
@@ -182,7 +183,7 @@ protected function processPlayers(Buffer $buffer)
// Only player name information is available
// Add player name, encoded
- $result->addPlayer('name', $this->convertToUtf8(trim($buffer->readPascalString(1, true))));
+ $result->addPlayer('name', Str::isoToUtf8(trim($buffer->readPascalString(1, true))));
}
return $result->fetch();
diff --git a/src/GameQ/Protocols/Minecraft.php b/src/GameQ/Protocols/Minecraft.php
index d1fa4fa5..2dc6d28b 100644
--- a/src/GameQ/Protocols/Minecraft.php
+++ b/src/GameQ/Protocols/Minecraft.php
@@ -40,7 +40,6 @@
*/
class Minecraft extends Gamespy3
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Minecraftbe.php b/src/GameQ/Protocols/Minecraftbe.php
index 298238a9..0469212d 100644
--- a/src/GameQ/Protocols/Minecraftbe.php
+++ b/src/GameQ/Protocols/Minecraftbe.php
@@ -27,7 +27,6 @@
*/
class Minecraftbe extends Raknet
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Minecraftpe.php b/src/GameQ/Protocols/Minecraftpe.php
index dc0496df..1a6fe826 100644
--- a/src/GameQ/Protocols/Minecraftpe.php
+++ b/src/GameQ/Protocols/Minecraftpe.php
@@ -27,7 +27,6 @@
*/
class Minecraftpe extends Minecraft
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Mordhau.php b/src/GameQ/Protocols/Mordhau.php
index dec895ba..68300e7a 100644
--- a/src/GameQ/Protocols/Mordhau.php
+++ b/src/GameQ/Protocols/Mordhau.php
@@ -26,7 +26,6 @@
*/
class Mordhau extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Mta.php b/src/GameQ/Protocols/Mta.php
index da8d5282..80ad6f3c 100644
--- a/src/GameQ/Protocols/Mta.php
+++ b/src/GameQ/Protocols/Mta.php
@@ -28,7 +28,6 @@
*/
class Mta extends Ase
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Mumble.php b/src/GameQ/Protocols/Mumble.php
index b679d28e..3f9e58e9 100644
--- a/src/GameQ/Protocols/Mumble.php
+++ b/src/GameQ/Protocols/Mumble.php
@@ -33,7 +33,6 @@
*/
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
@@ -144,9 +143,7 @@ public function processResponse(): mixed
return $result->fetch();
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handles processing the the channels and user info
diff --git a/src/GameQ/Protocols/Openttd.php b/src/GameQ/Protocols/Openttd.php
index 623b256a..e6bc3bb8 100644
--- a/src/GameQ/Protocols/Openttd.php
+++ b/src/GameQ/Protocols/Openttd.php
@@ -123,7 +123,7 @@ protected function processServerInfo(Buffer $buffer)
switch ($protocol_version) {
case 4:
- $num_grfs = $buffer->readInt8(); #number of grfs
+ $num_grfs = $buffer->readInt8(); //number of grfs
$result->add('num_grfs', $num_grfs);
//$buffer->skip ($num_grfs * 20); #skip grfs id and md5 hash
@@ -131,16 +131,18 @@ protected function processServerInfo(Buffer $buffer)
$result->add('grfs_'.$i.'_ID', strtoupper(bin2hex($buffer->read(4))));
$result->add('grfs_'.$i.'_MD5', strtoupper(bin2hex($buffer->read(16))));
}
- // No break, cascades all the down even if case is meet
+ // no break, cascades all the down even if case is meet
case 3:
$result->add('game_date', $buffer->readInt32());
$result->add('start_date', $buffer->readInt32());
// Cascades all the way down even if case is meet
+ // no break
case 2:
$result->add('companies_max', $buffer->readInt8());
$result->add('companies_on', $buffer->readInt8());
$result->add('spectators_max', $buffer->readInt8());
// Cascades all the way down even if case is meet
+ // no break
case 1:
$result->add('hostname', $buffer->readString());
$result->add('version', $buffer->readString());
@@ -154,7 +156,7 @@ protected function processServerInfo(Buffer $buffer)
$result->add('clients', $buffer->readInt8());
$result->add('spectators', $buffer->readInt8());
if ($protocol_version < 3) {
- $days = ( 365 * 1920 + 1920 / 4 - 1920 / 100 + 1920 / 400 );
+ $days = (365 * 1920 + 1920 / 4 - 1920 / 100 + 1920 / 400);
$result->add('game_date', $buffer->readInt16() + $days);
$result->add('start_date', $buffer->readInt16() + $days);
}
diff --git a/src/GameQ/Protocols/Pixark.php b/src/GameQ/Protocols/Pixark.php
index 69d47d7d..4c5873e6 100644
--- a/src/GameQ/Protocols/Pixark.php
+++ b/src/GameQ/Protocols/Pixark.php
@@ -26,7 +26,6 @@
*/
class Pixark extends Arkse
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Projectrealitybf2.php b/src/GameQ/Protocols/Projectrealitybf2.php
index 271fc43a..a9fe40c8 100644
--- a/src/GameQ/Protocols/Projectrealitybf2.php
+++ b/src/GameQ/Protocols/Projectrealitybf2.php
@@ -28,7 +28,6 @@
*/
class Projectrealitybf2 extends Bf2
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Quake2.php b/src/GameQ/Protocols/Quake2.php
index 01913e73..007b8565 100644
--- a/src/GameQ/Protocols/Quake2.php
+++ b/src/GameQ/Protocols/Quake2.php
@@ -134,7 +134,7 @@ protected function processServerInfo(Buffer $buffer)
// Add result
$result->add(
trim($buffer->readString('\\')),
- $this->convertToUtf8(trim($buffer->readStringMulti(['\\', "\x0a"])))
+ Str::isoToUtf8(trim($buffer->readStringMulti(['\\', "\x0a"])))
);
}
@@ -171,7 +171,7 @@ protected function processPlayers(Buffer $buffer)
$playerInfo->skip();
// Add player name, encoded
- $result->addPlayer('name', $this->convertToUtf8(trim(($playerInfo->readString('"')))));
+ $result->addPlayer('name', Str::isoToUtf8(trim(($playerInfo->readString('"')))));
// Skip first "
$playerInfo->skip(2);
diff --git a/src/GameQ/Protocols/Quake3.php b/src/GameQ/Protocols/Quake3.php
index 6f2c36ed..e6c1bed2 100644
--- a/src/GameQ/Protocols/Quake3.php
+++ b/src/GameQ/Protocols/Quake3.php
@@ -98,6 +98,10 @@ public function processResponse(): mixed
return $this->{$this->responses[$header]}($buffer);
}
+ /**
+ * @return array
+ * @throws ProtocolException
+ */
protected function processStatus(Buffer $buffer)
{
// We need to split the data and offload
@@ -127,7 +131,7 @@ protected function processServerInfo(Buffer $buffer)
// Add result
$result->add(
trim($buffer->readString('\\')),
- $this->convertToUtf8(trim($buffer->readStringMulti(['\\', "\x0a"])))
+ Str::isoToUtf8(trim($buffer->readStringMulti(['\\', "\x0a"])))
);
}
@@ -171,7 +175,7 @@ protected function processPlayers(Buffer $buffer)
}
// Add player name, encoded
- $result->addPlayer('name', $this->convertToUtf8(trim($buffer->readString('"'))));
+ $result->addPlayer('name', Str::isoToUtf8(trim($buffer->readString('"'))));
// Burn ending delimiter
$buffer->read();
diff --git a/src/GameQ/Protocols/Quake4.php b/src/GameQ/Protocols/Quake4.php
index 5080764b..73689bfd 100644
--- a/src/GameQ/Protocols/Quake4.php
+++ b/src/GameQ/Protocols/Quake4.php
@@ -63,7 +63,7 @@ protected function processPlayers(Buffer $buffer)
$result->addPlayer('ping', $buffer->readInt16());
$result->addPlayer('rate', $buffer->readInt32());
// Add player name, encoded
- $result->addPlayer('name', $this->convertToUtf8(trim($buffer->readString())));
+ $result->addPlayer('name', Str::isoToUtf8(trim($buffer->readString())));
$result->addPlayer('clantag', $buffer->readString());
// Increment
$playerCount++;
diff --git a/src/GameQ/Protocols/Risingstorm2.php b/src/GameQ/Protocols/Risingstorm2.php
index feb4a4e0..5bee0674 100644
--- a/src/GameQ/Protocols/Risingstorm2.php
+++ b/src/GameQ/Protocols/Risingstorm2.php
@@ -26,7 +26,6 @@
*/
class Risingstorm2 extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Rust.php b/src/GameQ/Protocols/Rust.php
index 30cb3415..c3ece2ae 100644
--- a/src/GameQ/Protocols/Rust.php
+++ b/src/GameQ/Protocols/Rust.php
@@ -29,7 +29,6 @@
*/
class Rust extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Samp.php b/src/GameQ/Protocols/Samp.php
index cbeb073d..526c34a2 100644
--- a/src/GameQ/Protocols/Samp.php
+++ b/src/GameQ/Protocols/Samp.php
@@ -20,6 +20,7 @@
use GameQ\Protocol;
use GameQ\Buffer;
+use GameQ\Helpers\Str;
use GameQ\Result;
use GameQ\Server;
use GameQ\Exception\ProtocolException;
@@ -34,7 +35,6 @@
*/
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
@@ -127,7 +127,6 @@ public function beforeSend(Server $server): void
*/
public function processResponse(): mixed
{
-
// Results that will be returned
$results = [];
@@ -169,9 +168,7 @@ public function processResponse(): mixed
return $results;
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handles processing the server status data
@@ -181,7 +178,6 @@ public function processResponse(): mixed
*/
protected function processStatus(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -194,7 +190,7 @@ protected function processStatus(Buffer $buffer)
$result->add('max_players', $buffer->readInt16());
// These are read differently for these last 3
- $result->add('servername', $this->convertToUtf8($buffer->read($buffer->readInt32())));
+ $result->add('servername', Str::isoToUtf8($buffer->read($buffer->readInt32())));
$result->add('gametype', $buffer->read($buffer->readInt32()));
$result->add('language', $buffer->read($buffer->readInt32()));
@@ -209,7 +205,6 @@ protected function processStatus(Buffer $buffer)
*/
protected function processPlayers(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -219,7 +214,7 @@ protected function processPlayers(Buffer $buffer)
// Run until we run out of buffer
while ($buffer->getLength()) {
$result->addPlayer('id', $buffer->readInt8());
- $result->addPlayer('name', $this->convertToUtf8($buffer->readPascalString()));
+ $result->addPlayer('name', Str::isoToUtf8($buffer->readPascalString()));
$result->addPlayer('score', $buffer->readInt32());
$result->addPlayer('ping', $buffer->readInt32());
}
@@ -235,7 +230,6 @@ protected function processPlayers(Buffer $buffer)
*/
protected function processRules(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
diff --git a/src/GameQ/Protocols/Serioussam.php b/src/GameQ/Protocols/Serioussam.php
index 5a192866..ad68512a 100644
--- a/src/GameQ/Protocols/Serioussam.php
+++ b/src/GameQ/Protocols/Serioussam.php
@@ -25,7 +25,6 @@
*/
class Serioussam extends Gamespy
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Ship.php b/src/GameQ/Protocols/Ship.php
index be73c911..33749f9e 100644
--- a/src/GameQ/Protocols/Ship.php
+++ b/src/GameQ/Protocols/Ship.php
@@ -32,7 +32,6 @@
*/
class Ship extends Source
{
-
/**
* String name of this protocol class
*/
@@ -53,7 +52,6 @@ class Ship extends Source
*/
protected function processPlayers(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
diff --git a/src/GameQ/Protocols/Soldat.php b/src/GameQ/Protocols/Soldat.php
index 68fc9086..6074c936 100644
--- a/src/GameQ/Protocols/Soldat.php
+++ b/src/GameQ/Protocols/Soldat.php
@@ -28,7 +28,6 @@
*/
class Soldat extends Ase
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Source.php b/src/GameQ/Protocols/Source.php
index 7b635b82..7c17ec7a 100644
--- a/src/GameQ/Protocols/Source.php
+++ b/src/GameQ/Protocols/Source.php
@@ -118,7 +118,6 @@ class Source extends Protocol
*/
public function challengeParseAndApply(Buffer $challenge_buffer): bool
{
-
// Skip the header
$challenge_buffer->skip(4);
@@ -206,22 +205,18 @@ public function processResponse(): mixed
return $results;
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Process the split packets and decompress if necessary
*
* @param $packet_id
* @param array $packets
- *
* @return string
* @throws ProtocolException
*/
protected function processPackets($packet_id, array $packets = [])
{
-
// Init array so we can order
$packs = [];
@@ -316,7 +311,6 @@ protected function processPackets($packet_id, array $packets = [])
*/
protected function processDetails(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -385,7 +379,6 @@ protected function processDetails(Buffer $buffer)
*/
protected function processDetailsGoldSource(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -429,7 +422,6 @@ protected function processDetailsGoldSource(Buffer $buffer)
*/
protected function processPlayers(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -463,7 +455,6 @@ protected function processPlayers(Buffer $buffer)
*/
protected function processRules(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
diff --git a/src/GameQ/Protocols/Squad.php b/src/GameQ/Protocols/Squad.php
index d35396eb..077e9af8 100644
--- a/src/GameQ/Protocols/Squad.php
+++ b/src/GameQ/Protocols/Squad.php
@@ -28,7 +28,6 @@
*/
class Squad extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Starmade.php b/src/GameQ/Protocols/Starmade.php
index d9394fec..71cadc66 100644
--- a/src/GameQ/Protocols/Starmade.php
+++ b/src/GameQ/Protocols/Starmade.php
@@ -34,7 +34,6 @@
*/
class Starmade extends Protocol
{
-
/**
* Array of packets we want to query.
*/
@@ -90,7 +89,6 @@ class Starmade extends Protocol
*/
public function processResponse(): mixed
{
-
// 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);
@@ -142,7 +140,6 @@ public function processResponse(): mixed
*/
protected function parseServerParameters(Buffer $buffer)
{
-
// Init the parsed data array
$parsed = [];
@@ -160,17 +157,17 @@ protected function parseServerParameters(Buffer $buffer)
$parsed[$i] = $buffer->readInt32Signed();
break;
- // 64-bit int
+ // 64-bit int
case 2:
$parsed[$i] = $buffer->readInt64();
break;
- // Float
+ // Float
case 3:
$parsed[$i] = $buffer->readFloat32();
break;
- // String
+ // String
case 4:
// The first 2 bytes are the string length
$strLength = $buffer->readInt16Signed();
@@ -181,22 +178,22 @@ protected function parseServerParameters(Buffer $buffer)
unset($strLength);
break;
- // Boolean
+ // Boolean
case 5:
$parsed[$i] = (bool)$buffer->readInt8Signed();
break;
- // 8-bit int
+ // 8-bit int
case 6:
$parsed[$i] = $buffer->readInt8Signed();
break;
- // 16-bit int
+ // 16-bit int
case 7:
$parsed[$i] = $buffer->readInt16Signed();
break;
- // Array
+ // Array
case 8:
// Not implemented
throw new ProtocolException("StarMade array parsing is not implemented!");
diff --git a/src/GameQ/Protocols/Stationeers.php b/src/GameQ/Protocols/Stationeers.php
new file mode 100644
index 00000000..2296dbcd
--- /dev/null
+++ b/src/GameQ/Protocols/Stationeers.php
@@ -0,0 +1,178 @@
+.
+ */
+
+namespace GameQ\Protocols;
+
+use GameQ\Exception\ProtocolException;
+use GameQ\Helpers\Arr;
+use GameQ\Result;
+use GameQ\Server;
+
+/**
+ * Stationeers Protocol Class
+ *
+ * **Note:** This protocol does use the offical, centralized "Metaserver" to query the list of all available servers. This
+ * is effectively a host controlled by a third party which could interfere with the functionality of this protocol.
+ *
+ * @author Austin Bischoff
+ */
+class Stationeers extends Http
+{
+ /**
+ * The host (address) of the "Metaserver" to query to get the list of servers
+ */
+ const SERVER_LIST_HOST = '40.82.200.175';
+
+ /**
+ * The port of the "Metaserver" to query to get the list of servers
+ */
+ const SERVER_LIST_PORT = 8081;
+
+ /**
+ * Packets to send
+ */
+ protected array $packets = [
+ self::PACKET_STATUS => "GET /list HTTP/1.0\r\nAccept: */*\r\n\r\n",
+ ];
+
+ /**
+ * The protocol being used
+ */
+ protected string $protocol = 'stationeers';
+
+ /**
+ * String name of this protocol class
+ */
+ protected string $name = 'stationeers';
+
+ /**
+ * Longer string name of this protocol class
+ */
+ protected string $name_long = "Stationeers";
+
+ /**
+ * Normalize some items
+ */
+ protected array $normalize = [
+ // General
+ 'general' => [
+ // target => source
+ 'dedicated' => 'dedicated',
+ 'hostname' => 'hostname',
+ 'mapname' => 'map',
+ 'maxplayers' => 'maxplayers',
+ 'numplayers' => 'numplayers',
+ 'password' => 'password',
+ ],
+ ];
+
+ /**
+ * Holds the real ip so we can overwrite it back
+ *
+ * **NOTE:** These is used during the runtime.
+ */
+ protected ?string $realIp = null;
+
+ /**
+ * Holds the real port so we can overwrite it back
+ *
+ * **NOTE:** These is used during the runtime.
+ *
+ * @var int
+ */
+ protected ?string $realPortQuery = null;
+
+ /**
+ * Handle changing the call to call a central server rather than the server directly
+ */
+ public function beforeSend(Server $server): void
+ {
+ // Determine the connection information to be used for the "Metaserver"
+ $metaServerHost = $server->getOption('meta_host') ? $server->getOption('meta_host') : self::SERVER_LIST_HOST;
+ $metaServerPort = $server->getOption('meta_port') ? $server->getOption('meta_port') : self::SERVER_LIST_PORT;
+
+ // Save the real connection information and overwrite the properties with the "Metaserver" connection information
+ Arr::shift($this->realIp, $server->ip, $metaServerHost);
+ Arr::shift($this->realPortQuery, $server->port_query, $metaServerPort);
+ }
+
+ /**
+ * Process the response
+ *
+ * @throws ProtocolException
+ */
+ public function processResponse(): array
+ {
+ // Ensure there is a reply from the "Metaserver"
+ 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 ProtocolException(__METHOD__ . " JSON response from Stationeers Metaserver is invalid.");
+ }
+
+ // By default no server is found
+ $server = null;
+
+ // Find the server on this list by iterating over the entire list.
+ foreach ($json->GameSessions as $serverEntry) {
+ // Server information passed matches an entry on this list
+ if ($serverEntry->Address === $this->realIp && (int)$serverEntry->Port === $this->realPortQuery) {
+ $server = $serverEntry;
+ break;
+ }
+ }
+
+ // Send to the garbage collector
+ unset($matches, $serverEntry, $json);
+
+ // Ensure the provided Server has been found in the list provided by the "Metaserver"
+ if (! $server) {
+ throw new ProtocolException(sprintf(
+ '%s Unable to find the server "%s:%d" in the Stationeer Metaservers server list',
+ __METHOD__,
+ $this->realIp,
+ $this->realPortQuery
+ ));
+ }
+
+ // Build the Result from the parsed JSON
+ $result = new Result();
+ $result->add('dedicated', 1); // Server is always dedicated
+ $result->add('hostname', $server->Name);
+ $result->add('gq_address', $server->Address);
+ $result->add('gq_port_query', $server->Port);
+ $result->add('version', $server->Version);
+ $result->add('map', $server->MapName);
+ $result->add('uptime', $server->UpTime);
+ $result->add('password', (int)$server->Password);
+ $result->add('numplayers', $server->Players);
+ $result->add('maxplayers', $server->MaxPlayers);
+ $result->add('type', $server->Type);
+
+ // Send to the garbage collector
+ unset($server);
+
+ return $result->fetch();
+ }
+}
diff --git a/src/GameQ/Protocols/Teamspeak2.php b/src/GameQ/Protocols/Teamspeak2.php
index 58ad5e91..44f6a5f9 100644
--- a/src/GameQ/Protocols/Teamspeak2.php
+++ b/src/GameQ/Protocols/Teamspeak2.php
@@ -20,6 +20,7 @@
use GameQ\Protocol;
use GameQ\Buffer;
+use GameQ\Helpers\Str;
use GameQ\Result;
use GameQ\Server;
use GameQ\Exception\ProtocolException;
@@ -36,7 +37,6 @@
*/
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
@@ -104,7 +104,6 @@ class Teamspeak2 extends Protocol
*/
public function beforeSend(Server $server): void
{
-
// 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])
@@ -127,7 +126,6 @@ public function beforeSend(Server $server): void
*/
public function processResponse(): mixed
{
-
// Make a new buffer out of all of the packets
$buffer = new Buffer(implode('', $this->packets_response));
@@ -173,9 +171,7 @@ public function processResponse(): mixed
return $result->fetch();
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
@@ -200,7 +196,7 @@ protected function processDetails(string $data, Result $result)
list($key, $value) = explode('=', $row, 2);
// Add this to the result
- $result->add($key, $this->convertToUtf8($value));
+ $result->add($key, Str::isoToUtf8($value));
}
unset($buffer, $row, $key, $value);
@@ -229,7 +225,7 @@ protected function processChannels(string $data, Result $result)
foreach ($data as $key => $value) {
// Now add the data to the result
- $result->addTeam($key, $this->convertToUtf8($value));
+ $result->addTeam($key, Str::isoToUtf8($value));
}
}
@@ -259,7 +255,7 @@ protected function processPlayers(string $data, Result $result)
foreach ($data as $key => $value) {
// Now add the data to the result
- $result->addPlayer($key, $this->convertToUtf8($value));
+ $result->addPlayer($key, Str::isoToUtf8($value));
}
}
diff --git a/src/GameQ/Protocols/Teamspeak3.php b/src/GameQ/Protocols/Teamspeak3.php
index 2176c201..f0ef39f5 100644
--- a/src/GameQ/Protocols/Teamspeak3.php
+++ b/src/GameQ/Protocols/Teamspeak3.php
@@ -20,6 +20,7 @@
use GameQ\Protocol;
use GameQ\Buffer;
+use GameQ\Helpers\Str;
use GameQ\Result;
use GameQ\Server;
use GameQ\Exception\ProtocolException;
@@ -36,7 +37,6 @@
*/
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
@@ -104,7 +104,6 @@ class Teamspeak3 extends Protocol
*/
public function beforeSend(Server $server): void
{
-
// 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])
@@ -127,7 +126,6 @@ public function beforeSend(Server $server): void
*/
public function processResponse(): mixed
{
-
// Make a new buffer out of all of the packets
$buffer = new Buffer(implode('', $this->packets_response));
@@ -187,9 +185,7 @@ public function processResponse(): mixed
return $result->fetch();
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Process the properties of the data.
@@ -197,12 +193,10 @@ public function processResponse(): mixed
* 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 = [];
@@ -215,7 +209,7 @@ protected function processProperties($data)
[$key, $value] = array_pad(explode('=', $item, 2), 2, '');
// Convert spaces and other character changes
- $properties[$key] = $this->convertToUtf8(str_replace(
+ $properties[$key] = Str::isoToUtf8(str_replace(
[
'\\s', // Translate spaces
],
diff --git a/src/GameQ/Protocols/Teeworlds.php b/src/GameQ/Protocols/Teeworlds.php
index 1683fa23..85afd717 100644
--- a/src/GameQ/Protocols/Teeworlds.php
+++ b/src/GameQ/Protocols/Teeworlds.php
@@ -33,7 +33,6 @@
*/
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
@@ -131,6 +130,7 @@ public function processResponse(): mixed
* Handle processing all of the data returned
*
* @return array
+ * @throws ProtocolException
*/
protected function processAll(Buffer $buffer)
{
diff --git a/src/GameQ/Protocols/Terraria.php b/src/GameQ/Protocols/Terraria.php
index 717de08d..9a0c9be3 100644
--- a/src/GameQ/Protocols/Terraria.php
+++ b/src/GameQ/Protocols/Terraria.php
@@ -27,7 +27,6 @@
*/
class Terraria extends Tshock
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Theforrest.php b/src/GameQ/Protocols/Theforrest.php
index 6b591020..2c6013ac 100644
--- a/src/GameQ/Protocols/Theforrest.php
+++ b/src/GameQ/Protocols/Theforrest.php
@@ -26,7 +26,6 @@
*/
class Theforrest extends Source
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Tibia.php b/src/GameQ/Protocols/Tibia.php
index 038fe450..0b10968a 100644
--- a/src/GameQ/Protocols/Tibia.php
+++ b/src/GameQ/Protocols/Tibia.php
@@ -34,7 +34,6 @@
*/
class Tibia extends Protocol
{
-
/**
* Array of packets we want to query.
*/
diff --git a/src/GameQ/Protocols/Unreal2.php b/src/GameQ/Protocols/Unreal2.php
index 04c2986d..e59d35c6 100644
--- a/src/GameQ/Protocols/Unreal2.php
+++ b/src/GameQ/Protocols/Unreal2.php
@@ -30,7 +30,6 @@
*/
class Unreal2 extends Protocol
{
-
/**
* Array of packets we want to look up.
* Each key should correspond to a defined method in this or a parent class
@@ -96,7 +95,6 @@ class Unreal2 extends Protocol
*/
public function processResponse(): mixed
{
-
// Will hold the packets after sorting
$packets = [];
@@ -134,9 +132,7 @@ public function processResponse(): mixed
return $results;
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Handles processing the details data into a usable format
@@ -147,7 +143,6 @@ public function processResponse(): mixed
*/
protected function processDetails(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -155,8 +150,8 @@ protected function processDetails(Buffer $buffer)
$result->add('serverip', $buffer->readPascalString(1)); // empty
$result->add('gameport', $buffer->readInt32());
$result->add('queryport', $buffer->readInt32()); // 0
- $result->add('servername', $this->convertToUtf8($buffer->readPascalString(1)));
- $result->add('mapname', $this->convertToUtf8($buffer->readPascalString(1)));
+ $result->add('servername', Str::isoToUtf8($buffer->readPascalString(1)));
+ $result->add('mapname', Str::isoToUtf8($buffer->readPascalString(1)));
$result->add('gametype', $buffer->readPascalString(1));
$result->add('numplayers', $buffer->readInt32());
$result->add('maxplayers', $buffer->readInt32());
@@ -173,7 +168,6 @@ protected function processDetails(Buffer $buffer)
*/
protected function processPlayers(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -183,7 +177,7 @@ protected function processPlayers(Buffer $buffer)
if (($id = $buffer->readInt32()) !== 0) {
// Add the results
$result->addPlayer('id', $id);
- $result->addPlayer('name', $this->convertToUtf8($buffer->readPascalString(1)));
+ $result->addPlayer('name', Str::isoToUtf8($buffer->readPascalString(1)));
$result->addPlayer('ping', $buffer->readInt32());
$result->addPlayer('score', $buffer->readInt32());
@@ -205,7 +199,6 @@ protected function processPlayers(Buffer $buffer)
*/
protected function processRules(Buffer $buffer)
{
-
// Set the result to a new result instance
$result = new Result();
@@ -220,7 +213,7 @@ protected function processRules(Buffer $buffer)
$key .= ++$inc;
}
- $result->add(strtolower($key), $this->convertToUtf8($buffer->readPascalString(1)));
+ $result->add(strtolower($key), Str::isoToUtf8($buffer->readPascalString(1)));
}
return $result->fetch();
diff --git a/src/GameQ/Protocols/Ut.php b/src/GameQ/Protocols/Ut.php
index 0f385e79..45488426 100644
--- a/src/GameQ/Protocols/Ut.php
+++ b/src/GameQ/Protocols/Ut.php
@@ -25,7 +25,6 @@
*/
class Ut extends Gamespy
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Ut2004.php b/src/GameQ/Protocols/Ut2004.php
index b87bec36..f11b08ef 100644
--- a/src/GameQ/Protocols/Ut2004.php
+++ b/src/GameQ/Protocols/Ut2004.php
@@ -25,7 +25,6 @@
*/
class Ut2004 extends Unreal2
{
-
/**
* String name of this protocol class
*/
diff --git a/src/GameQ/Protocols/Ut3.php b/src/GameQ/Protocols/Ut3.php
index 0e174fb6..7c7f65d3 100644
--- a/src/GameQ/Protocols/Ut3.php
+++ b/src/GameQ/Protocols/Ut3.php
@@ -29,7 +29,6 @@
*/
class Ut3 extends Gamespy3
{
-
/**
* String name of this protocol class
*/
@@ -59,7 +58,6 @@ class Ut3 extends Gamespy3
*/
public function processResponse(): mixed
{
-
// Grab the result from the parent
$result = parent::processResponse();
@@ -98,7 +96,6 @@ public function processResponse(): mixed
*/
protected function renameResult(array &$result, string $old, string $new): void
{
-
// Check to see if the old item is there
if (isset($result[$old])) {
$result[$new] = $result[$old];
@@ -111,7 +108,6 @@ protected function renameResult(array &$result, string $old, string $new): void
*/
protected function deleteResult(array &$result, array $array): void
{
-
foreach ($array as $key) {
unset($result[$key]);
}
diff --git a/src/GameQ/Protocols/Ventrilo.php b/src/GameQ/Protocols/Ventrilo.php
index c3df159e..907a5792 100644
--- a/src/GameQ/Protocols/Ventrilo.php
+++ b/src/GameQ/Protocols/Ventrilo.php
@@ -36,7 +36,6 @@
*/
class Ventrilo extends Protocol
{
-
/**
* Array of packets we want to look up.
* Each key should correspond to a defined method in this or a parent class
@@ -92,10 +91,8 @@ class Ventrilo extends Protocol
/**
* Encryption table for the header
- *
- * @type array
*/
- private $head_encrypt_table = [
+ private array $head_encrypt_table = [
0x80,
0xe5,
0x0e,
@@ -356,10 +353,8 @@ class Ventrilo extends Protocol
/**
* Encryption table for the data
- *
- * @type array
*/
- private $data_encrypt_table = [
+ private array $data_encrypt_table = [
0x82,
0x8b,
0x7f,
@@ -626,7 +621,6 @@ class Ventrilo extends Protocol
*/
public function processResponse(): mixed
{
-
// We need to decrypt the packets
$decrypted = $this->decryptPackets($this->packets_response);
@@ -699,19 +693,19 @@ static function ($matches) {
$this->processChannel($value, $channelFields, $result);
break;
- // Find the number of fields for the channels
+ // Find the number of fields for the channels
case 'channelfields':
$channelFields = count(explode(',', $value));
break;
- // Find the number of fields for the players
+ // Find the number of fields for the players
case 'clientfields':
$playerFields = count(explode(',', $value));
break;
- // By default we just add they key as an item
+ // By default we just add they key as an item
default:
- $result->add($key, $this->convertToUtf8($value));
+ $result->add($key, Str::isoToUtf8($value));
break;
}
}
@@ -722,9 +716,7 @@ static function ($matches) {
return $result->fetch();
}
- /*
- * Internal methods
- */
+ // Internal methods
/**
* Decrypt the incoming packets
@@ -734,12 +726,11 @@ static function ($matches) {
*/
protected function decryptPackets(array $packets = [])
{
-
// This will be returned
$decrypted = [];
foreach ($packets as $packet) {
- # Header :
+ // Header :
$header = substr($packet, 0, 20);
$header_items = [];
@@ -789,7 +780,7 @@ protected function decryptPackets(array $packets = [])
throw new ProtocolException(__METHOD__ . ": Too few packets received");
}
- # Data :
+ // Data :
$table = $this->data_encrypt_table;
$a1 = $header_items['datakey'] & 0xFF;
$a2 = $header_items['datakey'] >> 8;
@@ -822,7 +813,6 @@ protected function decryptPackets(array $packets = [])
*/
protected function processChannel(string $data, int $fieldCount, Result $result)
{
-
// Split the items on the comma
$items = explode(",", $data, $fieldCount);
@@ -831,7 +821,7 @@ protected function processChannel(string $data, int $fieldCount, Result $result)
// Split the key=value pair
list($key, $value) = explode("=", $item, 2);
- $result->addTeam(strtolower($key), $this->convertToUtf8($value));
+ $result->addTeam(strtolower($key), Str::isoToUtf8($value));
}
}
@@ -840,7 +830,6 @@ protected function processChannel(string $data, int $fieldCount, Result $result)
*/
protected function processPlayer(string $data, int $fieldCount, Result $result)
{
-
// Split the items on the comma
$items = explode(",", $data, $fieldCount);
@@ -849,7 +838,7 @@ protected function processPlayer(string $data, int $fieldCount, Result $result)
// Split the key=value pair
list($key, $value) = explode("=", $item, 2);
- $result->addPlayer(strtolower($key), $this->convertToUtf8($value));
+ $result->addPlayer(strtolower($key), Str::isoToUtf8($value));
}
}
}
diff --git a/src/GameQ/Protocols/Warsow.php b/src/GameQ/Protocols/Warsow.php
index fdf481e8..3236af36 100644
--- a/src/GameQ/Protocols/Warsow.php
+++ b/src/GameQ/Protocols/Warsow.php
@@ -69,7 +69,7 @@ protected function processPlayers(Buffer $buffer)
$playerInfo->skip();
// Add player name, encoded
- $result->addPlayer('name', $this->convertToUtf8(trim(($playerInfo->readString('"')))));
+ $result->addPlayer('name', Str::isoToUtf8(trim(($playerInfo->readString('"')))));
// Skip space
$playerInfo->skip();
diff --git a/src/GameQ/Protocols/Won.php b/src/GameQ/Protocols/Won.php
index a047648b..6edac29d 100644
--- a/src/GameQ/Protocols/Won.php
+++ b/src/GameQ/Protocols/Won.php
@@ -30,7 +30,6 @@
*/
class Won extends Source
{
-
/**
* Array of packets we want to look up.
* Each key should correspond to a defined method in this or a parent class
diff --git a/src/GameQ/Query/Core.php b/src/GameQ/Query/Core.php
index 8505717b..8206acf8 100644
--- a/src/GameQ/Query/Core.php
+++ b/src/GameQ/Query/Core.php
@@ -27,11 +27,10 @@
*/
abstract class Core
{
-
/**
* The socket used by this resource
*
- * @type null|resource
+ * @var null|resource
*/
public $socket;
diff --git a/src/GameQ/Query/Native.php b/src/GameQ/Query/Native.php
index cba316f9..3c31219a 100644
--- a/src/GameQ/Query/Native.php
+++ b/src/GameQ/Query/Native.php
@@ -35,7 +35,6 @@ class Native extends Core
*/
public function get(): mixed
{
-
// No socket for this server, make one
if (is_null($this->socket)) {
$this->create();
@@ -54,7 +53,6 @@ public function get(): mixed
*/
public function write(string|array $data): int
{
-
try {
// No socket for this server, make one
if (is_null($this->socket)) {
@@ -73,7 +71,6 @@ public function write(string|array $data): int
*/
public function close(): void
{
-
if ($this->socket) {
fclose($this->socket);
$this->socket = null;
@@ -87,7 +84,6 @@ public function close(): void
*/
protected function create(): void
{
-
// Create the remote address
$remote_addr = sprintf("%s://%s:%d", $this->transport, $this->ip, $this->port);
@@ -183,7 +179,7 @@ public function getResponses(array $sockets, int $timeout, int $stream_timeout):
// Loop the sockets that received data back
foreach ($read as $socket) {
- /* @var $socket resource */
+ // @var $socket resource
// See if we have a response
if (($response = fread($socket, 32768)) === false) {
diff --git a/src/GameQ/Result.php b/src/GameQ/Result.php
index e5d82f38..cdd657ae 100644
--- a/src/GameQ/Result.php
+++ b/src/GameQ/Result.php
@@ -89,7 +89,6 @@ public function addSub(string $sub, string $key, mixed $value): void
*/
public function fetch(): array
{
-
return $this->result;
}
diff --git a/src/GameQ/Server.php b/src/GameQ/Server.php
index 764e8a58..6e85feb9 100644
--- a/src/GameQ/Server.php
+++ b/src/GameQ/Server.php
@@ -36,9 +36,7 @@ class Server
public const SERVER_ID = 'id';
public const SERVER_OPTIONS = 'options';
- /*
- * Server options keys
- */
+ // Server options keys
/*
* Use this option when the query_port and client connect ports are different
@@ -139,7 +137,6 @@ public function __construct(array $server_info = [])
*/
protected function checkAndSetIpPort(string $ip_address): void
{
-
// Test for IPv6
if (substr_count($ip_address, ':') > 1) {
// See if we have a port, input should be in the format [::1]:27015 or similar
@@ -201,7 +198,6 @@ protected function checkAndSetIpPort(string $ip_address): void
*/
protected function checkAndSetServerOptions(): void
{
-
// Specific query port defined
if (array_key_exists(self::SERVER_OPTIONS_QUERY_PORT, $this->options)) {
$this->port_query = (int)$this->options[self::SERVER_OPTIONS_QUERY_PORT];
@@ -242,7 +238,6 @@ public function getOptions()
*/
public function id(): string
{
-
return $this->id;
}
@@ -251,7 +246,6 @@ public function id(): string
*/
public function ip(): string
{
-
return $this->ip;
}
@@ -260,7 +254,6 @@ public function ip(): string
*/
public function portClient(): int
{
-
return $this->port_client;
}
@@ -269,7 +262,6 @@ public function portClient(): int
*/
public function portQuery(): int
{
-
return $this->port_query;
}
@@ -278,7 +270,6 @@ public function portQuery(): int
*/
public function protocol(): ?Protocol
{
-
return $this->protocol;
}
@@ -296,16 +287,13 @@ public function getJoinLink(): ?string
return sprintf($joinLink, $this->ip, $this->portClient());
}
- /*
- * Socket holding
- */
+ // Socket holding
/**
* Add a socket for this server to be reused
*/
public function socketAdd(Core $socket): void
{
-
$this->sockets[] = $socket;
}
@@ -314,7 +302,6 @@ public function socketAdd(Core $socket): void
*/
public function socketGet(): ?Core
{
-
$socket = null;
if (count($this->sockets) > 0) {
diff --git a/tests/Buffer.php b/tests/Buffer.php
index 1c0781d6..bd7ded21 100644
--- a/tests/Buffer.php
+++ b/tests/Buffer.php
@@ -37,7 +37,6 @@ class Buffer extends TestBase
*/
protected function buildBuffer($data, $number_type = 'm')
{
-
return new \GameQ\Buffer($data, $number_type);
}
@@ -49,7 +48,6 @@ protected function buildBuffer($data, $number_type = 'm')
*/
public function integerDataProvider()
{
-
// Make the base path for the data to test since it has to be in ascii form
$basePath = sprintf('%s/Providers/Buffer', __DIR__);
diff --git a/tests/Filters/Base.php b/tests/Filters/Base.php
index c7d0f3d4..2fca6ded 100644
--- a/tests/Filters/Base.php
+++ b/tests/Filters/Base.php
@@ -27,7 +27,6 @@
*/
class Base extends TestBase
{
-
/**
* Load up the provider data for the specific filter type
*
@@ -35,7 +34,6 @@ class Base extends TestBase
*/
public function loadData()
{
-
// Explode the class that called to avoid strict error
$class = explode('\\', get_called_class());
@@ -82,16 +80,13 @@ public function loadData()
return $providers;
}
- /*
- * Real Base tests here
- */
+ // Real Base tests here
/**
* Test options setting on construct
*/
public function testOptions()
{
-
$options = [
'option1' => 'value1',
'option2' => 'value2',
diff --git a/tests/Filters/Normalize.php b/tests/Filters/Normalize.php
index ee884cd2..63fe01e4 100644
--- a/tests/Filters/Normalize.php
+++ b/tests/Filters/Normalize.php
@@ -25,7 +25,6 @@
*/
class Normalize extends Base
{
-
/**
* Test the filter for Normalize
*
@@ -37,7 +36,6 @@ class Normalize extends Base
*/
public function testFiltered($protocol, $raw, $filtered)
{
-
// Pop the key from the raw response
$host = key($raw);
@@ -65,7 +63,6 @@ public function testFiltered($protocol, $raw, $filtered)
*/
public function testEmpty()
{
-
// Create a mock server
$server = $this->getMockBuilder('\GameQ\Server')
->setConstructorArgs([
diff --git a/tests/Filters/Secondstohuman.php b/tests/Filters/Secondstohuman.php
index 36b171cd..b4c922c8 100644
--- a/tests/Filters/Secondstohuman.php
+++ b/tests/Filters/Secondstohuman.php
@@ -25,7 +25,6 @@
*/
class Secondstohuman extends Base
{
-
/**
* Test default filter settings
*/
diff --git a/tests/Filters/Stripcolors.php b/tests/Filters/Stripcolors.php
index 54c93c9f..98d18883 100644
--- a/tests/Filters/Stripcolors.php
+++ b/tests/Filters/Stripcolors.php
@@ -25,7 +25,6 @@
*/
class Stripcolors extends Base
{
-
/**
* Test the filter for Stripcolors
*
@@ -37,7 +36,6 @@ class Stripcolors extends Base
*/
public function testFiltered($protocol, $raw, $filtered)
{
-
// Pop the key from the raw response
$host = key($raw);
diff --git a/tests/GameQ.php b/tests/GameQ.php
index 19e3d25f..cd8b1670 100644
--- a/tests/GameQ.php
+++ b/tests/GameQ.php
@@ -25,11 +25,10 @@
*/
class GameQ extends TestBase
{
-
/**
* Holds stub on setup
*
- * @type \GameQ\GameQ
+ * @var \GameQ\GameQ
*/
protected $stub;
@@ -47,7 +46,6 @@ public function customSetUp()
*/
public function testFactory()
{
-
$this->assertInstanceOf('\GameQ\GameQ', \GameQ\GameQ::factory());
}
@@ -76,7 +74,6 @@ public function testGetSetOptions()
*/
public function testAddServer()
{
-
// Define some servers
$servers = [
[
@@ -118,7 +115,6 @@ public function testAddServer()
*/
public function testAddServersFromFiles()
{
-
// Test single file
$this->stub->addServersFromFiles(__DIR__ . '/Protocols/Providers/server_list1.json');
@@ -159,7 +155,6 @@ public function testAddServersFromFiles()
*/
public function testFiltersAddRemove()
{
-
// Add filter
$this->stub->addFilter('test_filter');
@@ -198,7 +193,6 @@ public function testFiltersAddRemove()
*/
public function testFilterApply()
{
-
// Define some fake results
$fakeResults = [
'key1' => 'val1',
@@ -234,7 +228,6 @@ public function testFilterApply()
*/
public function testBadFilterException()
{
-
// Define some fake results
$fakeResults = [
'key1' => 'val1',
diff --git a/tests/Issues/Issue307.php b/tests/Issues/Issue307.php
index 33d87ba4..fe624c92 100644
--- a/tests/Issues/Issue307.php
+++ b/tests/Issues/Issue307.php
@@ -37,7 +37,6 @@ class Issue307 extends TestBase
*/
public function test1()
{
-
$filePath = sprintf('%s/Providers/307.txt', __DIR__);
$testResult = $this->queryTest('127.0.0.1:27015', 'csgo', explode(PHP_EOL . '||' . PHP_EOL, file_get_contents($filePath)));
diff --git a/tests/Issues/Issue588.php b/tests/Issues/Issue588.php
index c9abf5ff..26cb600d 100644
--- a/tests/Issues/Issue588.php
+++ b/tests/Issues/Issue588.php
@@ -29,6 +29,11 @@
*/
class Issue588 extends TestBase
{
+ /**
+ * @var \GameQ\GameQ
+ */
+ protected $stub;
+
/**
* Setup to create our stub
* @before
diff --git a/tests/Protocol.php b/tests/Protocol.php
index baf6ea0b..659953b7 100644
--- a/tests/Protocol.php
+++ b/tests/Protocol.php
@@ -25,18 +25,17 @@
*/
class Protocol extends TestBase
{
-
/**
* Holds stub on setup
*
- * @type \GameQ\Protocol
+ * @var \GameQ\Protocol
*/
protected $stub;
/**
* Some dummy options
*
- * @type array
+ * @var array
*/
protected $options = [
'key1' => 'var1',
@@ -49,7 +48,6 @@ class Protocol extends TestBase
*/
public function customSetUp()
{
-
$this->stub = $this->getMockForAbstractClass('\GameQ\Protocol', [ $this->options ]);
}
@@ -58,7 +56,6 @@ public function customSetUp()
*/
public function testGeneral()
{
-
$name = 'Test name';
$nameLong = 'Test name bigger, longer';
$portDiff = 5454;
@@ -102,7 +99,6 @@ public function testGeneral()
*/
public function testPackets()
{
-
$packets = [
\GameQ\Protocol::PACKET_CHALLENGE => 'Do you even lift?',
\GameQ\Protocol::PACKET_RULES => 'There are no rules!!',
diff --git a/tests/Protocols/Arksa.php b/tests/Protocols/Arksa.php
new file mode 100644
index 00000000..c9371d3e
--- /dev/null
+++ b/tests/Protocols/Arksa.php
@@ -0,0 +1,49 @@
+.
+ */
+
+namespace GameQ\Tests\Protocols;
+
+/**
+ * Test Class for ARK: Survival Ascended
+ *
+ * @package GameQ\Tests\Protocols
+ */
+class Arksa extends Base
+{
+ /**
+ * Test responses for ARK: Survival Ascended
+ *
+ * @dataProvider loadData
+ *
+ * @param $responses
+ * @param $result
+ */
+ public function testResponses($responses, $result)
+ {
+ // Pull the first key off the array this is the server ip:port
+ $server = key($result);
+
+ $testResult = $this->queryTest(
+ $server,
+ 'arksa',
+ $responses
+ );
+
+ $this->assertEqualsDelta($result[$server], $testResult, 0.00000001);
+ }
+}
diff --git a/tests/Protocols/Ase.php b/tests/Protocols/Ase.php
index d8e006bd..957c1832 100644
--- a/tests/Protocols/Ase.php
+++ b/tests/Protocols/Ase.php
@@ -25,14 +25,14 @@ class Ase extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Ase
+ * @var \GameQ\Protocols\Ase
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_ALL => "s",
diff --git a/tests/Protocols/Atlas.php b/tests/Protocols/Atlas.php
index 76106c6c..8ce7f184 100644
--- a/tests/Protocols/Atlas.php
+++ b/tests/Protocols/Atlas.php
@@ -35,7 +35,6 @@ class Atlas extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
// Splited to later be compared with query port
diff --git a/tests/Protocols/Batt1944.php b/tests/Protocols/Batt1944.php
index 6273162c..2f94fb58 100644
--- a/tests/Protocols/Batt1944.php
+++ b/tests/Protocols/Batt1944.php
@@ -35,7 +35,6 @@ class Batt1944 extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Bf3.php b/tests/Protocols/Bf3.php
index 9d027efe..a9683b85 100644
--- a/tests/Protocols/Bf3.php
+++ b/tests/Protocols/Bf3.php
@@ -25,14 +25,14 @@ class Bf3 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Bf3
+ * @var \GameQ\Protocols\Bf3
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\x00\x00\x00\x21\x1b\x00\x00\x00\x01\x00\x00\x00\x0a\x00\x00\x00serverInfo\x00",
diff --git a/tests/Protocols/Bfbc2.php b/tests/Protocols/Bfbc2.php
index 6f030e45..b083a672 100644
--- a/tests/Protocols/Bfbc2.php
+++ b/tests/Protocols/Bfbc2.php
@@ -25,14 +25,14 @@ class Bfbc2 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Bfbc2
+ * @var \GameQ\Protocols\Bfbc2
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_VERSION => "\x00\x00\x00\x00\x18\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00version\x00",
diff --git a/tests/Protocols/Bfh.php b/tests/Protocols/Bfh.php
index d8488761..64197e05 100644
--- a/tests/Protocols/Bfh.php
+++ b/tests/Protocols/Bfh.php
@@ -20,7 +20,6 @@
class Bfh extends Base
{
-
/**
* Test responses for Battlefield Hardline
*
diff --git a/tests/Protocols/Codmw2.php b/tests/Protocols/Codmw2.php
index 93f9d28f..a00d46f9 100644
--- a/tests/Protocols/Codmw2.php
+++ b/tests/Protocols/Codmw2.php
@@ -35,7 +35,6 @@ class Codmw2 extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Cs2d.php b/tests/Protocols/Cs2d.php
index 98fbefa1..beedddbb 100644
--- a/tests/Protocols/Cs2d.php
+++ b/tests/Protocols/Cs2d.php
@@ -25,14 +25,14 @@ class Cs2d extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Cs2d
+ * @var \GameQ\Protocols\Cs2d
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\x01\x00\xFB\x01",
diff --git a/tests/Protocols/Doom3.php b/tests/Protocols/Doom3.php
index d43e6d78..67ed9440 100644
--- a/tests/Protocols/Doom3.php
+++ b/tests/Protocols/Doom3.php
@@ -35,7 +35,6 @@ class Doom3 extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Eco.php b/tests/Protocols/Eco.php
index ae78936a..2a476bb8 100644
--- a/tests/Protocols/Eco.php
+++ b/tests/Protocols/Eco.php
@@ -23,14 +23,14 @@ class Eco extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Eco
+ * @var \GameQ\Protocols\Eco
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "GET /frontpage HTTP/1.0\r\nAccept: */*\r\n\r\n",
diff --git a/tests/Protocols/Eos.php b/tests/Protocols/Eos.php
new file mode 100644
index 00000000..a6e7f1f0
--- /dev/null
+++ b/tests/Protocols/Eos.php
@@ -0,0 +1,42 @@
+.
+ */
+
+namespace GameQ\Tests\Protocols;
+
+class Eos extends Base
+{
+ /**
+ * Test to ensure the response processing is correct
+ *
+ * @return void
+ */
+ public function testResponses()
+ {
+ // Wrap the queryTest method in a try-catch block to handle the exception
+ try {
+ $this->queryTest('127.0.0.1:27015', 'eos', [], false);
+ } catch (Server $e) {
+ // Log the exception or handle as needed
+ $this->assertTrue(true, "Expected exception 'Failed to authenticate with EOS API' was caught");
+ return; // Exit the test since the exception is expected
+ }
+
+ // If no exception is thrown, the test passes as expected
+ $this->assertTrue(true, "Test passed without exception");
+ }
+}
diff --git a/tests/Protocols/Etqw.php b/tests/Protocols/Etqw.php
index 6c7aa96a..2afefbe7 100644
--- a/tests/Protocols/Etqw.php
+++ b/tests/Protocols/Etqw.php
@@ -25,14 +25,14 @@ class Etqw extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Etqw
+ * @var \GameQ\Protocols\Etqw
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\xFF\xFFgetInfoEx\x00\x00\x00\x00",
diff --git a/tests/Protocols/Ffow.php b/tests/Protocols/Ffow.php
index f904753b..21f1e97f 100644
--- a/tests/Protocols/Ffow.php
+++ b/tests/Protocols/Ffow.php
@@ -25,14 +25,14 @@ class Ffow extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Ffow
+ * @var \GameQ\Protocols\Ffow
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_CHALLENGE => "\xFF\xFF\xFF\xFF\x57",
diff --git a/tests/Protocols/Gamespy.php b/tests/Protocols/Gamespy.php
index 62d15063..735519d6 100644
--- a/tests/Protocols/Gamespy.php
+++ b/tests/Protocols/Gamespy.php
@@ -25,14 +25,14 @@ class Gamespy extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Gamespy
+ * @var \GameQ\Protocols\Gamespy
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\x5C\x73\x74\x61\x74\x75\x73\x5C",
diff --git a/tests/Protocols/Gamespy2.php b/tests/Protocols/Gamespy2.php
index bd1f8c17..6450b6ac 100644
--- a/tests/Protocols/Gamespy2.php
+++ b/tests/Protocols/Gamespy2.php
@@ -23,14 +23,14 @@ class Gamespy2 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Gamespy2
+ * @var \GameQ\Protocols\Gamespy2
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_DETAILS => "\xFE\xFD\x00\x43\x4F\x52\x59\xFF\x00\x00",
diff --git a/tests/Protocols/Gamespy3.php b/tests/Protocols/Gamespy3.php
index 7574215c..1e010eeb 100644
--- a/tests/Protocols/Gamespy3.php
+++ b/tests/Protocols/Gamespy3.php
@@ -23,14 +23,14 @@ class Gamespy3 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Gamespy3
+ * @var \GameQ\Protocols\Gamespy3
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_CHALLENGE => "\xFE\xFD\x09\x10\x20\x30\x40",
diff --git a/tests/Protocols/Gtan.php b/tests/Protocols/Gtan.php
index 1be58d9d..4a510e3b 100644
--- a/tests/Protocols/Gtan.php
+++ b/tests/Protocols/Gtan.php
@@ -23,14 +23,14 @@ class Gtan extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Gtan
+ * @var \GameQ\Protocols\Gtan
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "GET /gtan/api.php?ip=%s&raw HTTP/1.0\r\nHost: multiplayerhosting.info\r\nAccept: */*\r\n\r\n",
diff --git a/tests/Protocols/Gtar.php b/tests/Protocols/Gtar.php
index 2979c6e9..ec95d2aa 100644
--- a/tests/Protocols/Gtar.php
+++ b/tests/Protocols/Gtar.php
@@ -23,14 +23,14 @@ class Gtar extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Gtan
+ * @var \GameQ\Protocols\Gtan
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "GET /master/ HTTP/1.0\r\nHost: cdn.rage.mp\r\nAccept: */*\r\n\r\n",
diff --git a/tests/Protocols/Had2.php b/tests/Protocols/Had2.php
index 118ba36d..aa773fe4 100644
--- a/tests/Protocols/Had2.php
+++ b/tests/Protocols/Had2.php
@@ -35,7 +35,6 @@ class Had2 extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Halo.php b/tests/Protocols/Halo.php
index 65152e91..ceab3583 100644
--- a/tests/Protocols/Halo.php
+++ b/tests/Protocols/Halo.php
@@ -35,7 +35,6 @@ class Halo extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Hll.php b/tests/Protocols/Hll.php
index 92aed03a..d5f19d39 100644
--- a/tests/Protocols/Hll.php
+++ b/tests/Protocols/Hll.php
@@ -35,7 +35,6 @@ class Hll extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Justcause2.php b/tests/Protocols/Justcause2.php
index 840891df..bebc3f35 100644
--- a/tests/Protocols/Justcause2.php
+++ b/tests/Protocols/Justcause2.php
@@ -23,14 +23,14 @@ class Justcause2 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Gamespy
+ * @var \GameQ\Protocols\Gamespy
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_CHALLENGE => "\xFE\xFD\x09\x10\x20\x30\x40",
diff --git a/tests/Protocols/Lhmp.php b/tests/Protocols/Lhmp.php
index b175d687..76fbe9f9 100644
--- a/tests/Protocols/Lhmp.php
+++ b/tests/Protocols/Lhmp.php
@@ -25,14 +25,14 @@ class Lhmp extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Lhmp
+ * @var \GameQ\Protocols\Lhmp
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_DETAILS => "LHMPo",
diff --git a/tests/Protocols/M2mp.php b/tests/Protocols/M2mp.php
index 0e68cbef..a5ed3850 100644
--- a/tests/Protocols/M2mp.php
+++ b/tests/Protocols/M2mp.php
@@ -35,7 +35,6 @@ class M2mp extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Miscreated.php b/tests/Protocols/Miscreated.php
index 70b00b30..0e341676 100644
--- a/tests/Protocols/Miscreated.php
+++ b/tests/Protocols/Miscreated.php
@@ -35,7 +35,6 @@ class Miscreated extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Mohaa.php b/tests/Protocols/Mohaa.php
index f31c66d0..377d05f1 100644
--- a/tests/Protocols/Mohaa.php
+++ b/tests/Protocols/Mohaa.php
@@ -28,7 +28,7 @@ class Mohaa extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Mohaa
+ * @var \GameQ\Protocols\Mohaa
*/
protected $stub;
diff --git a/tests/Protocols/Mumble.php b/tests/Protocols/Mumble.php
index 65a58ea5..fbe6a9c4 100644
--- a/tests/Protocols/Mumble.php
+++ b/tests/Protocols/Mumble.php
@@ -28,14 +28,14 @@ class Mumble extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Mumble
+ * @var \GameQ\Protocols\Mumble
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_ALL => "\x6A\x73\x6F\x6E",
diff --git a/tests/Protocols/Openttd.php b/tests/Protocols/Openttd.php
index beccaf2c..ecbd7494 100644
--- a/tests/Protocols/Openttd.php
+++ b/tests/Protocols/Openttd.php
@@ -35,7 +35,6 @@ class Openttd extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Postscriptum.php b/tests/Protocols/Postscriptum.php
index b7f2de4c..1e621e02 100644
--- a/tests/Protocols/Postscriptum.php
+++ b/tests/Protocols/Postscriptum.php
@@ -35,7 +35,6 @@ class Postscriptum extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Providers/Arksa/1_response.txt b/tests/Protocols/Providers/Arksa/1_response.txt
new file mode 100644
index 00000000..87beedfc
--- /dev/null
+++ b/tests/Protocols/Providers/Arksa/1_response.txt
@@ -0,0 +1,3 @@
+{"access_token":"eyJraWQiOiIyMDIyLTA2LTE0VDA2OjE3OjU3LjA0NzkyODcwMFoiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJjbGllbnRJZCI6Inh5emE3ODkxbXVvbVJteW5JSUhhSkI5Q09CS2t3ajZuIiwicHJvZHVjdElkIjoiOTg1ZGM0ZDY3ZmYxNDI1ODhiNjM5M2M0NmIxZGZmODQiLCJpc3MiOiJlb3MiLCJlbnYiOiJwcm9kIiwib3JnYW5pemF0aW9uSWQiOiJvLXVzdmZibWxxZHQ2Nzh2cnAzNnF2bTJkNWN6MmNwciIsImZlYXR1cmVzIjpbIkFjaGlldmVtZW50cyIsIkNvbm5lY3QiLCJFY29tIiwiTGVhZGVyYm9hcmRzIiwiTWF0Y2htYWtpbmciLCJNZXRyaWNzIiwiU3RhdHMiLCJWb2ljZSJdLCJkZXBsb3ltZW50SWQiOiJhZDlhOGZlZmZiM2I0YjJjYTMxNTU0NmYwMzhjM2FlMiIsInNhbmRib3hJZCI6ImRhZTgwYzBkNGUzYjRkNjQ4NDk4YjQ4YWY2MDliOGJiIiwidG9rZW5UeXBlIjoiY2xpZW50VG9rZW4iLCJleHAiOjE3MzQ1MTgyMzEsImlhdCI6MTczNDUxNDYzMSwianRpIjoiYjk2YWY1M2RkMWEyNGZkNDk4OTRlNTRmZDUzZWU0ZmEifQ.0fZwExBmf0Bpx0J7T-kLWe900T-DLwjp7vhY3zh66rgwvtXhuPjDh1N_TOw7hPAKhZoDmUhGu5XAd9bde0AEav4iCUECG2gWcEPSBLjSc-BeUs6xbWFLSRQ6HL7VorkaWSS-SaRQaFNu5aSMwYQqhxTC-IynchNjMa3iakuetWvvFqhqpNJucV43GrUsYpga1MBxWSu-iPgkj3rwUItGAh8X1iS_viVN1pCYiOxY_PhrBGjie_S63Zct3kxpyvmt3o2T8dGH8GHRGuCYkkARtqXxQl7Zu30UI9tjAU0OmDBgnVxNs09-sxR-pd5qZdQn2MMjs0rkJ3ToqLT_Oj3xmg","token_type":"bearer","expires_at":"2024-12-18T10:37:11.149Z","features":["Achievements","Connect","Ecom","Leaderboards","Matchmaking","Metrics","Stats","Voice"],"organization_id":"o-usvfbmlqdt678vrp36qvm2d5cz2cpr","product_id":"985dc4d67ff142588b6393c46b1dff84","sandbox_id":"dae80c0d4e3b4d648498b48af609b8bb","deployment_id":"ad9a8feffb3b4b2ca315546f038c3ae2","expires_in":3599}
+||
+{"sessions":[{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"a92b9db4147c42cdaeb89919adaac2c5","bucket":"TestGameMode_C::TheIsland_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":4,"openPublicPlayers":66,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"EU-PVP-TheIsland2340","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"5237","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheIsland_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":177,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.112.15","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7779","SESSIONISPVE_l":0,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVPCrossplay","SESSIONNAMEUPPER_s":"EU-PVP-THEISLAND2340 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+PS5+XSX","MAPNAME_s":"TheIsland_WP","BUILDID_s":"56","SESSIONNAME_s":"EU-PVP-TheIsland2340 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"48b5308a809a44f79068d24122a0a0d5","bucket":"TestGameMode_C::TheIsland_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":0,"openPublicPlayers":70,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"EU-PVP-TheIsland2339","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"5180","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheIsland_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":219,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.112.15","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7777","SESSIONISPVE_l":0,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVPCrossplay","SESSIONNAMEUPPER_s":"EU-PVP-THEISLAND2339 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+PS5+XSX","MAPNAME_s":"TheIsland_WP","BUILDID_s":"56","SESSIONNAME_s":"EU-PVP-TheIsland2339 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"deedb3d1c71e4e81b92bcf5123352f7d","bucket":"TestGameMode_C::TheCenter_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":9,"openPublicPlayers":61,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"EU-PVE-TheCenter5666","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"2421","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheCenter_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":164,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.112.15","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7781","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"EU-PVE-THECENTER5666 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"TheCenter_WP","BUILDID_s":"56","SESSIONNAME_s":"EU-PVE-TheCenter5666 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"907ec32e712f4a88bbcff8f556439a01","bucket":"TestGameMode_C::Aberration_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":4,"openPublicPlayers":66,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"EU-PVE-Aberration5703","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"2439","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"Aberration_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":177,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.112.15","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7783","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"EU-PVE-ABERRATION5703 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"Aberration_WP","BUILDID_s":"56","SESSIONNAME_s":"EU-PVE-Aberration5703 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null}],"count":4}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Arksa/1_result.json b/tests/Protocols/Providers/Arksa/1_result.json
new file mode 100644
index 00000000..1c5be6a7
--- /dev/null
+++ b/tests/Protocols/Providers/Arksa/1_result.json
@@ -0,0 +1 @@
+{"5.62.112.15:7781":{"allowJoinInProgress":true,"anticheat":true,"day":"2421","gq_address":"5.62.112.15","gq_joinlink":null,"gq_name":"ARK: Survival Ascended","gq_online":true,"gq_port_client":7781,"gq_port_query":7781,"gq_protocol":"arksa","gq_transport":"tcp","gq_type":"arksa","hostname":"EU-PVE-TheCenter5666","mapname":"TheCenter_WP","maxplayers":70,"numplayers":9,"officialserver":true,"password":false,"pve":true,"version":"v56.18"}}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Arksa/2_response.txt b/tests/Protocols/Providers/Arksa/2_response.txt
new file mode 100644
index 00000000..14c3be81
--- /dev/null
+++ b/tests/Protocols/Providers/Arksa/2_response.txt
@@ -0,0 +1,3 @@
+{"access_token":"eyJraWQiOiIyMDIyLTA2LTE0VDA2OjE3OjU3LjA0NzkyODcwMFoiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJjbGllbnRJZCI6Inh5emE3ODkxbXVvbVJteW5JSUhhSkI5Q09CS2t3ajZuIiwicHJvZHVjdElkIjoiOTg1ZGM0ZDY3ZmYxNDI1ODhiNjM5M2M0NmIxZGZmODQiLCJpc3MiOiJlb3MiLCJlbnYiOiJwcm9kIiwib3JnYW5pemF0aW9uSWQiOiJvLXVzdmZibWxxZHQ2Nzh2cnAzNnF2bTJkNWN6MmNwciIsImZlYXR1cmVzIjpbIkFjaGlldmVtZW50cyIsIkNvbm5lY3QiLCJFY29tIiwiTGVhZGVyYm9hcmRzIiwiTWF0Y2htYWtpbmciLCJNZXRyaWNzIiwiU3RhdHMiLCJWb2ljZSJdLCJkZXBsb3ltZW50SWQiOiJhZDlhOGZlZmZiM2I0YjJjYTMxNTU0NmYwMzhjM2FlMiIsInNhbmRib3hJZCI6ImRhZTgwYzBkNGUzYjRkNjQ4NDk4YjQ4YWY2MDliOGJiIiwidG9rZW5UeXBlIjoiY2xpZW50VG9rZW4iLCJleHAiOjE3MzQ1MjI1NzEsImlhdCI6MTczNDUxODk3MSwianRpIjoiNGVhZGMxMDE5YThhNDFiNmJmMjg1MmVjOWVjYWUyYjAifQ.mIdSO3jrVkmvZ6pmtS3ab47PsLp2Qu89CXELl5EyubJug6HM3bfvEG7PO0XWJpLt6C3nnVYncF3v67uEL-Ix5LQoo3oY3seEciPb2MsY-DuIIAmaFWd6julIohQLO0i2M8owp7L6IWU3Sl340FBYsCJ61fVqwTV5bXLABt4M4TDdJgUfeRwsYSdruqeQHn7uMbhYrVoGRuP4S6grTkm9JbwBWT8677IN9kUBYo9kC8LHVWkOsZyrR1yjoiUDqXHzHp_WM5lF5DWH85SWbO0jDxKCawB1N_QKRkD1CdaO1vBYONRFrg3HbTVY_POvrnvHwS6CzarMMNWkmdylQ7TRZA","token_type":"bearer","expires_at":"2024-12-18T11:49:31.012Z","features":["Achievements","Connect","Ecom","Leaderboards","Matchmaking","Metrics","Stats","Voice"],"organization_id":"o-usvfbmlqdt678vrp36qvm2d5cz2cpr","product_id":"985dc4d67ff142588b6393c46b1dff84","sandbox_id":"dae80c0d4e3b4d648498b48af609b8bb","deployment_id":"ad9a8feffb3b4b2ca315546f038c3ae2","expires_in":3599}
+||
+{"sessions":[{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"5a711eafaf2a45f3b27607210b28cade","bucket":"TestGameMode_C::TheCenter_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":1,"openPublicPlayers":69,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"Asia-PVP-TheCenter2430","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"ENABLEDMODSFILEIDS_s":"","DAYTIME_s":"2547","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":297,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.119.20","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7777","SESSIONISPVE_l":0,"__EOS_BUSESPRESENCE_b":true,"PASSIVEMODS_s":"","CLUSTERID_s":"PVPCrossplay","ENABLEDMODS_s":"","SESSIONNAMEUPPER_s":"ASIA-PVP-THECENTER2430 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+PS5+XSX","MAPNAME_s":"TheCenter_WP","BUILDID_s":"56","SESSIONNAME_s":"Asia-PVP-TheCenter2430 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"a92643e6fa794703acefada43026d7c6","bucket":"TestGameMode_C::TheCenter_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":13,"openPublicPlayers":57,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"Asia-PVE-TheCenter5652","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"2515","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheCenter_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":206,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.119.20","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7779","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"ASIA-PVE-THECENTER5652 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"TheCenter_WP","BUILDID_s":"56","SESSIONNAME_s":"Asia-PVE-TheCenter5652 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"5add778e58494559a92e98c08767e458","bucket":"TestGameMode_C::TheCenter_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":1,"openPublicPlayers":69,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"Asia-PVP-TheCenter2430","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"2547","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheCenter_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":299,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.119.20","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7777","SESSIONISPVE_l":0,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVPCrossplay","SESSIONNAMEUPPER_s":"ASIA-PVP-THECENTER2430 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+PS5+XSX","MAPNAME_s":"TheCenter_WP","BUILDID_s":"56","SESSIONNAME_s":"Asia-PVP-TheCenter2430 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"4fdb413eac3146a39eb430659a845665","bucket":"TestGameMode_C::TheCenter_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":19,"openPublicPlayers":51,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"Asia-PVE-TheCenter5653","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"2512","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheCenter_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":177,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.119.20","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7781","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"ASIA-PVE-THECENTER5653 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"TheCenter_WP","BUILDID_s":"56","SESSIONNAME_s":"Asia-PVE-TheCenter5653 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"7abf7a6afdb54a92a00da9d8d76dbc1d","bucket":"TestGameMode_C::Aberration_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":3,"openPublicPlayers":67,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"Asia-PVP-Aberration2475","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"2472","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"Aberration_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":242,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.119.20","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7783","SESSIONISPVE_l":0,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVPCrossplay","SESSIONNAMEUPPER_s":"ASIA-PVP-ABERRATION2475 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+PS5+XSX","MAPNAME_s":"Aberration_WP","BUILDID_s":"56","SESSIONNAME_s":"Asia-PVP-Aberration2475 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null}],"count":5}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Arksa/2_result.json b/tests/Protocols/Providers/Arksa/2_result.json
new file mode 100644
index 00000000..8e8fb58f
--- /dev/null
+++ b/tests/Protocols/Providers/Arksa/2_result.json
@@ -0,0 +1 @@
+{"5.62.119.20:7779":{"allowJoinInProgress":true,"anticheat":true,"day":"2515","gq_address":"5.62.119.20","gq_joinlink":null,"gq_name":"ARK: Survival Ascended","gq_online":true,"gq_port_client":7779,"gq_port_query":7779,"gq_protocol":"arksa","gq_transport":"tcp","gq_type":"arksa","hostname":"Asia-PVE-TheCenter5652","mapname":"TheCenter_WP","maxplayers":70,"numplayers":13,"officialserver":true,"password":false,"pve":true,"version":"v56.18"}}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Arksa/3_response.txt b/tests/Protocols/Providers/Arksa/3_response.txt
new file mode 100644
index 00000000..861c843d
--- /dev/null
+++ b/tests/Protocols/Providers/Arksa/3_response.txt
@@ -0,0 +1,3 @@
+{"access_token":"eyJraWQiOiIyMDIyLTA2LTE0VDA2OjE3OjU3LjA0NzkyODcwMFoiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJjbGllbnRJZCI6Inh5emE3ODkxbXVvbVJteW5JSUhhSkI5Q09CS2t3ajZuIiwicHJvZHVjdElkIjoiOTg1ZGM0ZDY3ZmYxNDI1ODhiNjM5M2M0NmIxZGZmODQiLCJpc3MiOiJlb3MiLCJlbnYiOiJwcm9kIiwib3JnYW5pemF0aW9uSWQiOiJvLXVzdmZibWxxZHQ2Nzh2cnAzNnF2bTJkNWN6MmNwciIsImZlYXR1cmVzIjpbIkFjaGlldmVtZW50cyIsIkNvbm5lY3QiLCJFY29tIiwiTGVhZGVyYm9hcmRzIiwiTWF0Y2htYWtpbmciLCJNZXRyaWNzIiwiU3RhdHMiLCJWb2ljZSJdLCJkZXBsb3ltZW50SWQiOiJhZDlhOGZlZmZiM2I0YjJjYTMxNTU0NmYwMzhjM2FlMiIsInNhbmRib3hJZCI6ImRhZTgwYzBkNGUzYjRkNjQ4NDk4YjQ4YWY2MDliOGJiIiwidG9rZW5UeXBlIjoiY2xpZW50VG9rZW4iLCJleHAiOjE3MzQ1MjI1ODEsImlhdCI6MTczNDUxODk4MSwianRpIjoiYTg5NTFiNjg4NTYwNDMyYTlkZWZlMGZiZThiMThjYmYifQ.c8KpgfO-KNjBqjxIMkFHWjEQRDnCwp41REjQFpPD5w4IcsVCcH0bkuU4g0pBESkIltb2SeqDPztsq9xJgIdJ0gECfiAo9g2_njm8ZWmYbgygPIXWst5AJPDt6wghj_B7zObd2Ez1qdqHW9GkjXZ8QaMjfGdtt806L6spyoAeHp66IIfY6mkwA6vZl9fk4SIb5OTDEb-gBQlYVWnY6txrjuJJJeDZDKh3Ky6sB6a3fYbPQsjZVnU8hxtVHTlnzkWfMrBxvt9kgTXayQUKV3_AM6BKLtl2L8HdQbs37nJCGp-6poCL3A_47vlaKJtN0ZgMX7Yg8pLwrXmiaa1jfZGxgQ","token_type":"bearer","expires_at":"2024-12-18T11:49:41.150Z","features":["Achievements","Connect","Ecom","Leaderboards","Matchmaking","Metrics","Stats","Voice"],"organization_id":"o-usvfbmlqdt678vrp36qvm2d5cz2cpr","product_id":"985dc4d67ff142588b6393c46b1dff84","sandbox_id":"dae80c0d4e3b4d648498b48af609b8bb","deployment_id":"ad9a8feffb3b4b2ca315546f038c3ae2","expires_in":3599}
+||
+{"sessions":[{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"b20315b60f494e7e9e1c74d2089746a2","bucket":"TestGameMode_C::TheIsland_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":5,"openPublicPlayers":65,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"NA-PVE-TheIsland5174","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"5096","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheIsland_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":210,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.114.2","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7777","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"NA-PVE-THEISLAND5174 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"TheIsland_WP","BUILDID_s":"56","SESSIONNAME_s":"NA-PVE-TheIsland5174 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"ec3139bee09b4b1cad09e2a1810d5632","bucket":"TestGameMode_C::TheIsland_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":3,"openPublicPlayers":67,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"NA-PVE-TheIsland5176","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"5080","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheIsland_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":152,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.114.2","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7781","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"NA-PVE-THEISLAND5176 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"TheIsland_WP","BUILDID_s":"56","SESSIONNAME_s":"NA-PVE-TheIsland5176 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"c88dc644533c47d08bd99f91e0a425f4","bucket":"TestGameMode_C::TheIsland_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":7,"openPublicPlayers":63,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"NA-PVE-TheIsland5175","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"5089","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheIsland_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":241,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.114.2","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7779","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"NA-PVE-THEISLAND5175 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"TheIsland_WP","BUILDID_s":"56","SESSIONNAME_s":"NA-PVE-TheIsland5175 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null},{"deployment":"ad9a8feffb3b4b2ca315546f038c3ae2","id":"9ccfc376fc114d02b0a16680f0d80e91","bucket":"TestGameMode_C::TheIsland_WP","settings":{"maxPublicPlayers":70,"allowInvites":true,"shouldAdvertise":true,"allowReadById":true,"allowJoinViaPresence":true,"allowJoinInProgress":true,"allowConferenceRoom":false,"checkSanctions":false,"allowMigration":false,"rejoinAfterKick":"","platforms":null},"totalPlayers":3,"openPublicPlayers":67,"publicPlayers":[],"started":false,"lastUpdated":null,"attributes":{"MINORBUILDID_s":"18","MODID_l":0,"CUSTOMSERVERNAME_s":"NA-PVE-TheIsland5177","ISPRIVATE_l":0,"SERVERPASSWORD_b":false,"MATCHTIMEOUT_d":120.0,"DAYTIME_s":"5046","SOTFMATCHSTARTED_b":false,"STEELSHIELDENABLED_l":1,"FRIENDLYMAPNAME_s":"TheIsland_WP","SERVERUSESBATTLEYE_b":true,"EOSSERVERPING_l":228,"ALLOWDOWNLOADCHARS_l":1,"OFFICIALSERVER_s":"1","GAMEMODE_s":"TestGameMode_C","ADDRESS_s":"5.62.114.2","SEARCHKEYWORDS_s":"Custom","__EOS_BLISTENING_b":true,"ALLOWDOWNLOADITEMS_l":1,"LEGACY_l":0,"ADDRESSBOUND_s":"0.0.0.0:7783","SESSIONISPVE_l":1,"__EOS_BUSESPRESENCE_b":true,"CLUSTERID_s":"PVECrossplay","SESSIONNAMEUPPER_s":"NA-PVE-THEISLAND5177 - (V56.18)","SERVERPLATFORMTYPE_s":"PC+XSX+WINGDK+PS5","MAPNAME_s":"TheIsland_WP","BUILDID_s":"56","SESSIONNAME_s":"NA-PVE-TheIsland5177 - (v56.18)"},"owner":"Client_xyza7891muomRmynIIHaJB9COBKkwj6n","ownerPlatformId":null}],"count":4}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Arksa/3_result.json b/tests/Protocols/Providers/Arksa/3_result.json
new file mode 100644
index 00000000..0c544955
--- /dev/null
+++ b/tests/Protocols/Providers/Arksa/3_result.json
@@ -0,0 +1 @@
+{"5.62.114.2:7779":{"allowJoinInProgress":true,"anticheat":true,"day":"5089","gq_address":"5.62.114.2","gq_joinlink":null,"gq_name":"ARK: Survival Ascended","gq_online":true,"gq_port_client":7779,"gq_port_query":7779,"gq_protocol":"arksa","gq_transport":"tcp","gq_type":"arksa","hostname":"NA-PVE-TheIsland5175","mapname":"TheIsland_WP","maxplayers":70,"numplayers":7,"officialserver":true,"password":false,"pve":true,"version":"v56.18"}}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Stationeers/1_response.txt b/tests/Protocols/Providers/Stationeers/1_response.txt
new file mode 100644
index 00000000..2fa52927
--- /dev/null
+++ b/tests/Protocols/Providers/Stationeers/1_response.txt
@@ -0,0 +1,968 @@
+HTTP/1.1 200 OK
+Keep-Alive: true
+Content-Length: 22496
+Server: Microsoft-HTTPAPI/2.0
+Date: Tue, 30 Aug 2022 22:29:23 GMT
+Connection: close
+
+{
+ "Count": 63,
+ "TotalPlayers": 22,
+ "GameSessions": [
+ {
+ "SessionId": 15712,
+ "Name": "Catch22",
+ "Version": "0.2.3570.17365",
+ "Address": "103.114.12.10",
+ "Checksum": "E4F1D9C5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15716,
+ "Name": "Stationeers German/Deutsch BlackLand Hallo Leute leider geht es zu zeit nur in solo spiel :-(",
+ "Version": "0.2.3570.17365",
+ "Address": "194.163.170.243",
+ "Checksum": "B5963DBD",
+ "Port": "35700",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15721,
+ "Name": "0GravityBert",
+ "Version": "0.2.3570.17365",
+ "Address": "85.215.225.45",
+ "Checksum": "E916B8BD",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 5,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15723,
+ "Name": "LM - Europa",
+ "Version": "0.2.3570.17365",
+ "Address": "159.69.72.154",
+ "Checksum": "3AE1D2BD",
+ "Port": "25456",
+ "MapName": "Europa2",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15726,
+ "Name": "meshbase",
+ "Version": "0.2.3570.17365",
+ "Address": "103.62.50.20",
+ "Checksum": "B201B4BD",
+ "Port": "26510",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 16,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15739,
+ "Name": "4Netplayers Stationeers Server",
+ "Version": "0.2.3570.17365",
+ "Address": "62.104.16.117",
+ "Checksum": "1DCD0495",
+ "Port": "23800",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15762,
+ "Name": "Androneers",
+ "Version": "0.2.3570.17365",
+ "Address": "47.158.161.12",
+ "Checksum": "48EB8995",
+ "Port": "27016",
+ "MapName": "Proximab",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15768,
+ "Name": "Skyvale Interstellar",
+ "Version": "0.2.3570.17365",
+ "Address": "185.125.205.100",
+ "Checksum": "12FCE3C5",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15783,
+ "Name": "Apollo 4",
+ "Version": "0.2.3530.17210",
+ "Address": "87.97.24.142",
+ "Checksum": "E6432F93",
+ "Port": "27017",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15789,
+ "Name": "Grumpy",
+ "Version": "0.2.3570.17365",
+ "Address": "47.49.8.74",
+ "Checksum": "BE8B5395",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15803,
+ "Name": "Celestra FR",
+ "Version": "0.2.3570.17365",
+ "Address": "82.65.179.165",
+ "Checksum": "39B0CCBD",
+ "Port": "23520",
+ "MapName": "Europa",
+ "Players": 0,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15808,
+ "Name": "StationeersSamnick",
+ "Version": "0.2.3587.17443",
+ "Address": "159.69.72.154",
+ "C
+||
+hecksum": "8A8DE0B5",
+ "Port": "25448",
+ "MapName": "Mimas",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15810,
+ "Name": "Celestra Fr Mars",
+ "Version": "0.2.3570.17365",
+ "Address": "82.65.179.165",
+ "Checksum": "1207EAED",
+ "Port": "23536",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15832,
+ "Name": "Devilscary",
+ "Version": "0.2.3570.17365",
+ "Address": "74.210.225.225",
+ "Checksum": "7C080395",
+ "Port": "27516",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15844,
+ "Name": "4Netplayers Mars 1 geht leider nicht",
+ "Version": "0.2.3570.17365",
+ "Address": "62.104.16.117",
+ "Checksum": "35AC3EBD",
+ "Port": "34000",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15859,
+ "Name": "UrMimas",
+ "Version": "0.2.3570.17365",
+ "Address": "71.236.26.5",
+ "Checksum": "9DC30595",
+ "Port": "27016",
+ "MapName": "Mimas",
+ "Players": 0,
+ "MaxPlayers": 5,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15862,
+ "Name": "Stationeers",
+ "Version": "0.2.3570.17365",
+ "Address": "54.36.166.128",
+ "Checksum": "9CCCCC5",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15899,
+ "Name": "The D Venus",
+ "Version": "0.2.3570.17365",
+ "Address": "192.169.80.42",
+ "Checksum": "52EF5995",
+ "Port": "18265",
+ "MapName": "Venus",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15914,
+ "Name": "Executoronline Mars",
+ "Version": "0.2.3530.17210",
+ "Address": "95.216.38.190",
+ "Checksum": "2EB64593",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15921,
+ "Name": "Sanctuary",
+ "Version": "0.2.3570.17365",
+ "Address": "78.157.70.82",
+ "Checksum": "8ACED595",
+ "Port": "27016",
+||
+
+ "MapName": "Europa2",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15931,
+ "Name": "Muns (NZ)",
+ "Version": "0.2.3570.17365",
+ "Address": "101.100.143.138",
+ "Checksum": "83695095",
+ "Port": "30000",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15944,
+ "Name": "devildogs",
+ "Version": "0.2.3570.17365",
+ "Address": "74.141.20.22",
+ "Checksum": "8763F395",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15947,
+ "Name": "Avalon Reborn",
+ "Version": "0.2.3570.17365",
+ "Address": "51.89.173.203",
+ "Checksum": "CFF75995",
+ "Port": "18025",
+ "MapName": "Venus",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15961,
+ "Name": "VULCAN FR",
+ "Version": "0.2.3570.17365",
+ "Address": "82.66.177.148",
+ "Checksum": "7AAB2BBD",
+ "Port": "27016",
+ "MapName": "Vulcan2",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15974,
+ "Name": "Kevineers",
+ "Version": "0.2.3570.17365",
+ "Address": "73.42.182.16",
+ "Checksum": "EE214C95",
+ "Port": "27016",
+ "MapName": "Vulcan2",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16003,
+ "Name": "PTA Stationeers Mars",
+ "Version": "0.2.3570.17365",
+ "Address": "23.120.182.72",
+ "Checksum": "C5B3F8ED",
+ "Port": "27569",
+ "MapName": "MarsPTA",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16012,
+ "Name": "Devyns Play Thing",
+ "Version": "0.2.3588.17444",
+ "Address": "66.94.126.83",
+ "Checksum": "1076A8B5",
+ "Port": "27501",
+ "MapName": "Vulcan",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16031,
+ "Name": "FeenixDedi",
+ "Version": "0.2.3570.17365",
+ "Address": "68.3.236.182",
+ "Checksum": "F3448495",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "
+||
+MaxPlayers": 3,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16051,
+ "Name": "Bard Moon Adventure",
+ "Version": "0.2.3570.17365",
+ "Address": "5.95.156.237",
+ "Checksum": "FDFB58C5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16054,
+ "Name": "Gamers Hub Official",
+ "Version": "0.2.3570.17365",
+ "Address": "104.238.220.19",
+ "Checksum": "743818C5",
+ "Port": "25444",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16059,
+ "Name": "STONER PLANET",
+ "Version": "0.2.3588.17444",
+ "Address": "145.239.130.135",
+ "Checksum": "2C527C9D",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16061,
+ "Name": "allinone",
+ "Version": "0.2.3570.17365",
+ "Address": "84.131.212.232",
+ "Checksum": "517229ED",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16064,
+ "Name": "Peekas",
+ "Version": "0.2.3588.17444",
+ "Address": "173.212.250.184",
+ "Checksum": "88B006B5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16065,
+ "Name": "Kepler452B",
+ "Version": "0.2.3570.17365",
+ "Address": "73.158.104.124",
+ "Checksum": "8610CC5",
+ "Port": "27500",
+ "MapName": "Kepler452B",
+ "Players": 0,
+ "MaxPlayers": 30,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16070,
+ "Name": "Goatstation5",
+ "Version": "0.2.3570.17365",
+ "Address": "192.169.86.146",
+ "Checksum": "91967EED",
+ "Port": "18015",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16095,
+ "Name": "Amogus",
+ "Version": "0.2.3570.17365",
+ "Address": "185.60.46.74",
+ "Checksum": "C52E6DC5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16098,
+ "Name": "Dholio",
+ "Version": "0.2.3530.17210",
+ "Address": "154.127.54.201",
+ "Checksum": "7B290DEB",
+ "Port": "18015",
+ "MapName": "beachmars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16108,
+ "Name": "DSR",
+ "Version": "0.2.3570.17365",
+ "Address": "71.127.216.19",
+ "Checksum": "8F599DC5",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 30,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16123,
+ "Name": "Hyden",
+ "Version": "0.2.3570.17365",
+ "Address": "81.43.208.3",
+ "Checksum": "7E571595",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16125,
+ "Name": "M2M",
+ "Version": "0.2.3570.17365",
+ "Address": "178.167.195.138",
+ "Checksum": "8FB6E2C5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 11,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+
+||
+ "SessionId": 16136,
+ "Name": "Oymyakon",
+ "Version": "0.2.3570.17365",
+ "Address": "151.224.246.46",
+ "Checksum": "2C31F7C5",
+ "Port": "27016",
+ "MapName": "Syberia",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16138,
+ "Name": "BlueHell",
+ "Version": "0.2.3570.17365",
+ "Address": "178.27.166.108",
+ "Checksum": "D834E195",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16145,
+ "Name": "Tehscott's Stationeers",
+ "Version": "0.2.3588.17444",
+ "Address": "71.237.87.148",
+ "Checksum": "90B5B6CD",
+ "Port": "27016",
+ "MapName": "Europa2",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16149,
+ "Name": "Bastards Inc",
+ "Version": "0.2.3570.17365",
+ "Address": "75.174.200.93",
+ "Checksum": "8BA4B495",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 30,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16161,
+ "Name": "Luke",
+ "Version": "0.2.3570.17365",
+ "Address": "75.132.226.39",
+ "Checksum": "B23CD3ED",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16165,
+ "Name": "SpectR ServeR",
+ "Version": "0.2.3570.17365",
+ "Address": "178.65.157.15",
+ "Checksum": "1C5A3FC5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16167,
+ "Name": "Stationeers F*ckery 1: Dying on Mars",
+ "Version": "0.2.3588.17444",
+ "Address": "185.82.239.12",
+ "Checksum": "353CDF9D",
+ "Port": "25565",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 30,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16170,
+ "Name": "Artemis: Phase 2",
+ "Version": "0.2.3570.17365",
+ "Address": "143.244.166.105",
+ "Checksum": "898CDD95",
+ "Port": "27500",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16174,
+ "Name": "GuitouParty",
+ "Version": "0.2.3570.17365",
+ "Address": "90.70.112.42",
+ "Checksum": "4925FFC5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16189,
+ "Name": "Squeak",
+ "Version": "0.2.3570.17365",
+ "Address": "70.92.105.8",
+ "Checksum": "8D80EFED",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16195,
+ "Name": "stationeers survie",
+ "Version": "0.2.3570.17365",
+ "Address": "172.99.189.136",
+ "Checksum": "2439A95",
+ "Port": "20400",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16200,
+ "Name": "Berning Pham",
+ "Version": "0.2.3570.17365",
+ "Address": "136.33.249.104",
+ "Checksum": "7E99E4C5",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16201,
+ "Name": "Stationeers -Getreidebunker",
+ "Version": "0.2.3570.17365",
+ "Address": "45.141.122.194",
+ "Checksum": "97C754ED",
+ "Port": "36100",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16202,
+ "Name": "DonnyBresko",
+ "Version": "0.2.3570.17365",
+ "Address": "77.20.142.158",
+ "Checksum": "2C56E595",
+ "Port": "27016",
+ "MapName": "DoRopa",
+ "Players": 1,
+ "MaxPlayers": 3,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16217,
+ "Name": "bier",
+ "Version": "0.2.3570.17365",
+ "Address": "91.35.61.31",
+ "Checksum": "1EB4395",
+ "Port": "27016",
+ "MapName": "test",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16218,
+ "Name": "PiNgPonG",
+ "Version": "0.2.3570.17365",
+ "Address": "66.211.24.235",
+ "Checksum": "EF9BBC5",
+ "Port": "27016",
+ "MapName": "Vulcan2",
+ "Players": 1,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16219,
+ "Name": "Samael247",
+ "Version": "0.2.3570.17365",
+ "Address": "217.240.163.144",
+ "Checksum": "7CB6E1C5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16220,
+ "Name": "Hobos in Spaaace",
+ "Version": "0.2.3570.17365",
+ "Address": "73.86.89.115",
+ "Checksum": "A475DFBD",
+ "Port": "27016",
+ "MapName": "WORLD",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16221,
+ "Name": "Stationeers",
+ "Version": "0.2.3570.17365",
+ "Address": "91.162.194.51",
+ "Checksum": "11E7DFC5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 1,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16222,
+ "Name": "Stationeers Server2022",
+ "Version": "0.2.3570.17365",
+ "Address": "54.39.49.50",
+ "Checksum": "351BDCBD",
+ "Port": "25444",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16223,
+ "Name": "Family X gaming",
+ "Version": "0.2.3570.17365",
+ "Address": "216.245.216.178
+||
+",
+ "Checksum": "EDA5C3BD",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16224,
+ "Name": "Doomz",
+ "Version": "0.2.3429.16807",
+ "Address": "147.135.8.48",
+ "Checksum": "45F8C820",
+ "Port": "25444",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16225,
+ "Name": "ZoD World2",
+ "Version": "0.2.3431.16810",
+ "Address": "144.217.65.8",
+ "Checksum": "F1849B14",
+ "Port": "25448",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Stationeers/1_result.json b/tests/Protocols/Providers/Stationeers/1_result.json
new file mode 100644
index 00000000..099ebddf
--- /dev/null
+++ b/tests/Protocols/Providers/Stationeers/1_result.json
@@ -0,0 +1 @@
+{"47.158.161.12:27016":{"dedicated":1,"gq_address":"47.158.161.12","gq_joinlink":"","gq_name":"Stationeers","gq_online":true,"gq_port_client":27016,"gq_port_query":"27016","gq_protocol":"stationeers","gq_transport":"tcp","gq_type":"stationeers","hostname":"Androneers","map":"Proximab","maxplayers":10,"numplayers":1,"password":1,"type":0,"uptime":0,"version":"0.2.3570.17365"}}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Stationeers/2_response.txt b/tests/Protocols/Providers/Stationeers/2_response.txt
new file mode 100644
index 00000000..64a398d3
--- /dev/null
+++ b/tests/Protocols/Providers/Stationeers/2_response.txt
@@ -0,0 +1,974 @@
+HTTP/1.1 200 OK
+Keep-Alive: true
+Content-Length: 22496
+Server: Microsoft-HTTPAPI/2.0
+Date: Tue, 30 Aug 2022 22:30:30 GMT
+Connection: close
+
+{
+ "Count": 63,
+ "TotalPlayers": 22,
+ "GameSessions": [
+ {
+ "SessionId": 15712,
+ "Name": "Catch22",
+ "Version": "0.2.3570.17365",
+ "Address": "103.114.12.10",
+ "Checksum": "E4F1D9C5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15716,
+ "Name": "Stationeers German/Deutsch BlackLand Hallo Leute leider geht es zu zeit nur in solo spiel :-(",
+ "Version": "0.2.3570.17365",
+ "Address": "194.163.170.243",
+ "Checksum": "B5963DBD",
+ "Port": "35700",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15721,
+ "Name": "0GravityBert",
+ "Version": "0.2.3570.17365",
+ "Address": "85.215.225.45",
+ "Checksum": "E916B8BD",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 5,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15723,
+ "Name": "LM - Europa",
+ "Version": "0.2.3570.17365",
+||
+
+ "Address": "159.69.72.154",
+ "Checksum": "3AE1D2BD",
+ "Port": "25456",
+ "MapName": "Europa2",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15726,
+ "Name": "meshbase",
+ "Version": "0.2.3570.17365",
+ "Address": "103.62.50.20",
+ "Checksum": "B201B4BD",
+ "Port": "26510",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 16,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15739,
+ "Name": "4Netplayers Stationeers Server",
+ "Version": "0.2.3570.17365",
+ "Address": "62.104.16.117",
+ "Checksum": "1DCD0495",
+ "Port": "23800",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15762,
+ "Name": "Androneers",
+ "Version": "0.2.3570.17365",
+ "Address": "47.158.161.12",
+ "Checksum": "48EB8995",
+ "Port": "27016",
+ "MapName": "Proximab",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15768,
+ "Name": "Skyvale Interstellar",
+ "Version": "0.2.3570.17365",
+ "Address": "185.125.205.100",
+ "Checksum": "12FCE3C5",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15783,
+ "Name": "Apollo 4",
+ "Version": "0.2.3530.17210",
+ "Address": "87.97.24.142",
+ "Checksum": "E6432F93",
+ "Port": "27017",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15789,
+ "Name": "Grumpy",
+ "Version": "0.2.3570.17365",
+ "Address": "47.49.8.74",
+ "Checksum": "BE8B5395",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15803,
+ "Name": "Celestra FR",
+ "Version": "0.2.3570.17365",
+ "Address": "82.65.179.165",
+ "Checksum": "39B0CCBD",
+ "Port": "23520",
+ "MapName": "Europa",
+ "Players": 0,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15808,
+ "Name": "StationeersSamnick",
+ "Version": "0.2.3587.17443",
+ "Address": "159.69.72.154",
+ "Checksum": "8A8DE0B5",
+ "Port": "25448",
+ "MapName": "Mimas",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15810,
+ "Name": "Celestra Fr Mars",
+ "Version": "0.2.3570.17365",
+ "Address": "82.65.179.165",
+ "Checksum": "1207EAED",
+ "Port": "23536",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15832,
+ "Name": "Devilscary",
+ "Version": "0.2.3570.17365",
+ "Address": "74.210.225.225",
+ "Checksum": "7C080395",
+ "Port": "27516",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15844,
+ "Name": "4Netplayers Mars 1 geht leider nicht",
+ "Version": "0.2.3570.17365",
+ "Address": "62.104.16.117",
+ "Checksum": "35AC3EBD",
+ "Port": "34000",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15859,
+ "Name": "UrMimas",
+ "Version": "0.2.3570.17365",
+ "Address": "71.236.26.5",
+ "Checksum": "9D
+||
+C30595",
+ "Port": "27016",
+ "MapName": "Mimas",
+ "Players": 0,
+ "MaxPlayers": 5,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15862,
+ "Name": "Stationeers",
+ "Version": "0.2.3570.17365",
+ "Address": "54.36.166.128",
+ "Checksum": "9CCCCC5",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15899,
+ "Name": "The D Venus",
+ "Version": "0.2.3570.17365",
+ "Address": "192.169.80.42",
+ "Checksum": "52EF5995",
+ "Port": "18265",
+ "MapName": "Venus",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15914,
+ "Name": "Executoronline Mars",
+ "Version": "0.2.3530.17210",
+ "Address": "95.216.38.190",
+ "Checksum": "2EB64593",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15921,
+ "Name": "Sanctuary",
+ "Version": "0.2.3570.17365",
+ "Address": "78.157.70.82",
+ "Checksum": "8ACED595",
+ "Port": "27016",
+||
+
+ "MapName": "Europa2",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 15931,
+ "Name": "Muns (NZ)",
+ "Version": "0.2.3570.17365",
+ "Address": "101.100.143.138",
+ "Checksum": "83695095",
+ "Port": "30000",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15944,
+ "Name": "devildogs",
+ "Version": "0.2.3570.17365",
+ "Address": "74.141.20.22",
+ "Checksum": "8763F395",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15947,
+ "Name": "Avalon Reborn",
+ "Version": "0.2.3570.17365",
+ "Address": "51.89.173.203",
+ "Checksum": "CFF75995",
+ "Port": "18025",
+ "MapName": "Venus",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 15961,
+ "Name": "VULCAN FR",
+ "Version": "0.2.3570.17365",
+ "Address": "82.66.177.148",
+ "Checksum": "7AAB2BBD",
+ "Port": "27016",
+ "MapName": "Vulcan2",
+ "Pla
+||
+yers": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 15974,
+ "Name": "Kevineers",
+ "Version": "0.2.3570.17365",
+ "Address": "73.42.182.16",
+ "Checksum": "EE214C95",
+ "Port": "27016",
+ "MapName": "Vulcan2",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16003,
+ "Name": "PTA Stationeers Mars",
+ "Version": "0.2.3570.17365",
+ "Address": "23.120.182.72",
+ "Checksum": "C5B3F8ED",
+ "Port": "27569",
+ "MapName": "MarsPTA",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16012,
+ "Name": "Devyns Play Thing",
+ "Version": "0.2.3588.17444",
+ "Address": "66.94.126.83",
+ "Checksum": "1076A8B5",
+ "Port": "27501",
+ "MapName": "Vulcan",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16031,
+ "Name": "FeenixDedi",
+ "Version": "0.2.3570.17365",
+ "Address": "68.3.236.182",
+ "Checksum": "F3448495",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 3,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16051,
+ "Name": "Bard Moon Adventure",
+ "Version": "0.2.3570.17365",
+ "Address": "5.95.156.237",
+ "Checksum": "FDFB58C5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16054,
+ "Name": "Gamers Hub Official",
+ "Version": "0.2.3570.17365",
+ "Address": "104.238.220.19",
+ "Checksum": "743818C5",
+ "Port": "25444",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16059,
+ "Name": "STONER PLANET",
+ "Version": "0.2.3588.17444",
+ "Address": "145.239.130.135",
+ "Checksum": "2C527C9D",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16061,
+ "Name": "allinone",
+ "Version": "0.2.3570.17365",
+ "Address": "84.131.212.232",
+ "Checksum": "517229ED",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+
+||
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16064,
+ "Name": "Peekas",
+ "Version": "0.2.3588.17444",
+ "Address": "173.212.250.184",
+ "Checksum": "88B006B5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16065,
+ "Name": "Kepler452B",
+ "Version": "0.2.3570.17365",
+ "Address": "73.158.104.124",
+ "Checksum": "8610CC5",
+ "Port": "27500",
+ "MapName": "Kepler452B",
+ "Players": 0,
+ "MaxPlayers": 30,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16070,
+ "Name": "Goatstation5",
+ "Version": "0.2.3570.17365",
+ "Address": "192.169.86.146",
+ "Checksum": "91967EED",
+ "Port": "18015",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16095,
+ "Name": "Amogus",
+ "Version": "0.2.3570.17365",
+ "Address": "185.60.46.74",
+ "Checksum": "C52E6DC5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16098,
+ "Name": "Dholio",
+ "Version": "0.2.3530.17210",
+ "Address": "154.127.54.201",
+ "Checksum": "7B290DEB",
+ "Port": "18015",
+ "MapName": "beachmars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16108,
+ "Name": "DSR",
+ "Version": "0.2.3570.17365",
+ "Address": "71.127.216.19",
+ "Checksum": "8F599DC5",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 30,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16123,
+ "Name": "Hyden",
+ "Version": "0.2.3570.17365",
+ "Address": "81.43.208.3",
+ "Checksum": "7E571595",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16125,
+ "Name": "M2M",
+ "Version": "0.2.3570.17365",
+ "Address": "178.167.195.138",
+ "Checksum": "8FB6E2C5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 11,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+
+||
+ "SessionId": 16136,
+ "Name": "Oymyakon",
+ "Version": "0.2.3570.17365",
+ "Address": "151.224.246.46",
+ "Checksum": "2C31F7C5",
+ "Port": "27016",
+ "MapName": "Syberia",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16138,
+ "Name": "BlueHell",
+ "Version": "0.2.3570.17365",
+ "Address": "178.27.166.108",
+ "Checksum": "D834E195",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16145,
+ "Name": "Tehscott's Stationeers",
+ "Version": "0.2.3588.17444",
+ "Address": "71.237.87.148",
+ "Checksum": "90B5B6CD",
+ "Port": "27016",
+ "MapName": "Europa2",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16149,
+ "Name": "Bastards Inc",
+ "Version": "0.2.3570.17365",
+ "Address": "75.174.200.93",
+ "Checksum": "8BA4B495",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 30,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16161,
+ "Name": "Luke",
+ "Version": "0.2.3570.17365",
+ "Address": "75.132.226.39",
+ "Checksum": "B23CD3ED",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16165,
+ "Name": "SpectR ServeR",
+ "Version": "0.2.3570.17365",
+ "Address": "178.65.157.15",
+ "Checksum": "1C5A3FC5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16167,
+ "Name": "Stationeers F*ckery 1: Dying on Mars",
+ "Version": "0.2.3588.17444",
+ "Address": "185.82.239.12",
+ "Checksum": "353CDF9D",
+ "Port": "25565",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 30,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16170,
+ "Name": "Artemis: Phase 2",
+ "Version": "0.2.3570.17365",
+ "Address": "143.244.166.105",
+ "Checksum": "898CDD95",
+ "Port": "27500",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": false,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16174,
+ "Name": "GuitouParty",
+ "Version": "0.2.3570.17365",
+ "Address": "90.70.112.42",
+ "Checksum": "4925FFC5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16189,
+ "Name": "Squeak",
+ "Version": "0.2.3570.17365",
+ "Address": "70.92.105.8",
+ "Checksum": "8D80EFED",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16195,
+ "Name": "stationeers survie",
+ "Version": "0.2.3570.17365",
+ "Address": "172.99.189.136",
+ "Checksum": "2439A95",
+ "Port": "20400",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16200,
+ "Name": "Berning Pham",
+ "Version": "0.2.3570.17365",
+ "Address": "136.33.249.104",
+ "Checksum": "7E99E4C5",
+ "Port": "27016",
+ "MapName": "",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16201,
+ "Name": "Stationeers -Getreidebunker",
+
+||
+ "Version": "0.2.3570.17365",
+ "Address": "45.141.122.194",
+ "Checksum": "97C754ED",
+ "Port": "36100",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 20,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16202,
+ "Name": "DonnyBresko",
+ "Version": "0.2.3570.17365",
+ "Address": "77.20.142.158",
+ "Checksum": "2C56E595",
+ "Port": "27016",
+ "MapName": "DoRopa",
+ "Players": 1,
+ "MaxPlayers": 3,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16217,
+ "Name": "bier",
+ "Version": "0.2.3570.17365",
+ "Address": "91.35.61.31",
+ "Checksum": "1EB4395",
+ "Port": "27016",
+ "MapName": "test",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16218,
+ "Name": "PiNgPonG",
+ "Version": "0.2.3570.17365",
+ "Address": "66.211.24.235",
+ "Checksum": "EF9BBC5",
+ "Port": "27016",
+ "MapName": "Vulcan2",
+ "Players": 1,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16219,
+ "Name": "Samael247",
+ "Version": "0.2.3570.17365",
+ "Address": "217.240.163.144",
+ "Checksum": "7CB6E1C5",
+ "Port": "27016",
+ "MapName": "Mars",
+ "Players": 1,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16220,
+ "Name": "Hobos in Spaaace",
+ "Version": "0.2.3570.17365",
+ "Address": "73.86.89.115",
+ "Checksum": "A475DFBD",
+ "Port": "27016",
+ "MapName": "WORLD",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 2
+ },
+ {
+ "SessionId": 16221,
+ "Name": "Stationeers",
+ "Version": "0.2.3570.17365",
+ "Address": "91.162.194.51",
+ "Checksum": "11E7DFC5",
+ "Port": "27016",
+ "MapName": "Moon",
+ "Players": 1,
+ "MaxPlayers": 4,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 0
+ },
+ {
+ "SessionId": 16222,
+ "Name": "Stationeers Server2022",
+ "Version": "0.2.3570.17365",
+ "Address": "54.39.49.50",
+ "Checksum": "351BDCBD",
+ "Port": "25444",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 10,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16223,
+ "Name": "Family X gaming",
+ "Version": "0.2.3570.17365",
+ "Address": "216.245.216.178
+||
+",
+ "Checksum": "EDA5C3BD",
+ "Port": "18015",
+ "MapName": "Mars",
+ "Players": 0,
+ "MaxPlayers": 8,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16224,
+ "Name": "Doomz",
+ "Version": "0.2.3429.16807",
+ "Address": "147.135.8.48",
+ "Checksum": "45F8C820",
+ "Port": "25444",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ },
+ {
+ "SessionId": 16225,
+ "Name": "ZoD World2",
+ "Version": "0.2.3431.16810",
+ "Address": "144.217.65.8",
+ "Checksum": "F1849B14",
+ "Port": "25448",
+ "MapName": "Moon",
+ "Players": 0,
+ "MaxPlayers": 15,
+ "Password": true,
+ "UpTime": 0,
+ "Latency": 0,
+ "Type": 1
+ }
+ ]
+}
\ No newline at end of file
diff --git a/tests/Protocols/Providers/Stationeers/2_result.json b/tests/Protocols/Providers/Stationeers/2_result.json
new file mode 100644
index 00000000..843bed95
--- /dev/null
+++ b/tests/Protocols/Providers/Stationeers/2_result.json
@@ -0,0 +1 @@
+{"194.163.170.243:35700":{"dedicated":1,"gq_address":"194.163.170.243","gq_joinlink":"","gq_name":"Stationeers","gq_online":true,"gq_port_client":35700,"gq_port_query":"35700","gq_protocol":"stationeers","gq_transport":"tcp","gq_type":"stationeers","hostname":"Stationeers German\/Deutsch BlackLand Hallo Leute leider geht es zu zeit nur in solo spiel :-(","map":"Mars","maxplayers":20,"numplayers":0,"password":1,"type":1,"uptime":0,"version":"0.2.3570.17365"}}
\ No newline at end of file
diff --git a/tests/Protocols/Quake2.php b/tests/Protocols/Quake2.php
index c8847c34..f58c9f82 100644
--- a/tests/Protocols/Quake2.php
+++ b/tests/Protocols/Quake2.php
@@ -22,18 +22,17 @@
class Quake2 extends Base
{
-
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Quake2
+ * @var \GameQ\Protocols\Quake2
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\xFF\xFF\xFF\xFFstatus\x00",
@@ -46,7 +45,6 @@ class Quake2 extends Base
*/
public function customSetUp()
{
-
// Create the stub class
$this->stub = new \GameQ\Protocols\Quake2();
}
@@ -56,7 +54,6 @@ public function customSetUp()
*/
public function testPackets()
{
-
// Test to make sure packets are defined properly
$this->assertEquals($this->packets, $this->stub->getPacket());
}
@@ -66,7 +63,6 @@ public function testPackets()
*/
public function testInvalidPacketType()
{
-
// Read in a quake 2 source file
$source = file_get_contents(sprintf('%s/Providers/Quake2/1_response.txt', __DIR__));
diff --git a/tests/Protocols/Quake3.php b/tests/Protocols/Quake3.php
index c74ff82b..28e36148 100644
--- a/tests/Protocols/Quake3.php
+++ b/tests/Protocols/Quake3.php
@@ -22,18 +22,17 @@
class Quake3 extends Base
{
-
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Quake3
+ * @var \GameQ\Protocols\Quake3
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\xFF\xFF\xFF\xFF\x67\x65\x74\x73\x74\x61\x74\x75\x73\x0A",
diff --git a/tests/Protocols/Quake4.php b/tests/Protocols/Quake4.php
index 60999cd0..4a2e681e 100644
--- a/tests/Protocols/Quake4.php
+++ b/tests/Protocols/Quake4.php
@@ -35,7 +35,6 @@ class Quake4 extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Raknet.php b/tests/Protocols/Raknet.php
index cfd23114..13dc02de 100644
--- a/tests/Protocols/Raknet.php
+++ b/tests/Protocols/Raknet.php
@@ -25,14 +25,14 @@ class Raknet extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Raknet
+ * @var \GameQ\Protocols\Raknet
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\x01%s%s\x02\x00\x00\x00\x00\x00\x00\x00",
diff --git a/tests/Protocols/Rfactor.php b/tests/Protocols/Rfactor.php
index ddf7ade6..fc44c279 100644
--- a/tests/Protocols/Rfactor.php
+++ b/tests/Protocols/Rfactor.php
@@ -35,7 +35,6 @@ class Rfactor extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Rfactor2.php b/tests/Protocols/Rfactor2.php
index f43db283..49d1305d 100644
--- a/tests/Protocols/Rfactor2.php
+++ b/tests/Protocols/Rfactor2.php
@@ -35,7 +35,6 @@ class Rfactor2 extends Base
*/
public function testResponses($responses, $result)
{
-
// Pull the first key off the array this is the server ip:port
$server = key($result);
diff --git a/tests/Protocols/Risingstorm2.php b/tests/Protocols/Risingstorm2.php
index 7ba62209..e33ca0d7 100644
--- a/tests/Protocols/Risingstorm2.php
+++ b/tests/Protocols/Risingstorm2.php
@@ -28,7 +28,7 @@ class Risingstorm2 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Risingstorm2
+ * @var \GameQ\Protocols\Risingstorm2
*/
protected $stub;
diff --git a/tests/Protocols/Samp.php b/tests/Protocols/Samp.php
index 01e932ea..cc1653db 100644
--- a/tests/Protocols/Samp.php
+++ b/tests/Protocols/Samp.php
@@ -25,14 +25,14 @@ class Samp extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Samp
+ * @var \GameQ\Protocols\Samp
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "SAMP%si",
diff --git a/tests/Protocols/Source.php b/tests/Protocols/Source.php
index 27c67a06..4b299a7f 100644
--- a/tests/Protocols/Source.php
+++ b/tests/Protocols/Source.php
@@ -25,14 +25,14 @@ class Source extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Source
+ * @var \GameQ\Protocols\Source
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_CHALLENGE => "\xFF\xFF\xFF\xFF\x56\x00\x00\x00\x00",
@@ -103,6 +103,25 @@ public function testSkipChallengeApply()
$this->assertEquals($packets, $this->stub->getPacket());
}
+ /**
+ * Test that the challenge application is skipped if packet is not a challenge
+ */
+ public function testSkipChallengeApply()
+ {
+ $packets = $this->packets;
+
+ // Set what the packets should look like
+ $packets[\GameQ\Protocol::PACKET_DETAILS] = "\xFF\xFF\xFF\xFFTSource Engine Query\x00%s";
+ $packets[\GameQ\Protocol::PACKET_PLAYERS] = "\xFF\xFF\xFF\xFF\x55%s";
+ $packets[\GameQ\Protocol::PACKET_RULES] = "\xFF\xFF\xFF\xFF\x56%s";
+
+ // Create a fake buffer
+ $challenge_buffer = new \GameQ\Buffer("\xFF\xFF\xFF\xFF\xFFtest");
+
+ $this->stub->challengeParseAndApply($challenge_buffer);
+ $this->assertEquals($packets, $this->stub->getPacket());
+ }
+
/**
* Test invalid packet type without debug
*/
diff --git a/tests/Protocols/Starmade.php b/tests/Protocols/Starmade.php
index fc42417b..d1a493b8 100644
--- a/tests/Protocols/Starmade.php
+++ b/tests/Protocols/Starmade.php
@@ -28,14 +28,14 @@ class Starmade extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Starmade
+ * @var \GameQ\Protocols\Starmade
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\x00\x00\x00\x09\x2a\xff\xff\x01\x6f\x00\x00\x00\x00",
diff --git a/tests/Protocols/Stationeers.php b/tests/Protocols/Stationeers.php
new file mode 100644
index 00000000..cfd3cd8c
--- /dev/null
+++ b/tests/Protocols/Stationeers.php
@@ -0,0 +1,49 @@
+.
+ */
+
+namespace GameQ\Tests\Protocols;
+
+/**
+ * Test Class for Stationeers
+ *
+ * @package GameQ\Tests\Protocols
+ */
+class Stationeers extends Base
+{
+ /**
+ * Test responses for Stationeers
+ *
+ * @dataProvider loadData
+ *
+ * @param $responses
+ * @param $result
+ */
+ public function testResponses($responses, $result)
+ {
+ // Pull the first key off the array this is the server ip:port
+ $server = key($result);
+
+ $testResult = $this->queryTest(
+ $server,
+ 'stationeers',
+ $responses
+ );
+
+ $this->assertEquals($result[$server], $testResult);
+ }
+}
diff --git a/tests/Protocols/Teamspeak2.php b/tests/Protocols/Teamspeak2.php
index be81df99..ddfb7620 100644
--- a/tests/Protocols/Teamspeak2.php
+++ b/tests/Protocols/Teamspeak2.php
@@ -30,14 +30,14 @@ class Teamspeak2 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Teamspeak2
+ * @var \GameQ\Protocols\Teamspeak2
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_DETAILS => "sel %d\x0asi\x0a",
diff --git a/tests/Protocols/Teamspeak3.php b/tests/Protocols/Teamspeak3.php
index 5c81ee15..780b5f2f 100644
--- a/tests/Protocols/Teamspeak3.php
+++ b/tests/Protocols/Teamspeak3.php
@@ -30,14 +30,14 @@ class Teamspeak3 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Teamspeak3
+ * @var \GameQ\Protocols\Teamspeak3
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_DETAILS => "use port=%d\x0Aserverinfo\x0A",
diff --git a/tests/Protocols/Teeworlds.php b/tests/Protocols/Teeworlds.php
index cfacf0ff..8fbc4fe5 100644
--- a/tests/Protocols/Teeworlds.php
+++ b/tests/Protocols/Teeworlds.php
@@ -30,14 +30,14 @@ class Teeworlds extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Teeworlds
+ * @var \GameQ\Protocols\Teeworlds
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_ALL => "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x67\x69\x65\x33\x05",
diff --git a/tests/Protocols/Tibia.php b/tests/Protocols/Tibia.php
index 59ce3177..1e4f1918 100644
--- a/tests/Protocols/Tibia.php
+++ b/tests/Protocols/Tibia.php
@@ -25,14 +25,14 @@ class Tibia extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Tibia
+ * @var \GameQ\Protocols\Tibia
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_STATUS => "\x06\x00\xFF\xFF\x69\x6E\x66\x6F",
diff --git a/tests/Protocols/Unreal2.php b/tests/Protocols/Unreal2.php
index 057c62a4..c7b0efd2 100644
--- a/tests/Protocols/Unreal2.php
+++ b/tests/Protocols/Unreal2.php
@@ -25,14 +25,14 @@ class Unreal2 extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Unreal2
+ * @var \GameQ\Protocols\Unreal2
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_DETAILS => "\x79\x00\x00\x00\x00",
diff --git a/tests/Protocols/Ventrilo.php b/tests/Protocols/Ventrilo.php
index 52e1048c..4f6d9ca3 100644
--- a/tests/Protocols/Ventrilo.php
+++ b/tests/Protocols/Ventrilo.php
@@ -28,14 +28,14 @@ class Ventrilo extends Base
/**
* Holds stub on setup
*
- * @type \GameQ\Protocols\Ventrilo
+ * @var \GameQ\Protocols\Ventrilo
*/
protected $stub;
/**
* Holds the expected packets for this protocol class
*
- * @type array
+ * @var array
*/
protected $packets = [
\GameQ\Protocol::PACKET_ALL =>
diff --git a/tests/Protocols/generate_provider b/tests/Protocols/generate_provider
index 23ef2d55..a8bf7171 100644
--- a/tests/Protocols/generate_provider
+++ b/tests/Protocols/generate_provider
@@ -72,7 +72,7 @@ try {
// Make the directory if it does not already exist
if (!is_dir($provider_dir)) {
- mkdir($provider_dir, null, true);
+ mkdir($provider_dir, 0751, true);
}
// Figure out the number of files in the provider directory
@@ -102,12 +102,18 @@ try {
// Process
$results = $gq->process();
+ // Build the path where we want to store the result file
+ $result_file = sprintf('%s/%d_result.json', $provider_dir, $index);
+
// Save the result into a file
- $result = file_put_contents(sprintf('%s/%d_result.json', $provider_dir, $index), json_encode(
+ $result = file_put_contents($result_file, json_encode(
$results,
JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR
));
+ // Ensure the result file has proper permissions
+ chmod($result_file, 0640);
+
exit(0);
} catch (Exception $e) {
echo $e->getMessage() . PHP_EOL;
diff --git a/tests/Query/Core.php b/tests/Query/Core.php
index 079b1296..e89b42bc 100644
--- a/tests/Query/Core.php
+++ b/tests/Query/Core.php
@@ -32,7 +32,6 @@ class Core extends TestBase
*/
public function testSet()
{
-
$stub = $this->getMockForAbstractClass('\GameQ\Query\Core', [ ]);
// Set the properties
diff --git a/tests/Server.php b/tests/Server.php
index 6be6e03d..0e0b1f4d 100644
--- a/tests/Server.php
+++ b/tests/Server.php
@@ -89,7 +89,6 @@ public function testSetServerOptions()
*/
public function testServerId()
{
-
$id = '127.0.0.1:27015';
// Create a server with id
diff --git a/tests/TestBase.php b/tests/TestBase.php
index 9b22b76c..419b29f3 100644
--- a/tests/TestBase.php
+++ b/tests/TestBase.php
@@ -20,7 +20,6 @@
class TestBase extends \PHPUnit\Framework\TestCase
{
-
/**
* TestBase constructor overload.
*