dedicated-server-api update
This commit is contained in:
parent
33b86cdca0
commit
18cd71818a
104
application/core/Libs/Maniaplanet/DedicatedServer/Connection.php
Normal file → Executable file
104
application/core/Libs/Maniaplanet/DedicatedServer/Connection.php
Normal file → Executable file
@ -2081,31 +2081,23 @@ class Connection
|
|||||||
/**
|
/**
|
||||||
* Set new server options using the struct passed as parameters.
|
* Set new server options using the struct passed as parameters.
|
||||||
* Mandatory fields:
|
* Mandatory fields:
|
||||||
* Name, Comment, Password, PasswordForSpectator, CallVoteRatio
|
* Name, Comment, Password, PasswordForSpectator and CallVoteRatio.
|
||||||
* Optional fields:
|
* Ignored fields:
|
||||||
* NextMaxPlayers, NextMaxSpectators, IsP2PUpload, IsP2PDownload, NextLadderMode,
|
* LadderServerLimitMin, LadderServerLimitMax and those starting with Current.
|
||||||
* NextVehicleNetQuality, NextCallVoteTimeOut, AllowMapDownload, AutoSaveReplays,
|
* All other fields are optional and can be set to null to be ignored.
|
||||||
* RefereePassword, RefereeMode, AutoSaveValidationReplays, HideServer, UseChangingValidationSeed,
|
|
||||||
* ClientInputsMaxLatency, DisableHorns, DisableServiceAnnounces, KeepPlayerSlots.
|
|
||||||
* Only available to Admin.
|
* Only available to Admin.
|
||||||
* A change of NextMaxPlayers, NextMaxSpectators, NextLadderMode, NextVehicleNetQuality,
|
* A change of any field starting with Next requires a map restart to be taken into account.
|
||||||
* NextCallVoteTimeOut or UseChangingValidationSeed requires a map restart to be taken into account.
|
* @param Structures\ServerOptions $options
|
||||||
* @param struct $options
|
|
||||||
* @param bool $multicall
|
* @param bool $multicall
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
function setServerOptions($options, $multicall=false)
|
function setServerOptions($options, $multicall=false)
|
||||||
{
|
{
|
||||||
if(!is_array($options)
|
if(!($options instanceof Structures\ServerOptions && $options->isValid()))
|
||||||
|| !(isset($options['Name']) && is_string($options['Name']))
|
|
||||||
|| !(isset($options['Comment']) && is_string($options['Comment']))
|
|
||||||
|| !(isset($options['Password']) && is_string($options['Password']))
|
|
||||||
|| !(isset($options['PasswordForSpectator']) && is_string($options['PasswordForSpectator']))
|
|
||||||
|| !(isset($options['CallVoteRatio']) && Structures\VoteRatio::isRatio($options['CallVoteRatio'])))
|
|
||||||
throw new InvalidArgumentException('options = '.print_r($options, true));
|
throw new InvalidArgumentException('options = '.print_r($options, true));
|
||||||
|
|
||||||
return $this->execute(ucfirst(__FUNCTION__), array($options), $multicall);
|
return $this->execute(ucfirst(__FUNCTION__), array($options->toSetterArray()), $multicall);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2573,42 +2565,42 @@ class Connection
|
|||||||
/**
|
/**
|
||||||
* Get the script cloud variables of given object.
|
* Get the script cloud variables of given object.
|
||||||
* Only available to Admin.
|
* Only available to Admin.
|
||||||
* @param string $arg1
|
* @param string $type
|
||||||
* @param string $arg2
|
* @param string $id
|
||||||
* @param bool $multicall
|
* @param bool $multicall
|
||||||
* @return array
|
* @return array
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
function getScriptCloudVariables($arg1, $arg2, $multicall=false)
|
function getScriptCloudVariables($type, $id, $multicall=false)
|
||||||
{
|
{
|
||||||
if(!is_string($arg1))
|
if(!is_string($type))
|
||||||
throw new InvalidArgumentException('$arg1 = '.print_r($arg1, true));
|
throw new InvalidArgumentException('type = '.print_r($type, true));
|
||||||
if(!is_string($arg2))
|
if(!is_string($id))
|
||||||
throw new InvalidArgumentException('$arg2 = '.print_r($arg2, true));
|
throw new InvalidArgumentException('id = '.print_r($id, true));
|
||||||
|
|
||||||
return $this->execute(ucfirst(__FUNCTION__), array($arg1, $arg2), $multicall);
|
return $this->execute(ucfirst(__FUNCTION__), array($type, $id), $multicall);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the script cloud variables of given object.
|
* Set the script cloud variables of given object.
|
||||||
* Only available to Admin.
|
* Only available to Admin.
|
||||||
* @param string $arg1
|
* @param string $type
|
||||||
* @param string $arg2
|
* @param string $id
|
||||||
* @param struct $arg3
|
* @param mixed[] $variables {mixed <variable name>, ...}
|
||||||
* @param bool $multicall
|
* @param bool $multicall
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
*/
|
*/
|
||||||
function setScriptCloudVariables($arg1, $arg2, $arg3, $multicall=false)
|
function setScriptCloudVariables($type, $id, $variables, $multicall=false)
|
||||||
{
|
{
|
||||||
if(!is_string($arg1))
|
if(!is_string($type))
|
||||||
throw new InvalidArgumentException('$arg1 = '.print_r($arg1, true));
|
throw new InvalidArgumentException('type = '.print_r($type, true));
|
||||||
if(!is_string($arg2))
|
if(!is_string($id))
|
||||||
throw new InvalidArgumentException('$arg2 = '.print_r($arg2, true));
|
throw new InvalidArgumentException('id = '.print_r($id, true));
|
||||||
if(!is_struct($arg3))
|
if(!is_array($variables) || !$variables)
|
||||||
throw new InvalidArgumentException('$arg3 = '.print_r($arg3, true));
|
throw new InvalidArgumentException('variables = '.print_r($variables, true));
|
||||||
|
|
||||||
return $this->execute(ucfirst(__FUNCTION__), array($arg1, $arg2, $arg3), $multicall);
|
return $this->execute(ucfirst(__FUNCTION__), array($type, $id, $variables), $multicall);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3548,7 +3540,7 @@ class Connection
|
|||||||
/**
|
/**
|
||||||
* Set as next maps the list of maps with the specified filenames, if they are present in the selection.
|
* Set as next maps the list of maps with the specified filenames, if they are present in the selection.
|
||||||
* Only available to Admin.
|
* Only available to Admin.
|
||||||
* @param array $filenames Relative to the Maps path
|
* @param string[] $filenames Relative to the Maps path
|
||||||
* @param bool $multicall
|
* @param bool $multicall
|
||||||
* @return int Number of maps actually chosen
|
* @return int Number of maps actually chosen
|
||||||
* @throws InvalidArgumentException
|
* @throws InvalidArgumentException
|
||||||
@ -3942,6 +3934,46 @@ class Connection
|
|||||||
return $this->execute(ucfirst(__FUNCTION__), array(), $multicall);
|
return $this->execute(ucfirst(__FUNCTION__), array(), $multicall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join the server on lan.
|
||||||
|
* Only available on client.
|
||||||
|
* Only available to Admin.
|
||||||
|
* @param string $host IPv4 with optionally a port (eg. '192.168.1.42:2350')
|
||||||
|
* @param string $password
|
||||||
|
* @param bool $multicall
|
||||||
|
* @return bool
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
function joinServerLan($host, $password='', $multicall=false)
|
||||||
|
{
|
||||||
|
if(!is_string($host))
|
||||||
|
throw new InvalidArgumentException('host = '.print_r($host, true));
|
||||||
|
if(!is_string($password))
|
||||||
|
throw new InvalidArgumentException('password = '.print_r($password, true));
|
||||||
|
|
||||||
|
return $this->execute(ucfirst(__FUNCTION__), array(array('Server' => $host, 'ServerPassword' => $password)), $multicall);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join the server on internet.
|
||||||
|
* Only available on client.
|
||||||
|
* Only available to Admin.
|
||||||
|
* @param string $host Server login or IPv4 with optionally a port (eg. '192.168.1.42:2350')
|
||||||
|
* @param string $password
|
||||||
|
* @param bool $multicall
|
||||||
|
* @return bool
|
||||||
|
* @throws InvalidArgumentException
|
||||||
|
*/
|
||||||
|
function joinServerInternet($host, $password='', $multicall=false)
|
||||||
|
{
|
||||||
|
if(!is_string($host))
|
||||||
|
throw new InvalidArgumentException('host = '.print_r($host, true));
|
||||||
|
if(!is_string($password))
|
||||||
|
throw new InvalidArgumentException('password = '.print_r($password, true));
|
||||||
|
|
||||||
|
return $this->execute(ucfirst(__FUNCTION__), array(array('Server' => $host, 'ServerPassword' => $password)), $multicall);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the login of the given player
|
* Returns the login of the given player
|
||||||
* @param mixed $player
|
* @param mixed $player
|
||||||
|
@ -71,4 +71,35 @@ class ServerOptions extends AbstractStructure
|
|||||||
public $disableHorns;
|
public $disableHorns;
|
||||||
/** @var bool */
|
/** @var bool */
|
||||||
public $disableServiceAnnounces;
|
public $disableServiceAnnounces;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function isValid()
|
||||||
|
{
|
||||||
|
return is_string($this->name)
|
||||||
|
&& is_string($this->comment)
|
||||||
|
&& is_string($this->password)
|
||||||
|
&& is_string($this->passwordForSpectator)
|
||||||
|
&& VoteRatio::isRatio($this->callVoteRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
* @return mixed[]
|
||||||
|
*/
|
||||||
|
function toSetterArray()
|
||||||
|
{
|
||||||
|
$out = array();
|
||||||
|
foreach(get_object_vars($this) as $key => $value)
|
||||||
|
{
|
||||||
|
if(substr($key, 0, 7) == 'current' || $value === null)
|
||||||
|
continue;
|
||||||
|
if($key == 'nextUseChangingValidationSeed')
|
||||||
|
$key = 'useChangingValidationSeed';
|
||||||
|
$out[ucfirst($key)] = $value;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ class Status extends AbstractStructure
|
|||||||
const SYNCHRONIZATION = 3;
|
const SYNCHRONIZATION = 3;
|
||||||
const PLAY = 4;
|
const PLAY = 4;
|
||||||
const EXITING = 6;
|
const EXITING = 6;
|
||||||
|
const LOCAL = 7;
|
||||||
|
|
||||||
/** @var int */
|
/** @var int */
|
||||||
public $code;
|
public $code;
|
||||||
|
@ -34,6 +34,7 @@ class Vote extends AbstractStructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function isValid()
|
function isValid()
|
||||||
|
@ -37,6 +37,7 @@ class VoteRatio extends AbstractStructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
function isValid()
|
function isValid()
|
||||||
@ -47,6 +48,7 @@ class VoteRatio extends AbstractStructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @internal
|
||||||
* @param float $ratio
|
* @param float $ratio
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
|
67
application/core/Libs/Maniaplanet/DedicatedServer/Xmlrpc/GbxRemote.php
Normal file → Executable file
67
application/core/Libs/Maniaplanet/DedicatedServer/Xmlrpc/GbxRemote.php
Normal file → Executable file
@ -16,10 +16,8 @@ class GbxRemote
|
|||||||
public static $sent;
|
public static $sent;
|
||||||
|
|
||||||
private $socket;
|
private $socket;
|
||||||
private $timeouts = array(
|
private $readTimeout = array('sec' => 5, 'usec' => 0);
|
||||||
'read' => 8000,
|
private $writeTimeout = array('sec' => 5, 'usec' => 0);
|
||||||
'write' => 8000
|
|
||||||
);
|
|
||||||
private $requestHandle;
|
private $requestHandle;
|
||||||
private $callbacksBuffer = array();
|
private $callbacksBuffer = array();
|
||||||
private $multicallBuffer = array();
|
private $multicallBuffer = array();
|
||||||
@ -49,9 +47,15 @@ class GbxRemote
|
|||||||
function setTimeouts($read=0, $write=0)
|
function setTimeouts($read=0, $write=0)
|
||||||
{
|
{
|
||||||
if($read)
|
if($read)
|
||||||
$this->timeouts['read'] = $read;
|
{
|
||||||
|
$this->readTimeout['sec'] = (int) ($read / 1000);
|
||||||
|
$this->readTimeout['usec'] = ($read % 1000) * 1000;
|
||||||
|
}
|
||||||
if($write)
|
if($write)
|
||||||
$this->timeouts['write'] = $write;
|
{
|
||||||
|
$this->writeTimeout['sec'] = (int) ($write / 1000);
|
||||||
|
$this->writeTimeout['usec'] = ($write % 1000) * 1000;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,12 +79,13 @@ class GbxRemote
|
|||||||
if(!$this->socket)
|
if(!$this->socket)
|
||||||
throw new TransportException('Cannot open socket', TransportException::NOT_INITIALIZED);
|
throw new TransportException('Cannot open socket', TransportException::NOT_INITIALIZED);
|
||||||
|
|
||||||
|
stream_set_read_buffer($this->socket, 0);
|
||||||
stream_set_write_buffer($this->socket, 0);
|
stream_set_write_buffer($this->socket, 0);
|
||||||
|
|
||||||
// handshake
|
// handshake
|
||||||
$header = $this->read(15);
|
$header = $this->read(15);
|
||||||
if($header === false)
|
if($header === false)
|
||||||
throw new TransportException('Connection interrupted during handshake', TransportException::INTERRUPTED);
|
$this->onIoFailure('during handshake');
|
||||||
|
|
||||||
extract(unpack('Vsize/a*protocol', $header));
|
extract(unpack('Vsize/a*protocol', $header));
|
||||||
/** @var $size int */
|
/** @var $size int */
|
||||||
@ -185,10 +190,7 @@ class GbxRemote
|
|||||||
private function flush($waitResponse=false)
|
private function flush($waitResponse=false)
|
||||||
{
|
{
|
||||||
$r = array($this->socket);
|
$r = array($this->socket);
|
||||||
$w = null;
|
while($waitResponse || @stream_select($r, $w, $e, 0) > 0)
|
||||||
$e = null;
|
|
||||||
$n = @stream_select($r, $w, $e, 0);
|
|
||||||
while($waitResponse || $n > 0)
|
|
||||||
{
|
{
|
||||||
list($handle, $xml) = $this->readMessage();
|
list($handle, $xml) = $this->readMessage();
|
||||||
list($type, $value) = Request::decode($xml);
|
list($type, $value) = Request::decode($xml);
|
||||||
@ -203,10 +205,7 @@ class GbxRemote
|
|||||||
case 'call':
|
case 'call':
|
||||||
$this->callbacksBuffer[] = $value;
|
$this->callbacksBuffer[] = $value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(!$waitResponse)
|
|
||||||
$n = @stream_select($r, $w, $e, 0);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,8 +217,7 @@ class GbxRemote
|
|||||||
{
|
{
|
||||||
$header = $this->read(8);
|
$header = $this->read(8);
|
||||||
if($header === false)
|
if($header === false)
|
||||||
throw new TransportException('Connection interrupted while reading header '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED);
|
$this->onIoFailure('while reading header');
|
||||||
//throw new TransportException('Connection interrupted while reading header', TransportException::INTERRUPTED);
|
|
||||||
|
|
||||||
extract(unpack('Vsize/Vhandle', $header));
|
extract(unpack('Vsize/Vhandle', $header));
|
||||||
/** @var $size int */
|
/** @var $size int */
|
||||||
@ -232,8 +230,7 @@ class GbxRemote
|
|||||||
|
|
||||||
$data = $this->read($size);
|
$data = $this->read($size);
|
||||||
if($data === false)
|
if($data === false)
|
||||||
//throw new TransportException('Connection interrupted while reading data', TransportException::INTERRUPTED);
|
$this->onIoFailure('while reading data');
|
||||||
throw new TransportException('Connection interrupted while reading data '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED);
|
|
||||||
|
|
||||||
$this->lastNetworkActivity = time();
|
$this->lastNetworkActivity = time();
|
||||||
return array($handle, $data);
|
return array($handle, $data);
|
||||||
@ -245,10 +242,11 @@ class GbxRemote
|
|||||||
*/
|
*/
|
||||||
private function writeMessage($xml)
|
private function writeMessage($xml)
|
||||||
{
|
{
|
||||||
$data = pack('V2a*', strlen($xml), ++$this->requestHandle, $xml);
|
if($this->requestHandle == (int) 0xffffffff)
|
||||||
|
$this->requestHandle = (int) 0x80000000;
|
||||||
|
$data = pack('V2', strlen($xml), ++$this->requestHandle).$xml;
|
||||||
if(!$this->write($data))
|
if(!$this->write($data))
|
||||||
throw new TransportException('Connection interrupted while writing '.print_r(stream_get_meta_data($this->socket), true), TransportException::INTERRUPTED);
|
$this->onIoFailure('while writing');
|
||||||
//throw new TransportException('Connection interrupted while writing', TransportException::INTERRUPTED);
|
|
||||||
$this->lastNetworkActivity = time();
|
$this->lastNetworkActivity = time();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +256,7 @@ class GbxRemote
|
|||||||
*/
|
*/
|
||||||
private function read($size)
|
private function read($size)
|
||||||
{
|
{
|
||||||
@stream_set_timeout($this->socket, 0, $this->timeouts['read'] * 1000);
|
@stream_set_timeout($this->socket, $this->readTimeout['sec'], $this->readTimeout['usec']);
|
||||||
|
|
||||||
$data = '';
|
$data = '';
|
||||||
while(strlen($data) < $size)
|
while(strlen($data) < $size)
|
||||||
@ -279,7 +277,8 @@ class GbxRemote
|
|||||||
*/
|
*/
|
||||||
private function write($data)
|
private function write($data)
|
||||||
{
|
{
|
||||||
@stream_set_timeout($this->socket, 0, $this->timeouts['write'] * 1000);
|
@stream_set_timeout($this->socket, $this->writeTimeout['sec'], $this->writeTimeout['usec']);
|
||||||
|
self::$sent += strlen($data);
|
||||||
|
|
||||||
while(strlen($data) > 0)
|
while(strlen($data) > 0)
|
||||||
{
|
{
|
||||||
@ -287,22 +286,32 @@ class GbxRemote
|
|||||||
if($written === 0 || $written === false)
|
if($written === 0 || $written === false)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
fflush($this->socket);
|
|
||||||
|
|
||||||
$data = substr($data, $written);
|
$data = substr($data, $written);
|
||||||
}
|
}
|
||||||
|
|
||||||
self::$sent += strlen($data);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $when
|
||||||
|
* @throws TransportException
|
||||||
|
*/
|
||||||
|
private function onIoFailure($when)
|
||||||
|
{
|
||||||
|
$meta = stream_get_meta_data($this->socket);
|
||||||
|
if($meta['timed_out'])
|
||||||
|
throw new TransportException('Connection timed out '.$when, TransportException::TIMED_OUT);
|
||||||
|
throw new TransportException('Connection interrupted '.$when, TransportException::INTERRUPTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TransportException extends Exception
|
class TransportException extends Exception
|
||||||
{
|
{
|
||||||
const NOT_INITIALIZED = 1;
|
const NOT_INITIALIZED = 1;
|
||||||
const INTERRUPTED = 2;
|
const INTERRUPTED = 2;
|
||||||
const WRONG_PROTOCOL = 3;
|
const TIMED_OUT = 3;
|
||||||
const PROTOCOL_ERROR = 4;
|
const WRONG_PROTOCOL = 4;
|
||||||
|
const PROTOCOL_ERROR = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
class MessageException extends Exception
|
class MessageException extends Exception
|
||||||
|
Loading…
Reference in New Issue
Block a user