- PVSM.RU - https://www.pvsm.ru -

Разберем, что такое Source-Query

Разберем, что такое Source-Query - 1
Понятие Source-Query
Source-Query, используется для отображения информации о сервере, так же он используется для управления сервером, через RCON команды. Source-Query разработал «xPaw». Сервера используют протокол «Source», таким образом «Source-Query» получает данные о сервере.

Типы данных
Все запросы сервера состоят из пяти основных типов данных, упакованных вместе в поток данных. Все типы имеют немного обратный порядок байт.
Пример
1. Байт-8 битовый символ или целое число без знака
2. Короткий-16-битное целое число
3. Длинной-32 битное целое число
4. Плавающий 32 бит с плавающей точкой
5. Длинный-длинный- 64 бит целое число без знака
Строка-байтовое поле переменной длины, закодированные в «UTF-8», которые завершаются «0х00»

Протокол

Так как «Source-Query» был создан для получения и управления серверами «Steam». Steam использует размер пакета 1400 байт + «IP / UDP» заголовков. Если запрос или ответ нуждается в большем количестве пакетов для данных, то он запускает пакеты с дополнительным заголовком.

Поддерживаемые игры
Counter-Strike 1.6
Counter-Strike: Global Offensive
Team Fortress 2
Left 4 Dead 2
Rag Doll Kung Fu
The Ship
Garry's Mod
Nuclear Dawn
Dino D-Day
Arma 3
Call of Duty: Modern Warfare 3
Starbound
Space Engineers
Rust
Quake Live
ARK: Survival Evolved
Minecraft

Список поддерживаемых игр обновляется, и расширяется. Если вы хотите узнать поддерживает ли «Source-Query» выбранную вами игру то просто добавьте игру в «Steam» в избранные, если «Steam» показывает вам информацию о сервере, то он поддерживается «Source-Query»

Функции

Connect( $Ip, $Port, $Timeout, $Engine )	Открывает соединение с сервером
Disconnect( )     закрывает все открытые соединения с сервером
Ping( )	Пингует сервер
GetInfo( )	Возвращает информацию о сервере в массиве
GetPlayers( )	Возвращает игроков на сервере в массиве
GetRules( )	Возвращает правила сервера (CVars) в массиве
SetRconPassword( $Password )	Устанавливает RCON пароль, для последующего использования с RCON ()
Устанавливает RCON пароль, для последующего использования с RCON ()
Rcon( $Command )	Выполняет RCON команду на сервере
Выполняет RCON команду на сервере

Требования

PHP (5.5 и выше)
64-bit PHP или Модуль "GMP" (sudo apt-get install php5-gmp) "PHP-GMP"
Веб-сервер должен разрешать UDP соединения

Пример использования

<?php
	require __DIR__ . '/../SourceQuery/bootstrap.php';
	use xPawSourceQuerySourceQuery;
	
	// For the sake of this example
	Header( 'Content-Type: text/plain' );
	Header( 'X-Content-Type-Options: nosniff' );
	
	// Edit this ->
	define( 'SQ_SERVER_ADDR', 'localhost' );
	define( 'SQ_SERVER_PORT', 27015 );
	define( 'SQ_TIMEOUT',     1 );
	define( 'SQ_ENGINE',      SourceQuery::SOURCE );
	// Edit this <-
	
	$Query = new SourceQuery( );
	
	try
	{
		$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE );
		
		print_r( $Query->GetInfo( ) );
		print_r( $Query->GetPlayers( ) );
		print_r( $Query->GetRules( ) );
	}
	catch( Exception $e )
	{
		echo $e->getMessage( );
	}
	finally
	{
		$Query->Disconnect( );
	}

Пример страницы

Пример страницы

<?php
	require __DIR__ . '/../SourceQuery/bootstrap.php';
	use xPawSourceQuerySourceQuery;
	
	// Edit this ->
	define( 'SQ_SERVER_ADDR', 'localhost' );
	define( 'SQ_SERVER_PORT', 27015 );
	define( 'SQ_TIMEOUT',     3 );
	define( 'SQ_ENGINE',      SourceQuery::SOURCE );
	// Edit this <-
	
	$Timer = MicroTime( true );
	
	$Query = new SourceQuery( );
	
	$Info    = Array( );
	$Rules   = Array( );
	$Players = Array( );
	
	try
	{
		$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE );
		//$Query->SetUseOldGetChallengeMethod( true ); // Use this when players/rules retrieval fails on games like Starbound
		
		$Info    = $Query->GetInfo( );
		$Players = $Query->GetPlayers( );
		$Rules   = $Query->GetRules( );
	}
	catch( Exception $e )
	{
		$Exception = $e;
	}
	finally
	{
		$Query->Disconnect( );
	}
	
	$Timer = Number_Format( MicroTime( true ) - $Timer, 4, '.', '' );
?>
<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<title>Source Query PHP Library</title>
	
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
	<style type="text/css">
		.table {
			table-layout: fixed;
			border-top-color: #428BCA;
		}
		
		.table td {
			overflow-x: auto;
		}
		
		.table thead th {
			background-color: #428BCA;
			border-color: #428BCA !important;
			color: #FFF;
		}
		
		.info-column {
			width: 120px;
		}
		
		.frags-column {
			width: 80px;
		}
	</style>
</head>

<body>
	<div class="jumbotron">
		<div class="container">
			<h1>Source Query PHP Library</h1>
			
			<p class="lead">This library was created to query game server which use the Source (Steamworks) query protocol.</p>
			
			<p>
				<a class="btn btn-large btn-primary" href="https://xpaw.me">Made by xPaw</a>
				<a class="btn btn-large btn-primary" href="https://github.com/xPaw/PHP-Source-Query">View on GitHub</a>
				<a class="btn btn-large btn-danger" href="https://github.com/xPaw/PHP-Source-Query/blob/master/LICENSE">LGPL v2.1</a>
			</p>
		</div>
	</div>
		
	<div class="container">
<?php if( isset( $Exception ) ): ?>
		<div class="panel panel-primary">
			<div class="panel-heading"><?php echo Get_Class( $Exception ); ?> at line <?php echo $Exception->getLine( ); ?></div>
			<p><b><?php echo htmlspecialchars( $Exception->getMessage( ) ); ?></b></p>
			<p><?php echo nl2br( $e->getTraceAsString(), false ); ?></p>
		</div>
<?php else: ?>
		<div class="row">
			<div class="col-sm-6">
				<table class="table table-bordered table-striped">
					<thead>
						<tr>
							<th class="info-column">Server Info</th>
							<th><span class="label label-<?php echo $Timer > 1.0 ? 'danger' : 'success'; ?>"><?php echo $Timer; ?>s</span></th>
						</tr>
					</thead>
					<tbody>
<?php if( Is_Array( $Info ) ): ?>
<?php foreach( $Info as $InfoKey => $InfoValue ): ?>
						<tr>
							<td><?php echo htmlspecialchars( $InfoKey ); ?></td>
							<td><?php
	if( Is_Array( $InfoValue ) )
	{
		echo "<pre>";
		print_r( $InfoValue );
		echo "</pre>";
	}
	else
	{
		if( $InfoValue === true )
		{
			echo 'true';
		}
		else if( $InfoValue === false )
		{
			echo 'false';
		}
		else
		{
			echo htmlspecialchars( $InfoValue );
		}
	}
?></td>
						</tr>
<?php endforeach; ?>
<?php else: ?>
						<tr>
							<td colspan="2">No information received</td>
						</tr>
<?php endif; ?>
					</tbody>
				</table>
			</div>
			<div class="col-sm-6">
				<table class="table table-bordered table-striped">
					<thead>
						<tr>
							<th>Player <span class="label label-info"><?php echo count( $Players ); ?></span></th>
							<th class="frags-column">Frags</th>
							<th class="frags-column">Time</th>
						</tr>
					</thead>
					<tbody>
<?php if( !empty( $Players ) ): ?>
<?php foreach( $Players as $Player ): ?>
						<tr>
							<td><?php echo htmlspecialchars( $Player[ 'Name' ] ); ?></td>
							<td><?php echo $Player[ 'Frags' ]; ?></td>
							<td><?php echo $Player[ 'TimeF' ]; ?></td>
						</tr>
<?php endforeach; ?>
<?php else: ?>
						<tr>
							<td colspan="3">No players received</td>
						</tr>
<?php endif; ?>
					</tbody>
				</table>
			</div>
		</div>
		<div class="row">
			<div class="col-sm-12">
				<table class="table table-bordered table-striped">
					<thead>
						<tr>
							<th colspan="2">Rules <span class="label label-info"><?php echo count( $Rules ); ?></span></th>
						</tr>
					</thead>
					<tbody>
<?php if( Is_Array( $Rules ) ): ?>
<?php foreach( $Rules as $Rule => $Value ): ?>
						<tr>
							<td><?php echo htmlspecialchars( $Rule ); ?></td>
							<td><?php echo htmlspecialchars( $Value ); ?></td>
						</tr>
<?php endforeach; ?>
<?php else: ?>
						<tr>
							<td colspan="2">No rules received</td>
						</tr>
<?php endif; ?>
					</tbody>
				</table>
			</div>
		</div>
<?php endif; ?>
	</div>
</body>
</html>

Пример rcon использования

Пример rcon

<?php
	require __DIR__ . '/../SourceQuery/bootstrap.php';
	use xPawSourceQuerySourceQuery;
	
	// For the sake of this example
	Header( 'Content-Type: text/plain' );
	Header( 'X-Content-Type-Options: nosniff' );
	
	// Edit this ->
	define( 'SQ_SERVER_ADDR', 'localhost' );
	define( 'SQ_SERVER_PORT', 27015 );
	define( 'SQ_TIMEOUT',     1 );
	define( 'SQ_ENGINE',      SourceQuery::SOURCE );
	// Edit this <-
	
	$Query = new SourceQuery( );
	
	try
	{
		$Query->Connect( SQ_SERVER_ADDR, SQ_SERVER_PORT, SQ_TIMEOUT, SQ_ENGINE );
		
		$Query->SetRconPassword( 'my_awesome_password' );
		
		var_dump( $Query->Rcon( 'say hello' ) );
	}
	catch( Exception $e )
	{
		echo $e->getMessage( );
	}
	finally
	{
		$Query->Disconnect( );
	}

Пример страницы {2}

Пример страницы {2}

<?php
// Подключение класса
require __DIR__ . '/SourceQuery/SourceQuery.class.php';

// IP
$ip = '31.135.208.99';

// Порт сервера
$port = 27203;

// Таймаут
$timeout = 1;

// Экземпляр
$Query = new SourceQuery();

// Попытаться выполнить какое-то действие. В нашем случае выполнить метод подключения к серверу
try {
	$Query->Connect($ip, $port, $timeout, SourceQuery :: GOLDSOURCE);
} catch(Exception $e) {
	// если произошла ошибка, и в классе прописано исключение, то попытаться словить это исключение и остановить скрипт, выведя ошибку
	exit($e->getMessage());
}

// Получение информации и запись ее в переменную
$info = $Query->GetInfo();

// Получение игроков и запись их в переменную
$players = $Query->GetPlayers();

// Отключение от сервера
$Query->Disconnect();
?>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Страница с инфой сервера</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
  </head>
  <body>
		<div class="container">
			<div class="panel panel-default">
				<div class="panel-heading">
					<h3>Информация</h3>
				</div>
				<div class="panel-body">
					<table class="table table-bordered">
						<?php if($info):?>
						<tr>
							<th>Название сервера</th>
							<td><?php echo $info['HostName']?></td>
						</tr>
						<tr>
							<th>Адрес сервера сервера</th>
							<td><?php echo $ip . ':' . $port?></td>
						</tr>
						<tr>
							<th>Карта</th>
							<td><?php echo $info['Map']?></td>
						</tr>
						<tr>
							<th>Игроков сейчас</th>
							<td><?php echo $info['Players']?></td>
						</tr>
						<tr>
							<th>Игроков всего</th>
							<td><?php echo $info['MaxPlayers']?></td>
						</tr>
						<?php else:?>
						<tr>
							<th>Информация не получена. Сервер возможно выключен</th>
						</tr>
						<?php endif;?>
					</table>
				</div>
			</div>
			<div class="panel panel-default">
				<div class="panel-heading">
					<h3>Информация</h3>
				</div>
				<div class="panel-body">
					<table class="table table-bordered table-condenced">
						<?php if($players):?>
						<thead>
							<tr>
								<th>Ник</th>
								<th>Счет</th>
								<th>Время</th>
							</tr>
						</thead>
						<tbody>
							<?php foreach($players as $player):?>
							<tr>
								<td><?php echo htmlspecialchars($player['Name'], ENT_QUOTES)?></td>
								<td><?php echo intval($player['Frags'])?></td>
								<td><?php echo $player['TimeF']?></td>
							</tr>
							<?php endforeach;?>
						</tbody>
						<?php else:?>
						<tr><td>Нет игроков</td></tr>
						<?php endif;?>
					</table>
				</div>
			</div>
	  </div>
  </body>
</html>

TeamSpeak

Так же вы можете использовать «Source-Query» в своих целях. Можно вывести информацию о сервере, как на заголовке публикации, баннер будет обновляться каждые 30 сек. после выводя информацию о сервере.

Пример для «TeamSpeak»

Пример использования для TS

<?php
    
    require_once('libraries/TeamSpeak3/TeamSpeak3.php');
    require_once('libraries/SourceQuery/bootstrap.php');
    use xPawSourceQuerySourceQuery;
    
    $replacer = [
        "ts3" => [
            "%status%" => "virtualserver_status",
            "%sid%" => "virtualserver_id",
            "%sport%" => "virtualserver_port",
            "%platform%" => "virtualserver_platform",
            "%servername%" => "virtualserver_name",
            "%serverversion%" => "virtualserver_version",
            "%maxclients%" => "virtualserver_maxclients",
            "%clientsonline%" => "virtualserver_clientsonline",
            "%channelcount%" => "virtualserver_channelsonline",
            "%packetloss%" => "virtualserver_total_packetloss_total",
            "%ping%" => "virtualserver_total_ping"
        ]
    ];

    $package = [
        'general' => [
            'static' => [
                '%timeHi%', '%timeHis%', '%date%'
            ]
        ],
        'ts3' => [
            'static' => [
                '%status%', '%sid%', '%sport%', '%platform%', '%servername%', '%serverversion%', '%packetloss_floored%', '%ping_floored%', 
                '%packetloss_00%', '%maxclients%', '%clientsonline%', '%channelcount%', '%packetloss%', '%ping%', '%realclients%', '%nickname%'
            ],
            'regex' => [
                "%groupcount[([0-9,]{0,})]%",
            ],
        ],
    ];

    function getIp() {
        if (isset($_SERVER['HTTP_CLIENT_IP']))
            return $_SERVER['HTTP_CLIENT_IP'];
        else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
            return $_SERVER['HTTP_X_FORWARDED_FOR'];
        else if(isset($_SERVER['HTTP_X_FORWARDED']))
            return $_SERVER['HTTP_X_FORWARDED'];
        else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
            return $_SERVER['HTTP_FORWARDED_FOR'];
        else if(isset($_SERVER['HTTP_FORWARDED']))
            return $_SERVER['HTTP_FORWARDED'];
        else if(isset($_SERVER['REMOTE_ADDR']))
            return $_SERVER['REMOTE_ADDR'];
        else
            return NULL;
    }
    
    function paintText($image, $fontsize, $xpos, $ypos, $color, $fontfile, $text) {
        $hex = str_replace("#", "", $color);
        if(strlen($hex) == 3) {
            $r = hexdec(substr($hex,0,1).substr($hex,0,1));
            $g = hexdec(substr($hex,1,1).substr($hex,1,1));
            $b = hexdec(substr($hex,2,1).substr($hex,2,1));
        } else {
            $r = hexdec(substr($hex,0,2));
            $g = hexdec(substr($hex,2,2));
            $b = hexdec(substr($hex,4,2));
        }
        imagettftext($image,$fontsize,0,$xpos,$ypos,imagecolorallocate($image, $r, $g, $b),$fontfile,$text);
        return;
    }
    
    function getImage() {
        global $config;
        $packetmanager = json_decode(file_get_contents('cache/packages.json'), 1);
        $image = imagecreatefrompng('cache/cached_img');
        if (in_array('ts3', $packetmanager['packages'])) {
            require_once('cache/clients.php');
            if (!empty($nicklist[getIp()])) {
                $nickname = $nicklist[getIp()];
                foreach ($config['textfield'] as $field) {
                    if (strpos($field['text'], '%nickname%') !== FALSE) {
                        paintText($image, $field['fontsize'], $field['xpos'], $field['ypos'], $field['color'], $field['fontfile'], str_replace('%nickname%', $nickname, $field['text'])); 
                    }
                }
            }
        }
        return $image;
    }
    
    try {
        if (!function_exists('imagettftext')) {
            throw new Exception ('PHP-GD not installed');
        }
        if (!is_writable('cache/')) {
            throw new Exception ('Нет прав для записи 'cache/' в директории');
        }
        if (!file_exists('config.php' )) {
            throw new Exception ('config.php does not exist');
        } else {
            require_once('config.php' ); 
        }
        if (!file_exists('cache/packages.json') || filemtime('cache/packages.json') < filemtime('config.php')) {
            $packages = [];
            if (count($config['sourcequery']) > 0 and $config['sqenable']) $packages[] = 'sq';
            foreach ($config['textfield'] as $txt) {
                foreach ($package as $key => $pkg) {
                    if (array_key_exists('static', $pkg)) {
                        foreach ($pkg['static'] as $static) {
                            if (strpos($txt['text'], $static) !== false and !in_array($key, $packages)) $packages[] = $key;
                        }
                    }
                    if (array_key_exists('regex', $pkg)) {
                        foreach ($pkg['regex'] as $regex) {
                            preg_match_all('/'.$regex.'/i', $txt['text'], $out);
                            if (count($out[0]) > 0 and !in_array($key, $packages)) {
                                $packages[] = $key;
                            }
                        }
                    }
                }
            }
            $packagefile = fopen('cache/packages.json', 'w+');
            fwrite($packagefile, json_encode(['packages' => $packages],1));
            fclose($packagefile);
        }
        
        $packetmanager = json_decode(file_get_contents('cache/packages.json'), 1);
        
        if (
            (
                file_exists('cache/cached_img')
                and filemtime('cache/cached_img') > (time() - $config['syncintervall'])
                //and strpos('TeamSpeak3', $_SERVER['HTTP_USER_AGENT']) !== FALSE
            ) || (
                file_exists('cache/cache.lock')
            )
        ){
            $i = 0;
            while (file_exists('cache/cache.lock')) {
                if ($i >= 10) throw new Exception ('Cache Lock exists... Please Remove the File 'cache.lock' in Folder 'cache' manually if it still exists after this Error!');
                $i++;
                sleep(1);
            }
            header('Content-Type: image/png');
            imagepng(getImage());
            die();
        }
        
        fclose(fopen("cache/cache.lock", "w+"));
        
        if (!file_exists($config['backgroundimage'])) throw new Exception ('Error! Background Image not found! Check your config! Searched at '.$config['backgroundimage']);
        $image = imagecreatefrompng($config['backgroundimage']);
        
        
        if (in_array('ts3', $packetmanager['packages'])) {
            try {
                $ts3 = TeamSpeak3::factory(
                    "serverquery://". $config['teamspeak']['loginname'] .":". $config['teamspeak']['loginpass'] 
                    ."@". $config['teamspeak']['ip'] .":". $config['teamspeak']['queryport'] 
                    ."/?server_port=". $config['teamspeak']['serverport'] 
                    ."&nickname=Banner%20Generator"
                );
            } catch (Exception $e) {
                if (!strpos('TeamSpeak3-ImageFetcher', $_SERVER['HTTP_USER_AGENT'])) throw $e;
                $i = 0;
                while (file_exists('cache/cache.lock')) {
                    if ($i >= 10) throw new Exception ('Cache Lock exists... Please Remove the File 'cache.lock' in Folder 'cache' manually if it still exists after this Error!');
                    $i++;
                    sleep(1);
                }
                header('Content-Type: image/png');
                imagepng(getImage());
                die();
            }
            $groupcount = [];
            $serverinfo = $ts3->getInfo();
            $clients = $ts3->clientList(['client_type' => 0]);
            foreach ($clients as $client) {
                $ts3clients[htmlentities($client->connection_client_ip)] = htmlentities($client->client_nickname);
            }
            $clientcache = fopen('cache/clients.php', 'w+');
            fwrite($clientcache, '<?php $nicklist = json_decode(''.str_replace("'", "'", json_encode($ts3clients, 1)).'',1);');
            fclose($clientcache);
        }
        if (in_array('sq', $packetmanager['packages'])) {
            $sqinfo = [];
            foreach ($config['sourcequery'] as $server => $conf) {
                try {
                    $sq = new SourceQuery();
                    $sq->Connect($conf['ip'], $conf['port'], $conf['timeout'], SourceQuery::SOURCE);
                    $y = 12;
                    foreach ($sq->GetInfo() as $key => $value) {
                        $sqinfo[$server][$key] = $value;
                        if ($conf['debug']) {
                            $color = imagecolorallocate($image, 255, 0, 0);
                            imagettftext($image, 9, 0, 4, $y, $color, $config['sqlistfont'], 'Use "%sqinfo['.$server.']['.$key.']%" in Textfield to Display "'.$value.'"');
                            $y = $y + 11;
                        }
                    }
                    $sq->Disconnect();
                } catch (Exception $e) {
                    $color = imagecolorallocate($image, 255, 0, 0);
                    imagettftext($image, 11, 0, 4, 15, $color, $config['sqlistfont'], 'SourceQuery Error on Server "'.$server.'":'.$e->getMessage()
                    );
                }
            }
        }

        foreach ($config['textfield'] as $field) {
            if (!file_exists($field['fontfile'])) throw new Exception ('Font File not found! Searched at '.$field['fontfile'].PHP_EOL.'You may need to set the absolute path (from root directory /var/www/...)');
            if (strpos($field['text'], '%nickname%') !== FALSE) continue;
            if (in_array('sq', $packetmanager['packages'])) {
                $field['text'] = preg_replace_callback('/%sqinfo[(.*?)][(.*?)]%/', function($matches) {
                    global $sqinfo;
                    return $sqinfo[$matches[1]][$matches[2]];
                }, $field['text']);
            }
            if (in_array('ts3', $packetmanager['packages'])) {
                foreach ($replacer['ts3'] as $k => $v) {
                    $field['text'] = str_replace($k, $serverinfo[$v], $field['text']);
                }
                $field['text'] = preg_replace_callback('/%groupcount[([0-9,]{0,})]%/', function($match) {
                    global $ts3;
                    $count = 0;
                    $groups = explode(',',$match[1]);
                    foreach ($ts3->clientList(['client_type' => 0]) as $client) {
                        foreach (explode(',',$client->client_servergroups) as $g) {
                            if (in_array($g,$groups)) {
                                $count++;
                                break;
                            }
                        }
                    }
                    return $count;
                }, $field['text']);
                foreach ($groupcount as $k => $v) {
                    $field['text'] = str_replace($k, $groupcount[$k], $field['text']);
                }
                $field['text'] = str_replace('%realclients%', $serverinfo['virtualserver_clientsonline']-$serverinfo['virtualserver_queryclientsonline'], $field['text']);
                $field['text'] = str_replace('%ping_floored%', floor(htmlentities($serverinfo['virtualserver_total_ping'])), $field['text']);
                $field['text'] = str_replace('%packetloss_00%', round(htmlentities($serverinfo['virtualserver_total_packetloss_total']), 2, PHP_ROUND_HALF_DOWN), $field['text']);
                $field['text'] = str_replace('%packetloss_floored%', floor(htmlentities($serverinfo['virtualserver_total_packetloss_total'])), $field['text']);
            }
            $field['text'] = str_replace('%timeHi%', date("H:i"), $field['text']);
            $field['text'] = str_replace('%timeHis%', date("H:i:s"), $field['text']);
            $field['text'] = str_replace('%date%', date("d.m.Y"), $field['text']);
            paintText($image, $field['fontsize'], $field['xpos'], $field['ypos'], $field['color'], $field['fontfile'], $field['text']);           
        }
        imagepng($image, 'cache/cached_img');
        unlink('cache/cache.lock');
        header('Content-Type: image/png');
        imagepng(getImage());
        imagedestroy($image);
    } catch (Exception $e) {
        echo $e->getMessage();
        if (file_exists('cache/cache.lock')) unlink('cache/cache.lock');
    }

А так же config

<?php   
$config = array('textfield' => [], 'sourcequery' => []);

    /*
    ** Teamspeak Configurations
    */

    //Teamspeak Connection IP
    $config['teamspeak']['ip'] = '192.168.0.3';
    //Teamspeak Query Port
    $config['teamspeak']['queryport'] = '10011';
    //Teamspeak Connection/Voice Port
    $config['teamspeak']['serverport'] = '9987'; 
    //Teamspeak Query Login Name
    $config['teamspeak']['loginname'] = 'serveradmin';
    //Teamspeak Query Password
    $config['teamspeak']['loginpass'] = 'cgixTVmy';
    
    //Background Image to use
    $config['backgroundimage'] = 'banner-layout.png';

    //Refresh Intervall for the Image Generator in seconds
    $config['syncintervall'] = 60;
    
    
    //Source Query
    
    //Изначально включен SourceQuery
    $config['sqenable'] = true;
    //Шрифт для списка всех доступных параметров для данного сервера
    $config['sqlistfont'] = 'font/arial.ttf';
    
    
    /*

    
    /*
        $config['sourcequery']['server1'] = [
            //
            'ip' => '192.168.0.3',
            //
            'port' => '27015',
            //
            'timeout' => 1,
            //
            'debug' => true,
        ];
        
    */
    
    //Конец Source Query
   
    

    /*
    
        $config['textfield'][] = [
            'text' => '',
            'xpos' => '',
            'ypos' => '',
            'fontsize' => '',
            'fontfile' => 'font/bank.ttf',
            'color' => '',
        ];
        
    */
    
    
    $config['textfield'][] = [
        'text' => '%channelcount%',
        'xpos' => '595',
        'ypos' => '230',
        'fontsize' => '22',
        'fontfile' => 'font/bank.ttf',
        'color' => '#1C86EE',
    ];
    
    $config['textfield'][] = [
        'text' => '%date%',
        'xpos' => '570',
        'ypos' => '320',
        'fontsize' => '16',
        'fontfile' => 'font/bank.ttf',
        'color' => '#CD2626',
    ];
    
    $config['textfield'][] = [
        'text' => '%clientsonline%/%maxclients%',
        'xpos' => '570',
        'ypos' => '65',
        'fontsize' => '22',
        'fontfile' => 'font/bank.ttf',
        'color' => '#1C86EE',
    ];
    
    $config['textfield'][] = [
        'text' => '%timeHi%',
        'xpos' => '590',
        'ypos' => '295',
        'fontsize' => '16',
        'fontfile' => 'font/bank.ttf',
        'color' => '#CD2626',
    ];
    
    $config['textfield'][] = [
        'text' => '%groupcount[9,203,204,79,102,111]%',
        'xpos' => '610',
        'ypos' => '150',
        'fontsize' => '22',
        'fontfile' => 'font/bank.ttf',
        'color' => '#CD2626',
    ];
    
    
    /*
        Показывает ник нейм пользователя в баннере
    */
    $config['textfield'][] = [
        'text' => 'Привет %nickname% <3',
        'xpos' => '100',
        'ypos' => '430',
        'fontsize' => '24',
        'fontfile' => 'font/bank.ttf',
        'color' => '#e74c3c',
    ];
    
    /*
        Пример использования SourceQuery для отображения на баннере сервера ARMA III
    */
    /*
        $config['textfield'][] = [
            'text' => 'SourceQuery Slots:',
            'xpos' => '150',
            'ypos' => '350',
            'fontsize' => '24',
            'fontfile' => 'font/bank.ttf',
            'color' => '#ecf0f1',
        ];
        
        $config['textfield'][] = [
            'text' => '%sqinfo[server1][Players]%/%sqinfo[server1][MaxPlayers]%',
            'xpos' => '220',
            'ypos' => '400',
            'fontsize' => '24',
            'fontfile' => 'font/bank.ttf',
            'color' => '#ecf0f1',
        ];
    */

Вывод
Это были примеры применения «Source-Query», но может вы придумали им другое назначение? Спасибо всем, надеюсь вам понравилось, обращайтесь с вопросами.
Разберем, что такое Source-Query - 2
данные о протоколах [1]

Автор: Denis_Minin

Источник [2]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/php-2/133309

Ссылки в тексте:

[1] данные о протоколах: https://developer.valvesoftware.com/wiki/Server_queries

[2] Источник: https://habrahabr.ru/post/303172/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best