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
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:
Option Type Default Description timeoutint 3 Query timeout in seconds debugbool false Enable debug output stream_timeoutint 200000 Socket stream timeout (microseconds) write_waitint 500 Pause 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.
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
Game Type ID Default Port Counter-Strike: Global Offensive csgo27015 Counter-Strike: Source css27015 Team Fortress 2 tf227015 Left 4 Dead 2 l4d227015 Garry’s Mod garrysmod27015 Half-Life 2: Deathmatch hl2dm27015
Other Popular Games
Game Type ID Default Port Minecraft minecraft25565 ARK: Survival Evolved arkse27015 Rust rust28015 Killing Floor 2 kf27777 7 Days to Die 7daystodie26900 Insurgency insurgency27015
Legacy Games
Game Type ID Default Port Counter-Strike 1.6 cs1627015 Team Fortress Classic tfc27015 Half-Life halflife27015 Quake III Arena quake327960 Unreal Tournament 2004 ut20047777
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 " ;
}
}
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
Server shows offline but is actually online
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:
Reduce timeout:
$gq -> setOption ( 'timeout' , 3 );
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 ();
}
Use asynchronous queries (requires custom implementation)
Integration Examples
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
Always use the normalise filter
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 );
Handle offline servers gracefully
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.