Понятие 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 использования
<?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}
<?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»
<?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», но может вы придумали им другое назначение? Спасибо всем, надеюсь вам понравилось, обращайтесь с вопросами.
данные о протоколах
Автор: Denis_Minin