Пример как пинговать сервер CS 1.6
<?php
function ping_cs_server($server_ip, $server_port = 27015)
{
$res = fsockopen('udp://'.$server_ip, $server_port);
stream_set_timeout($res, 0, 80000);
fwrite($res, "\xFF\xFF\xFF\xFFTSource Engine Query\0");
$raw = fread($res, 5);
if(ord($raw[4]) == 0x6d)
return true;
return false;
}
?>
Я использовал данную функцию для автоматизации рестарта сервера, иногда это говно зависает и превращается в зомби без падения процесса, а с помощью непосредственного пинга удается узнать, что сервер отвалился и выполнить операцию по его рестарту.
-------------
Далее функция получения флагов из игры
<?php
$GLOBALS['CS_FLAG'] = array('a' => 1<<0, 'b' => 1<<1, 'c' => 1<<2,
'd' => 1<<3, 'e' => 1<<4, 'f' => 1<<5,
'g' => 1<<6, 'h' => 1<<7, 'i' => 1<<8,
'j' => 1<<9, 'k' => 1<<10, 'l' => 1<<11,
'm' => 1<<12, 'n' => 1<<13, 'o' => 1<<14,
'p' => 1<<15, 'q' => 1<<16, 'r' => 1<<17,
's' => 1<<18, 't' => 1<<19, 'u' => 1<<20,
'v' => 1<<21, 'w' => 1<<22, 'x' => 1<<23,
'y' => 1<<24, 'z' => 1<<25);
$GLOBALS['CS_FLAG_N'] = array(1<<0,1<<1,1<<2,1<<3,1<<4,1<<5,
1<<6,1<<7,1<<8,1<<9,1<<10,1<<11,
1<<12,1<<13,1<<14,1<<15,1<<16,1<<17,
1<<18,1<<19,1<<20,1<<21,1<<22,1<<23,1<<24,1<<25);
$GLOBALS['CS_FLAG_ALP'] = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z');
function cs_get_player_flags($flags)
{
$flags_str = 'abcdefghijklmnopqrstuvwxyz';
$flags_length = strlen($flags_str);
$usr_flags = 0;
for($i=0;$i<$flags_length;$i++)
{
if(strpos($flags, $flags_str[$i]) !== false)
$usr_flags += 1<<$i;
}
return $usr_flags;
}
?>
С помощью флагов устанавливаются права на обычном классике, но флаги можно расширять сколь угодно добавляя на сервере дополнительные глобалки с флагами.
Например у меня было 2 глобалки, одни стандартные для определения прав админа, на возможность менять карты и тд. Другие глобалки использовались для предоставления платного доступа к ништякам :)
------------------
Функция расчетного периода с учетом годичного смещения и космического межгалактического времени :)
<?
echo add_date('31.01.2010 19:40:32',120);
function add_date($givendate,$month_count) {
$cd = strtotime($givendate);
for($i=0;$i<$month_count;$i++){
$newdate = date('d.m.Y H:i:s', mktime(date('H',$cd), date('i',$cd), date('s',$cd), date('m',$cd)+1, date('d',$cd), date('Y',$cd)));
$cd = strtotime($newdate);
}
return $newdate;
}
?>
Многие быдло-провайдеры используют схему 30 дней, на чем экономят до 7% годичной прибыли, в крупных компаниях это мешки бобла :-)
-----
Авто-рестартилка серваков (под BSD, но не сложно переписать)
<?php
error_reporting(0);
date_default_timezone_set('Europe/Moscow');
get_servers_config();
$GLOBALS['cstrike_serverinfo'] = new ServerInfo();
$GLOBALS['cstrike_servercontroll'] = new ServerControll();
$error_detected = false;
check_run_files();
for($i=0;$i<$GLOBALS['cstrike_serverscount'];$i++)
{
$error_count[$i] = 0;
$GLOBALS['cstrike_serverlastmap'][$i] = get_first_map($GLOBALS['cstrike_srvconfig'][$i]['server_fullpath']);
}
while(true)
{
for($i=0;$i<$GLOBALS['cstrike_serverscount'];$i++)
{
$GLOBALS['cstrike_servercontroll']->connect($i);
if($GLOBALS['cstrike_servercontroll']->get_server_state($i))
{
if($error_count[$i] != 0)
$error_count[$i] = 0;
}
else
{
$error_count[$i]++;
}
if($error_count[$i] >= 5)
{
system('killall -9 '.$GLOBALS['cstrike_srvconfig'][$i]['server_bin']);
system('su '.$GLOBALS['cstrike_srvconfig'][$i]['server_exec_user'].' '.$GLOBALS['cstrike_srvconfig'][$i]['server_fullpath'].'/cstrike_run_srv.sh '.$GLOBALS['cstrike_srvconfig'][$i]['server_fullpath'].' ./'.$GLOBALS['cstrike_srvconfig'][$i]['server_bin'].' '.$GLOBALS['cstrike_srvconfig'][$i]['server_ip'].' '.$GLOBALS['cstrike_srvconfig'][$i]['server_port'].' '.$GLOBALS['cstrike_serverlastmap'][$i]);
file_put_contents('./logs/'.$GLOBALS['cstrike_srvconfig'][$i]['server_ip'].'_'.$GLOBALS['cstrike_srvconfig'][$i]['server_port'].'.log', 'RESTARTED: '.date('d.n.Y h:i:s')." MAP: ".$GLOBALS['cstrike_serverlastmap'][$i]."\r\n", FILE_APPEND);
sleep(20);
}
if($error_count[$i] > 0)
$error_detected = true;
}
if($error_detected)
{
sleep(3);
}
else
{
sleep(10);
}
$error_detected = false;
}
function check_run_files()
{
for($i=0;$i<$GLOBALS['cstrike_serverscount'];$i++)
{
if(!file_exists($GLOBALS['cstrike_srvconfig'][$i]['server_fullpath'].'/cstrike_run_srv.sh'))
{
file_put_contents($GLOBALS['cstrike_srvconfig'][$i]['server_fullpath'].'/cstrike_run_srv.sh', '#!/bin/sh'."\n\n".'cd $1'."\n".'./hlds_run -game cstrike -binary $2 +sv_lan 0 +ip $3 -port $4 -norestart +map $5 +maxplayers 32 -insecure -pingboost 3 -sys_ticrate 350 > /dev/null 2>&1 &');
chmod($GLOBALS['cstrike_srvconfig'][$i]['server_fullpath'].'/cstrike_run_srv.sh', 0744);
}
}
}
function get_servers_config(){
$temp = parse_ini_file('./config/servers.ini', true);
foreach ($temp as $key){
$GLOBALS['cstrike_srvconfig'][] = $key;
}
$GLOBALS['cstrike_serverscount'] = count($GLOBALS['cstrike_srvconfig']);
}
function get_first_map($dir){
$dir .= '/cstrike/maps';
$handle = opendir($dir);
while(false !== ($file = readdir($handle)))
{
if(strpos($file, ".bsp"))
{
closedir($handle);
return substr($file, 0, -4);
}
}
closedir($handle);
return false;
}
class ServerControll
{
public function connect($server_num){
$GLOBALS['cstrike_serverinfo']->connect($GLOBALS['cstrike_srvconfig'][$server_num]['server_ip'], $GLOBALS['cstrike_srvconfig'][$server_num]['server_port']);
}
public function get_server_state($server_num){
$server_info = $GLOBALS['cstrike_serverinfo']->getInfo();
$server_test = trim($server_info['name']);
if(!empty($server_test))
{
if($GLOBALS['cstrike_serverlastmap'][$server_num] != $server_info['map'])
$GLOBALS['cstrike_serverlastmap'][$server_num] = $server_info['map'];
return true;
}
else
{
return false;
}
}
}
class ServerInfo {
var $connected;
var $resource;
var $ip;
var $port;
var $raw;
function ServerInfo() {
$this->connected = false;
$this->resource = false;
}
function connect( $address, $port = 27015) {
$this->disconnect();
$this->port = (int)$port;
$this->ip = gethostbyname( $address );
if( $this->resource = fsockopen( 'udp://' . $this->ip, $this->port ) ) {
$this->connected = true;
stream_set_timeout( $this->resource, 2);
}
}
function disconnect() {
if( $this->connected ) {
fclose( $this->resource );
$this->connected = false;
}
}
function getByte() {
$return = ord( $this->raw[0] );
$this->raw = substr( $this->raw , 1 );
return $return;
}
function getShort() {
$return = (ord($this->raw[1]) << 8) | ord($this->raw[0]);
$this->raw = substr( $this->raw , 2 );
return $return;
}
function getLong() {
$lo = (ord($this->raw[1]) << 8) | ord($this->raw[0]);
$hi = (ord($this->raw[3]) << 8) | ord($this->raw[2]);
$this->raw = substr( $this->raw , 4 );
return ($hi << 16) | $lo;
}
function getFloat() {
$lo = (ord($this->raw[1]) << 8) | ord($this->raw[0]);
$hi = (ord($this->raw[2]) << 8) | ord($this->raw[3]);
$this->raw = substr( $this->raw , 4 );
return ($hi << 16) | $lo;
}
function getString() {
$str = "";
$i = 0;
$n = strlen( $this->raw );
while( ( $this->raw[$i] != "\0" ) && ( $i < $n ) ) {
$str .= $this->raw[$i];
$i++;
}
$this->raw = substr( $this->raw , strlen( $str ) + 1);
return $str;
}
function getInfo() {
if( !$this->connected )
return false;
$return = array();
fwrite( $this->resource, "\xFF\xFF\xFF\xFFTSource Engine Query\0" );
fread( $this->resource, 4 );
$status = socket_get_status( $this->resource );
if( $status['unread_bytes'] > 0 ) {
$this->raw = fread( $this->resource, $status['unread_bytes'] );
$tmp = $this->getByte();
if( $tmp == 0x6d ) {
$this->getString();
$return['name'] = $this->getString();
$return['map'] = $this->getString();
$return['directory'] = $this->getString();
$return['desсriрtion'] = $this->getString();
$return['players'] = $this->getByte();
$return['max_players'] = $this->getByte();
$return['version'] = $this->getByte();
$this->getByte();
$tmp = chr( $this->getByte() );
if( $tmp == 'l' )
$return['os'] = 'Linux';
else
$return['os'] = 'Windows';
if( $this->getByte() == 0x01 )
$return['password'] = 'yes';
else
$return['password'] = 'no';
if( $this->getByte() == 0x01 ) {
$this->getString();
$this->getString();
$this->raw = substr( $this->raw, 11 );
}
if( $this->getByte() == 0x01 )
$return['secure'] = 'yes';
else
$return['secure'] = 'no';
$return['bots'] = $this->getByte();
} elseif( $tmp == 0x49 ) {
$return['version'] = $this->getByte();
$return['name'] = $this->getString();
$return['map'] = $this->getString();
$return['directory'] = $this->getString();
$return['desсriрtion'] = $this->getString();
$this->raw = substr( $this->raw, 2 );
$return['players'] = $this->getByte();
$return['max_players'] = $this->getByte();
$return['bots'] = $this->getByte();
$this->getByte();
$tmp = chr( $this->getByte() );
if( $tmp == 'l' )
$return['os'] = 'Linux';
else
$return['os'] = 'Windows';
if( $this->getByte() == 0x01 )
$return['password'] = 'yes';
else
$return['password'] = 'no';
if( $this->getByte() == 0x01 )
$return['secure'] = 'yes';
else
$return['secure'] = 'no';
}
} else {
$this->disconnect();
return false;
}
return $return;
}
function getPlayers() {
$return = array();
if( !$this->connected )
return $return;
fwrite( $this->resource, "\xFF\xFF\xFF\xFF\x55" . $this->getChallenge() );
fread( $this->resource, 4 );
$status = socket_get_status( $this->resource );
if( $status['unread_bytes'] > 0 ) {
$this->raw = fread( $this->resource, $status['unread_bytes'] );
if( $this->getByte() == 0x44 ) {
$num = $this->getByte();
for($i = 0; $i < $num; $i++ ) {
$tmp = $this->getByte();
$name = $this->getString();
$kills = $this->getLong();
$time = @unpack( "f1float", $this->raw );
$this->raw = substr( $this->raw, 4 );
$return[] = array(
'name' => $name,
'kills' => $kills,
'time' => gmdate( "H:i:s", (int)$time['float'] )
);
}
}
}
return $return;
}
function getChallenge() {
if( !$this->connected )
return false;
fwrite( $this->resource, "\xFF\xFF\xFF\xFF\x55\xFF\xFF\xFF\xFF" );
fread( $this->resource, 5 );
return fread( $this->resource, 4 );
}
function getRules() {
$return = array();
if( !$this->connected )
return $return;
fwrite( $this->resource, "\xFF\xFF\xFF\xFF\x56" . $this->getChallenge() );
fread( $this->resource, 13 );
$status = socket_get_status( $this->resource );
if( $status['unread_bytes'] > 0 ) {
$this->raw = fread( $this->resource, $status['unread_bytes'] );
if( $this->getByte() == 0x45 ) {
$this->getShort();
$arr = explode( "\0", $this->raw );
$num = count( $arr );
for( $i = 0; $i < $num ; $i++ )
$return[$arr[$i]] = $arr[++$i];
}
}
return $return;
}
}
?>
Файл конфига
[Classic]
server_ip = 127.0.0.1
server_port = 27015
server_bin = zm_54
server_fullpath = /usr/local/cs_servers/classic/srv
server_exec_user = I
[NightFear]
server_ip = 127.0.0.1
server_port = 27015
server_bin = zm_123
server_fullpath = /usr/local/cs_servers/345/srv
server_exec_user = I
[NightChaos]
server_ip = 127.0.0.1
server_port = 27015
server_bin = zm_234
server_fullpath = /usr/local/cs_servers/345s/srv
server_exec_user = I
В принципе есть готовый меганавороченный ZM сервер, ZM advanced сосет болтяру, лично мной переписано почти всё, около 500 тысяч строк кода, но Valve подонки не захотели баги и утечки в сервере устранять + сервер не приносил прибыли, хотя монетизация в него входит полностью на автомате все работает :)
Эх печально, думаю вот попробывать себя в minecraft, но риски слишком велики, а сидеть сутками на пролет кодить, ради 20000 тысяч рублей в месяц с сервака, чет лениво :)