Skip to main content
GamePanelX V3 integrates the GameQ library to provide real-time server status monitoring, player counts, and server information. GameQ queries game servers using their native protocols to retrieve accurate, up-to-date information.

Overview

GameQ is a PHP library that communicates with game servers using their query protocols (Source, Quake, GameSpy, etc.). It retrieves information such as:
  • Online/Offline status
  • Current player count
  • Maximum players
  • Server name/hostname
  • Current map
  • Game mode
  • Additional game-specific data
GameQ is an open-source library included with GamePanelX. The version used is compatible with PHP 5.2+ and supports over 100 game types.

GameQ Library Location

GamePanelX includes two GameQ implementations:

Main GameQ Class

Location: includes/classes/gameq.php Legacy wrapper class that loads the GameQ library.

GameQ Library

Location: includes/GameQ/ Complete GameQ library with:
  • GameQ.php - Main GameQ class (v2.0.1)
  • gameq/protocols/ - Protocol definitions for each game
  • gameq/filters/ - Output filters
  • gameq/ - Core library components

Basic Usage

Querying a Single Server

<?php
require_once('includes/GameQ/GameQ.php');

// Create GameQ instance
$gq = GameQ::factory();

// Add server
$gq->addServer([
    'type' => 'csgo',
    'host' => '192.168.1.100:27015',
]);

// Set timeout
$gq->setOption('timeout', 5);

// Query servers
$results = $gq->requestData();

// Display results
echo '<pre>';
print_r($results);
echo '</pre>';
?>

Querying Multiple Servers

<?php
require_once('includes/GameQ/GameQ.php');

$gq = GameQ::factory();

// Add multiple servers
$servers = [
    'server1' => [
        'type' => 'csgo',
        'host' => '192.168.1.100:27015',
    ],
    'server2' => [
        'type' => 'tf2',
        'host' => '192.168.1.101:27015',
    ],
    'server3' => [
        'type' => 'minecraft',
        'host' => '192.168.1.102:25565',
    ],
];

$gq->addServers($servers);
$gq->setOption('timeout', 3);
$results = $gq->requestData();

foreach ($results as $server_id => $data) {
    echo "Server: $server_id\n";
    echo "Status: " . ($data['gq_online'] ? 'Online' : 'Offline') . "\n";
    echo "Players: {$data['gq_numplayers']}/{$data['gq_maxplayers']}\n\n";
}
?>

GamePanelX Integration

Server List Integration

GamePanelX uses GameQ in the server listing to show real-time status:
// Build array of servers for GameQ
$gameq_arr = array();
$total_srv = 0;

while($row_srv = mysql_fetch_array($result_srv))
{
    // Add GameQ required info
    if($row_srv['id'])          $gameq_arr[$total_srv]['id']   = $row_srv['id'];
    if($row_srv['gameq_name'])  $gameq_arr[$total_srv]['type'] = $row_srv['gameq_name'];
    if($row_srv['port'])        $gameq_arr[$total_srv]['host'] = ':' . $row_srv['port'];
    if($row_srv['ip'])          $gameq_arr[$total_srv]['host'] = $row_srv['ip'] . $gameq_arr[$total_srv]['host'];
    
    $total_srv++;
}

// Get GameQ status
require(DOCROOT.'/includes/GameQ/GameQ.php');
$gq = GameQ::factory();
$gq->addServers($gameq_arr);
$gq->setOption('timeout', 8);
$gq->setFilter('normalise');
$gq_results = $gq->requestData();

// Process results
foreach($srv_arr as $row_srv)
{
    $srv_id           = $row_srv['id'];
    $gameq_status     = $gq_results[$srv_id]['gq_online'];
    $gameq_numplayers = $gq_results[$srv_id]['gq_numplayers'];
    $gameq_maxplayers = $gq_results[$srv_id]['gq_maxplayers'];
    
    // Display status
    if($gameq_status == 'online') {
        $srv_status = '<font color="green">Online</font>';
    } else {
        $srv_status = '<font color="red">Offline</font>';
    }
}

Server Details Page

Query a specific server for detailed information:
<?php
// Get server info from database
$srv_info = $Servers->getinfo($srv_id);

// Query via GameQ
$gq = GameQ::factory();
$gq->addServer('server', [
    'type' => $srv_info['gameq_name'],
    'host' => $srv_info['ip'] . ':' . $srv_info['port'],
]);

$gq->setOption('timeout', 5);
$results = $gq->requestData();

$server_data = $results['server'];

// Display detailed info
echo "Server Name: " . $server_data['gq_hostname'] . "<br>";
echo "Map: " . $server_data['gq_mapname'] . "<br>";
echo "Players: {$server_data['gq_numplayers']}/{$server_data['gq_maxplayers']}<br>";

// Player list
if (isset($server_data['players'])) {
    echo "<h3>Players Online</h3>";
    foreach ($server_data['players'] as $player) {
        echo "- {$player['gq_name']} (Score: {$player['gq_score']})<br>";
    }
}
?>

GameQ API Reference

Factory Method

$gq = GameQ::factory();
Creates a new GameQ instance.

Adding Servers

addServer()

$gq->addServer(string $id, array $server);
Parameters:
  • $id - Unique identifier for the server
  • $server - Array with server configuration:
    • type - Game type (see Supported Games)
    • host - IP:Port or hostname:port
Example:
$gq->addServer('my_csgo_server', [
    'type' => 'csgo',
    'host' => '192.168.1.100:27015',
]);

addServers()

$gq->addServers(array $servers);
Add multiple servers at once. Example:
$servers = [
    'server1' => ['type' => 'csgo', 'host' => '192.168.1.100:27015'],
    'server2' => ['type' => 'tf2', 'host' => '192.168.1.101:27015'],
];
$gq->addServers($servers);

Setting Options

setOption()

$gq->setOption(string $option, mixed $value);
Available Options:
OptionTypeDefaultDescription
timeoutint3Query timeout in seconds
debugboolfalseEnable debug output
stream_timeoutint200000Socket stream timeout (microseconds)
write_waitint500Pause between socket writes (microseconds)
Example:
$gq->setOption('timeout', 8);        // 8 second timeout
$gq->setOption('debug', true);       // Enable debugging

Filters

setFilter()

$gq->setFilter(string $name, array $params = []);
Apply output filters to normalize data. Available Filters:
  • normalise - Standardizes output keys (recommended)
  • stripcolor - Removes color codes from strings
  • core - Basic filtering
Example:
$gq->setFilter('normalise');
$gq->setFilter('stripcolor');

Querying Servers

requestData()

$results = $gq->requestData();
Queries all added servers and returns results array. Returns: Array of server data indexed by server ID.

Response Format

Array
(
    [server_id] => Array
    (
        [gq_online]      => 1              // Online status (1/0)
        [gq_address]     => 192.168.1.100  // IP address
        [gq_port]        => 27015          // Port
        [gq_type]        => csgo           // Game type
        [gq_hostname]    => My Server      // Server name
        [gq_mapname]     => de_dust2       // Current map
        [gq_numplayers]  => 8              // Current players
        [gq_maxplayers]  => 16             // Max players
        [gq_password]    => 0              // Password protected
        
        // Game-specific data
        [players] => Array                 // Player list
        [rules]   => Array                 // Server rules/cvars
    )
)

Standard Response Keys

All game types return these standard keys (when using normalise filter):
  • gq_online - Server online status (true/false)
  • gq_address - Server IP address
  • gq_port - Server port
  • gq_type - Game type identifier
  • gq_prot - Protocol used
  • gq_hostname - Server name/hostname
  • gq_mapname - Current map
  • gq_numplayers - Current player count
  • gq_maxplayers - Maximum players
  • gq_password - Password protected (1/0)

Player Data

When available, player information includes:
[players] => Array
(
    [0] => Array
    (
        [gq_name]  => PlayerName
        [gq_score] => 25
        [gq_time]  => 1245
    )
)

Supported Games

GameQ supports 100+ game types. Common games in GamePanelX:

Source Engine Games

GameType IDDefault Port
Counter-Strike: Global Offensivecsgo27015
Counter-Strike: Sourcecss27015
Team Fortress 2tf227015
Left 4 Dead 2l4d227015
Garry’s Modgarrysmod27015
Half-Life 2: Deathmatchhl2dm27015
GameType IDDefault Port
Minecraftminecraft25565
ARK: Survival Evolvedarkse27015
Rustrust28015
Killing Floor 2kf27777
7 Days to Die7daystodie26900
Insurgencyinsurgency27015

Legacy Games

GameType IDDefault Port
Counter-Strike 1.6cs1627015
Team Fortress Classictfc27015
Half-Lifehalflife27015
Quake III Arenaquake327960
Unreal Tournament 2004ut20047777
Check includes/GameQ/gameq/protocols/ directory for the complete list of supported game protocols.

Advanced Usage

Custom Server Options

Pass additional options to specific servers:
$gq->addServer('server1', [
    'type' => 'csgo',
    'host' => '192.168.1.100:27015',
    'options' => [
        'query_port' => 27016,    // Custom query port
    ],
]);

Raw Data Mode

Get raw protocol responses without processing:
$gq->setOption('raw', true);
$raw_results = $gq->requestData();

// Returns unprocessed packet data
print_r($raw_results);

Debugging

Enable debug mode to troubleshoot query issues:
$gq->setOption('debug', true);
$results = $gq->requestData();

// Debug output will show:
// - Packets sent
// - Responses received
// - Parsing errors

Error Handling

Check for online status before accessing data:
$results = $gq->requestData();

foreach ($results as $server_id => $data) {
    if ($data['gq_online']) {
        // Server is online, data is reliable
        echo "Server: {$data['gq_hostname']}\n";
        echo "Players: {$data['gq_numplayers']}/{$data['gq_maxplayers']}\n";
    } else {
        // Server is offline or not responding
        echo "Server $server_id is offline\n";
    }
}

Performance Optimization

Batch Queries

Query multiple servers in a single request:
// ✅ Efficient - Single query operation
$gq->addServers($all_servers);
$results = $gq->requestData();

// ❌ Inefficient - Multiple query operations
foreach ($servers as $server) {
    $gq = GameQ::factory();
    $gq->addServer($server);
    $result = $gq->requestData();
}

Timeout Settings

Balance between accuracy and performance:
// Fast query, may miss slow-responding servers
$gq->setOption('timeout', 2);

// Slower but more reliable
$gq->setOption('timeout', 8);

// For LAN servers
$gq->setOption('timeout', 1);

Caching Results

Cache GameQ results to reduce query frequency:
$cache_file = '/tmp/gameq_cache.json';
$cache_time = 60; // 60 seconds

if (file_exists($cache_file) && (time() - filemtime($cache_file)) < $cache_time) {
    // Use cached data
    $results = json_decode(file_get_contents($cache_file), true);
} else {
    // Query and cache
    $gq = GameQ::factory();
    $gq->addServers($servers);
    $results = $gq->requestData();
    
    file_put_contents($cache_file, json_encode($results));
}

Common Issues

Causes:
  • Firewall blocking query port
  • Query timeout too short
  • Wrong game type specified
  • Server query port differs from game port
Solutions:
// Increase timeout
$gq->setOption('timeout', 10);

// Verify game type is correct
$gq->addServer('server', [
    'type' => 'csgo',  // Must match actual game
    'host' => '192.168.1.100:27015',
]);

// Check firewall allows UDP on query port
// For Source games, query port = game port + 1 (usually)
Cause: Some games don’t report players via standard query.Solution: Check if game supports player queries:
$results = $gq->requestData();

if (isset($results['server']['players']) && is_array($results['server']['players'])) {
    // Game supports player list
    $player_count = count($results['server']['players']);
} else {
    // Use numeric count if available
    $player_count = $results['server']['gq_numplayers'];
}
Cause: Server hasn’t fully started or is changing maps.Solution: Handle missing data gracefully:
$hostname = isset($data['gq_hostname']) ? $data['gq_hostname'] : 'Unknown';
$map = isset($data['gq_mapname']) ? $data['gq_mapname'] : 'Loading...';
Solutions:
  1. Reduce timeout:
$gq->setOption('timeout', 3);
  1. Query fewer servers at once:
// Query in batches of 10
$batches = array_chunk($servers, 10);
foreach ($batches as $batch) {
    $gq = GameQ::factory();
    $gq->addServers($batch);
    $results = $gq->requestData();
}
  1. Use asynchronous queries (requires custom implementation)

Integration Examples

Server Status Widget

Display real-time server status on your website:
<?php
require_once('includes/GameQ/GameQ.php');

$gq = GameQ::factory();
$gq->addServer('main', [
    'type' => 'csgo',
    'host' => '192.168.1.100:27015',
]);
$gq->setOption('timeout', 3);
$gq->setFilter('normalise');

$results = $gq->requestData();
$server = $results['main'];

if ($server['gq_online']) {
    ?>
    <div class="server-widget online">
        <h3><?php echo htmlspecialchars($server['gq_hostname']); ?></h3>
        <p>Map: <?php echo htmlspecialchars($server['gq_mapname']); ?></p>
        <p>Players: <?php echo $server['gq_numplayers']; ?>/<?php echo $server['gq_maxplayers']; ?></p>
        <p class="status"> Online</p>
    </div>
    <?php
} else {
    ?>
    <div class="server-widget offline">
        <h3>Server Offline</h3>
        <p class="status"> Offline</p>
    </div>
    <?php
}
?>

JSON API Endpoint

Create an API endpoint for server status:
<?php
header('Content-Type: application/json');
require_once('includes/GameQ/GameQ.php');

$gq = GameQ::factory();

// Add servers from database or config
$servers = [
    'server1' => ['type' => 'csgo', 'host' => '192.168.1.100:27015'],
    'server2' => ['type' => 'tf2', 'host' => '192.168.1.101:27015'],
];

$gq->addServers($servers);
$gq->setOption('timeout', 5);
$gq->setFilter('normalise');

$results = $gq->requestData();

// Format response
$response = [
    'success' => true,
    'timestamp' => time(),
    'servers' => [],
];

foreach ($results as $id => $data) {
    $response['servers'][] = [
        'id' => $id,
        'online' => $data['gq_online'],
        'name' => $data['gq_hostname'] ?? 'Unknown',
        'map' => $data['gq_mapname'] ?? '',
        'players' => [
            'current' => $data['gq_numplayers'] ?? 0,
            'max' => $data['gq_maxplayers'] ?? 0,
        ],
    ];
}

echo json_encode($response, JSON_PRETTY_PRINT);
?>

AJAX Server Status

Update server status without page reload:
function updateServerStatus() {
    fetch('api/server-status.php')
        .then(response => response.json())
        .then(data => {
            data.servers.forEach(server => {
                const element = document.getElementById('server-' + server.id);
                element.querySelector('.status').textContent = server.online ? 'Online' : 'Offline';
                element.querySelector('.players').textContent = 
                    server.players.current + '/' + server.players.max;
                element.querySelector('.map').textContent = server.map;
            });
        });
}

// Update every 30 seconds
setInterval(updateServerStatus, 30000);

Best Practices

Standardizes output keys across different game types:
$gq->setFilter('normalise');
Balance between speed and reliability:
// LAN servers
$gq->setOption('timeout', 1);

// Internet servers
$gq->setOption('timeout', 5);

// Unreliable connections
$gq->setOption('timeout', 10);
if (!isset($results[$server_id]) || !$results[$server_id]['gq_online']) {
    // Show offline status
    echo "Server temporarily unavailable";
    return;
}

// Process online server data
Never trust raw server data:
$hostname = htmlspecialchars($data['gq_hostname'] ?? 'Unknown Server');
$map = htmlspecialchars($data['gq_mapname'] ?? 'Unknown');

Troubleshooting

Enable Debug Mode

$gq->setOption('debug', true);
error_reporting(E_ALL);
ini_set('display_errors', 1);

$results = $gq->requestData();

Check Protocol Files

Verify the protocol file exists:
ls -la includes/GameQ/gameq/protocols/csgo.php

Test Network Connectivity

# UDP connectivity test
nc -u -v 192.168.1.100 27015

# Check if port is open
nmap -sU -p 27015 192.168.1.100

Manual Query Test

Test GameQ in isolation:
<?php
require_once('includes/GameQ/GameQ.php');

$gq = GameQ::factory();
$gq->setOption('debug', true);
$gq->setOption('timeout', 10);

$gq->addServer('test', [
    'type' => 'csgo',
    'host' => '192.168.1.100:27015',
]);

echo "<pre>";
$results = $gq->requestData();
print_r($results);
echo "</pre>";
?>

Reference

GameQ Version

Version: 2.0.1
PHP Requirements: PHP 5.2+
Recommended: PHP 5.3+

Required PHP Extensions

  • Bzip2: php-bzip2
  • Zlib: php-zlib
  • Sockets: php-sockets

Protocol Directory

includes/GameQ/gameq/protocols/ Each game has a protocol file (e.g., csgo.php, minecraft.php) that defines how to query that specific game type.

Filter Directory

includes/GameQ/gameq/filters/ Contains filters for processing query results.

Build docs developers (and LLMs) love