Merge remote-tracking branch 'refs/remotes/ManiaControl/master'
This commit is contained in:
commit
42f3846ce7
@ -54,6 +54,7 @@
|
|||||||
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
|
<option name="ALIGN_GROUP_FIELD_DECLARATIONS" value="true" />
|
||||||
<option name="SPACE_AFTER_TYPE_CAST" value="true" />
|
<option name="SPACE_AFTER_TYPE_CAST" value="true" />
|
||||||
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
|
<option name="BINARY_OPERATION_SIGN_ON_NEXT_LINE" value="true" />
|
||||||
|
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
|
||||||
<option name="IF_BRACE_FORCE" value="3" />
|
<option name="IF_BRACE_FORCE" value="3" />
|
||||||
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
<option name="DOWHILE_BRACE_FORCE" value="3" />
|
||||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||||
@ -72,5 +73,4 @@
|
|||||||
</option>
|
</option>
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -3,5 +3,4 @@
|
|||||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
|
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false">
|
||||||
<file url="PROJECT" charset="UTF-8" />
|
<file url="PROJECT" charset="UTF-8" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -34,11 +34,11 @@ http://www.maniacontrol.com
|
|||||||
## REQUIREMENTS:
|
## REQUIREMENTS:
|
||||||
- MySQL Database
|
- MySQL Database
|
||||||
- PHP 5.4+
|
- PHP 5.4+
|
||||||
- Needed extensions:
|
- Needed extensions (on ManiaControl startup you will see if you have them activated):
|
||||||
- php_mysqli
|
- php_mysqli
|
||||||
- php_curl
|
- php_curl
|
||||||
- php_xmlrpc (TM only)
|
- php_xmlrpc (TM only, recomended for SM)
|
||||||
|
- php_zlib
|
||||||
|
|
||||||
### How to report bugs or request features?:
|
### How to report bugs or request features?:
|
||||||
- Write a mail to bugs(at)maniacontrol(dot)com
|
- Write a mail to bugs(at)maniacontrol(dot)com
|
||||||
|
60
changelog.txt
Normal file
60
changelog.txt
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
###v0.163###
|
||||||
|
#Additions
|
||||||
|
- completely reworked the filereader (new version, way more flexible), old methods are still working but deprecated
|
||||||
|
- added pause command and vote command for other gamemodes than elite (especially Chase/Combo)
|
||||||
|
- added Scriptcallbacks SCORESREADY / SCORES
|
||||||
|
- added SSL support as well as http Redirections of the FileReader
|
||||||
|
|
||||||
|
# Bug fixes
|
||||||
|
- Banning of not connected Players now possible
|
||||||
|
|
||||||
|
###v0.162###
|
||||||
|
#Additions
|
||||||
|
- added typhinting ladderStat in Player object
|
||||||
|
- added optional AsynchronousFileReader Parameter for loadFile and postFile to set additional Headers
|
||||||
|
- added ServerLogin header for Mania-Exchange downloads
|
||||||
|
|
||||||
|
###v0.161###
|
||||||
|
#Additions
|
||||||
|
- added admin chatcommand //uptime which displays the time since when the server is running
|
||||||
|
- updated playerhitstructure with new properties
|
||||||
|
|
||||||
|
#Bug Fixes
|
||||||
|
- fixed some z positions to be in front of overlays (especially in Trackmania)
|
||||||
|
- fixed limit problem on maniaexchange list
|
||||||
|
|
||||||
|
###v0.16###
|
||||||
|
#Additions
|
||||||
|
- added changelog
|
||||||
|
- added CommunicationManager which acts like a communication interface you can connect to and interact with ManiaControl (also thanks to TGYoshi for some help)
|
||||||
|
- You can call ManiaControl from a Website or from ManiaControl itself
|
||||||
|
- added "//removerights login" command
|
||||||
|
- added new EchoManager which handles Interactions between different Controllers
|
||||||
|
- It is possible to send an Echo command via the Method sendEcho, as message Parameter strings, objects or arrays can get used
|
||||||
|
- An EchoListener can be added, callable by closure or implicit use (like on callbacks)
|
||||||
|
- The Listener always returns either an Stringer or an Object back as Param (arrays get converted into objects)
|
||||||
|
- On sending an Echo Message from another controller you need to provide an string to the dedicated method or an json_encoded array or object
|
||||||
|
- 4 Echos are Implemented by ManiaControl (ManiaControl.Restart, ManiaControl.AuthenticationManager.GrandLevel, ManiaControl.AuthenticationManager.RevokeLevel, ManiaControl.PlayerManager.WarnPlayer)
|
||||||
|
- added Method getServerLoginByIndex to Server object
|
||||||
|
- added to PlayerManager's Method PlayerManager the Parameter "withoutBots" (default on true)
|
||||||
|
- added Method getSpectators() in PlayerManager
|
||||||
|
- added Method restartMap(), skipToMapByMxId(), skipToMapByUid() into MapActions
|
||||||
|
- added some missing PHP Docs
|
||||||
|
- added some depency libraries as they are used by the Socket Handler
|
||||||
|
- added additional Callback which gets triggered on ManiaControl Restart
|
||||||
|
- added class name to the BillData object
|
||||||
|
- updated some depency libraries
|
||||||
|
|
||||||
|
#Bug Fixes
|
||||||
|
- fixed TriggerDebugNotice Method
|
||||||
|
- Exception fix on kicking Players
|
||||||
|
- updated FaultException List
|
||||||
|
|
||||||
|
###v0.157###
|
||||||
|
- labelline improvements
|
||||||
|
- new usage examples:
|
||||||
|
$positions = array($posX + 5, $posX + 18, $posX + 70);
|
||||||
|
$texts = array($index, $admin->nickname, $admin->login);
|
||||||
|
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, array($positions, $texts));
|
||||||
|
- improvements on Billmanager, added receiver to the BillData
|
||||||
|
- increased timeout time (fixes crashes on speedball)
|
@ -290,7 +290,7 @@ class ActionsMenu implements CallbackListener, ManialinkPageAnswerListener {
|
|||||||
unset($this->playerMenuItems[$order]);
|
unset($this->playerMenuItems[$order]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (isset($this->playerMenuItems[$order])) {
|
if (isset($this->adminMenuItems[$order])) {
|
||||||
unset($this->adminMenuItems[$order]);
|
unset($this->adminMenuItems[$order]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,9 +133,9 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener {
|
|||||||
$lineQuad->setZ(0.001);
|
$lineQuad->setZ(0.001);
|
||||||
}
|
}
|
||||||
|
|
||||||
$array = array($index => $posX + 5, $admin->nickname => $posX + 18, $admin->login => $posX + 70);
|
$positions = array($posX + 5, $posX + 18, $posX + 70);
|
||||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, $array);
|
$texts = array($index, $admin->nickname, $admin->login);
|
||||||
|
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, array($positions, $texts));
|
||||||
|
|
||||||
// Level Quad
|
// Level Quad
|
||||||
$rightQuad = new Quad_BgRaceScore2();
|
$rightQuad = new Quad_BgRaceScore2();
|
||||||
|
@ -32,6 +32,8 @@ class AuthCommands implements CommandListener {
|
|||||||
$this->maniaControl->getCommandManager()->registerCommandListener('addsuperadmin', $this, 'command_AddSuperAdmin', true, 'Add Player to the AdminList as SuperAdmin.');
|
$this->maniaControl->getCommandManager()->registerCommandListener('addsuperadmin', $this, 'command_AddSuperAdmin', true, 'Add Player to the AdminList as SuperAdmin.');
|
||||||
$this->maniaControl->getCommandManager()->registerCommandListener('addadmin', $this, 'command_AddAdmin', true, 'Add Player to the AdminList as Admin.');
|
$this->maniaControl->getCommandManager()->registerCommandListener('addadmin', $this, 'command_AddAdmin', true, 'Add Player to the AdminList as Admin.');
|
||||||
$this->maniaControl->getCommandManager()->registerCommandListener('addmod', $this, 'command_AddModerator', true, 'Add Player to the AdminList as Moderator.');
|
$this->maniaControl->getCommandManager()->registerCommandListener('addmod', $this, 'command_AddModerator', true, 'Add Player to the AdminList as Moderator.');
|
||||||
|
|
||||||
|
$this->maniaControl->getCommandManager()->registerCommandListener('removerights', $this, 'command_RemoveRights', true, 'Remove Player from the AdminList.');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -159,4 +161,53 @@ class AuthCommands implements CommandListener {
|
|||||||
$message = "Usage Example: '//addmod login'";
|
$message = "Usage Example: '//addmod login'";
|
||||||
return $this->maniaControl->getChat()->sendUsageInfo($message, $player);
|
return $this->maniaControl->getChat()->sendUsageInfo($message, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle //removerights command
|
||||||
|
*
|
||||||
|
* @param array $chatCallback
|
||||||
|
* @param Player $player
|
||||||
|
*/
|
||||||
|
public function command_RemoveRights(array $chatCallback, Player $player) {
|
||||||
|
if (!AuthenticationManager::checkRight($player, AuthenticationManager::AUTH_LEVEL_ADMIN)) {
|
||||||
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$text = $chatCallback[1][2];
|
||||||
|
$commandParts = explode(' ', $text);
|
||||||
|
if (!array_key_exists(1, $commandParts)) {
|
||||||
|
$this->sendRemoveRightsUsageInfo($player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($commandParts[1]);
|
||||||
|
if (!$target) {
|
||||||
|
$this->maniaControl->getChat()->sendError("Player '{$commandParts[1]}' not found!", $player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($target->authLevel == AuthenticationManager::AUTH_LEVEL_MASTERADMIN) {
|
||||||
|
$this->maniaControl->getChat()->sendError("You can't remove an MasterAdmin from the Adminlists", $player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, AuthenticationManager::AUTH_LEVEL_PLAYER);
|
||||||
|
if (!$success) {
|
||||||
|
$this->maniaControl->getChat()->sendError('Error occurred.', $player);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$message = $player->getEscapedNickname() . ' removed ' . $target->getEscapedNickname() . ' from the Adminlists!';
|
||||||
|
$this->maniaControl->getChat()->sendSuccess($message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send usage example for //removerights command
|
||||||
|
*
|
||||||
|
* @param Player $player
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function sendRemoveRightsUsageInfo(Player $player) {
|
||||||
|
$message = "Usage Example: '//addadmin login'";
|
||||||
|
return $this->maniaControl->getChat()->sendUsageInfo($message, $player);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,10 @@ namespace ManiaControl\Admin;
|
|||||||
|
|
||||||
use ManiaControl\Callbacks\CallbackListener;
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
use ManiaControl\Callbacks\Callbacks;
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
|
use ManiaControl\Callbacks\EchoListener;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
@ -17,7 +21,7 @@ use ManiaControl\Settings\Setting;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class AuthenticationManager implements CallbackListener {
|
class AuthenticationManager implements CallbackListener, EchoListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -33,6 +37,8 @@ class AuthenticationManager implements CallbackListener {
|
|||||||
const AUTH_NAME_MASTERADMIN = 'MasterAdmin';
|
const AUTH_NAME_MASTERADMIN = 'MasterAdmin';
|
||||||
const CB_AUTH_LEVEL_CHANGED = 'AuthenticationManager.AuthLevelChanged';
|
const CB_AUTH_LEVEL_CHANGED = 'AuthenticationManager.AuthLevelChanged';
|
||||||
|
|
||||||
|
const ECHO_GRANT_LEVEL = 'ManiaControl.AuthenticationManager.GrandLevel';
|
||||||
|
const ECHO_REVOKE_LEVEL = 'ManiaControl.AuthenticationManager.RevokeLevel';
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
@ -52,6 +58,56 @@ class AuthenticationManager implements CallbackListener {
|
|||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
|
||||||
|
|
||||||
|
// Echo Grant Level Command (Usage: sendEcho json_encode("player" => "loginName", "level" => "AUTH_LEVEL_NUMBER")
|
||||||
|
$this->maniaControl->getEchoManager()->registerEchoListener(self::ECHO_GRANT_LEVEL, $this, function ($params) {
|
||||||
|
if (property_exists($params, 'level') && property_exists($params, 'player')) {
|
||||||
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($params->player);
|
||||||
|
if ($player) {
|
||||||
|
$this->grantAuthLevel($player, $params->level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Echo Revoke Level Command (Usage: sendEcho json_encode("player" => "loginName")
|
||||||
|
$this->maniaControl->getEchoManager()->registerEchoListener(self::ECHO_REVOKE_LEVEL, $this, function ($params) {
|
||||||
|
if (property_exists($params, 'player')) {
|
||||||
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($params->player);
|
||||||
|
if ($player) {
|
||||||
|
$this->maniaControl->getAuthenticationManager()->grantAuthLevel($player, self::AUTH_LEVEL_PLAYER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//Communication Listenings
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GRANT_AUTH_LEVEL, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, 'level') || !property_exists($data, 'login')) {
|
||||||
|
return new CommunicationAnswer("No valid level or player login provided!", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($data->login);
|
||||||
|
if ($player) {
|
||||||
|
$success = $this->grantAuthLevel($player, $data->level);
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
} else {
|
||||||
|
return new CommunicationAnswer("Player not found!", true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::REVOKE_AUTH_LEVEL, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, 'login')) {
|
||||||
|
return new CommunicationAnswer("No valid player login provided!", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($data->login);
|
||||||
|
if ($player) {
|
||||||
|
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($player, self::AUTH_LEVEL_PLAYER);
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
} else {
|
||||||
|
return new CommunicationAnswer("Player not found!", true);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -83,12 +139,12 @@ class AuthenticationManager implements CallbackListener {
|
|||||||
*/
|
*/
|
||||||
public static function getAuthLevelInt($authLevelParam) {
|
public static function getAuthLevelInt($authLevelParam) {
|
||||||
if (is_object($authLevelParam) && property_exists($authLevelParam, 'authLevel')) {
|
if (is_object($authLevelParam) && property_exists($authLevelParam, 'authLevel')) {
|
||||||
return (int)$authLevelParam->authLevel;
|
return (int) $authLevelParam->authLevel;
|
||||||
}
|
}
|
||||||
if (is_string($authLevelParam)) {
|
if (is_string($authLevelParam)) {
|
||||||
return self::getAuthLevel($authLevelParam);
|
return self::getAuthLevel($authLevelParam);
|
||||||
}
|
}
|
||||||
return (int)$authLevelParam;
|
return (int) $authLevelParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,7 +154,7 @@ class AuthenticationManager implements CallbackListener {
|
|||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public static function getAuthLevel($authLevelName) {
|
public static function getAuthLevel($authLevelName) {
|
||||||
$authLevelName = (string)$authLevelName;
|
$authLevelName = (string) $authLevelName;
|
||||||
switch ($authLevelName) {
|
switch ($authLevelName) {
|
||||||
case self::AUTH_NAME_MASTERADMIN:
|
case self::AUTH_NAME_MASTERADMIN:
|
||||||
return self::AUTH_LEVEL_MASTERADMIN;
|
return self::AUTH_LEVEL_MASTERADMIN;
|
||||||
@ -189,7 +245,7 @@ class AuthenticationManager implements CallbackListener {
|
|||||||
}
|
}
|
||||||
$success = true;
|
$success = true;
|
||||||
foreach ($loginElements as $loginElement) {
|
foreach ($loginElements as $loginElement) {
|
||||||
$login = (string)$loginElement;
|
$login = (string) $loginElement;
|
||||||
$adminStatement->bind_param('si', $login, $masterAdminLevel);
|
$adminStatement->bind_param('si', $login, $masterAdminLevel);
|
||||||
$adminStatement->execute();
|
$adminStatement->execute();
|
||||||
if ($adminStatement->error) {
|
if ($adminStatement->error) {
|
||||||
@ -271,7 +327,7 @@ class AuthenticationManager implements CallbackListener {
|
|||||||
if (!$player || !is_numeric($authLevel)) {
|
if (!$player || !is_numeric($authLevel)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$authLevel = (int)$authLevel;
|
$authLevel = (int) $authLevel;
|
||||||
if ($authLevel >= self::AUTH_LEVEL_MASTERADMIN) {
|
if ($authLevel >= self::AUTH_LEVEL_MASTERADMIN) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -15,28 +15,34 @@ class BillData {
|
|||||||
/*
|
/*
|
||||||
* Public properties
|
* Public properties
|
||||||
*/
|
*/
|
||||||
public $function = null;
|
public $function = null;
|
||||||
public $pay = false;
|
public $pay = false;
|
||||||
public $player = null;
|
public $player = null;
|
||||||
public $receiverLogin = null;
|
public $receiverLogin = null;
|
||||||
public $amount = 0;
|
public $amount = 0;
|
||||||
public $creationTime = -1;
|
public $creationTime = -1;
|
||||||
|
public $message = "";
|
||||||
|
public $class = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct new Bill Data Model
|
* Construct new Bill Data Model
|
||||||
*
|
*
|
||||||
|
* @param string $class
|
||||||
* @param callable $function
|
* @param callable $function
|
||||||
* @param Player|string $player
|
* @param Player|string $player
|
||||||
* @param int $amount
|
* @param int $amount
|
||||||
* @param bool $pay
|
* @param bool $pay
|
||||||
* @param string $receiverLogin
|
* @param string $receiverLogin
|
||||||
|
* @param string $message
|
||||||
*/
|
*/
|
||||||
public function __construct(callable $function, $player, $amount, $pay = false, $receiverLogin = null) {
|
public function __construct($class, callable $function, $player, $amount, $pay = false, $receiverLogin = null, $message = '') {
|
||||||
|
$this->class = $class;
|
||||||
$this->function = $function;
|
$this->function = $function;
|
||||||
$this->player = $player;
|
$this->player = $player;
|
||||||
$this->amount = $amount;
|
$this->amount = $amount;
|
||||||
$this->pay = $pay;
|
$this->pay = $pay;
|
||||||
$this->receiverLogin = $receiverLogin;
|
$this->receiverLogin = $receiverLogin;
|
||||||
|
$this->message = $message;
|
||||||
$this->creationTime = time();
|
$this->creationTime = time();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ use ManiaControl\Callbacks\CallbackListener;
|
|||||||
use ManiaControl\Callbacks\CallbackManager;
|
use ManiaControl\Callbacks\CallbackManager;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
|
use Maniaplanet\DedicatedServer\InvalidArgumentException;
|
||||||
use Maniaplanet\DedicatedServer\Structures\Bill;
|
use Maniaplanet\DedicatedServer\Structures\Bill;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -24,7 +25,7 @@ class BillManager implements CallbackListener {
|
|||||||
const PAYED_FROM_SERVER = 3;
|
const PAYED_FROM_SERVER = 3;
|
||||||
const PLAYER_REFUSED_DONATION = 4;
|
const PLAYER_REFUSED_DONATION = 4;
|
||||||
const ERROR_WHILE_TRANSACTION = 5;
|
const ERROR_WHILE_TRANSACTION = 5;
|
||||||
const CB_BILL_PAID = 'Billmanager.BillPaid';
|
const CB_BILL_PAID = 'Billmanager.BillPaid';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
@ -57,11 +58,21 @@ class BillManager implements CallbackListener {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function sendBill(callable $function, Player $player, $amount, $message, $receiver = '') {
|
public function sendBill(callable $function, Player $player, $amount, $message, $receiver = '') {
|
||||||
$billId = $this->maniaControl->getClient()->sendBill($player->login, $amount, $message, $receiver);
|
//Get the Caller Class
|
||||||
$this->openBills[$billId] = new BillData($function, $player, $amount);
|
$backTrace = debug_backtrace();
|
||||||
|
$class = $backTrace[1]['class'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$billId = $this->maniaControl->getClient()->sendBill($player->login, intval($amount), $message, $receiver);
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
//TODO better error handling, maybe call the user func with ERROR_WHILE_TRANSACTION
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->openBills[$billId] = new BillData($class, $function, $player, $amount, false, $receiver, $message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send planets from the server to a player
|
* Send planets from the server to a player
|
||||||
*
|
*
|
||||||
@ -72,8 +83,17 @@ class BillManager implements CallbackListener {
|
|||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function sendPlanets(callable $function, $receiverLogin, $amount, $message) {
|
public function sendPlanets(callable $function, $receiverLogin, $amount, $message) {
|
||||||
$billId = $this->maniaControl->getClient()->pay($receiverLogin, $amount, $message);
|
//Get the Caller Class
|
||||||
$this->openBills[$billId] = new BillData($function, $receiverLogin, $amount, true);
|
$backTrace = debug_backtrace();
|
||||||
|
$class = $backTrace[1]['class'];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$billId = $this->maniaControl->getClient()->pay($receiverLogin, intval($amount), $message);
|
||||||
|
} catch (InvalidArgumentException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->openBills[$billId] = new BillData($class, $function, $receiverLogin, $amount, true, $receiverLogin, $message);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +153,6 @@ class CallbackManager {
|
|||||||
return $this->removeCallbackListener($this->callbackListenings, $listener);
|
return $this->removeCallbackListener($this->callbackListenings, $listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO better name (used only in customvotesPlugin)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the Callback Listener from the given Listeners Array
|
* Remove the Callback Listener from the given Listeners Array
|
||||||
*
|
*
|
||||||
@ -212,6 +210,9 @@ class CallbackManager {
|
|||||||
// Manage Timings
|
// Manage Timings
|
||||||
$this->maniaControl->getTimerManager()->manageTimings();
|
$this->maniaControl->getTimerManager()->manageTimings();
|
||||||
|
|
||||||
|
// Manage Socket Tickets
|
||||||
|
$this->maniaControl->getCommunicationManager()->tick();
|
||||||
|
|
||||||
// Server Callbacks
|
// Server Callbacks
|
||||||
if (!$this->maniaControl->getClient()) {
|
if (!$this->maniaControl->getClient()) {
|
||||||
return;
|
return;
|
||||||
|
@ -18,6 +18,7 @@ interface Callbacks {
|
|||||||
const ONINIT = 'Callbacks.OnInit';
|
const ONINIT = 'Callbacks.OnInit';
|
||||||
const AFTERINIT = 'Callbacks.AfterInit';
|
const AFTERINIT = 'Callbacks.AfterInit';
|
||||||
const ONSHUTDOWN = 'Callbacks.OnShutdown';
|
const ONSHUTDOWN = 'Callbacks.OnShutdown';
|
||||||
|
const ONRESTART = 'Callbacks.OnRestart';
|
||||||
|
|
||||||
/** Script Callback: CallbackName, CallbackData */
|
/** Script Callback: CallbackName, CallbackData */
|
||||||
const SCRIPTCALLBACK = 'Callbacks.ScriptCallback';
|
const SCRIPTCALLBACK = 'Callbacks.ScriptCallback';
|
||||||
@ -49,6 +50,8 @@ interface Callbacks {
|
|||||||
const ENDTURNSTOP = 'Callbacks.EndTurnStop';
|
const ENDTURNSTOP = 'Callbacks.EndTurnStop';
|
||||||
/** EndRound Callback: RoundNumber */
|
/** EndRound Callback: RoundNumber */
|
||||||
const ENDROUND = 'Callbacks.EndRound';
|
const ENDROUND = 'Callbacks.EndRound';
|
||||||
|
/** EndRound Callback: RoundNumber */
|
||||||
|
const ENDROUNDSTOP = 'Callbacks.EndRoundStop';
|
||||||
/** EndSubmatch Callback: SubmatchNumber */
|
/** EndSubmatch Callback: SubmatchNumber */
|
||||||
const ENDSUBMATCH = 'Callbacks.EndSubmatch';
|
const ENDSUBMATCH = 'Callbacks.EndSubmatch';
|
||||||
/** EndMap Callback: Map */
|
/** EndMap Callback: Map */
|
||||||
@ -67,6 +70,12 @@ interface Callbacks {
|
|||||||
/** EndWarmup Callback */
|
/** EndWarmup Callback */
|
||||||
const ENDWARMUP = 'Callbacks.EndWarmUp';
|
const ENDWARMUP = 'Callbacks.EndWarmUp';
|
||||||
|
|
||||||
|
/** Scores Callback (returned after LibXmlRpc_PlayerRanking): Scores */
|
||||||
|
const SCORESREADY = 'Callbacks.ScoresReady';
|
||||||
|
|
||||||
|
/** Scores Callback (returned after LibXmlRpc_PlayerRanking in SM, or LibXmlRpc_TeamsScores in Trackmania): Scores */
|
||||||
|
const SCORES = 'Callbacks.Scores';
|
||||||
|
|
||||||
/** PlayerRanking Callback, returned after LibXmlRpc_PlayerRanking
|
/** PlayerRanking Callback, returned after LibXmlRpc_PlayerRanking
|
||||||
* try to avoid to use this, just use the Get function of the RankingsManager instead
|
* try to avoid to use this, just use the Get function of the RankingsManager instead
|
||||||
* param1 Player $player
|
* param1 Player $player
|
||||||
@ -80,8 +89,6 @@ interface Callbacks {
|
|||||||
*/
|
*/
|
||||||
/** RankingsUpdated Callback: SortedRankings */
|
/** RankingsUpdated Callback: SortedRankings */
|
||||||
const RANKINGSUPDATED = 'Callbacks.RankingsUpdated';
|
const RANKINGSUPDATED = 'Callbacks.RankingsUpdated';
|
||||||
/** Scores Callback (returned after LibXmlRpc_PlayerRanking): Scores */
|
|
||||||
const SCORES = 'Callbacks.Scores';
|
|
||||||
|
|
||||||
/** Returns the AFKStatus of an Player, returned after param1 Scores */ //returned after TODO
|
/** Returns the AFKStatus of an Player, returned after param1 Scores */ //returned after TODO
|
||||||
const AFKSTATUS = 'Callbacks.AfkStatus';
|
const AFKSTATUS = 'Callbacks.AfkStatus';
|
||||||
|
12
core/Callbacks/EchoListener.php
Normal file
12
core/Callbacks/EchoListener.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
namespace ManiaControl\Callbacks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for EchoListener
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
interface EchoListener {
|
||||||
|
}
|
150
core/Callbacks/EchoManager.php
Normal file
150
core/Callbacks/EchoManager.php
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ManiaControl\Callbacks;
|
||||||
|
|
||||||
|
|
||||||
|
use ManiaControl\ManiaControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for managing Echo Callbacks
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
class EchoManager implements CallbackListener, EchoListener {
|
||||||
|
/*
|
||||||
|
* Private properties
|
||||||
|
*/
|
||||||
|
/** @var ManiaControl $maniaControl */
|
||||||
|
private $maniaControl = null;
|
||||||
|
/** @var Listening[] $echoListenings */
|
||||||
|
private $echoListenings = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Echo Handler Instance
|
||||||
|
*
|
||||||
|
* @param ManiaControl $maniaControl
|
||||||
|
*/
|
||||||
|
public function __construct(ManiaControl $maniaControl) {
|
||||||
|
$this->maniaControl = $maniaControl;
|
||||||
|
|
||||||
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_ECHO, $this, 'handleEchos');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an Echo Message
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param mixed $data (can be array, object or string)
|
||||||
|
* @return bool
|
||||||
|
* @throws \Maniaplanet\DedicatedServer\InvalidArgumentException
|
||||||
|
*/
|
||||||
|
public function sendEcho($name, $data) {
|
||||||
|
if (is_string($data)) {
|
||||||
|
$success = $this->maniaControl->getClient()->dedicatedEcho($data, $name);
|
||||||
|
} else {
|
||||||
|
$success = $this->maniaControl->getClient()->dedicatedEcho(json_encode($data), $name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new Echo Listener
|
||||||
|
*
|
||||||
|
* @param string $callbackName
|
||||||
|
* @param EchoListener $listener
|
||||||
|
* @param string $method
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function registerEchoListener($echoName, EchoListener $listener, $method) {
|
||||||
|
if (!Listening::checkValidCallback($listener, $method)) {
|
||||||
|
$listenerClass = get_class($listener);
|
||||||
|
trigger_error("Given Listener '{$listenerClass}' can't handle Callback '{$echoName}': No callable Method '{$method}'!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!array_key_exists($echoName, $this->echoListenings)) {
|
||||||
|
$this->echoListenings[$echoName] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$listening = new Listening($listener, $method);
|
||||||
|
array_push($this->echoListenings[$echoName], $listening);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a Echo Listener
|
||||||
|
*
|
||||||
|
* @param EchoListener $listener
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function unregisterEchoListener(EchoListener $listener) {
|
||||||
|
return $this->removeEchoListener($this->echoListenings, $listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the Echo Listener from the given Listeners Array
|
||||||
|
*
|
||||||
|
* @param Listening[] $listeningsArray
|
||||||
|
* @param EchoListener $listener
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function removeEchoListener(array &$listeningsArray, EchoListener $listener) {
|
||||||
|
$removed = false;
|
||||||
|
foreach ($listeningsArray as &$listenings) {
|
||||||
|
foreach ($listenings as $key => &$listening) {
|
||||||
|
if ($listening->listener === $listener) {
|
||||||
|
unset($listenings[$key]);
|
||||||
|
$removed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger a specific Callback
|
||||||
|
*
|
||||||
|
* @param mixed $callback
|
||||||
|
*/
|
||||||
|
public function triggerEchoCallback($callbackName) {
|
||||||
|
if (!array_key_exists($callbackName, $this->echoListenings)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$params = func_get_args();
|
||||||
|
$params = array_slice($params, 1, null, true);
|
||||||
|
|
||||||
|
//var_dump($params);
|
||||||
|
foreach ($this->echoListenings[$callbackName] as $listening) {
|
||||||
|
/** @var Listening $listening */
|
||||||
|
$listening->triggerCallbackWithParams($params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the given Callback
|
||||||
|
*
|
||||||
|
* @param array $callback
|
||||||
|
*/
|
||||||
|
public function handleEchos($param) {
|
||||||
|
$name = $param[1][0];
|
||||||
|
if (is_object($decode = json_decode($param[1][1]))) {
|
||||||
|
$message = $decode;
|
||||||
|
} else {
|
||||||
|
$message = $param[1][1];
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($name) {
|
||||||
|
case 'ManiaControl.Restart':
|
||||||
|
$this->maniaControl->restart($message);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$this->triggerEchoCallback($name, $message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -82,6 +82,9 @@ class LibXmlRpcCallbacks implements CallbackListener {
|
|||||||
case 'LibXmlRpc_EndRound':
|
case 'LibXmlRpc_EndRound':
|
||||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDROUND, $data[0]);
|
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDROUND, $data[0]);
|
||||||
break;
|
break;
|
||||||
|
case 'LibXmlRpc_EndRoundStop':
|
||||||
|
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDROUNDSTOP, $data[0]);
|
||||||
|
break;
|
||||||
case 'LibXmlRpc_EndSubmatch':
|
case 'LibXmlRpc_EndSubmatch':
|
||||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDSUBMATCH, $data[0]);
|
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDSUBMATCH, $data[0]);
|
||||||
break;
|
break;
|
||||||
@ -146,6 +149,12 @@ class LibXmlRpcCallbacks implements CallbackListener {
|
|||||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($data[0]);
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($data[0]);
|
||||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONPLAYERREQUESTRESPAWN, $player);
|
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONPLAYERREQUESTRESPAWN, $player);
|
||||||
break;
|
break;
|
||||||
|
case 'LibXmlRpc_Scores':
|
||||||
|
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::SCORES, $data);
|
||||||
|
break;
|
||||||
|
case 'LibXmlRpc_ScoresReady':
|
||||||
|
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::SCORESREADY, $data);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +57,10 @@ class Listening {
|
|||||||
* Trigger the Listener's Method with the given Array of Params
|
* Trigger the Listener's Method with the given Array of Params
|
||||||
*
|
*
|
||||||
* @param array $params
|
* @param array $params
|
||||||
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function triggerCallbackWithParams(array $params) {
|
public function triggerCallbackWithParams(array $params) {
|
||||||
call_user_func_array($this->getUserFunction(), $params);
|
return call_user_func_array($this->getUserFunction(), $params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,9 +52,6 @@ class ShootManiaCallbacks implements CallbackListener {
|
|||||||
case 'LibXmlRpc_Rankings':
|
case 'LibXmlRpc_Rankings':
|
||||||
$this->maniaControl->getServer()->getRankingManager()->updateRankings($data[0]);
|
$this->maniaControl->getServer()->getRankingManager()->updateRankings($data[0]);
|
||||||
break;
|
break;
|
||||||
case 'LibXmlRpc_Scores':
|
|
||||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::SCORES, $data);
|
|
||||||
break;
|
|
||||||
case 'LibAFK_IsAFK':
|
case 'LibAFK_IsAFK':
|
||||||
$this->triggerAfkStatus($data[0]);
|
$this->triggerAfkStatus($data[0]);
|
||||||
break;
|
break;
|
||||||
|
@ -4,7 +4,13 @@ namespace ManiaControl\Callbacks\Structures;
|
|||||||
|
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
|
/**
|
||||||
|
* Structure Class for the ArmorEmpty Callback
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
class ArmorEmptyStructure {
|
class ArmorEmptyStructure {
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
|
@ -5,6 +5,13 @@ namespace ManiaControl\Callbacks\Structures;
|
|||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure Class for the Capture Callback
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
class CaptureStructure {
|
class CaptureStructure {
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
@ -42,7 +49,7 @@ class CaptureStructure {
|
|||||||
$playerArray = array();
|
$playerArray = array();
|
||||||
foreach ($this->playerArray as $login) {
|
foreach ($this->playerArray as $login) {
|
||||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||||
if($player){
|
if ($player) {
|
||||||
$playerArray[$login] = $player;
|
$playerArray[$login] = $player;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,13 @@ namespace ManiaControl\Callbacks\Structures;
|
|||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure Class for the EliteBeginTurn Callback
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
class EliteBeginTurnStructure {
|
class EliteBeginTurnStructure {
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
@ -22,8 +29,8 @@ class EliteBeginTurnStructure {
|
|||||||
* @param array $data
|
* @param array $data
|
||||||
*/
|
*/
|
||||||
public function __construct(ManiaControl $maniaControl, array $data) {
|
public function __construct(ManiaControl $maniaControl, array $data) {
|
||||||
$this->maniaControl = $maniaControl;
|
$this->maniaControl = $maniaControl;
|
||||||
$this->attackerLogin = $data[0];
|
$this->attackerLogin = $data[0];
|
||||||
$this->defenderLogins = $data[1];
|
$this->defenderLogins = $data[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,13 @@ namespace ManiaControl\Callbacks\Structures;
|
|||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure Class for the NearMiss Callback
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
class NearMissStructure {
|
class NearMissStructure {
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
|
||||||
* Player Hit Structure
|
|
||||||
*
|
|
||||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
|
||||||
* @copyright 2014-2015 ManiaControl Team
|
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
|
||||||
*/
|
|
||||||
namespace ManiaControl\Callbacks\Structures;
|
namespace ManiaControl\Callbacks\Structures;
|
||||||
|
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Structure Class for the Player Hit Callback
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
class PlayerHitStructure {
|
class PlayerHitStructure {
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
@ -20,7 +21,11 @@ class PlayerHitStructure {
|
|||||||
private $damage;
|
private $damage;
|
||||||
private $shooterPoints;
|
private $shooterPoints;
|
||||||
private $weapon;
|
private $weapon;
|
||||||
private $hitDistance = 0;
|
private $hitDistance;
|
||||||
|
private $shooterPosition = 0;
|
||||||
|
private $victimPosition = 0;
|
||||||
|
private $shooterAimDirection = 0;
|
||||||
|
private $victimAimDirection = 0;
|
||||||
|
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl;
|
private $maniaControl;
|
||||||
@ -38,10 +43,23 @@ class PlayerHitStructure {
|
|||||||
$this->damage = $data[2];
|
$this->damage = $data[2];
|
||||||
$this->weapon = $data[3];
|
$this->weapon = $data[3];
|
||||||
$this->shooterPoints = $data[4];
|
$this->shooterPoints = $data[4];
|
||||||
|
$this->hitDistance = $data[5];
|
||||||
//TODO remove key check in some months (hitDistance got implemented 2014-10-16)
|
|
||||||
if (array_key_exists(5, $data)) {
|
//TODO remove key check in some months (got implemented 2015-05-03)
|
||||||
$this->hitDistance = $data[5];
|
if (array_key_exists(6, $data)) {
|
||||||
|
$this->shooterPosition = $data[6];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists(7, $data)) {
|
||||||
|
$this->victimPosition = $data[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists(8, $data)) {
|
||||||
|
$this->shooterAimDirection = $data[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (array_key_exists(9, $data)) {
|
||||||
|
$this->victimAimDirection = $data[9];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
107
core/Chat.php
107
core/Chat.php
@ -3,6 +3,11 @@
|
|||||||
namespace ManiaControl;
|
namespace ManiaControl;
|
||||||
|
|
||||||
use ManiaControl\Admin\AuthenticationManager;
|
use ManiaControl\Admin\AuthenticationManager;
|
||||||
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
|
use ManiaControl\Callbacks\CallbackManager;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||||
|
|
||||||
@ -13,7 +18,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class Chat {
|
class Chat implements CallbackListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -22,12 +27,13 @@ class Chat {
|
|||||||
const SETTING_FORMAT_SUCCESS = 'Success Format';
|
const SETTING_FORMAT_SUCCESS = 'Success Format';
|
||||||
const SETTING_FORMAT_ERROR = 'Error Format';
|
const SETTING_FORMAT_ERROR = 'Error Format';
|
||||||
const SETTING_FORMAT_USAGEINFO = 'UsageInfo Format';
|
const SETTING_FORMAT_USAGEINFO = 'UsageInfo Format';
|
||||||
|
const CHAT_BUFFER_SIZE = 200;
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
|
private $chatBuffer = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct chat utility
|
* Construct chat utility
|
||||||
@ -43,6 +49,15 @@ class Chat {
|
|||||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_FORMAT_SUCCESS, '$0f0');
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_FORMAT_SUCCESS, '$0f0');
|
||||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_FORMAT_ERROR, '$f30');
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_FORMAT_ERROR, '$f30');
|
||||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_FORMAT_USAGEINFO, '$f80');
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_FORMAT_USAGEINFO, '$f80');
|
||||||
|
|
||||||
|
//Callbacks
|
||||||
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERCHAT, $this, 'onPlayerChat');
|
||||||
|
|
||||||
|
//Socket Listenings
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::SEND_CHAT_MESSAGE, $this, "communcationSendChat");
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GET_SERVER_CHAT, $this, function ($data) {
|
||||||
|
return new CommunicationAnswer($this->chatBuffer);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,4 +241,92 @@ class Chat {
|
|||||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_USAGEINFO);
|
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_USAGEINFO);
|
||||||
return $this->sendChat($format . $message, $login, $prefix);
|
return $this->sendChat($format . $message, $login, $prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles SendChat Communication Request
|
||||||
|
*
|
||||||
|
* @param $data
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function communcationSendChat($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "message")) {
|
||||||
|
return new CommunicationAnswer("You have to provide a valid message", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$prefix = true;
|
||||||
|
if (property_exists($data, "prefix")) {
|
||||||
|
$prefix = $data->prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
$login = null;
|
||||||
|
if (property_exists($data, "login")) {
|
||||||
|
$login = $data->login;
|
||||||
|
}
|
||||||
|
|
||||||
|
$adminLevel = 0;
|
||||||
|
if (property_exists($data, "adminLevel")) {
|
||||||
|
$adminLevel = $data->adminLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
$type = "default";
|
||||||
|
if (property_exists($data, "type")) {
|
||||||
|
$type = $data->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ($type) {
|
||||||
|
case "information":
|
||||||
|
if ($adminLevel) {
|
||||||
|
$this->sendInformationToAdmins($data->message, $adminLevel, $prefix);
|
||||||
|
} else {
|
||||||
|
$this->sendInformation($data->message, $login, $prefix);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "success":
|
||||||
|
if ($adminLevel) {
|
||||||
|
$this->sendInformationToAdmins($data->message, $adminLevel, $prefix);
|
||||||
|
} else {
|
||||||
|
$this->sendSuccess($data->message, $login, $prefix);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "error":
|
||||||
|
if ($adminLevel) {
|
||||||
|
$this->sendErrorToAdmins($data->message, $adminLevel, $prefix);
|
||||||
|
} else {
|
||||||
|
$this->sendError($data->message, $login, $prefix);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "usage":
|
||||||
|
$this->sendUsageInfo($data->message, $login, $prefix);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if ($adminLevel) {
|
||||||
|
$this->sendMessageToAdmins($data->message, $adminLevel, $prefix);
|
||||||
|
} else {
|
||||||
|
$this->sendChat($data->message, $login, $prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommunicationAnswer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the ChatMessage in the Buffer
|
||||||
|
*
|
||||||
|
* @param $data
|
||||||
|
*/
|
||||||
|
public function onPlayerChat($data) {
|
||||||
|
$login = $data[1][1];
|
||||||
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||||
|
|
||||||
|
$nickname = "";
|
||||||
|
if ($player) {
|
||||||
|
$nickname = $player->nickname;
|
||||||
|
}
|
||||||
|
array_push($this->chatBuffer, array("user" => $login, "nickname" => $nickname, "message" => $data[1][2]));
|
||||||
|
if (count($this->chatBuffer) > self::CHAT_BUFFER_SIZE) {
|
||||||
|
array_shift($this->chatBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,14 @@ use ManiaControl\Players\Player;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class HelpManager implements CommandListener, CallbackListener {
|
class HelpManager implements CommandListener, CallbackListener {
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
private $playerCommands = array();
|
private $playerCommands = array();
|
||||||
private $adminCommands = array();
|
private $adminCommands = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new Commands Manager
|
* Construct a new Commands Manager
|
||||||
@ -58,14 +57,14 @@ class HelpManager implements CommandListener, CallbackListener {
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function command_adminHelp(array $chatCallback, Player $player) {
|
public function command_adminHelp(array $chatCallback, Player $player) {
|
||||||
// Parse list from array
|
// Parse list from array
|
||||||
$message = $this->parseHelpList($this->adminCommands);
|
$message = $this->parseHelpList($this->adminCommands);
|
||||||
|
|
||||||
// Show message when it's not empty
|
// Show message when it's not empty
|
||||||
if($message != NULL){
|
if ($message != null) {
|
||||||
$message = 'Supported Admin Commands: ' . $message;
|
$message = 'Supported Admin Commands: ' . $message;
|
||||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,14 +74,14 @@ class HelpManager implements CommandListener, CallbackListener {
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function command_playerHelp(array $chatCallback, Player $player) {
|
public function command_playerHelp(array $chatCallback, Player $player) {
|
||||||
// Parse list from array
|
// Parse list from array
|
||||||
$message = $this->parseHelpList($this->playerCommands);
|
$message = $this->parseHelpList($this->playerCommands);
|
||||||
|
|
||||||
// Show message when it's not empty
|
// Show message when it's not empty
|
||||||
if($message != NULL){
|
if ($message != null) {
|
||||||
$message = 'Supported Player Commands: ' . $message;
|
$message = 'Supported Player Commands: ' . $message;
|
||||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,23 +91,24 @@ class HelpManager implements CommandListener, CallbackListener {
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function command_playerHelpAll(array $chatCallback, Player $player) {
|
public function command_playerHelpAll(array $chatCallback, Player $player) {
|
||||||
$this->parseHelpList($this->playerCommands, true, $player);
|
$this->parseHelpList($this->playerCommands, true, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse list with commands from array
|
* Parse list with commands from array
|
||||||
* @param array $commands
|
*
|
||||||
* @param bool $isHelpAll
|
* @param array $commands
|
||||||
* @param Player $player
|
* @param bool $isHelpAll
|
||||||
* @return string|void
|
* @param Player $player
|
||||||
*/
|
* @return string|void
|
||||||
|
*/
|
||||||
private function parseHelpList(array $commands, $isHelpAll = false, Player $player = null) {
|
private function parseHelpList(array $commands, $isHelpAll = false, Player $player = null) {
|
||||||
$showCommands = array();
|
$showCommands = array();
|
||||||
$registeredMethods = array();
|
$registeredMethods = array();
|
||||||
$message = '';
|
$message = '';
|
||||||
foreach (array_reverse($commands) as $command) {
|
foreach (array_reverse($commands) as $command) {
|
||||||
if (array_key_exists($command['Method'], $registeredMethods)) {
|
if (array_key_exists($command['Method'], $registeredMethods)) {
|
||||||
if($showCommands[$registeredMethods[$command['Method']]]['Description'] === $command['Description']) {
|
if ($showCommands[$registeredMethods[$command['Method']]]['Description'] === $command['Description']) {
|
||||||
$name = $registeredMethods[$command['Method']];
|
$name = $registeredMethods[$command['Method']];
|
||||||
$showCommands[$name]['Name'] .= '|' . $command['Name'];
|
$showCommands[$name]['Name'] .= '|' . $command['Name'];
|
||||||
} else {
|
} else {
|
||||||
@ -125,20 +125,17 @@ class HelpManager implements CommandListener, CallbackListener {
|
|||||||
return strcmp($commandA['Name'], $commandB['Name']);
|
return strcmp($commandA['Name'], $commandB['Name']);
|
||||||
});
|
});
|
||||||
|
|
||||||
if(!$isHelpAll){
|
if (!$isHelpAll) {
|
||||||
foreach ($showCommands as $command) {
|
foreach ($showCommands as $command) {
|
||||||
$message .= $command['Name'] . ',';
|
$message .= $command['Name'] . ',';
|
||||||
}
|
}
|
||||||
$message = substr($message, 0, -1);
|
$message = substr($message, 0, -1);
|
||||||
|
} else {
|
||||||
return $message;
|
if ($player != null) {
|
||||||
}else{
|
|
||||||
if($player != NULL){
|
|
||||||
$this->showHelpAllList($showCommands, $player);
|
$this->showHelpAllList($showCommands, $player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return $message;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -221,7 +218,7 @@ class HelpManager implements CommandListener, CallbackListener {
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function command_adminHelpAll(array $chatCallback, Player $player) {
|
public function command_adminHelpAll(array $chatCallback, Player $player) {
|
||||||
$this->parseHelpList($this->adminCommands, true, $player);
|
$this->parseHelpList($this->adminCommands, true, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
107
core/Communication/Communication.php
Normal file
107
core/Communication/Communication.php
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ManiaControl\Communication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for Communicating with other ManiaControls
|
||||||
|
* to call @see ManiaControl\Communication\CommunicationManager\createCommunication
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
class Communication {
|
||||||
|
private $socket;
|
||||||
|
private $ip;
|
||||||
|
private $port;
|
||||||
|
private $encryptionPassword;
|
||||||
|
|
||||||
|
private $buffer = "";
|
||||||
|
private $messageQueue = array();
|
||||||
|
|
||||||
|
public function __construct($ip, $port, $encryptionPassword) {
|
||||||
|
$this->ip = $ip;
|
||||||
|
$this->port = $port;
|
||||||
|
$this->encryptionPassword = $encryptionPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Create an Connection */
|
||||||
|
public function createConnection() {
|
||||||
|
$errno = null;
|
||||||
|
$errstr = null;
|
||||||
|
$this->socket = @fsockopen($this->ip, $this->port, $errno, $errstr, 2);
|
||||||
|
|
||||||
|
//socket_set_nonblock($this->socket);
|
||||||
|
stream_set_blocking($this->socket, 0);
|
||||||
|
|
||||||
|
if ($errno != 0 || !$this->socket) {
|
||||||
|
var_dump($errstr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call an Method Asynchronously
|
||||||
|
*
|
||||||
|
* @param callable $function
|
||||||
|
* @param $method
|
||||||
|
* @param string $data
|
||||||
|
*/
|
||||||
|
public function call(callable $function, $method, $data = "") {
|
||||||
|
if (!$this->socket) {
|
||||||
|
call_user_func($function, true, "You need to create an Communication before using it");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = json_encode(array("method" => $method, "data" => $data));
|
||||||
|
|
||||||
|
$data = openssl_encrypt($data, CommunicationManager::ENCRYPTION_METHOD, $this->encryptionPassword, OPENSSL_RAW_DATA, CommunicationManager::ENCRYPTION_IV);
|
||||||
|
|
||||||
|
array_push($this->messageQueue, $function);
|
||||||
|
|
||||||
|
// Write Request on Socket
|
||||||
|
fwrite($this->socket, strlen($data) . "\n" . $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process data on every Tick
|
||||||
|
*/
|
||||||
|
public function tick() {
|
||||||
|
//Check if the connection is enabled
|
||||||
|
if (!$this->socket) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = fgets($this->socket, 1024); // reads as much as possible OR nothing at all
|
||||||
|
if (strlen($data) > 0) { // got new data
|
||||||
|
$this->buffer .= $data; // append new data to buffer
|
||||||
|
// handle the data the exact same way
|
||||||
|
$arr = explode("\n", $this->buffer, 2);
|
||||||
|
while (count($arr) == 2 && strlen($arr[1]) >= (int) $arr[0]) {
|
||||||
|
// received full message
|
||||||
|
$len = (int) $arr[0];
|
||||||
|
$msg = substr($arr[1], 0, $len); // clip msg
|
||||||
|
$this->buffer = substr($this->buffer, strlen((string) $len) + 1 /* newline */ + $len); // clip buffer
|
||||||
|
|
||||||
|
// Decode Message
|
||||||
|
$data = openssl_decrypt($msg, CommunicationManager::ENCRYPTION_METHOD, $this->encryptionPassword, OPENSSL_RAW_DATA, CommunicationManager::ENCRYPTION_IV);
|
||||||
|
$data = json_decode($data);
|
||||||
|
|
||||||
|
// Received something!
|
||||||
|
//Call Function with Data
|
||||||
|
call_user_func(array_shift($this->messageQueue), $data->error, $data->data);
|
||||||
|
|
||||||
|
// next msg
|
||||||
|
$arr = explode("\n", $this->buffer, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Closes the connection, don't call yourself, let it do the Communication Manager */
|
||||||
|
public function closeConnection() {
|
||||||
|
if ($this->socket) {
|
||||||
|
fclose($this->socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
core/Communication/CommunicationAnswer.php
Normal file
25
core/Communication/CommunicationAnswer.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ManiaControl\Communication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for Answer of Communication Request
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
class CommunicationAnswer {
|
||||||
|
/** Properties are Public for serialization */
|
||||||
|
public $error;
|
||||||
|
public $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $data
|
||||||
|
* @param bool $error
|
||||||
|
*/
|
||||||
|
public function __construct($data = "", $error = false) {
|
||||||
|
$this->data = $data;
|
||||||
|
$this->error = $error;
|
||||||
|
}
|
||||||
|
}
|
13
core/Communication/CommunicationListener.php
Normal file
13
core/Communication/CommunicationListener.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ManiaControl\Communication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for SocketListener
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
interface CommunicationListener {
|
||||||
|
}
|
311
core/Communication/CommunicationManager.php
Normal file
311
core/Communication/CommunicationManager.php
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
<?php
|
||||||
|
namespace ManiaControl\Communication;
|
||||||
|
|
||||||
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
|
use ManiaControl\Callbacks\Listening;
|
||||||
|
use ManiaControl\Logger;
|
||||||
|
use ManiaControl\ManiaControl;
|
||||||
|
use ManiaControl\Settings\Setting;
|
||||||
|
use ManiaControl\Settings\SettingManager;
|
||||||
|
use React\EventLoop\Factory;
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
use React\Socket\Connection;
|
||||||
|
use React\Socket\ConnectionException;
|
||||||
|
use React\Socket\Server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class for managing Socket Callbacks
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
class CommunicationManager implements CallbackListener {
|
||||||
|
/** Constants */
|
||||||
|
const SETTING_SOCKET_ENABLED = "Activate Socket";
|
||||||
|
const SETTING_SOCKET_PASSWORD = "Password for the Socket Connection";
|
||||||
|
const SETTING_SOCKET_PORT = "Socket Port for Server ";
|
||||||
|
|
||||||
|
const ENCRYPTION_IV = "kZ2Kt0CzKUjN2MJX";
|
||||||
|
const ENCRYPTION_METHOD = "aes-192-cbc";
|
||||||
|
|
||||||
|
/** @var ManiaControl $maniaControl */
|
||||||
|
private $maniaControl = null;
|
||||||
|
|
||||||
|
/** @var LoopInterface $loop */
|
||||||
|
private $loop = null;
|
||||||
|
|
||||||
|
/** @var Listening[] $communicationListenings */
|
||||||
|
private $communicationListenings = array();
|
||||||
|
|
||||||
|
/** @var Server $socket */
|
||||||
|
private $socket = null;
|
||||||
|
/** @var Communication[] $communcations */
|
||||||
|
private $communications = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Communication Handler Instance
|
||||||
|
*
|
||||||
|
* @param ManiaControl $maniaControl
|
||||||
|
*/
|
||||||
|
public function __construct(ManiaControl $maniaControl) {
|
||||||
|
$this->maniaControl = $maniaControl;
|
||||||
|
|
||||||
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(SettingManager::CB_SETTING_CHANGED, $this, 'updateSettings');
|
||||||
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'initCommunicationManager');
|
||||||
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONRESTART, $this, 'onShutDown');
|
||||||
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONSHUTDOWN, $this, 'onShutDown');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a Communication to another ManiaControl
|
||||||
|
*
|
||||||
|
* @param $ip
|
||||||
|
* @param $port
|
||||||
|
* @return \ManiaControl\Communication\Communication
|
||||||
|
*/
|
||||||
|
public function createCommunication($ip, $port, $encryptionKey) {
|
||||||
|
$communication = new Communication($ip, $port, $encryptionKey);
|
||||||
|
$communication->createConnection();
|
||||||
|
|
||||||
|
$this->communications[] = $communication;
|
||||||
|
return $communication;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes a opened Communication
|
||||||
|
* Does not necessarily need be called, all connections get destroyed on ManiaControl Shutdown
|
||||||
|
*
|
||||||
|
* @param Communication $communication
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function closeCommunication($communication) {
|
||||||
|
$key = array_search($communication, $this->communications);
|
||||||
|
if (isset($this->communications[$key])) {
|
||||||
|
$this->communications[$key]->closeConnection();
|
||||||
|
unset($this->communications[$key]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Close all Sockets on maniaControl Shutdown */
|
||||||
|
public function onShutDown() {
|
||||||
|
if ($this->socket && $this->socket->master) {
|
||||||
|
//Stop the Socket Listening
|
||||||
|
$this->socket->shutdown();
|
||||||
|
$this->socket = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->communications as $communication) {
|
||||||
|
$this->closeCommunication($communication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new Communication Listener
|
||||||
|
*
|
||||||
|
* @param string $callbackName
|
||||||
|
* @param CommunicationListener $listener
|
||||||
|
* @param string $method
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function registerCommunicationListener($echoName, CommunicationListener $listener, $method) {
|
||||||
|
if (!Listening::checkValidCallback($listener, $method)) {
|
||||||
|
$listenerClass = get_class($listener);
|
||||||
|
trigger_error("Given Listener '{$listenerClass}' can't handle Callback '{$echoName}': No callable Method '{$method}'!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!array_key_exists($echoName, $this->communicationListenings)) {
|
||||||
|
$this->communicationListenings[$echoName] = new Listening($listener, $method);
|
||||||
|
} else {
|
||||||
|
//TODO say which is already listening and other stuff
|
||||||
|
trigger_error("Only one Listener can listen on a specific Communication Message");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger a specific Callback
|
||||||
|
*
|
||||||
|
* @param mixed $callback
|
||||||
|
*/
|
||||||
|
public function triggerCommuncationCallback($callbackName) {
|
||||||
|
if (!array_key_exists($callbackName, $this->communicationListenings)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$params = func_get_args();
|
||||||
|
$params = array_slice($params, 1, null, true);
|
||||||
|
|
||||||
|
$listening = $this->communicationListenings[$callbackName];
|
||||||
|
/** @var Listening $listening */
|
||||||
|
return $listening->triggerCallbackWithParams($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a Communication Listener
|
||||||
|
*
|
||||||
|
* @param CommunicationListener $listener
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function unregisterCommunicationListener(CommunicationListener $listener) {
|
||||||
|
return $this->removeCommunicationListener($this->communicationListenings, $listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the Communication Listener from the given Listeners Array
|
||||||
|
*
|
||||||
|
* @param Listening[] $listeningsArray
|
||||||
|
* @param CommunicationListener $listener
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function removeCommunicationListener(array &$listeningsArray, CommunicationListener $listener) {
|
||||||
|
$removed = false;
|
||||||
|
foreach ($listeningsArray as &$listening) {
|
||||||
|
if ($listening->listener === $listener) {
|
||||||
|
unset($listening);
|
||||||
|
$removed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $removed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inits the Communication Manager after ManiaControl Startup
|
||||||
|
*/
|
||||||
|
public function initCommunicationManager() {
|
||||||
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_SOCKET_ENABLED, false);
|
||||||
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_SOCKET_PASSWORD, "");
|
||||||
|
|
||||||
|
$servers = $this->maniaControl->getServer()->getAllServers();
|
||||||
|
foreach ($servers as $server) {
|
||||||
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_SOCKET_PORT . $server->login, 31500 + $server->index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->createListeningSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update Setting
|
||||||
|
*
|
||||||
|
* @param Setting $setting
|
||||||
|
*/
|
||||||
|
public function updateSettings(Setting $setting) {
|
||||||
|
if (!$setting->belongsToClass($this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$socketEnabled = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_SOCKET_ENABLED);
|
||||||
|
|
||||||
|
if ($socketEnabled && !$this->socket) {
|
||||||
|
$this->createListeningSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$socketEnabled) {
|
||||||
|
$this->socket = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates The Socket
|
||||||
|
*/
|
||||||
|
private function createListeningSocket() {
|
||||||
|
$socketEnabled = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_SOCKET_ENABLED);
|
||||||
|
if ($socketEnabled) {
|
||||||
|
|
||||||
|
Logger::log("[CommunicationManager] Trying to create Socket");
|
||||||
|
|
||||||
|
// Check for MySQLi
|
||||||
|
$message = '[CommunicationManager] Checking for installed openssl ... ';
|
||||||
|
if (!extension_loaded('openssl')) {
|
||||||
|
Logger::log($message . 'NOT FOUND!');
|
||||||
|
Logger::log(" -- You don't have openssl installed! Check: http://www.php.net/manual/en/openssl.installation.php");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
Logger::log($message . 'FOUND!');
|
||||||
|
}
|
||||||
|
|
||||||
|
$serverLogin = $this->maniaControl->getServer()->login;
|
||||||
|
$socketPort = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_SOCKET_PORT . $serverLogin);
|
||||||
|
$password = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_SOCKET_PASSWORD);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->loop = Factory::create();
|
||||||
|
$this->socket = new Server($this->loop);
|
||||||
|
|
||||||
|
$this->socket->on('error', function ($e) {
|
||||||
|
Logger::log("[CommunicationManager] Socket Error" . $e);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->socket->on('connection', function (Connection $connection) use ($password) {
|
||||||
|
$buffer = '';
|
||||||
|
$connection->on('data', function ($data) use (&$buffer, &$connection, $password) {
|
||||||
|
$buffer .= $data;
|
||||||
|
$arr = explode("\n", $buffer, 2);
|
||||||
|
while (count($arr) == 2 && strlen($arr[1]) >= (int) $arr[0]) {
|
||||||
|
// received full message
|
||||||
|
$len = (int) $arr[0];
|
||||||
|
$msg = substr($arr[1], 0, $len); // clip msg
|
||||||
|
$buffer = substr($buffer, strlen((string) $len) + 1 /* newline */ + $len); // clip buffer
|
||||||
|
|
||||||
|
// Decode Message
|
||||||
|
$data = openssl_decrypt($msg, self::ENCRYPTION_METHOD, $password, OPENSSL_RAW_DATA, self::ENCRYPTION_IV);
|
||||||
|
$data = json_decode($data);
|
||||||
|
|
||||||
|
if ($data == null) {
|
||||||
|
$data = array("error" => true, "data" => "Data is not provided as an valid AES-196-encrypted encrypted JSON");
|
||||||
|
} else if (!property_exists($data, "method") || !property_exists($data, "data")) {
|
||||||
|
$data = array("error" => true, "data" => "Invalid Message");
|
||||||
|
} else {
|
||||||
|
$answer = $this->triggerCommuncationCallback($data->method, $data->data);
|
||||||
|
//Prepare Response
|
||||||
|
if (!$answer) {
|
||||||
|
$data = new CommunicationAnswer("No listener or response on the given Message", true);
|
||||||
|
} else {
|
||||||
|
$data = $answer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Encode, Encrypt and Send Response
|
||||||
|
$data = json_encode($data);
|
||||||
|
|
||||||
|
$data = openssl_encrypt($data, self::ENCRYPTION_METHOD, $password, OPENSSL_RAW_DATA, self::ENCRYPTION_IV);
|
||||||
|
$connection->write(strlen($data) . "\n" . $data);
|
||||||
|
|
||||||
|
// next msg
|
||||||
|
$arr = explode("\n", $buffer, 2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
//TODO check if port is closed
|
||||||
|
$this->socket->listen($socketPort, $this->maniaControl->getServer()->ip);
|
||||||
|
|
||||||
|
Logger::log("[CommunicationManager] Socket " . $this->maniaControl->getServer()->ip . ":" . $this->socket->getPort() . " Successfully created!");
|
||||||
|
} catch (ConnectionException $e) {
|
||||||
|
Logger::log("[CommunicationManager] Exception: " . $e->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes Data on every ManiaControl Tick, don't call this Method
|
||||||
|
*/
|
||||||
|
public function tick() {
|
||||||
|
if ($this->loop) {
|
||||||
|
$this->loop->tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->communications as $communication) {
|
||||||
|
$communication->tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
173
core/Communication/CommunicationMethods.php
Normal file
173
core/Communication/CommunicationMethods.php
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ManiaControl\Communication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Communication Methods Interface
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
interface CommunicationMethods {
|
||||||
|
/** Restarts Mania Control
|
||||||
|
* Optional Params
|
||||||
|
* - message
|
||||||
|
*/
|
||||||
|
const RESTART_MANIA_CONTROL = "ManiaControl.Restart";
|
||||||
|
|
||||||
|
/** Grands an Authentication Level on a Player
|
||||||
|
* Required Parameters
|
||||||
|
* - login (login of the player)
|
||||||
|
* - level (integer, 0-3 possible, @see AuthenticationManager)
|
||||||
|
*/
|
||||||
|
const GRANT_AUTH_LEVEL = "AuthenticationManager.GrandLevel";
|
||||||
|
|
||||||
|
/** Revokes an Authentication Level on a Player
|
||||||
|
* Required Parameters
|
||||||
|
* - login (login of the player)
|
||||||
|
*/
|
||||||
|
const REVOKE_AUTH_LEVEL = "AuthenticationManager.RevokeLevel";
|
||||||
|
|
||||||
|
/** Provides the Server Options
|
||||||
|
* no Parameters
|
||||||
|
*/
|
||||||
|
const GET_SERVER_OPTIONS = "ServerOptions.GetServerOptions";
|
||||||
|
|
||||||
|
/** Set Server Options
|
||||||
|
* Required Parameter
|
||||||
|
* - scriptSettings (array(optionName1 => value1, optionName2 => value2...))
|
||||||
|
*/
|
||||||
|
const SET_SERVER_OPTIONS = "ServerOptions.SetServerOptions";
|
||||||
|
|
||||||
|
/** Provides the ModeScriptSettings
|
||||||
|
* no Parameters
|
||||||
|
*/
|
||||||
|
const GET_SCRIPT_SETTINGS = "ScriptSettings.GetScriptSettings";
|
||||||
|
|
||||||
|
/** Set ModeScriptSettings
|
||||||
|
* Required Parameter
|
||||||
|
* - scriptSettings (array(settingName1 => value1, settingName2 => value2...))
|
||||||
|
*/
|
||||||
|
const SET_SCRIPT_SETTINGS = "ScriptSettings.SetScriptSettings";
|
||||||
|
|
||||||
|
/** Restarts the Current Map
|
||||||
|
* no Parameters
|
||||||
|
*/
|
||||||
|
const RESTART_MAP = "MapActions.RestartMap";
|
||||||
|
|
||||||
|
/** Skips the Current Map
|
||||||
|
* no Parameters
|
||||||
|
*/
|
||||||
|
const SKIP_MAP = "MapActions.SkipMap";
|
||||||
|
|
||||||
|
/** Skips to a Specific Map by MxId or MapUid
|
||||||
|
* Required Parameters
|
||||||
|
* - mxId (integer)
|
||||||
|
* OR
|
||||||
|
* - mapUid (string)
|
||||||
|
*/
|
||||||
|
const SKIP_TO_MAP = "MapActions.SkipToMap";
|
||||||
|
|
||||||
|
/** Adds a Map from Mania Exchange to the Server
|
||||||
|
* Required Parameters
|
||||||
|
* - mxId (integer)
|
||||||
|
* (no success returning yet because of asynchronously of adding)
|
||||||
|
*/
|
||||||
|
const ADD_MAP = "MapManager.AddMap";
|
||||||
|
|
||||||
|
/** Removes a Map from the Server
|
||||||
|
* Required Parameters
|
||||||
|
* - mapUid (string)
|
||||||
|
* Optional Parameters
|
||||||
|
* - displayMessage (default true)
|
||||||
|
* - eraseMapFile (default false)
|
||||||
|
*/
|
||||||
|
const REMOVE_MAP = "MapManager.RemoveMap";
|
||||||
|
|
||||||
|
/** Updates a Map over Mania Exchange
|
||||||
|
* Required Parameters
|
||||||
|
* - mapUid
|
||||||
|
* (no success returning yet because of asynchronously of adding)
|
||||||
|
*/
|
||||||
|
const UPDATE_MAP = "MapManager.UpdateMap";
|
||||||
|
|
||||||
|
/** Gets the current Map
|
||||||
|
* Required Parameters
|
||||||
|
* - mxId (integer)
|
||||||
|
* OR
|
||||||
|
* - mapUid (string)
|
||||||
|
*/
|
||||||
|
const GET_CURRENT_MAP = "MapManager.GetCurrentMap";
|
||||||
|
|
||||||
|
/** Gets the specific Map
|
||||||
|
* no Parameters
|
||||||
|
*/
|
||||||
|
const GET_MAP = "MapManager.GetMap";
|
||||||
|
|
||||||
|
/** Gets the current Map List
|
||||||
|
* no Parameters
|
||||||
|
*/
|
||||||
|
const GET_MAP_LIST = "MapManager.GetMapList";
|
||||||
|
|
||||||
|
/** Gets Mania Control PlayerList
|
||||||
|
* no Parameters
|
||||||
|
*/
|
||||||
|
const GET_PLAYER_LIST = "PlayerManager.GetPlayerList";
|
||||||
|
|
||||||
|
/** Warns a Player
|
||||||
|
* Required Params
|
||||||
|
* - login
|
||||||
|
*/
|
||||||
|
const WARN_PLAYER = "PlayerActions.WarnPlayer";
|
||||||
|
|
||||||
|
/** Mutes a Player
|
||||||
|
* Required Params
|
||||||
|
* - login
|
||||||
|
*/
|
||||||
|
const MUTE_PLAYER = "PlayerActions.MutePlayer";
|
||||||
|
|
||||||
|
/** UnMutes a Player
|
||||||
|
* Required Params
|
||||||
|
* - login
|
||||||
|
*/
|
||||||
|
const UNMUTE_PLAYER = "PlayerActions.UnMutePlayer";
|
||||||
|
|
||||||
|
/** UnMutes a Player
|
||||||
|
* Required Params
|
||||||
|
* - login
|
||||||
|
* Optional Params
|
||||||
|
* - message
|
||||||
|
*/
|
||||||
|
const KICK_PLAYER = "PlayerActions.KickPlayer";
|
||||||
|
|
||||||
|
/** Forces a player to Spectator
|
||||||
|
* Required Params
|
||||||
|
* - login
|
||||||
|
*/
|
||||||
|
const FORCE_PLAYER_TO_SPEC = "PlayerActions.ForcePlayerToSpec";
|
||||||
|
|
||||||
|
/** Forces a player to Spectator
|
||||||
|
* Required Params
|
||||||
|
* - login
|
||||||
|
* Optional Params
|
||||||
|
* - teamId (integer, id of the team the player should get forced into it)
|
||||||
|
*/
|
||||||
|
const FORCE_PLAYER_TO_PLAY = "PlayerActions.ForcePlayerToPlay";
|
||||||
|
|
||||||
|
/** Returns the last 200 lines of the chat (inclusive player logins and nicknames)
|
||||||
|
* No Params
|
||||||
|
*/
|
||||||
|
const GET_SERVER_CHAT = "Chat.GetServerChat";
|
||||||
|
|
||||||
|
/** Sends a ChatMessage to the Server
|
||||||
|
* Required Params:
|
||||||
|
* - message
|
||||||
|
* Optional Params
|
||||||
|
* - prefix (use custom prefix or false for no prefix)
|
||||||
|
* - login (login of a receiver if the message don't get sent to all)
|
||||||
|
* - adminLevel (minimum Admin Level if the Message should get sent to an Admin)
|
||||||
|
* - type (type of the message (information, error, success or usage)
|
||||||
|
*/
|
||||||
|
const SEND_CHAT_MESSAGE = "Chat.SendChatMessage";
|
||||||
|
}
|
53
core/Communication/usage_documentation.txt
Normal file
53
core/Communication/usage_documentation.txt
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
The CommuncationListening of the Communcation Manager can be enabled in the ingame Settings.
|
||||||
|
|
||||||
|
There the following settings are existing:
|
||||||
|
-- Enable Socket Listening (Let the CommunicationManager listen for incoming calls)
|
||||||
|
-- Passsword (Password which get used to encrypt and decrypt the messages for the openssl connection)
|
||||||
|
-- Listening port for every server (this is the port the CommunicationManager listens at)
|
||||||
|
|
||||||
|
|
||||||
|
For the description of the available implemented communcation Methods check the CommunicationMethods interface.
|
||||||
|
|
||||||
|
If you need methods which are not implemented, or additional Parameters, feel free to contact us.
|
||||||
|
|
||||||
|
Sample ManiaControl Implementation (for ManiaControl to ManiaControl connections)
|
||||||
|
|
||||||
|
##php code begin
|
||||||
|
$communication = $this->maniaControl->getCommunicationManager()->createCommunication(IP/Domain, PORT, 'YOUR_PASSWORD');
|
||||||
|
$communication->call(function($data){
|
||||||
|
var_dump($data);
|
||||||
|
}, CommunicationMethods::GET_SERVER_CHAT);
|
||||||
|
##php code end
|
||||||
|
|
||||||
|
Sample Web Implementation (to call ManiaControl from a website)
|
||||||
|
##php code begin
|
||||||
|
$errno = null;
|
||||||
|
$errstr = null;
|
||||||
|
$socket = fsockopen("xx.xxx.xx.xx", xxxxx, $errno, $errstr, 2);
|
||||||
|
echo "ok?" . $errno . " - " . $errstr . "\n";
|
||||||
|
|
||||||
|
$data = array("method" => "getServerChat", "data" => "");
|
||||||
|
|
||||||
|
// Encode and Encrypt the Data
|
||||||
|
$data = json_encode(array("method" => "getServerChat", "data" => ""));
|
||||||
|
$data = openssl_encrypt($data, 'aes-192-cbc', 'YOUR_PASSWORD', OPENSSL_RAW_DATA, 'kZ2Kt0CzKUjN2MJX');
|
||||||
|
|
||||||
|
// Write the Data on the Socket
|
||||||
|
fwrite($socket, strlen($data) . "\n" . $data);
|
||||||
|
|
||||||
|
|
||||||
|
// Read Answer Data
|
||||||
|
$len = (int)fgets($socket);
|
||||||
|
echo $len;
|
||||||
|
$buff = '';
|
||||||
|
while (!feof($socket) && strlen($buff) < $len) {
|
||||||
|
$buff .= fgets($socket, $len - strlen($buff) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrypt and Decode the Response Data
|
||||||
|
$data = openssl_decrypt($buff, 'aes-192-cbc', 'YOUR_PASSWORD', OPENSSL_RAW_DATA, 'kZ2Kt0CzKUjN2MJX');
|
||||||
|
echo json_decode($data);
|
||||||
|
|
||||||
|
//Close the Socket
|
||||||
|
fclose($socket);
|
||||||
|
##php code end
|
@ -199,11 +199,11 @@ class Configurator implements CallbackListener, CommandListener, ManialinkPageAn
|
|||||||
|
|
||||||
$frame = new Frame();
|
$frame = new Frame();
|
||||||
$manialink->add($frame);
|
$manialink->add($frame);
|
||||||
$frame->setPosition($menuPosX, $menuPosY, 10);
|
$frame->setPosition($menuPosX, $menuPosY, 34);
|
||||||
|
|
||||||
$backgroundQuad = new Quad();
|
$backgroundQuad = new Quad();
|
||||||
$frame->add($backgroundQuad);
|
$frame->add($backgroundQuad);
|
||||||
$backgroundQuad->setZ(-10)->setSize($menuWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
$backgroundQuad->setZ(-2)->setSize($menuWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
||||||
|
|
||||||
$menuItemsFrame = new Frame();
|
$menuItemsFrame = new Frame();
|
||||||
$frame->add($menuItemsFrame);
|
$frame->add($menuItemsFrame);
|
||||||
@ -211,7 +211,7 @@ class Configurator implements CallbackListener, CommandListener, ManialinkPageAn
|
|||||||
|
|
||||||
$itemsBackgroundQuad = new Quad();
|
$itemsBackgroundQuad = new Quad();
|
||||||
$menuItemsFrame->add($itemsBackgroundQuad);
|
$menuItemsFrame->add($itemsBackgroundQuad);
|
||||||
$backgroundQuad->setZ(-9);
|
$backgroundQuad->setZ(-1);
|
||||||
$itemsBackgroundQuad->setSize($menuListWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
$itemsBackgroundQuad->setSize($menuListWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
||||||
|
|
||||||
$menusFrame = new Frame();
|
$menusFrame = new Frame();
|
||||||
|
@ -14,6 +14,9 @@ use FML\Script\Script;
|
|||||||
use ManiaControl\Admin\AuthenticationManager;
|
use ManiaControl\Admin\AuthenticationManager;
|
||||||
use ManiaControl\Callbacks\CallbackListener;
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
use ManiaControl\Callbacks\Callbacks;
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
@ -26,7 +29,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
class ScriptSettings implements ConfiguratorMenu, CallbackListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -61,6 +64,10 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
|||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_SCRIPT_SETTINGS, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_SCRIPT_SETTINGS, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||||
|
|
||||||
|
//TODO remove to somewhere cleaner
|
||||||
|
//Communication Listenings
|
||||||
|
$this->initalizeCommunicationListenings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,8 +156,7 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
|||||||
* Handle Begin Map Callback
|
* Handle Begin Map Callback
|
||||||
*/
|
*/
|
||||||
public function onBeginMap() {
|
public function onBeginMap() {
|
||||||
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_LOAD_DEFAULT_SETTINGS_MAP_BEGIN)
|
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_LOAD_DEFAULT_SETTINGS_MAP_BEGIN)) {
|
||||||
) {
|
|
||||||
$this->loadSettingsFromDatabase();
|
$this->loadSettingsFromDatabase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,8 +288,7 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
|||||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||||
*/
|
*/
|
||||||
public function saveConfigData(array $configData, Player $player) {
|
public function saveConfigData(array $configData, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SCRIPT_SETTINGS)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SCRIPT_SETTINGS)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -327,6 +332,7 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
|||||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the Array of new Script Settings
|
* Apply the Array of new Script Settings
|
||||||
*
|
*
|
||||||
@ -406,6 +412,63 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
|||||||
if (is_bool($value)) {
|
if (is_bool($value)) {
|
||||||
return ($value ? 'True' : 'False');
|
return ($value ? 'True' : 'False');
|
||||||
}
|
}
|
||||||
return (string)$value;
|
return (string) $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the communication Listenings
|
||||||
|
*/
|
||||||
|
private function initalizeCommunicationListenings() {
|
||||||
|
//Communication Listenings
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GET_SCRIPT_SETTINGS, $this, function ($data) {
|
||||||
|
try {
|
||||||
|
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||||||
|
} catch (GameModeException $e) {
|
||||||
|
return new CommunicationAnswer($e->getMessage(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommunicationAnswer($scriptSettings);
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::SET_SCRIPT_SETTINGS, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "scriptSettings")) {
|
||||||
|
return new CommunicationAnswer("No valid ScriptSettings provided!", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||||||
|
} catch (GameModeException $e) {
|
||||||
|
return new CommunicationAnswer($e->getMessage(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$newSettings = array();
|
||||||
|
foreach ($data->scriptSettings as $name => $value) {
|
||||||
|
if (!isset($scriptSettings[$name])) {
|
||||||
|
var_dump('no setting ' . $name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($value == $scriptSettings[$name]) {
|
||||||
|
// Not changed
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$newSettings[$name] = $value;
|
||||||
|
settype($newSettings[$name], gettype($scriptSettings[$name]));
|
||||||
|
}
|
||||||
|
|
||||||
|
//No new Settings
|
||||||
|
if (empty($newSettings)) {
|
||||||
|
return new CommunicationAnswer(array("success" => true));
|
||||||
|
}
|
||||||
|
|
||||||
|
//Trigger Scriptsettings Changed Callback
|
||||||
|
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SCRIPTSETTINGS_CHANGED);
|
||||||
|
|
||||||
|
//Set the Settings
|
||||||
|
$success = $this->maniaControl->getClient()->setModeScriptSettings($newSettings);
|
||||||
|
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
207
core/Files/AsyncHttpRequest.php
Normal file
207
core/Files/AsyncHttpRequest.php
Normal file
@ -0,0 +1,207 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ManiaControl\Files;
|
||||||
|
|
||||||
|
use cURL\Event;
|
||||||
|
use cURL\Request;
|
||||||
|
use ManiaControl\ManiaControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous Http Request Class
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
class AsyncHttpRequest {
|
||||||
|
/*
|
||||||
|
* Constants
|
||||||
|
*/
|
||||||
|
const CONTENT_TYPE_JSON = 'application/json';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Private properties
|
||||||
|
*/
|
||||||
|
/** @var ManiaControl $maniaControl */
|
||||||
|
private $maniaControl;
|
||||||
|
|
||||||
|
private $url;
|
||||||
|
private $function;
|
||||||
|
private $content;
|
||||||
|
private $compression = false;
|
||||||
|
private $contentType = 'text/xml; charset=UTF-8;';
|
||||||
|
private $headers = array();
|
||||||
|
|
||||||
|
public function __construct($maniaControl, $url) {
|
||||||
|
$this->maniaControl = $maniaControl;
|
||||||
|
$this->url = $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new cURL Request for the given URL
|
||||||
|
*
|
||||||
|
* @param string $url
|
||||||
|
* @return Request
|
||||||
|
*/
|
||||||
|
private function newRequest($url) {
|
||||||
|
$request = new Request($url);
|
||||||
|
$request->getOptions()->set(CURLOPT_TIMEOUT, 60)->set(CURLOPT_HEADER, false)// don't display response header
|
||||||
|
->set(CURLOPT_CRLF, true)// linux line feed
|
||||||
|
->set(CURLOPT_ENCODING, '')// accept encoding
|
||||||
|
->set(CURLOPT_USERAGENT, 'ManiaControl v' . ManiaControl::VERSION)// user-agent
|
||||||
|
->set(CURLOPT_RETURNTRANSFER, true)//
|
||||||
|
->set(CURLOPT_FOLLOWLOCATION, true)// support redirect
|
||||||
|
->set(CURLOPT_SSL_VERIFYPEER, false);
|
||||||
|
return $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Carry out a GetData Request
|
||||||
|
*
|
||||||
|
* @param int $keepAlive
|
||||||
|
*/
|
||||||
|
public function getData($keepAlive = 0) {
|
||||||
|
array_push($this->headers, 'Content-Type: ' . $this->contentType);
|
||||||
|
if ($keepAlive) {
|
||||||
|
array_push($this->headers, 'Keep-Alive: ' . $keepAlive);
|
||||||
|
array_push($this->headers, 'Connection: Keep-Alive');
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = $this->newRequest($this->url);
|
||||||
|
$request->getOptions()->set(CURLOPT_AUTOREFERER, true)// accept link reference
|
||||||
|
->set(CURLOPT_HTTPHEADER, $this->headers); // headers
|
||||||
|
|
||||||
|
$this->processRequest($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Carry out a PostData Request
|
||||||
|
*/
|
||||||
|
public function postData() {
|
||||||
|
array_push($this->headers, 'Content-Type: ' . $this->contentType);
|
||||||
|
array_push($this->headers, 'Keep-Alive: timeout=600, max=2000');
|
||||||
|
array_push($this->headers, 'Connection: Keep-Alive');
|
||||||
|
|
||||||
|
$content = str_replace(array("\r", "\n"), '', $this->content);
|
||||||
|
if ($this->compression) {
|
||||||
|
$content = zlib_encode($content, 31);
|
||||||
|
array_push($this->headers, 'Content-Encoding: gzip');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$request = $this->newRequest($this->url);
|
||||||
|
$request->getOptions()->set(CURLOPT_POST, true)// post method
|
||||||
|
->set(CURLOPT_POSTFIELDS, $content)// post content field
|
||||||
|
->set(CURLOPT_HTTPHEADER, $this->headers) // headers
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->processRequest($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes the Request
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
*/
|
||||||
|
private function processRequest(Request $request) {
|
||||||
|
$request->addListener('complete', function (Event $event) {
|
||||||
|
$error = null;
|
||||||
|
$content = null;
|
||||||
|
if ($event->response->hasError()) {
|
||||||
|
$error = $event->response->getError()->getMessage();
|
||||||
|
} else {
|
||||||
|
$content = $event->response->getContent();
|
||||||
|
}
|
||||||
|
call_user_func($this->function, $content, $error);
|
||||||
|
});
|
||||||
|
|
||||||
|
$fileReader = $this->maniaControl->getFileReader();
|
||||||
|
$fileReader->addRequest($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $url
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setURL($url) {
|
||||||
|
$this->url = $url;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param callable $function
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCallable($function) {
|
||||||
|
$this->function = $function;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getContent() {
|
||||||
|
return $this->content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $content
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setContent($content) {
|
||||||
|
$this->content = $content;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function getCompression() {
|
||||||
|
return $this->compression;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param boolean $compression
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCompression($compression) {
|
||||||
|
$this->compression = $compression;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getHeaders() {
|
||||||
|
return $this->headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $headers
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setHeaders($headers) {
|
||||||
|
if(is_array($headers)){
|
||||||
|
$this->headers = $headers;
|
||||||
|
}
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getContentType() {
|
||||||
|
return $this->contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $contentType
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setContentType($contentType) {
|
||||||
|
$this->contentType = $contentType;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace ManiaControl\Files;
|
namespace ManiaControl\Files;
|
||||||
|
|
||||||
use cURL\Event;
|
|
||||||
use cURL\Request;
|
use cURL\Request;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
|
|
||||||
@ -38,10 +37,10 @@ class AsynchronousFileReader {
|
|||||||
|
|
||||||
public static function newRequestTest($url) {
|
public static function newRequestTest($url) {
|
||||||
$request = new Request($url);
|
$request = new Request($url);
|
||||||
$request->getOptions()->set(CURLOPT_TIMEOUT, 60)->set(CURLOPT_HEADER, false) // don't display response header
|
$request->getOptions()->set(CURLOPT_TIMEOUT, 60)->set(CURLOPT_HEADER, false)// don't display response header
|
||||||
->set(CURLOPT_CRLF, true) // linux line feed
|
->set(CURLOPT_CRLF, true)// linux line feed
|
||||||
->set(CURLOPT_ENCODING, '') // accept encoding
|
->set(CURLOPT_ENCODING, '')// accept encoding
|
||||||
->set(CURLOPT_USERAGENT, 'ManiaControl v' . ManiaControl::VERSION) // user-agent
|
->set(CURLOPT_USERAGENT, 'ManiaControl v' . ManiaControl::VERSION)// user-agent
|
||||||
->set(CURLOPT_RETURNTRANSFER, true); // return instead of output content
|
->set(CURLOPT_RETURNTRANSFER, true); // return instead of output content
|
||||||
return $request;
|
return $request;
|
||||||
}
|
}
|
||||||
@ -66,93 +65,15 @@ class AsynchronousFileReader {
|
|||||||
* @param callable $function
|
* @param callable $function
|
||||||
* @param string $contentType
|
* @param string $contentType
|
||||||
* @param int $keepAlive
|
* @param int $keepAlive
|
||||||
|
* @param array $headers Additional Headers
|
||||||
|
* @deprecated @see ManiaControl\Files\AsyncHttpRequest
|
||||||
*/
|
*/
|
||||||
public function loadFile($url, callable $function, $contentType = 'UTF-8', $keepAlive = 0) {
|
public function loadFile($url, callable $function, $contentType = 'UTF-8', $keepAlive = 0, $headers = array()) {
|
||||||
$headers = array();
|
$httpRequest = new AsyncHttpRequest($this->maniaControl, $url);
|
||||||
array_push($headers, 'Content-Type: ' . $contentType);
|
$httpRequest->setCallable($function)->setContentType($contentType)->setHeaders($headers);
|
||||||
if ($keepAlive) {
|
$httpRequest->getData($keepAlive);
|
||||||
array_push($headers, 'Keep-Alive: ' . $keepAlive);
|
|
||||||
array_push($headers, 'Connection: Keep-Alive');
|
|
||||||
}
|
|
||||||
|
|
||||||
$request = $this->newRequest($url);
|
|
||||||
$request->getOptions()->set(CURLOPT_AUTOREFERER, true) // accept link reference
|
|
||||||
->set(CURLOPT_HTTPHEADER, $headers); // headers
|
|
||||||
|
|
||||||
$request->addListener('complete', function (Event $event) use (&$function) {
|
|
||||||
$error = null;
|
|
||||||
$content = null;
|
|
||||||
if ($event->response->hasError()) {
|
|
||||||
$error = $event->response->getError()->getMessage();
|
|
||||||
} else {
|
|
||||||
$content = $event->response->getContent();
|
|
||||||
}
|
|
||||||
call_user_func($function, $content, $error);
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->addRequest($request);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new cURL Request for the given URL
|
|
||||||
*
|
|
||||||
* @param string $url
|
|
||||||
* @return Request
|
|
||||||
*/
|
|
||||||
protected function newRequest($url) {
|
|
||||||
$request = new Request($url);
|
|
||||||
$request->getOptions()->set(CURLOPT_TIMEOUT, 60)->set(CURLOPT_HEADER, false) // don't display response header
|
|
||||||
->set(CURLOPT_CRLF, true) // linux line feed
|
|
||||||
->set(CURLOPT_ENCODING, '') // accept encoding
|
|
||||||
->set(CURLOPT_USERAGENT, 'ManiaControl v' . ManiaControl::VERSION) // user-agent
|
|
||||||
->set(CURLOPT_RETURNTRANSFER, true); // return instead of output content
|
|
||||||
return $request;
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO remove, they are just for testing dedimania
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a Request to the queue
|
|
||||||
*
|
|
||||||
* @param Request $request
|
|
||||||
*/
|
|
||||||
protected function addRequest(Request $request) {
|
|
||||||
array_push($this->requests, $request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function postDataTest(Request $request, $url, callable $function, $content, $compression = false, $contentType = 'text/xml; charset=UTF-8;') {
|
|
||||||
|
|
||||||
$headers = array();
|
|
||||||
array_push($headers, 'Content-Type: ' . $contentType);
|
|
||||||
array_push($headers, 'Keep-Alive: timeout=600, max=2000');
|
|
||||||
array_push($headers, 'Connection: Keep-Alive');
|
|
||||||
|
|
||||||
$content = str_replace(array("\r", "\n"), '', $content);
|
|
||||||
if ($compression) {
|
|
||||||
$content = zlib_encode($content, 31);
|
|
||||||
array_push($headers, 'Content-Encoding: gzip');
|
|
||||||
}
|
|
||||||
|
|
||||||
$request->getOptions()->set(CURLOPT_POST, true) // post method
|
|
||||||
->set(CURLOPT_POSTFIELDS, $content) // post content field
|
|
||||||
->set(CURLOPT_HTTPHEADER, $headers) // headers
|
|
||||||
;
|
|
||||||
$request->addListener('complete', function (Event $event) use (&$function) {
|
|
||||||
$error = null;
|
|
||||||
$content = null;
|
|
||||||
if ($event->response->hasError()) {
|
|
||||||
$error = $event->response->getError()->getMessage();
|
|
||||||
} else {
|
|
||||||
$content = $event->response->getContent();
|
|
||||||
}
|
|
||||||
|
|
||||||
call_user_func($function, $content, $error);
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->addRequest($request);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send Data via POST Method
|
* Send Data via POST Method
|
||||||
*
|
*
|
||||||
@ -161,36 +82,21 @@ class AsynchronousFileReader {
|
|||||||
* @param string $content
|
* @param string $content
|
||||||
* @param bool $compression
|
* @param bool $compression
|
||||||
* @param string $contentType
|
* @param string $contentType
|
||||||
|
* @param array $headers Additional Headers
|
||||||
|
* @deprecated @see ManiaControl\Files\AsyncHttpRequest
|
||||||
*/
|
*/
|
||||||
public function postData($url, callable $function, $content, $compression = false, $contentType = 'text/xml; charset=UTF-8;') {
|
public function postData($url, callable $function, $content, $compression = false, $contentType = 'text/xml; charset=UTF-8;', $headers = array()) {
|
||||||
|
$httpRequest = new AsyncHttpRequest($this->maniaControl, $url);
|
||||||
|
$httpRequest->setCallable($function)->setContent($content)->setCompression($compression)->setContentType($contentType)->setHeaders($headers);
|
||||||
|
$httpRequest->postData();
|
||||||
|
}
|
||||||
|
|
||||||
$headers = array();
|
/**
|
||||||
array_push($headers, 'Content-Type: ' . $contentType);
|
* Add a Request to the queue, DO NOT CALL MANUALLY!
|
||||||
array_push($headers, 'Keep-Alive: timeout=600, max=2000');
|
*
|
||||||
array_push($headers, 'Connection: Keep-Alive');
|
* @param Request $request
|
||||||
|
*/
|
||||||
$content = str_replace(array("\r", "\n"), '', $content);
|
public function addRequest(Request $request) {
|
||||||
if ($compression) {
|
array_push($this->requests, $request);
|
||||||
$content = zlib_encode($content, 31);
|
|
||||||
array_push($headers, 'Content-Encoding: gzip');
|
|
||||||
}
|
|
||||||
|
|
||||||
$request = $this->newRequest($url);
|
|
||||||
$request->getOptions()->set(CURLOPT_POST, true) // post method
|
|
||||||
->set(CURLOPT_POSTFIELDS, $content) // post content field
|
|
||||||
->set(CURLOPT_HTTPHEADER, $headers) // headers
|
|
||||||
;
|
|
||||||
$request->addListener('complete', function (Event $event) use (&$function) {
|
|
||||||
$error = null;
|
|
||||||
$content = null;
|
|
||||||
if ($event->response->hasError()) {
|
|
||||||
$error = $event->response->getError()->getMessage();
|
|
||||||
} else {
|
|
||||||
$content = $event->response->getContent();
|
|
||||||
}
|
|
||||||
call_user_func($function, $content, $error);
|
|
||||||
});
|
|
||||||
|
|
||||||
$this->addRequest($request);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,15 @@ use ManiaControl\Bills\BillManager;
|
|||||||
use ManiaControl\Callbacks\CallbackListener;
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
use ManiaControl\Callbacks\CallbackManager;
|
use ManiaControl\Callbacks\CallbackManager;
|
||||||
use ManiaControl\Callbacks\Callbacks;
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
|
use ManiaControl\Callbacks\EchoManager;
|
||||||
use ManiaControl\Callbacks\TimerListener;
|
use ManiaControl\Callbacks\TimerListener;
|
||||||
use ManiaControl\Callbacks\TimerManager;
|
use ManiaControl\Callbacks\TimerManager;
|
||||||
use ManiaControl\Commands\CommandListener;
|
use ManiaControl\Commands\CommandListener;
|
||||||
use ManiaControl\Commands\CommandManager;
|
use ManiaControl\Commands\CommandManager;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationManager;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Configurator\Configurator;
|
use ManiaControl\Configurator\Configurator;
|
||||||
use ManiaControl\Database\Database;
|
use ManiaControl\Database\Database;
|
||||||
use ManiaControl\Files\AsynchronousFileReader;
|
use ManiaControl\Files\AsynchronousFileReader;
|
||||||
@ -38,11 +43,11 @@ use Maniaplanet\DedicatedServer\Xmlrpc\TransportException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
class ManiaControl implements CallbackListener, CommandListener, TimerListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
const VERSION = '0.155';
|
const VERSION = '0.163';
|
||||||
const API_VERSION = '2013-04-16';
|
const API_VERSION = '2013-04-16';
|
||||||
const MIN_DEDIVERSION = '2014-04-02_18_00';
|
const MIN_DEDIVERSION = '2014-04-02_18_00';
|
||||||
const SCRIPT_TIMEOUT = 10;
|
const SCRIPT_TIMEOUT = 10;
|
||||||
@ -164,6 +169,10 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
|||||||
*/
|
*/
|
||||||
private $requestQuitMessage = null;
|
private $requestQuitMessage = null;
|
||||||
|
|
||||||
|
/** @var EchoManager $echoManager */
|
||||||
|
private $echoManager = null;
|
||||||
|
private $communicationManager = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new ManiaControl instance
|
* Construct a new ManiaControl instance
|
||||||
*/
|
*/
|
||||||
@ -176,6 +185,8 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
|||||||
|
|
||||||
// Load ManiaControl Modules
|
// Load ManiaControl Modules
|
||||||
$this->callbackManager = new CallbackManager($this);
|
$this->callbackManager = new CallbackManager($this);
|
||||||
|
$this->echoManager = new EchoManager($this);
|
||||||
|
$this->communicationManager = new CommunicationManager($this);
|
||||||
$this->timerManager = new TimerManager($this);
|
$this->timerManager = new TimerManager($this);
|
||||||
$this->database = new Database($this);
|
$this->database = new Database($this);
|
||||||
$this->fileReader = new AsynchronousFileReader($this);
|
$this->fileReader = new AsynchronousFileReader($this);
|
||||||
@ -194,6 +205,7 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
|||||||
$this->pluginManager = new PluginManager($this);
|
$this->pluginManager = new PluginManager($this);
|
||||||
$this->updateManager = new UpdateManager($this);
|
$this->updateManager = new UpdateManager($this);
|
||||||
|
|
||||||
|
|
||||||
$this->getErrorHandler()->init();
|
$this->getErrorHandler()->init();
|
||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
@ -207,6 +219,18 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
|||||||
|
|
||||||
// Check connection every 30 seconds
|
// Check connection every 30 seconds
|
||||||
$this->getTimerManager()->registerTimerListening($this, 'checkConnection', 1000 * 30);
|
$this->getTimerManager()->registerTimerListening($this, 'checkConnection', 1000 * 30);
|
||||||
|
|
||||||
|
// Communication Methods
|
||||||
|
$this->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::RESTART_MANIA_CONTROL, $this, function ($data) {
|
||||||
|
//Delay Shutdown to send answer first
|
||||||
|
$this->getTimerManager()->registerOneTimeListening($this, function () use ($data) {
|
||||||
|
if (is_object($data) && property_exists($data, "message")) {
|
||||||
|
$this->restart($data->message);
|
||||||
|
}
|
||||||
|
$this->restart();
|
||||||
|
}, 3000);
|
||||||
|
return new CommunicationAnswer();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -278,6 +302,24 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
|||||||
return $this->callbackManager;
|
return $this->callbackManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the echo manager
|
||||||
|
*
|
||||||
|
* @return EchoManager
|
||||||
|
*/
|
||||||
|
public function getEchoManager() {
|
||||||
|
return $this->echoManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the socket manager
|
||||||
|
*
|
||||||
|
* @return CommunicationManager
|
||||||
|
*/
|
||||||
|
public function getCommunicationManager() {
|
||||||
|
return $this->communicationManager;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the chat
|
* Return the chat
|
||||||
*
|
*
|
||||||
@ -465,6 +507,9 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
|||||||
* @param string $message
|
* @param string $message
|
||||||
*/
|
*/
|
||||||
public function restart($message = null) {
|
public function restart($message = null) {
|
||||||
|
// Trigger callback on Restart
|
||||||
|
$this->getCallbackManager()->triggerCallback(Callbacks::ONRESTART);
|
||||||
|
|
||||||
// Announce restart
|
// Announce restart
|
||||||
try {
|
try {
|
||||||
$this->getChat()->sendInformation('Restarting ManiaControl...');
|
$this->getChat()->sendInformation('Restarting ManiaControl...');
|
||||||
|
@ -130,14 +130,18 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// search for matching maps
|
//Search the Maps
|
||||||
$this->maniaControl->getMapManager()->getMXManager()->fetchMapsAsync(function (array $maps) use (&$player) {
|
$mxSearch = new ManiaExchangeMapSearch($this->maniaControl);
|
||||||
|
$mxSearch->setAuthorName($author);
|
||||||
|
$mxSearch->setEnvironments($environment);
|
||||||
|
$mxSearch->setMapName($searchString);
|
||||||
|
$mxSearch->fetchMapsAsync(function (array $maps) use (&$player) {
|
||||||
if (!$maps) {
|
if (!$maps) {
|
||||||
$this->maniaControl->getChat()->sendError('No maps found, or MX is down!', $player->login);
|
$this->maniaControl->getChat()->sendError('No maps found, or MX is down!', $player->login);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->showManiaExchangeList($maps, $player);
|
$this->showManiaExchangeList($maps, $player);
|
||||||
}, $searchString, $author, $environment);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,7 +9,7 @@ use ManiaControl\Maps\MapManager;
|
|||||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mania Exchange Info Searcher Class
|
* Mania Exchange Manager Class
|
||||||
*
|
*
|
||||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
@ -18,8 +18,9 @@ use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
|||||||
class ManiaExchangeManager {
|
class ManiaExchangeManager {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
|
* @deprecated SEARCH Constants
|
||||||
*/
|
*/
|
||||||
//Search others
|
//Search orders (prior parameter) http://api.mania-exchange.com/documents/enums#orderings
|
||||||
const SEARCH_ORDER_NONE = -1;
|
const SEARCH_ORDER_NONE = -1;
|
||||||
const SEARCH_ORDER_TRACK_NAME = 0;
|
const SEARCH_ORDER_TRACK_NAME = 0;
|
||||||
const SEARCH_ORDER_AUTHOR = 1;
|
const SEARCH_ORDER_AUTHOR = 1;
|
||||||
@ -47,7 +48,7 @@ class ManiaExchangeManager {
|
|||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
private $mxIdUidVector = array();
|
private $mxIdUidVector = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,9 +270,9 @@ class ManiaExchangeManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
* @deprecated
|
||||||
* @see \ManiaControl\ManiaExchange\ManiaExchangeManager::fetchMapsAsync()
|
* @see \ManiaControl\ManiaExchange\ManiaExchangeMapSearch
|
||||||
*/
|
*/
|
||||||
public function getMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = self::SEARCH_ORDER_UPDATED_NEWEST) {
|
public function getMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = ManiaExchangeMapSearch::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||||
$this->fetchMapsAsync($function, $name, $author, $env, $maxMapsReturned, $searchOrder);
|
$this->fetchMapsAsync($function, $name, $author, $env, $maxMapsReturned, $searchOrder);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -285,73 +286,22 @@ class ManiaExchangeManager {
|
|||||||
* @param string $env
|
* @param string $env
|
||||||
* @param int $maxMapsReturned
|
* @param int $maxMapsReturned
|
||||||
* @param int $searchOrder
|
* @param int $searchOrder
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
* @see \ManiaControl\ManiaExchange\ManiaExchangeMapSearch
|
||||||
*/
|
*/
|
||||||
public function fetchMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = self::SEARCH_ORDER_UPDATED_NEWEST) {
|
public function fetchMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $sortOrder = ManiaExchangeMapSearch::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||||
// TODO: remove $env because it's not really used?
|
$mapSearch = new ManiaExchangeMapSearch($this->maniaControl);
|
||||||
|
$mapSearch->setMapName($name);
|
||||||
|
$mapSearch->setAuthorName($author);
|
||||||
|
$mapSearch->setMapLimit($maxMapsReturned);
|
||||||
|
$mapSearch->setPrioritySortOrder($sortOrder);
|
||||||
|
|
||||||
// Get Title Id
|
if($env){
|
||||||
$titleId = $this->maniaControl->getServer()->titleId;
|
$mapSearch->setEnvironments($env);
|
||||||
$titlePrefix = $this->maniaControl->getMapManager()->getCurrentMap()->getGame();
|
|
||||||
|
|
||||||
// compile search URL
|
|
||||||
$url = 'http://' . $titlePrefix . '.mania-exchange.com/tracksearch2/search?api=on';
|
|
||||||
|
|
||||||
$game = explode('@', $titleId);
|
|
||||||
$envNumber = $this->getEnvironment($game[0]);
|
|
||||||
if ($env || $envNumber > -1) {
|
|
||||||
$url .= '&environments=' . $envNumber;
|
|
||||||
}
|
|
||||||
if ($name) {
|
|
||||||
$url .= '&trackname=' . str_replace(" ", "%20", $name);
|
|
||||||
}
|
|
||||||
if ($author) {
|
|
||||||
$url .= '&author=' . $author;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$url .= '&priord=' . $searchOrder;
|
$mapSearch->fetchMapsAsync($function);
|
||||||
$url .= '&limit=' . $maxMapsReturned;
|
|
||||||
|
|
||||||
if ($titlePrefix !== "tm") {
|
|
||||||
$url .= '&minexebuild=' . self::MIN_EXE_BUILD;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get MapTypes
|
|
||||||
try {
|
|
||||||
$scriptInfos = $this->maniaControl->getClient()->getModeScriptInfo();
|
|
||||||
$mapTypes = $scriptInfos->compatibleMapTypes;
|
|
||||||
$url .= '&mtype=' . $mapTypes;
|
|
||||||
} catch (GameModeException $e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->maniaControl->getFileReader()->loadFile($url, function ($mapInfo, $error) use (&$function, $titlePrefix) {
|
|
||||||
if ($error) {
|
|
||||||
trigger_error($error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mxMapList = json_decode($mapInfo);
|
|
||||||
|
|
||||||
if (!isset($mxMapList->results)) {
|
|
||||||
trigger_error('Cannot decode searched JSON data');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$mxMapList = $mxMapList->results;
|
|
||||||
|
|
||||||
if ($mxMapList === null) {
|
|
||||||
trigger_error('Cannot decode searched JSON data');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$maps = array();
|
|
||||||
foreach ($mxMapList as $map) {
|
|
||||||
if (!empty($map)) {
|
|
||||||
array_push($maps, new MXMapInfo($titlePrefix, $map));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
call_user_func($function, $maps);
|
|
||||||
}, AsynchronousFileReader::CONTENT_TYPE_JSON);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
437
core/ManiaExchange/ManiaExchangeMapSearch.php
Normal file
437
core/ManiaExchange/ManiaExchangeMapSearch.php
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
<?php
|
||||||
|
namespace ManiaControl\ManiaExchange;
|
||||||
|
|
||||||
|
use ManiaControl\Files\AsynchronousFileReader;
|
||||||
|
use ManiaControl\ManiaControl;
|
||||||
|
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mania Exchange Map Searching Class
|
||||||
|
*
|
||||||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
|
*/
|
||||||
|
class ManiaExchangeMapSearch {
|
||||||
|
//Search orders (prior parameter) http://api.mania-exchange.com/documents/enums#orderings
|
||||||
|
const SEARCH_ORDER_NONE = -1;
|
||||||
|
const SEARCH_ORDER_TRACK_NAME = 0;
|
||||||
|
const SEARCH_ORDER_AUTHOR = 1;
|
||||||
|
const SEARCH_ORDER_UPLOADED_NEWEST = 2;
|
||||||
|
const SEARCH_ORDER_UPLOADED_OLDEST = 3;
|
||||||
|
const SEARCH_ORDER_UPDATED_NEWEST = 4;
|
||||||
|
const SEARCH_ORDER_UPDATED_OLDEST = 5;
|
||||||
|
const SEARCH_ORDER_ACTIVITY_LATEST = 6;
|
||||||
|
const SEARCH_ORDER_ACTIVITY_OLDEST = 7;
|
||||||
|
const SEARCH_ORDER_AWARDS_MOST = 8;
|
||||||
|
const SEARCH_ORDER_AWARDS_LEAST = 9;
|
||||||
|
const SEARCH_ORDER_COMMENTS_MOST = 10;
|
||||||
|
const SEARCH_ORDER_COMMENTS_LEAST = 11;
|
||||||
|
const SEARCH_ORDER_DIFFICULTY_EASIEST = 12;
|
||||||
|
const SEARCH_ORDER_DIFFICULTY_HARDEST = 13;
|
||||||
|
const SEARCH_ORDER_LENGTH_SHORTEST = 14;
|
||||||
|
const SEARCH_ORDER_LENGTH_LONGEST = 15;
|
||||||
|
const SEARCH_ORDER_TRACK_VALUE_LTH = 24;
|
||||||
|
const SEARCH_ORDER_TRACK_VALUE_HTL = 25;
|
||||||
|
const SEARCH_ORDER_ONLINE_RATING_LTH = 26;
|
||||||
|
const SEARCH_ORDER_ONLINE_RATING_HTL = 27;
|
||||||
|
|
||||||
|
//Special Search Orders (mode parameter): http://api.mania-exchange.com/documents/enums#modes
|
||||||
|
const SEARCH_ORDER_SPECIAL_DEFAULT = 0;
|
||||||
|
const SEARCH_ORDER_SPECIAL_USER_TRACKS = 1;
|
||||||
|
const SEARCH_ORDER_SPECIAL_LATEST_TRACKS = 2;
|
||||||
|
const SEARCH_ORDER_SPECIAL_RECENTLY_AWARDED = 3;
|
||||||
|
const SEARCH_ORDER_SPECIAL_BEST_OF_WEEK_AWARDS = 4;
|
||||||
|
const SEARCH_ORDER_SPECIAL_BEST_OF_MONTH_AWARDS = 5;
|
||||||
|
const SEARCH_ORDER_SPECIAL_MX_SUPPORTER_TRACKS = 10;
|
||||||
|
const SEARCH_ORDER_SPECIAL_DUO_ACCOUNT_TRACKS = 11;
|
||||||
|
const SEARCH_ORDER_SPECIAL_MOST_COMPETITIVE_WEEK = 19;
|
||||||
|
const SEARCH_ORDER_SPECIAL_MOST_COMPETITIVE_MONTH = 20;
|
||||||
|
const SEARCH_ORDER_SPECIAL_BEST_ONLINE_RATING_WEEK = 21;
|
||||||
|
const SEARCH_ORDER_SPECIAL_BEST_ONLINE_RATING_MONTH = 22;
|
||||||
|
|
||||||
|
//Private Properties
|
||||||
|
private $url = "";
|
||||||
|
private $titlePrefix = "";
|
||||||
|
|
||||||
|
private $mode = null;
|
||||||
|
private $mapName = null;
|
||||||
|
private $authorName = null;
|
||||||
|
private $mod = null;
|
||||||
|
private $authorId = null;
|
||||||
|
private $maniaScriptType = null;
|
||||||
|
private $titlePack = null;
|
||||||
|
private $replayType = null;
|
||||||
|
private $style = null;
|
||||||
|
private $length = null;
|
||||||
|
private $lengthOperator = null;
|
||||||
|
private $priorityOrder = null;
|
||||||
|
private $secondaryOrder = null;
|
||||||
|
private $environments = null;
|
||||||
|
private $vehicles = null;
|
||||||
|
private $page = null;
|
||||||
|
private $mapLimit = null;
|
||||||
|
private $unreleased = null;
|
||||||
|
private $mapGroup = null;
|
||||||
|
private $commentsMinLength = null;
|
||||||
|
private $customScreenshot = null;
|
||||||
|
private $minExeBuild = null;
|
||||||
|
private $envMix = null;
|
||||||
|
private $ghostBlocks = null;
|
||||||
|
private $embeddedObjects = null;
|
||||||
|
|
||||||
|
/** @var ManiaControl $maniaControl */
|
||||||
|
private $maniaControl = null;
|
||||||
|
|
||||||
|
//TODO use class by mxlist
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct map manager
|
||||||
|
*
|
||||||
|
* @param \ManiaControl\ManiaControl $maniaControl
|
||||||
|
*/
|
||||||
|
public function __construct(ManiaControl $maniaControl) {
|
||||||
|
$this->maniaControl = $maniaControl;
|
||||||
|
|
||||||
|
|
||||||
|
$titleId = $this->maniaControl->getServer()->titleId;
|
||||||
|
$this->titlePrefix = $this->maniaControl->getMapManager()->getCurrentMap()->getGame();
|
||||||
|
|
||||||
|
$this->url = 'https://' . $this->titlePrefix . '.mania-exchange.com/tracksearch2/search?api=on';
|
||||||
|
|
||||||
|
//Set some defaults:
|
||||||
|
$this->mapLimit = 100;
|
||||||
|
$this->priorityOrder = self::SEARCH_ORDER_UPDATED_NEWEST;
|
||||||
|
|
||||||
|
//Set Min Exe Build Default for games which are not Trackmania
|
||||||
|
if ($this->titlePrefix !== "tm") {
|
||||||
|
$this->minExeBuild = ManiaExchangeManager::MIN_EXE_BUILD;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set MapTypes
|
||||||
|
try {
|
||||||
|
$scriptInfos = $this->maniaControl->getClient()->getModeScriptInfo();
|
||||||
|
$mapTypes = $scriptInfos->compatibleMapTypes;
|
||||||
|
$this->maniaScriptType = $mapTypes;
|
||||||
|
} catch (GameModeException $e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set Environments on Trackmania
|
||||||
|
$game = explode('@', $titleId);
|
||||||
|
$envNumber = $this->getEnvironment($game[0]); //TODO enviroment as constant
|
||||||
|
if ($envNumber > -1) {
|
||||||
|
$this->environments = $envNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a MapList Asynchronously
|
||||||
|
*
|
||||||
|
* @param callable $function
|
||||||
|
*/
|
||||||
|
public function fetchMapsAsync(callable $function) {
|
||||||
|
// compile search URL
|
||||||
|
$parameters = "";
|
||||||
|
|
||||||
|
if ($this->mode) {
|
||||||
|
$parameters .= "&mode=" . $this->mode;
|
||||||
|
}
|
||||||
|
if ($this->mapName) {
|
||||||
|
$parameters .= "&trackname=" . urlencode($this->mapName);
|
||||||
|
}
|
||||||
|
if ($this->authorName) {
|
||||||
|
$parameters .= "&author=" . urlencode($this->authorName);
|
||||||
|
}
|
||||||
|
if ($this->mod) {
|
||||||
|
$parameters .= "&mod=" . urlencode($this->mod);
|
||||||
|
}
|
||||||
|
if ($this->authorId) {
|
||||||
|
$parameters .= "&authorid= " . $this->authorId;
|
||||||
|
}
|
||||||
|
if ($this->maniaScriptType) {
|
||||||
|
$parameters .= "&mtype=" . urlencode($this->maniaScriptType);
|
||||||
|
}
|
||||||
|
if ($this->titlePack) {
|
||||||
|
$parameters .= "&tpack=" . urlencode($this->titlePack);
|
||||||
|
}
|
||||||
|
if ($this->replayType) {
|
||||||
|
$parameters .= "&rytpe=" . $this->replayType;
|
||||||
|
}
|
||||||
|
if ($this->style) {
|
||||||
|
$parameters .= "&style=" . $this->style;
|
||||||
|
}
|
||||||
|
if ($this->length) {
|
||||||
|
$parameters .= "&length=" . $this->length;
|
||||||
|
}
|
||||||
|
if ($this->lengthOperator) {
|
||||||
|
$parameters .= "&lengthop=" . $this->lengthOperator;
|
||||||
|
}
|
||||||
|
if ($this->priorityOrder) {
|
||||||
|
$parameters .= "&priord=" . $this->priorityOrder;
|
||||||
|
}
|
||||||
|
if ($this->secondaryOrder) {
|
||||||
|
$parameters .= "&secord=" . $this->secondaryOrder;
|
||||||
|
}
|
||||||
|
if ($this->environments) {
|
||||||
|
$parameters .= "&environemtns=" . $this->environments;
|
||||||
|
}
|
||||||
|
if ($this->vehicles) {
|
||||||
|
$parameters .= "&vehicles=" . $this->vehicles;
|
||||||
|
}
|
||||||
|
if ($this->page) {
|
||||||
|
$parameters .= "&page=" . $this->page;
|
||||||
|
}
|
||||||
|
if ($this->mapLimit) {
|
||||||
|
$parameters .= "&limit=" . $this->mapLimit;
|
||||||
|
}
|
||||||
|
if (isset($this->unreleased)) {
|
||||||
|
$parameters .= "&unreleased=" . (int) $this->unreleased;
|
||||||
|
}
|
||||||
|
if ($this->mapGroup) {
|
||||||
|
$parameters .= "&mapgroup=" . $this->mapGroup;
|
||||||
|
}
|
||||||
|
if ($this->commentsMinLength) {
|
||||||
|
$parameters .= "&commentsminlength=" . $this->commentsMinLength;
|
||||||
|
}
|
||||||
|
if (isset($this->customScreenshot)) {
|
||||||
|
$parameters .= "&customscreenshot=" . $this->customScreenshot;
|
||||||
|
}
|
||||||
|
if ($this->minExeBuild) {
|
||||||
|
$parameters .= "&minexebuild=" . urlencode($this->minExeBuild);
|
||||||
|
}
|
||||||
|
if (isset($this->envMix)) {
|
||||||
|
$parameters .= "&envmix=" . (int) $this->envMix;
|
||||||
|
}
|
||||||
|
if (isset($this->ghostBlocks)) {
|
||||||
|
$parameters .= "&ghostblocks=" . (int) $this->ghostBlocks;
|
||||||
|
}
|
||||||
|
if (isset($this->embeddedObjects)) {
|
||||||
|
$parameters .= "&embeddedobjects=" . (int) $this->embeddedObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->maniaControl->getFileReader()->loadFile($this->url . $parameters, function ($mapInfo, $error) use (&$function) {
|
||||||
|
if ($error) {
|
||||||
|
trigger_error($error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mxMapList = json_decode($mapInfo);
|
||||||
|
|
||||||
|
if (!isset($mxMapList->results)) {
|
||||||
|
trigger_error('Cannot decode searched JSON data');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mxMapList = $mxMapList->results;
|
||||||
|
|
||||||
|
if ($mxMapList === null) {
|
||||||
|
trigger_error('Cannot decode searched JSON data');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$maps = array();
|
||||||
|
foreach ($mxMapList as $map) {
|
||||||
|
if (!empty($map)) {
|
||||||
|
array_push($maps, new MXMapInfo($this->titlePrefix, $map));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
call_user_func($function, $maps);
|
||||||
|
}, AsynchronousFileReader::CONTENT_TYPE_JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the Current Environment by String
|
||||||
|
*
|
||||||
|
* @param string $env
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
private function getEnvironment($env) {
|
||||||
|
switch ($env) {
|
||||||
|
case 'TMCanyon':
|
||||||
|
return 1;
|
||||||
|
case 'TMStadium':
|
||||||
|
return 2;
|
||||||
|
case 'TMValley':
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $mode
|
||||||
|
*/
|
||||||
|
public function setMode($mode) {
|
||||||
|
$this->mode = $mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $mapName
|
||||||
|
*/
|
||||||
|
public function setMapName($mapName) {
|
||||||
|
$this->mapName = $mapName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $authorName
|
||||||
|
*/
|
||||||
|
public function setAuthorName($authorName) {
|
||||||
|
$this->authorName = $authorName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $authorId
|
||||||
|
*/
|
||||||
|
public function setAuthorId($authorId) {
|
||||||
|
$this->authorId = $authorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $maniaScriptType
|
||||||
|
*/
|
||||||
|
public function setManiaScriptType($maniaScriptType) {
|
||||||
|
$this->maniaScriptType = $maniaScriptType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $mod
|
||||||
|
*/
|
||||||
|
public function setMod($mod) {
|
||||||
|
$this->mod = $mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $titlePack
|
||||||
|
*/
|
||||||
|
public function setTitlePack($titlePack) {
|
||||||
|
$this->titlePack = $titlePack;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $replayType
|
||||||
|
*/
|
||||||
|
public function setReplayType($replayType) {
|
||||||
|
$this->replayType = $replayType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $length
|
||||||
|
*/
|
||||||
|
public function setLength($length) {
|
||||||
|
$this->length = $length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $style
|
||||||
|
*/
|
||||||
|
public function setStyle($style) {
|
||||||
|
$this->style = $style;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $lengthOperator
|
||||||
|
*/
|
||||||
|
public function setLengthOperator($lengthOperator) {
|
||||||
|
$this->lengthOperator = $lengthOperator;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $secondaryOrder
|
||||||
|
*/
|
||||||
|
public function setSecondarySortOrder($secondaryOrder) {
|
||||||
|
$this->secondaryOrder = $secondaryOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $priorityOrder
|
||||||
|
*/
|
||||||
|
public function setPrioritySortOrder($priorityOrder) {
|
||||||
|
$this->priorityOrder = $priorityOrder;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $environments
|
||||||
|
*/
|
||||||
|
public function setEnvironments($environments) {
|
||||||
|
$this->environments = $environments;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $page
|
||||||
|
*/
|
||||||
|
public function setPage($page) {
|
||||||
|
$this->page = $page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $vehicles
|
||||||
|
*/
|
||||||
|
public function setVehicles($vehicles) {
|
||||||
|
$this->vehicles = $vehicles;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $unreleased
|
||||||
|
*/
|
||||||
|
public function setUnreleased($unreleased) {
|
||||||
|
$this->unreleased = $unreleased;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $mapGroup
|
||||||
|
*/
|
||||||
|
public function setMapGroup($mapGroup) {
|
||||||
|
$this->mapGroup = $mapGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $commentsMinLength
|
||||||
|
*/
|
||||||
|
public function setCommentsMinLength($commentsMinLength) {
|
||||||
|
$this->commentsMinLength = $commentsMinLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $customScreenshot
|
||||||
|
*/
|
||||||
|
public function setCustomScreenshot($customScreenshot) {
|
||||||
|
$this->customScreenshot = $customScreenshot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $envMix
|
||||||
|
*/
|
||||||
|
public function setEnvMix($envMix) {
|
||||||
|
$this->envMix = $envMix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $minExeBuild
|
||||||
|
*/
|
||||||
|
public function setMinExeBuild($minExeBuild) {
|
||||||
|
$this->minExeBuild = $minExeBuild;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $ghostBlocks
|
||||||
|
*/
|
||||||
|
public function setGhostBlocks($ghostBlocks) {
|
||||||
|
$this->ghostBlocks = $ghostBlocks;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $embeddedObjects
|
||||||
|
*/
|
||||||
|
public function setEmbeddedObjects($embeddedObjects) {
|
||||||
|
$this->embeddedObjects = $embeddedObjects;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param null $mapLimit
|
||||||
|
*/
|
||||||
|
public function setMapLimit($mapLimit) {
|
||||||
|
$this->mapLimit = $mapLimit;
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@ use ManiaControl\Players\Player;
|
|||||||
use ManiaControl\Players\PlayerManager;
|
use ManiaControl\Players\PlayerManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class managing the Custom UI in TrackMania
|
* Class managing the Custom UI in ManiaPlanet
|
||||||
*
|
*
|
||||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
@ -28,7 +28,7 @@ class CustomUIManager implements CallbackListener, TimerListener {
|
|||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
/** @var customUI $customUI */
|
/** @var customUI $customUI */
|
||||||
private $customUI = null;
|
private $customUI = null;
|
||||||
private $updateManialink = false;
|
private $updateManialink = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -262,7 +262,7 @@ class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener
|
|||||||
}
|
}
|
||||||
} catch (UnknownPlayerException $e) {
|
} catch (UnknownPlayerException $e) {
|
||||||
return false;
|
return false;
|
||||||
} catch (FaultException $e){
|
} catch (FaultException $e) {
|
||||||
//TODO added 17.01.2015, remove later:
|
//TODO added 17.01.2015, remove later:
|
||||||
$this->maniaControl->getErrorHandler()->triggerDebugNotice("Fault Exception: ManiaLink Manager, Message: " . $e->getMessage());
|
$this->maniaControl->getErrorHandler()->triggerDebugNotice("Fault Exception: ManiaLink Manager, Message: " . $e->getMessage());
|
||||||
return false;
|
return false;
|
||||||
@ -349,8 +349,11 @@ class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener
|
|||||||
return $success;
|
return $success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a line of labels
|
* Adds a line of labels
|
||||||
|
* LabelLine should be an array with the following structure: array(array(positions), array(texts))
|
||||||
|
* or array($text1 => $pos1, $text2 => $pos2 ...)
|
||||||
*
|
*
|
||||||
* @param Frame $frame
|
* @param Frame $frame
|
||||||
* @param array $labelStrings
|
* @param array $labelStrings
|
||||||
@ -366,21 +369,49 @@ class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener
|
|||||||
$profile = (isset($properties['profile']) ? $properties['profile'] : false);
|
$profile = (isset($properties['profile']) ? $properties['profile'] : false);
|
||||||
|
|
||||||
$labels = array();
|
$labels = array();
|
||||||
foreach ($labelStrings as $text => $x) {
|
|
||||||
$label = new Label_Text();
|
|
||||||
$frame->add($label);
|
|
||||||
$label->setHAlign($hAlign);
|
|
||||||
$label->setX($x);
|
|
||||||
$label->setStyle($style);
|
|
||||||
$label->setTextSize($textSize);
|
|
||||||
$label->setText($text);
|
|
||||||
$label->setTextColor($textColor);
|
|
||||||
|
|
||||||
if ($profile) {
|
//If you call LabelLine with array(array(positions), array(texts))
|
||||||
$label->addPlayerProfileFeature($profile);
|
if (count($labelStrings) == 2 && array_key_exists(0, $labelStrings) && array_key_exists(1, $labelStrings) && array_key_exists(0, $labelStrings[0]) && array_key_exists(0, $labelStrings[1])) {
|
||||||
|
$positions = $labelStrings[0];
|
||||||
|
$texts = $labelStrings[1];
|
||||||
|
|
||||||
|
if (count($positions) != count($texts)) {
|
||||||
|
trigger_error("LabelLine Position length is not equal to Text Length", E_USER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_push($labels, $label);
|
foreach ($positions as $key => $x) {
|
||||||
|
$label = new Label_Text();
|
||||||
|
$frame->add($label);
|
||||||
|
$label->setHAlign($hAlign);
|
||||||
|
$label->setX($x);
|
||||||
|
$label->setStyle($style);
|
||||||
|
$label->setTextSize($textSize);
|
||||||
|
$label->setText($texts[$key]);
|
||||||
|
$label->setTextColor($textColor);
|
||||||
|
|
||||||
|
if ($profile) {
|
||||||
|
$label->addPlayerProfileFeature($profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($labels, $label);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
foreach ($labelStrings as $text => $x) {
|
||||||
|
$label = new Label_Text();
|
||||||
|
$frame->add($label);
|
||||||
|
$label->setHAlign($hAlign);
|
||||||
|
$label->setX($x);
|
||||||
|
$label->setStyle($style);
|
||||||
|
$label->setTextSize($textSize);
|
||||||
|
$label->setText($text);
|
||||||
|
$label->setTextColor($textColor);
|
||||||
|
|
||||||
|
if ($profile) {
|
||||||
|
$label->addPlayerProfileFeature($profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_push($labels, $label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $labels;
|
return $labels;
|
||||||
|
@ -161,6 +161,13 @@ class StyleManager {
|
|||||||
$frame = new Frame();
|
$frame = new Frame();
|
||||||
$frame->setSize($width, $height)->setZ(45); //TODO place before scoreboards
|
$frame->setSize($width, $height)->setZ(45); //TODO place before scoreboards
|
||||||
|
|
||||||
|
//TODO remove: (just temporary fix for tm bug)
|
||||||
|
if ($this->maniaControl->getMapManager()->getCurrentMap()->getGame() === 'tm'
|
||||||
|
) {
|
||||||
|
$frame->setSize($width, $height)->setZ(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Background Quad
|
// Background Quad
|
||||||
$backgroundQuad = new Quad();
|
$backgroundQuad = new Quad();
|
||||||
$frame->add($backgroundQuad);
|
$frame->add($backgroundQuad);
|
||||||
|
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace ManiaControl\Maps;
|
namespace ManiaControl\Maps;
|
||||||
|
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
||||||
|
|
||||||
@ -12,7 +15,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class MapActions {
|
class MapActions implements CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
@ -26,12 +29,79 @@ class MapActions {
|
|||||||
*/
|
*/
|
||||||
public function __construct(ManiaControl $maniaControl) {
|
public function __construct(ManiaControl $maniaControl) {
|
||||||
$this->maniaControl = $maniaControl;
|
$this->maniaControl = $maniaControl;
|
||||||
|
|
||||||
|
//Communication Listenings
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::SKIP_MAP, $this, function ($data) {
|
||||||
|
$success = $this->skipMap();
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::RESTART_MAP, $this, function ($data) {
|
||||||
|
$success = $this->restartMap();
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::SKIP_TO_MAP, $this, function ($data) {
|
||||||
|
if (!is_object($data)) {
|
||||||
|
return new CommunicationAnswer("Error in provided Data", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property_exists($data, "mxId")) {
|
||||||
|
$success = $this->skipToMapByMxId($data->mxId);
|
||||||
|
} else if (property_exists($data, "mapUid")) {
|
||||||
|
$success = $this->skipToMapByUid($data->mapUid);
|
||||||
|
} else {
|
||||||
|
return new CommunicationAnswer("No mxId or mapUid provided.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips to a Map by its given UID
|
||||||
|
*
|
||||||
|
* @param String $uid
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function skipToMapByUid($uid) {
|
||||||
|
//TODO message
|
||||||
|
//Check if Map exists
|
||||||
|
$map = $this->maniaControl->getMapManager()->getMapByUid($uid);
|
||||||
|
if (!$map) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->maniaControl->getClient()->jumpToMapIdent($uid);
|
||||||
|
} catch (ChangeInProgressException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Skips to a Map by its given MxId
|
||||||
|
*
|
||||||
|
* @param int $mxId
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function skipToMapByMxId($mxId) {
|
||||||
|
$map = $this->maniaControl->getMapManager()->getMapByMxId($mxId);
|
||||||
|
if (!$map) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->skipToMapByUid($map->uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Skip the current Map
|
* Skip the current Map
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function skipMap() {
|
public function skipMap() {
|
||||||
|
//TODO message
|
||||||
|
|
||||||
// Force an EndMap on the MapQueue to set the next Map
|
// Force an EndMap on the MapQueue to set the next Map
|
||||||
$this->maniaControl->getMapManager()->getMapQueue()->endMap(null);
|
$this->maniaControl->getMapManager()->getMapQueue()->endMap(null);
|
||||||
|
|
||||||
@ -42,6 +112,27 @@ class MapActions {
|
|||||||
try {
|
try {
|
||||||
$this->maniaControl->getClient()->nextMap();
|
$this->maniaControl->getClient()->nextMap();
|
||||||
} catch (ChangeInProgressException $e) {
|
} catch (ChangeInProgressException $e) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restarts the Current Map
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function restartMap() {
|
||||||
|
//TODO message
|
||||||
|
|
||||||
|
//Restarts the Current Map
|
||||||
|
try {
|
||||||
|
$this->maniaControl->getClient()->restartMap();
|
||||||
|
} catch (ChangeInProgressException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,8 +436,18 @@ class MapCommands implements CommandListener, ManialinkPageAnswerListener, Callb
|
|||||||
*/
|
*/
|
||||||
private function showMapListKarma($best, Player $player) {
|
private function showMapListKarma($best, Player $player) {
|
||||||
/** @var \MCTeam\KarmaPlugin $karmaPlugin */
|
/** @var \MCTeam\KarmaPlugin $karmaPlugin */
|
||||||
$karmaPlugin = $this->maniaControl->getPluginManager()->getPlugin(MapList::DEFAULT_KARMA_PLUGIN);
|
$karmaPlugin = $this->maniaControl->getPluginManager()->getPlugin(MapList::DEFAULT_KARMA_PLUGIN);
|
||||||
|
$displayMxKarma = $this->maniaControl->getSettingManager()->getSettingValue($karmaPlugin, $karmaPlugin::SETTING_WIDGET_DISPLAY_MX);
|
||||||
|
|
||||||
if ($karmaPlugin) {
|
if ($karmaPlugin) {
|
||||||
|
//Sort by Mx Karma in Maplist
|
||||||
|
if ($displayMxKarma) { //TODO
|
||||||
|
|
||||||
|
//Sort by Local Karma in Maplist
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
$maps = $this->maniaControl->getMapManager()->getMaps();
|
$maps = $this->maniaControl->getMapManager()->getMaps();
|
||||||
$mapList = array();
|
$mapList = array();
|
||||||
foreach ($maps as $map) {
|
foreach ($maps as $map) {
|
||||||
|
@ -122,7 +122,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
|
|||||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||||
|
|
||||||
if ($pageIndex < 0) {
|
if ($pageIndex < 0) {
|
||||||
$pageIndex = (int)$player->getCache($this, self::CACHE_CURRENT_PAGE);
|
$pageIndex = (int) $player->getCache($this, self::CACHE_CURRENT_PAGE);
|
||||||
}
|
}
|
||||||
$player->setCache($this, self::CACHE_CURRENT_PAGE, $pageIndex);
|
$player->setCache($this, self::CACHE_CURRENT_PAGE, $pageIndex);
|
||||||
$queueBuffer = $this->maniaControl->getMapManager()->getMapQueue()->getQueueBuffer();
|
$queueBuffer = $this->maniaControl->getMapManager()->getMapQueue()->getQueueBuffer();
|
||||||
@ -441,9 +441,20 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
|
|||||||
|
|
||||||
// Display Karma bar
|
// Display Karma bar
|
||||||
if ($karmaPlugin) {
|
if ($karmaPlugin) {
|
||||||
$karma = $karmaPlugin->getMapKarma($map);
|
$displayMxKarma = $this->maniaControl->getSettingManager()->getSettingValue($karmaPlugin, $karmaPlugin::SETTING_WIDGET_DISPLAY_MX);
|
||||||
$votes = $karmaPlugin->getMapVotes($map);
|
|
||||||
if (is_numeric($karma)) {
|
//Display Mx Karma
|
||||||
|
if ($displayMxKarma && $map->mx) {
|
||||||
|
$karma = $map->mx->ratingVoteAverage / 100;
|
||||||
|
$votes = array("count" => $map->mx->ratingVoteCount);
|
||||||
|
|
||||||
|
//Display Local Karma
|
||||||
|
} else {
|
||||||
|
$karma = $karmaPlugin->getMapKarma($map);
|
||||||
|
$votes = $karmaPlugin->getMapVotes($map);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_numeric($karma) && $votes['count'] > 0) {
|
||||||
if ($this->maniaControl->getSettingManager()->getSettingValue($karmaPlugin, $karmaPlugin::SETTING_NEWKARMA)
|
if ($this->maniaControl->getSettingManager()->getSettingValue($karmaPlugin, $karmaPlugin::SETTING_NEWKARMA)
|
||||||
) {
|
) {
|
||||||
$karmaText = ' ' . round($karma * 100.) . '% (' . $votes['count'] . ')';
|
$karmaText = ' ' . round($karma * 100.) . '% (' . $votes['count'] . ')';
|
||||||
@ -692,7 +703,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
|
|||||||
default:
|
default:
|
||||||
if (substr($actionId, 0, strlen(self::ACTION_PAGING_CHUNKS)) === self::ACTION_PAGING_CHUNKS) {
|
if (substr($actionId, 0, strlen(self::ACTION_PAGING_CHUNKS)) === self::ACTION_PAGING_CHUNKS) {
|
||||||
// Paging chunks
|
// Paging chunks
|
||||||
$neededPage = (int)substr($actionId, strlen(self::ACTION_PAGING_CHUNKS));
|
$neededPage = (int) substr($actionId, strlen(self::ACTION_PAGING_CHUNKS));
|
||||||
$this->showMapList($player, null, $neededPage - 1);
|
$this->showMapList($player, null, $neededPage - 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -6,6 +6,9 @@ use ManiaControl\Admin\AuthenticationManager;
|
|||||||
use ManiaControl\Callbacks\CallbackListener;
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
use ManiaControl\Callbacks\CallbackManager;
|
use ManiaControl\Callbacks\CallbackManager;
|
||||||
use ManiaControl\Callbacks\Callbacks;
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Files\FileUtil;
|
use ManiaControl\Files\FileUtil;
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
@ -30,7 +33,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnavailableFeatureException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class MapManager implements CallbackListener {
|
class MapManager implements CallbackListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -135,34 +138,9 @@ class MapManager implements CallbackListener {
|
|||||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_AUTOSAVE_MAPLIST, true);
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_AUTOSAVE_MAPLIST, true);
|
||||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAPLIST_FILE, "MatchSettings/tracklist.txt");
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAPLIST_FILE, "MatchSettings/tracklist.txt");
|
||||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_WRITE_OWN_MAPLIST_FILE, false);
|
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_WRITE_OWN_MAPLIST_FILE, false);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
//Initlaize Communication Listenings
|
||||||
* Initialize necessary database tables
|
$this->initalizeCommunicationListenings();
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
private function initTables() {
|
|
||||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
|
||||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_MAPS . "` (
|
|
||||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
|
||||||
`mxid` int(11),
|
|
||||||
`uid` varchar(50) NOT NULL,
|
|
||||||
`name` varchar(150) NOT NULL,
|
|
||||||
`authorLogin` varchar(100) NOT NULL,
|
|
||||||
`fileName` varchar(100) NOT NULL,
|
|
||||||
`environment` varchar(50) NOT NULL,
|
|
||||||
`mapType` varchar(50) 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 COLLATE=utf8_unicode_ci COMMENT='Map Data' AUTO_INCREMENT=1;";
|
|
||||||
$result = $mysqli->query($query);
|
|
||||||
if ($mysqli->error) {
|
|
||||||
trigger_error($mysqli->error, E_USER_ERROR);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -213,14 +191,16 @@ class MapManager implements CallbackListener {
|
|||||||
/**
|
/**
|
||||||
* Update a Map from Mania Exchange
|
* Update a Map from Mania Exchange
|
||||||
*
|
*
|
||||||
* @param Player $admin
|
* @param Player|null $admin
|
||||||
* @param string $uid
|
* @param string $uid
|
||||||
*/
|
*/
|
||||||
public function updateMap(Player $admin, $uid) {
|
public function updateMap($admin, $uid) {
|
||||||
$this->updateMapTimestamp($uid);
|
$this->updateMapTimestamp($uid);
|
||||||
|
|
||||||
if (!isset($uid) || !isset($this->maps[$uid])) {
|
if (!isset($uid) || !isset($this->maps[$uid])) {
|
||||||
$this->maniaControl->getChat()->sendError("Error updating Map: Unknown UID '{$uid}'!", $admin);
|
if ($admin) {
|
||||||
|
$this->maniaControl->getChat()->sendError("Error updating Map: Unknown UID '{$uid}'!", $admin);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +209,11 @@ class MapManager implements CallbackListener {
|
|||||||
|
|
||||||
$mxId = $map->mx->id;
|
$mxId = $map->mx->id;
|
||||||
$this->removeMap($admin, $uid, true, false);
|
$this->removeMap($admin, $uid, true, false);
|
||||||
$this->addMapFromMx($mxId, $admin->login, true);
|
if ($admin) {
|
||||||
|
$this->addMapFromMx($mxId, $admin->login, true);
|
||||||
|
} else {
|
||||||
|
$this->addMapFromMx($mxId, null, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -263,15 +247,18 @@ class MapManager implements CallbackListener {
|
|||||||
/**
|
/**
|
||||||
* Remove a Map
|
* Remove a Map
|
||||||
*
|
*
|
||||||
* @param Player $admin
|
* @param Player|null $admin
|
||||||
* @param string $uid
|
* @param string $uid
|
||||||
* @param bool $eraseFile
|
* @param bool $eraseFile
|
||||||
* @param bool $message
|
* @param bool $message
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function removeMap(Player $admin, $uid, $eraseFile = false, $message = true) {
|
public function removeMap($admin, $uid, $eraseFile = false, $message = true) {
|
||||||
if (!isset($this->maps[$uid])) {
|
if (!isset($this->maps[$uid])) {
|
||||||
$this->maniaControl->getChat()->sendError('Map does not exist!', $admin);
|
if ($admin) {
|
||||||
return;
|
$this->maniaControl->getChat()->sendError('Map does not exist!', $admin);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var Map $map */
|
/** @var Map $map */
|
||||||
@ -296,26 +283,35 @@ class MapManager implements CallbackListener {
|
|||||||
if ($eraseFile) {
|
if ($eraseFile) {
|
||||||
// Check if ManiaControl can even write to the maps dir
|
// Check if ManiaControl can even write to the maps dir
|
||||||
$mapDir = $this->maniaControl->getClient()->getMapsDirectory();
|
$mapDir = $this->maniaControl->getClient()->getMapsDirectory();
|
||||||
if ($this->maniaControl->getServer()->checkAccess($mapDir)
|
if ($this->maniaControl->getServer()->checkAccess($mapDir)) {
|
||||||
) {
|
|
||||||
// Delete map file
|
// Delete map file
|
||||||
if (!@unlink($mapDir . $map->fileName)) {
|
if (!@unlink($mapDir . $map->fileName)) {
|
||||||
$this->maniaControl->getChat()->sendError("Couldn't erase the map file.", $admin);
|
if ($admin) {
|
||||||
|
$this->maniaControl->getChat()->sendError("Couldn't erase the map file.", $admin);
|
||||||
|
}
|
||||||
$eraseFile = false;
|
$eraseFile = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->maniaControl->getChat()->sendError("Couldn't erase the map file (no access).", $admin);
|
if ($admin) {
|
||||||
|
$this->maniaControl->getChat()->sendError("Couldn't erase the map file (no access).", $admin);
|
||||||
|
}
|
||||||
$eraseFile = false;
|
$eraseFile = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show Message
|
// Show Message
|
||||||
if ($message) {
|
if ($message) {
|
||||||
$action = ($eraseFile ? 'erased' : 'removed');
|
$action = ($eraseFile ? 'erased' : 'removed');
|
||||||
$message = $admin->getEscapedNickname() . ' ' . $action . ' ' . $map->getEscapedName() . '!';
|
if ($admin) {
|
||||||
|
$message = $admin->getEscapedNickname() . ' ' . $action . ' ' . $map->getEscapedName() . '!';
|
||||||
|
} else {
|
||||||
|
$message = $map->getEscapedName() . ' got ' . $action . '!';
|
||||||
|
}
|
||||||
$this->maniaControl->getChat()->sendSuccess($message);
|
$this->maniaControl->getChat()->sendSuccess($message);
|
||||||
Logger::logInfo($message, true);
|
Logger::logInfo($message, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -342,6 +338,7 @@ class MapManager implements CallbackListener {
|
|||||||
* @param int $mapId
|
* @param int $mapId
|
||||||
* @param string $login
|
* @param string $login
|
||||||
* @param bool $update
|
* @param bool $update
|
||||||
|
* @param bool $displayMessage
|
||||||
*/
|
*/
|
||||||
public function addMapFromMx($mapId, $login, $update = false) {
|
public function addMapFromMx($mapId, $login, $update = false) {
|
||||||
if (is_numeric($mapId)) {
|
if (is_numeric($mapId)) {
|
||||||
@ -350,8 +347,10 @@ class MapManager implements CallbackListener {
|
|||||||
&$login, &$update
|
&$login, &$update
|
||||||
) {
|
) {
|
||||||
if (!$mapInfo || !isset($mapInfo->uploaded)) {
|
if (!$mapInfo || !isset($mapInfo->uploaded)) {
|
||||||
// Invalid id
|
if ($login) {
|
||||||
$this->maniaControl->getChat()->sendError('Invalid MX-Id!', $login);
|
// Invalid id
|
||||||
|
$this->maniaControl->getChat()->sendError('Invalid MX-Id!', $login);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -360,14 +359,17 @@ class MapManager implements CallbackListener {
|
|||||||
&$login, &$mapInfo, &$update
|
&$login, &$mapInfo, &$update
|
||||||
) {
|
) {
|
||||||
if (!$file || $error) {
|
if (!$file || $error) {
|
||||||
// Download error
|
if ($login) {
|
||||||
$this->maniaControl->getChat()->sendError("Download failed: '{$error}'!", $login);
|
// Download error
|
||||||
|
$this->maniaControl->getChat()->sendError("Download failed: '{$error}'!", $login);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$this->processMapFile($file, $mapInfo, $login, $update);
|
$this->processMapFile($file, $mapInfo, $login, $update);
|
||||||
});
|
}, 'UTF-8', 0, array("X-ManiaPlanet-ServerLogin: " . $this->maniaControl->getServer()->login));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -459,19 +461,21 @@ class MapManager implements CallbackListener {
|
|||||||
}
|
}
|
||||||
$map->lastUpdate = time();
|
$map->lastUpdate = time();
|
||||||
|
|
||||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
//TODO messages for communication
|
||||||
|
if ($login) {
|
||||||
if (!$update) {
|
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||||
// Message
|
if (!$update) {
|
||||||
$message = $player->getEscapedNickname() . ' added $<' . $mapInfo->name . '$>!';
|
// Message
|
||||||
$this->maniaControl->getChat()->sendSuccess($message);
|
$message = $player->getEscapedNickname() . ' added $<' . $mapInfo->name . '$>!';
|
||||||
Logger::logInfo($message, true);
|
$this->maniaControl->getChat()->sendSuccess($message);
|
||||||
// Queue requested Map
|
Logger::logInfo($message, true);
|
||||||
$this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($login, $mapInfo->uid);
|
// Queue requested Map
|
||||||
} else {
|
$this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($login, $mapInfo->uid);
|
||||||
$message = $player->getEscapedNickname() . ' updated $<' . $mapInfo->name . '$>!';
|
} else {
|
||||||
$this->maniaControl->getChat()->sendSuccess($message);
|
$message = $player->getEscapedNickname() . ' updated $<' . $mapInfo->name . '$>!';
|
||||||
Logger::logInfo($message, true);
|
$this->maniaControl->getChat()->sendSuccess($message);
|
||||||
|
Logger::logInfo($message, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -522,10 +526,8 @@ class MapManager implements CallbackListener {
|
|||||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPS_UPDATED);
|
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPS_UPDATED);
|
||||||
|
|
||||||
// Write MapList
|
// Write MapList
|
||||||
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_AUTOSAVE_MAPLIST)
|
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_AUTOSAVE_MAPLIST)) {
|
||||||
) {
|
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_WRITE_OWN_MAPLIST_FILE)) {
|
||||||
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_WRITE_OWN_MAPLIST_FILE)
|
|
||||||
) {
|
|
||||||
$serverLogin = $this->maniaControl->getServer()->login;
|
$serverLogin = $this->maniaControl->getServer()->login;
|
||||||
$matchSettingsFileName = "MatchSettings/{$serverLogin}.txt";
|
$matchSettingsFileName = "MatchSettings/{$serverLogin}.txt";
|
||||||
} else {
|
} else {
|
||||||
@ -884,4 +886,102 @@ class MapManager implements CallbackListener {
|
|||||||
public function getMapsCount() {
|
public function getMapsCount() {
|
||||||
return count($this->maps);
|
return count($this->maps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the Communication Listenings
|
||||||
|
*/
|
||||||
|
private function initalizeCommunicationListenings() {
|
||||||
|
// Communication Listenings
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GET_CURRENT_MAP, $this, function ($data) {
|
||||||
|
return new CommunicationAnswer($this->getCurrentMap());
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GET_MAP_LIST, $this, function ($data) {
|
||||||
|
return new CommunicationAnswer($this->getMaps());
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GET_MAP, $this, function ($data) {
|
||||||
|
if (!is_object($data)) {
|
||||||
|
return new CommunicationAnswer("Error in provided Data", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property_exists($data, "mxId")) {
|
||||||
|
return new CommunicationAnswer($this->getMapByMxId($data->mxId));
|
||||||
|
} else if (property_exists($data, "mapUid")) {
|
||||||
|
return new CommunicationAnswer($this->getMapByUid($data->mapUid));
|
||||||
|
} else {
|
||||||
|
return new CommunicationAnswer("No mxId or mapUid provided.", true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::ADD_MAP, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "mxId")) {
|
||||||
|
return new CommunicationAnswer("No valid mxId provided.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->addMapFromMx($data->mxId, null);
|
||||||
|
|
||||||
|
return new CommunicationAnswer();
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::REMOVE_MAP, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "mapUid")) {
|
||||||
|
return new CommunicationAnswer("No valid mapUid provided.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->getMapByUid($data->mapUid)) {
|
||||||
|
return new CommunicationAnswer("Map not found.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$erase = false;
|
||||||
|
if (property_exists($data, "eraseMapFile")) {
|
||||||
|
$erase = $data->eraseMapFile;
|
||||||
|
}
|
||||||
|
$showMessage = true;
|
||||||
|
if (property_exists($data, "showChatMessage")) {
|
||||||
|
$showMessage = $data->showChatMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = $this->removeMap(null, $data->mapUid, $erase, $showMessage);
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::UPDATE_MAP, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "mapUid")) {
|
||||||
|
return new CommunicationAnswer("No valid mapUid provided.", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->updateMap(null, $data->mapUid);
|
||||||
|
return new CommunicationAnswer();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize necessary database tables
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function initTables() {
|
||||||
|
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||||
|
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_MAPS . "` (
|
||||||
|
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||||
|
`mxid` int(11),
|
||||||
|
`uid` varchar(50) NOT NULL,
|
||||||
|
`name` varchar(150) NOT NULL,
|
||||||
|
`authorLogin` varchar(100) NOT NULL,
|
||||||
|
`fileName` varchar(100) NOT NULL,
|
||||||
|
`environment` varchar(50) NOT NULL,
|
||||||
|
`mapType` varchar(50) 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 COLLATE=utf8_unicode_ci COMMENT='Map Data' AUTO_INCREMENT=1;";
|
||||||
|
$result = $mysqli->query($query);
|
||||||
|
if ($mysqli->error) {
|
||||||
|
trigger_error($mysqli->error, E_USER_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,10 +42,10 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
*/
|
*/
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
private $queuedMaps = array();
|
private $queuedMaps = array();
|
||||||
private $nextMap = null;
|
private $nextMap = null;
|
||||||
private $buffer = array();
|
private $buffer = array();
|
||||||
private $nextNoQueue = false;
|
private $nextNoQueue = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new map queue instance
|
* Construct a new map queue instance
|
||||||
@ -108,8 +108,7 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
* @param Player $admin |null
|
* @param Player $admin |null
|
||||||
*/
|
*/
|
||||||
public function clearMapQueue(Player $admin = null) {
|
public function clearMapQueue(Player $admin = null) {
|
||||||
if ($admin && !$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)
|
if ($admin && !$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -223,8 +222,8 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
if (array_key_exists($map->uid, $this->queuedMaps)) {
|
if (array_key_exists($map->uid, $this->queuedMaps)) {
|
||||||
unset($this->queuedMaps[$map->uid]);
|
unset($this->queuedMaps[$map->uid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
array_unshift($this->queuedMaps, array($player, $map, true));
|
array_unshift($this->queuedMaps, array($player, $map, true));
|
||||||
|
$this->maniaControl->callbackManager->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('add', $map));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,8 +307,7 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
// Check if map is in the buffer
|
// Check if map is in the buffer
|
||||||
if (in_array($uid, $this->buffer)) {
|
if (in_array($uid, $this->buffer)) {
|
||||||
$this->maniaControl->getChat()->sendError('That map has recently been played!', $login);
|
$this->maniaControl->getChat()->sendError('That map has recently been played!', $login);
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)) {
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,10 +327,10 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
/**
|
/**
|
||||||
* Remove a Map from the Map queue
|
* Remove a Map from the Map queue
|
||||||
*
|
*
|
||||||
* @param Player $player
|
* @param Player|null $player
|
||||||
* @param string $uid
|
* @param string $uid
|
||||||
*/
|
*/
|
||||||
public function removeFromMapQueue(Player $player, $uid) {
|
public function removeFromMapQueue($player, $uid) {
|
||||||
if (!isset($this->queuedMaps[$uid])) {
|
if (!isset($this->queuedMaps[$uid])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -340,7 +338,9 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
$map = $this->queuedMaps[$uid][1];
|
$map = $this->queuedMaps[$uid][1];
|
||||||
unset($this->queuedMaps[$uid]);
|
unset($this->queuedMaps[$uid]);
|
||||||
|
|
||||||
$this->maniaControl->getChat()->sendInformation('$fa0$<$fff' . $map->name . '$> is removed from the Map-Queue by $<$fff' . $player->nickname . '$>.');
|
if ($player) {
|
||||||
|
$this->maniaControl->getChat()->sendInformation('$fa0$<$fff' . $map->name . '$> is removed from the Map-Queue by $<$fff' . $player->nickname . '$>.');
|
||||||
|
}
|
||||||
|
|
||||||
// Trigger callback
|
// Trigger callback
|
||||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('remove', $map));
|
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('remove', $map));
|
||||||
@ -359,8 +359,7 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->nextMap = null;
|
$this->nextMap = null;
|
||||||
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_SKIP_MAP_ON_LEAVE)
|
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_SKIP_MAP_ON_LEAVE)) {
|
||||||
) {
|
|
||||||
// Skip Map if requester has left
|
// Skip Map if requester has left
|
||||||
foreach ($this->queuedMaps as $queuedMap) {
|
foreach ($this->queuedMaps as $queuedMap) {
|
||||||
$player = $queuedMap[0];
|
$player = $queuedMap[0];
|
||||||
@ -423,8 +422,7 @@ class MapQueue implements CallbackListener, CommandListener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count($this->buffer) >= $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_BUFFERSIZE)
|
if (count($this->buffer) >= $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_BUFFERSIZE)) {
|
||||||
) {
|
|
||||||
array_shift($this->buffer);
|
array_shift($this->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ namespace ManiaControl\Players;
|
|||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Utils\ClassUtil;
|
use ManiaControl\Utils\ClassUtil;
|
||||||
use ManiaControl\Utils\Formatter;
|
use ManiaControl\Utils\Formatter;
|
||||||
|
use Maniaplanet\DedicatedServer\Structures\LadderStats;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Player Model Class
|
* Player Model Class
|
||||||
@ -17,55 +18,56 @@ class Player {
|
|||||||
/*
|
/*
|
||||||
* Public Properties
|
* Public Properties
|
||||||
*/
|
*/
|
||||||
public $index = -1;
|
public $index = -1;
|
||||||
public $pid = -1;
|
public $pid = -1;
|
||||||
public $login = null;
|
public $login = null;
|
||||||
public $nickname = null;
|
public $nickname = null;
|
||||||
public $rawNickname = null;
|
public $rawNickname = null;
|
||||||
public $path = null;
|
public $path = null;
|
||||||
public $authLevel = 0;
|
public $authLevel = 0;
|
||||||
public $language = null;
|
public $language = null;
|
||||||
public $avatar = null;
|
public $avatar = null;
|
||||||
public $allies = array();
|
public $allies = array();
|
||||||
public $clubLink = null;
|
public $clubLink = null;
|
||||||
public $teamId = -1;
|
public $teamId = -1;
|
||||||
public $isOfficial = null;
|
public $isOfficial = null;
|
||||||
public $ladderScore = -1.;
|
public $ladderScore = -1.;
|
||||||
public $ladderRank = -1;
|
public $ladderRank = -1;
|
||||||
public $ladderStats = null;
|
/** @var LadderStats $ladderStats */
|
||||||
public $joinTime = -1;
|
public $ladderStats = null;
|
||||||
public $ipAddress = null;
|
public $joinTime = -1;
|
||||||
public $isConnected = true;
|
public $ipAddress = null;
|
||||||
public $clientVersion = null;
|
public $isConnected = true;
|
||||||
public $downloadRate = -1;
|
public $clientVersion = null;
|
||||||
public $uploadRate = -1;
|
public $downloadRate = -1;
|
||||||
public $skins = null;
|
public $uploadRate = -1;
|
||||||
|
public $skins = null;
|
||||||
public $daysSinceZoneInscription = -1;
|
public $daysSinceZoneInscription = -1;
|
||||||
|
|
||||||
//Flags details
|
//Flags details
|
||||||
public $forcedSpectatorState = 0;
|
public $forcedSpectatorState = 0;
|
||||||
public $isReferee = false;
|
public $isReferee = false;
|
||||||
public $isPodiumReady = false;
|
public $isPodiumReady = false;
|
||||||
public $isUsingStereoscopy = false;
|
public $isUsingStereoscopy = false;
|
||||||
public $isManagedByAnOtherServer = false;
|
public $isManagedByAnOtherServer = false;
|
||||||
public $isServer = false;
|
public $isServer = false;
|
||||||
public $hasPlayerSlot = false;
|
public $hasPlayerSlot = false;
|
||||||
public $isBroadcasting = false;
|
public $isBroadcasting = false;
|
||||||
public $hasJoinedGame = false;
|
public $hasJoinedGame = false;
|
||||||
|
|
||||||
//SpectatorStatus details
|
//SpectatorStatus details
|
||||||
public $isSpectator = false;
|
public $isSpectator = false;
|
||||||
public $isTemporarySpectator = false;
|
public $isTemporarySpectator = false;
|
||||||
public $isPureSpectator = false;
|
public $isPureSpectator = false;
|
||||||
public $autoTarget = false;
|
public $autoTarget = false;
|
||||||
public $currentTargetId = 0;
|
public $currentTargetId = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
private $cache = array();
|
private $cache = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new Player
|
* Construct a new Player
|
||||||
@ -75,7 +77,7 @@ class Player {
|
|||||||
*/
|
*/
|
||||||
public function __construct(ManiaControl $maniaControl, $connected) {
|
public function __construct(ManiaControl $maniaControl, $connected) {
|
||||||
$this->maniaControl = $maniaControl;
|
$this->maniaControl = $maniaControl;
|
||||||
$this->isConnected = (bool)$connected;
|
$this->isConnected = (bool) $connected;
|
||||||
if ($connected) {
|
if ($connected) {
|
||||||
$this->joinTime = time();
|
$this->joinTime = time();
|
||||||
}
|
}
|
||||||
@ -89,9 +91,9 @@ class Player {
|
|||||||
*/
|
*/
|
||||||
public static function parseLogin($player) {
|
public static function parseLogin($player) {
|
||||||
if (is_object($player) && property_exists($player, 'login')) {
|
if (is_object($player) && property_exists($player, 'login')) {
|
||||||
return (string)$player->login;
|
return (string) $player->login;
|
||||||
}
|
}
|
||||||
return (string)$player;
|
return (string) $player;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -235,14 +237,14 @@ class Player {
|
|||||||
public function updatePlayerFlags($flags) {
|
public function updatePlayerFlags($flags) {
|
||||||
//Detail flags
|
//Detail flags
|
||||||
$this->forcedSpectatorState = $flags % 10; // 0, 1 or 2
|
$this->forcedSpectatorState = $flags % 10; // 0, 1 or 2
|
||||||
$this->isReferee = (bool)(intval($flags / 10) % 10);
|
$this->isReferee = (bool) (intval($flags / 10) % 10);
|
||||||
$this->isPodiumReady = (bool)(intval($flags / 100) % 10);
|
$this->isPodiumReady = (bool) (intval($flags / 100) % 10);
|
||||||
$this->isUsingStereoscopy = (bool)(intval($flags / 1000) % 10);
|
$this->isUsingStereoscopy = (bool) (intval($flags / 1000) % 10);
|
||||||
$this->isManagedByAnOtherServer = (bool)(intval($flags / 10000) % 10);
|
$this->isManagedByAnOtherServer = (bool) (intval($flags / 10000) % 10);
|
||||||
$this->isServer = (bool)(intval($flags / 100000) % 10);
|
$this->isServer = (bool) (intval($flags / 100000) % 10);
|
||||||
$this->hasPlayerSlot = (bool)(intval($flags / 1000000) % 10);
|
$this->hasPlayerSlot = (bool) (intval($flags / 1000000) % 10);
|
||||||
$this->isBroadcasting = (bool)(intval($flags / 10000000) % 10);
|
$this->isBroadcasting = (bool) (intval($flags / 10000000) % 10);
|
||||||
$this->hasJoinedGame = (bool)(intval($flags / 100000000) % 10);
|
$this->hasJoinedGame = (bool) (intval($flags / 100000000) % 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -252,10 +254,10 @@ class Player {
|
|||||||
*/
|
*/
|
||||||
public function updateSpectatorStatus($spectatorStatus) {
|
public function updateSpectatorStatus($spectatorStatus) {
|
||||||
//Details spectatorStatus
|
//Details spectatorStatus
|
||||||
$this->isSpectator = (bool)($spectatorStatus % 10);
|
$this->isSpectator = (bool) ($spectatorStatus % 10);
|
||||||
$this->isTemporarySpectator = (bool)(intval($spectatorStatus / 10) % 10);
|
$this->isTemporarySpectator = (bool) (intval($spectatorStatus / 10) % 10);
|
||||||
$this->isPureSpectator = (bool)(intval($spectatorStatus / 100) % 10);
|
$this->isPureSpectator = (bool) (intval($spectatorStatus / 100) % 10);
|
||||||
$this->autoTarget = (bool)(intval($spectatorStatus / 1000) % 10);
|
$this->autoTarget = (bool) (intval($spectatorStatus / 1000) % 10);
|
||||||
$this->currentTargetId = intval($spectatorStatus / 10000);
|
$this->currentTargetId = intval($spectatorStatus / 10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,10 @@ use FML\Controls\Quad;
|
|||||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||||
use FML\ManiaLink;
|
use FML\ManiaLink;
|
||||||
use ManiaControl\Admin\AuthenticationManager;
|
use ManiaControl\Admin\AuthenticationManager;
|
||||||
|
use ManiaControl\Callbacks\EchoListener;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Manialinks\ManialinkManager;
|
use ManiaControl\Manialinks\ManialinkManager;
|
||||||
@ -26,7 +30,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class PlayerActions {
|
class PlayerActions implements EchoListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -36,6 +40,7 @@ class PlayerActions {
|
|||||||
const SPECTATOR_SPECTATOR = 1;
|
const SPECTATOR_SPECTATOR = 1;
|
||||||
const SPECTATOR_PLAYER = 2;
|
const SPECTATOR_PLAYER = 2;
|
||||||
const SPECTATOR_BUT_KEEP_SELECTABLE = 3;
|
const SPECTATOR_BUT_KEEP_SELECTABLE = 3;
|
||||||
|
const ECHO_WARN_PLAYER = 'ManiaControl.PlayerManager.WarnPlayer';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Permission Setting Constants
|
* Permission Setting Constants
|
||||||
@ -48,6 +53,7 @@ class PlayerActions {
|
|||||||
const SETTING_PERMISSION_KICK_PLAYER = 'Kick Player';
|
const SETTING_PERMISSION_KICK_PLAYER = 'Kick Player';
|
||||||
const SETTING_PERMISSION_BAN_PLAYER = 'Ban Player';
|
const SETTING_PERMISSION_BAN_PLAYER = 'Ban Player';
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
@ -70,6 +76,75 @@ class PlayerActions {
|
|||||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_PLAY, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_PLAY, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_TEAM, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_TEAM, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_SPEC, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_SPEC, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||||
|
|
||||||
|
// Echo Warn Command (Usage: sendEcho json_encode("player" => "loginName")
|
||||||
|
$this->maniaControl->getEchoManager()->registerEchoListener(self::ECHO_WARN_PLAYER, $this, function ($params) {
|
||||||
|
$this->warnPlayer(null, $params->player, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Communication Manager Methods
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::WARN_PLAYER, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "login")) {
|
||||||
|
return new CommunicationAnswer("You have to provide a valid player Login", true);
|
||||||
|
}
|
||||||
|
$success = $this->warnPlayer(null, $data->login, false);
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::MUTE_PLAYER, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "login")) {
|
||||||
|
return new CommunicationAnswer("You have to provide a valid player Login", true);
|
||||||
|
}
|
||||||
|
$success = $this->mutePlayer(null, $data->login, false);
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::UNMUTE_PLAYER, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "login")) {
|
||||||
|
return new CommunicationAnswer("You have to provide a valid player Login", true);
|
||||||
|
}
|
||||||
|
$success = $this->unMutePlayer(null, $data->login, false);
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::KICK_PLAYER, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "login")) {
|
||||||
|
return new CommunicationAnswer("You have to provide a valid player Login", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$message = "";
|
||||||
|
if (property_exists($data, "message")) {
|
||||||
|
$message = $data->message;
|
||||||
|
}
|
||||||
|
|
||||||
|
$success = $this->kickPlayer(null, $data->login, $message, false);
|
||||||
|
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::FORCE_PLAYER_TO_SPEC, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "login")) {
|
||||||
|
return new CommunicationAnswer("You have to provide a valid player Login", true);
|
||||||
|
}
|
||||||
|
//TODO allow parameters like spectator state
|
||||||
|
$success = $this->forcePlayerToSpectator(null, $data->login, self::SPECTATOR_BUT_KEEP_SELECTABLE, true, false);
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::FORCE_PLAYER_TO_PLAY, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "login")) {
|
||||||
|
return new CommunicationAnswer("You have to provide a valid player Login", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO allow parameters like spectator state
|
||||||
|
if (property_exists($data, "teamId")) {
|
||||||
|
$success = $this->forcePlayerToTeam(null, $data->login, $data->teamId, false);
|
||||||
|
} else {
|
||||||
|
$success = $this->forcePlayerToPlay(null, $data->login, true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,26 +153,34 @@ class PlayerActions {
|
|||||||
* @param string $adminLogin
|
* @param string $adminLogin
|
||||||
* @param string $targetLogin
|
* @param string $targetLogin
|
||||||
* @param int $teamId
|
* @param int $teamId
|
||||||
|
* @param bool $calledByAdmin
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function forcePlayerToTeam($adminLogin, $targetLogin, $teamId) {
|
public function forcePlayerToTeam($adminLogin, $targetLogin, $teamId, $calledByAdmin = true) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
if ($calledByAdmin) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_TEAM)
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
) {
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_TEAM)) {
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
if (!$admin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
if (!$target || !$admin) {
|
if (!$target) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($target->isSpectator) {
|
if ($target->isSpectator) {
|
||||||
try {
|
try {
|
||||||
if (!$this->forcePlayerToPlay($adminLogin, $targetLogin, true, false)) {
|
if (!$this->forcePlayerToPlay($adminLogin, $targetLogin, true, false, $calledByAdmin)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (FaultException $exception) {
|
} catch (FaultException $exception) {
|
||||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
if ($calledByAdmin) {
|
||||||
|
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,27 +188,43 @@ class PlayerActions {
|
|||||||
$this->maniaControl->getClient()->forcePlayerTeam($target->login, $teamId);
|
$this->maniaControl->getClient()->forcePlayerTeam($target->login, $teamId);
|
||||||
} catch (ServerOptionsException $exception) {
|
} catch (ServerOptionsException $exception) {
|
||||||
$this->forcePlayerToPlay($adminLogin, $targetLogin);
|
$this->forcePlayerToPlay($adminLogin, $targetLogin);
|
||||||
return;
|
return false;
|
||||||
} catch (UnknownPlayerException $exception) {
|
} catch (UnknownPlayerException $exception) {
|
||||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
if ($calledByAdmin) {
|
||||||
return;
|
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
} catch (GameModeException $exception) {
|
} catch (GameModeException $exception) {
|
||||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
if ($calledByAdmin) {
|
||||||
return;
|
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$chatMessage = false;
|
$chatMessage = false;
|
||||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
|
||||||
if ($teamId === self::TEAM_BLUE) {
|
if ($calledByAdmin) {
|
||||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' into the Blue-Team!';
|
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||||
} else if ($teamId === self::TEAM_RED) {
|
if ($teamId === self::TEAM_BLUE) {
|
||||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' into the Red-Team!';
|
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' into the Blue-Team!';
|
||||||
|
} else if ($teamId === self::TEAM_RED) {
|
||||||
|
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' into the Red-Team!';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ($teamId === self::TEAM_BLUE) {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got forced into the Blue-Team!';
|
||||||
|
} else if ($teamId === self::TEAM_RED) {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got forced into the Red-Team!';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$chatMessage) {
|
if (!$chatMessage) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||||
Logger::logInfo($chatMessage, true);
|
Logger::logInfo($chatMessage, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,15 +234,18 @@ class PlayerActions {
|
|||||||
* @param string $targetLogin
|
* @param string $targetLogin
|
||||||
* @param bool $userIsAbleToSelect
|
* @param bool $userIsAbleToSelect
|
||||||
* @param bool $displayAnnouncement
|
* @param bool $displayAnnouncement
|
||||||
|
* @param bool $calledByAdmin
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function forcePlayerToPlay($adminLogin, $targetLogin, $userIsAbleToSelect = true, $displayAnnouncement = true) {
|
public function forcePlayerToPlay($adminLogin, $targetLogin, $userIsAbleToSelect = true, $displayAnnouncement = true, $calledByAdmin = true) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
if ($calledByAdmin) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_PLAY)
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
) {
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_PLAY)) {
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
if (!$target) {
|
if (!$target) {
|
||||||
return false;
|
return false;
|
||||||
@ -152,7 +254,9 @@ class PlayerActions {
|
|||||||
try {
|
try {
|
||||||
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_PLAYER);
|
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_PLAYER);
|
||||||
} catch (ServerOptionsException $exception) {
|
} catch (ServerOptionsException $exception) {
|
||||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
if ($calledByAdmin) {
|
||||||
|
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,14 +264,22 @@ class PlayerActions {
|
|||||||
try {
|
try {
|
||||||
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_USER_SELECTABLE);
|
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_USER_SELECTABLE);
|
||||||
} catch (ServerOptionsException $exception) {
|
} catch (ServerOptionsException $exception) {
|
||||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
if ($calledByAdmin) {
|
||||||
|
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Announce force
|
// Announce force
|
||||||
if ($displayAnnouncement) {
|
if ($displayAnnouncement) {
|
||||||
$chatMessage = $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' to Play!';
|
if ($calledByAdmin) {
|
||||||
|
$chatMessage = $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' to Play!';
|
||||||
|
} else {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got forced to Play!';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -181,29 +293,43 @@ class PlayerActions {
|
|||||||
* @param string $targetLogin
|
* @param string $targetLogin
|
||||||
* @param int $spectatorState
|
* @param int $spectatorState
|
||||||
* @param bool $releaseSlot
|
* @param bool $releaseSlot
|
||||||
|
* @param bool $calledByAdmin
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function forcePlayerToSpectator($adminLogin, $targetLogin, $spectatorState = self::SPECTATOR_BUT_KEEP_SELECTABLE, $releaseSlot = true) {
|
public function forcePlayerToSpectator($adminLogin, $targetLogin, $spectatorState = self::SPECTATOR_BUT_KEEP_SELECTABLE, $releaseSlot = true, $calledByAdmin = true) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
if ($calledByAdmin) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_SPEC)
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
) {
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_SPEC)) {
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$admin) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
|
|
||||||
if (!$admin || !$target || $target->isSpectator) {
|
if (!$target || $target->isSpectator) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->maniaControl->getClient()->forceSpectator($target->login, $spectatorState);
|
$this->maniaControl->getClient()->forceSpectator($target->login, $spectatorState);
|
||||||
} catch (ServerOptionsException $exception) {
|
} catch (ServerOptionsException $exception) {
|
||||||
$this->maniaControl->getChat()->sendException($exception, $admin->login);
|
if ($calledByAdmin) {
|
||||||
return;
|
$this->maniaControl->getChat()->sendException($exception, $admin->login);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
if ($calledByAdmin) {
|
||||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' to Spectator!';
|
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||||
|
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' to Spectator!';
|
||||||
|
} else {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got forced to Spectator!';
|
||||||
|
}
|
||||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||||
Logger::logInfo($chatMessage, true);
|
Logger::logInfo($chatMessage, true);
|
||||||
|
|
||||||
@ -215,39 +341,50 @@ class PlayerActions {
|
|||||||
} catch (UnknownPlayerException $e) {
|
} catch (UnknownPlayerException $e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UnMute a Player
|
* UnMute a Player
|
||||||
*
|
*
|
||||||
* @param string $adminLogin
|
* @param $adminLogin
|
||||||
* @param string $targetLogin
|
* @param $targetLogin
|
||||||
|
* @param bool $calledByAdmin
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function unMutePlayer($adminLogin, $targetLogin) {
|
public function unMutePlayer($adminLogin, $targetLogin, $calledByAdmin = true) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
if ($calledByAdmin) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
) {
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)) {
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
|
|
||||||
if (!$target) {
|
if (!$target) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->maniaControl->getClient()->unIgnore($targetLogin);
|
$this->maniaControl->getClient()->unIgnore($targetLogin);
|
||||||
} catch (NotInListException $e) {
|
} catch (NotInListException $e) {
|
||||||
$this->maniaControl->getChat()->sendError('Player is not ignored!', $adminLogin);
|
$this->maniaControl->getChat()->sendError('Player is not ignored!', $adminLogin);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($calledByAdmin) {
|
||||||
|
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||||
|
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' un-muted ' . $target->getEscapedNickname() . '!';
|
||||||
|
} else {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got un-muted!';
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
|
||||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' un-muted ' . $target->getEscapedNickname() . '!';
|
|
||||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||||
Logger::logInfo($chatMessage, true);
|
Logger::logInfo($chatMessage, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -255,32 +392,42 @@ class PlayerActions {
|
|||||||
*
|
*
|
||||||
* @param string $adminLogin
|
* @param string $adminLogin
|
||||||
* @param string $targetLogin
|
* @param string $targetLogin
|
||||||
|
* @param bool $calledByAdmin
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function mutePlayer($adminLogin, $targetLogin) {
|
public function mutePlayer($adminLogin, $targetLogin, $calledByAdmin = true) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
if ($calledByAdmin) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
) {
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)) {
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
|
|
||||||
if (!$target) {
|
if (!$target) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->maniaControl->getClient()->ignore($targetLogin);
|
$this->maniaControl->getClient()->ignore($targetLogin);
|
||||||
} catch (AlreadyInListException $e) {
|
} catch (AlreadyInListException $e) {
|
||||||
$this->maniaControl->getChat()->sendError("Player already ignored!", $adminLogin);
|
$this->maniaControl->getChat()->sendError("Player already ignored!", $adminLogin);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Announce warning
|
||||||
|
if ($calledByAdmin) {
|
||||||
|
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||||
|
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' muted ' . $target->getEscapedNickname() . '!';
|
||||||
|
} else {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got muted!';
|
||||||
}
|
}
|
||||||
|
|
||||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
|
||||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' muted ' . $target->getEscapedNickname() . '!';
|
|
||||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||||
Logger::logInfo($chatMessage, true);
|
Logger::logInfo($chatMessage, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -288,19 +435,22 @@ class PlayerActions {
|
|||||||
*
|
*
|
||||||
* @param string $adminLogin
|
* @param string $adminLogin
|
||||||
* @param string $targetLogin
|
* @param string $targetLogin
|
||||||
|
* @param bool $calledByAdmin
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function warnPlayer($adminLogin, $targetLogin) {
|
public function warnPlayer($adminLogin, $targetLogin, $calledByAdmin = true) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
if ($calledByAdmin) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_WARN_PLAYER)
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
) {
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_WARN_PLAYER)) {
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
|
|
||||||
if (!$target) {
|
if (!$target) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display warning message
|
// Display warning message
|
||||||
@ -360,49 +510,78 @@ class PlayerActions {
|
|||||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $target);
|
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $target);
|
||||||
|
|
||||||
// Announce warning
|
// Announce warning
|
||||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
if ($calledByAdmin) {
|
||||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' warned ' . $target->getEscapedNickname() . '!';
|
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||||
|
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' warned ' . $target->getEscapedNickname() . '!';
|
||||||
|
} else {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got an administrative warning!';
|
||||||
|
}
|
||||||
|
|
||||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||||
Logger::log($chatMessage, true);
|
Logger::log($chatMessage, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kick a Player
|
* Kick a Player
|
||||||
*
|
*
|
||||||
* @param string $adminLogin
|
* @param $adminLogin
|
||||||
* @param string $targetLogin
|
* @param $targetLogin
|
||||||
* @param string $message
|
* @param string $message
|
||||||
|
* @param bool $calledByAdmin
|
||||||
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function kickPlayer($adminLogin, $targetLogin, $message = '') {
|
public function kickPlayer($adminLogin, $targetLogin, $message = '', $calledByAdmin = true) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
if ($calledByAdmin) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_KICK_PLAYER)
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
) {
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_KICK_PLAYER)) {
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
|
||||||
if (!$target) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
if ($target->isFakePlayer()) {
|
if (!$target) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($target->isFakePlayer()) {
|
||||||
|
try {
|
||||||
$this->maniaControl->getClient()->disconnectFakePlayer($target->login);
|
$this->maniaControl->getClient()->disconnectFakePlayer($target->login);
|
||||||
} else {
|
} catch (PlayerStateException $e) {
|
||||||
$this->maniaControl->getClient()->kick($target->login, $message);
|
if ($calledByAdmin) {
|
||||||
|
$this->maniaControl->getChat()->sendException($e, $admin);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
$this->maniaControl->getClient()->kick($target->login, $message);
|
||||||
|
} catch (UnknownPlayerException $e) {
|
||||||
|
if ($calledByAdmin) {
|
||||||
|
$this->maniaControl->getChat()->sendException($e, $admin);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
} catch (UnknownPlayerException $e) {
|
|
||||||
$this->maniaControl->getChat()->sendException($e, $admin);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Announce kick
|
// Announce kick
|
||||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
if ($calledByAdmin) {
|
||||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' kicked ' . $target->getEscapedNickname() . '!';
|
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||||
|
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' kicked ' . $target->getEscapedNickname() . '!';
|
||||||
|
} else {
|
||||||
|
$chatMessage = $target->getEscapedNickname() . ' got kicked!';
|
||||||
|
}
|
||||||
|
|
||||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||||
Logger::logInfo($chatMessage, true);
|
Logger::logInfo($chatMessage, true);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ban a Player
|
* Ban a Player
|
||||||
*
|
*
|
||||||
@ -412,17 +591,18 @@ class PlayerActions {
|
|||||||
*/
|
*/
|
||||||
public function banPlayer($adminLogin, $targetLogin, $message = '') {
|
public function banPlayer($adminLogin, $targetLogin, $message = '') {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_BAN_PLAYER)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_BAN_PLAYER)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||||
if (!$target) {
|
if (!$target) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($target->isFakePlayer()) {
|
//Todo Validate (Problem: Not connected player isFakePlayer)
|
||||||
|
if ($target->isOfficial && $target->isFakePlayer()) {
|
||||||
$this->maniaControl->getChat()->sendError('It is not possible to Ban a bot', $admin);
|
$this->maniaControl->getChat()->sendError('It is not possible to Ban a bot', $admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -450,8 +630,7 @@ class PlayerActions {
|
|||||||
*/
|
*/
|
||||||
public function unBanPlayer($adminLogin, $targetLogin) {
|
public function unBanPlayer($adminLogin, $targetLogin) {
|
||||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_BAN_PLAYER)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_BAN_PLAYER)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -485,14 +664,12 @@ class PlayerActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$authLevelName = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($authLevel);
|
$authLevelName = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($authLevel);
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkRight($admin, $authLevel + 1)
|
if (!$this->maniaControl->getAuthenticationManager()->checkRight($admin, $authLevel + 1)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getChat()->sendError("You don't have the permission to add a {$authLevelName}!", $admin);
|
$this->maniaControl->getChat()->sendError("You don't have the permission to add a {$authLevelName}!", $admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->maniaControl->getAuthenticationManager()->checkRight($target, $authLevel)
|
if ($this->maniaControl->getAuthenticationManager()->checkRight($target, $authLevel)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getChat()->sendError("This Player is already {$authLevelName}!", $admin);
|
$this->maniaControl->getChat()->sendError("This Player is already {$authLevelName}!", $admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -523,15 +700,13 @@ class PlayerActions {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkRight($admin, $target->authLevel + 1)
|
if (!$this->maniaControl->getAuthenticationManager()->checkRight($admin, $target->authLevel + 1)) {
|
||||||
) {
|
|
||||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($target->authLevel);
|
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($target->authLevel);
|
||||||
$this->maniaControl->getChat()->sendError("You can't revoke the Rights of a {$title}!", $admin);
|
$this->maniaControl->getChat()->sendError("You can't revoke the Rights of a {$title}!", $admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->maniaControl->getAuthenticationManager()->checkRight($target, AuthenticationManager::AUTH_LEVEL_MASTERADMIN)
|
if ($this->maniaControl->getAuthenticationManager()->checkRight($target, AuthenticationManager::AUTH_LEVEL_MASTERADMIN)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getChat()->sendError("MasterAdmins can't be removed!", $admin);
|
$this->maniaControl->getChat()->sendError("MasterAdmins can't be removed!", $admin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
private $playersListShown = array();
|
private $playersListShown = array();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,9 +163,9 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
$headFrame = new Frame();
|
$headFrame = new Frame();
|
||||||
$frame->add($headFrame);
|
$frame->add($headFrame);
|
||||||
$headFrame->setY($posY - 5);
|
$headFrame->setY($posY - 5);
|
||||||
|
|
||||||
$labelLineArray = array('Id' => $posX + 5, 'Nickname' => $posX + 18, 'Login' => $posX + 70, 'Location' => $posX + 101);
|
$labelLineArray = array('Id' => $posX + 5, 'Nickname' => $posX + 18, 'Login' => $posX + 70, 'Location' => $posX + 101);
|
||||||
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)
|
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)) {
|
||||||
) {
|
|
||||||
$labelLineArray['Actions'] = $posX + 135;
|
$labelLineArray['Actions'] = $posX + 135;
|
||||||
}
|
}
|
||||||
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $labelLineArray);
|
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $labelLineArray);
|
||||||
@ -195,8 +195,9 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
$lineQuad->setZ(0.001);
|
$lineQuad->setZ(0.001);
|
||||||
}
|
}
|
||||||
|
|
||||||
$array = array($index => $posX + 5, $listPlayer->nickname => $posX + 18, $listPlayer->login => $posX + 70, $path => $posX + 101);
|
$positions = array($posX + 5, $posX + 18, $posX + 70, $posX + 101);
|
||||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, $array);
|
$texts = array($index, $listPlayer->nickname, $listPlayer->login, $path);
|
||||||
|
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, array($positions, $texts));
|
||||||
|
|
||||||
$playerFrame->setY($posY);
|
$playerFrame->setY($posY);
|
||||||
|
|
||||||
@ -304,8 +305,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
$description = 'View Player Profile of $<' . $listPlayer->nickname . '$>';
|
$description = 'View Player Profile of $<' . $listPlayer->nickname . '$>';
|
||||||
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||||
|
|
||||||
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)
|
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)) {
|
||||||
) {
|
|
||||||
// Further Player actions Quad
|
// Further Player actions Quad
|
||||||
$playerQuad = new Quad_Icons64x64_1();
|
$playerQuad = new Quad_Icons64x64_1();
|
||||||
$playerFrame->add($playerQuad);
|
$playerFrame->add($playerQuad);
|
||||||
@ -320,10 +320,8 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->maniaControl->getServer()->isTeamMode()
|
if ($this->maniaControl->getServer()->isTeamMode()) {
|
||||||
) {
|
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_TEAM)) {
|
||||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_TEAM)
|
|
||||||
) {
|
|
||||||
// Force to Red-Team Quad
|
// Force to Red-Team Quad
|
||||||
$redQuad = new Quad_Emblems();
|
$redQuad = new Quad_Emblems();
|
||||||
$playerFrame->add($redQuad);
|
$playerFrame->add($redQuad);
|
||||||
@ -350,8 +348,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
$description = 'Force $<' . $listPlayer->nickname . '$> to Blue Team!';
|
$description = 'Force $<' . $listPlayer->nickname . '$> to Blue Team!';
|
||||||
$blueQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
$blueQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||||
|
|
||||||
} else if ($this->maniaControl->getPluginManager()->isPluginActive(self::DEFAULT_CUSTOM_VOTE_PLUGIN)
|
} else if ($this->maniaControl->getPluginManager()->isPluginActive(self::DEFAULT_CUSTOM_VOTE_PLUGIN)) {
|
||||||
) {
|
|
||||||
// Kick Player Vote
|
// Kick Player Vote
|
||||||
$kickQuad = new Quad_UIConstruction_Buttons();
|
$kickQuad = new Quad_UIConstruction_Buttons();
|
||||||
$playerFrame->add($kickQuad);
|
$playerFrame->add($kickQuad);
|
||||||
@ -365,8 +362,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
$kickQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
$kickQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_PLAY)
|
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_PLAY)) {
|
||||||
) {
|
|
||||||
// Force to Play
|
// Force to Play
|
||||||
$playQuad = new Quad_Emblems();
|
$playQuad = new Quad_Emblems();
|
||||||
$playerFrame->add($playQuad);
|
$playerFrame->add($playQuad);
|
||||||
@ -381,8 +377,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_SPEC)
|
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_SPEC)) {
|
||||||
) {
|
|
||||||
// Force to Spectator Quad
|
// Force to Spectator Quad
|
||||||
$spectatorQuad = new Quad_BgRaceScore2();
|
$spectatorQuad = new Quad_BgRaceScore2();
|
||||||
$playerFrame->add($spectatorQuad);
|
$playerFrame->add($spectatorQuad);
|
||||||
@ -395,8 +390,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
// Force to Spectator Description Label
|
// Force to Spectator Description Label
|
||||||
$description = 'Force $<' . $listPlayer->nickname . '$> to Spectator!';
|
$description = 'Force $<' . $listPlayer->nickname . '$> to Spectator!';
|
||||||
$spectatorQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
$spectatorQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||||
} else if ($this->maniaControl->getPluginManager()->isPluginActive(self::DEFAULT_CUSTOM_VOTE_PLUGIN)
|
} else if ($this->maniaControl->getPluginManager()->isPluginActive(self::DEFAULT_CUSTOM_VOTE_PLUGIN)) {
|
||||||
) {
|
|
||||||
// Force to Spectator Quad
|
// Force to Spectator Quad
|
||||||
$spectatorQuad = new Quad_BgRaceScore2();
|
$spectatorQuad = new Quad_BgRaceScore2();
|
||||||
$playerFrame->add($spectatorQuad);
|
$playerFrame->add($spectatorQuad);
|
||||||
@ -451,7 +445,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
// mainframe
|
// mainframe
|
||||||
$frame = new Frame();
|
$frame = new Frame();
|
||||||
$frame->setSize($width, $height);
|
$frame->setSize($width, $height);
|
||||||
$frame->setPosition($posX + $width / 2, 0);
|
$frame->setPosition($posX + $width / 2, 0, 31);
|
||||||
|
|
||||||
// Add Close Quad (X)
|
// Add Close Quad (X)
|
||||||
$closeQuad = new Quad_Icons64x64_1();
|
$closeQuad = new Quad_Icons64x64_1();
|
||||||
@ -467,14 +461,14 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
|||||||
$backgroundQuad->setSize($width, $height);
|
$backgroundQuad->setSize($width, $height);
|
||||||
$backgroundQuad->setImage('https://dl.dropboxusercontent.com/u/105352981/Stuff/CAM%20SM%20BORDER%20PNG.png'); //TODO just a test
|
$backgroundQuad->setImage('https://dl.dropboxusercontent.com/u/105352981/Stuff/CAM%20SM%20BORDER%20PNG.png'); //TODO just a test
|
||||||
//$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
//$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||||
$backgroundQuad->setZ(0.2);
|
$backgroundQuad->setZ(-0.3);
|
||||||
|
|
||||||
// Background Quad
|
// Background Quad
|
||||||
$backgroundQuad = new Quad();
|
$backgroundQuad = new Quad();
|
||||||
$frame->add($backgroundQuad);
|
$frame->add($backgroundQuad);
|
||||||
$backgroundQuad->setSize($width - 2, $height - 2);
|
$backgroundQuad->setSize($width - 2, $height - 2);
|
||||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||||
$backgroundQuad->setZ(0.1);
|
$backgroundQuad->setZ(-0.4);
|
||||||
|
|
||||||
// Show headline
|
// Show headline
|
||||||
$label = new Label_Text();
|
$label = new Label_Text();
|
||||||
|
@ -7,6 +7,9 @@ use ManiaControl\Callbacks\CallbackListener;
|
|||||||
use ManiaControl\Callbacks\CallbackManager;
|
use ManiaControl\Callbacks\CallbackManager;
|
||||||
use ManiaControl\Callbacks\Callbacks;
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
use ManiaControl\Callbacks\TimerListener;
|
use ManiaControl\Callbacks\TimerListener;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Statistics\StatisticManager;
|
use ManiaControl\Statistics\StatisticManager;
|
||||||
@ -20,7 +23,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class PlayerManager implements CallbackListener, TimerListener {
|
class PlayerManager implements CallbackListener, TimerListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -105,6 +108,12 @@ class PlayerManager implements CallbackListener, TimerListener {
|
|||||||
// Player stats
|
// Player stats
|
||||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_JOIN_COUNT);
|
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_JOIN_COUNT);
|
||||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_SERVERTIME, StatisticManager::STAT_TYPE_TIME);
|
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_SERVERTIME, StatisticManager::STAT_TYPE_TIME);
|
||||||
|
|
||||||
|
|
||||||
|
// Communication Listenings
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GET_PLAYER_LIST, $this, function ($data) {
|
||||||
|
return new CommunicationAnswer($this->players);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -184,6 +193,7 @@ class PlayerManager implements CallbackListener, TimerListener {
|
|||||||
return $this->adminLists;
|
return $this->adminLists;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle OnInit callback
|
* Handle OnInit callback
|
||||||
*/
|
*/
|
||||||
@ -374,15 +384,24 @@ class PlayerManager implements CallbackListener, TimerListener {
|
|||||||
* Get the count of all Players
|
* Get the count of all Players
|
||||||
*
|
*
|
||||||
* @param bool $withoutSpectators
|
* @param bool $withoutSpectators
|
||||||
|
* @param bool $withoutBots
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function getPlayerCount($withoutSpectators = true) {
|
public function getPlayerCount($withoutSpectators = true, $withoutBots = true) {
|
||||||
if (!$withoutSpectators) {
|
|
||||||
return count($this->players);
|
|
||||||
}
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
foreach ($this->players as $player) {
|
foreach ($this->players as $player) {
|
||||||
if (!$player->isSpectator) {
|
$valid = true;
|
||||||
|
if ($withoutSpectators) {
|
||||||
|
if ($player->isSpectator) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($withoutBots) {
|
||||||
|
if ($player->isFakePlayer()) {
|
||||||
|
$valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($valid) {
|
||||||
$count++;
|
$count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -516,6 +535,22 @@ class PlayerManager implements CallbackListener, TimerListener {
|
|||||||
return $this->players;
|
return $this->players;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a List of Spectators
|
||||||
|
*
|
||||||
|
* @return Player[]
|
||||||
|
*/
|
||||||
|
public function getSpectators() {
|
||||||
|
$spectators = array();
|
||||||
|
foreach ($this->players as $player) {
|
||||||
|
if ($player->isSpectator) {
|
||||||
|
$spectators[] = $player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $spectators;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the count of all spectators
|
* Get the count of all spectators
|
||||||
*
|
*
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
namespace ManiaControl\Plugins;
|
namespace ManiaControl\Plugins;
|
||||||
|
|
||||||
use ManiaControl\Callbacks\CallbackListener;
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
|
use ManiaControl\Callbacks\EchoListener;
|
||||||
use ManiaControl\Callbacks\TimerListener;
|
use ManiaControl\Callbacks\TimerListener;
|
||||||
use ManiaControl\Commands\CommandListener;
|
use ManiaControl\Commands\CommandListener;
|
||||||
use ManiaControl\Files\FileUtil;
|
use ManiaControl\Files\FileUtil;
|
||||||
@ -141,6 +142,9 @@ class PluginManager {
|
|||||||
|
|
||||||
$plugin->unload();
|
$plugin->unload();
|
||||||
|
|
||||||
|
if ($plugin instanceof EchoListener) {
|
||||||
|
$this->maniaControl->getEchoManager()->unregisterEchoListener($plugin);
|
||||||
|
}
|
||||||
if ($plugin instanceof CallbackListener) {
|
if ($plugin instanceof CallbackListener) {
|
||||||
$this->maniaControl->getCallbackManager()->unregisterCallbackListener($plugin);
|
$this->maniaControl->getCallbackManager()->unregisterCallbackListener($plugin);
|
||||||
$this->maniaControl->getCallbackManager()->unregisterScriptCallbackListener($plugin);
|
$this->maniaControl->getCallbackManager()->unregisterScriptCallbackListener($plugin);
|
||||||
|
@ -40,13 +40,14 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
const SETTING_PERMISSION_CHANGE_SERVERSETTINGS = 'Change ServerSettings';
|
const SETTING_PERMISSION_CHANGE_SERVERSETTINGS = 'Change ServerSettings';
|
||||||
const COMMAND_EXTEND_WARMUP = 'WarmUp_Extend';
|
const COMMAND_EXTEND_WARMUP = 'WarmUp_Extend';
|
||||||
const COMMAND_FORCE_WARMUP = 'Command_ForceWarmUp';
|
const COMMAND_FORCE_WARMUP = 'Command_ForceWarmUp';
|
||||||
|
const COMMAND_SET_PAUSE = 'Command_SetPause';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Private properties
|
* Private properties
|
||||||
*/
|
*/
|
||||||
/** @var ManiaControl $maniaControl */
|
/** @var ManiaControl $maniaControl */
|
||||||
private $maniaControl = null;
|
private $maniaControl = null;
|
||||||
private $serverShutdownTime = -1;
|
private $serverShutdownTime = -1;
|
||||||
private $serverShutdownEmpty = false;
|
private $serverShutdownEmpty = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -113,7 +114,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
try {
|
try {
|
||||||
$scriptInfos = $this->maniaControl->getClient()->getModeScriptInfo();
|
$scriptInfos = $this->maniaControl->getClient()->getModeScriptInfo();
|
||||||
foreach ($scriptInfos->commandDescs as $param) {
|
foreach ($scriptInfos->commandDescs as $param) {
|
||||||
if ($param->name === self::COMMAND_FORCE_WARMUP) {
|
if ($param->name === self::COMMAND_FORCE_WARMUP || $param->name === self::COMMAND_SET_PAUSE) {
|
||||||
$pauseExists = true;
|
$pauseExists = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -163,14 +164,12 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandCancelVote(array $chatCallback, Player $player) {
|
public function commandCancelVote(array $chatCallback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CANCEL_VOTE)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CANCEL_VOTE)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->maniaControl->getClient()->cancelVote()
|
if ($this->maniaControl->getClient()->cancelVote()) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' cancelled the Vote!');
|
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' cancelled the Vote!');
|
||||||
} else {
|
} else {
|
||||||
$this->maniaControl->getChat()->sendInformation("There's no vote running currently!", $player);
|
$this->maniaControl->getChat()->sendInformation("There's no vote running currently!", $player);
|
||||||
@ -187,8 +186,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandExtendWarmup(array $callback, Player $player) {
|
public function commandExtendWarmup(array $callback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_HANDLE_WARMUP)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_HANDLE_WARMUP)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -207,8 +205,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandEndWarmup(array $callback, Player $player) {
|
public function commandEndWarmup(array $callback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_HANDLE_WARMUP)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_HANDLE_WARMUP)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -227,16 +224,27 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function setPause(array $callback, Player $player) {
|
public function setPause(array $callback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SET_PAUSE)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SET_PAUSE)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Normal Gamemodes
|
||||||
try {
|
try {
|
||||||
$this->maniaControl->getClient()->sendModeScriptCommands(array('Command_ForceWarmUp' => true));
|
$this->maniaControl->getClient()->sendModeScriptCommands(array('Command_ForceWarmUp' => true));
|
||||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' paused the Game!');
|
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' paused the Game!');
|
||||||
} catch (GameModeException $e) {
|
} catch (GameModeException $e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
//Chase and Combo?
|
||||||
|
$this->maniaControl->getClient()->sendModeScriptCommands(array('Command_SetPause' => true));
|
||||||
|
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' paused the Game!');
|
||||||
|
|
||||||
|
//Especially for chase, force end of the round to reach a draw
|
||||||
|
$this->maniaControl->getClient()->sendModeScriptCommands(array('Command_ForceEndRound' => true));
|
||||||
|
} catch (GameModeException $ex) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -246,8 +254,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
// TODO: move empty & delayed shutdown code into server class
|
// TODO: move empty & delayed shutdown code into server class
|
||||||
// Empty shutdown
|
// Empty shutdown
|
||||||
if ($this->serverShutdownEmpty) {
|
if ($this->serverShutdownEmpty) {
|
||||||
if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) <= 0
|
if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) <= 0) {
|
||||||
) {
|
|
||||||
$this->shutdownServer('empty');
|
$this->shutdownServer('empty');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -277,8 +284,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandSystemInfo(array $chat, Player $player) {
|
public function commandSystemInfo(array $chat, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SHOW_SYSTEMINFO)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SHOW_SYSTEMINFO)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -294,8 +300,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandShutdownServer(array $chat, Player $player) {
|
public function commandShutdownServer(array $chat, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SHUTDOWN_SERVER)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SHUTDOWN_SERVER)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -312,7 +317,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
$this->maniaControl->getChat()->sendInformation("Empty-shutdown cancelled!", $player);
|
$this->maniaControl->getChat()->sendInformation("Empty-shutdown cancelled!", $player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$delay = (int)$param;
|
$delay = (int) $param;
|
||||||
if ($delay <= 0) {
|
if ($delay <= 0) {
|
||||||
// Cancel shutdown
|
// Cancel shutdown
|
||||||
$this->serverShutdownTime = -1;
|
$this->serverShutdownTime = -1;
|
||||||
@ -334,8 +339,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandSetServerName(array $chat, Player $player) {
|
public function commandSetServerName(array $chat, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -356,8 +360,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandSetPwd(array $chatCallback, Player $player) {
|
public function commandSetPwd(array $chatCallback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -379,8 +382,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandSetSpecPwd(array $chatCallback, Player $player) {
|
public function commandSetSpecPwd(array $chatCallback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -402,8 +404,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandSetMaxPlayers(array $chatCallback, Player $player) {
|
public function commandSetMaxPlayers(array $chatCallback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -417,7 +418,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxplayers 16', $player);
|
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxplayers 16', $player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$amount = (int)$amount;
|
$amount = (int) $amount;
|
||||||
if ($amount < 0) {
|
if ($amount < 0) {
|
||||||
$amount = 0;
|
$amount = 0;
|
||||||
}
|
}
|
||||||
@ -433,8 +434,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
* @param Player $player
|
* @param Player $player
|
||||||
*/
|
*/
|
||||||
public function commandSetMaxSpectators(array $chatCallback, Player $player) {
|
public function commandSetMaxSpectators(array $chatCallback, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -448,7 +448,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
|||||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxspectators 16', $player);
|
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxspectators 16', $player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$amount = (int)$amount;
|
$amount = (int) $amount;
|
||||||
if ($amount < 0) {
|
if ($amount < 0) {
|
||||||
$amount = 0;
|
$amount = 0;
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ namespace ManiaControl\Server;
|
|||||||
|
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
|
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manager for Game Mode Script related Stuff
|
* Manager for Game Mode Script related Stuff
|
||||||
@ -39,13 +40,18 @@ class ScriptManager {
|
|||||||
if (!$this->isScriptMode()) {
|
if (!$this->isScriptMode()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
|
||||||
|
try {
|
||||||
|
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||||||
|
} catch (GameModeException $e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!array_key_exists('S_UseScriptCallbacks', $scriptSettings)) {
|
if (!array_key_exists('S_UseScriptCallbacks', $scriptSettings)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$scriptSettings['S_UseScriptCallbacks'] = (bool)$enable;
|
$scriptSettings['S_UseScriptCallbacks'] = (bool) $enable;
|
||||||
$actionName = ($enable ? 'en' : 'dis');
|
$actionName = ($enable ? 'en' : 'dis');
|
||||||
|
|
||||||
$this->maniaControl->getClient()->setModeScriptSettings($scriptSettings);
|
$this->maniaControl->getClient()->setModeScriptSettings($scriptSettings);
|
||||||
|
@ -4,6 +4,7 @@ namespace ManiaControl\Server;
|
|||||||
|
|
||||||
use ManiaControl\Callbacks\CallbackListener;
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
use ManiaControl\Callbacks\Callbacks;
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
|
use ManiaControl\Commands\CommandListener;
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
use ManiaControl\Players\Player;
|
use ManiaControl\Players\Player;
|
||||||
@ -17,7 +18,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\Exception;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class Server implements CallbackListener {
|
class Server implements CallbackListener, CommandListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -85,6 +86,30 @@ class Server implements CallbackListener {
|
|||||||
|
|
||||||
// Callbacks
|
// Callbacks
|
||||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
||||||
|
|
||||||
|
$this->maniaControl->getCommandManager()->registerCommandListener("uptime", $this, "chatUpTime", true, "Show how long the server is running.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays how long the Server is running already in the Chat
|
||||||
|
*
|
||||||
|
* @param array $chatCallback
|
||||||
|
* @param \ManiaControl\Players\Player $player
|
||||||
|
*/
|
||||||
|
public function chatUpTime(array $chatCallback, Player $player) {
|
||||||
|
$networkStats = $this->maniaControl->getClient()->getNetworkStats();
|
||||||
|
|
||||||
|
$minutestotal = $networkStats->uptime / 60;
|
||||||
|
$hourstotal = $minutestotal / 60;
|
||||||
|
$days = intval($hourstotal / 24);
|
||||||
|
$hours = intval($hourstotal - 24 * $days);
|
||||||
|
$minutes = intval($minutestotal - 24 * 60 * $days - $hours * 60);
|
||||||
|
|
||||||
|
$days > 1 ? $dayString = 'days' : $dayString = 'day';
|
||||||
|
$hours > 1 ? $hourString = 'hours' : $hourString = 'hour';
|
||||||
|
$minutes > 1 ? $minuteString = 'minutes' : $minuteString = 'minute';
|
||||||
|
|
||||||
|
$this->maniaControl->getChat()->sendChat('Server is running since $<$fff' . $days . '$> ' . $dayString . ', $<$fff' . $hours . '$> ' . $hourString . ' and $<$fff' . $minutes . '$> ' . $minuteString, $player);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -226,6 +251,30 @@ class Server implements CallbackListener {
|
|||||||
return $servers;
|
return $servers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get Server Login by Index
|
||||||
|
*
|
||||||
|
* @param int $index
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getServerLoginByIndex($index) {
|
||||||
|
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||||
|
$query = "SELECT * FROM `" . self::TABLE_SERVERS . "` WHERE `index`=" . $index . ";";
|
||||||
|
$result = $mysqli->query($query);
|
||||||
|
|
||||||
|
if (!$result) {
|
||||||
|
trigger_error($mysqli->error);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result->num_rows != 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = $result->fetch_object();
|
||||||
|
|
||||||
|
return $row->login;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle OnInit Callback
|
* Handle OnInit Callback
|
||||||
*/
|
*/
|
||||||
|
@ -14,6 +14,9 @@ use ManiaControl\Admin\AuthenticationManager;
|
|||||||
use ManiaControl\Callbacks\CallbackListener;
|
use ManiaControl\Callbacks\CallbackListener;
|
||||||
use ManiaControl\Callbacks\Callbacks;
|
use ManiaControl\Callbacks\Callbacks;
|
||||||
use ManiaControl\Callbacks\TimerListener;
|
use ManiaControl\Callbacks\TimerListener;
|
||||||
|
use ManiaControl\Communication\CommunicationAnswer;
|
||||||
|
use ManiaControl\Communication\CommunicationListener;
|
||||||
|
use ManiaControl\Communication\CommunicationMethods;
|
||||||
use ManiaControl\Configurator\ConfiguratorMenu;
|
use ManiaControl\Configurator\ConfiguratorMenu;
|
||||||
use ManiaControl\Logger;
|
use ManiaControl\Logger;
|
||||||
use ManiaControl\ManiaControl;
|
use ManiaControl\ManiaControl;
|
||||||
@ -28,7 +31,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\ServerOptionsException;
|
|||||||
* @copyright 2014-2015 ManiaControl Team
|
* @copyright 2014-2015 ManiaControl Team
|
||||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||||
*/
|
*/
|
||||||
class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerListener {
|
class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerListener, CommunicationListener {
|
||||||
/*
|
/*
|
||||||
* Constants
|
* Constants
|
||||||
*/
|
*/
|
||||||
@ -64,6 +67,10 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
|
|||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_SERVER_OPTIONS, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_SERVER_OPTIONS, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||||
|
|
||||||
|
//TODO remove to somewhere cleaner
|
||||||
|
//Communication Listenings
|
||||||
|
$this->initalizeCommunicationListenings();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -322,8 +329,7 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
|
|||||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||||
*/
|
*/
|
||||||
public function saveConfigData(array $configData, Player $player) {
|
public function saveConfigData(array $configData, Player $player) {
|
||||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVER_OPTIONS)
|
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVER_OPTIONS)) {
|
||||||
) {
|
|
||||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -376,4 +382,43 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the communication Listenings
|
||||||
|
*/
|
||||||
|
private function initalizeCommunicationListenings() {
|
||||||
|
//Communication Listenings
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::GET_SERVER_OPTIONS, $this, function ($data) {
|
||||||
|
return new CommunicationAnswer($this->maniaControl->getClient()->getServerOptions());
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->maniaControl->getCommunicationManager()->registerCommunicationListener(CommunicationMethods::SET_SERVER_OPTIONS, $this, function ($data) {
|
||||||
|
if (!is_object($data) || !property_exists($data, "serverOptions")) {
|
||||||
|
return new CommunicationAnswer("No valid ServerOptions provided!", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$oldServerOptions = $this->maniaControl->getClient()->getServerOptions();
|
||||||
|
$newServerOptions = new ServerOptions();
|
||||||
|
|
||||||
|
foreach ($data->serverOptions as $name => $value) {
|
||||||
|
$optionName = $name;
|
||||||
|
$newServerOptions->$optionName = $value;
|
||||||
|
settype($newServerOptions->$optionName, gettype($oldServerOptions->$optionName));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fillUpMandatoryOptions($newServerOptions, $oldServerOptions);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$success = $this->maniaControl->getClient()->setServerOptions($newServerOptions);
|
||||||
|
} catch (ServerOptionsException $exception) {
|
||||||
|
return new CommunicationAnswer($exception->getMessage(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Trigger Server Options Changed Callback
|
||||||
|
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SERVER_OPTIONS_CHANGED, array(self::CB_SERVER_OPTIONS_CHANGED));
|
||||||
|
|
||||||
|
return new CommunicationAnswer(array("success" => $success));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,6 +77,16 @@ class SystemUtil {
|
|||||||
Logger::log($message . 'FOUND!');
|
Logger::log($message . 'FOUND!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for Zlib
|
||||||
|
$message = 'Checking for installed Zlib ... ';
|
||||||
|
if (!extension_loaded('zlib')) {
|
||||||
|
Logger::log($message . 'NOT FOUND!');
|
||||||
|
Logger::log(" -- You don't have Zlib installed! Check: http://php.net/manual/de/zlib.setup.php");
|
||||||
|
$success = false;
|
||||||
|
} else {
|
||||||
|
Logger::log($message . 'FOUND!');
|
||||||
|
}
|
||||||
|
|
||||||
if (!$success) {
|
if (!$success) {
|
||||||
// Missing requirements
|
// Missing requirements
|
||||||
self::quit();
|
self::quit();
|
||||||
|
17
libs/Evenement/EventEmitter.php
Normal file
17
libs/Evenement/EventEmitter.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Evenement.
|
||||||
|
*
|
||||||
|
* (c) Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Evenement;
|
||||||
|
|
||||||
|
class EventEmitter implements EventEmitterInterface
|
||||||
|
{
|
||||||
|
use EventEmitterTrait;
|
||||||
|
}
|
22
libs/Evenement/EventEmitterInterface.php
Normal file
22
libs/Evenement/EventEmitterInterface.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Evenement.
|
||||||
|
*
|
||||||
|
* (c) Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Evenement;
|
||||||
|
|
||||||
|
interface EventEmitterInterface
|
||||||
|
{
|
||||||
|
public function on($event, callable $listener);
|
||||||
|
public function once($event, callable $listener);
|
||||||
|
public function removeListener($event, callable $listener);
|
||||||
|
public function removeAllListeners($event = null);
|
||||||
|
public function listeners($event);
|
||||||
|
public function emit($event, array $arguments = []);
|
||||||
|
}
|
68
libs/Evenement/EventEmitterTrait.php
Normal file
68
libs/Evenement/EventEmitterTrait.php
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Evenement.
|
||||||
|
*
|
||||||
|
* (c) Igor Wiedler <igor@wiedler.ch>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Evenement;
|
||||||
|
|
||||||
|
trait EventEmitterTrait
|
||||||
|
{
|
||||||
|
protected $listeners = [];
|
||||||
|
|
||||||
|
public function on($event, callable $listener)
|
||||||
|
{
|
||||||
|
if (!isset($this->listeners[$event])) {
|
||||||
|
$this->listeners[$event] = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->listeners[$event][] = $listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function once($event, callable $listener)
|
||||||
|
{
|
||||||
|
$onceListener = function () use (&$onceListener, $event, $listener) {
|
||||||
|
$this->removeListener($event, $onceListener);
|
||||||
|
|
||||||
|
call_user_func_array($listener, func_get_args());
|
||||||
|
};
|
||||||
|
|
||||||
|
$this->on($event, $onceListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeListener($event, callable $listener)
|
||||||
|
{
|
||||||
|
if (isset($this->listeners[$event])) {
|
||||||
|
$index = array_search($listener, $this->listeners[$event], true);
|
||||||
|
if (false !== $index) {
|
||||||
|
unset($this->listeners[$event][$index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeAllListeners($event = null)
|
||||||
|
{
|
||||||
|
if ($event !== null) {
|
||||||
|
unset($this->listeners[$event]);
|
||||||
|
} else {
|
||||||
|
$this->listeners = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listeners($event)
|
||||||
|
{
|
||||||
|
return isset($this->listeners[$event]) ? $this->listeners[$event] : [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function emit($event, array $arguments = [])
|
||||||
|
{
|
||||||
|
foreach ($this->listeners($event) as $listener) {
|
||||||
|
call_user_func_array($listener, $arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4250,9 +4250,9 @@ class Connection
|
|||||||
if(is_string($filename))
|
if(is_string($filename))
|
||||||
{
|
{
|
||||||
$filename = $this->stripBom($filename);
|
$filename = $this->stripBom($filename);
|
||||||
if(mb_check_encoding($filename, 'ascii'))
|
if(preg_match('/[^\x09\x0A\x0D\x20-\x7E]/', $filename))
|
||||||
return $filename;
|
return "\xEF\xBB\xBF".$filename;
|
||||||
return "\xEF\xBB\xBF".$filename;
|
return $filename;
|
||||||
}
|
}
|
||||||
return array_map(array($this, 'secureUtf8'), $filename);
|
return array_map(array($this, 'secureUtf8'), $filename);
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,9 @@
|
|||||||
|
|
||||||
namespace Maniaplanet\DedicatedServer\Xmlrpc;
|
namespace Maniaplanet\DedicatedServer\Xmlrpc;
|
||||||
|
|
||||||
class FaultException extends Exception
|
class FaultException extends Exception {
|
||||||
{
|
static function create($faultString, $faultCode) {
|
||||||
static function create($faultString, $faultCode)
|
switch ($faultString) {
|
||||||
{
|
|
||||||
switch($faultString)
|
|
||||||
{
|
|
||||||
case 'Password incorrect.':
|
case 'Password incorrect.':
|
||||||
case 'Permission denied.':
|
case 'Permission denied.':
|
||||||
return new AuthenticationException($faultString, $faultCode);
|
return new AuthenticationException($faultString, $faultCode);
|
||||||
@ -34,6 +31,7 @@ class FaultException extends Exception
|
|||||||
return new LockedFeatureException($faultString, $faultCode);
|
return new LockedFeatureException($faultString, $faultCode);
|
||||||
case 'Login or Uid unknown.':
|
case 'Login or Uid unknown.':
|
||||||
case 'Login unknown.':
|
case 'Login unknown.':
|
||||||
|
case 'Payer login unknown.':
|
||||||
return new UnknownPlayerException($faultString, $faultCode);
|
return new UnknownPlayerException($faultString, $faultCode);
|
||||||
case 'The player is not a spectator':
|
case 'The player is not a spectator':
|
||||||
case 'The player is not a spectator.':
|
case 'The player is not a spectator.':
|
||||||
@ -72,6 +70,7 @@ class FaultException extends Exception
|
|||||||
case 'You cannot change the max spectators count: AllowSpectatorRelays is activated.':
|
case 'You cannot change the max spectators count: AllowSpectatorRelays is activated.':
|
||||||
case 'There are too many players':
|
case 'There are too many players':
|
||||||
case 'There are too many spectators':
|
case 'There are too many spectators':
|
||||||
|
case 'Unknown hideserver value':
|
||||||
return new ServerOptionsException($faultString, $faultCode);
|
return new ServerOptionsException($faultString, $faultCode);
|
||||||
case 'New mode unknown.':
|
case 'New mode unknown.':
|
||||||
case 'You need to stop the server to change to/from script mode.':
|
case 'You need to stop the server to change to/from script mode.':
|
||||||
@ -79,6 +78,7 @@ class FaultException extends Exception
|
|||||||
case 'Not in Team mode.':
|
case 'Not in Team mode.':
|
||||||
case 'Not in Rounds or Laps mode.':
|
case 'Not in Rounds or Laps mode.':
|
||||||
case 'The scores must be decreasing.':
|
case 'The scores must be decreasing.':
|
||||||
|
case 'No current script.':
|
||||||
return new GameModeException($faultString, $faultCode);
|
return new GameModeException($faultString, $faultCode);
|
||||||
case 'Unable to write the black list file.':
|
case 'Unable to write the black list file.':
|
||||||
case 'Unable to write the guest list file.':
|
case 'Unable to write the guest list file.':
|
||||||
@ -90,26 +90,55 @@ class FaultException extends Exception
|
|||||||
case 'Invalid url.':
|
case 'Invalid url.':
|
||||||
return new FileException($faultString, $faultCode);
|
return new FileException($faultString, $faultCode);
|
||||||
}
|
}
|
||||||
if(preg_match('~^Unknown setting \'.*\'\.$~iu', $faultString))
|
if (preg_match('~^Unknown setting \'.*\'\.$~iu', $faultString)) {
|
||||||
return new GameModeException($faultString, $faultCode);
|
return new GameModeException($faultString, $faultCode);
|
||||||
if(preg_match('~^Couldn\'t load \'.*\'\.$~iu', $faultString))
|
}
|
||||||
|
if (preg_match('~^Couldn\'t load \'.*\'\.$~iu', $faultString)) {
|
||||||
return new FileException($faultString, $faultCode);
|
return new FileException($faultString, $faultCode);
|
||||||
|
}
|
||||||
|
|
||||||
return new self($faultString, $faultCode);
|
return new self($faultString, $faultCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AuthenticationException extends FaultException {}
|
class AuthenticationException extends FaultException {
|
||||||
class UnavailableFeatureException extends FaultException {}
|
}
|
||||||
class LockedFeatureException extends FaultException {}
|
|
||||||
class UnknownPlayerException extends FaultException {}
|
class UnavailableFeatureException extends FaultException {
|
||||||
class PlayerStateException extends FaultException {}
|
}
|
||||||
class AlreadyInListException extends FaultException {}
|
|
||||||
class NotInListException extends FaultException {}
|
class LockedFeatureException extends FaultException {
|
||||||
class IndexOutOfBoundException extends FaultException {}
|
}
|
||||||
class NextMapException extends FaultException{}
|
|
||||||
class ChangeInProgressException extends FaultException {}
|
class UnknownPlayerException extends FaultException {
|
||||||
class InvalidMapException extends FaultException{}
|
}
|
||||||
class GameModeException extends FaultException {}
|
|
||||||
class ServerOptionsException extends FaultException {}
|
class PlayerStateException extends FaultException {
|
||||||
class FileException extends FaultException {}
|
}
|
||||||
|
|
||||||
|
class AlreadyInListException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotInListException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class IndexOutOfBoundException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class NextMapException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChangeInProgressException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class InvalidMapException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class GameModeException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class ServerOptionsException extends FaultException {
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileException extends FaultException {
|
||||||
|
}
|
||||||
|
@ -16,8 +16,8 @@ class GbxRemote
|
|||||||
public static $sent;
|
public static $sent;
|
||||||
|
|
||||||
private $socket;
|
private $socket;
|
||||||
private $readTimeout = array('sec' => 5, 'usec' => 0);
|
private $readTimeout = array('sec' => 30, 'usec' => 0);
|
||||||
private $writeTimeout = array('sec' => 5, 'usec' => 0);
|
private $writeTimeout = array('sec' => 30, 'usec' => 0);
|
||||||
private $requestHandle;
|
private $requestHandle;
|
||||||
private $callbacksBuffer = array();
|
private $callbacksBuffer = array();
|
||||||
private $multicallBuffer = array();
|
private $multicallBuffer = array();
|
||||||
|
327
libs/React/EventLoop/ExtEventLoop.php
Normal file
327
libs/React/EventLoop/ExtEventLoop.php
Normal file
@ -0,0 +1,327 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop;
|
||||||
|
|
||||||
|
use Event;
|
||||||
|
use EventBase;
|
||||||
|
use EventConfig as EventBaseConfig;
|
||||||
|
use React\EventLoop\Tick\FutureTickQueue;
|
||||||
|
use React\EventLoop\Tick\NextTickQueue;
|
||||||
|
use React\EventLoop\Timer\Timer;
|
||||||
|
use React\EventLoop\Timer\TimerInterface;
|
||||||
|
use SplObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ext-event based React.
|
||||||
|
*/
|
||||||
|
class ExtEventLoop implements LoopInterface
|
||||||
|
{
|
||||||
|
private $eventBase;
|
||||||
|
private $nextTickQueue;
|
||||||
|
private $futureTickQueue;
|
||||||
|
private $timerCallback;
|
||||||
|
private $timerEvents;
|
||||||
|
private $streamCallback;
|
||||||
|
private $streamEvents = [];
|
||||||
|
private $streamFlags = [];
|
||||||
|
private $readListeners = [];
|
||||||
|
private $writeListeners = [];
|
||||||
|
private $running;
|
||||||
|
|
||||||
|
public function __construct(EventBaseConfig $config = null)
|
||||||
|
{
|
||||||
|
$this->eventBase = new EventBase($config);
|
||||||
|
$this->nextTickQueue = new NextTickQueue($this);
|
||||||
|
$this->futureTickQueue = new FutureTickQueue($this);
|
||||||
|
$this->timerEvents = new SplObjectStorage();
|
||||||
|
|
||||||
|
$this->createTimerCallback();
|
||||||
|
$this->createStreamCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addReadStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (!isset($this->readListeners[$key])) {
|
||||||
|
$this->readListeners[$key] = $listener;
|
||||||
|
$this->subscribeStreamEvent($stream, Event::READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addWriteStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (!isset($this->writeListeners[$key])) {
|
||||||
|
$this->writeListeners[$key] = $listener;
|
||||||
|
$this->subscribeStreamEvent($stream, Event::WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeReadStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->readListeners[$key])) {
|
||||||
|
unset($this->readListeners[$key]);
|
||||||
|
$this->unsubscribeStreamEvent($stream, Event::READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeWriteStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->writeListeners[$key])) {
|
||||||
|
unset($this->writeListeners[$key]);
|
||||||
|
$this->unsubscribeStreamEvent($stream, Event::WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->streamEvents[$key])) {
|
||||||
|
$this->streamEvents[$key]->free();
|
||||||
|
|
||||||
|
unset(
|
||||||
|
$this->streamFlags[$key],
|
||||||
|
$this->streamEvents[$key],
|
||||||
|
$this->readListeners[$key],
|
||||||
|
$this->writeListeners[$key]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, false);
|
||||||
|
|
||||||
|
$this->scheduleTimer($timer);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addPeriodicTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, true);
|
||||||
|
|
||||||
|
$this->scheduleTimer($timer);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function cancelTimer(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
if ($this->isTimerActive($timer)) {
|
||||||
|
$this->timerEvents[$timer]->free();
|
||||||
|
$this->timerEvents->detach($timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isTimerActive(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
return $this->timerEvents->contains($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function nextTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function futureTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->futureTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function tick()
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
// @-suppression: https://github.com/reactphp/react/pull/234#discussion-diff-7759616R226
|
||||||
|
@$this->eventBase->loop(EventBase::LOOP_ONCE | EventBase::LOOP_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->running = true;
|
||||||
|
|
||||||
|
while ($this->running) {
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
$flags = EventBase::LOOP_ONCE;
|
||||||
|
if (!$this->running || !$this->nextTickQueue->isEmpty() || !$this->futureTickQueue->isEmpty()) {
|
||||||
|
$flags |= EventBase::LOOP_NONBLOCK;
|
||||||
|
} elseif (!$this->streamEvents && !$this->timerEvents->count()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @-suppression: https://github.com/reactphp/react/pull/234#discussion-diff-7759616R226
|
||||||
|
@$this->eventBase->loop($flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function stop()
|
||||||
|
{
|
||||||
|
$this->running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a timer for execution.
|
||||||
|
*
|
||||||
|
* @param TimerInterface $timer
|
||||||
|
*/
|
||||||
|
private function scheduleTimer(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
$flags = Event::TIMEOUT;
|
||||||
|
|
||||||
|
if ($timer->isPeriodic()) {
|
||||||
|
$flags |= Event::PERSIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event = new Event($this->eventBase, -1, $flags, $this->timerCallback, $timer);
|
||||||
|
$this->timerEvents[$timer] = $event;
|
||||||
|
|
||||||
|
$event->add($timer->getInterval());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ext-event Event object, or update the existing one.
|
||||||
|
*
|
||||||
|
* @param resource $stream
|
||||||
|
* @param integer $flag Event::READ or Event::WRITE
|
||||||
|
*/
|
||||||
|
private function subscribeStreamEvent($stream, $flag)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->streamEvents[$key])) {
|
||||||
|
$event = $this->streamEvents[$key];
|
||||||
|
$flags = ($this->streamFlags[$key] |= $flag);
|
||||||
|
|
||||||
|
$event->del();
|
||||||
|
$event->set($this->eventBase, $stream, Event::PERSIST | $flags, $this->streamCallback);
|
||||||
|
} else {
|
||||||
|
$event = new Event($this->eventBase, $stream, Event::PERSIST | $flag, $this->streamCallback);
|
||||||
|
|
||||||
|
$this->streamEvents[$key] = $event;
|
||||||
|
$this->streamFlags[$key] = $flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event->add();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the ext-event Event object for this stream to stop listening to
|
||||||
|
* the given event type, or remove it entirely if it's no longer needed.
|
||||||
|
*
|
||||||
|
* @param resource $stream
|
||||||
|
* @param integer $flag Event::READ or Event::WRITE
|
||||||
|
*/
|
||||||
|
private function unsubscribeStreamEvent($stream, $flag)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
$flags = $this->streamFlags[$key] &= ~$flag;
|
||||||
|
|
||||||
|
if (0 === $flags) {
|
||||||
|
$this->removeStream($stream);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event = $this->streamEvents[$key];
|
||||||
|
|
||||||
|
$event->del();
|
||||||
|
$event->set($this->eventBase, $stream, Event::PERSIST | $flags, $this->streamCallback);
|
||||||
|
$event->add();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a callback used as the target of timer events.
|
||||||
|
*
|
||||||
|
* A reference is kept to the callback for the lifetime of the loop
|
||||||
|
* to prevent "Cannot destroy active lambda function" fatal error from
|
||||||
|
* the event extension.
|
||||||
|
*/
|
||||||
|
private function createTimerCallback()
|
||||||
|
{
|
||||||
|
$this->timerCallback = function ($_, $_, $timer) {
|
||||||
|
call_user_func($timer->getCallback(), $timer);
|
||||||
|
|
||||||
|
if (!$timer->isPeriodic() && $this->isTimerActive($timer)) {
|
||||||
|
$this->cancelTimer($timer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a callback used as the target of stream events.
|
||||||
|
*
|
||||||
|
* A reference is kept to the callback for the lifetime of the loop
|
||||||
|
* to prevent "Cannot destroy active lambda function" fatal error from
|
||||||
|
* the event extension.
|
||||||
|
*/
|
||||||
|
private function createStreamCallback()
|
||||||
|
{
|
||||||
|
$this->streamCallback = function ($stream, $flags) {
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (Event::READ === (Event::READ & $flags) && isset($this->readListeners[$key])) {
|
||||||
|
call_user_func($this->readListeners[$key], $stream, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Event::WRITE === (Event::WRITE & $flags) && isset($this->writeListeners[$key])) {
|
||||||
|
call_user_func($this->writeListeners[$key], $stream, $this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
21
libs/React/EventLoop/Factory.php
Normal file
21
libs/React/EventLoop/Factory.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop;
|
||||||
|
|
||||||
|
class Factory
|
||||||
|
{
|
||||||
|
public static function create()
|
||||||
|
{
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
if (function_exists('event_base_new')) {
|
||||||
|
return new LibEventLoop();
|
||||||
|
} elseif (class_exists('libev\EventLoop', false)) {
|
||||||
|
return new LibEvLoop;
|
||||||
|
} elseif (class_exists('EventBase', false)) {
|
||||||
|
return new ExtEventLoop;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StreamSelectLoop();
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
|
}
|
218
libs/React/EventLoop/LibEvLoop.php
Normal file
218
libs/React/EventLoop/LibEvLoop.php
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop;
|
||||||
|
|
||||||
|
use libev\EventLoop;
|
||||||
|
use libev\IOEvent;
|
||||||
|
use libev\TimerEvent;
|
||||||
|
use React\EventLoop\Tick\FutureTickQueue;
|
||||||
|
use React\EventLoop\Tick\NextTickQueue;
|
||||||
|
use React\EventLoop\Timer\Timer;
|
||||||
|
use React\EventLoop\Timer\TimerInterface;
|
||||||
|
use SplObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://github.com/m4rw3r/php-libev
|
||||||
|
* @see https://gist.github.com/1688204
|
||||||
|
*/
|
||||||
|
class LibEvLoop implements LoopInterface
|
||||||
|
{
|
||||||
|
private $loop;
|
||||||
|
private $nextTickQueue;
|
||||||
|
private $futureTickQueue;
|
||||||
|
private $timerEvents;
|
||||||
|
private $readEvents = [];
|
||||||
|
private $writeEvents = [];
|
||||||
|
private $running;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->loop = new EventLoop();
|
||||||
|
$this->nextTickQueue = new NextTickQueue($this);
|
||||||
|
$this->futureTickQueue = new FutureTickQueue($this);
|
||||||
|
$this->timerEvents = new SplObjectStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addReadStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$callback = function () use ($stream, $listener) {
|
||||||
|
call_user_func($listener, $stream, $this);
|
||||||
|
};
|
||||||
|
|
||||||
|
$event = new IOEvent($callback, $stream, IOEvent::READ);
|
||||||
|
$this->loop->add($event);
|
||||||
|
|
||||||
|
$this->readEvents[(int) $stream] = $event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addWriteStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$callback = function () use ($stream, $listener) {
|
||||||
|
call_user_func($listener, $stream, $this);
|
||||||
|
};
|
||||||
|
|
||||||
|
$event = new IOEvent($callback, $stream, IOEvent::WRITE);
|
||||||
|
$this->loop->add($event);
|
||||||
|
|
||||||
|
$this->writeEvents[(int) $stream] = $event;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeReadStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->readEvents[$key])) {
|
||||||
|
$this->readEvents[$key]->stop();
|
||||||
|
unset($this->readEvents[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeWriteStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->writeEvents[$key])) {
|
||||||
|
$this->writeEvents[$key]->stop();
|
||||||
|
unset($this->writeEvents[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeStream($stream)
|
||||||
|
{
|
||||||
|
$this->removeReadStream($stream);
|
||||||
|
$this->removeWriteStream($stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, false);
|
||||||
|
|
||||||
|
$callback = function () use ($timer) {
|
||||||
|
call_user_func($timer->getCallback(), $timer);
|
||||||
|
|
||||||
|
if ($this->isTimerActive($timer)) {
|
||||||
|
$this->cancelTimer($timer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$event = new TimerEvent($callback, $timer->getInterval());
|
||||||
|
$this->timerEvents->attach($timer, $event);
|
||||||
|
$this->loop->add($event);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addPeriodicTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, true);
|
||||||
|
|
||||||
|
$callback = function () use ($timer) {
|
||||||
|
call_user_func($timer->getCallback(), $timer);
|
||||||
|
};
|
||||||
|
|
||||||
|
$event = new TimerEvent($callback, $interval, $interval);
|
||||||
|
$this->timerEvents->attach($timer, $event);
|
||||||
|
$this->loop->add($event);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function cancelTimer(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
if (isset($this->timerEvents[$timer])) {
|
||||||
|
$this->loop->remove($this->timerEvents[$timer]);
|
||||||
|
$this->timerEvents->detach($timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isTimerActive(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
return $this->timerEvents->contains($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function nextTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function futureTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->futureTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function tick()
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
$this->loop->run(EventLoop::RUN_ONCE | EventLoop::RUN_NOWAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->running = true;
|
||||||
|
|
||||||
|
while ($this->running) {
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
$flags = EventLoop::RUN_ONCE;
|
||||||
|
if (!$this->running || !$this->nextTickQueue->isEmpty() || !$this->futureTickQueue->isEmpty()) {
|
||||||
|
$flags |= EventLoop::RUN_NOWAIT;
|
||||||
|
} elseif (!$this->readEvents && !$this->writeEvents && !$this->timerEvents->count()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->loop->run($flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function stop()
|
||||||
|
{
|
||||||
|
$this->running = false;
|
||||||
|
}
|
||||||
|
}
|
343
libs/React/EventLoop/LibEventLoop.php
Normal file
343
libs/React/EventLoop/LibEventLoop.php
Normal file
@ -0,0 +1,343 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop;
|
||||||
|
|
||||||
|
use Event;
|
||||||
|
use EventBase;
|
||||||
|
use React\EventLoop\Tick\FutureTickQueue;
|
||||||
|
use React\EventLoop\Tick\NextTickQueue;
|
||||||
|
use React\EventLoop\Timer\Timer;
|
||||||
|
use React\EventLoop\Timer\TimerInterface;
|
||||||
|
use SplObjectStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An ext-libevent based React.
|
||||||
|
*/
|
||||||
|
class LibEventLoop implements LoopInterface
|
||||||
|
{
|
||||||
|
const MICROSECONDS_PER_SECOND = 1000000;
|
||||||
|
|
||||||
|
private $eventBase;
|
||||||
|
private $nextTickQueue;
|
||||||
|
private $futureTickQueue;
|
||||||
|
private $timerCallback;
|
||||||
|
private $timerEvents;
|
||||||
|
private $streamCallback;
|
||||||
|
private $streamEvents = [];
|
||||||
|
private $streamFlags = [];
|
||||||
|
private $readListeners = [];
|
||||||
|
private $writeListeners = [];
|
||||||
|
private $running;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->eventBase = event_base_new();
|
||||||
|
$this->nextTickQueue = new NextTickQueue($this);
|
||||||
|
$this->futureTickQueue = new FutureTickQueue($this);
|
||||||
|
$this->timerEvents = new SplObjectStorage();
|
||||||
|
|
||||||
|
$this->createTimerCallback();
|
||||||
|
$this->createStreamCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addReadStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (!isset($this->readListeners[$key])) {
|
||||||
|
$this->readListeners[$key] = $listener;
|
||||||
|
$this->subscribeStreamEvent($stream, EV_READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addWriteStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (!isset($this->writeListeners[$key])) {
|
||||||
|
$this->writeListeners[$key] = $listener;
|
||||||
|
$this->subscribeStreamEvent($stream, EV_WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeReadStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->readListeners[$key])) {
|
||||||
|
unset($this->readListeners[$key]);
|
||||||
|
$this->unsubscribeStreamEvent($stream, EV_READ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeWriteStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->writeListeners[$key])) {
|
||||||
|
unset($this->writeListeners[$key]);
|
||||||
|
$this->unsubscribeStreamEvent($stream, EV_WRITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->streamEvents[$key])) {
|
||||||
|
$event = $this->streamEvents[$key];
|
||||||
|
|
||||||
|
event_del($event);
|
||||||
|
event_free($event);
|
||||||
|
|
||||||
|
unset(
|
||||||
|
$this->streamFlags[$key],
|
||||||
|
$this->streamEvents[$key],
|
||||||
|
$this->readListeners[$key],
|
||||||
|
$this->writeListeners[$key]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, false);
|
||||||
|
|
||||||
|
$this->scheduleTimer($timer);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addPeriodicTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, true);
|
||||||
|
|
||||||
|
$this->scheduleTimer($timer);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function cancelTimer(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
if ($this->isTimerActive($timer)) {
|
||||||
|
$event = $this->timerEvents[$timer];
|
||||||
|
|
||||||
|
event_del($event);
|
||||||
|
event_free($event);
|
||||||
|
|
||||||
|
$this->timerEvents->detach($timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isTimerActive(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
return $this->timerEvents->contains($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function nextTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function futureTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->futureTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function tick()
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
event_base_loop($this->eventBase, EVLOOP_ONCE | EVLOOP_NONBLOCK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->running = true;
|
||||||
|
|
||||||
|
while ($this->running) {
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
$flags = EVLOOP_ONCE;
|
||||||
|
if (!$this->running || !$this->nextTickQueue->isEmpty() || !$this->futureTickQueue->isEmpty()) {
|
||||||
|
$flags |= EVLOOP_NONBLOCK;
|
||||||
|
} elseif (!$this->streamEvents && !$this->timerEvents->count()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_base_loop($this->eventBase, $flags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function stop()
|
||||||
|
{
|
||||||
|
$this->running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a timer for execution.
|
||||||
|
*
|
||||||
|
* @param TimerInterface $timer
|
||||||
|
*/
|
||||||
|
private function scheduleTimer(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
$this->timerEvents[$timer] = $event = event_timer_new();
|
||||||
|
|
||||||
|
event_timer_set($event, $this->timerCallback, $timer);
|
||||||
|
event_base_set($event, $this->eventBase);
|
||||||
|
event_add($event, $timer->getInterval() * self::MICROSECONDS_PER_SECOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new ext-libevent event resource, or update the existing one.
|
||||||
|
*
|
||||||
|
* @param resource $stream
|
||||||
|
* @param integer $flag EV_READ or EV_WRITE
|
||||||
|
*/
|
||||||
|
private function subscribeStreamEvent($stream, $flag)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->streamEvents[$key])) {
|
||||||
|
$event = $this->streamEvents[$key];
|
||||||
|
$flags = $this->streamFlags[$key] |= $flag;
|
||||||
|
|
||||||
|
event_del($event);
|
||||||
|
event_set($event, $stream, EV_PERSIST | $flags, $this->streamCallback);
|
||||||
|
} else {
|
||||||
|
$event = event_new();
|
||||||
|
|
||||||
|
event_set($event, $stream, EV_PERSIST | $flag, $this->streamCallback);
|
||||||
|
event_base_set($event, $this->eventBase);
|
||||||
|
|
||||||
|
$this->streamEvents[$key] = $event;
|
||||||
|
$this->streamFlags[$key] = $flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
event_add($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the ext-libevent event resource for this stream to stop listening to
|
||||||
|
* the given event type, or remove it entirely if it's no longer needed.
|
||||||
|
*
|
||||||
|
* @param resource $stream
|
||||||
|
* @param integer $flag EV_READ or EV_WRITE
|
||||||
|
*/
|
||||||
|
private function unsubscribeStreamEvent($stream, $flag)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
$flags = $this->streamFlags[$key] &= ~$flag;
|
||||||
|
|
||||||
|
if (0 === $flags) {
|
||||||
|
$this->removeStream($stream);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$event = $this->streamEvents[$key];
|
||||||
|
|
||||||
|
event_del($event);
|
||||||
|
event_set($event, $stream, EV_PERSIST | $flags, $this->streamCallback);
|
||||||
|
event_add($event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a callback used as the target of timer events.
|
||||||
|
*
|
||||||
|
* A reference is kept to the callback for the lifetime of the loop
|
||||||
|
* to prevent "Cannot destroy active lambda function" fatal error from
|
||||||
|
* the event extension.
|
||||||
|
*/
|
||||||
|
private function createTimerCallback()
|
||||||
|
{
|
||||||
|
$this->timerCallback = function ($_, $_, $timer) {
|
||||||
|
call_user_func($timer->getCallback(), $timer);
|
||||||
|
|
||||||
|
// Timer already cancelled ...
|
||||||
|
if (!$this->isTimerActive($timer)) {
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Reschedule periodic timers ...
|
||||||
|
} elseif ($timer->isPeriodic()) {
|
||||||
|
event_add(
|
||||||
|
$this->timerEvents[$timer],
|
||||||
|
$timer->getInterval() * self::MICROSECONDS_PER_SECOND
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clean-up one shot timers ...
|
||||||
|
} else {
|
||||||
|
$this->cancelTimer($timer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a callback used as the target of stream events.
|
||||||
|
*
|
||||||
|
* A reference is kept to the callback for the lifetime of the loop
|
||||||
|
* to prevent "Cannot destroy active lambda function" fatal error from
|
||||||
|
* the event extension.
|
||||||
|
*/
|
||||||
|
private function createStreamCallback()
|
||||||
|
{
|
||||||
|
$this->streamCallback = function ($stream, $flags) {
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (EV_READ === (EV_READ & $flags) && isset($this->readListeners[$key])) {
|
||||||
|
call_user_func($this->readListeners[$key], $stream, $this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EV_WRITE === (EV_WRITE & $flags) && isset($this->writeListeners[$key])) {
|
||||||
|
call_user_func($this->writeListeners[$key], $stream, $this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
121
libs/React/EventLoop/LoopInterface.php
Normal file
121
libs/React/EventLoop/LoopInterface.php
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop;
|
||||||
|
|
||||||
|
use React\EventLoop\Timer\TimerInterface;
|
||||||
|
|
||||||
|
interface LoopInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Register a listener to be notified when a stream is ready to read.
|
||||||
|
*
|
||||||
|
* @param resource $stream The PHP stream resource to check.
|
||||||
|
* @param callable $listener Invoked when the stream is ready.
|
||||||
|
*/
|
||||||
|
public function addReadStream($stream, callable $listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a listener to be notified when a stream is ready to write.
|
||||||
|
*
|
||||||
|
* @param resource $stream The PHP stream resource to check.
|
||||||
|
* @param callable $listener Invoked when the stream is ready.
|
||||||
|
*/
|
||||||
|
public function addWriteStream($stream, callable $listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the read event listener for the given stream.
|
||||||
|
*
|
||||||
|
* @param resource $stream The PHP stream resource.
|
||||||
|
*/
|
||||||
|
public function removeReadStream($stream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the write event listener for the given stream.
|
||||||
|
*
|
||||||
|
* @param resource $stream The PHP stream resource.
|
||||||
|
*/
|
||||||
|
public function removeWriteStream($stream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all listeners for the given stream.
|
||||||
|
*
|
||||||
|
* @param resource $stream The PHP stream resource.
|
||||||
|
*/
|
||||||
|
public function removeStream($stream);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue a callback to be invoked once after the given interval.
|
||||||
|
*
|
||||||
|
* The execution order of timers scheduled to execute at the same time is
|
||||||
|
* not guaranteed.
|
||||||
|
*
|
||||||
|
* @param int|float $interval The number of seconds to wait before execution.
|
||||||
|
* @param callable $callback The callback to invoke.
|
||||||
|
*
|
||||||
|
* @return TimerInterface
|
||||||
|
*/
|
||||||
|
public function addTimer($interval, callable $callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue a callback to be invoked repeatedly after the given interval.
|
||||||
|
*
|
||||||
|
* The execution order of timers scheduled to execute at the same time is
|
||||||
|
* not guaranteed.
|
||||||
|
*
|
||||||
|
* @param int|float $interval The number of seconds to wait before execution.
|
||||||
|
* @param callable $callback The callback to invoke.
|
||||||
|
*
|
||||||
|
* @return TimerInterface
|
||||||
|
*/
|
||||||
|
public function addPeriodicTimer($interval, callable $callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel a pending timer.
|
||||||
|
*
|
||||||
|
* @param TimerInterface $timer The timer to cancel.
|
||||||
|
*/
|
||||||
|
public function cancelTimer(TimerInterface $timer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a given timer is active.
|
||||||
|
*
|
||||||
|
* @param TimerInterface $timer The timer to check.
|
||||||
|
*
|
||||||
|
* @return boolean True if the timer is still enqueued for execution.
|
||||||
|
*/
|
||||||
|
public function isTimerActive(TimerInterface $timer);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a callback to be invoked on the next tick of the event loop.
|
||||||
|
*
|
||||||
|
* Callbacks are guaranteed to be executed in the order they are enqueued,
|
||||||
|
* before any timer or stream events.
|
||||||
|
*
|
||||||
|
* @param callable $listener The callback to invoke.
|
||||||
|
*/
|
||||||
|
public function nextTick(callable $listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a callback to be invoked on a future tick of the event loop.
|
||||||
|
*
|
||||||
|
* Callbacks are guaranteed to be executed in the order they are enqueued.
|
||||||
|
*
|
||||||
|
* @param callable $listener The callback to invoke.
|
||||||
|
*/
|
||||||
|
public function futureTick(callable $listener);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a single iteration of the event loop.
|
||||||
|
*/
|
||||||
|
public function tick();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the event loop until there are no more tasks to perform.
|
||||||
|
*/
|
||||||
|
public function run();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instruct a running event loop to stop.
|
||||||
|
*/
|
||||||
|
public function stop();
|
||||||
|
}
|
262
libs/React/EventLoop/StreamSelectLoop.php
Normal file
262
libs/React/EventLoop/StreamSelectLoop.php
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop;
|
||||||
|
|
||||||
|
use React\EventLoop\Tick\FutureTickQueue;
|
||||||
|
use React\EventLoop\Tick\NextTickQueue;
|
||||||
|
use React\EventLoop\Timer\Timer;
|
||||||
|
use React\EventLoop\Timer\TimerInterface;
|
||||||
|
use React\EventLoop\Timer\Timers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A stream_select() based React.
|
||||||
|
*/
|
||||||
|
class StreamSelectLoop implements LoopInterface
|
||||||
|
{
|
||||||
|
const MICROSECONDS_PER_SECOND = 1000000;
|
||||||
|
|
||||||
|
private $nextTickQueue;
|
||||||
|
private $futureTickQueue;
|
||||||
|
private $timers;
|
||||||
|
private $readStreams = [];
|
||||||
|
private $readListeners = [];
|
||||||
|
private $writeStreams = [];
|
||||||
|
private $writeListeners = [];
|
||||||
|
private $running;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->nextTickQueue = new NextTickQueue($this);
|
||||||
|
$this->futureTickQueue = new FutureTickQueue($this);
|
||||||
|
$this->timers = new Timers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addReadStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (!isset($this->readStreams[$key])) {
|
||||||
|
$this->readStreams[$key] = $stream;
|
||||||
|
$this->readListeners[$key] = $listener;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addWriteStream($stream, callable $listener)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (!isset($this->writeStreams[$key])) {
|
||||||
|
$this->writeStreams[$key] = $stream;
|
||||||
|
$this->writeListeners[$key] = $listener;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeReadStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
unset(
|
||||||
|
$this->readStreams[$key],
|
||||||
|
$this->readListeners[$key]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeWriteStream($stream)
|
||||||
|
{
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
unset(
|
||||||
|
$this->writeStreams[$key],
|
||||||
|
$this->writeListeners[$key]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function removeStream($stream)
|
||||||
|
{
|
||||||
|
$this->removeReadStream($stream);
|
||||||
|
$this->removeWriteStream($stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, false);
|
||||||
|
|
||||||
|
$this->timers->add($timer);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function addPeriodicTimer($interval, callable $callback)
|
||||||
|
{
|
||||||
|
$timer = new Timer($this, $interval, $callback, true);
|
||||||
|
|
||||||
|
$this->timers->add($timer);
|
||||||
|
|
||||||
|
return $timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function cancelTimer(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
$this->timers->cancel($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isTimerActive(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
return $this->timers->contains($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function nextTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function futureTick(callable $listener)
|
||||||
|
{
|
||||||
|
$this->futureTickQueue->add($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function tick()
|
||||||
|
{
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
$this->timers->tick();
|
||||||
|
|
||||||
|
$this->waitForStreamActivity(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
$this->running = true;
|
||||||
|
|
||||||
|
while ($this->running) {
|
||||||
|
$this->nextTickQueue->tick();
|
||||||
|
|
||||||
|
$this->futureTickQueue->tick();
|
||||||
|
|
||||||
|
$this->timers->tick();
|
||||||
|
|
||||||
|
// Next-tick or future-tick queues have pending callbacks ...
|
||||||
|
if (!$this->running || !$this->nextTickQueue->isEmpty() || !$this->futureTickQueue->isEmpty()) {
|
||||||
|
$timeout = 0;
|
||||||
|
|
||||||
|
// There is a pending timer, only block until it is due ...
|
||||||
|
} elseif ($scheduledAt = $this->timers->getFirst()) {
|
||||||
|
$timeout = $scheduledAt - $this->timers->getTime();
|
||||||
|
if ($timeout < 0) {
|
||||||
|
$timeout = 0;
|
||||||
|
} else {
|
||||||
|
$timeout *= self::MICROSECONDS_PER_SECOND;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The only possible event is stream activity, so wait forever ...
|
||||||
|
} elseif ($this->readStreams || $this->writeStreams) {
|
||||||
|
$timeout = null;
|
||||||
|
|
||||||
|
// There's nothing left to do ...
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->waitForStreamActivity($timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function stop()
|
||||||
|
{
|
||||||
|
$this->running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait/check for stream activity, or until the next timer is due.
|
||||||
|
*/
|
||||||
|
private function waitForStreamActivity($timeout)
|
||||||
|
{
|
||||||
|
$read = $this->readStreams;
|
||||||
|
$write = $this->writeStreams;
|
||||||
|
|
||||||
|
$this->streamSelect($read, $write, $timeout);
|
||||||
|
|
||||||
|
foreach ($read as $stream) {
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->readListeners[$key])) {
|
||||||
|
call_user_func($this->readListeners[$key], $stream, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($write as $stream) {
|
||||||
|
$key = (int) $stream;
|
||||||
|
|
||||||
|
if (isset($this->writeListeners[$key])) {
|
||||||
|
call_user_func($this->writeListeners[$key], $stream, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emulate a stream_select() implementation that does not break when passed
|
||||||
|
* empty stream arrays.
|
||||||
|
*
|
||||||
|
* @param array &$read An array of read streams to select upon.
|
||||||
|
* @param array &$write An array of write streams to select upon.
|
||||||
|
* @param integer|null $timeout Activity timeout in microseconds, or null to wait forever.
|
||||||
|
*
|
||||||
|
* @return integer The total number of streams that are ready for read/write.
|
||||||
|
*/
|
||||||
|
protected function streamSelect(array &$read, array &$write, $timeout)
|
||||||
|
{
|
||||||
|
if ($read || $write) {
|
||||||
|
$except = null;
|
||||||
|
|
||||||
|
return stream_select($read, $write, $except, $timeout === null ? null : 0, $timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep($timeout);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
59
libs/React/EventLoop/Tick/FutureTickQueue.php
Normal file
59
libs/React/EventLoop/Tick/FutureTickQueue.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop\Tick;
|
||||||
|
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
use SplQueue;
|
||||||
|
|
||||||
|
class FutureTickQueue
|
||||||
|
{
|
||||||
|
private $eventLoop;
|
||||||
|
private $queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param LoopInterface $eventLoop The event loop passed as the first parameter to callbacks.
|
||||||
|
*/
|
||||||
|
public function __construct(LoopInterface $eventLoop)
|
||||||
|
{
|
||||||
|
$this->eventLoop = $eventLoop;
|
||||||
|
$this->queue = new SplQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback to be invoked on a future tick of the event loop.
|
||||||
|
*
|
||||||
|
* Callbacks are guaranteed to be executed in the order they are enqueued.
|
||||||
|
*
|
||||||
|
* @param callable $listener The callback to invoke.
|
||||||
|
*/
|
||||||
|
public function add(callable $listener)
|
||||||
|
{
|
||||||
|
$this->queue->enqueue($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush the callback queue.
|
||||||
|
*/
|
||||||
|
public function tick()
|
||||||
|
{
|
||||||
|
// Only invoke as many callbacks as were on the queue when tick() was called.
|
||||||
|
$count = $this->queue->count();
|
||||||
|
|
||||||
|
while ($count--) {
|
||||||
|
call_user_func(
|
||||||
|
$this->queue->dequeue(),
|
||||||
|
$this->eventLoop
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the next tick queue is empty.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return $this->queue->isEmpty();
|
||||||
|
}
|
||||||
|
}
|
57
libs/React/EventLoop/Tick/NextTickQueue.php
Normal file
57
libs/React/EventLoop/Tick/NextTickQueue.php
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop\Tick;
|
||||||
|
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
use SplQueue;
|
||||||
|
|
||||||
|
class NextTickQueue
|
||||||
|
{
|
||||||
|
private $eventLoop;
|
||||||
|
private $queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param LoopInterface $eventLoop The event loop passed as the first parameter to callbacks.
|
||||||
|
*/
|
||||||
|
public function __construct(LoopInterface $eventLoop)
|
||||||
|
{
|
||||||
|
$this->eventLoop = $eventLoop;
|
||||||
|
$this->queue = new SplQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a callback to be invoked on the next tick of the event loop.
|
||||||
|
*
|
||||||
|
* Callbacks are guaranteed to be executed in the order they are enqueued,
|
||||||
|
* before any timer or stream events.
|
||||||
|
*
|
||||||
|
* @param callable $listener The callback to invoke.
|
||||||
|
*/
|
||||||
|
public function add(callable $listener)
|
||||||
|
{
|
||||||
|
$this->queue->enqueue($listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush the callback queue.
|
||||||
|
*/
|
||||||
|
public function tick()
|
||||||
|
{
|
||||||
|
while (!$this->queue->isEmpty()) {
|
||||||
|
call_user_func(
|
||||||
|
$this->queue->dequeue(),
|
||||||
|
$this->eventLoop
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the next tick queue is empty.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return $this->queue->isEmpty();
|
||||||
|
}
|
||||||
|
}
|
102
libs/React/EventLoop/Timer/Timer.php
Normal file
102
libs/React/EventLoop/Timer/Timer.php
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop\Timer;
|
||||||
|
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
|
||||||
|
class Timer implements TimerInterface
|
||||||
|
{
|
||||||
|
const MIN_INTERVAL = 0.000001;
|
||||||
|
|
||||||
|
protected $loop;
|
||||||
|
protected $interval;
|
||||||
|
protected $callback;
|
||||||
|
protected $periodic;
|
||||||
|
protected $data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor initializes the fields of the Timer
|
||||||
|
*
|
||||||
|
* @param LoopInterface $loop The loop with which this timer is associated
|
||||||
|
* @param float $interval The interval after which this timer will execute, in seconds
|
||||||
|
* @param callable $callback The callback that will be executed when this timer elapses
|
||||||
|
* @param bool $periodic Whether the time is periodic
|
||||||
|
* @param mixed $data Arbitrary data associated with timer
|
||||||
|
*/
|
||||||
|
public function __construct(LoopInterface $loop, $interval, callable $callback, $periodic = false, $data = null)
|
||||||
|
{
|
||||||
|
if ($interval < self::MIN_INTERVAL) {
|
||||||
|
$interval = self::MIN_INTERVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->loop = $loop;
|
||||||
|
$this->interval = (float) $interval;
|
||||||
|
$this->callback = $callback;
|
||||||
|
$this->periodic = (bool) $periodic;
|
||||||
|
$this->data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getLoop()
|
||||||
|
{
|
||||||
|
return $this->loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getInterval()
|
||||||
|
{
|
||||||
|
return $this->interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getCallback()
|
||||||
|
{
|
||||||
|
return $this->callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function setData($data)
|
||||||
|
{
|
||||||
|
$this->data = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getData()
|
||||||
|
{
|
||||||
|
return $this->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isPeriodic()
|
||||||
|
{
|
||||||
|
return $this->periodic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isActive()
|
||||||
|
{
|
||||||
|
return $this->loop->isTimerActive($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function cancel()
|
||||||
|
{
|
||||||
|
$this->loop->cancelTimer($this);
|
||||||
|
}
|
||||||
|
}
|
62
libs/React/EventLoop/Timer/TimerInterface.php
Normal file
62
libs/React/EventLoop/Timer/TimerInterface.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop\Timer;
|
||||||
|
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
|
||||||
|
interface TimerInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Get the loop with which this timer is associated
|
||||||
|
*
|
||||||
|
* @return LoopInterface
|
||||||
|
*/
|
||||||
|
public function getLoop();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the interval after which this timer will execute, in seconds
|
||||||
|
*
|
||||||
|
* @return float
|
||||||
|
*/
|
||||||
|
public function getInterval();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the callback that will be executed when this timer elapses
|
||||||
|
*
|
||||||
|
* @return callable
|
||||||
|
*/
|
||||||
|
public function getCallback();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set arbitrary data associated with timer
|
||||||
|
*
|
||||||
|
* @param mixed $data
|
||||||
|
*/
|
||||||
|
public function setData($data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get arbitrary data associated with timer
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getData();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the time is periodic
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isPeriodic();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the time is active
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isActive();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel this timer
|
||||||
|
*/
|
||||||
|
public function cancel();
|
||||||
|
}
|
100
libs/React/EventLoop/Timer/Timers.php
Normal file
100
libs/React/EventLoop/Timer/Timers.php
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\EventLoop\Timer;
|
||||||
|
|
||||||
|
use SplObjectStorage;
|
||||||
|
use SplPriorityQueue;
|
||||||
|
|
||||||
|
class Timers
|
||||||
|
{
|
||||||
|
private $time;
|
||||||
|
private $timers;
|
||||||
|
private $scheduler;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->timers = new SplObjectStorage();
|
||||||
|
$this->scheduler = new SplPriorityQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateTime()
|
||||||
|
{
|
||||||
|
return $this->time = microtime(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTime()
|
||||||
|
{
|
||||||
|
return $this->time ?: $this->updateTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
$interval = $timer->getInterval();
|
||||||
|
$scheduledAt = $interval + $this->getTime();
|
||||||
|
|
||||||
|
$this->timers->attach($timer, $scheduledAt);
|
||||||
|
$this->scheduler->insert($timer, -$scheduledAt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function contains(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
return $this->timers->contains($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cancel(TimerInterface $timer)
|
||||||
|
{
|
||||||
|
$this->timers->detach($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFirst()
|
||||||
|
{
|
||||||
|
while ($this->scheduler->count()) {
|
||||||
|
$timer = $this->scheduler->top();
|
||||||
|
|
||||||
|
if ($this->timers->contains($timer)) {
|
||||||
|
return $this->timers[$timer];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->scheduler->extract();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEmpty()
|
||||||
|
{
|
||||||
|
return count($this->timers) === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tick()
|
||||||
|
{
|
||||||
|
$time = $this->updateTime();
|
||||||
|
$timers = $this->timers;
|
||||||
|
$scheduler = $this->scheduler;
|
||||||
|
|
||||||
|
while (!$scheduler->isEmpty()) {
|
||||||
|
$timer = $scheduler->top();
|
||||||
|
|
||||||
|
if (!isset($timers[$timer])) {
|
||||||
|
$scheduler->extract();
|
||||||
|
$timers->detach($timer);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($timers[$timer] >= $time) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$scheduler->extract();
|
||||||
|
call_user_func($timer->getCallback(), $timer);
|
||||||
|
|
||||||
|
if ($timer->isPeriodic() && isset($timers[$timer])) {
|
||||||
|
$timers[$timer] = $scheduledAt = $timer->getInterval() + $time;
|
||||||
|
$scheduler->insert($timer, -$scheduledAt);
|
||||||
|
} else {
|
||||||
|
$timers->detach($timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
42
libs/React/Socket/Connection.php
Normal file
42
libs/React/Socket/Connection.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Socket;
|
||||||
|
|
||||||
|
use React\Stream\Stream;
|
||||||
|
|
||||||
|
class Connection extends Stream implements ConnectionInterface
|
||||||
|
{
|
||||||
|
public function handleData($stream)
|
||||||
|
{
|
||||||
|
// Socket is raw, not using fread as it's interceptable by filters
|
||||||
|
// See issues #192, #209, and #240
|
||||||
|
$data = stream_socket_recvfrom($stream, $this->bufferSize);
|
||||||
|
if ('' !== $data && false !== $data) {
|
||||||
|
$this->emit('data', array($data, $this));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('' === $data || false === $data || !is_resource($stream) || feof($stream)) {
|
||||||
|
$this->end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleClose()
|
||||||
|
{
|
||||||
|
if (is_resource($this->stream)) {
|
||||||
|
// http://chat.stackoverflow.com/transcript/message/7727858#7727858
|
||||||
|
stream_socket_shutdown($this->stream, STREAM_SHUT_RDWR);
|
||||||
|
stream_set_blocking($this->stream, false);
|
||||||
|
fclose($this->stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRemoteAddress()
|
||||||
|
{
|
||||||
|
return $this->parseAddress(stream_socket_get_name($this->stream, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function parseAddress($address)
|
||||||
|
{
|
||||||
|
return trim(substr($address, 0, strrpos($address, ':')), '[]');
|
||||||
|
}
|
||||||
|
}
|
7
libs/React/Socket/ConnectionException.php
Normal file
7
libs/React/Socket/ConnectionException.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Socket;
|
||||||
|
|
||||||
|
class ConnectionException extends \ErrorException
|
||||||
|
{
|
||||||
|
}
|
12
libs/React/Socket/ConnectionInterface.php
Normal file
12
libs/React/Socket/ConnectionInterface.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Socket;
|
||||||
|
|
||||||
|
use Evenement\EventEmitterInterface;
|
||||||
|
use React\Stream\ReadableStreamInterface;
|
||||||
|
use React\Stream\WritableStreamInterface;
|
||||||
|
|
||||||
|
interface ConnectionInterface extends ReadableStreamInterface, WritableStreamInterface
|
||||||
|
{
|
||||||
|
public function getRemoteAddress();
|
||||||
|
}
|
71
libs/React/Socket/Server.php
Normal file
71
libs/React/Socket/Server.php
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Socket;
|
||||||
|
|
||||||
|
use Evenement\EventEmitter;
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
|
||||||
|
/** @event connection */
|
||||||
|
class Server extends EventEmitter implements ServerInterface
|
||||||
|
{
|
||||||
|
public $master;
|
||||||
|
private $loop;
|
||||||
|
|
||||||
|
public function __construct(LoopInterface $loop)
|
||||||
|
{
|
||||||
|
$this->loop = $loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function listen($port, $host = '127.0.0.1')
|
||||||
|
{
|
||||||
|
if (strpos($host, ':') !== false) {
|
||||||
|
// enclose IPv6 addresses in square brackets before appending port
|
||||||
|
$host = '[' . $host . ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->master = @stream_socket_server("tcp://$host:$port", $errno, $errstr);
|
||||||
|
if (false === $this->master) {
|
||||||
|
$message = "Could not bind to tcp://$host:$port: $errstr";
|
||||||
|
throw new ConnectionException($message, $errno);
|
||||||
|
}
|
||||||
|
stream_set_blocking($this->master, 0);
|
||||||
|
|
||||||
|
$this->loop->addReadStream($this->master, function ($master) {
|
||||||
|
$newSocket = stream_socket_accept($master);
|
||||||
|
if (false === $newSocket) {
|
||||||
|
$this->emit('error', array(new \RuntimeException('Error accepting new connection')));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->handleConnection($newSocket);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleConnection($socket)
|
||||||
|
{
|
||||||
|
stream_set_blocking($socket, 0);
|
||||||
|
|
||||||
|
$client = $this->createConnection($socket);
|
||||||
|
|
||||||
|
$this->emit('connection', array($client));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getPort()
|
||||||
|
{
|
||||||
|
$name = stream_socket_get_name($this->master, false);
|
||||||
|
|
||||||
|
return (int) substr(strrchr($name, ':'), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shutdown()
|
||||||
|
{
|
||||||
|
$this->loop->removeStream($this->master);
|
||||||
|
fclose($this->master);
|
||||||
|
$this->removeAllListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createConnection($socket)
|
||||||
|
{
|
||||||
|
return new Connection($socket, $this->loop);
|
||||||
|
}
|
||||||
|
}
|
13
libs/React/Socket/ServerInterface.php
Normal file
13
libs/React/Socket/ServerInterface.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Socket;
|
||||||
|
|
||||||
|
use Evenement\EventEmitterInterface;
|
||||||
|
|
||||||
|
/** @event connection */
|
||||||
|
interface ServerInterface extends EventEmitterInterface
|
||||||
|
{
|
||||||
|
public function listen($port, $host = '127.0.0.1');
|
||||||
|
public function getPort();
|
||||||
|
public function shutdown();
|
||||||
|
}
|
135
libs/React/Stream/Buffer.php
Normal file
135
libs/React/Stream/Buffer.php
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use Evenement\EventEmitter;
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
|
||||||
|
/** @event full-drain */
|
||||||
|
class Buffer extends EventEmitter implements WritableStreamInterface
|
||||||
|
{
|
||||||
|
public $stream;
|
||||||
|
public $listening = false;
|
||||||
|
public $softLimit = 2048;
|
||||||
|
private $writable = true;
|
||||||
|
private $loop;
|
||||||
|
private $data = '';
|
||||||
|
private $lastError = array(
|
||||||
|
'number' => 0,
|
||||||
|
'message' => '',
|
||||||
|
'file' => '',
|
||||||
|
'line' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
public function __construct($stream, LoopInterface $loop)
|
||||||
|
{
|
||||||
|
$this->stream = $stream;
|
||||||
|
$this->loop = $loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWritable()
|
||||||
|
{
|
||||||
|
return $this->writable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
if (!$this->writable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->data .= $data;
|
||||||
|
|
||||||
|
if (!$this->listening) {
|
||||||
|
$this->listening = true;
|
||||||
|
|
||||||
|
$this->loop->addWriteStream($this->stream, array($this, 'handleWrite'));
|
||||||
|
}
|
||||||
|
|
||||||
|
$belowSoftLimit = strlen($this->data) < $this->softLimit;
|
||||||
|
|
||||||
|
return $belowSoftLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function end($data = null)
|
||||||
|
{
|
||||||
|
if (null !== $data) {
|
||||||
|
$this->write($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writable = false;
|
||||||
|
|
||||||
|
if ($this->listening) {
|
||||||
|
$this->on('full-drain', array($this, 'close'));
|
||||||
|
} else {
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
$this->writable = false;
|
||||||
|
$this->listening = false;
|
||||||
|
$this->data = '';
|
||||||
|
|
||||||
|
$this->emit('close', [$this]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleWrite()
|
||||||
|
{
|
||||||
|
if (!is_resource($this->stream)) {
|
||||||
|
$this->emit('error', array(new \RuntimeException('Tried to write to invalid stream.'), $this));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
set_error_handler(array($this, 'errorHandler'));
|
||||||
|
|
||||||
|
$sent = fwrite($this->stream, $this->data);
|
||||||
|
|
||||||
|
restore_error_handler();
|
||||||
|
|
||||||
|
if (false === $sent) {
|
||||||
|
$this->emit('error', array(
|
||||||
|
new \ErrorException(
|
||||||
|
$this->lastError['message'],
|
||||||
|
0,
|
||||||
|
$this->lastError['number'],
|
||||||
|
$this->lastError['file'],
|
||||||
|
$this->lastError['line']
|
||||||
|
),
|
||||||
|
$this
|
||||||
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 === $sent && feof($this->stream)) {
|
||||||
|
$this->emit('error', array(new \RuntimeException('Tried to write to closed stream.'), $this));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$len = strlen($this->data);
|
||||||
|
if ($len >= $this->softLimit && $len - $sent < $this->softLimit) {
|
||||||
|
$this->emit('drain', [$this]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->data = (string) substr($this->data, $sent);
|
||||||
|
|
||||||
|
if (0 === strlen($this->data)) {
|
||||||
|
$this->loop->removeWriteStream($this->stream);
|
||||||
|
$this->listening = false;
|
||||||
|
|
||||||
|
$this->emit('full-drain', [$this]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function errorHandler($errno, $errstr, $errfile, $errline)
|
||||||
|
{
|
||||||
|
$this->lastError['number'] = $errno;
|
||||||
|
$this->lastError['message'] = $errstr;
|
||||||
|
$this->lastError['file'] = $errfile;
|
||||||
|
$this->lastError['line'] = $errline;
|
||||||
|
}
|
||||||
|
}
|
59
libs/React/Stream/BufferedSink.php
Normal file
59
libs/React/Stream/BufferedSink.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use React\Promise\Deferred;
|
||||||
|
use React\Promise\PromisorInterface;
|
||||||
|
|
||||||
|
class BufferedSink extends WritableStream implements PromisorInterface
|
||||||
|
{
|
||||||
|
private $buffer = '';
|
||||||
|
private $deferred;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->deferred = new Deferred();
|
||||||
|
|
||||||
|
$this->on('pipe', array($this, 'handlePipeEvent'));
|
||||||
|
$this->on('error', array($this, 'handleErrorEvent'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePipeEvent($source)
|
||||||
|
{
|
||||||
|
Util::forwardEvents($source, $this, array('error'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleErrorEvent($e)
|
||||||
|
{
|
||||||
|
$this->deferred->reject($e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
$this->buffer .= $data;
|
||||||
|
$this->deferred->progress($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
if ($this->closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent::close();
|
||||||
|
$this->deferred->resolve($this->buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function promise()
|
||||||
|
{
|
||||||
|
return $this->deferred->promise();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createPromise(ReadableStreamInterface $stream)
|
||||||
|
{
|
||||||
|
$sink = new static();
|
||||||
|
$stream->pipe($sink);
|
||||||
|
|
||||||
|
return $sink->promise();
|
||||||
|
}
|
||||||
|
}
|
84
libs/React/Stream/CompositeStream.php
Normal file
84
libs/React/Stream/CompositeStream.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use Evenement\EventEmitter;
|
||||||
|
|
||||||
|
class CompositeStream extends EventEmitter implements DuplexStreamInterface
|
||||||
|
{
|
||||||
|
protected $readable;
|
||||||
|
protected $writable;
|
||||||
|
protected $pipeSource;
|
||||||
|
|
||||||
|
public function __construct(ReadableStreamInterface $readable, WritableStreamInterface $writable)
|
||||||
|
{
|
||||||
|
$this->readable = $readable;
|
||||||
|
$this->writable = $writable;
|
||||||
|
|
||||||
|
Util::forwardEvents($this->readable, $this, array('data', 'end', 'error', 'close'));
|
||||||
|
Util::forwardEvents($this->writable, $this, array('drain', 'error', 'close', 'pipe'));
|
||||||
|
|
||||||
|
$this->readable->on('close', array($this, 'close'));
|
||||||
|
$this->writable->on('close', array($this, 'close'));
|
||||||
|
|
||||||
|
$this->on('pipe', array($this, 'handlePipeEvent'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handlePipeEvent($source)
|
||||||
|
{
|
||||||
|
$this->pipeSource = $source;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isReadable()
|
||||||
|
{
|
||||||
|
return $this->readable->isReadable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pause()
|
||||||
|
{
|
||||||
|
if ($this->pipeSource) {
|
||||||
|
$this->pipeSource->pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->readable->pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resume()
|
||||||
|
{
|
||||||
|
if ($this->pipeSource) {
|
||||||
|
$this->pipeSource->resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->readable->resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pipe(WritableStreamInterface $dest, array $options = array())
|
||||||
|
{
|
||||||
|
Util::pipe($this, $dest, $options);
|
||||||
|
|
||||||
|
return $dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWritable()
|
||||||
|
{
|
||||||
|
return $this->writable->isWritable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
return $this->writable->write($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function end($data = null)
|
||||||
|
{
|
||||||
|
$this->writable->end($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
$this->pipeSource = null;
|
||||||
|
|
||||||
|
$this->readable->close();
|
||||||
|
$this->writable->close();
|
||||||
|
}
|
||||||
|
}
|
7
libs/React/Stream/DuplexStreamInterface.php
Normal file
7
libs/React/Stream/DuplexStreamInterface.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
interface DuplexStreamInterface extends ReadableStreamInterface, WritableStreamInterface
|
||||||
|
{
|
||||||
|
}
|
42
libs/React/Stream/ReadableStream.php
Normal file
42
libs/React/Stream/ReadableStream.php
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use Evenement\EventEmitter;
|
||||||
|
|
||||||
|
class ReadableStream extends EventEmitter implements ReadableStreamInterface
|
||||||
|
{
|
||||||
|
protected $closed = false;
|
||||||
|
|
||||||
|
public function isReadable()
|
||||||
|
{
|
||||||
|
return !$this->closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pause()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resume()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pipe(WritableStreamInterface $dest, array $options = array())
|
||||||
|
{
|
||||||
|
Util::pipe($this, $dest, $options);
|
||||||
|
|
||||||
|
return $dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
if ($this->closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->closed = true;
|
||||||
|
$this->emit('end', array($this));
|
||||||
|
$this->emit('close', array($this));
|
||||||
|
$this->removeAllListeners();
|
||||||
|
}
|
||||||
|
}
|
20
libs/React/Stream/ReadableStreamInterface.php
Normal file
20
libs/React/Stream/ReadableStreamInterface.php
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use Evenement\EventEmitterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @event data
|
||||||
|
* @event end
|
||||||
|
* @event error
|
||||||
|
* @event close
|
||||||
|
*/
|
||||||
|
interface ReadableStreamInterface extends EventEmitterInterface
|
||||||
|
{
|
||||||
|
public function isReadable();
|
||||||
|
public function pause();
|
||||||
|
public function resume();
|
||||||
|
public function pipe(WritableStreamInterface $dest, array $options = array());
|
||||||
|
public function close();
|
||||||
|
}
|
141
libs/React/Stream/Stream.php
Normal file
141
libs/React/Stream/Stream.php
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use Evenement\EventEmitter;
|
||||||
|
use React\EventLoop\LoopInterface;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
|
||||||
|
class Stream extends EventEmitter implements DuplexStreamInterface
|
||||||
|
{
|
||||||
|
public $bufferSize = 4096;
|
||||||
|
public $stream;
|
||||||
|
protected $readable = true;
|
||||||
|
protected $writable = true;
|
||||||
|
protected $closing = false;
|
||||||
|
protected $loop;
|
||||||
|
protected $buffer;
|
||||||
|
|
||||||
|
public function __construct($stream, LoopInterface $loop)
|
||||||
|
{
|
||||||
|
$this->stream = $stream;
|
||||||
|
if (!is_resource($this->stream) || get_resource_type($this->stream) !== "stream") {
|
||||||
|
throw new InvalidArgumentException('First parameter must be a valid stream resource');
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_set_blocking($this->stream, 0);
|
||||||
|
|
||||||
|
$this->loop = $loop;
|
||||||
|
$this->buffer = new Buffer($this->stream, $this->loop);
|
||||||
|
|
||||||
|
$this->buffer->on('error', function ($error) {
|
||||||
|
$this->emit('error', array($error, $this));
|
||||||
|
$this->close();
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->buffer->on('drain', function () {
|
||||||
|
$this->emit('drain', array($this));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isReadable()
|
||||||
|
{
|
||||||
|
return $this->readable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWritable()
|
||||||
|
{
|
||||||
|
return $this->writable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pause()
|
||||||
|
{
|
||||||
|
$this->loop->removeReadStream($this->stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function resume()
|
||||||
|
{
|
||||||
|
if ($this->readable) {
|
||||||
|
$this->loop->addReadStream($this->stream, array($this, 'handleData'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
if (!$this->writable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->buffer->write($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
if (!$this->writable && !$this->closing) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->closing = false;
|
||||||
|
|
||||||
|
$this->readable = false;
|
||||||
|
$this->writable = false;
|
||||||
|
|
||||||
|
$this->emit('end', array($this));
|
||||||
|
$this->emit('close', array($this));
|
||||||
|
$this->loop->removeStream($this->stream);
|
||||||
|
$this->buffer->removeAllListeners();
|
||||||
|
$this->removeAllListeners();
|
||||||
|
|
||||||
|
$this->handleClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function end($data = null)
|
||||||
|
{
|
||||||
|
if (!$this->writable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->closing = true;
|
||||||
|
|
||||||
|
$this->readable = false;
|
||||||
|
$this->writable = false;
|
||||||
|
|
||||||
|
$this->buffer->on('close', function () {
|
||||||
|
$this->close();
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->buffer->end($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pipe(WritableStreamInterface $dest, array $options = array())
|
||||||
|
{
|
||||||
|
Util::pipe($this, $dest, $options);
|
||||||
|
|
||||||
|
return $dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleData($stream)
|
||||||
|
{
|
||||||
|
$data = fread($stream, $this->bufferSize);
|
||||||
|
|
||||||
|
$this->emit('data', array($data, $this));
|
||||||
|
|
||||||
|
if (!is_resource($stream) || feof($stream)) {
|
||||||
|
$this->end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleClose()
|
||||||
|
{
|
||||||
|
if (is_resource($this->stream)) {
|
||||||
|
fclose($this->stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBuffer()
|
||||||
|
{
|
||||||
|
return $this->buffer;
|
||||||
|
}
|
||||||
|
}
|
33
libs/React/Stream/ThroughStream.php
Normal file
33
libs/React/Stream/ThroughStream.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
class ThroughStream extends CompositeStream
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$readable = new ReadableStream();
|
||||||
|
$writable = new WritableStream();
|
||||||
|
|
||||||
|
parent::__construct($readable, $writable);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filter($data)
|
||||||
|
{
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
$this->readable->emit('data', array($this->filter($data), $this));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function end($data = null)
|
||||||
|
{
|
||||||
|
if (null !== $data) {
|
||||||
|
$this->readable->emit('data', array($this->filter($data), $this));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->writable->end($data);
|
||||||
|
}
|
||||||
|
}
|
45
libs/React/Stream/Util.php
Normal file
45
libs/React/Stream/Util.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
// TODO: move to a trait
|
||||||
|
|
||||||
|
class Util
|
||||||
|
{
|
||||||
|
public static function pipe(ReadableStreamInterface $source, WritableStreamInterface $dest, array $options = array())
|
||||||
|
{
|
||||||
|
// TODO: use stream_copy_to_stream
|
||||||
|
// it is 4x faster than this
|
||||||
|
// but can lose data under load with no way to recover it
|
||||||
|
|
||||||
|
$dest->emit('pipe', array($source));
|
||||||
|
|
||||||
|
$source->on('data', function ($data) use ($source, $dest) {
|
||||||
|
$feedMore = $dest->write($data);
|
||||||
|
|
||||||
|
if (false === $feedMore) {
|
||||||
|
$source->pause();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$dest->on('drain', function () use ($source) {
|
||||||
|
$source->resume();
|
||||||
|
});
|
||||||
|
|
||||||
|
$end = isset($options['end']) ? $options['end'] : true;
|
||||||
|
if ($end && $source !== $dest) {
|
||||||
|
$source->on('end', function () use ($dest) {
|
||||||
|
$dest->end();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function forwardEvents($source, $target, array $events)
|
||||||
|
{
|
||||||
|
foreach ($events as $event) {
|
||||||
|
$source->on($event, function () use ($event, $target) {
|
||||||
|
$target->emit($event, func_get_args());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
libs/React/Stream/WritableStream.php
Normal file
40
libs/React/Stream/WritableStream.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use Evenement\EventEmitter;
|
||||||
|
|
||||||
|
class WritableStream extends EventEmitter implements WritableStreamInterface
|
||||||
|
{
|
||||||
|
protected $closed = false;
|
||||||
|
|
||||||
|
public function write($data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function end($data = null)
|
||||||
|
{
|
||||||
|
if (null !== $data) {
|
||||||
|
$this->write($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isWritable()
|
||||||
|
{
|
||||||
|
return !$this->closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close()
|
||||||
|
{
|
||||||
|
if ($this->closed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->closed = true;
|
||||||
|
$this->emit('end', array($this));
|
||||||
|
$this->emit('close', array($this));
|
||||||
|
$this->removeAllListeners();
|
||||||
|
}
|
||||||
|
}
|
19
libs/React/Stream/WritableStreamInterface.php
Normal file
19
libs/React/Stream/WritableStreamInterface.php
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace React\Stream;
|
||||||
|
|
||||||
|
use Evenement\EventEmitterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @event drain
|
||||||
|
* @event error
|
||||||
|
* @event close
|
||||||
|
* @event pipe
|
||||||
|
*/
|
||||||
|
interface WritableStreamInterface extends EventEmitterInterface
|
||||||
|
{
|
||||||
|
public function isWritable();
|
||||||
|
public function write($data);
|
||||||
|
public function end($data = null);
|
||||||
|
public function close();
|
||||||
|
}
|
@ -121,7 +121,7 @@ class ContainerAwareEventDispatcher extends EventDispatcher
|
|||||||
public function getListeners($eventName = null)
|
public function getListeners($eventName = null)
|
||||||
{
|
{
|
||||||
if (null === $eventName) {
|
if (null === $eventName) {
|
||||||
foreach (array_keys($this->listenerIds) as $serviceEventName) {
|
foreach ($this->listenerIds as $serviceEventName => $args) {
|
||||||
$this->lazyLoad($serviceEventName);
|
$this->lazyLoad($serviceEventName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -31,6 +31,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
|||||||
|
|
||||||
private $called;
|
private $called;
|
||||||
private $dispatcher;
|
private $dispatcher;
|
||||||
|
private $wrappedListeners;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@ -45,6 +46,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
|||||||
$this->stopwatch = $stopwatch;
|
$this->stopwatch = $stopwatch;
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
$this->called = array();
|
$this->called = array();
|
||||||
|
$this->wrappedListeners = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -68,6 +70,16 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
|||||||
*/
|
*/
|
||||||
public function removeListener($eventName, $listener)
|
public function removeListener($eventName, $listener)
|
||||||
{
|
{
|
||||||
|
if (isset($this->wrappedListeners[$eventName])) {
|
||||||
|
foreach ($this->wrappedListeners[$eventName] as $index => $wrappedListener) {
|
||||||
|
if ($wrappedListener->getWrappedListener() === $listener) {
|
||||||
|
$listener = $wrappedListener;
|
||||||
|
unset($this->wrappedListeners[$eventName][$index]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $this->dispatcher->removeListener($eventName, $listener);
|
return $this->dispatcher->removeListener($eventName, $listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,7 +158,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
|||||||
$allListeners = $this->getListeners();
|
$allListeners = $this->getListeners();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
if (null !== $this->logger) {
|
if (null !== $this->logger) {
|
||||||
$this->logger->info(sprintf('An exception was thrown while getting the uncalled listeners (%s)', $e->getMessage()), array('exception' => $e));
|
$this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e));
|
||||||
}
|
}
|
||||||
|
|
||||||
// unable to retrieve the uncalled listeners
|
// unable to retrieve the uncalled listeners
|
||||||
@ -216,12 +228,15 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
|||||||
$this->dispatcher->removeListener($eventName, $listener);
|
$this->dispatcher->removeListener($eventName, $listener);
|
||||||
$info = $this->getListenerInfo($listener, $eventName);
|
$info = $this->getListenerInfo($listener, $eventName);
|
||||||
$name = isset($info['class']) ? $info['class'] : $info['type'];
|
$name = isset($info['class']) ? $info['class'] : $info['type'];
|
||||||
$this->dispatcher->addListener($eventName, new WrappedListener($listener, $name, $this->stopwatch));
|
$wrappedListener = new WrappedListener($listener, $name, $this->stopwatch, $this);
|
||||||
|
$this->wrappedListeners[$eventName][] = $wrappedListener;
|
||||||
|
$this->dispatcher->addListener($eventName, $wrappedListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function postProcess($eventName)
|
private function postProcess($eventName)
|
||||||
{
|
{
|
||||||
|
unset($this->wrappedListeners[$eventName]);
|
||||||
$skipped = false;
|
$skipped = false;
|
||||||
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
|
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
|
||||||
if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch.
|
if (!$listener instanceof WrappedListener) { // #12845: a new listener was added during dispatch.
|
||||||
@ -259,7 +274,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns information about the listener
|
* Returns information about the listener.
|
||||||
*
|
*
|
||||||
* @param object $listener The listener
|
* @param object $listener The listener
|
||||||
* @param string $eventName The event name
|
* @param string $eventName The event name
|
||||||
|
@ -25,12 +25,14 @@ class WrappedListener
|
|||||||
private $called;
|
private $called;
|
||||||
private $stoppedPropagation;
|
private $stoppedPropagation;
|
||||||
private $stopwatch;
|
private $stopwatch;
|
||||||
|
private $dispatcher;
|
||||||
|
|
||||||
public function __construct($listener, $name, Stopwatch $stopwatch)
|
public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null)
|
||||||
{
|
{
|
||||||
$this->listener = $listener;
|
$this->listener = $listener;
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->stopwatch = $stopwatch;
|
$this->stopwatch = $stopwatch;
|
||||||
|
$this->dispatcher = $dispatcher;
|
||||||
$this->called = false;
|
$this->called = false;
|
||||||
$this->stoppedPropagation = false;
|
$this->stoppedPropagation = false;
|
||||||
}
|
}
|
||||||
@ -56,7 +58,7 @@ class WrappedListener
|
|||||||
|
|
||||||
$e = $this->stopwatch->start($this->name, 'event_listener');
|
$e = $this->stopwatch->start($this->name, 'event_listener');
|
||||||
|
|
||||||
call_user_func($this->listener, $event, $eventName, $dispatcher);
|
call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher);
|
||||||
|
|
||||||
if ($e->isStarted()) {
|
if ($e->isStarted()) {
|
||||||
$e->stop();
|
$e->stop();
|
||||||
|
@ -91,8 +91,12 @@ class RegisterListenersPass implements CompilerPassInterface
|
|||||||
throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id));
|
throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($def->isAbstract()) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The service "%s" must not be abstract as event subscribers are lazy-loaded.', $id));
|
||||||
|
}
|
||||||
|
|
||||||
// We must assume that the class value has been correctly filled, even if the service is created by a factory
|
// We must assume that the class value has been correctly filled, even if the service is created by a factory
|
||||||
$class = $def->getClass();
|
$class = $container->getParameterBag()->resolveValue($def->getClass());
|
||||||
|
|
||||||
$refClass = new \ReflectionClass($class);
|
$refClass = new \ReflectionClass($class);
|
||||||
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
|
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
|
||||||
|
@ -77,7 +77,7 @@ class Event
|
|||||||
*
|
*
|
||||||
* @param EventDispatcherInterface $dispatcher
|
* @param EventDispatcherInterface $dispatcher
|
||||||
*
|
*
|
||||||
* @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
|
* @deprecated since version 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
@ -91,12 +91,14 @@ class Event
|
|||||||
*
|
*
|
||||||
* @return EventDispatcherInterface
|
* @return EventDispatcherInterface
|
||||||
*
|
*
|
||||||
* @deprecated Deprecated in 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
|
* @deprecated since version 2.4, to be removed in 3.0. The event dispatcher is passed to the listener call.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function getDispatcher()
|
public function getDispatcher()
|
||||||
{
|
{
|
||||||
|
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.4 and will be removed in 3.0. The event dispatcher instance can be received in the listener call instead.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
return $this->dispatcher;
|
return $this->dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,12 +107,14 @@ class Event
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*
|
*
|
||||||
* @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call.
|
* @deprecated since version 2.4, to be removed in 3.0. The event name is passed to the listener call.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function getName()
|
public function getName()
|
||||||
{
|
{
|
||||||
|
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.4 and will be removed in 3.0. The event name can be received in the listener call instead.', E_USER_DEPRECATED);
|
||||||
|
|
||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +123,7 @@ class Event
|
|||||||
*
|
*
|
||||||
* @param string $name The event name.
|
* @param string $name The event name.
|
||||||
*
|
*
|
||||||
* @deprecated Deprecated in 2.4, to be removed in 3.0. The event name is passed to the listener call.
|
* @deprecated since version 2.4, to be removed in 3.0. The event name is passed to the listener call.
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
|
@ -68,7 +68,7 @@ class EventDispatcher implements EventDispatcherInterface
|
|||||||
return $this->sorted[$eventName];
|
return $this->sorted[$eventName];
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (array_keys($this->listeners) as $eventName) {
|
foreach ($this->listeners as $eventName => $eventListeners) {
|
||||||
if (!isset($this->sorted[$eventName])) {
|
if (!isset($this->sorted[$eventName])) {
|
||||||
$this->sortListeners($eventName);
|
$this->sortListeners($eventName);
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ interface EventDispatcherInterface
|
|||||||
public function removeSubscriber(EventSubscriberInterface $subscriber);
|
public function removeSubscriber(EventSubscriberInterface $subscriber);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the listeners of a specific event or all listeners.
|
* Gets the listeners of a specific event or all listeners sorted by descending priority.
|
||||||
*
|
*
|
||||||
* @param string $eventName The name of the event
|
* @param string $eventName The name of the event
|
||||||
*
|
*
|
||||||
|
@ -71,7 +71,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
|
|||||||
return $this->arguments[$key];
|
return $this->arguments[$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new \InvalidArgumentException(sprintf('%s not found in %s', $key, $this->getName()));
|
throw new \InvalidArgumentException(sprintf('Argument "%s" not found.', $key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,5 +23,5 @@ Resources
|
|||||||
You can run the unit tests with the following command:
|
You can run the unit tests with the following command:
|
||||||
|
|
||||||
$ cd path/to/Symfony/Component/EventDispatcher/
|
$ cd path/to/Symfony/Component/EventDispatcher/
|
||||||
$ composer.phar install
|
$ composer install
|
||||||
$ phpunit
|
$ phpunit
|
||||||
|
@ -118,10 +118,21 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
|
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
|
||||||
$event = new Event();
|
$event = new Event();
|
||||||
$return = $this->dispatcher->dispatch(self::preFoo, $event);
|
$return = $this->dispatcher->dispatch(self::preFoo, $event);
|
||||||
$this->assertEquals('pre.foo', $event->getName());
|
|
||||||
$this->assertSame($event, $return);
|
$this->assertSame($event, $return);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function testLegacyDispatch()
|
||||||
|
{
|
||||||
|
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
$event = new Event();
|
||||||
|
$return = $this->dispatcher->dispatch(self::preFoo, $event);
|
||||||
|
$this->assertEquals('pre.foo', $event->getName());
|
||||||
|
}
|
||||||
|
|
||||||
public function testDispatchForClosure()
|
public function testDispatchForClosure()
|
||||||
{
|
{
|
||||||
$invoked = 0;
|
$invoked = 0;
|
||||||
@ -239,8 +250,13 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
|
$this->assertFalse($this->dispatcher->hasListeners(self::preFoo));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testEventReceivesTheDispatcherInstance()
|
/**
|
||||||
|
* @group legacy
|
||||||
|
*/
|
||||||
|
public function testLegacyEventReceivesTheDispatcherInstance()
|
||||||
{
|
{
|
||||||
|
$this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED);
|
||||||
|
|
||||||
$dispatcher = null;
|
$dispatcher = null;
|
||||||
$this->dispatcher->addListener('test', function ($event) use (&$dispatcher) {
|
$this->dispatcher->addListener('test', function ($event) use (&$dispatcher) {
|
||||||
$dispatcher = $event->getDispatcher();
|
$dispatcher = $event->getDispatcher();
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\EventDispatcher\Tests\Debug;
|
namespace Symfony\Component\EventDispatcher\Tests\Debug;
|
||||||
|
|
||||||
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
|
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
|
||||||
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||||
use Symfony\Component\EventDispatcher\Event;
|
use Symfony\Component\EventDispatcher\Event;
|
||||||
@ -86,6 +87,20 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
|
$this->assertEquals(array(), $tdispatcher->getNotCalledListeners());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetCalledListenersNested()
|
||||||
|
{
|
||||||
|
$tdispatcher = null;
|
||||||
|
$dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||||
|
$dispatcher->addListener('foo', function (Event $event, $eventName, $dispatcher) use (&$tdispatcher) {
|
||||||
|
$tdispatcher = $dispatcher;
|
||||||
|
$dispatcher->dispatch('bar');
|
||||||
|
});
|
||||||
|
$dispatcher->addListener('bar', function (Event $event) {});
|
||||||
|
$dispatcher->dispatch('foo');
|
||||||
|
$this->assertSame($dispatcher, $tdispatcher);
|
||||||
|
$this->assertCount(2, $dispatcher->getCalledListeners());
|
||||||
|
}
|
||||||
|
|
||||||
public function testLogger()
|
public function testLogger()
|
||||||
{
|
{
|
||||||
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||||
@ -160,6 +175,19 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
|||||||
$dispatcher->dispatch('foo');
|
$dispatcher->dispatch('foo');
|
||||||
$this->assertTrue($nestedCall);
|
$this->assertTrue($nestedCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testListenerCanRemoveItselfWhenExecuted()
|
||||||
|
{
|
||||||
|
$eventDispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
|
||||||
|
$listener1 = function ($event, $eventName, EventDispatcherInterface $dispatcher) use (&$listener1) {
|
||||||
|
$dispatcher->removeListener('foo', $listener1);
|
||||||
|
};
|
||||||
|
$eventDispatcher->addListener('foo', $listener1);
|
||||||
|
$eventDispatcher->addListener('foo', function () {});
|
||||||
|
$eventDispatcher->dispatch('foo');
|
||||||
|
|
||||||
|
$this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class EventSubscriber implements EventSubscriberInterface
|
class EventSubscriber implements EventSubscriberInterface
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user