2013-12-17 17:38:44 +01:00
< ? php
2014-02-10 22:54:49 +01:00
namespace ManiaControl\Update ;
2013-12-17 17:38:44 +01:00
use ManiaControl\Admin\AuthenticationManager ;
use ManiaControl\Callbacks\CallbackListener ;
2014-01-31 00:04:40 +01:00
use ManiaControl\Callbacks\TimerListener ;
2013-12-17 17:38:44 +01:00
use ManiaControl\Commands\CommandListener ;
2014-05-02 17:50:30 +02:00
use ManiaControl\Files\BackupUtil ;
2014-02-10 16:52:16 +01:00
use ManiaControl\Files\FileUtil ;
2014-02-10 22:54:49 +01:00
use ManiaControl\ManiaControl ;
2013-12-17 17:38:44 +01:00
use ManiaControl\Players\Player ;
use ManiaControl\Players\PlayerManager ;
/**
2014-05-02 04:03:33 +02:00
* Manager checking for ManiaControl Core Updates
2014-05-02 17:50:30 +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-12-17 17:38:44 +01:00
*/
2014-01-31 00:04:40 +01:00
class UpdateManager implements CallbackListener , CommandListener , TimerListener {
2014-01-19 22:32:09 +01:00
/*
2013-12-17 17:38:44 +01:00
* Constants
*/
2014-05-02 17:50:30 +02:00
const SETTING_ENABLEUPDATECHECK = 'Enable Automatic Core Update Check' ;
const SETTING_UPDATECHECK_INTERVAL = 'Core Update Check Interval (Hours)' ;
const SETTING_UPDATECHECK_CHANNEL = 'Core Update Channel (release, beta, nightly)' ;
const SETTING_PERFORM_BACKUPS = 'Perform Backup before Updating' ;
const SETTING_AUTO_UPDATE = 'Perform update automatically' ;
const SETTING_PERMISSION_UPDATE = 'Update Core' ;
2014-01-31 16:55:01 +01:00
const SETTING_PERMISSION_UPDATECHECK = 'Check Core Update' ;
2014-05-02 17:50:30 +02:00
const CHANNEL_RELEASE = 'release' ;
const CHANNEL_BETA = 'beta' ;
const CHANNEL_NIGHTLY = 'nightly' ;
2014-05-02 04:03:33 +02:00
/*
* Public Properties
*/
public $pluginUpdateManager = null ;
2014-05-02 17:50:30 +02:00
2014-01-19 22:32:09 +01:00
/*
2013-12-17 17:38:44 +01:00
* Private Properties
*/
private $maniaControl = null ;
2014-04-29 23:53:55 +02:00
/**
* @ var UpdateData $coreUpdateData
*/
2013-12-17 17:38:44 +01:00
private $coreUpdateData = null ;
2014-05-02 04:03:33 +02:00
private $currentBuildDate = null ;
2013-12-17 17:38:44 +01:00
/**
2014-01-19 22:32:09 +01:00
* Create a new Update Manager
2014-05-02 17:50:30 +02:00
*
2013-12-31 17:17:40 +01:00
* @ param ManiaControl $maniaControl
2013-12-17 17:38:44 +01:00
*/
public function __construct ( ManiaControl $maniaControl ) {
$this -> maniaControl = $maniaControl ;
2014-05-02 17:50:30 +02:00
2013-12-17 17:38:44 +01:00
// Init settings
$this -> maniaControl -> settingManager -> initSetting ( $this , self :: SETTING_ENABLEUPDATECHECK , true );
2014-01-21 19:12:55 +01:00
$this -> maniaControl -> settingManager -> initSetting ( $this , self :: SETTING_AUTO_UPDATE , true );
2014-02-10 16:46:41 +01:00
$this -> maniaControl -> settingManager -> initSetting ( $this , self :: SETTING_UPDATECHECK_INTERVAL , 1 );
2014-04-29 23:22:33 +02:00
$this -> maniaControl -> settingManager -> initSetting ( $this , self :: SETTING_UPDATECHECK_CHANNEL , self :: CHANNEL_BETA );
2013-12-31 18:25:07 +01:00
$this -> maniaControl -> settingManager -> initSetting ( $this , self :: SETTING_PERFORM_BACKUPS , true );
2014-05-02 17:50:30 +02:00
2013-12-17 17:38:44 +01:00
// Register for callbacks
2014-02-10 16:46:41 +01:00
$updateInterval = $this -> maniaControl -> settingManager -> getSetting ( $this , self :: SETTING_UPDATECHECK_INTERVAL );
$this -> maniaControl -> timerManager -> registerTimerListening ( $this , 'hourlyUpdateCheck' , 1000 * 60 * 60 * $updateInterval );
2014-02-19 10:43:37 +01:00
$this -> maniaControl -> callbackManager -> registerCallbackListener ( PlayerManager :: CB_PLAYERCONNECT , $this , 'handlePlayerJoined' );
2014-05-02 04:03:33 +02:00
$this -> maniaControl -> callbackManager -> registerCallbackListener ( PlayerManager :: CB_PLAYERDISCONNECT , $this , 'handlePlayerDisconnect' );
2014-05-02 17:50:30 +02:00
2014-04-29 23:53:55 +02:00
// define Permissions
2014-01-31 16:55:01 +01:00
$this -> maniaControl -> authenticationManager -> definePermissionLevel ( self :: SETTING_PERMISSION_UPDATE , AuthenticationManager :: AUTH_LEVEL_ADMIN );
$this -> maniaControl -> authenticationManager -> definePermissionLevel ( self :: SETTING_PERMISSION_UPDATECHECK , AuthenticationManager :: AUTH_LEVEL_MODERATOR );
2014-05-02 17:50:30 +02:00
2013-12-17 17:38:44 +01:00
// Register for chat commands
2014-05-01 01:41:19 +02:00
$this -> maniaControl -> commandManager -> registerCommandListener ( 'checkupdate' , $this , 'handle_CheckUpdate' , true , 'Checks if there is a core update.' );
$this -> maniaControl -> commandManager -> registerCommandListener ( 'coreupdate' , $this , 'handle_CoreUpdate' , true , 'Performs the core update.' );
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
// Plugin update manager
$this -> pluginUpdateManager = new PluginUpdateManager ( $maniaControl );
}
2013-12-17 17:38:44 +01:00
/**
2014-02-10 16:46:41 +01:00
* Perform Hourly Update Check
2014-05-02 17:50:30 +02:00
*
2014-01-31 00:04:40 +01:00
* @ param $time
2013-12-17 17:38:44 +01:00
*/
2014-02-01 18:33:06 +01:00
public function hourlyUpdateCheck ( $time ) {
2013-12-17 17:38:44 +01:00
$updateCheckEnabled = $this -> maniaControl -> settingManager -> getSetting ( $this , self :: SETTING_ENABLEUPDATECHECK );
2014-01-28 16:23:50 +01:00
if ( ! $updateCheckEnabled ) {
2014-05-02 04:03:33 +02:00
$this -> setCoreUpdateData ();
2013-12-17 17:38:44 +01:00
return ;
}
2014-05-02 04:03:33 +02:00
$this -> checkUpdate ();
2013-12-17 17:38:44 +01:00
}
2014-05-02 17:50:30 +02:00
/**
* Set Core Update Data
*
* @ param UpdateData $coreUpdateData
*/
public function setCoreUpdateData ( UpdateData $coreUpdateData = null ) {
$this -> coreUpdateData = $coreUpdateData ;
}
/**
* Start an Update Check
*/
public function checkUpdate () {
$this -> checkCoreUpdateAsync ( array ( $this , 'handleUpdateCheck' ));
}
/**
* Checks a Core Update asynchronously
*
* @ param callable $function
*/
private function checkCoreUpdateAsync ( $function ) {
$updateChannel = $this -> getCurrentUpdateChannelSetting ();
$url = ManiaControl :: URL_WEBSERVICE . 'versions?current=1&channel=' . $updateChannel ;
$this -> maniaControl -> fileReader -> loadFile ( $url , function ( $dataJson , $error ) use ( & $function ) {
$versions = json_decode ( $dataJson );
if ( ! $versions || ! isset ( $versions [ 0 ])) {
call_user_func ( $function , null );
} else {
$updateData = new UpdateData ( $versions [ 0 ]);
call_user_func ( $function , $updateData );
}
});
}
/**
* Retrieve the Update Channel Setting
*
* @ return string
*/
private function getCurrentUpdateChannelSetting () {
$updateChannel = $this -> maniaControl -> settingManager -> getSetting ( $this , self :: SETTING_UPDATECHECK_CHANNEL );
$updateChannel = strtolower ( $updateChannel );
if ( ! in_array ( $updateChannel , array ( self :: CHANNEL_RELEASE , self :: CHANNEL_BETA , self :: CHANNEL_NIGHTLY ))) {
$updateChannel = self :: CHANNEL_RELEASE ;
}
return $updateChannel ;
}
2013-12-17 17:38:44 +01:00
/**
2014-05-02 04:03:33 +02:00
* Handle the fetched Update Data
2014-05-02 17:50:30 +02:00
*
2014-05-02 04:03:33 +02:00
* @ param UpdateData $updateData
2013-12-17 17:38:44 +01:00
*/
2014-05-02 04:03:33 +02:00
public function handleUpdateCheck ( UpdateData $updateData ) {
if ( ! $this -> checkUpdateData ( $updateData )) {
// No new update available
2014-01-20 21:54:58 +01:00
return ;
}
2014-05-02 04:03:33 +02:00
if ( ! $this -> checkUpdateDataBuildVersion ( $updateData )) {
// Server incompatible
$this -> maniaControl -> log ( " Please update Your Server to ' { $updateData -> minDedicatedBuild } ' in order to receive further Updates! " );
2014-01-20 21:54:58 +01:00
return ;
}
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
if ( $this -> isNightlyUpdateChannel ()) {
$this -> maniaControl -> log ( " New Nightly Build ( { $updateData -> releaseDate } ) available! " );
2014-05-02 17:50:30 +02:00
} else {
2014-05-02 04:03:33 +02:00
$this -> maniaControl -> log ( " New ManiaControl Version { $updateData -> version } available! " );
}
$this -> setCoreUpdateData ( $updateData );
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
$this -> checkAutoUpdate ();
2013-12-17 17:38:44 +01:00
}
2014-01-20 21:54:58 +01:00
/**
2014-05-02 04:03:33 +02:00
* Check if the given Update Data has a new Version and fits for the Server
2014-05-02 17:50:30 +02:00
*
2014-05-02 04:03:33 +02:00
* @ param UpdateData $updateData
* @ return bool
2014-01-20 21:54:58 +01:00
*/
2014-05-02 04:03:33 +02:00
public function checkUpdateData ( UpdateData $updateData = null ) {
if ( ! $updateData || ! $updateData -> url ) {
// Data corrupted
return false ;
2014-01-20 21:54:58 +01:00
}
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
$isNightly = $this -> isNightlyUpdateChannel ();
$buildDate = $this -> getNightlyBuildDate ();
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
if ( $isNightly || $buildDate ) {
return $updateData -> isNewerThan ( $buildDate );
2014-04-14 14:38:00 +02:00
}
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
return ( $updateData -> version > ManiaControl :: VERSION );
2014-01-20 21:54:58 +01:00
}
2014-05-02 17:50:30 +02:00
/**
* Check if ManiaControl is running the Nightly Update Channel
*
* @ param string $updateChannel
* @ return bool
*/
public function isNightlyUpdateChannel ( $updateChannel = null ) {
if ( ! $updateChannel ) {
$updateChannel = $this -> getCurrentUpdateChannelSetting ();
}
return ( $updateChannel === self :: CHANNEL_NIGHTLY );
}
/**
* Get the Build Date of the local Nightly Build Version
*
* @ return string
*/
public function getNightlyBuildDate () {
if ( ! $this -> currentBuildDate ) {
$nightlyBuildDateFile = ManiaControlDir . '/core/nightly_build.txt' ;
if ( file_exists ( $nightlyBuildDateFile )) {
$this -> currentBuildDate = file_get_contents ( $nightlyBuildDateFile );
}
}
return $this -> currentBuildDate ;
}
2013-12-17 17:38:44 +01:00
/**
2014-05-02 04:03:33 +02:00
* Check if the Update Data is compatible with the Server
2014-05-02 17:50:30 +02:00
*
2014-05-02 04:03:33 +02:00
* @ param UpdateData $updateData
* @ return bool
2013-12-17 17:38:44 +01:00
*/
2014-05-02 04:03:33 +02:00
public function checkUpdateDataBuildVersion ( UpdateData $updateData = null ) {
if ( ! $updateData ) {
// Data corrupted
return false ;
2014-04-29 23:53:55 +02:00
}
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
$version = $this -> maniaControl -> client -> getVersion ();
if ( $updateData -> minDedicatedBuild > $version -> build ) {
// Server not compatible
return false ;
2014-04-16 01:22:31 +02:00
}
2014-05-02 17:50:30 +02:00
return true ;
2014-02-10 21:32:41 +01:00
}
2013-12-31 18:25:07 +01:00
/**
2014-05-02 04:03:33 +02:00
* Check if an automatic Update should be performed
2013-12-31 18:25:07 +01:00
*/
2014-05-02 04:03:33 +02:00
public function checkAutoUpdate () {
$autoUpdate = $this -> maniaControl -> settingManager -> getSetting ( $this , self :: SETTING_AUTO_UPDATE );
if ( ! $autoUpdate ) {
// Auto update turned off
return ;
}
if ( ! $this -> coreUpdateData ) {
// No update available
return ;
}
if ( count ( $this -> maniaControl -> playerManager -> getPlayers ()) > 0 ) {
// Server not empty
2013-12-31 18:25:07 +01:00
return ;
}
2014-04-16 22:53:14 +02:00
2014-05-02 17:50:30 +02:00
$this -> performCoreUpdate ();
2014-02-10 21:32:41 +01:00
}
2013-12-27 23:26:27 +01:00
/**
* Perform a Core Update
2014-05-02 17:50:30 +02:00
*
2014-05-02 04:03:33 +02:00
* @ param Player $player
2013-12-27 23:26:27 +01:00
* @ return bool
*/
2014-05-02 04:03:33 +02:00
private function performCoreUpdate ( Player $player = null ) {
if ( ! $this -> coreUpdateData ) {
$message = 'Update failed: No update Data available!' ;
2014-03-31 21:41:05 +02:00
if ( $player ) {
2014-05-02 04:03:33 +02:00
$this -> maniaControl -> chat -> sendError ( $message , $player );
2014-02-09 18:22:47 +01:00
}
2014-05-02 04:03:33 +02:00
$this -> maniaControl -> log ( $message );
2014-01-28 16:23:50 +01:00
return false ;
}
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
$this -> maniaControl -> log ( " Starting Update to Version v { $this -> coreUpdateData -> version } ... " );
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
$directories = array ( '/core/' , '/plugins/' );
if ( ! FileUtil :: checkWritePermissions ( $directories )) {
$message = 'Update not possible: Incorrect File System Permissions!' ;
2014-03-31 21:41:05 +02:00
if ( $player ) {
2014-05-02 04:03:33 +02:00
$this -> maniaControl -> chat -> sendError ( $message , $player );
2013-12-27 23:26:27 +01:00
}
2014-05-02 04:03:33 +02:00
$this -> maniaControl -> log ( $message );
2014-02-10 21:32:41 +01:00
return false ;
2013-12-27 23:26:27 +01:00
}
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
$performBackup = $this -> maniaControl -> settingManager -> getSetting ( $this , self :: SETTING_PERFORM_BACKUPS );
if ( $performBackup && ! BackupUtil :: performFullBackup ()) {
$message = 'Creating Backup before Update failed!' ;
if ( $player ) {
$this -> maniaControl -> chat -> sendError ( $message , $player );
}
$this -> maniaControl -> log ( $message );
}
2014-05-02 17:50:30 +02:00
2014-04-20 14:52:26 +02:00
$self = $this ;
2014-05-02 17:50:30 +02:00
$this -> maniaControl -> fileReader -> loadFile ( $this -> coreUpdateData -> url , function ( $updateFileContent , $error ) use ( & $self , & $updateData , & $player ) {
$tempDir = FileUtil :: getTempFolder ();
2014-02-09 18:22:47 +01:00
$updateFileName = $tempDir . basename ( $updateData -> url );
2014-05-02 17:50:30 +02:00
2014-02-09 18:22:47 +01:00
$bytes = file_put_contents ( $updateFileName , $updateFileContent );
if ( ! $bytes || $bytes <= 0 ) {
2014-05-02 04:03:33 +02:00
$message = " Update failed: Couldn't save Update zip! " ;
2014-03-31 21:41:05 +02:00
if ( $player ) {
2014-05-02 04:03:33 +02:00
$self -> maniaControl -> chat -> sendError ( $message , $player );
2014-02-09 18:22:47 +01:00
}
2014-05-02 04:03:33 +02:00
logMessage ( $message );
return ;
2014-02-09 18:22:47 +01:00
}
2014-05-02 17:50:30 +02:00
$zip = new \ZipArchive ();
2014-02-09 18:22:47 +01:00
$result = $zip -> open ( $updateFileName );
if ( $result !== true ) {
trigger_error ( " Couldn't open Update Zip. ( { $result } ) " );
2014-03-31 21:41:05 +02:00
if ( $player ) {
2014-05-02 04:03:33 +02:00
$self -> maniaControl -> chat -> sendError ( " Update failed: Couldn't open Update zip! " , $player );
2014-02-09 18:22:47 +01:00
}
2014-05-02 04:03:33 +02:00
return ;
2014-02-09 18:22:47 +01:00
}
2014-05-02 17:50:30 +02:00
2014-02-09 18:22:47 +01:00
$zip -> extractTo ( ManiaControlDir );
$zip -> close ();
unlink ( $updateFileName );
2014-05-02 04:03:33 +02:00
FileUtil :: removeTempFolder ();
2014-05-02 17:50:30 +02:00
2014-04-29 23:53:55 +02:00
// Set the Nightly Build Date
2014-04-20 14:52:26 +02:00
$self -> setNightlyBuildDate ( $updateData -> releaseDate );
2014-05-02 17:50:30 +02:00
2014-05-02 04:03:33 +02:00
$message = 'Update finished!' ;
2014-03-31 21:41:05 +02:00
if ( $player ) {
2014-05-02 04:03:33 +02:00
$self -> maniaControl -> chat -> sendSuccess ( $message , $player );
2014-02-09 18:22:47 +01:00
}
2014-05-02 04:03:33 +02:00
$self -> maniaControl -> log ( $message );
2014-05-02 17:50:30 +02:00
2014-04-20 14:52:26 +02:00
$self -> maniaControl -> restart ();
2014-02-09 18:22:47 +01:00
});
2014-05-02 17:50:30 +02:00
2013-12-27 23:26:27 +01:00
return true ;
}
2014-01-28 16:23:50 +01:00
/**
2014-05-02 17:50:30 +02:00
* Set the Build Date of the local Nightly Build Version
*
* @ param string $date
2014-05-02 16:13:45 +02:00
* @ return bool
2014-01-28 16:23:50 +01:00
*/
2014-05-02 17:50:30 +02:00
private function setNightlyBuildDate ( $date ) {
$nightlyBuildDateFile = ManiaControlDir . '/core/nightly_build.txt' ;
$success = ( bool ) file_put_contents ( $nightlyBuildDateFile , $date );
$this -> currentBuildDate = $date ;
return $success ;
}
/**
* Handle ManiaControl PlayerJoined callback
*
* @ param Player $player
*/
public function handlePlayerJoined ( Player $player ) {
if ( ! $this -> coreUpdateData ) {
return ;
}
// Announce available update
if ( ! $this -> maniaControl -> authenticationManager -> checkPermission ( $player , self :: SETTING_PERMISSION_UPDATE )) {
return ;
}
if ( $this -> isNightlyUpdateChannel ()) {
$this -> maniaControl -> chat -> sendSuccess ( 'New Nightly Build (' . $this -> coreUpdateData -> releaseDate . ') available!' , $player -> login );
} else {
$this -> maniaControl -> chat -> sendInformation ( 'New ManiaControl Version ' . $this -> coreUpdateData -> version . ' available!' , $player -> login );
2014-01-28 16:23:50 +01:00
}
}
2014-01-24 19:00:26 +01:00
2013-12-27 23:26:27 +01:00
/**
2014-05-02 17:50:30 +02:00
* Handle Player Disconnect Callback
*
* @ param Player $player
2013-12-27 23:26:27 +01:00
*/
2014-05-02 17:50:30 +02:00
public function handlePlayerDisconnect ( Player $player ) {
$this -> checkAutoUpdate ();
}
/**
* Handle //checkupdate command
*
* @ param array $chatCallback
* @ param Player $player
*/
public function handle_CheckUpdate ( array $chatCallback , Player $player ) {
if ( ! $this -> maniaControl -> authenticationManager -> checkPermission ( $player , self :: SETTING_PERMISSION_UPDATECHECK )) {
$this -> maniaControl -> authenticationManager -> sendNotAllowed ( $player );
return ;
2013-12-27 23:26:27 +01:00
}
2014-05-02 17:50:30 +02:00
$self = $this ;
$this -> checkCoreUpdateAsync ( function ( UpdateData $updateData = null ) use ( & $self , & $player ) {
if ( ! $self -> checkUpdateData ( $updateData )) {
$self -> maniaControl -> chat -> sendInformation ( 'No Update available!' , $player -> login );
return ;
}
if ( ! $self -> checkUpdateDataBuildVersion ( $updateData )) {
$self -> maniaControl -> chat -> sendError ( " Please update Your Server to ' { $updateData -> minDedicatedBuild } ' in order to receive further Updates! " , $player -> login );
return ;
}
$isNightly = $self -> isNightlyUpdateChannel ();
if ( $isNightly ) {
$buildDate = $self -> getNightlyBuildDate ();
if ( $buildDate ) {
if ( $updateData -> isNewerThan ( $buildDate )) {
$self -> maniaControl -> chat -> sendInformation ( " No new Build available! (Current Build: ' { $buildDate } ') " , $player -> login );
} else {
$self -> maniaControl -> chat -> sendSuccess ( " New Nightly Build ( { $updateData -> releaseDate } ) available! (Current Build: ' { $buildDate } ') " , $player -> login );
}
} else {
$self -> maniaControl -> chat -> sendSuccess ( " New Nightly Build (' { $updateData -> releaseDate } ') available! " , $player -> login );
}
} else {
$self -> maniaControl -> chat -> sendSuccess ( 'Update for Version ' . $updateData -> version . ' available!' , $player -> login );
}
});
}
/**
* Handle //coreupdate command
*
* @ param array $chatCallback
* @ param Player $player
*/
public function handle_CoreUpdate ( array $chatCallback , Player $player ) {
if ( ! $this -> maniaControl -> authenticationManager -> checkPermission ( $player , self :: SETTING_PERMISSION_UPDATE )) {
$this -> maniaControl -> authenticationManager -> sendNotAllowed ( $player );
return ;
}
$self = $this ;
$this -> checkCoreUpdateAsync ( function ( UpdateData $updateData = null ) use ( & $self , & $player ) {
if ( ! $updateData ) {
$self -> maniaControl -> chat -> sendError ( 'Update is currently not possible!' , $player -> login );
return ;
}
if ( ! $self -> checkUpdateDataBuildVersion ( $updateData )) {
$self -> maniaControl -> chat -> sendError ( " The Next ManiaControl Update requires a newer Dedicated Server Version! " , $player -> login );
return ;
}
$message = " Starting Update to Version v { $updateData -> version } ... " ;
$self -> maniaControl -> chat -> sendInformation ( $message , $player -> login );
$self -> maniaControl -> log ( $message );
$performBackup = $self -> maniaControl -> settingManager -> getSetting ( $self , UpdateManager :: SETTING_PERFORM_BACKUPS );
if ( $performBackup && ! BackupUtil :: performFullBackup ()) {
$message = 'Creating Backup failed!' ;
$self -> maniaControl -> chat -> sendError ( $message , $player -> login );
$self -> maniaControl -> log ( $message );
}
$self -> performCoreUpdate ( $player );
});
2013-12-27 23:26:27 +01:00
}
2013-12-17 17:38:44 +01:00
}