2013-11-10 17:29:21 +01:00
< ? php
namespace ManiaControl ;
2013-12-31 12:42:07 +01:00
use ManiaControl\Admin\ActionsMenu ;
2013-11-13 01:43:12 +01:00
use ManiaControl\Admin\AuthenticationManager ;
2014-02-25 18:34:35 +01:00
use ManiaControl\Bills\BillManager ;
2014-06-20 16:19:30 +02:00
use ManiaControl\Callbacks\CallbackListener ;
2013-11-12 15:48:25 +01:00
use ManiaControl\Callbacks\CallbackManager ;
2014-05-24 16:39:12 +02:00
use ManiaControl\Callbacks\Callbacks ;
2014-02-22 11:14:35 +01:00
use ManiaControl\Callbacks\TimerListener ;
2014-01-30 22:35:32 +01:00
use ManiaControl\Callbacks\TimerManager ;
2013-11-24 23:55:54 +01:00
use ManiaControl\Commands\CommandListener ;
2013-11-12 15:48:25 +01:00
use ManiaControl\Commands\CommandManager ;
2013-11-28 03:47:08 +01:00
use ManiaControl\Configurators\Configurator ;
2014-05-02 17:40:47 +02:00
use ManiaControl\Database\Database ;
2014-02-07 12:30:53 +01:00
use ManiaControl\Files\AsynchronousFileReader ;
2014-02-07 00:27:10 +01:00
use ManiaControl\Files\FileUtil ;
2013-11-28 03:47:08 +01:00
use ManiaControl\Manialinks\ManialinkManager ;
2013-11-12 15:48:25 +01:00
use ManiaControl\Maps\MapManager ;
2013-11-24 23:55:54 +01:00
use ManiaControl\Players\Player ;
2013-11-13 01:43:12 +01:00
use ManiaControl\Players\PlayerManager ;
2013-11-12 15:48:25 +01:00
use ManiaControl\Plugins\PluginManager ;
2013-11-19 20:29:37 +01:00
use ManiaControl\Server\Server ;
2014-01-27 17:29:48 +01:00
use ManiaControl\Settings\SettingManager ;
2014-01-01 17:59:29 +01:00
use ManiaControl\Statistics\StatisticManager ;
2014-02-10 22:54:49 +01:00
use ManiaControl\Update\UpdateManager ;
2014-05-13 14:32:30 +02:00
use ManiaControl\Utils\CommandLineHelper ;
use ManiaControl\Utils\Formatter ;
2014-06-15 00:51:43 +02:00
use ManiaControl\Utils\SystemUtil ;
2014-01-16 17:19:01 +01:00
use Maniaplanet\DedicatedServer\Connection ;
2014-06-13 17:11:45 +02:00
use Maniaplanet\DedicatedServer\Xmlrpc\AuthenticationException ;
2014-02-13 14:21:25 +01:00
use Maniaplanet\DedicatedServer\Xmlrpc\Exception ;
2014-04-27 15:21:57 +02:00
use Maniaplanet\DedicatedServer\Xmlrpc\TransportException ;
2013-12-31 12:42:07 +01:00
2014-02-18 15:54:36 +01:00
require_once __DIR__ . '/Libs/Maniaplanet/DedicatedServer/Connection.php' ;
require_once __DIR__ . '/Libs/FML/autoload.php' ;
2014-02-18 18:13:59 +01:00
require_once __DIR__ . '/Libs/Symfony/autoload.php' ;
require_once __DIR__ . '/Libs/curl-easy/autoload.php' ;
2013-11-10 17:29:21 +01:00
/**
* ManiaControl Server Controller for ManiaPlanet Server
2014-05-02 17:40:47 +02:00
*
* @ author ManiaControl Team < mail @ maniacontrol . com >
* @ copyright 2014 ManiaControl Team
* @ license http :// www . gnu . org / licenses / GNU General Public License , Version 3
2013-11-10 17:29:21 +01:00
*/
2014-06-20 16:19:30 +02:00
class ManiaControl implements CallbackListener , CommandListener , TimerListener {
2014-04-12 12:14:37 +02:00
/*
2013-11-10 17:29:21 +01:00
* Constants
*/
2014-06-15 18:57:41 +02:00
const VERSION = '0.152' ;
2014-05-02 17:40:47 +02:00
const API_VERSION = '2013-04-16' ;
const MIN_DEDIVERSION = '2014-04-02_18_00' ;
2014-05-09 16:33:33 +02:00
const SCRIPT_TIMEOUT = 10 ;
2014-05-02 17:40:47 +02:00
const URL_WEBSERVICE = 'http://ws.maniacontrol.com/' ;
2014-01-31 16:55:01 +01:00
const SETTING_PERMISSION_SHUTDOWN = 'Shutdown ManiaControl' ;
2014-05-02 17:40:47 +02:00
const SETTING_PERMISSION_RESTART = 'Restart ManiaControl' ;
2014-04-12 12:14:37 +02:00
/*
* Public Properties
2013-11-10 17:29:21 +01:00
*/
2013-12-31 12:42:07 +01:00
public $actionsMenu = null ;
2013-11-13 01:43:12 +01:00
public $authenticationManager = null ;
2013-11-12 15:48:25 +01:00
public $callbackManager = null ;
2013-11-10 17:29:21 +01:00
public $chat = null ;
2014-06-13 19:53:36 +02:00
/** @var \SimpleXMLElement $config */
2014-05-01 20:21:40 +02:00
public $config = null ;
2013-11-28 03:47:08 +01:00
public $configurator = null ;
2014-05-10 10:12:48 +02:00
/** @var Connection $client */
2013-11-10 17:29:21 +01:00
public $client = null ;
2013-11-12 15:48:25 +01:00
public $commandManager = null ;
2013-11-10 17:29:21 +01:00
public $database = null ;
2013-11-28 02:04:06 +01:00
public $manialinkManager = null ;
2013-11-12 15:48:25 +01:00
public $mapManager = null ;
public $playerManager = null ;
public $pluginManager = null ;
2013-11-10 17:29:21 +01:00
public $server = null ;
public $settingManager = null ;
2013-12-31 17:31:05 +01:00
public $statisticManager = null ;
2014-05-02 15:35:52 +02:00
/** @var UpdateManager $updateManager */
2013-12-17 17:38:44 +01:00
public $updateManager = null ;
2014-01-27 20:28:37 +01:00
public $errorHandler = null ;
2014-01-30 22:35:32 +01:00
public $timerManager = null ;
2014-02-07 12:30:53 +01:00
public $fileReader = null ;
2014-02-25 18:34:35 +01:00
public $billManager = null ;
2014-05-02 17:40:47 +02:00
2014-04-12 12:14:37 +02:00
/*
* Private Properties
2013-11-10 17:29:21 +01:00
*/
2014-06-20 16:34:19 +02:00
private $requestQuitMessage = null ;
2013-11-10 17:29:21 +01:00
/**
* Construct ManiaControl
*/
public function __construct () {
2014-06-12 15:50:13 +02:00
$this -> log ( 'Loading ManiaControl v' . self :: VERSION . ' ...' );
2014-05-02 17:40:47 +02:00
2014-06-26 11:07:53 +02:00
$this -> errorHandler = new ErrorHandler ( $this );
2014-05-01 20:21:40 +02:00
$this -> loadConfig ();
2014-05-02 17:40:47 +02:00
2013-12-17 17:38:44 +01:00
// Load ManiaControl Modules
2014-05-02 17:40:47 +02:00
$this -> callbackManager = new CallbackManager ( $this );
$this -> timerManager = new TimerManager ( $this );
$this -> database = new Database ( $this );
$this -> fileReader = new AsynchronousFileReader ( $this );
$this -> billManager = new BillManager ( $this );
$this -> settingManager = new SettingManager ( $this );
$this -> statisticManager = new StatisticManager ( $this );
$this -> manialinkManager = new ManialinkManager ( $this );
$this -> actionsMenu = new ActionsMenu ( $this );
$this -> chat = new Chat ( $this );
$this -> commandManager = new CommandManager ( $this );
$this -> server = new Server ( $this );
2013-11-26 13:49:36 +01:00
$this -> authenticationManager = new AuthenticationManager ( $this );
2014-05-02 17:40:47 +02:00
$this -> playerManager = new PlayerManager ( $this );
$this -> mapManager = new MapManager ( $this );
$this -> configurator = new Configurator ( $this );
$this -> pluginManager = new PluginManager ( $this );
$this -> updateManager = new UpdateManager ( $this );
2014-05-29 22:46:38 +02:00
$this -> errorHandler -> init ();
2014-03-20 16:19:50 +01:00
// Define Permission Levels
2014-01-31 16:55:01 +01:00
$this -> authenticationManager -> definePermissionLevel ( self :: SETTING_PERMISSION_SHUTDOWN , AuthenticationManager :: AUTH_LEVEL_SUPERADMIN );
$this -> authenticationManager -> definePermissionLevel ( self :: SETTING_PERMISSION_RESTART , AuthenticationManager :: AUTH_LEVEL_SUPERADMIN );
2014-05-02 17:40:47 +02:00
2013-12-17 17:38:44 +01:00
// Register for commands
2014-06-13 16:59:25 +02:00
$this -> commandManager -> registerCommandListener ( 'version' , $this , 'commandVersion' , false , 'Shows ManiaControl version.' );
$this -> commandManager -> registerCommandListener ( 'restart' , $this , 'commandRestart' , true , 'Restarts ManiaControl.' );
$this -> commandManager -> registerCommandListener ( 'shutdown' , $this , 'commandShutdown' , true , 'Shuts ManiaControl down.' );
2014-05-02 17:40:47 +02:00
2014-05-01 20:21:40 +02:00
// Check connection every 30 seconds
2014-04-20 15:13:31 +02:00
$this -> timerManager -> registerTimerListening ( $this , 'checkConnection' , 1000 * 30 );
2014-04-19 00:32:34 +02:00
}
2014-05-02 17:40:47 +02:00
/**
* Print a message to console and log
*
* @ param string $message
* @ param bool $stripCodes
*/
public function log ( $message , $stripCodes = false ) {
if ( $stripCodes ) {
$message = Formatter :: stripCodes ( $message );
}
2014-06-17 22:59:49 +02:00
Logger :: log ( $message );
2014-05-02 17:40:47 +02:00
}
2014-05-01 20:21:40 +02:00
/**
* Load the Config XML - File
*/
private function loadConfig () {
2014-05-02 17:40:47 +02:00
$configId = CommandLineHelper :: getParameter ( '-config' );
2014-05-01 20:21:40 +02:00
$configFileName = ( $configId ? $configId : 'server.xml' );
2014-05-02 17:40:47 +02:00
$this -> config = FileUtil :: loadConfig ( $configFileName );
2014-05-01 20:21:40 +02:00
if ( ! $this -> config ) {
2014-05-15 13:04:05 +02:00
$this -> quit ( " Error loading Configuration XML-File! (' { $configFileName } ') " , true );
2014-05-01 20:21:40 +02:00
}
2014-06-13 19:53:36 +02:00
if ( $this -> config -> count () < 3 ) {
2014-05-27 08:57:26 +02:00
$this -> quit ( " Your Configuration File (' { $configFileName } ') doesn't seem to be maintained properly. Please check it again! " , true );
2014-05-01 20:21:40 +02:00
}
}
2014-05-15 13:04:05 +02:00
/**
* Quit ManiaControl and log the given message
*
* @ param string $message
* @ param bool $errorPrefix
*/
public function quit ( $message = null , $errorPrefix = false ) {
if ( $message ) {
if ( $errorPrefix ) {
$message = '[ERROR] ' . $message ;
}
$this -> log ( $message );
}
2014-05-29 22:54:43 +02:00
$this -> disconnect ();
2014-05-15 13:04:05 +02:00
exit ();
}
2014-05-29 22:54:43 +02:00
/**
* Close the Client Connection
*/
public function disconnect () {
Connection :: delete ( $this -> client );
$this -> client = null ;
}
2014-04-19 00:32:34 +02:00
/**
2014-05-13 16:40:05 +02:00
* Check Connection
2014-04-19 00:32:34 +02:00
*/
2014-05-13 16:40:05 +02:00
public function checkConnection () {
2014-04-19 22:59:11 +02:00
if ( $this -> client -> getIdleTime () > 180 ) {
2014-04-19 00:32:34 +02:00
$this -> client -> getServerName ();
}
2013-11-10 17:29:21 +01:00
}
2013-12-09 15:53:10 +01:00
/**
2014-05-02 17:40:47 +02:00
* Handle Version Command
*
* @ param array $chatCallback
* @ param Player $player
*/
2014-06-13 16:59:25 +02:00
public function commandVersion ( array $chatCallback , Player $player ) {
2014-05-02 17:40:47 +02:00
$message = 'This server is using ManiaControl v' . ManiaControl :: VERSION . '!' ;
$this -> chat -> sendInformation ( $message , $player -> login );
}
/**
* Handle Restart AdminCommand
*
* @ param array $chatCallback
* @ param Player $player
*/
2014-06-13 16:59:25 +02:00
public function commandRestart ( array $chatCallback , Player $player ) {
2014-05-02 17:40:47 +02:00
if ( ! $this -> authenticationManager -> checkPermission ( $player , self :: SETTING_PERMISSION_RESTART )) {
$this -> authenticationManager -> sendNotAllowed ( $player );
return ;
}
$this -> restart ( " ManiaControl Restart requested by ' { $player -> login } '! " );
}
/**
* Restart ManiaControl
*
2013-12-31 12:42:07 +01:00
* @ param string $message
2013-12-09 15:53:10 +01:00
*/
2014-05-02 17:40:47 +02:00
public function restart ( $message = null ) {
// Shutdown callback
2014-05-24 16:39:12 +02:00
$this -> callbackManager -> triggerCallback ( Callbacks :: ONSHUTDOWN );
2014-05-02 17:40:47 +02:00
// Announce restart
$this -> chat -> sendInformation ( 'Restarting ManiaControl...' );
if ( $message ) {
$this -> log ( $message );
2014-01-05 14:13:18 +01:00
}
2014-05-02 17:40:47 +02:00
// Hide widgets
2014-06-13 16:48:14 +02:00
if ( $this -> client ) {
$this -> client -> sendHideManialinkPage ();
}
2014-05-02 17:40:47 +02:00
$this -> log ( 'Restarting ManiaControl!' );
// Execute start script in background
2014-06-15 00:51:43 +02:00
if ( SystemUtil :: isUnix ()) {
2014-06-15 01:02:59 +02:00
// Unix
if ( ! SystemUtil :: checkFunctionAvailability ( 'exec' )) {
$this -> log ( " Can't restart ManiaControl because the function 'exec' is disabled! " );
return ;
}
2014-06-29 17:27:01 +02:00
$fileName = ManiaControlDir . 'ManiaControl.sh' ;
if ( ! is_readable ( $fileName )) {
$this -> log ( " Can't restart ManiaControl because the file 'ManiaControl.sh' doesn't exist or isn't readable! " );
return ;
}
$command = 'sh ' . escapeshellarg ( $fileName ) . ' > /dev/null &' ;
2014-05-02 17:40:47 +02:00
exec ( $command );
} else {
2014-06-15 01:02:59 +02:00
// Windows
if ( ! SystemUtil :: checkFunctionAvailability ( 'system' )) {
$this -> log ( " Can't restart ManiaControl because the function 'system' is disabled! " );
return ;
}
2014-05-03 21:37:28 +02:00
$command = escapeshellarg ( ManiaControlDir . " ManiaControl.bat " );
2014-06-12 15:46:24 +02:00
system ( $command ); // TODO: windows gets stuck here as long controller is running
2014-05-02 17:40:47 +02:00
}
2014-06-12 14:02:16 +02:00
// Quit the old instance
$this -> quit ( 'Quitting ManiaControl to restart.' );
2013-12-09 15:53:10 +01:00
}
2014-01-01 19:25:51 +01:00
/**
2014-06-13 16:59:25 +02:00
* Handle Shutdown Command
2014-05-02 17:40:47 +02:00
*
* @ param array $chat
2014-01-01 19:25:51 +01:00
* @ param Player $player
*/
2014-06-13 16:59:25 +02:00
public function commandShutdown ( array $chat , Player $player ) {
2014-01-31 16:55:01 +01:00
if ( ! $this -> authenticationManager -> checkPermission ( $player , self :: SETTING_PERMISSION_SHUTDOWN )) {
2014-01-01 19:25:51 +01:00
$this -> authenticationManager -> sendNotAllowed ( $player );
return ;
}
2014-06-20 16:34:19 +02:00
$this -> requestQuit ( " ManiaControl Shutdown requested by ' { $player -> login } '! " );
2013-11-24 23:55:54 +01:00
}
2014-06-23 16:14:47 +02:00
/**
* Request ManiaControl to quit
*
* @ param mixed $message
*/
public function requestQuit ( $message = true ) {
$this -> requestQuitMessage = $message ;
}
2013-11-10 17:29:21 +01:00
/**
* Run ManiaControl
*/
public function run () {
2013-12-31 18:24:40 +01:00
$this -> log ( 'Starting ManiaControl v' . self :: VERSION . '!' );
2014-05-02 17:40:47 +02:00
2014-02-15 21:48:23 +01:00
// Connect to server
$this -> connect ();
2014-05-02 17:40:47 +02:00
2014-04-14 12:18:44 +02:00
// Check if the version of the server is high enough
$version = $this -> client -> getVersion ();
2014-05-01 20:21:40 +02:00
if ( $version -> build < self :: MIN_DEDIVERSION ) {
2014-05-29 22:54:43 +02:00
$this -> quit ( " The Server has Version ' { $version -> build } ', while at least ' " . self :: MIN_DEDIVERSION . " ' is required! " , true );
2014-04-30 00:19:18 +02:00
}
2014-05-02 17:40:47 +02:00
2014-06-20 16:19:30 +02:00
// Listen for shutdown
$this -> callbackManager -> registerCallbackListener ( CallbackManager :: CB_MP_SERVERSTOP , $this , 'handleServerStopCallback' );
2013-12-09 15:43:08 +01:00
// OnInit callback
2014-05-24 16:39:12 +02:00
$this -> callbackManager -> triggerCallback ( Callbacks :: ONINIT );
2014-05-02 17:40:47 +02:00
2014-01-18 10:26:32 +01:00
// Load plugins
$this -> pluginManager -> loadPlugins ();
2014-05-02 04:04:13 +02:00
$this -> updateManager -> pluginUpdateManager -> checkPluginsUpdate ();
2014-05-02 17:40:47 +02:00
2014-02-12 21:07:54 +01:00
// AfterInit callback
2014-05-24 16:39:12 +02:00
$this -> callbackManager -> triggerCallback ( Callbacks :: AFTERINIT );
2014-05-02 17:40:47 +02:00
2014-01-10 13:08:26 +01:00
// Loading finished
$this -> log ( 'Loading completed!' );
2014-02-13 20:41:55 +01:00
$this -> log ( 'Link: maniaplanet://#join=' . $this -> server -> login . '@' . $this -> server -> titleId );
2014-05-29 22:54:43 +02:00
$this -> chat -> sendInformation ( 'ManiaControl v' . self :: VERSION . ' successfully started!' );
2014-05-02 17:40:47 +02:00
2013-11-10 17:29:21 +01:00
// Main loop
2014-06-20 16:34:19 +02:00
while ( ! $this -> requestQuitMessage ) {
2014-05-09 13:46:04 +02:00
$this -> loop ();
}
2014-05-02 17:40:47 +02:00
2014-05-09 13:46:04 +02:00
// Shutdown
2014-06-20 16:34:19 +02:00
$this -> quit ( $this -> requestQuitMessage );
2014-05-09 13:46:04 +02:00
}
2014-05-02 17:40:47 +02:00
2013-11-10 17:29:21 +01:00
/**
* Connect to ManiaPlanet server
*/
private function connect () {
// Load remote client
2014-04-27 15:12:09 +02:00
$this -> server -> loadConfig ();
2014-05-02 17:40:47 +02:00
2014-05-29 22:54:43 +02:00
$this -> log ( " Connecting to Server at { $this -> server -> config -> host } : { $this -> server -> config -> port } ... " );
2014-05-02 17:40:47 +02:00
2014-01-17 16:32:53 +01:00
try {
2014-06-13 17:24:59 +02:00
$this -> client = Connection :: factory ( $this -> server -> config -> host , $this -> server -> config -> port , self :: SCRIPT_TIMEOUT , $this -> server -> config -> user , $this -> server -> config -> pass , self :: API_VERSION );
2014-06-23 16:14:47 +02:00
} catch ( TransportException $exception ) {
$message = " Couldn't connect to the server: ' { $exception -> getMessage () } ' " ;
$this -> quit ( $message , true );
} catch ( AuthenticationException $exception ) {
$message = " Couldn't authenticate on Server with User ' { $this -> server -> config -> user } ' & Pass ' { $this -> server -> config -> pass } '! " . $exception -> getMessage ();
2014-05-09 14:08:39 +02:00
$this -> quit ( $message , true );
2014-03-20 16:19:50 +01:00
}
2014-05-02 17:40:47 +02:00
2013-11-10 17:29:21 +01:00
// Enable callback system
2014-02-13 14:21:25 +01:00
$this -> client -> enableCallbacks ( true );
2014-05-02 17:40:47 +02:00
2013-11-10 17:29:21 +01:00
// Wait for server to be ready
2014-03-01 10:49:07 +01:00
try {
if ( ! $this -> server -> waitForStatus ( 4 )) {
2014-05-06 10:34:57 +02:00
$this -> quit ( " Server couldn't get ready! " );
2014-03-01 10:49:07 +01:00
}
2014-05-02 17:40:47 +02:00
} catch ( Exception $e ) {
2014-03-20 16:19:50 +01:00
// TODO remove
2014-05-06 02:17:11 +02:00
$this -> errorHandler -> handleException ( $e , false );
2014-05-09 14:08:39 +02:00
$this -> quit ( $e -> getMessage (), true );
2013-11-10 17:29:21 +01:00
}
2014-05-02 17:40:47 +02:00
2013-11-10 17:29:21 +01:00
// Connect finished
2014-06-14 19:08:07 +02:00
$this -> log ( 'Server Connection successfully established!' );
2014-05-02 17:40:47 +02:00
2013-12-31 14:50:45 +01:00
// Hide old widgets
2014-01-16 17:19:01 +01:00
$this -> client -> sendHideManialinkPage ();
2014-05-02 17:40:47 +02:00
2014-05-06 02:17:11 +02:00
// Enable script callbacks
$this -> server -> scriptManager -> enableScriptCallbacks ();
2013-11-10 17:29:21 +01:00
}
2014-05-09 14:08:39 +02:00
/**
* Perform the Main Loop
*/
private function loop () {
$loopStart = microtime ( true );
2014-05-09 16:33:33 +02:00
// Extend script timeout
2014-05-09 14:08:39 +02:00
set_time_limit ( self :: SCRIPT_TIMEOUT );
try {
$this -> callbackManager -> manageCallbacks ();
} catch ( TransportException $e ) {
$this -> log ( " Connection interrupted! " );
// TODO remove
$this -> errorHandler -> handleException ( $e , false );
$this -> quit ( $e -> getMessage (), true );
}
// Manage FileReader
$this -> fileReader -> appendData ();
// Yield for next tick
$loopEnd = microtime ( true );
$loopDuration = $loopEnd - $loopStart ;
$sleepTime = ( int )( 2500 - $loopDuration * 1000000 );
if ( $sleepTime > 0 ) {
usleep ( $sleepTime );
}
}
2014-06-20 16:19:30 +02:00
/**
* Handle Server Stop Callback
*/
2014-06-20 16:22:45 +02:00
public function handleServerStopCallback () {
2014-06-20 16:34:19 +02:00
$this -> requestQuit ( 'The Server has been shut down!' );
}
2013-11-10 17:29:21 +01:00
}