Location: PHPKode > scripts > Soldat Server Stats > soldat-server-stats/SoldatServer.php
<?php

require('SoldatPlayer.php');

/**
 * SoldatServer class
 *
 * Stores Soldat server information.
 *
 * @copyright  2009 Tomaž Muraus
 * @license    http://www.gnu.org/copyleft/gpl.html   GPL License
 * @version    Release: 1.0
 * @link       http://www.tomaz-muraus.info
 */
class SoldatServer
{
	protected $_ip;
	protected $_port;
	protected $_timeout;
	protected $_socket = null;
	protected $_command = "s";

	protected $_ping;
    protected $_version;
    protected $_name;
    protected $_map;
    protected $_gametype;
    protected $_playerCount;
    protected $_maxPlayers;
    protected $_rules = array();
    protected $_players = array();

	/**
	 * Constructor.
	 *
	 * @param string $ip Server IP address.
	 * @param int $port Server port.
	 * @param int $timeout Connection and socket read/write timeout in seconds.
	 */
	public function __construct($ip, $port = 23073, $timeout = 2)
	{
		$this->_ip = $ip;
		$this->_port = $port + 123;
		$this->_timeout = $timeout;
	}

	public function getIp()
	{
	    return $this->_ip;
	}

	public function getPort()
	{
	    return $this->_port;
	}

	public function getPing()
	{
	    return $this->_ping;
	}

	public function getVersion()
	{
	    return $this->_version;
	}

	public function getName()
	{
	    return $this->_name;
	}

	public function getMap()
	{
	    return $this->_map;
	}

	public function getGametype()
	{
	    return $this->_gametype;
	}

	public function getRules()
	{
	    return $this->_rules;
	}

	public function getPlayerCount()
	{
	    return $this->_playerCount;
	}

	public function getMaxPlayers()
	{
	    return $this->_maxPlayers;
	}

	public function getPlayers()
	{
	    return $this->_players;
	}

	/**
	 * Opens a socket and requests server information.
	 *
	 * @return boolean TRUE on success, FALSE otherwise.
	 */
	public function queryServer()
	{
	    // Creates a socket and connects to it
		$this->_socket = stream_socket_client('udp://' . $this->_ip . ':' . $this->_port, $errno, $errstr, $this->_timeout);

		// Stream (read/write) timeout
		stream_set_timeout($this->_socket, $this->_timeout);

		if ($this->_socket !== FALSE)
		{
		    $start = microtime(TRUE);
            // Sends the status command and reads the response
            fwrite($this->_socket, $this->_command);
            $response = fread($this->_socket, 16384);
            $end = microtime(TRUE);

            if ($response)
            {
                // Ping in ms (response time - request time) * 1000 (1 ms = 1000 us)
                $this->_ping = round((($end - $start) * 1000));

                // Parses the server response
                $this->_parseServerResponse($response);

                // Closes a socket resource
		        fclose($this->_socket);

                return TRUE;
            }
            else
            {
                // Closes a socket resource
		        fclose($this->_socket);

                return FALSE;
            }
		}
		else
		{
		    return FALSE;
		}
	}

	/**
	 * Parses the server response and saves the result into the class variables.
	 *
	 * @param string $response Server response delimited with ASCII characters.
	 *
	 * @return void
	 */
	protected function _parseServerResponse($response)
	{
        // Cut the first 4 characters (EYE1)
        $response = substr($response, 4);

        // General server information
        $this->_readString($response);
        $this->_readString($response);
        $this->_name = $this->_readString($response);
        $this->_gametype = $this->_readString($response);
        $this->_map = $this->_readString($response);
        $this->_version = $this->_readString($response);
        $this->_readString($response);
        $this->_playerCount = $this->_readString($response);
        $this->_maxPlayers = $this->_readString($response);

        // Server rules
        while (ord(substr($response, 0, 1)) > 1)
        {
            $this->_rules[$this->_readString($response)] = $this->_readString($response);
        }

        // Players
        if (strlen(substr($response, 1)) > 0)
        {
            $this->_parsePlayerData(substr($response, 2));
        }
	}

	/**
	 * Parses the player data and saves the response into the class variable $_players.
	 *
	 * @param string $data Player list delimited with ASCII characters.
	 *
	 * @return void
	 */
	protected function _parsePlayerData($data)
	{
	    $matches = array();
	    preg_match_all('/
	    [\x00-\xff|\s](.*?)										# player name
	    [\x00-\xff](Alpha|Bravo|Charlie|Delta|N\/A|Spectator)	# team
	    [\x00-\xff](Alpha|Bravo|Charlie|Delta|N\/A|Spectator)	# skin
	    [\x00-\xff](\d+)										# score (kills)
	    [\x00-\xff](\d+)										# ping
	    [\x00-\xff](.*?)m\?{0,1}								# time
	    /ix', $data, $matches);

	    for ($i = 0; $i < count($matches[0]); $i++)
        {
            $this->_players[] = new SoldatPlayer($matches[1][$i], $matches[2][$i], $matches[4][$i], $matches[5][$i], $matches[6][$i]);
        }
	}

	/**
	 * Reads and removes a single information from the response string.
	 *
	 * @param string $response Server response delimited with ASCII characters.
	 *
	 * @return string
	 */
	protected function _readString(&$response)
	{
	    // Length of the information following this ASCII character
        $length = ord(substr($response, 0, 1));

        if ($length > 0)
        {
            $value = substr($response, 1, $length - 1);
        }
        else
        {
            $value = NULL;
        }

        $response = substr($response, $length);

        return $value;
	}

}

/* End of file SoldatServer.php */
/* Location: ./SoldatServer.php */
Return current item: Soldat Server Stats