GameQ is a PHP library for querying many kinds of multiplayer game and voice servers. A single GameQ instance can query mixed UDP, TCP, TLS, HTTP, and master-list protocols and return a consistent result structure.
This repository is the maintained SoftCreatR Media fork of Austinb/GameQ. Version 5 targets PHP 8.1 and newer, provides a documented migration path from 4.x, and deliberately modernizes the extension API while adding current protocol support, stricter parsing, bounded batching, and modern quality checks.
- 186 game, voice-server, and generic protocol identifiers.
- Concurrent mixed-protocol queries with configurable batch and response limits.
- Normalized
gq_*fields plus protocol-native data, players, teams, and join links. - Broad coverage through established families such as Source and GoldSource, GameSpy, Quake, Unreal, Doom 3, Frostbite, RakNet, and dedicated voice-server protocols.
- Direct UDP, TCP, TLS, and SSL queries alongside protocols that use HTTP APIs, plugins, or public master lists.
- PHPStan at maximum level, PHPUnit coverage for captured protocol responses, and automated compatibility checks within the GameQ 5 release line.
Composer is recommended:
composer require softcreatr/gameq:^5.2GameQ requires PHP 8.1 or newer and the curl, libxml, simplexml, and xml extensions. The optional bz2 extension is only needed to decode compressed Source/A2S split responses. See the installation guide for standalone loading and platform details.
<?php
require __DIR__ . '/vendor/autoload.php';
use GameQ\GameQ;
$gameQ = new GameQ();
$gameQ->addServers([
[
'id' => 'source-server',
'type' => 'css',
'host' => '192.0.2.10:27015',
],
[
'id' => 'unreal-server',
'type' => 'ut2004',
'host' => '192.0.2.20:7777',
],
]);
$gameQ
->setOption('timeout', 5)
->setOption('max_servers_per_batch', 50);
$results = $gameQ->process();
if ($results['source-server']['gq_online']) {
printf(
"%s: %d/%d players\n",
$results['source-server']['gq_hostname'],
$results['source-server']['gq_numplayers'],
$results['source-server']['gq_maxplayers'],
);
}The port in host is always the client/connect port. GameQ calculates the query port where a protocol has a known offset; use the per-server query_port option when the server uses a custom query port.
All HTTP requests, including EOS/Dragonwilds, WARDOGS, official directories, authenticated APIs, and legacy HTTP packet protocols, use the configured transport. UDP and non-HTTP TCP queries continue to use GameQ's query transport.
The default GameQ\Http\CurlClient works without additional dependencies.
Use any PSR-18 client with PSR-17 request and stream factories through the optional
GameQ\Http\Psr18Client adapter. Configure its proxy, TLS verification, redirect
refusal, and timeout on the underlying client: PSR-18 has no per-request options.
The adapter bounds response reads, but an underlying client may buffer the response
before returning it.
For Guzzle, the optional GameQ\Http\GuzzleClient adapter applies each protocol's
timeout and decoded response size limit during transfer, verifies TLS, and refuses
redirects. Install Guzzle separately (composer require guzzlehttp/guzzle:^7.9):
use GameQ\GameQ;
use GameQ\Http\GuzzleClient;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
$factory = new HttpFactory();
$gameQ = (new GameQ())->setHttpClient(new GuzzleClient(
new Client(['proxy' => 'http://proxy.example:8080']),
$factory,
$factory,
));For another PSR-18 implementation, replace GuzzleClient with Psr18Client and
provide your client and factories. For transports without PSR support, implement
GameQ\Http\ClientInterface::send(Request $request): Response. Honor the request's
timeout and size limit, verify TLS, refuse redirects, and throw HttpException for
transfer failures. HTTP error statuses are returned as responses; protocols decide
whether they mean offline. Windrose login cookies are scoped to the current server
and query, and directory caches are scoped to the configured transport.
setHttpClient() updates existing servers and servers added later. Independently
created Server/Protocol instances can use protocolInstance()->setHttpClient().
The standalone autoloader remains supported without installing PSR or Guzzle packages
when using the default cURL transport.
In WoltLab Suite, use new wcf\system\gameq\ScGameQ() from the developer package.
It injects a client from the Suite's HttpFactory and honors PROXY_SERVER_HTTP.
Project documentation is maintained in the separate GameQ Wiki, updated from the useful parts of the upstream wiki for this fork and version 5.
Protocol-specific credentials and HTTP endpoints need additional care. Read protocol options and security guidance before exposing queries through a public application.
- Report reproducible problems through GitHub Issues.
- See CONTRIBUTING.md before submitting changes.
- Run
composer testfor the complete local quality suite. - Review CHANGELOG.md before upgrading.
GameQ is licensed under the GNU Lesser General Public License 3.0 or later.