1217 lines
38 KiB
PHP
1217 lines
38 KiB
PHP
<?php
|
|
|
|
namespace ManiaControl;
|
|
|
|
// TODO: show mix of best and next records (depending on own one)
|
|
// TODO: enable keep-alive
|
|
// TODO: enable gzip compression
|
|
// TODO: log errors from WarningsAndTTR2
|
|
// TODO: check map requirements (cp count + length)
|
|
// TODO: check checkpoints on finish
|
|
// TODO: threaded requests
|
|
|
|
/**
|
|
* ManiaControl Records Plugin
|
|
*
|
|
* @author steeffeen
|
|
*/
|
|
class Plugin_Records {
|
|
/**
|
|
* Constants
|
|
*/
|
|
const VERSION = '1.0';
|
|
const MLID_LOCAL = 'ml_local_records';
|
|
const MLID_DEDI = 'ml_dedimania_records';
|
|
const TABLE_RECORDS = 'ic_records';
|
|
const XMLRPC_MULTICALL = 'system.multicall';
|
|
const DEDIMANIA_URL = 'http://dedimania.net:8081/Dedimania';
|
|
const DEDIMANIA_OPENSESSION = 'dedimania.OpenSession';
|
|
const DEDIMANIA_CHECKSESSION = 'dedimania.CheckSession';
|
|
const DEDIMANIA_GETRECORDS = 'dedimania.GetChallengeRecords';
|
|
const DEDIMANIA_PLAYERCONNECT = 'dedimania.PlayerConnect';
|
|
const DEDIMANIA_PLAYERDISCONNECT = 'dedimania.PlayerDisconnect';
|
|
const DEDIMANIA_UPDATESERVERPLAYERS = 'dedimania.UpdateServerPlayers';
|
|
const DEDIMANIA_SETCHALLENGETIMES = 'dedimania.SetChallengeTimes';
|
|
const DEDIMANIA_WARNINGSANDTTR2 = 'dedimania.WarningsAndTTR2';
|
|
|
|
/**
|
|
* Private properties
|
|
*/
|
|
private $mControl = null;
|
|
|
|
private $settings = null;
|
|
|
|
private $config = null;
|
|
|
|
private $mapInfo = null;
|
|
|
|
private $manialinks = array();
|
|
|
|
private $lastSendManialinks = array();
|
|
|
|
private $updateManialinks = array();
|
|
|
|
private $dedimaniaData = array();
|
|
|
|
private $checkpoints = array();
|
|
|
|
/**
|
|
* Constuct plugin
|
|
*/
|
|
public function __construct($mControl) {
|
|
$this->mControl = $mControl;
|
|
|
|
// Load config
|
|
$this->config = Tools::loadConfig('records.plugin.xml');
|
|
|
|
// Check for enabled setting
|
|
if (!Tools::toBool($this->config->enabled)) return;
|
|
|
|
// Load settings
|
|
$this->loadSettings();
|
|
|
|
// Init tables
|
|
$this->initTables();
|
|
|
|
// Register for callbacks
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_ONINIT, $this, 'handleOnInit');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_1_SECOND, $this, 'handle1Second');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_1_MINUTE, $this, 'handle1Minute');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_3_MINUTE, $this, 'handle3Minute');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_BEGINMAP, $this, 'handleMapBegin');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_CLIENTUPDATED, $this, 'handleClientUpdated');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_ENDMAP, $this, 'handleMapEnd');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'handlePlayerConnect');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERDISCONNECT, $this, 'handlePlayerDisconnect');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_TM_PLAYERFINISH, $this, 'handlePlayerFinish');
|
|
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_TM_PLAYERCHECKPOINT, $this, 'handlePlayerCheckpoint');
|
|
|
|
error_log('Records Pugin v' . self::VERSION . ' ready!');
|
|
}
|
|
|
|
/**
|
|
* Init needed database tables
|
|
*/
|
|
private function initTables() {
|
|
$database = $this->iControl->database;
|
|
|
|
// Records table
|
|
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_RECORDS . "` (
|
|
`index` int(11) NOT NULL AUTO_INCREMENT,
|
|
`mapUId` varchar(100) NOT NULL,
|
|
`Login` varchar(100) NOT NULL,
|
|
`time` int(11) NOT NULL,
|
|
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
PRIMARY KEY (`index`),
|
|
UNIQUE KEY `player_map_record` (`mapUId`,`Login`)
|
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;";
|
|
if (!$database->query($query)) {
|
|
trigger_error("Couldn't create records table. " . $database->mysqli->error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load settings from config
|
|
*/
|
|
private function loadSettings() {
|
|
$this->settings = new \stdClass();
|
|
|
|
$this->settings->enabled = Tools::toBool($this->config->enabled);
|
|
|
|
$this->settings->local_records_enabled = $this->settings->enabled && Tools::toBool($this->config->local_records->enabled);
|
|
$this->settings->dedimania_enabled = $this->settings->enabled && Tools::toBool($this->config->dedimania_records->enabled);
|
|
}
|
|
|
|
/**
|
|
* Handle ManiaControl init
|
|
*/
|
|
public function handleOnInit($callback = null) {
|
|
// Let manialinks update
|
|
if ($this->settings->local_records_enabled) {
|
|
$this->updateManialinks[self::MLID_LOCAL] = true;
|
|
}
|
|
|
|
// Update mapinfo
|
|
$this->mapInfo = $this->getMapInfo();
|
|
|
|
if ($this->settings->dedimania_enabled) {
|
|
// Open dedimania session
|
|
$accounts = $this->config->xpath('dedimania_records/account');
|
|
if (!$accounts) {
|
|
trigger_error('Invalid dedimania_code in config.');
|
|
$this->settings->dedimania_enabled = false;
|
|
}
|
|
else {
|
|
$this->openDedimaniaSession();
|
|
}
|
|
$this->fetchDedimaniaRecords();
|
|
$this->updateManialinks[self::MLID_DEDI] = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Fetch dedimania records of the current map
|
|
*/
|
|
private function fetchDedimaniaRecords($reset = true) {
|
|
if (!isset($this->dedimaniaData['context'])) return false;
|
|
if ($reset || !isset($this->dedimaniaData['records']) && !is_array($this->dedimaniaData['records'])) {
|
|
// Reset records
|
|
$this->dedimaniaData['records'] = array();
|
|
}
|
|
|
|
// Fetch records
|
|
$servInfo = $this->getSrvInfo();
|
|
$playerInfo = $this->getPlayerList();
|
|
$gameMode = $this->getGameModeString();
|
|
$data = array($this->dedimaniaData['sessionId'], $this->mapInfo, $gameMode, $servInfo, $playerInfo);
|
|
$request = $this->encode_request(self::DEDIMANIA_GETRECORDS, $data);
|
|
stream_context_set_option($this->dedimaniaData['context'], 'http', 'content', $request);
|
|
$file = file_get_contents(self::DEDIMANIA_URL, false, $this->dedimaniaData['context']);
|
|
|
|
// Handle response
|
|
$response = $this->decode($file);
|
|
if (is_array($response)) {
|
|
foreach ($response as $index => $methodResponse) {
|
|
if (xmlrpc_is_fault($methodResponse)) {
|
|
$this->handleXmlRpcFault($methodResponse);
|
|
return false;
|
|
}
|
|
else if ($index <= 0) {
|
|
$responseData = $methodResponse[0];
|
|
$this->dedimaniaData['records'] = $responseData;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Checks dedimania session
|
|
*/
|
|
private function checkDedimaniaSession() {
|
|
if (!$this->settings->dedimania_enabled) return false;
|
|
if (!isset($this->dedimaniaData['context'])) return false;
|
|
if (!isset($this->dedimaniaData['sessionId']) || !is_string($this->dedimaniaData['sessionId'])) return false;
|
|
|
|
// Check session
|
|
$request = $this->encode_request(self::DEDIMANIA_CHECKSESSION, array($this->dedimaniaData['sessionId']));
|
|
stream_context_set_option($this->dedimaniaData['context'], 'http', 'content', $request);
|
|
$file = file_get_contents(self::DEDIMANIA_URL, false, $this->dedimaniaData['context']);
|
|
|
|
// Handle response
|
|
$response = $this->decode($file);
|
|
$result = false;
|
|
if (is_array($response)) {
|
|
foreach ($response as $methodResponse) {
|
|
if (xmlrpc_is_fault($methodResponse)) {
|
|
$this->handleXmlRpcFault($methodResponse);
|
|
}
|
|
else {
|
|
$responseData = $methodResponse[0];
|
|
if (is_bool($responseData)) {
|
|
$result = $responseData;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Renews dedimania session
|
|
*/
|
|
private function openDedimaniaSession($init = false) {
|
|
if (!$this->settings->dedimania_enabled) return false;
|
|
|
|
// Get server data
|
|
if ($init || !array_key_exists('serverData', $this->dedimaniaData) || !is_array($this->dedimaniaData['serverData'])) {
|
|
$serverData = array();
|
|
$serverData['Game'] = 'TM2';
|
|
$serverInfo = $this->iControl->server->getInfo(true);
|
|
|
|
// Get dedimania account data
|
|
$accounts = $this->config->xpath('dedimania_records/account');
|
|
foreach ($accounts as $account) {
|
|
$login = (string) $account->login;
|
|
if ($login != $serverInfo['Login']) continue;
|
|
$code = (string) $account->code;
|
|
$serverData['Login'] = $login;
|
|
$serverData['Code'] = $code;
|
|
break;
|
|
}
|
|
|
|
if (!isset($serverData['Login']) || !isset($serverData['Code'])) {
|
|
// Wrong configuration for current server
|
|
trigger_error("Records Plugin: Invalid dedimania configuration for login '" . $serverInfo['Login'] . "'.");
|
|
if (isset($this->dedimaniaData['context'])) unset($this->dedimaniaData['context']);
|
|
if (isset($this->dedimaniaData['sessionId'])) unset($this->dedimaniaData['sessionId']);
|
|
return false;
|
|
}
|
|
|
|
// Complete seesion data
|
|
$serverData['Path'] = $serverInfo['Path'];
|
|
$systemInfo = $this->iControl->server->getSystemInfo();
|
|
$serverData['Packmask'] = substr($systemInfo['TitleId'], 2);
|
|
$serverVersion = $this->iControl->server->getVersion();
|
|
$serverData['ServerVersion'] = $serverVersion['Version'];
|
|
$serverData['ServerBuild'] = $serverVersion['Build'];
|
|
$serverData['Tool'] = 'ManiaControl';
|
|
$serverData['Version'] = ManiaControl::VERSION;
|
|
$this->dedimaniaData['serverData'] = $serverData;
|
|
}
|
|
|
|
// Init header
|
|
if ($init || !array_key_exists('header', $this->dedimaniaData) || !is_array($this->dedimaniaData['header'])) {
|
|
$header = '';
|
|
$header .= 'Accept-Charset: utf-8;' . PHP_EOL;
|
|
$header .= 'Accept-Encoding: gzip;' . PHP_EOL;
|
|
$header .= 'Content-Type: text/xml; charset=utf-8;' . PHP_EOL;
|
|
$header .= 'Keep-Alive: 300;' . PHP_EOL;
|
|
$header .= 'User-Agent: ManiaControl v' . ManiaControl::VERSION . ';' . PHP_EOL;
|
|
$this->dedimaniaData['header'] = $header;
|
|
}
|
|
|
|
// Open session
|
|
$request = $this->encode_request(self::DEDIMANIA_OPENSESSION, array($this->dedimaniaData['serverData']));
|
|
$context = stream_context_create(array('http' => array('method' => 'POST', 'header' => $this->dedimaniaData['header'])));
|
|
stream_context_set_option($context, 'http', 'content', $request);
|
|
$file = file_get_contents(self::DEDIMANIA_URL, false, $context);
|
|
|
|
// Handle response
|
|
$response = $this->decode($file);
|
|
$result = false;
|
|
if (is_array($response)) {
|
|
foreach ($response as $index => $methodResponse) {
|
|
if (xmlrpc_is_fault($methodResponse)) {
|
|
$this->handleXmlRpcFault($methodResponse);
|
|
}
|
|
else if ($index <= 0) {
|
|
$responseData = $methodResponse[0];
|
|
$this->dedimaniaData['context'] = $context;
|
|
$this->dedimaniaData['sessionId'] = $responseData['SessionId'];
|
|
$result = true;
|
|
}
|
|
}
|
|
}
|
|
if ($result) error_log("Dedimania connection successfully established.");
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Handle 1Second callback
|
|
*/
|
|
public function handle1Second() {
|
|
if (!$this->settings->enabled) return;
|
|
|
|
// Send records manialinks if needed
|
|
foreach ($this->updateManialinks as $id => $update) {
|
|
if (!$update) continue;
|
|
if (array_key_exists($id, $this->lastSendManialinks) && $this->lastSendManialinks[$id] + 2 > time()) continue;
|
|
|
|
switch ($id) {
|
|
case self::MLID_LOCAL:
|
|
{
|
|
$this->manialinks[$id] = $this->buildLocalManialink();
|
|
break;
|
|
}
|
|
case self::MLID_DEDI:
|
|
{
|
|
$this->manialinks[$id] = $this->buildDedimaniaManialink();
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
continue 2;
|
|
break;
|
|
}
|
|
}
|
|
$this->updateManialinks[$id] = false;
|
|
$this->lastSendManialinks[$id] = time();
|
|
$this->sendManialink($this->manialinks[$id]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle 1Minute callback
|
|
*/
|
|
public function handle1Minute($callback = null) {
|
|
if ($this->settings->dedimania_enabled) {
|
|
// Keep dedimania session alive
|
|
if (!$this->checkDedimaniaSession()) {
|
|
// Renew session
|
|
$this->openDedimaniaSession();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle PlayerConnect callback
|
|
*/
|
|
public function handlePlayerConnect($callback) {
|
|
$login = $callback[1][0];
|
|
if ($this->settings->local_records_enabled) $this->sendManialink($this->manialinks[self::MLID_LOCAL], $login);
|
|
|
|
if ($this->settings->dedimania_enabled && $this->dedimaniaData['context']) {
|
|
$player = $this->iControl->server->getPlayer($login, true);
|
|
if ($player) {
|
|
// Send dedimania request
|
|
$data = array($this->dedimaniaData['sessionId'], $player['Login'], $player['NickName'], $player['Path'],
|
|
$player['IsSpectator']);
|
|
$request = $this->encode_request(self::DEDIMANIA_PLAYERCONNECT, $data);
|
|
stream_context_set_option($this->dedimaniaData['context'], 'http', 'content', $request);
|
|
$file = file_get_contents(self::DEDIMANIA_URL, false, $this->dedimaniaData['context']);
|
|
|
|
// Handle response
|
|
$response = $this->decode($file);
|
|
if (is_array($response)) {
|
|
foreach ($response as $methodResponse) {
|
|
if (xmlrpc_is_fault($methodResponse)) {
|
|
$this->handleXmlRpcFault($methodResponse);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (!$response) {
|
|
trigger_error('XmlRpc Error.');
|
|
var_dump($response);
|
|
}
|
|
}
|
|
}
|
|
$this->sendManialink($this->manialinks[self::MLID_DEDI], $login);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle PlayerDisconnect callback
|
|
*/
|
|
public function handlePlayerDisconnect($callback) {
|
|
$login = $callback[1][0];
|
|
|
|
if ($this->settings->dedimania_enabled && $this->dedimaniaData['context']) {
|
|
// Send dedimania request
|
|
$data = array($this->dedimaniaData['sessionId'], $login, '');
|
|
$request = $this->encode_request(self::DEDIMANIA_PLAYERDISCONNECT, $data);
|
|
stream_context_set_option($this->dedimaniaData['context'], 'http', 'content', $request);
|
|
$file = file_get_contents(self::DEDIMANIA_URL, false, $this->dedimaniaData['context']);
|
|
|
|
// Handle response
|
|
$response = $this->decode($file);
|
|
if (is_array($response)) {
|
|
foreach ($response as $methodResponse) {
|
|
if (xmlrpc_is_fault($methodResponse)) {
|
|
$this->handleXmlRpcFault($methodResponse);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (!$response) {
|
|
trigger_error('XmlRpc Error.');
|
|
var_dump($response);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle BeginMap callback
|
|
*/
|
|
public function handleMapBegin($callback) {
|
|
// Update map
|
|
$this->mapInfo = $this->getMapInfo();
|
|
|
|
if ($this->settings->local_records_enabled) {
|
|
// Update local records
|
|
$this->updateManialinks[self::MLID_LOCAL] = true;
|
|
}
|
|
|
|
if ($this->settings->dedimania_enabled) {
|
|
// Update dedimania records
|
|
$this->fetchDedimaniaRecords(true);
|
|
$this->updateManialinks[self::MLID_DEDI] = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Build map info struct for dedimania requests
|
|
*/
|
|
private function getMapInfo() {
|
|
$map = $this->iControl->server->getMap();
|
|
if (!$map) return null;
|
|
$mapInfo = array();
|
|
$mapInfo['UId'] = $map['UId'];
|
|
$mapInfo['Name'] = $map['Name'];
|
|
$mapInfo['Author'] = $map['Author'];
|
|
$mapInfo['Environment'] = $map['Environnement'];
|
|
$mapInfo['NbCheckpoints'] = $map['NbCheckpoints'];
|
|
$mapInfo['NbLaps'] = $map['NbLaps'];
|
|
return $mapInfo;
|
|
}
|
|
|
|
/**
|
|
* Handle EndMap callback
|
|
*/
|
|
public function handleMapEnd($callback) {
|
|
if ($this->settings->dedimania_enabled) {
|
|
// Send dedimania records
|
|
$gameMode = $this->getGameModeString();
|
|
$times = array();
|
|
$replays = array();
|
|
foreach ($this->dedimaniaData['records']['Records'] as $record) {
|
|
if (!isset($record['New']) || !$record['New']) continue;
|
|
array_push($times, array('Login' => $record['Login'], 'Best' => $record['Best'], 'Checks' => $record['Checks']));
|
|
if (!isset($replays['VReplay'])) {
|
|
$replays['VReplay'] = $record['VReplay'];
|
|
}
|
|
if (!isset($replays['Top1GReplay']) && isset($record['Top1GReplay'])) {
|
|
$replays['Top1GReplay'] = $record['Top1GReplay'];
|
|
}
|
|
// TODO: VReplayChecks
|
|
}
|
|
if (!isset($replays['VReplay'])) $replays['VReplay'] = '';
|
|
if (!isset($replays['VReplayChecks'])) $replays['VReplayChecks'] = '';
|
|
if (!isset($replays['Top1GReplay'])) $replays['Top1GReplay'] = '';
|
|
|
|
xmlrpc_set_type($replays['VReplay'], 'base64');
|
|
xmlrpc_set_type($replays['Top1GReplay'], 'base64');
|
|
|
|
$data = array($this->dedimaniaData['sessionId'], $this->mapInfo, $gameMode, $times, $replays);
|
|
$request = $this->encode_request(self::DEDIMANIA_SETCHALLENGETIMES, $data);
|
|
stream_context_set_option($this->dedimaniaData['context'], 'http', 'content', $request);
|
|
$file = file_get_contents(self::DEDIMANIA_URL, false, $this->dedimaniaData['context']);
|
|
|
|
// Handle response
|
|
$response = $this->decode($file);
|
|
if (is_array($response)) {
|
|
foreach ($response as $index => $methodResponse) {
|
|
if (xmlrpc_is_fault($methodResponse)) {
|
|
$this->handleXmlRpcFault($methodResponse);
|
|
}
|
|
else {
|
|
if ($index <= 0) {
|
|
// Called method response
|
|
$responseData = $methodResponse[0];
|
|
if (!$responseData) {
|
|
trigger_error("Records Plugin: Submitting dedimania records failed.");
|
|
}
|
|
continue;
|
|
}
|
|
|
|
// Warnings and TTR
|
|
$errors = $methodResponse[0]['methods'][0]['errors'];
|
|
if ($errors) {
|
|
trigger_error($errors);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get current checkpoint string for dedimania record
|
|
*
|
|
* @param string $login
|
|
* @return string
|
|
*/
|
|
private function getChecks($login) {
|
|
if (!$login || !isset($this->checkpoints[$login])) return null;
|
|
$string = '';
|
|
$count = count($this->checkpoints[$login]);
|
|
foreach ($this->checkpoints[$login] as $index => $check) {
|
|
$string .= $check;
|
|
if ($index < $count - 1) $string .= ',';
|
|
}
|
|
return $string;
|
|
}
|
|
|
|
/**
|
|
* Build server info struct for callbacks
|
|
*/
|
|
private function getSrvInfo() {
|
|
$server = $this->iControl->server->getOptions();
|
|
if (!$server) return null;
|
|
$client = null;
|
|
$players = null;
|
|
$spectators = null;
|
|
$this->iControl->server->getPlayers($client, $players, $spectators);
|
|
if (!is_array($players) || !is_array($spectators)) return null;
|
|
return array('SrvName' => $server['Name'], 'Comment' => $server['Comment'], 'Private' => (strlen($server['Password']) > 0),
|
|
'NumPlayers' => count($players), 'MaxPlayers' => $server['CurrentMaxPlayers'], 'NumSpecs' => count($spectators),
|
|
'MaxSpecs' => $server['CurrentMaxSpectators']);
|
|
}
|
|
|
|
/**
|
|
* Build simple player list for callbacks
|
|
*/
|
|
private function getPlayerList($votes = false) {
|
|
$client = null;
|
|
$players;
|
|
$spectators;
|
|
$allPlayers = $this->iControl->server->getPlayers($client, $players, $spectators);
|
|
if (!is_array($players) || !is_array($spectators)) return null;
|
|
$playerInfo = array();
|
|
foreach ($allPlayers as $player) {
|
|
array_push($playerInfo, array('Login' => $player['Login'], 'IsSpec' => in_array($player, $spectators)));
|
|
}
|
|
return $playerInfo;
|
|
}
|
|
|
|
/**
|
|
* Get dedi string representation of the current game mode
|
|
*/
|
|
private function getGameModeString() {
|
|
$gameMode = $this->iControl->server->getGameMode();
|
|
if ($gameMode === null) {
|
|
trigger_error("Couldn't retrieve game mode. " . $this->iControl->getClientErrorText());
|
|
return null;
|
|
}
|
|
switch ($gameMode) {
|
|
case 1:
|
|
case 3:
|
|
case 5:
|
|
{
|
|
return 'Rounds';
|
|
}
|
|
case 2:
|
|
case 4:
|
|
{
|
|
return 'TA';
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Build votes info struct for callbacks
|
|
*/
|
|
private function getVotesInfo() {
|
|
$map = $this->iControl->server->getMap();
|
|
if (!$map) return null;
|
|
$gameMode = $this->getGameModeString();
|
|
if (!$gameMode) return null;
|
|
return array('UId' => $map['UId'], 'GameMode' => $gameMode);
|
|
}
|
|
|
|
/**
|
|
* Handle 3Minute callback
|
|
*/
|
|
public function handle3Minute($callback = null) {
|
|
if ($this->settings->dedimania_enabled) {
|
|
// Update dedimania players
|
|
$servInfo = $this->getSrvInfo();
|
|
$votesInfo = $this->getVotesInfo();
|
|
$playerList = $this->getPlayerList(true);
|
|
if ($servInfo && $votesInfo && $playerList) {
|
|
$data = array($this->dedimaniaData['sessionId'], $servInfo, $votesInfo, $playerList);
|
|
$request = $this->encode_request(self::DEDIMANIA_UPDATESERVERPLAYERS, $data);
|
|
stream_context_set_option($this->dedimaniaData['context'], 'http', 'content', $request);
|
|
$file = file_get_contents(self::DEDIMANIA_URL, false, $this->dedimaniaData['context']);
|
|
|
|
// Handle response
|
|
$response = $this->decode($file);
|
|
if (is_array($response)) {
|
|
foreach ($response as $methodResponse) {
|
|
if (xmlrpc_is_fault($methodResponse)) {
|
|
$this->handleXmlRpcFault($methodResponse);
|
|
}
|
|
}
|
|
}
|
|
else if (!$response) {
|
|
trigger_error('XmlRpc Error.');
|
|
var_dump($response);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle PlayerCheckpoint callback
|
|
*/
|
|
public function handlePlayerCheckpoint($callback) {
|
|
$data = $callback[1];
|
|
$login = $data[1];
|
|
$time = $data[2];
|
|
$lap = $data[3];
|
|
$cpIndex = $data[4];
|
|
if (!isset($this->checkpoints[$login]) || $cpIndex <= 0) $this->checkpoints[$login] = array();
|
|
$this->checkpoints[$login][$cpIndex] = $time;
|
|
}
|
|
|
|
/**
|
|
* Handle PlayerFinish callback
|
|
*/
|
|
public function handlePlayerFinish($callback) {
|
|
$data = $callback[1];
|
|
if ($data[0] <= 0 || $data[2] <= 0) return;
|
|
|
|
$login = $data[1];
|
|
$time = $data[2];
|
|
$newMap = $this->iControl->server->getMap();
|
|
if (!$newMap) return;
|
|
if (!$this->mapInfo || $this->mapInfo['UId'] !== $newMap['UId']) {
|
|
$this->mapInfo = $this->getMapInfo();
|
|
}
|
|
$map = $newMap;
|
|
|
|
$player = $this->iControl->server->getPlayer($login);
|
|
|
|
if ($this->settings->local_records_enabled) {
|
|
// Get old record of the player
|
|
$oldRecord = $this->getLocalRecord($map['UId'], $login);
|
|
$save = true;
|
|
if ($oldRecord) {
|
|
if ($oldRecord['time'] < $time) {
|
|
// Not improved
|
|
$save = false;
|
|
}
|
|
else if ($oldRecord['time'] == $time) {
|
|
// Same time
|
|
$message = '$<' . $player['NickName'] . '$> equalized her/his $<$o' . $oldRecord['rank'] . '.$> Local Record: ' .
|
|
Tools::formatTime($oldRecord['time']);
|
|
$this->iControl->chat->sendInformation($message);
|
|
$save = false;
|
|
}
|
|
}
|
|
if ($save) {
|
|
// Save time
|
|
$database = $this->iControl->database;
|
|
$query = "INSERT INTO `" . self::TABLE_RECORDS . "` (
|
|
`mapUId`,
|
|
`Login`,
|
|
`time`
|
|
) VALUES (
|
|
'" . $database->escape($map['UId']) . "',
|
|
'" . $database->escape($login) . "',
|
|
" . $time . "
|
|
) ON DUPLICATE KEY UPDATE
|
|
`time` = VALUES(`time`);";
|
|
if (!$database->query($query)) {
|
|
trigger_error("Couldn't save player record. " . $database->mysqli->error);
|
|
}
|
|
else {
|
|
// Announce record
|
|
$newRecord = $this->getLocalRecord($map['UId'], $login);
|
|
if ($oldRecord == null || $newRecord['rank'] < $oldRecord['rank']) {
|
|
// Gained rank
|
|
$improvement = 'gained the';
|
|
}
|
|
else {
|
|
// Only improved time
|
|
$improvement = 'improved her/his';
|
|
}
|
|
$message = '$<' . $player['NickName'] . '$> ' . $improvement . ' $<$o' . $newRecord['rank'] . '.$> Local Record: ' .
|
|
Tools::formatTime($newRecord['time']);
|
|
$this->iControl->chat->sendInformation($message);
|
|
$this->updateManialinks[self::MLID_LOCAL] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($this->settings->dedimania_enabled) {
|
|
// Get old record of the player
|
|
$oldRecord = $this->getDediRecord($login);
|
|
$save = true;
|
|
if ($oldRecord) {
|
|
if ($oldRecord['Best'] < $time) {
|
|
// Not improved
|
|
$save = false;
|
|
}
|
|
else if ($oldRecord['Best'] == $time) {
|
|
// Same time
|
|
$save = false;
|
|
}
|
|
}
|
|
if ($save) {
|
|
// Save time
|
|
$newRecord = array('Login' => $login, 'NickName' => $player['NickName'], 'Best' => $data[2],
|
|
'Checks' => $this->getChecks($login), 'New' => true);
|
|
$inserted = $this->insertDediRecord($newRecord, $oldRecord);
|
|
if ($inserted) {
|
|
// Get newly saved record
|
|
foreach ($this->dedimaniaData['records']['Records'] as $key => &$record) {
|
|
if ($record['Login'] !== $newRecord['Login']) continue;
|
|
$newRecord = $record;
|
|
break;
|
|
}
|
|
|
|
// Announce record
|
|
if (!$oldRecord || $newRecord['Rank'] < $oldRecord['Rank']) {
|
|
// Gained rank
|
|
$improvement = 'gained the';
|
|
}
|
|
else {
|
|
// Only improved time
|
|
$improvement = 'improved her/his';
|
|
}
|
|
$message = '$<' . $player['NickName'] . '$> ' . $improvement . ' $<$o' . $newRecord['Rank'] .
|
|
'.$> Dedimania Record: ' . Tools::formatTime($newRecord['Best']);
|
|
$this->iControl->chat->sendInformation($message);
|
|
$this->updateManialinks[self::MLID_DEDI] = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get max rank for given login
|
|
*/
|
|
private function getMaxRank($login) {
|
|
if (!isset($this->dedimaniaData['records'])) return null;
|
|
$records = $this->dedimaniaData['records'];
|
|
$maxRank = $records['ServerMaxRank'];
|
|
foreach ($records['Players'] as $player) {
|
|
if ($player['Login'] === $login) {
|
|
if ($player['MaxRank'] > $maxRank) $maxRank = $player['MaxRank'];
|
|
break;
|
|
}
|
|
}
|
|
return $maxRank;
|
|
}
|
|
|
|
/**
|
|
* Inserts the given new dedimania record at the proper position
|
|
*
|
|
* @param struct $newRecord
|
|
* @return bool
|
|
*/
|
|
private function insertDediRecord(&$newRecord, $oldRecord) {
|
|
if (!$newRecord || !isset($this->dedimaniaData['records']) || !isset($this->dedimaniaData['records']['Records'])) return false;
|
|
|
|
$insert = false;
|
|
$newRecords = array();
|
|
|
|
// Get max possible rank
|
|
$maxRank = $this->getMaxRank($newRecord['Login']);
|
|
if (!$maxRank) $maxRank = 30;
|
|
|
|
// Loop through existing records
|
|
foreach ($this->dedimaniaData['records']['Records'] as $key => &$record) {
|
|
if ($record['Rank'] > $maxRank) {
|
|
// Max rank reached
|
|
return false;
|
|
}
|
|
|
|
if ($record['Login'] === $newRecord['Login']) {
|
|
// Old record of the same player
|
|
if ($record['Best'] <= $newRecord['Best']) {
|
|
// It's better - Do nothing
|
|
return false;
|
|
}
|
|
|
|
// Replace old record
|
|
unset($this->dedimaniaData['records']['Records'][$key]);
|
|
$insert = true;
|
|
break;
|
|
}
|
|
|
|
// Other player's record
|
|
if ($record['Best'] <= $newRecord['Best']) {
|
|
// It's better - Skip
|
|
continue;
|
|
}
|
|
|
|
// New record is better - Insert it
|
|
$insert = true;
|
|
if ($oldRecord) {
|
|
// Remove old record
|
|
foreach ($this->dedimaniaData['records']['Records'] as $key2 => $record2) {
|
|
if ($record2['Login'] !== $oldRecord['Login']) continue;
|
|
unset($this->dedimaniaData['records']['Records'][$key2]);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (!$insert && count($this->dedimaniaData['records']['Records']) < $maxRank) {
|
|
// Records list not full - Append new record
|
|
$insert = true;
|
|
}
|
|
|
|
if ($insert) {
|
|
// Insert new record
|
|
array_push($this->dedimaniaData['records']['Records'], $newRecord);
|
|
|
|
// Update ranks
|
|
$this->updateDediRecordRanks();
|
|
|
|
// Save replays
|
|
foreach ($this->dedimaniaData['records']['Records'] as $key => &$record) {
|
|
if ($record['Login'] !== $newRecord['Login']) continue;
|
|
$this->setRecordReplays($record);
|
|
break;
|
|
}
|
|
|
|
// Record inserted
|
|
return true;
|
|
}
|
|
|
|
// No new record
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Updates the replay values for the given record
|
|
*
|
|
* @param struct $record
|
|
*/
|
|
private function setRecordReplays(&$record) {
|
|
if (!$record || !$this->settings->dedimania_enabled) return;
|
|
|
|
// Set validation replay
|
|
$validationReplay = $this->iControl->server->getValidationReplay($record['Login']);
|
|
if ($validationReplay) $record['VReplay'] = $validationReplay;
|
|
|
|
// Set ghost replay
|
|
if ($record['Rank'] <= 1) {
|
|
$dataDirectory = $this->iControl->server->getDataDirectory();
|
|
if (!isset($this->dedimaniaData['directoryAccessChecked'])) {
|
|
$access = $this->iControl->server->checkAccess($dataDirectory);
|
|
if (!$access) {
|
|
trigger_error("No access to the servers data directory. Can't retrieve ghost replays.");
|
|
}
|
|
$this->dedimaniaData['directoryAccessChecked'] = $access;
|
|
}
|
|
if ($this->dedimaniaData['directoryAccessChecked']) {
|
|
$ghostReplay = $this->iControl->server->getGhostReplay($record['Login']);
|
|
if ($ghostReplay) $record['Top1GReplay'] = $ghostReplay;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update the sorting and the ranks of all dedimania records
|
|
*/
|
|
private function updateDediRecordRanks() {
|
|
if (!isset($this->dedimaniaData['records']) || !isset($this->dedimaniaData['records']['Records'])) return;
|
|
|
|
// Sort records
|
|
usort($this->dedimaniaData['records']['Records'], array($this, 'compareRecords'));
|
|
|
|
// Update ranks
|
|
$rank = 1;
|
|
foreach ($this->dedimaniaData['records']['Records'] as &$record) {
|
|
$record['Rank'] = $rank;
|
|
$rank++;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Compare function for sorting dedimania records
|
|
*
|
|
* @param struct $first
|
|
* @param struct $second
|
|
* @return int
|
|
*/
|
|
private function compareRecords($first, $second) {
|
|
if ($first['Best'] < $second['Best']) {
|
|
return -1;
|
|
}
|
|
else if ($first['Best'] > $second['Best']) {
|
|
return 1;
|
|
}
|
|
else {
|
|
if ($first['Rank'] < $second['Rank']) {
|
|
return -1;
|
|
}
|
|
else {
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the dedimania record of the given login
|
|
*
|
|
* @param string $login
|
|
* @return struct
|
|
*/
|
|
private function getDediRecord($login) {
|
|
if (!isset($this->dedimaniaData['records'])) return null;
|
|
$records = $this->dedimaniaData['records']['Records'];
|
|
foreach ($records as $index => $record) {
|
|
if ($record['Login'] === $login) return $record;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Send manialink to clients
|
|
*/
|
|
private function sendManialink($manialink, $login = null) {
|
|
if (!$manialink || !$this->iControl->client) return;
|
|
if (!$login) {
|
|
if (!$this->iControl->client->query('SendDisplayManialinkPage', $manialink->asXML(), 0, false)) {
|
|
trigger_error("Couldn't send manialink to players. " . $this->iControl->getClientErrorText());
|
|
}
|
|
}
|
|
else {
|
|
if (!$this->iControl->client->query('SendDisplayManialinkPageToLogin', $login, $manialink->asXML(), 0, false)) {
|
|
trigger_error("Couldn't send manialink to player '" . $login . "'. " . $this->iControl->getClientErrorText());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle ClientUpdated callback
|
|
*
|
|
* @param mixed $data
|
|
*/
|
|
public function handleClientUpdated($data) {
|
|
$this->openDedimaniaSession(true);
|
|
if (isset($this->updateManialinks[self::MLID_LOCAL])) $this->updateManialinks[self::MLID_LOCAL] = true;
|
|
if (isset($this->updateManialinks[self::MLID_DEDI])) $this->updateManialinks[self::MLID_DEDI] = true;
|
|
}
|
|
|
|
/**
|
|
* Update local records manialink
|
|
*/
|
|
private function buildLocalManialink() {
|
|
$map = $this->iControl->server->getMap();
|
|
if (!$map) {
|
|
return null;
|
|
}
|
|
|
|
$pos_x = (float) $this->config->local_records->widget->pos_x;
|
|
$pos_y = (float) $this->config->local_records->widget->pos_y;
|
|
$title = (string) $this->config->local_records->widget->title;
|
|
$width = (float) $this->config->local_records->widget->width;
|
|
$lines = (int) $this->config->local_records->widget->lines;
|
|
$line_height = (float) $this->config->local_records->widget->line_height;
|
|
|
|
$recordResult = $this->getLocalRecords($map['UId']);
|
|
if (!$recordResult) {
|
|
trigger_error("Couldn't fetch player records.");
|
|
return null;
|
|
}
|
|
|
|
$xml = Tools::newManialinkXml(self::MLID_LOCAL);
|
|
|
|
$frame = $xml->addChild('frame');
|
|
$frame->addAttribute('posn', $pos_x . ' ' . $pos_y);
|
|
|
|
// Background
|
|
$quad = $frame->addChild('quad');
|
|
Tools::addAlignment($quad, 'center', 'top');
|
|
$quad->addAttribute('sizen', ($width * 1.05) . ' ' . (7. + $lines * $line_height));
|
|
$quad->addAttribute('style', 'Bgs1InRace');
|
|
$quad->addAttribute('substyle', 'BgTitleShadow');
|
|
|
|
// Title
|
|
$label = $frame->addChild('label');
|
|
Tools::addAlignment($label);
|
|
Tools::addTranslate($xml);
|
|
$label->addAttribute('posn', '0 ' . ($line_height * -0.9));
|
|
$label->addAttribute('sizen', $width . ' 0');
|
|
$label->addAttribute('style', 'TextTitle1');
|
|
$label->addAttribute('textsize', '2');
|
|
$label->addAttribute('text', $title);
|
|
|
|
// Times
|
|
$index = 0;
|
|
while ($record = $recordResult->fetch_assoc()) {
|
|
$y = -8. - $index * $line_height;
|
|
|
|
$recordFrame = $frame->addChild('frame');
|
|
$recordFrame->addAttribute('posn', '0 ' . $y);
|
|
|
|
// Background
|
|
$quad = $recordFrame->addChild('quad');
|
|
Tools::addAlignment($quad);
|
|
$quad->addAttribute('sizen', $width . ' ' . $line_height);
|
|
$quad->addAttribute('style', 'Bgs1InRace');
|
|
$quad->addAttribute('substyle', 'BgTitleGlow');
|
|
|
|
// Rank
|
|
$label = $recordFrame->addChild('label');
|
|
Tools::addAlignment($label, 'left');
|
|
$label->addAttribute('posn', ($width * -0.47) . ' 0');
|
|
$label->addAttribute('sizen', ($width * 0.06) . ' ' . $line_height);
|
|
$label->addAttribute('textsize', '1');
|
|
$label->addAttribute('textprefix', '$o');
|
|
$label->addAttribute('text', $record['rank']);
|
|
|
|
// Name
|
|
$label = $recordFrame->addChild('label');
|
|
Tools::addAlignment($label, 'left');
|
|
$label->addAttribute('posn', ($width * -0.4) . ' 0');
|
|
$label->addAttribute('sizen', ($width * 0.6) . ' ' . $line_height);
|
|
$label->addAttribute('textsize', '1');
|
|
$label->addAttribute('text', $record['NickName']);
|
|
|
|
// Time
|
|
$label = $recordFrame->addChild('label');
|
|
Tools::addAlignment($label, 'right');
|
|
$label->addAttribute('posn', ($width * 0.47) . ' 0');
|
|
$label->addAttribute('sizen', ($width * 0.25) . ' ' . $line_height);
|
|
$label->addAttribute('textsize', '1');
|
|
$label->addAttribute('text', Tools::formatTime($record['time']));
|
|
|
|
$index++;
|
|
}
|
|
|
|
return $xml;
|
|
}
|
|
|
|
/**
|
|
* Update dedimania records manialink
|
|
*/
|
|
private function buildDedimaniaManialink() {
|
|
if (!isset($this->dedimaniaData['records'])) {
|
|
return;
|
|
}
|
|
$records = $this->dedimaniaData['records']['Records'];
|
|
|
|
$pos_x = (float) $this->config->dedimania_records->widget->pos_x;
|
|
$pos_y = (float) $this->config->dedimania_records->widget->pos_y;
|
|
$title = (string) $this->config->dedimania_records->widget->title;
|
|
$width = (float) $this->config->dedimania_records->widget->width;
|
|
$lines = (int) $this->config->dedimania_records->widget->lines;
|
|
$line_height = (float) $this->config->dedimania_records->widget->line_height;
|
|
|
|
$xml = Tools::newManialinkXml(self::MLID_DEDI);
|
|
|
|
$frame = $xml->addChild('frame');
|
|
$frame->addAttribute('posn', $pos_x . ' ' . $pos_y);
|
|
|
|
// Background
|
|
$quad = $frame->addChild('quad');
|
|
Tools::addAlignment($quad, 'center', 'top');
|
|
$quad->addAttribute('sizen', ($width * 1.05) . ' ' . (7. + $lines * $line_height));
|
|
$quad->addAttribute('style', 'Bgs1InRace');
|
|
$quad->addAttribute('substyle', 'BgTitleShadow');
|
|
|
|
// Title
|
|
$label = $frame->addChild('label');
|
|
Tools::addAlignment($label);
|
|
Tools::addTranslate($xml);
|
|
$label->addAttribute('posn', '0 ' . ($line_height * -0.9));
|
|
$label->addAttribute('sizen', $width . ' 0');
|
|
$label->addAttribute('style', 'TextTitle1');
|
|
$label->addAttribute('textsize', '2');
|
|
$label->addAttribute('text', $title);
|
|
|
|
// Times
|
|
foreach ($records as $index => $record) {
|
|
$y = -8. - $index * $line_height;
|
|
|
|
$recordFrame = $frame->addChild('frame');
|
|
$recordFrame->addAttribute('posn', '0 ' . $y);
|
|
|
|
// Background
|
|
$quad = $recordFrame->addChild('quad');
|
|
Tools::addAlignment($quad);
|
|
$quad->addAttribute('sizen', $width . ' ' . $line_height);
|
|
$quad->addAttribute('style', 'Bgs1InRace');
|
|
$quad->addAttribute('substyle', 'BgTitleGlow');
|
|
|
|
// Rank
|
|
$label = $recordFrame->addChild('label');
|
|
Tools::addAlignment($label, 'left');
|
|
$label->addAttribute('posn', ($width * -0.47) . ' 0');
|
|
$label->addAttribute('sizen', ($width * 0.06) . ' ' . $line_height);
|
|
$label->addAttribute('textsize', '1');
|
|
$label->addAttribute('textprefix', '$o');
|
|
$label->addAttribute('text', $record['Rank']);
|
|
|
|
// Name
|
|
$label = $recordFrame->addChild('label');
|
|
Tools::addAlignment($label, 'left');
|
|
$label->addAttribute('posn', ($width * -0.4) . ' 0');
|
|
$label->addAttribute('sizen', ($width * 0.6) . ' ' . $line_height);
|
|
$label->addAttribute('textsize', '1');
|
|
$label->addAttribute('text', $record['NickName']);
|
|
|
|
// Time
|
|
$label = $recordFrame->addChild('label');
|
|
Tools::addAlignment($label, 'right');
|
|
$label->addAttribute('posn', ($width * 0.47) . ' 0');
|
|
$label->addAttribute('sizen', ($width * 0.25) . ' ' . $line_height);
|
|
$label->addAttribute('textsize', '1');
|
|
$label->addAttribute('text', Tools::formatTime($record['Best']));
|
|
|
|
if ($index >= $lines - 1) break;
|
|
}
|
|
|
|
return $xml;
|
|
}
|
|
|
|
/**
|
|
* Fetch local records for the given map
|
|
*
|
|
* @param string $mapUId
|
|
* @param int $limit
|
|
* @return array
|
|
*/
|
|
private function getLocalRecords($mapUId, $limit = -1) {
|
|
$query = "SELECT * FROM (
|
|
SELECT recs.*, @rank := @rank + 1 as `rank` FROM `" . self::TABLE_RECORDS . "` recs, (SELECT @rank := 0) ra
|
|
WHERE recs.`mapUId` = '" . $this->iControl->database->escape($mapUId) . "'
|
|
ORDER BY recs.`time` ASC
|
|
" . ($limit > 0 ? "LIMIT " . $limit : "") . ") records
|
|
LEFT JOIN `" . Database::TABLE_PLAYERS . "` players
|
|
ON records.`Login` = players.`Login`;";
|
|
return $this->iControl->database->query($query);
|
|
}
|
|
|
|
/**
|
|
* Retrieve the local record for the given map and login
|
|
*
|
|
* @param string $mapUId
|
|
* @param string $login
|
|
* @return array
|
|
*/
|
|
private function getLocalRecord($mapUId, $login) {
|
|
if (!$mapUId || !$login) return null;
|
|
$database = $this->iControl->database;
|
|
$query = "SELECT records.* FROM (
|
|
SELECT recs.*, @rank := @rank + 1 as `rank` FROM `" . self::TABLE_RECORDS . "` `recs`, (SELECT @rank := 0) r
|
|
WHERE recs.`mapUid` = '" . $database->escape($mapUId) . "'
|
|
ORDER BY recs.`time` ASC) `records`
|
|
WHERE records.`Login` = '" . $database->escape($login) . "';";
|
|
$result = $database->query($query);
|
|
if (!$result || !is_object($result)) {
|
|
trigger_error("Couldn't retrieve player record for '" . $login . "'." . $database->mysqli->error);
|
|
return null;
|
|
}
|
|
while ($record = $result->fetch_assoc()) {
|
|
return $record;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Encodes the given xml rpc method and params
|
|
*
|
|
* @param string $method
|
|
* @param array $params
|
|
* @return string
|
|
*/
|
|
private function encode_request($method, $params) {
|
|
$paramArray = array(array('methodName' => $method, 'params' => $params),
|
|
array('methodName' => self::DEDIMANIA_WARNINGSANDTTR2, 'params' => array()));
|
|
return xmlrpc_encode_request(self::XMLRPC_MULTICALL, array($paramArray), array('encoding' => 'UTF-8', 'escaping' => 'markup'));
|
|
}
|
|
|
|
/**
|
|
* Decodes xml rpc response
|
|
*
|
|
* @param string $response
|
|
* @return mixed
|
|
*/
|
|
private function decode($response) {
|
|
return xmlrpc_decode($response, 'utf-8');
|
|
}
|
|
|
|
/**
|
|
* Handles xml rpc fault
|
|
*
|
|
* @param struct $fault
|
|
*/
|
|
private function handleXmlRpcFault($fault) {
|
|
trigger_error('XmlRpc Fault: ' . $fault['faultString'] . ' (' . $fault['faultCode'] . ')');
|
|
}
|
|
}
|
|
|
|
?>
|