diff --git a/application/ManiaControl.bat b/application/ManiaControl.bat index 1938a7d8..c823edcc 100644 --- a/application/ManiaControl.bat +++ b/application/ManiaControl.bat @@ -3,4 +3,4 @@ REM Set the path to your php.exe here set phpPath="D:\Programme\xampp\php\php.exe" REM Start ManiaControl -START "" /B %phpPath% -f "ManiaControl.php" 2>&1 +START "" /B %phpPath% -f "startManiaControl.php" 2>&1 diff --git a/application/ManiaControl.sh b/application/ManiaControl.sh index c73f84c7..b43b48f0 100644 --- a/application/ManiaControl.sh +++ b/application/ManiaControl.sh @@ -1,3 +1,3 @@ #!/bin/sh -php ManiaControl.php 2>&1 & +php startManiaControl.php 2>&1 & echo $! > ManiaControl.pid diff --git a/application/configs/authentication.ManiaControl.xml b/application/configs/authentication.xml similarity index 100% rename from application/configs/authentication.ManiaControl.xml rename to application/configs/authentication.xml diff --git a/application/configs/chat.ManiaControl.xml b/application/configs/chat.xml similarity index 100% rename from application/configs/chat.ManiaControl.xml rename to application/configs/chat.xml diff --git a/application/configs/chatlog.plugin.xml b/application/configs/chatlog.plugin.xml deleted file mode 100644 index ee659092..00000000 --- a/application/configs/chatlog.plugin.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - true - - - chat.log - - - true - - diff --git a/application/configs/commands.ManiaControl.xml b/application/configs/commands.xml similarity index 100% rename from application/configs/commands.ManiaControl.xml rename to application/configs/commands.xml diff --git a/application/configs/core.ManiaControl.xml b/application/configs/core.xml similarity index 100% rename from application/configs/core.ManiaControl.xml rename to application/configs/core.xml diff --git a/application/configs/database.ManiaControl.xml b/application/configs/database.xml similarity index 81% rename from application/configs/database.ManiaControl.xml rename to application/configs/database.xml index 10b48976..677ce413 100644 --- a/application/configs/database.ManiaControl.xml +++ b/application/configs/database.xml @@ -7,10 +7,10 @@ 3306 - steff + maniacontrol kjhgvhbjnfih2394ugnjk - steff_united + maniacontrol_dev diff --git a/application/configs/karma.plugin.xml b/application/configs/karma.plugin.xml deleted file mode 100644 index 7198d770..00000000 --- a/application/configs/karma.plugin.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - true - - - Map Voting - - - 92 - 83 - - diff --git a/application/configs/obstacle.plugin.xml b/application/configs/obstacle.plugin.xml deleted file mode 100644 index 7d6378e5..00000000 --- a/application/configs/obstacle.plugin.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - true - - - operator - - diff --git a/application/configs/plugins.ManiaControl.xml b/application/configs/plugins.ManiaControl.xml deleted file mode 100644 index d9022328..00000000 --- a/application/configs/plugins.ManiaControl.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - diff --git a/application/configs/records.plugin.xml b/application/configs/records.plugin.xml deleted file mode 100644 index bba44fdb..00000000 --- a/application/configs/records.plugin.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - true - - - - true - - - 200 - - - - true - -139 - 65 - Local Records - 40 - 25 - 4 - - - - - - - true - - - - steff_test - 468a0a185c - - - nsa_dev - 3c20cbc737 - - - united_canyon - 703d080ddd - - - united_stadium - 067b0d0017 - - - united_valley - 37ed993fe1 - - - - - true - 139 - 60 - Dedimania - 40 - 20 - 4 - - - - - diff --git a/application/configs/server.ManiaControl.xml b/application/configs/server.ManiaControl.xml deleted file mode 100644 index 179b9eb5..00000000 --- a/application/configs/server.ManiaControl.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - true - - - 144.76.158.111 - localhost - 21003 - - - SuperAdmin - dtcfvgubhnjomkjnbhv - - diff --git a/application/configs/united.plugin.xml b/application/configs/united.plugin.xml deleted file mode 100644 index f8b89e79..00000000 --- a/application/configs/united.plugin.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - false - - - false - - - - 2 - - - false - - - true - - - - - - a - - - - - - - - - - - - 144.76.158.111 - 21013 - SuperAdmin - dtcfvgubhnjomkjnbhv - - - - - 144.76.158.111 - 21033 - SuperAdmin - dtcfvgubhnjomkjnbhv - - - - - 144.76.158.111 - 21053 - SuperAdmin - dtcfvgubhnjomkjnbhv - - - - - - - - - a - - - - - - - - - - - - 144.76.158.111 - 21023 - SuperAdmin - dtcfvgubhnjomkjnbhv - - - - - 144.76.158.111 - 21043 - SuperAdmin - dtcfvgubhnjomkjnbhv - - - - - 144.76.158.111 - 21063 - SuperAdmin - dtcfvgubhnjomkjnbhv - - - - - - - true - - - - true - 76 - 85.5 - 10 - 10 - - true - - - - - diff --git a/application/core/authentication.php b/application/core/authentication.php index 410dbb40..265b8e99 100644 --- a/application/core/authentication.php +++ b/application/core/authentication.php @@ -28,7 +28,7 @@ class Authentication { $this->mc = $mc; // Load config - $this->config = Tools::loadConfig('authentication.ManiaControl.xml'); + $this->config = Tools::loadConfig('authentication.xml'); } /** diff --git a/application/core/callbacks.php b/application/core/callbacks.php index ac0da0aa..5e4814bb 100644 --- a/application/core/callbacks.php +++ b/application/core/callbacks.php @@ -3,7 +3,7 @@ namespace ManiaControl; /** - * Class for handling server callbacks + * Class for handling server and controller callbacks * * @author steeffeen */ @@ -12,14 +12,14 @@ class Callbacks { * Constants */ // ManiaControl callbacks - const CB_IC_1_SECOND = 'ManiaControl.1Second'; - const CB_IC_5_SECOND = 'ManiaControl.5Second'; - const CB_IC_1_MINUTE = 'ManiaControl.1Minute'; - const CB_IC_3_MINUTE = 'ManiaControl.3Minute'; - const CB_IC_ONINIT = 'ManiaControl.OnInit'; - const CB_IC_CLIENTUPDATED = 'ManiaControl.ClientUpdated'; - const CB_IC_BEGINMAP = 'ManiaControl.BeginMap'; - const CB_IC_ENDMAP = 'ManiaControl.EndMap'; + const CB_MC_1_SECOND = 'ManiaControl.1Second'; + const CB_MC_5_SECOND = 'ManiaControl.5Second'; + const CB_MC_1_MINUTE = 'ManiaControl.1Minute'; + const CB_MC_3_MINUTE = 'ManiaControl.3Minute'; + const CB_MC_ONINIT = 'ManiaControl.OnInit'; + const CB_MC_CLIENTUPDATED = 'ManiaControl.ClientUpdated'; + const CB_MC_BEGINMAP = 'ManiaControl.BeginMap'; + const CB_MC_ENDMAP = 'ManiaControl.EndMap'; // ManiaPlanet callbacks const CB_MP_SERVERSTART = 'ManiaPlanet.ServerStart'; const CB_MP_SERVERSTOP = 'ManiaPlanet.ServerStop'; @@ -45,27 +45,24 @@ class Callbacks { const CB_TM_PLAYERCHECKPOINT = 'TrackMania.PlayerCheckpoint'; const CB_TM_PLAYERFINISH = 'TrackMania.PlayerFinish'; const CB_TM_PLAYERINCOHERENCE = 'TrackMania.PlayerIncoherence'; - + /** * Private properties */ - private $mc = null; - + private $maniaControl = null; private $callbackHandlers = array(); - private $last1Second = -1; - private $last5Second = -1; - private $last1Minute = -1; - private $last3Minute = -1; /** * Construct callbacks handler + * + * @param ManiaControl $maniaControl */ - public function __construct($mc) { - $this->mc = $mc; + public function __construct(ManiaControl $maniaControl) { + $this->maniaControl = $maniaControl; // Init values $this->last1Second = time(); @@ -79,12 +76,12 @@ class Callbacks { */ public function onInit() { // On init callback - $this->triggerCallback(self::CB_IC_ONINIT, array(self::CB_IC_ONINIT)); + $this->triggerCallback(self::CB_MC_ONINIT, array(self::CB_MC_ONINIT)); // Simulate begin map - $map = $this->mc->server->getMap(); + $map = $this->maniaControl->server->getMap(); if ($map) { - $this->triggerCallback(self::CB_IC_BEGINMAP, array(self::CB_IC_BEGINMAP, array($map))); + $this->triggerCallback(self::CB_MC_BEGINMAP, array(self::CB_MC_BEGINMAP, array($map))); } } @@ -97,37 +94,39 @@ class Callbacks { $this->last1Second = time(); // 1 second - $this->triggerCallback(self::CB_IC_1_SECOND, array(self::CB_IC_1_SECOND)); + $this->triggerCallback(self::CB_MC_1_SECOND, array(self::CB_MC_1_SECOND)); if ($this->last5Second <= time() - 5) { $this->last5Second = time(); // 5 second - $this->triggerCallback(self::CB_IC_5_SECOND, array(self::CB_IC_5_SECOND)); + $this->triggerCallback(self::CB_MC_5_SECOND, array(self::CB_MC_5_SECOND)); if ($this->last1Minute <= time() - 60) { $this->last1Minute = time(); // 1 minute - $this->triggerCallback(self::CB_IC_1_MINUTE, array(self::CB_IC_1_MINUTE)); + $this->triggerCallback(self::CB_MC_1_MINUTE, array(self::CB_MC_1_MINUTE)); if ($this->last3Minute <= time() - 180) { $this->last3Minute = time(); // 3 minute - $this->triggerCallback(self::CB_IC_3_MINUTE, array(self::CB_IC_3_MINUTE)); + $this->triggerCallback(self::CB_MC_3_MINUTE, array(self::CB_MC_3_MINUTE)); } } } } // Get server callbacks - if (!$this->mc->client) return; - $this->mc->client->resetError(); - $this->mc->client->readCB(); - $callbacks = $this->mc->client->getCBResponses(); - if (!is_array($callbacks) || $this->mc->client->isError()) { - trigger_error("Error reading server callbacks. " . $this->mc->getClientErrorText()); + if (!$this->maniaControl->client) { + return; + } + $this->maniaControl->client->resetError(); + $this->maniaControl->client->readCB(); + $callbacks = $this->maniaControl->client->getCBResponses(); + if (!is_array($callbacks) || $this->maniaControl->client->isError()) { + trigger_error("Error reading server callbacks. " . $this->maniaControl->getClientErrorText()); return; } @@ -139,14 +138,14 @@ class Callbacks { { // Map begin $this->triggerCallback($callbackName, $callback); - $this->triggerCallback(self::CB_IC_BEGINMAP, $callback); + $this->triggerCallback(self::CB_MC_BEGINMAP, $callback); break; } case self::CB_MP_ENDMAP: { // Map end $this->triggerCallback($callbackName, $callback); - $this->triggerCallback(self::CB_IC_ENDMAP, $callback); + $this->triggerCallback(self::CB_MC_ENDMAP, $callback); break; } default: @@ -162,12 +161,14 @@ class Callbacks { * Trigger a specific callback * * @param string $callbackName - * @param mixed $data + * @param array $data */ - public function triggerCallback($callbackName, $data) { - if (!array_key_exists($callbackName, $this->callbackHandlers) || !is_array($this->callbackHandlers[$callbackName])) return; + public function triggerCallback($callbackName, array $callback) { + if (!array_key_exists($callbackName, $this->callbackHandlers)) { + return; + } foreach ($this->callbackHandlers[$callbackName] as $handler) { - call_user_func(array($handler[0], $handler[1]), $data); + call_user_func(array($handler[0], $handler[1]), $callback); } } @@ -176,7 +177,7 @@ class Callbacks { */ public function registerCallbackHandler($callback, $handler, $method) { if (!is_object($handler) || !method_exists($handler, $method)) { - trigger_error("Given handler can't handle callback '" . $callback . "' (no method '" . $method . "')!"); + trigger_error("Given handler can't handle callback '{$callback}' (no method '{$method}')!"); return; } if (!array_key_exists($callback, $this->callbackHandlers) || !is_array($this->callbackHandlers[$callback])) { diff --git a/application/core/chat.php b/application/core/chat.php index 22272c92..4b9ebde9 100644 --- a/application/core/chat.php +++ b/application/core/chat.php @@ -25,7 +25,7 @@ class Chat { $this->mc = $mc; // Load config - $this->config = Tools::loadConfig('chat.ManiaControl.xml'); + $this->config = Tools::loadConfig('chat.xml'); } /** @@ -41,7 +41,8 @@ class Chat { return $this->mc->client->query('ChatSendServerMessage', '$z' . ($prefix ? $this->prefix : '') . $message . '$z'); } else { - return $this->mc->client->query('ChatSendServerMessageToLogin', '$z' . ($prefix ? $this->prefix : '') . $message . '$z', $login); + return $this->mc->client->query('ChatSendServerMessageToLogin', '$z' . ($prefix ? $this->prefix : '') . $message . '$z', + $login); } } diff --git a/application/core/commands.php b/application/core/commands.php index 01ac1c31..bebdf941 100644 --- a/application/core/commands.php +++ b/application/core/commands.php @@ -31,10 +31,10 @@ class Commands { $this->mc = $mc; // Load config - $this->config = Tools::loadConfig('commands.ManiaControl.xml'); + $this->config = Tools::loadConfig('commands.xml'); // Register for callbacks - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_5_SECOND, $this, 'each5Seconds'); + $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MC_5_SECOND, $this, 'each5Seconds'); $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_BILLUPDATED, $this, 'handleBillUpdated'); $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCHAT, $this, 'handleChatCallback'); @@ -345,7 +345,7 @@ class Commands { $this->mc->authentication->sendNotAllowed($login); return; } - $this->mc->quit("ManiaControl shutdown requested by '" . $login . "'"); + $this->mc->quit("ManiaControl shutdown requested by '{$login}'"); } /** diff --git a/application/core/database.php b/application/core/database.php index 5d0b95d8..2c483830 100644 --- a/application/core/database.php +++ b/application/core/database.php @@ -11,32 +11,28 @@ class Database { /** * Constants */ - const TABLE_PLAYERS = 'ic_players'; - const TABLE_MAPS = 'ic_maps'; - + const TABLE_PLAYERS = 'mc_players'; + const TABLE_MAPS = 'mc_maps'; + /** * Public properties */ public $mysqli = null; - + /** * Private properties */ - private $mc = null; - + private $maniaControl = null; private $config = null; - private $multiQueries = ''; - /** * Construct database connection */ - public function __construct($mc) { - $this->mc = $mc; + public function __construct(ManiaControl $maniaControl) { + $this->maniaControl = $maniaControl; // Load config - $this->config = Tools::loadConfig('database.ManiaControl.xml'); - $this->mc->checkConfig($this->config, array("host", "user"), 'database.ManiaControl.xml'); + $this->config = Tools::loadConfig('database.xml'); // Get mysql server information $host = $this->config->xpath('host'); @@ -58,23 +54,12 @@ class Database { // Open database connection $this->mysqli = new \mysqli($host, $user, $pass, null, $port); if ($this->mysqli->connect_error) { - // Connection error - throw new \Exception( - "Error on connecting to mysql server. " . $this->mysqli->connect_error . " (" . $this->mysqli->connect_errno . ")"); + trigger_error($this->mysqli->connect_error, E_USER_ERROR); } - - // Set charset $this->mysqli->set_charset("utf8"); - // Create/Connect database $this->initDatabase(); - - // Init tables - $this->initTables(); - - // Register for callbacks - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_5_SECOND, $this, 'handle5Second'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_BEGINMAP, $this, 'handleBeginMap'); + $this->optimizeTables(); } /** @@ -86,6 +71,8 @@ class Database { /** * Connect to the defined database (create it if needed) + * + * @return bool */ private function initDatabase() { $dbname = $this->config->xpath('database'); @@ -94,307 +81,67 @@ class Database { // Try to connect $result = $this->mysqli->select_db($dbname); - if (!$result) { - // Create database - $query = "CREATE DATABASE `" . $this->escape($dbname) . "`;"; - $result = $this->mysqli->query($query); - if (!$result) { - trigger_error( - "Couldn't create database '" . $dbname . "'. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')', - E_USER_ERROR); - } - else { - // Connect to database - $result = $this->mysqli->select_db($dbname); - if (!$result) { - trigger_error( - "Couldn't select database '" . $dbname . "'. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')', - E_USER_ERROR); - } - } - } - } - - /** - * Create the needed tables - */ - private function initTables() { - $query = ""; - - // Players table - $query .= "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLAYERS . "` ( - `index` int(11) NOT NULL AUTO_INCREMENT, - `Login` varchar(100) NOT NULL, - `NickName` varchar(250) NOT NULL, - `PlayerId` int(11) NOT NULL, - `LadderRanking` int(11) NOT NULL, - `Flags` varchar(50) NOT NULL, - `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`index`), - UNIQUE KEY `Login` (`Login`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Store player metadata' AUTO_INCREMENT=1;"; - - // Maps table - $query .= "CREATE TABLE IF NOT EXISTS `ic_maps` ( - `index` int(11) NOT NULL AUTO_INCREMENT, - `UId` varchar(100) NOT NULL, - `Name` varchar(100) NOT NULL, - `FileName` varchar(200) NOT NULL, - `Author` varchar(150) NOT NULL, - `Environnement` varchar(50) NOT NULL, - `Mood` varchar(50) NOT NULL, - `BronzeTime` int(11) NOT NULL DEFAULT '-1', - `SilverTime` int(11) NOT NULL DEFAULT '-1', - `GoldTime` int(11) NOT NULL DEFAULT '-1', - `AuthorTime` int(11) NOT NULL DEFAULT '-1', - `CopperPrice` int(11) NOT NULL DEFAULT '-1', - `LapRace` tinyint(1) NOT NULL, - `NbLaps` int(11) NOT NULL DEFAULT '-1', - `NbCheckpoints` int(11) NOT NULL DEFAULT '-1', - `MapType` varchar(100) NOT NULL, - `MapStyle` varchar(100) NOT NULL, - `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`index`), - UNIQUE KEY `UId` (`UId`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Store map metadata' AUTO_INCREMENT=1;"; - - // Perform queries - if (!$this->multiQuery($query)) { - trigger_error("Creating basic tables failed. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')', E_USER_ERROR); - } - - // Optimize all existing tables - $query = "SHOW TABLES;"; - $result = $this->query($query); - if (!$result || !is_object($result)) { - trigger_error("Couldn't select tables. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')'); - } - else { - $query = "OPTIMIZE TABLE "; - $count = $result->num_rows; - $index = 0; - while ($row = $result->fetch_row()) { - $query .= "`" . $row[0] . "`"; - if ($index < $count - 1) $query .= ", "; - $index++; - } - $query .= ";"; - if (!$this->query($query)) { - trigger_error("Couldn't optimize tables. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')'); - } - } - } - - /** - * Wrapper for performing a simple query - * - * @param string $query - * @return mixed query result - */ - public function query($query) { - if (!is_string($query)) return false; - if (strlen($query) <= 0) return true; - return $this->mysqli->query($query); - } - - /** - * Perform multi query - * - * @param - * string multi_query - * @return bool whether no error occured during executing the multi query - */ - public function multiQuery($query) { - if (!is_string($query)) return false; - if (strlen($query) <= 0) return true; - $noError = true; - $this->mysqli->multi_query($query); - if ($this->mysqli->error) { - trigger_error("Executing multi query failed. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')'); - $noError = false; - } - while ($this->mysqli->more_results() && $this->mysqli->next_result()) { - if ($this->mysqli->error) { - trigger_error("Executing multi query failed. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')'); - $noError = false; - } - } - return $noError; - } - - /** - * Handle 5Second callback - */ - public function handle5Second($callback = null) { - // Save current players in database - $players = $this->mc->server->getPlayers(); - if ($players) { - $query = ""; - foreach ($players as $player) { - if (!Tools::isPlayer($player)) continue; - $query .= $this->composeInsertPlayer($player); - } - $this->multiQuery($query); - } - } - - /** - * Handle BeginMap callback - */ - public function handleBeginMap($callback) { - $map = $callback[1][0]; - $query = $this->composeInsertMap($map); - $result = $this->query($query); - if ($this->mysqli->error) { - trigger_error("Couldn't save map. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')'); - } - } - - /** - * Get the player index for the given login - * - * @param string $login - * @return int null - */ - public function getPlayerIndex($login) { - $query = "SELECT `index` FROM `" . self::TABLE_PLAYERS . "` WHERE `Login` = '" . $this->escape($login) . "';"; - $result = $this->query($query); - $result = $result->fetch_assoc(); if ($result) { - return $result['index']; + return true; } - return null; - } - - /** - * Get the map index for the given UId - * - * @param string $uid - * @return int null - */ - public function getMapIndex($uid) { - $query = "SELECT `index` FROM `" . self::TABLE_MAPS . "` WHERE `UId` = '" . $this->escape($uid) . "';"; - $result = $this->query($query); - $result = $result->fetch_assoc(); - if ($result) { - return $result['index']; + + // Create database + $databaseQuery = "CREATE DATABASE ?;"; + $databaseStatement = $this->mysqli->prepare($databaseQuery); + if ($this->mysqli->error) { + trigger_error($this->mysqli->error, E_USER_ERROR); + return false; } - return null; - } - - /** - * Compose a query string for inserting the given player - * - * @param array $player - */ - private function composeInsertPlayer($player) { - if (!Tools::isPlayer($player)) return ""; - return "INSERT INTO `" . self::TABLE_PLAYERS . "` ( - `Login`, - `NickName`, - `PlayerId`, - `LadderRanking`, - `Flags` - ) VALUES ( - '" . $this->escape($player['Login']) . "', - '" . $this->escape($player['NickName']) . "', - " . $player['PlayerId'] . ", - " . $player['LadderRanking'] . ", - '" . $this->escape($player['Flags']) . "' - ) ON DUPLICATE KEY UPDATE - `NickName` = VALUES(`NickName`), - `PlayerId` = VALUES(`PlayerId`), - `LadderRanking` = VALUES(`LadderRanking`), - `Flags` = VALUES(`Flags`);"; - } - - /** - * Compose a query string for inserting the given map - * - * @param array $map - */ - private function composeInsertMap($map) { - if (!$map) return ""; - return "INSERT INTO `" . self::TABLE_MAPS . "` ( - `UId`, - `Name`, - `FileName`, - `Author`, - `Environnement`, - `Mood`, - `BronzeTime`, - `SilverTime`, - `GoldTime`, - `AuthorTime`, - `CopperPrice`, - `LapRace`, - `NbLaps`, - `NbCheckpoints`, - `MapType`, - `MapStyle` - ) VALUES ( - '" . $this->escape($map['UId']) . "', - '" . $this->escape($map['Name']) . "', - '" . $this->escape($map['FileName']) . "', - '" . $this->escape($map['Author']) . "', - '" . $this->escape($map['Environnement']) . "', - '" . $this->escape($map['Mood']) . "', - " . $map['BronzeTime'] . ", - " . $map['SilverTime'] . ", - " . $map['GoldTime'] . ", - " . $map['AuthorTime'] . ", - " . $map['CopperPrice'] . ", - " . Tools::boolToInt($map['LapRace']) . ", - " . $map['NbLaps'] . ", - " . $map['NbCheckpoints'] . ", - '" . $this->escape($map['MapType']) . "', - '" . $this->escape($map['MapStyle']) . "' - ) ON DUPLICATE KEY UPDATE - `Name` = VALUES(`Name`), - `FileName` = VALUES(`FileName`), - `Author` = VALUES(`Author`), - `Environnement` = VALUES(`Environnement`), - `Mood` = VALUES(`Mood`), - `BronzeTime` = VALUES(`BronzeTime`), - `SilverTime` = VALUES(`SilverTime`), - `GoldTime` = VALUES(`GoldTime`), - `AuthorTime` = VALUES(`AuthorTime`), - `CopperPrice` = VALUES(`CopperPrice`), - `LapRace` = VALUES(`LapRace`), - `NbLaps` = VALUES(`NbLaps`), - `NbCheckpoints` = VALUES(`NbCheckpoints`), - `MapType` = VALUES(`MapType`), - `MapStyle` = VALUES(`MapStyle`);"; - } - - /** - * Retrieve all information about the player with the given login - */ - public function getPlayer($login) { - if (!$login) return null; - $query = "SELECT * FROM `" . self::TABLE_PLAYERS . "` WHERE `Login` = '" . $this->escape($login) . "';"; - $result = $this->mysqli->query($query); - if ($this->mysqli->error || !$result) { - trigger_error( - "Couldn't select player with login '" . $login . "'. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')'); - return null; + $databaseStatement->bind_param('s', $dbname); + $databaseStatement->execute(); + if ($databaseStatement->error) { + trigger_error($databaseStatement->error, E_USER_ERROR); + return false; } - else { - while ($player = $result->fetch_assoc()) { - return $player; + $databaseStatement->close(); + + // Connect to new database + $this->mysqli->select_db($dbname); + if ($this->mysqli->error) { + trigger_error("Couldn't select database '{$dbname}'. " . $this->mysqli->error, E_USER_ERROR); + return false; + } + return true; + } + + /** + * Optimize all existing tables + * + * @return bool + */ + private function optimizeTables() { + $showQuery = "SHOW TABLES;"; + $result = $this->mysqli->query($showQuery); + if ($this->mysqli->error) { + trigger_error($this->mysqli->error); + return false; + } + $count = $result->num_rows; + if ($count <= 0) { + return true; + } + $optimizeQuery = "OPTIMIZE TABLE "; + $index = 0; + while ($row = $result->fetch_row()) { + $tableName = $row[0]; + $optimizeQuery .= "`{$tableName}`"; + if ($index < $count - 1) { + $optimizeQuery .= ", "; } - return null; + $index++; } - } - - /** - * Escapes the given string for a mysql query - * - * @param string $string - * @return string - */ - public function escape($string) { - return $this->mysqli->escape_string($string); + $optimizeQuery .= ";"; + $this->mysqli->query($optimizeQuery); + if ($this->mysqli->error) { + trigger_error($this->mysqli->error); + return false; + } + return true; } } diff --git a/application/core/core.php b/application/core/maniaControl.php similarity index 52% rename from application/core/core.php rename to application/core/maniaControl.php index 47812bf9..12332953 100644 --- a/application/core/core.php +++ b/application/core/maniaControl.php @@ -11,12 +11,9 @@ require_once __DIR__ . '/chat.php'; require_once __DIR__ . '/commands.php'; require_once __DIR__ . '/database.php'; require_once __DIR__ . '/server.php'; -require_once __DIR__ . '/stats.php'; require_once __DIR__ . '/tools.php'; require_once __DIR__ . '/pluginHandler.php'; -require_once __DIR__ . '/plugin.php'; require_once __DIR__ . '/playerHandler.php'; -require_once __DIR__ . '/player.php'; require_once __DIR__ . '/manialinkIdHandler.php'; list($endiantest) = array_values(unpack('L1L', pack('V', 1))); if ($endiantest == 1) { @@ -38,90 +35,40 @@ class ManiaControl { const VERSION = '0.1'; const API_VERSION = '2013-04-16'; const DATE = 'd-m-y h:i:sa T'; - - /** - * Private properties - */ - private $version = 0; - + /** * Public properties */ public $authentication = null; - public $callbacks = null; - public $client = null; - public $chat = null; - - public $config = null; - public $commands = null; - public $database = null; - - public $debug = false; - public $server = null; - - public $startTime = -1; - - public $stats = null; - - public $manialinkIdHandler = null; - public $pluginHandler = null; - + public $manialinkIdHandler = null; + public $pluginHandler = null; + /** * Private properties */ - //private $plugins = array(); - private $shutdownRequested = false; + private $config = null; /** * Construct ManiaControl */ public function __construct() { - // Load core - $this->config = Tools::loadConfig('core.ManiaControl.xml'); - $this->startTime = time(); - - // Load chat tool + $this->config = Tools::loadConfig('core.xml'); $this->chat = new Chat($this); - - // Load callbacks handler $this->callbacks = new Callbacks($this); - - // Load database $this->database = new Database($this); - - // Load server $this->server = new Server($this); - - // Load authentication $this->authentication = new Authentication($this); - - // Load playerHandler - $this->playerHandler = new PlayerHandler($this); - - // Load manialinkidHandler - $this->manialinkIdHandler = new ManialinkIdHandler(); - - // Load pluginHandler - $this->pluginHandler = new PluginHandler($this); - - // Load commands handler + $this->playerHandler = new PlayerHandler($this); + $this->manialinkIdHandler = new ManialinkIdHandler(); $this->commands = new Commands($this); - - // Load stats manager - $this->stats = new Stats($this); - - // Register for core callbacks - $this->callbacks->registerCallbackHandler(Callbacks::CB_MP_ENDMAP, $this, 'handleEndMap'); - - // Set ManiaControl version - $this->version = self::VERSION; + $this->pluginHandler = new PluginHandler($this); } /** @@ -141,8 +88,6 @@ class ManiaControl { * Quit ManiaControl and log the given message */ public function quit($message = false) { - if ($this->shutdownRequested) return; - if ($this->client) { // Announce quit $this->chat->sendInformation('ManiaControl shutting down.'); @@ -157,7 +102,9 @@ class ManiaControl { } // Shutdown - if ($this->client) $this->client->Terminate(); + if ($this->client) { + $this->client->Terminate(); + } error_log("Quitting ManiaControl!"); exit(); @@ -166,14 +113,12 @@ class ManiaControl { /** * Run ManiaControl */ - public function run($debug = false) { + public function run() { error_log('Starting ManiaControl v' . self::VERSION . '!'); - $this->debug = (bool) $debug; // Load plugins - //$this->loadPlugins(); $this->pluginHandler->loadPlugins(); - + // Connect to server $this->connect(); @@ -181,14 +126,8 @@ class ManiaControl { error_log("Loading completed!"); // Announce ManiaControl - if (!$this->chat->sendInformation('ManiaControl v' . self::VERSION . ' successfully started!')) { - trigger_error("Couldn't announce ManiaControl. " . $this->getClientErrorText()); - } - - //get PlayerList - $this->client->query('GetPlayerList', 300, 0, 2); - $this->playerHandler->addPlayerList($this->client->getResponse()); - + $this->chat->sendInformation('ManiaControl v' . self::VERSION . ' successfully started!'); + // OnInit $this->callbacks->onInit(); @@ -202,14 +141,6 @@ class ManiaControl { // Handle server callbacks $this->callbacks->handleCallbacks(); - // Loop plugins - /*foreach ($this->plugins as $plugin) { - if (!method_exists($plugin, 'loop')) { - continue; - } - $plugin->loop(); - }*/ - // Yield for next tick $loopEnd = microtime(true); $sleepTime = 300000 - $loopEnd + $loopStart; @@ -243,13 +174,11 @@ class ManiaControl { if (!$timeout) trigger_error("Invalid core configuration (timeout).", E_USER_ERROR); $timeout = (int) $timeout[0]; - error_log("Connecting to server at " . $host . ":" . $port . "..."); + error_log("Connecting to server at {$host}:{$port}..."); // Connect if (!$this->client->InitWithIp($host, $port, $timeout)) { - trigger_error( - "Couldn't connect to server! " . $this->client->getErrorMessage() . "(" . $this->client->getErrorCode() . ")", - E_USER_ERROR); + trigger_error("Couldn't connect to server! " . $this->getClientErrorText(), E_USER_ERROR); } $login = $this->server->config->xpath('login'); @@ -261,15 +190,12 @@ class ManiaControl { // Authenticate if (!$this->client->query('Authenticate', $login, $pass)) { - trigger_error( - "Couldn't authenticate on server with user '" . $login . "'! " . $this->client->getErrorMessage() . "(" . - $this->client->getErrorCode() . ")", E_USER_ERROR); + trigger_error("Couldn't authenticate on server with user '{$login}'! " . $this->getClientErrorText(), E_USER_ERROR); } // Enable callback system if (!$this->client->query('EnableCallbacks', true)) { - trigger_error("Couldn't enable callbacks! " . $this->client->getErrorMessage() . "(" . $this->client->getErrorCode() . ")", - E_USER_ERROR); + trigger_error("Couldn't enable callbacks! " . $this->getClientErrorText(), E_USER_ERROR); } // Wait for server to be ready @@ -280,18 +206,12 @@ class ManiaControl { // Set api version if (!$this->client->query('SetApiVersion', self::API_VERSION)) { trigger_error( - "Couldn't set API version '" . self::API_VERSION . "'! This might cause problems. " . - $this->getClientErrorText()); + "Couldn't set API version '" . self::API_VERSION . "'! This might cause problems. " . $this->getClientErrorText()); } // Connect finished error_log("Server connection succesfully established!"); - // Enable service announces - if (!$this->client->query("DisableServiceAnnounces", false)) { - trigger_error("Couldn't enable service announces. " . $this->getClientErrorText()); - } - // Enable script callbacks if needed if ($this->server->getGameMode() === 0) { if (!$this->client->query('GetModeScriptSettings')) { @@ -302,8 +222,7 @@ class ManiaControl { if (array_key_exists('S_UseScriptCallbacks', $scriptSettings)) { $scriptSettings['S_UseScriptCallbacks'] = true; if (!$this->client->query('SetModeScriptSettings', $scriptSettings)) { - trigger_error( - "Couldn't set mode script settings to enable script callbacks. " . $this->getClientErrorText()); + trigger_error("Couldn't set mode script settings to enable script callbacks. " . $this->getClientErrorText()); } else { error_log("Script callbacks successfully enabled."); @@ -312,84 +231,6 @@ class ManiaControl { } } } - - /** - * Load ManiaControl plugins - */ - //private function loadPlugins() { - /* $pluginsConfig = Tools::loadConfig('plugins.ManiaControl.xml'); - if (!$pluginsConfig || !isset($pluginsConfig->plugin)) { - trigger_error('Invalid plugins config.'); - return; - } - - // Load plugin classes - $classes = get_declared_classes(); - foreach ($pluginsConfig->xpath('plugin') as $plugin) { - $fileName = ManiaControlDir . '/plugins/' . $plugin; - if (!file_exists($fileName)) { - trigger_error("Couldn't load plugin '" . $plugin . "'! File doesn't exist. (/plugins/" . $plugin . ")"); - } - else { - require_once $fileName; - error_log("Loading plugin: " . $plugin); - } - } - $plugins = array_diff(get_declared_classes(), $classes); - - // Create plugins - foreach ($plugins as $plugin) { - $nameIndex = stripos($plugin, 'plugin'); - if ($nameIndex === false) continue; - array_push($this->plugins, new $plugin($this)); - }*/ - //} - - /** - * Handle EndMap callback - */ - public function handleEndMap($callback) { - // Autosave match settings - $autosaveMatchsettings = $this->config->xpath('autosave_matchsettings'); - if ($autosaveMatchsettings) { - $autosaveMatchsettings = (string) $autosaveMatchsettings[0]; - if ($autosaveMatchsettings) { - if (!$this->client->query('SaveMatchSettings', 'MatchSettings/' . $autosaveMatchsettings)) { - trigger_error("Couldn't autosave match settings. " . $this->getClientErrorText()); - } - } - } - } - - /** - * Check config settings - */ - public function checkConfig($config, $settings, $name = 'Config XML') { - if (!is_array($settings)) $settings = array($settings); - foreach ($settings as $setting) { - $settingTags = $config->xpath('//' . $setting); - if (empty($settingTags)) { - trigger_error("Missing property '" . $setting . "' in config '" . $name . "'!", E_USER_ERROR); - } - } - } - - /** - * @param mixed $version - */ - public function setVersion($version) - { - $this->version = $version; - } - - /** - * @return mixed - */ - public function getVersion() - { - return $this->version; - } - } ?> diff --git a/application/core/player.php b/application/core/player.php index ac26162c..f1fc1855 100644 --- a/application/core/player.php +++ b/application/core/player.php @@ -1,111 +1,80 @@ login = $rpc_infos['Login']; - $this->nickname = $rpc_infos['NickName']; - $this->pid = $rpc_infos['PlayerId']; - $this->teamid = $rpc_infos['TeamId']; - $this->ipport = $rpc_infos['IPAddress']; - $this->ip = preg_replace('/:\d+/', '', $rpc_infos['IPAddress']); // strip port - //$this->prevstatus = false; - $this->isSpectator = $rpc_infos['IsSpectator']; - $this->isOfficial = $rpc_infos['IsInOfficialMode']; - $this->teamname = $rpc_infos['LadderStats']['TeamName']; - $this->zone = substr($rpc_infos['Path'], 6); // strip 'World|' - $zones = explode('|', $rpc_infos['Path']); - if (isset($zones[1])) { - switch ($zones[1]) { - case 'Europe': - case 'Africa': - case 'Asia': - case 'Middle East': - case 'North America': - case 'South America': - case 'Oceania': - $this->continent = $zones[1]; - $this->nation = $zones[2]; - break; - default: - $this->continent = ''; - $this->nation = $zones[1]; - } - } else { - $this->continent = ''; - $this->nation = ''; - } - $this->ladderrank = $rpc_infos['LadderStats']['PlayerRankings'][0]['Ranking']; - $this->ladderscore = round($rpc_infos['LadderStats']['PlayerRankings'][0]['Score'], 2); - $this->client = $rpc_infos['ClientVersion']; - $this->language = $rpc_infos['Language']; - $this->avatar = $rpc_infos['Avatar']['FileName']; - $this->created = time(); - } else { - // set defaults - $this->pid = 0; - $this->login = ''; - $this->nickname = ''; - $this->ipport = ''; - $this->ip = ''; - //$this->prevstatus = false; - $this->isSpectator = false; - $this->isOfficial = false; - $this->teamname = ''; - $this->zone = ''; - $this->continent = ''; - $this->nation = ''; - $this->ladderrank = 0; - $this->ladderscore = 0; - $this->created = 0; - } - - - //rightlevels, 0 = user, 1 = operator, 2 = admin, 3 = superadmin, 4 = headadmin (from config) - $this->rightLevel = 0; - } + /** + * Public properties + */ + public $index = -1; + public $pid = -1; + public $login = ''; + public $nickname = ''; + public $isFakePlayer = false; + public $teamName = ''; + public $ip = ''; + public $ipFull = ''; + public $clientVersion = ''; + public $zone = ''; + public $continent = ''; + public $nation = ''; + public $isSpectator = false; + public $isOfficial = false; + public $language = ''; + public $avatar = ''; + public $teamId; // TODO: default value + public $unlocked; // TODO: default value + public $ladderRank = -1; + public $ladderScore = -1; + public $created = -1; + public $rightLevel = 0; + + // TODO: usefull construct player without rpc info? + // TODO: add all attributes like, allies, clublink ... just make vardump on rpc infos + // TODO: READ ADDITIONAL INFOS FROM DATABASE + /** + * Construct a player + * + * @param array $rpcInfos + */ + public function __construct($rpcInfos) { + $this->created = time(); + if (!$rpcInfos) { + return; + } + + $this->login = $rpcInfos['Login']; + $this->isFakePlayer = (stripos($this->login, '*') !== false); + $this->nickname = $rpcInfos['NickName']; + $this->pid = $rpcInfos['PlayerId']; + $this->teamId = $rpcInfos['TeamId']; + $this->ipFull = $rpcInfos['IPAddress']; + $this->ip = preg_replace('/:\d+/', '', $this->ipFull); + $this->isSpectator = $rpcInfos['IsSpectator']; + $this->isOfficial = $rpcInfos['IsInOfficialMode']; + $this->teamName = $rpcInfos['LadderStats']['TeamName']; + $this->zone = substr($rpcInfos['Path'], 6); + $zones = explode('|', $rpcInfos['Path']); + if (isset($zones[1])) { + if (isset($zones[2])) { + $this->continent = $zones[1]; + $this->nation = $zones[2]; + } + else { + $this->nation = $zones[1]; + } + } + $this->ladderRank = $rpcInfos['LadderStats']['PlayerRankings'][0]['Ranking']; + $this->ladderScore = round($rpcInfos['LadderStats']['PlayerRankings'][0]['Score'], 2); + $this->clientVersion = $rpcInfos['ClientVersion']; + $this->language = $rpcInfos['Language']; + $this->avatar = $rpcInfos['Avatar']['FileName']; + } } ?> \ No newline at end of file diff --git a/application/core/playerHandler.php b/application/core/playerHandler.php index 0fadfb8e..3486f428 100644 --- a/application/core/playerHandler.php +++ b/application/core/playerHandler.php @@ -1,113 +1,156 @@ 'Player', 1 => 'Operator', 2 => 'Admin', 3 => 'MasterAdmin', 4 => 'Owner'); + + /** + * Private properties + */ + private $maniaControl = null; + private $playerList = array(); - /** - * Private properties - */ - private $playerList; - private $mc; + /** + * Construct player handler + * + * @param ManiaControl $maniaControl + */ + public function __construct(ManiaControl $maniaControl) { + $this->maniaControl = $maniaControl; + + $this->initTables(); + + $this->maniaControl->callbacks->registerCallbackHandler(Callbacks::CB_MC_ONINIT, $this, 'onInit'); + $this->maniaControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'playerConnect'); + $this->maniaControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERDISCONNECT, $this, 'playerDisconnect'); + } - /** - * Public properties - */ - public $rightLevels = array(0 => 'Player', 1 => 'Operator', 2 => 'Admin', 3 => 'MasterAdmin', 4 => 'MasterAdmin'); + /** + * Initialize all necessary tables + * + * @return bool + */ + private function initTables() { + $mysqli = $this->maniaControl->database->mysqli; + $playerTableQuery = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLAYERS . "` ( + `index` int(11) NOT NULL AUTO_INCREMENT, + `pid` int(11) NOT NULL DEFAULT '-1', + `login` varchar(100) COLLATE utf8_unicode_ci NOT NULL, + `ipFull` varchar(50) COLLATE utf8_unicode_ci NOT NULL, + `clientVersion` varchar(50) COLLATE utf8_unicode_ci NOT NULL, + `zone` varchar(150) COLLATE utf8_unicode_ci NOT NULL, + `language` varchar(50) COLLATE utf8_unicode_ci NOT NULL, + `avatar` varchar(100) COLLATE utf8_unicode_ci NOT NULL, + `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`index`), + UNIQUE KEY `login` (`login`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Player data' AUTO_INCREMENT=1;"; + $playerTableStatement = $mysqli->prepare($playerTableQuery); + if ($mysqli->error) { + trigger_error($mysqli->error, E_USER_ERROR); + return false; + } + $playerTableStatement->execute(); + if ($playerTableStatement->error) { + trigger_error($playerTableStatement->error, E_USER_ERROR); + return false; + } + $playerTableStatement->close(); + return true; + } - public function __construct(ManiaControl $mc){ - $this->mc = $mc; - $this->playerList = array(); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'playerConnect'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERDISCONNECT, $this, 'playerDisconnect'); - } + /** + * Handle OnInit callback + * + * @param array $callback + */ + public function onInit(array $callback) { + $this->maniaControl->client->query('GetPlayerList', 300, 0, 2); + $playerList = $this->maniaControl->client->getResponse(); + foreach ($playerList as $player) { + $callback = array(Callbacks::CB_MP_PLAYERCONNECT, array($player['Login'])); + $this->playerConnect($callback); + } + } + /** + * Handle playerConnect callback + * + * @param array $callback + */ + public function playerConnect(array $callback) { + $login = $callback[1][0]; + $this->maniaControl->client->query('GetDetailedPlayerInfo', $login); + $playerInfo = $this->maniaControl->client->getResponse(); + $player = new Player($playerInfo); + $this->addPlayer($player); + } - /** - * initializes a Whole PlayerList - * @param $players - */ - public function addPlayerList($players){ - foreach($players as $player){ - $this->playerConnect(array($player['Login'], '')); - } - } - /** - * Handles a playerConnect - * @param $player - */ - public function playerConnect($player){ - //TODO: Welcome Message?, on mc restart not all players listed, no relay support yet - //TODO: Add Rights - //TODO: Database - $this->mc->client->query('GetDetailedPlayerInfo', $player[0]); - $this->addPlayer(new Player($this->mc->client->getResponse())); - $player = $this->playerList[$player[0]]; - if($player->pid != 0){ //Player 0 = server - $string = array(0 => 'New Player', 1 => 'Operator', 2 => 'Admin', 3 => 'MasterAdmin', 4 => 'MasterAdmin'); - $this->mc->chat->sendChat('$ff0'.$string[$player->rightLevel].': '. $player->nickname . '$z $ff0Nation:$fff ' . $player->nation . ' $ff0Ladder: $fff' . $player->ladderrank); - } - } + /** + * Handle playerDisconnect callback + * + * @param array $callback + */ + public function playerDisconnect(array $callback) { + $login = $callback[1][0]; + $player = $this->removePlayer($login); + } - /** - * Handles a playerDisconnect - * @param $player - */ - public function playerDisconnect($player){ - $player = $this->removePlayer($player[0]); - $played = TOOLS::formatTime(time() - $player->created); - $this->mc->chat->sendChat($player->nickname . '$z $ff0has left the game. Played:$fff ' . $played); - } + /** + * Get a Player from the PlayerList + * + * @param string $login + * @return Player + */ + public function getPlayer($login) { + if (!isset($this->playerList[$login])) { + return null; + } + return $this->playerList[$login]; + } + /** + * Add a player to the PlayerList + * + * @param Player $player + * @return bool + */ + private function addPlayer(Player $player) { + if (!$player) { + return false; + } + $this->playerList[$player->login] = $player; + return true; + } - /** - * Gets a Player from the Playerlist - * @param $login - * @return null - */ - public function getPlayer($login){ - if (isset($this->playerList[$login])) - return $this->playerList[$login]; - else - return null; - } - - /** - * Adds a player to the PlayerList - * @param Player $player - * @return bool - */ - private function addPlayer(Player $player){ - if($player != null){ - $this->playerList[$player->login] = $player; - return true; - }else{ - return false; - } - } - /** - * Removes a Player from the PlayerList - * @param $login - * @return Player $player - */ - private function removePlayer($login){ - if(isset($this->playerList[$login])){ - $player = $this->playerList[$login]; - unset($this->playerList[$login]); - } else { - $player = null; - } - return $player; - } + /** + * Remove a Player from the PlayerList + * + * @param string $login + * @return Player $player + */ + private function removePlayer($login) { + if (!isset($this->playerList[$login])) { + return null; + } + $player = $this->playerList[$login]; + unset($this->playerList[$login]); + return $player; + } } \ No newline at end of file diff --git a/application/core/plugin.php b/application/core/plugin.php index 75e51564..a3246597 100644 --- a/application/core/plugin.php +++ b/application/core/plugin.php @@ -3,152 +3,55 @@ namespace ManiaControl; /** - * Class plugin parent class for all plugins + * Plugin parent class * * @author Lukas Kremsmayr and steeffeen */ - - - class Plugin { - +abstract class Plugin { + /** - * Private properties - */ - private $mc; - private $version; - private $author; - private $updateUrl; - private $name; - private $description; - private $active; - - public function __construct($mc, $name, $version = 0, $author = '', $description = '', $updateUrl = ''){ - $this->mc = $mc; - $this->name = $name; - $this->version = $version; - $this->author = $author; - $this->description = $description; - $this->updateUrl = $updateUrl; - - $this->mc->pluginHandler->registerPlugin($this); - } - - /** - * Reserves manialinks on the ManialinkIdHandler - * - * @param int $count - * @return array with manialink Ids + * Private properties */ - public function reserveManialinkIds($count){ - return $this->mc->manialinkIdHandler->reserveManialikIds($count); - } + protected $maniaControl; + protected $name; + protected $version; + protected $author; + protected $description; - public function checkUpdate(){ - - } + /** + * Create plugin instance + * + * @param ManiaControl $maniaControl + */ + public abstract function __construct(ManiaControl $maniaControl); - /** - * Enables the Plugin - */ - public function enablePlugin() - { - $this->active = true; - } + /** + * Get plugin author + * + * @return string + */ + public abstract function getAuthor(); - /** - * Disable the Plugin - */ - public function disablePlugin() - { - $this->active = false; - } + /** + * Get plugin version + * + * @return float + */ + public abstract function getVersion(); - /** - * @return mixed - */ - public function isActive() - { - return $this->active; - } + /** + * Get plugin name + * + * @return string + */ + public abstract function getName(); - /** - * @param mixed $author - */ - public function setAuthor($author) - { - $this->author = $author; - } + /** + * Get plugin description + * + * @return string + */ + public abstract function getDescription(); +} - /** - * @return mixed - */ - public function getAuthor() - { - return $this->author; - } - - /** - * @param mixed $updateUrl - */ - public function setUpdateUrl($updateUrl) - { - $this->updateUrl = $updateUrl; - } - - /** - * @return mixed - */ - public function getUpdateUrl() - { - return $this->updateUrl; - } - - /** - * @param mixed $version - */ - public function setVersion($version) - { - $this->version = $version; - } - - /** - * @return mixed - */ - public function getVersion() - { - return $this->version; - } - /** - * @param mixed $name - */ - public function setName($name) - { - $this->name = $name; - } - - /** - * @return mixed - */ - public function getName() - { - return $this->name; - } - - /** - * @param string $description - */ - public function setDescription($description) - { - $this->description = $description; - } - - /** - * @return string - */ - public function getDescription() - { - return $this->description; - } - - } -?> \ No newline at end of file +?> diff --git a/application/core/pluginHandler.php b/application/core/pluginHandler.php index 955812b0..60ad1992 100644 --- a/application/core/pluginHandler.php +++ b/application/core/pluginHandler.php @@ -2,32 +2,163 @@ namespace ManiaControl; +require_once __DIR__ . '/plugin.php'; + /** - * Class handles plugins + * Class handling plugins * * @author Lukas Kremsmayr and steeffeen */ +class PluginHandler { + /** + * Constants + */ + const TABLE_PLUGINS = 'mc_plugins'; + + /** + * Private properties + */ + private $maniaControl = null; + private $activePlugins = array(); + private $pluginClasses = array(); + /** + * Construct plugin handler + * + * @param ManiaControl $maniaControl + */ + public function __construct(ManiaControl $maniaControl) { + $this->maniaControl = $maniaControl; + $this->initTables(); + } - class PluginHandler { + /** + * Initialize necessary database tables + * + * @return bool + */ + private function initTables() { + $mysqli = $this->maniaControl->database->mysqli; + $pluginsTableQuery = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLUGINS . "` ( + `index` int(11) NOT NULL AUTO_INCREMENT, + `className` varchar(100) COLLATE utf8_unicode_ci NOT NULL, + `active` tinyint(1) NOT NULL DEFAULT '0', + `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`index`) + ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='ManiaControl plugin status' AUTO_INCREMENT=1;"; + $tableStatement = $mysqli->prepare($pluginsTableQuery); + if ($mysqli->error) { + trigger_error($mysqli->error, E_USER_ERROR); + return false; + } + $tableStatement->execute(); + if ($tableStatement->error) { + trigger_error($tableStatement->error, E_USER_ERROR); + return false; + } + $tableStatement->close(); + return true; + } - /** - * Private properties - */ - private $mc; - private $plugins; + /** + * Save plugin status in database + * + * @param string $className + * @param bool $active + * @return bool + */ + private function savePluginStatus($className, $active) { + $mysqli = $this->maniaControl->database->mysqli; + $pluginStatusQuery = "INSERT INTO `" . self::TABLE_PLUGINS . "` ( + `className`, + `active` + ) VALUES ( + ?, ? + ) ON DUPLICATE KEY UPDATE + `active` = VALUES(`active`);"; + $pluginStatement = $mysqli->prepare($pluginStatusQuery); + if ($mysqli->error) { + trigger_error($mysqli->error); + return false; + } + $activeInt = ($active ? 1 : 0); + $pluginStatement->bind_param('si', $className, $activeInt); + $pluginStatement->execute(); + if ($pluginStatement->error) { + trigger_error($pluginStatement->error); + return false; + } + $pluginStatement->close(); + return true; + } - public function __construct($mc){ - $this->mc = $mc; - $this->plugins = array(); - } + /** + * Get plugin status from database + * + * @param string $className + * @return bool + */ + private function getPluginStatus($className) { + $mysqli = $this->maniaControl->database->mysqli; + $pluginStatusQuery = "SELECT `active` FROM `" . self::TABLE_PLUGINS . "` + WHERE `className` = ?;"; + $pluginStatement = $mysqli->prepare($pluginStatusQuery); + if ($mysqli->error) { + trigger_error($mysqli->error); + return false; + } + $pluginStatement->bind_param('s', $className); + $pluginStatement->execute(); + if ($pluginStatement->error) { + trigger_error($pluginStatement->error); + $pluginStatement->close(); + return false; + } + $pluginStatement->store_result(); + if ($pluginStatement->num_rows <= 0) { + $pluginStatement->free_result(); + $pluginStatement->close(); + return false; + } + $pluginStatement->bind_result($activeInt); + $pluginStatement->fetch(); + $active = ($activeInt === 1); + $pluginStatement->free_result(); + $pluginStatement->close(); + return $active; + } - public function registerPlugin($plugin){ - array_push($this->plugins, $plugin); - } + /** + * Load complete plugins directory and start all configured plugins + */ + public function loadPlugins() { + $pluginsDirectory = ManiaControlDir . '/plugins/'; + $pluginFiles = scandir($pluginsDirectory, 0); + foreach ($pluginFiles as $pluginFile) { + if (stripos($pluginFile, '.') === 0) { + continue; + } + $classesBefore = get_declared_classes(); + $success = include_once $pluginsDirectory . $pluginFile; + if (!$success) { + continue; + } + $classesAfter = get_declared_classes(); + $newClasses = array_diff($classesAfter, $classesBefore); + foreach ($newClasses as $className) { + if (!is_subclass_of($className, 'ManiaControl\Plugin')) { + continue; + } + array_push($this->pluginClasses, $className); + $active = $this->getPluginStatus($className); + if (!$active) { + continue; + } + $plugin = new $className($this->maniaControl); + array_push($this->activePlugins, $plugin); + } + } + } +} - public function loadPlugins(){ - - } - } -?> \ No newline at end of file +?> diff --git a/application/core/server.php b/application/core/server.php index bed14fc9..785c85a2 100644 --- a/application/core/server.php +++ b/application/core/server.php @@ -31,11 +31,10 @@ class Server { $this->mc = $mc; // Load config - $this->config = Tools::loadConfig('server.ManiaControl.xml'); - $this->mc->checkConfig($this->config, array('host', 'port', 'login', 'pass'), 'server'); + $this->config = Tools::loadConfig('server.xml'); // Register for callbacks - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_1_SECOND, $this, 'eachSecond'); + $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MC_1_SECOND, $this, 'eachSecond'); } /** @@ -226,8 +225,8 @@ class Server { } return $gameMode; } - - //TODO: remove getPlayer / getPlayers -> methods now in playerHandler handeld, but should be improved more + + // TODO: remove getPlayer / getPlayers -> methods now in playerHandler handeld, but should be improved more /** * Fetch player info * diff --git a/application/core/tools.php b/application/core/tools.php index ae57ffbf..ce47b9e6 100644 --- a/application/core/tools.php +++ b/application/core/tools.php @@ -140,15 +140,15 @@ class Tools { return $format; } - /** - * Formats the given time (seconds) to hh:mm:ss - * - * @param int $time - * @return string - */ - public static function formatTimeH($seconds) { - return gmdate("H:i:s", $seconds); - } + /** + * Formats the given time (seconds) to hh:mm:ss + * + * @param int $time + * @return string + */ + public static function formatTimeH($seconds) { + return gmdate("H:i:s", $seconds); + } /** * Convert given data to real boolean diff --git a/application/plugins/oldstructure/chatlog.plugin.php b/application/plugins/oldstructure/chatlog.plugin.php deleted file mode 100644 index 61e60bb1..00000000 --- a/application/plugins/oldstructure/chatlog.plugin.php +++ /dev/null @@ -1,85 +0,0 @@ -mc = $mc; - - // Load config - $this->config = Tools::loadConfig('chatlog.plugin.xml'); - - // Check for enabled setting - if (!Tools::toBool($this->config->enabled)) return; - - // Load settings - $this->loadSettings(); - - // Register for callbacksc - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCHAT, $this, 'handlePlayerChatCallback'); - - error_log('Chatlog Pugin v' . self::VERSION . ' ready!'); - } - - /** - * Load settings from config - */ - private function loadSettings() { - $this->settings = new \stdClass(); - - // File name - $fileName = (string) $this->config->filename; - $this->settings->fileName = ManiaControlDir . '/' . $fileName; - - // log_server_messages - $log_server_messages = $this->config->xpath('log_server_messages'); - $this->settings->log_server_messages = ($log_server_messages ? (Tools::toBool($log_server_messages[0])) : false); - } - - /** - * Handle PlayerChat callback - */ - public function handlePlayerChatCallback($callback) { - $data = $callback[1]; - if ($data[0] <= 0 && !$this->settings->log_server_messages) { - // Skip server message - return; - } - $this->logText($data[2], $data[1]); - } - - /** - * Log the given message - * - * @param string $message - * @param string $login - */ - private function logText($text, $login = null) { - $message = date(ManiaControl::DATE) . '>> ' . ($login ? $login . ': ' : '') . $text . PHP_EOL; - file_put_contents($this->settings->fileName, $message, FILE_APPEND); - } -} - -?> diff --git a/application/plugins/oldstructure/karma.plugin.php b/application/plugins/oldstructure/karma.plugin.php deleted file mode 100644 index f5b89cd7..00000000 --- a/application/plugins/oldstructure/karma.plugin.php +++ /dev/null @@ -1,305 +0,0 @@ -mc = $mc; - - // Load config - $this->config = Tools::loadConfig('karma.plugin.xml'); - if (!Tools::toBool($this->config->enabled)) return; - - // Init database - $this->initDatabase(); - - // Register for callbacks - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_ONINIT, $this, 'handleOnInitCallback'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_BEGINMAP, $this, 'handleBeginMapCallback'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'handlePlayerConnectCallback'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, - 'handleManialinkPageAnswerCallback'); - - error_log('Karma Pugin v' . self::VERSION . ' ready!'); - } - - /** - * Repetitive actions - */ - public function loop() { - if ($this->sendManialinkRequested > 0 && $this->sendManialinkRequested <= time()) { - $this->sendManialinkRequested = -1; - - // Send manialink to all players - $players = $this->mc->server->getPlayers(); - foreach ($players as $player) { - $login = $player['Login']; - $manialink = $this->buildManialink($login); - if (!$manialink) { - // Skip and retry - $this->sendManialinkRequested = time() + 5; - continue; - } - Tools::sendManialinkPage($this->mc->client, $manialink->asXml(), $login); - } - } - } - - /** - * Handle OnInit ManiaControl callback - * - * @param array $callback - */ - public function handleOnInitCallback($callback) { - // Send manialink to all players once - $this->sendManialinkRequested = time() + 3; - } - - /** - * Handle ManiaControl BeginMap callback - * - * @param array $callback - */ - public function handleBeginMapCallback($callback) { - // Send manialink to all players once - $this->sendManialinkRequested = time() + 2; - } - - /** - * Handle PlayerConnect callback - * - * @param array $callback - */ - public function handlePlayerConnectCallback($callback) { - $login = $callback[1][0]; - $manialink = $this->buildManialink($login); - if (!$manialink) return; - Tools::sendManialinkPage($this->mc->client, $manialink->asXml(), $login); - } - - /** - * Create necessary tables - */ - private function initDatabase() { - $query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_KARMA . "` ( - `index` int(11) NOT NULL AUTO_INCREMENT, - `mapIndex` int(11) NOT NULL, - `playerIndex` int(11) NOT NULL, - `vote` tinyint(1) NOT NULL, - `changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (`index`), - UNIQUE KEY `player_map_vote` (`mapIndex`, `playerIndex`) - ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Save players map votes' AUTO_INCREMENT=1;"; - $result = $this->mc->database->query($query); - if ($this->mc->database->mysqli->error) { - trigger_error('MySQL Error on creating karma table. ' . $this->mc->database->mysqli->error, E_USER_ERROR); - } - } - - /** - * Handle ManialinkPageAnswer callback - * - * @param array $callback - */ - public function handleManialinkPageAnswerCallback($callback) { - $action = $callback[1][2]; - if (substr($action, 0, strlen(self::MLID_KARMA)) !== self::MLID_KARMA) return; - - // Get vote - $action = substr($action, -4); - $vote = null; - switch ($action) { - case '.pos': - { - $vote = 1; - break; - } - case '.neu': - { - $vote = 0; - break; - } - case '.neg': - { - $vote = -1; - break; - } - default: - { - return; - } - } - - // Save vote - $login = $callback[1][1]; - $playerIndex = $this->mc->database->getPlayerIndex($login); - $map = $this->mc->server->getMap(); - $mapIndex = $this->mc->database->getMapIndex($map['UId']); - $query = "INSERT INTO `" . self::TABLE_KARMA . "` ( - `mapIndex`, - `playerIndex`, - `vote` - ) VALUES ( - " . $mapIndex . ", - " . $playerIndex . ", - " . $vote . " - ) ON DUPLICATE KEY UPDATE - `vote` = VALUES(`vote`);"; - $result = $this->mc->database->query($query); - if (!$result) return; - - // Send success message - $this->mc->chat->sendSuccess('Vote successfully updated!', $login); - - // Send updated manialink - $this->sendManialinkRequested = time() + 1; - } - - /** - * Build karma voting manialink xml for the given login - */ - private function buildManialink($login) { - // Get config - $title = (string) $this->config->title; - $pos_x = (float) $this->config->pos_x; - $pos_y = (float) $this->config->pos_y; - - $mysqli = $this->mc->database->mysqli; - - // Get indezes - $playerIndex = $this->mc->database->getPlayerIndex($login); - if ($playerIndex === null) return null; - $map = $this->mc->server->getMap(); - if (!$map) return null; - $mapIndex = $this->mc->database->getMapIndex($map['UId']); - if ($mapIndex === null) return null; - - // Get votings - $query = "SELECT - (SELECT `vote` FROM `" . - self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `playerIndex` = " . $playerIndex . ") as `playerVote`, - (SELECT COUNT(`vote`) FROM `" . - self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `vote` = 1) AS `positiveVotes`, - (SELECT COUNT(`vote`) FROM `" . - self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `vote` = 0) AS `neutralVotes`, - (SELECT COUNT(`vote`) FROM `" . - self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `vote` = -1) AS `negativeVotes` - FROM `" . self::TABLE_KARMA . "`;"; - $result = $mysqli->query($query); - if ($mysqli->error) { - trigger_error('MySQL ERROR: ' . $mysqli->error); - } - $votes = $result->fetch_assoc(); - if (!$votes) { - $votes = array('playerVote' => null, 'positiveVotes' => 0, 'neutralVotes' => 0, 'negativeVotes' => 0); - } - - // Build manialink - $xml = Tools::newManialinkXml(self::MLID_KARMA); - - $frameXml = $xml->addChild('frame'); - $frameXml->addAttribute('posn', $pos_x . ' ' . $pos_y); - - // Title - $labelXml = $frameXml->addChild('label'); - Tools::addAlignment($labelXml); - $labelXml->addAttribute('posn', '0 4.5 -1'); - $labelXml->addAttribute('sizen', '22 0'); - $labelXml->addAttribute('style', 'TextTitle1'); - $labelXml->addAttribute('textsize', '1'); - $labelXml->addAttribute('text', $title); - - // Background - $quadXml = $frameXml->addChild('quad'); - Tools::addAlignment($quadXml); - $quadXml->addAttribute('sizen', '23 15 -2'); - $quadXml->addAttribute('style', 'Bgs1InRace'); - $quadXml->addAttribute('substyle', 'BgTitleShadow'); - - // Votes - for ($i = 1; $i >= -1; $i--) { - $x = $i * 7.; - - // Vote button - $quadXml = $frameXml->addChild('quad'); - Tools::addAlignment($quadXml); - $quadXml->addAttribute('posn', $x . ' 0 0'); - $quadXml->addAttribute('sizen', '6 6'); - $quadXml->addAttribute('style', 'Icons64x64_1'); - - // Vote count - $labelXml = $frameXml->addChild('label'); - Tools::addAlignment($labelXml); - $labelXml->addAttribute('posn', $x . ' -4.5 0'); - $labelXml->addAttribute('style', 'TextTitle1'); - $labelXml->addAttribute('textsize', '2'); - - if ((string) $i === $votes['playerVote']) { - // Player vote X - $voteQuadXml = $frameXml->addChild('quad'); - Tools::addAlignment($voteQuadXml); - $voteQuadXml->addAttribute('posn', $x . ' 0 1'); - $voteQuadXml->addAttribute('sizen', '6 6'); - $voteQuadXml->addAttribute('style', 'Icons64x64_1'); - $voteQuadXml->addAttribute('substyle', 'Close'); - } - - switch ($i) { - case 1: - { - // Positive - $quadXml->addAttribute('substyle', 'LvlGreen'); - $quadXml->addAttribute('action', self::MLID_KARMA . '.pos'); - $labelXml->addAttribute('text', $votes['positiveVotes']); - break; - } - case 0: - { - // Neutral - $quadXml->addAttribute('substyle', 'LvlYellow'); - $quadXml->addAttribute('action', self::MLID_KARMA . '.neu'); - $labelXml->addAttribute('text', $votes['neutralVotes']); - break; - } - case -1: - { - // Negative - $quadXml->addAttribute('substyle', 'LvlRed'); - $quadXml->addAttribute('action', self::MLID_KARMA . '.neg'); - $labelXml->addAttribute('text', $votes['negativeVotes']); - break; - } - } - } - - return $xml; - } -} - -?> diff --git a/application/plugins/oldstructure/obstacle.plugin.php b/application/plugins/oldstructure/obstacle.plugin.php deleted file mode 100644 index b52c6859..00000000 --- a/application/plugins/oldstructure/obstacle.plugin.php +++ /dev/null @@ -1,63 +0,0 @@ -mc = $mc; - - // Load config - $this->config = Tools::loadConfig('obstacle.plugin.xml'); - - // Check for enabled setting - if (!Tools::toBool($this->config->enabled)) return; - - // Register for jump command - $this->mc->commands->registerCommandHandler('jumpto', $this, 'command_jumpto'); - - error_log('Obstacle Pugin v' . self::VERSION . ' ready!'); - } - - /** - * Handle jumpto command - */ - public function command_jumpto($chat) { - $login = $chat[1][1]; - $rightLevel = (string) $this->config->jumps_rightlevel; - if (!$this->mc->authentication->checkRight($login, $rightLevel)) { - // Not allowed - $this->mc->authentication->sendNotAllowed($login); - } - else { - // Send jump callback - $params = explode(' ', $chat[1][2], 2); - $param = $login . ";" . $params[1] . ";"; - if (!$this->mc->client->query('TriggerModeScriptEvent', self::CB_JUMPTO, $param)) { - trigger_error("Couldn't send jump callback for '" . $login . "'. " . $this->mc->getClientErrorText()); - } - } - } -} - -?> diff --git a/application/plugins/oldstructure/plugin.ManiaControl.php b/application/plugins/oldstructure/plugin.ManiaControl.php deleted file mode 100644 index 5ea3a62b..00000000 --- a/application/plugins/oldstructure/plugin.ManiaControl.php +++ /dev/null @@ -1,37 +0,0 @@ -mc = $mc; - - error_log('Pugin v' . self::VERSION . ' ready!'); - } - - /** - * Perform actions during each loop - */ - public function loop() { - } -} - -?> diff --git a/application/plugins/oldstructure/records.plugin.php b/application/plugins/oldstructure/records.plugin.php deleted file mode 100644 index 40e2b3c7..00000000 --- a/application/plugins/oldstructure/records.plugin.php +++ /dev/null @@ -1,1216 +0,0 @@ -mc = $mc; - - // 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->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_ONINIT, $this, 'handleOnInit'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_1_SECOND, $this, 'handle1Second'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_1_MINUTE, $this, 'handle1Minute'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_3_MINUTE, $this, 'handle3Minute'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_BEGINMAP, $this, 'handleMapBegin'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_CLIENTUPDATED, $this, 'handleClientUpdated'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_ENDMAP, $this, 'handleMapEnd'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'handlePlayerConnect'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERDISCONNECT, $this, 'handlePlayerDisconnect'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_TM_PLAYERFINISH, $this, 'handlePlayerFinish'); - $this->mc->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->mc->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->mc->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->mc->server->getSystemInfo(); - $serverData['Packmask'] = substr($systemInfo['TitleId'], 2); - $serverVersion = $this->mc->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->mc->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->mc->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->mc->server->getOptions(); - if (!$server) return null; - $client = null; - $players = null; - $spectators = null; - $this->mc->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->mc->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->mc->server->getGameMode(); - if ($gameMode === null) { - trigger_error("Couldn't retrieve game mode. " . $this->mc->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->mc->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->mc->server->getMap(); - if (!$newMap) return; - if (!$this->mapInfo || $this->mapInfo['UId'] !== $newMap['UId']) { - $this->mapInfo = $this->getMapInfo(); - } - $map = $newMap; - - $player = $this->mc->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->mc->chat->sendInformation($message); - $save = false; - } - } - if ($save) { - // Save time - $database = $this->mc->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->mc->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->mc->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->mc->server->getValidationReplay($record['Login']); - if ($validationReplay) $record['VReplay'] = $validationReplay; - - // Set ghost replay - if ($record['Rank'] <= 1) { - $dataDirectory = $this->mc->server->getDataDirectory(); - if (!isset($this->dedimaniaData['directoryAccessChecked'])) { - $access = $this->mc->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->mc->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->mc->client) return; - if (!$login) { - if (!$this->mc->client->query('SendDisplayManialinkPage', $manialink->asXML(), 0, false)) { - trigger_error("Couldn't send manialink to players. " . $this->mc->getClientErrorText()); - } - } - else { - if (!$this->mc->client->query('SendDisplayManialinkPageToLogin', $login, $manialink->asXML(), 0, false)) { - trigger_error("Couldn't send manialink to player '" . $login . "'. " . $this->mc->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->mc->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->mc->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->mc->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->mc->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'] . ')'); - } -} - -?> diff --git a/application/plugins/oldstructure/united.plugin.php b/application/plugins/oldstructure/united.plugin.php deleted file mode 100644 index 8ec3c2ed..00000000 --- a/application/plugins/oldstructure/united.plugin.php +++ /dev/null @@ -1,677 +0,0 @@ -mc = $mc; - - // Load config - $this->config = Tools::loadConfig('united.plugin.xml'); - $this->loadSettings(); - - // Check for enabled setting - if (!$this->settings->enabled) return; - - // Load clients - $this->loadClients(); - - // Register for callbacks - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_ONINIT, $this, 'handleOnInitCallback'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_IC_5_SECOND, $this, 'handle5Seconds'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'handlePlayerConnect'); - $this->mc->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, - 'handleManialinkPageAnswer'); - - // Register for commands - $this->mc->commands->registerCommandHandler('nextserver', $this, 'handleNextServerCommand'); - - if ($this->settings->widgets_enabled) { - // Build addfavorite manialink - $this->buildFavoriteManialink(); - } - - error_log('United Pugin v' . self::VERSION . ' ready!'); - } - - /** - * Handle ManiaControl OnInit callback - * - * @param array $callback - */ - public function handleOnInitCallback($callback) { - if ($this->settings->widgets_enabled) { - // Send widgets to all players - - if (Tools::toBool($this->config->widgets->addfavorite->enabled)) { - // Send favorite widget - if (!$this->mc->client->query('SendDisplayManialinkPage', $this->manialinks[self::ML_ADDFAVORITE]->asXml(), 0, - false)) { - trigger_error("Couldn't send favorite widget! " . $this->mc->getClientErrorText()); - } - } - } - } - - /** - * Load settings from config - */ - private function loadSettings() { - $this->settings = new \stdClass(); - - // Enabled - $this->settings->enabled = Tools::toBool($this->config->enabled); - - // Timeout - $timeout = $this->mc->server->config->xpath('timeout'); - if ($timeout) { - $this->settings->timeout = (int) $timeout[0]; - } - else { - $this->settings->timeout = 30; - } - - // Game mode - $mode = $this->config->xpath('mode'); - if ($mode) { - $mode = (int) $mode[0]; - if ($mode < 1 || $mode > 6) { - $this->settings->gamemode = 2; - } - else { - $this->settings->gamemode = $mode; - } - } - - // Server status - $hide_game_server = $this->config->xpath('hide_game_server'); - if ($hide_game_server) { - $this->settings->hide_game_server = Tools::toBool($hide_game_server[0]); - } - else { - $this->settings->hide_game_server = true; - } - - // Passwords - $lobbyPassword = $this->config->xpath('lobbies/password'); - if ($lobbyPassword) { - $this->settings->lobbyPassword = (string) $lobbyPassword[0]; - } - else { - $this->settings->lobbyPassword = ''; - } - $gamePassword = $this->config->xpath('gameserver/password'); - if ($gamePassword) { - $this->settings->gamePassword = (string) $gamePassword[0]; - } - else { - $this->settings->gamePassword = ''; - } - - // Widgets - $this->settings->widgets_enabled = Tools::toBool($this->config->widgets->enabled); - } - - /** - * Loop events on clients - */ - public function loop() { - if (!$this->settings->enabled) return; - - // Check callbacks all clients - $clients = array_merge($this->gameServer, $this->lobbies); - $currentServer = $this->gameServer[$this->currentClientIndex]; - foreach ($clients as $index => $client) { - $client->resetError(); - $client->readCB(); - $callbacks = $client->getCBResponses(); - if (!is_array($callbacks) || $client->isError()) { - trigger_error("Error reading server callbacks! " . $this->mc->getClientErrorText($client)); - } - else { - if ($client == $currentServer) { - // Currently active game server - foreach ($callbacks as $index => $callback) { - $callbackName = $callback[0]; - switch ($callbackName) { - case Callbacks::CB_MP_ENDMAP: - { - $this->switchToNextServer(false); - break; - } - } - } - - if ($this->lastStatusCheck + 2 > time()) continue; - $this->lastStatusCheck = time(); - - if (!$client->query('CheckEndMatchCondition')) { - trigger_error("Couldn't get game server status. " . $this->mc->getClientErrorText($client)); - } - else { - $response = $client->getResponse(); - switch ($response) { - case 'Finished': - { - if ($this->finishedBegin < 0) { - $this->finishedBegin = time(); - } - else if ($this->finishedBegin + 13 <= time()) { - $this->switchToNextServer(true); - } - break; - } - default: - { - $this->finishedBegin = -1; - break; - } - } - } - } - else { - // Lobby or inactive game server -> Redirect players - foreach ($callbacks as $callback) { - switch ($callback[0]) { - case Callbacks::CB_MP_PLAYERCONNECT: - { - $this->playerJoinedLobby($client, $callback); - break; - } - } - } - } - } - } - - // Check for switch server request - if ($this->switchServerRequested > 0 && $this->switchServerRequested <= time()) { - $this->switchServerRequested = -1; - - // Switch server - $this->switchToNextServer(true); - } - } - - /** - * Handle 5 seconds callback - */ - public function handle5Seconds($callback = null) { - // Update lobby infos - $players = $this->mc->server->getPlayers(); - if (is_array($players)) { - $playerCount = count($players); - $playerLevel = 0.; - if ($playerCount > 0) { - foreach ($players as $player) { - $playerLevel += $player['LadderRanking']; - } - $playerLevel /= $playerCount; - } - foreach ($this->lobbies as $lobby) { - if (!$lobby->query('SetLobbyInfo', true, $playerCount, 255, $playerLevel)) { - trigger_error("Couldn't update lobby info. " . $this->mc->getClientErrorText($lobby)); - } - } - } - - // Check for not-redirected players - $clients = array_merge($this->gameServer, $this->lobbies); - $joinLink = $this->getJoinLink(); - foreach ($clients as $client) { - if ($client == $this->gameServer[$this->currentClientIndex]) continue; - $players = $this->mc->server->getPlayers($client); - if (!is_array($players)) continue; - foreach ($players as $player) { - $login = $player['Login']; - if (!$client->query('SendOpenLinkToLogin', $login, $joinLink, 1)) { - trigger_error( - "Couldn't redirect player '" . $login . "' to active game server. " . - $this->mc->getClientErrorText($client)); - } - } - } - } - - /** - * Handle player manialink page answer callback - */ - public function handleManialinkPageAnswer($callback) { - $login = $callback[1][1]; - $action = $callback[1][2]; - switch ($action) { - case self::ML_ADDFAVORITE: - { - // Open manialink to add server logins to favorite - $serverLogins = array(); - $add_all = Tools::toBool($this->config->widgets->addfavorite->add_all); - if ($add_all) { - // Add all server - foreach ($this->gameServer as $serverClient) { - array_push($serverLogins, $this->mc->server->getLogin($serverClient)); - } - foreach ($this->lobbies as $serverClient) { - array_push($serverLogins, $this->mc->server->getLogin($serverClient)); - } - } - else { - // Add only current server - array_push($serverLogins, $this->mc->server->getLogin()); - } - - // Build manialink url - $manialink = 'mc?favorite'; - foreach ($serverLogins as $serverLogin) { - $manialink .= '&' . $serverLogin; - } - - // Send url to player - if (!$this->mc->client->query('SendOpenLinkToLogin', $login, $manialink, 1)) { - trigger_error( - "Couldn't open manialink to add server to favorite for '" . $login . "'! " . - $this->mc->getClientErrorText()); - } - break; - } - } - } - - /** - * Switch to the next server - * - * @param bool $simulateMapEnd - * Simulate end of the map by sending callbacks - */ - private function switchToNextServer($simulateMapEnd) { - $this->finishedBegin = -1; - $oldClient = $this->gameServer[$this->currentClientIndex]; - - $random_order = Tools::toBool($this->config->random_order); - if ($random_order) { - // Random next server - $this->currentClientIndex = rand(0, count($this->gameServer) - 1); - } - else { - // Next server in list - $this->currentClientIndex++; - } - if ($this->currentClientIndex >= count($this->gameServer)) $this->currentClientIndex = 0; - - $newClient = $this->gameServer[$this->currentClientIndex]; - if ($newClient == $oldClient) return; - - // Restart map on next game server - if (!$newClient->query('RestartMap')) { - trigger_error("Couldn't restart map on next game server. " . $this->mc->getClientErrorText($newClient)); - } - - if ($simulateMapEnd) { - // Simulate EndMap on old client - $this->mc->callbacks->triggerCallback(Callbacks::CB_IC_ENDMAP, array(Callbacks::CB_IC_ENDMAP)); - } - - // Transfer players to next server - $joinLink = $this->getJoinLink($newClient); - if (!$oldClient->query('GetPlayerList', 255, 0)) { - trigger_error("Couldn't get player list. " . $this->mc->getClientErrorText($oldClient)); - } - else { - $playerList = $oldClient->getResponse(); - foreach ($playerList as $player) { - $login = $player['Login']; - if (!$oldClient->query('SendOpenLinkToLogin', $login, $joinLink, 1)) { - trigger_error("Couldn't redirect player to next game server. " . $this->mc->getClientErrorText($oldClient)); - } - } - - $this->mc->client = $newClient; - } - - // Trigger client updated callback - $this->mc->callbacks->triggerCallback(Callbacks::CB_IC_CLIENTUPDATED, "Plugin_United.SwitchedServer"); - - if ($simulateMapEnd) { - // Simulate BeginMap on new client - $map = $this->mc->server->getMap(); - if ($map) { - $this->mc->callbacks->triggerCallback(Callbacks::CB_IC_BEGINMAP, array(Callbacks::CB_IC_BEGINMAP, array($map))); - } - } - } - - /** - * Handle nextserver command - * - * @param mixed $command - */ - public function handleNextServerCommand($command) { - if (!$command) return; - $login = $command[1][1]; - - if (!$this->mc->authentication->checkRight($login, 'operator')) { - // Not allowed - $this->mc->authentication->sendNotAllowed($login); - return; - } - - // Request skip to next server - $this->switchServerRequested = time() + 3; - - // Send chat message - $this->mc->chat->sendInformation("Switching to next server in 3 seconds..."); - } - - /** - * Handle PlayerConnect callback - */ - public function playerJoinedLobby($client, $callback) { - if (!$client) return; - - $data = $callback[1]; - $login = $data[0]; - - // Redirect player to current game server - $gameserver = $this->gameServer[$this->currentClientIndex]; - $joinLink = $this->getJoinLink($gameserver, !$data[1]); - if (!$client->query('SendOpenLinkToLogin', $login, $joinLink, 1)) { - trigger_error( - "United Plugin: Couldn't redirect player to current game server. " . $this->mc->getClientErrorText($client)); - } - } - - /** - * Connect to the game server defined in the config - */ - private function loadClients() { - $gameserver = $this->config->xpath('gameserver/server'); - $lobbies = $this->config->xpath('lobbies/server'); - - $clientsConfig = array_merge($gameserver, $lobbies); - foreach ($clientsConfig as $index => $serv) { - $isGameServer = (in_array($serv, $gameserver)); - - $host = $serv->xpath('host'); - $port = $serv->xpath('port'); - if (!$host || !$port) { - trigger_error("Invalid configuration!", E_USER_ERROR); - } - $host = (string) $host[0]; - $port = (string) $port[0]; - - error_log("Connecting to united " . ($isGameServer ? 'game' : 'lobby') . " server at " . $host . ":" . $port . "..."); - $client = new \IXR_ClientMulticall_Gbx(); - - // Connect - if (!$client->InitWithIp($host, $port, $this->settings->timeout)) { - trigger_error( - "Couldn't connect to united " . ($isGameServer ? 'game' : lobby) . " server! " . $client->getErrorMessage() . - "(" . $client->getErrorCode() . ")", E_USER_ERROR); - } - - $login = $serv->xpath('login'); - $pass = $serv->xpath('pass'); - if (!$login || !$pass) { - trigger_error("Invalid configuration!", E_USER_ERROR); - } - $login = (string) $login[0]; - $pass = (string) $pass[0]; - - // Authenticate - if (!$client->query('Authenticate', $login, $pass)) { - trigger_error( - "Couldn't authenticate on united " . ($isGameServer ? 'game' : 'lobby') . " server with user '" . $login . "'! " . - $client->getErrorMessage() . "(" . $client->getErrorCode() . ")", E_USER_ERROR); - } - - // Enable callback system - if (!$client->query('EnableCallbacks', true)) { - trigger_error("Couldn't enable callbacks! " . $client->getErrorMessage() . "(" . $client->getErrorCode() . ")", - E_USER_ERROR); - } - - // Wait for server to be ready - if (!$this->mc->server->waitForStatus($client, 4)) { - trigger_error("Server couldn't get ready!", E_USER_ERROR); - } - - // Set api version - if (!$client->query('SetApiVersion', ManiaControl::API_VERSION)) { - trigger_error( - "Couldn't set API version '" . ManiaControl::API_VERSION . "'! This might cause problems. " . - $this->mc->getClientErrorText($client)); - } - - // Set server settings - $password = ($isGameServer ? $this->settings->gamePassword : $this->settings->lobbyPassword); - $hideServer = ($isGameServer && $this->settings->hide_game_server ? 1 : 0); - // Passwords - if (!$client->query('SetServerPassword', $password)) { - trigger_error("Couldn't set server join password. " . $this->mc->getClientErrorText($client)); - } - if (!$client->query('SetServerPasswordForSpectator', $password)) { - trigger_error("Couldn't set server spec password. " . $this->mc->getClientErrorText($client)); - } - // Show/Hide server - if (!$client->query('SetHideServer', $hideServer)) { - trigger_error( - "Couldn't set server '" . ($hideServer == 0 ? 'shown' : 'hidden') . "'. " . - $this->mc->getClientErrorText($client)); - } - - // Enable service announces - if (!$client->query("DisableServiceAnnounces", false)) { - trigger_error("Couldn't enable service announces. " . $this->mc->getClientErrorText($client)); - } - - // Set game mode - if (!$client->query('SetGameMode', $this->settings->gamemode)) { - trigger_error( - "Couldn't set game mode (" . $this->settings->gamemode . "). " . $this->mc->getClientErrorText($client)); - } - else if (!$client->query('RestartMap')) { - trigger_error("Couldn't restart map to change game mode. " . $this->mc->getClientErrorText($client)); - } - - // Save client - $client->index = $index; - if ($isGameServer) { - array_push($this->gameServer, $client); - if (count($this->gameServer) === 1) { - $this->mc->client = $client; - } - } - else { - array_push($this->lobbies, $client); - } - } - - error_log("United Plugin: Connected to all game and lobby server!"); - } - - /** - * Handle PlayerConnect callback - * - * @param array $callback - */ - public function handlePlayerConnect($callback) { - if ($this->settings->widgets_enabled) { - // Send manialinks to the client - $login = $callback[1][0]; - - if (Tools::toBool($this->config->widgets->addfavorite->enabled)) { - // Send favorite widget - if (!$this->mc->client->query('SendDisplayManialinkPageToLogin', $login, - $this->manialinks[self::ML_ADDFAVORITE]->asXml(), 0, false)) { - trigger_error("Couldn't send favorite widget to player '" . $login . "'! " . $this->mc->getClientErrorText()); - } - } - } - } - - /** - * Build join link for the given client - */ - private function getJoinLink(&$client = null, $play = true) { - if (!$client) { - $client = $this->gameServer[$this->currentClientIndex]; - } - if (!$client->query('GetSystemInfo')) { - trigger_error("Couldn't fetch server system info. " . $this->mc->getClientErrorText($client)); - return null; - } - else { - $systemInfo = $client->getResponse(); - $password = ''; - if (!$client->query('GetServerPassword')) { - trigger_error("Couldn't get server password. " . $this->mc->getClientErrorText($client)); - } - else { - $password = $client->getResponse(); - } - return '#q' . ($play ? 'join' : 'spectate') . '=' . $systemInfo['ServerLogin'] . - (strlen($password) > 0 ? ':' . $password : '') . '@' . $systemInfo['TitleId']; - } - } - - /** - * Build manialink for addfavorite button - */ - private function buildFavoriteManialink() { - // Load configs - $config = $this->config->widgets->addfavorite; - if (!Tools::toBool($config->enabled)) return; - - $pos_x = (float) $config->pos_x; - $pos_y = (float) $config->pos_y; - $height = (float) $config->height; - $width = (float) $config->width; - $add_all = Tools::toBool($config->add_all); - - // Build manialink - $xml = Tools::newManialinkXml(self::ML_ADDFAVORITE); - - $frameXml = $xml->addChild('frame'); - $frameXml->addAttribute('posn', $pos_x . ' ' . $pos_y); - - // Background - $quadXml = $frameXml->addChild('quad'); - Tools::addAlignment($quadXml); - $quadXml->addAttribute('posn', '0 0 0'); - $quadXml->addAttribute('sizen', $width . ' ' . $height); - $quadXml->addAttribute('style', 'Bgs1InRace'); - $quadXml->addAttribute('substyle', 'BgTitleShadow'); - $quadXml->addAttribute('action', self::ML_ADDFAVORITE); - - // Heart - $quadXml = $frameXml->addChild('quad'); - Tools::addAlignment($quadXml); - $quadXml->addAttribute('id', 'Quad_AddFavorite'); - $quadXml->addAttribute('posn', '0 0 1'); - $quadXml->addAttribute('sizen', ($width - 1.) . ' ' . ($height - 0.8)); - $quadXml->addAttribute('style', 'Icons64x64_1'); - $quadXml->addAttribute('substyle', 'StateFavourite'); - $quadXml->addAttribute('scriptevents', '1'); - - // Tooltip - $tooltipFrameXml = $frameXml->addChild('frame'); - $tooltipFrameXml->addAttribute('id', 'Frame_FavoriteTooltip'); - $tooltipFrameXml->addAttribute('posn', '0 ' . ($pos_y >= 0 ? '-' : '') . '13'); - $tooltipFrameXml->addAttribute('hidden', '1'); - - $quadXml = $tooltipFrameXml->addChild('quad'); - Tools::addAlignment($quadXml); - $quadXml->addAttribute('posn', '0 0 2'); - $quadXml->addAttribute('sizen', '28 16'); - $quadXml->addAttribute('style', 'Bgs1InRace'); - $quadXml->addAttribute('substyle', 'BgTitleShadow'); - - $labelXml = $tooltipFrameXml->addChild('label'); - Tools::addAlignment($labelXml); - Tools::addTranslate($labelXml); - $labelXml->addAttribute('posn', '0 0 3'); - $labelXml->addAttribute('sizen', '26 0'); - $labelXml->addAttribute('style', 'TextTitle1'); - $labelXml->addAttribute('textsize', '2'); - $labelXml->addAttribute('autonewline', '1'); - $countText = ''; - if ($add_all) { - $count = count($this->gameServer) + count($this->lobbies); - $countText = 'all ' . $count . ' '; - } - $labelXml->addAttribute('text', 'Add ' . $countText . 'server to Favorite!'); - - // Script for tooltip - $script = ' -declare Frame_FavoriteTooltip <=> (Page.GetFirstChild("Frame_FavoriteTooltip") as CMlFrame); -while (True) { - yield; - foreach (Event in PendingEvents) { - switch (Event.Type) { - case CMlEvent::Type::MouseOver: { - switch (Event.ControlId) { - case "Quad_AddFavorite": { - Frame_FavoriteTooltip.Visible = True; - } - } - } - case CMlEvent::Type::MouseOut: { - switch (Event.ControlId) { - case "Quad_AddFavorite": { - Frame_FavoriteTooltip.Visible = False; - } - } - } - } - } -}'; - $xml->addChild('script', $script); - - $this->manialinks[self::ML_ADDFAVORITE] = $xml; - } -} - -?> - \ No newline at end of file diff --git a/application/plugins/testPlugin.php b/application/plugins/testPlugin.php new file mode 100644 index 00000000..7d52bcc4 --- /dev/null +++ b/application/plugins/testPlugin.php @@ -0,0 +1,28 @@ +maniaControl = $maniaControl; + } + + public function getAuthor() { + return 'steeffeen'; + } + + public function getName() { + return 'Test Plugin'; + } + + public function getVersion() { + return '1.0'; + } + + public function getDescription() { + return 'Dummy plugin for testing plugin handling'; + } +} + +?> diff --git a/application/ManiaControl.php b/application/startManiaControl.php similarity index 68% rename from application/ManiaControl.php rename to application/startManiaControl.php index b586154d..5f90e2c9 100644 --- a/application/ManiaControl.php +++ b/application/startManiaControl.php @@ -1,11 +1,9 @@ run(true); +$maniaControl->run(); ?> diff --git a/rsa b/rsa deleted file mode 100644 index e69de29b..00000000