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="SPACE_AFTER_TYPE_CAST" 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="DOWHILE_BRACE_FORCE" value="3" />
|
||||
<option name="WHILE_BRACE_FORCE" value="3" />
|
||||
@ -73,4 +74,3 @@
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
|
@ -4,4 +4,3 @@
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
|
@ -34,11 +34,11 @@ http://www.maniacontrol.com
|
||||
## REQUIREMENTS:
|
||||
- MySQL Database
|
||||
- PHP 5.4+
|
||||
- Needed extensions:
|
||||
- Needed extensions (on ManiaControl startup you will see if you have them activated):
|
||||
- php_mysqli
|
||||
- php_curl
|
||||
- php_xmlrpc (TM only)
|
||||
|
||||
- php_xmlrpc (TM only, recomended for SM)
|
||||
- php_zlib
|
||||
|
||||
### How to report bugs or request features?:
|
||||
- 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]);
|
||||
}
|
||||
} else {
|
||||
if (isset($this->playerMenuItems[$order])) {
|
||||
if (isset($this->adminMenuItems[$order])) {
|
||||
unset($this->adminMenuItems[$order]);
|
||||
}
|
||||
}
|
||||
|
@ -133,9 +133,9 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener {
|
||||
$lineQuad->setZ(0.001);
|
||||
}
|
||||
|
||||
$array = array($index => $posX + 5, $admin->nickname => $posX + 18, $admin->login => $posX + 70);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, $array);
|
||||
|
||||
$positions = array($posX + 5, $posX + 18, $posX + 70);
|
||||
$texts = array($index, $admin->nickname, $admin->login);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, array($positions, $texts));
|
||||
|
||||
// Level Quad
|
||||
$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('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('removerights', $this, 'command_RemoveRights', true, 'Remove Player from the AdminList.');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,4 +161,53 @@ class AuthCommands implements CommandListener {
|
||||
$message = "Usage Example: '//addmod login'";
|
||||
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\Callbacks;
|
||||
use ManiaControl\Callbacks\EchoListener;
|
||||
use ManiaControl\Communication\CommunicationAnswer;
|
||||
use ManiaControl\Communication\CommunicationListener;
|
||||
use ManiaControl\Communication\CommunicationMethods;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
@ -17,7 +21,7 @@ use ManiaControl\Settings\Setting;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class AuthenticationManager implements CallbackListener {
|
||||
class AuthenticationManager implements CallbackListener, EchoListener, CommunicationListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
@ -33,6 +37,8 @@ class AuthenticationManager implements CallbackListener {
|
||||
const AUTH_NAME_MASTERADMIN = 'MasterAdmin';
|
||||
const CB_AUTH_LEVEL_CHANGED = 'AuthenticationManager.AuthLevelChanged';
|
||||
|
||||
const ECHO_GRANT_LEVEL = 'ManiaControl.AuthenticationManager.GrandLevel';
|
||||
const ECHO_REVOKE_LEVEL = 'ManiaControl.AuthenticationManager.RevokeLevel';
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
@ -52,6 +58,56 @@ class AuthenticationManager implements CallbackListener {
|
||||
|
||||
// Callbacks
|
||||
$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) {
|
||||
if (is_object($authLevelParam) && property_exists($authLevelParam, 'authLevel')) {
|
||||
return (int)$authLevelParam->authLevel;
|
||||
return (int) $authLevelParam->authLevel;
|
||||
}
|
||||
if (is_string($authLevelParam)) {
|
||||
return self::getAuthLevel($authLevelParam);
|
||||
}
|
||||
return (int)$authLevelParam;
|
||||
return (int) $authLevelParam;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -98,7 +154,7 @@ class AuthenticationManager implements CallbackListener {
|
||||
* @return int
|
||||
*/
|
||||
public static function getAuthLevel($authLevelName) {
|
||||
$authLevelName = (string)$authLevelName;
|
||||
$authLevelName = (string) $authLevelName;
|
||||
switch ($authLevelName) {
|
||||
case self::AUTH_NAME_MASTERADMIN:
|
||||
return self::AUTH_LEVEL_MASTERADMIN;
|
||||
@ -189,7 +245,7 @@ class AuthenticationManager implements CallbackListener {
|
||||
}
|
||||
$success = true;
|
||||
foreach ($loginElements as $loginElement) {
|
||||
$login = (string)$loginElement;
|
||||
$login = (string) $loginElement;
|
||||
$adminStatement->bind_param('si', $login, $masterAdminLevel);
|
||||
$adminStatement->execute();
|
||||
if ($adminStatement->error) {
|
||||
@ -271,7 +327,7 @@ class AuthenticationManager implements CallbackListener {
|
||||
if (!$player || !is_numeric($authLevel)) {
|
||||
return false;
|
||||
}
|
||||
$authLevel = (int)$authLevel;
|
||||
$authLevel = (int) $authLevel;
|
||||
if ($authLevel >= self::AUTH_LEVEL_MASTERADMIN) {
|
||||
return false;
|
||||
}
|
||||
|
@ -15,28 +15,34 @@ class BillData {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $function = null;
|
||||
public $pay = false;
|
||||
public $player = null;
|
||||
public $function = null;
|
||||
public $pay = false;
|
||||
public $player = null;
|
||||
public $receiverLogin = null;
|
||||
public $amount = 0;
|
||||
public $creationTime = -1;
|
||||
public $amount = 0;
|
||||
public $creationTime = -1;
|
||||
public $message = "";
|
||||
public $class = "";
|
||||
|
||||
/**
|
||||
* Construct new Bill Data Model
|
||||
*
|
||||
* @param string $class
|
||||
* @param callable $function
|
||||
* @param Player|string $player
|
||||
* @param int $amount
|
||||
* @param bool $pay
|
||||
* @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->player = $player;
|
||||
$this->amount = $amount;
|
||||
$this->pay = $pay;
|
||||
$this->receiverLogin = $receiverLogin;
|
||||
$this->message = $message;
|
||||
$this->creationTime = time();
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\InvalidArgumentException;
|
||||
use Maniaplanet\DedicatedServer\Structures\Bill;
|
||||
|
||||
/**
|
||||
@ -24,7 +25,7 @@ class BillManager implements CallbackListener {
|
||||
const PAYED_FROM_SERVER = 3;
|
||||
const PLAYER_REFUSED_DONATION = 4;
|
||||
const ERROR_WHILE_TRANSACTION = 5;
|
||||
const CB_BILL_PAID = 'Billmanager.BillPaid';
|
||||
const CB_BILL_PAID = 'Billmanager.BillPaid';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
@ -57,11 +58,21 @@ class BillManager implements CallbackListener {
|
||||
* @return bool
|
||||
*/
|
||||
public function sendBill(callable $function, Player $player, $amount, $message, $receiver = '') {
|
||||
$billId = $this->maniaControl->getClient()->sendBill($player->login, $amount, $message, $receiver);
|
||||
$this->openBills[$billId] = new BillData($function, $player, $amount);
|
||||
//Get the Caller Class
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send planets from the server to a player
|
||||
*
|
||||
@ -72,8 +83,17 @@ class BillManager implements CallbackListener {
|
||||
* @return bool
|
||||
*/
|
||||
public function sendPlanets(callable $function, $receiverLogin, $amount, $message) {
|
||||
$billId = $this->maniaControl->getClient()->pay($receiverLogin, $amount, $message);
|
||||
$this->openBills[$billId] = new BillData($function, $receiverLogin, $amount, true);
|
||||
//Get the Caller Class
|
||||
$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;
|
||||
}
|
||||
|
||||
|
@ -153,8 +153,6 @@ class CallbackManager {
|
||||
return $this->removeCallbackListener($this->callbackListenings, $listener);
|
||||
}
|
||||
|
||||
//TODO better name (used only in customvotesPlugin)
|
||||
|
||||
/**
|
||||
* Remove the Callback Listener from the given Listeners Array
|
||||
*
|
||||
@ -212,6 +210,9 @@ class CallbackManager {
|
||||
// Manage Timings
|
||||
$this->maniaControl->getTimerManager()->manageTimings();
|
||||
|
||||
// Manage Socket Tickets
|
||||
$this->maniaControl->getCommunicationManager()->tick();
|
||||
|
||||
// Server Callbacks
|
||||
if (!$this->maniaControl->getClient()) {
|
||||
return;
|
||||
|
@ -18,6 +18,7 @@ interface Callbacks {
|
||||
const ONINIT = 'Callbacks.OnInit';
|
||||
const AFTERINIT = 'Callbacks.AfterInit';
|
||||
const ONSHUTDOWN = 'Callbacks.OnShutdown';
|
||||
const ONRESTART = 'Callbacks.OnRestart';
|
||||
|
||||
/** Script Callback: CallbackName, CallbackData */
|
||||
const SCRIPTCALLBACK = 'Callbacks.ScriptCallback';
|
||||
@ -49,6 +50,8 @@ interface Callbacks {
|
||||
const ENDTURNSTOP = 'Callbacks.EndTurnStop';
|
||||
/** EndRound Callback: RoundNumber */
|
||||
const ENDROUND = 'Callbacks.EndRound';
|
||||
/** EndRound Callback: RoundNumber */
|
||||
const ENDROUNDSTOP = 'Callbacks.EndRoundStop';
|
||||
/** EndSubmatch Callback: SubmatchNumber */
|
||||
const ENDSUBMATCH = 'Callbacks.EndSubmatch';
|
||||
/** EndMap Callback: Map */
|
||||
@ -67,6 +70,12 @@ interface Callbacks {
|
||||
/** EndWarmup Callback */
|
||||
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
|
||||
* try to avoid to use this, just use the Get function of the RankingsManager instead
|
||||
* param1 Player $player
|
||||
@ -80,8 +89,6 @@ interface Callbacks {
|
||||
*/
|
||||
/** RankingsUpdated Callback: SortedRankings */
|
||||
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
|
||||
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':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDROUND, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_EndRoundStop':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDROUNDSTOP, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_EndSubmatch':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDSUBMATCH, $data[0]);
|
||||
break;
|
||||
@ -146,6 +149,12 @@ class LibXmlRpcCallbacks implements CallbackListener {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($data[0]);
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONPLAYERREQUESTRESPAWN, $player);
|
||||
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
|
||||
*
|
||||
* @param array $params
|
||||
* @return mixed
|
||||
*/
|
||||
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':
|
||||
$this->maniaControl->getServer()->getRankingManager()->updateRankings($data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_Scores':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::SCORES, $data);
|
||||
break;
|
||||
case 'LibAFK_IsAFK':
|
||||
$this->triggerAfkStatus($data[0]);
|
||||
break;
|
||||
|
@ -4,7 +4,13 @@ namespace ManiaControl\Callbacks\Structures;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
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 {
|
||||
/*
|
||||
* Private properties
|
||||
|
@ -5,6 +5,13 @@ namespace ManiaControl\Callbacks\Structures;
|
||||
use ManiaControl\ManiaControl;
|
||||
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 {
|
||||
/*
|
||||
* Private properties
|
||||
@ -42,7 +49,7 @@ class CaptureStructure {
|
||||
$playerArray = array();
|
||||
foreach ($this->playerArray as $login) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if($player){
|
||||
if ($player) {
|
||||
$playerArray[$login] = $player;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,13 @@ namespace ManiaControl\Callbacks\Structures;
|
||||
use ManiaControl\ManiaControl;
|
||||
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 {
|
||||
/*
|
||||
* Private properties
|
||||
@ -22,8 +29,8 @@ class EliteBeginTurnStructure {
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl, array $data) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->attackerLogin = $data[0];
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->attackerLogin = $data[0];
|
||||
$this->defenderLogins = $data[1];
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,13 @@ namespace ManiaControl\Callbacks\Structures;
|
||||
use ManiaControl\ManiaControl;
|
||||
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 {
|
||||
/*
|
||||
* Private properties
|
||||
|
@ -1,16 +1,17 @@
|
||||
<?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;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
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 {
|
||||
/*
|
||||
* Private properties
|
||||
@ -20,7 +21,11 @@ class PlayerHitStructure {
|
||||
private $damage;
|
||||
private $shooterPoints;
|
||||
private $weapon;
|
||||
private $hitDistance = 0;
|
||||
private $hitDistance;
|
||||
private $shooterPosition = 0;
|
||||
private $victimPosition = 0;
|
||||
private $shooterAimDirection = 0;
|
||||
private $victimAimDirection = 0;
|
||||
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl;
|
||||
@ -38,10 +43,23 @@ class PlayerHitStructure {
|
||||
$this->damage = $data[2];
|
||||
$this->weapon = $data[3];
|
||||
$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)) {
|
||||
$this->hitDistance = $data[5];
|
||||
//TODO remove key check in some months (got implemented 2015-05-03)
|
||||
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;
|
||||
|
||||
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 Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
|
||||
@ -13,7 +18,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Chat {
|
||||
class Chat implements CallbackListener, CommunicationListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
@ -22,12 +27,13 @@ class Chat {
|
||||
const SETTING_FORMAT_SUCCESS = 'Success Format';
|
||||
const SETTING_FORMAT_ERROR = 'Error Format';
|
||||
const SETTING_FORMAT_USAGEINFO = 'UsageInfo Format';
|
||||
|
||||
const CHAT_BUFFER_SIZE = 200;
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $chatBuffer = array();
|
||||
|
||||
/**
|
||||
* 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_ERROR, '$f30');
|
||||
$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);
|
||||
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
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
|
||||
class HelpManager implements CommandListener, CallbackListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $maniaControl = null;
|
||||
private $playerCommands = array();
|
||||
private $adminCommands = array();
|
||||
private $adminCommands = array();
|
||||
|
||||
/**
|
||||
* Construct a new Commands Manager
|
||||
@ -58,14 +57,14 @@ class HelpManager implements CommandListener, CallbackListener {
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_adminHelp(array $chatCallback, Player $player) {
|
||||
// Parse list from array
|
||||
$message = $this->parseHelpList($this->adminCommands);
|
||||
// Parse list from array
|
||||
$message = $this->parseHelpList($this->adminCommands);
|
||||
|
||||
// Show message when it's not empty
|
||||
if($message != NULL){
|
||||
$message = 'Supported Admin Commands: ' . $message;
|
||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||
}
|
||||
// Show message when it's not empty
|
||||
if ($message != null) {
|
||||
$message = 'Supported Admin Commands: ' . $message;
|
||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -75,14 +74,14 @@ class HelpManager implements CommandListener, CallbackListener {
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_playerHelp(array $chatCallback, Player $player) {
|
||||
// Parse list from array
|
||||
// Parse list from array
|
||||
$message = $this->parseHelpList($this->playerCommands);
|
||||
|
||||
// Show message when it's not empty
|
||||
if($message != NULL){
|
||||
$message = 'Supported Player Commands: ' . $message;
|
||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||
}
|
||||
// Show message when it's not empty
|
||||
if ($message != null) {
|
||||
$message = 'Supported Player Commands: ' . $message;
|
||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,23 +91,24 @@ class HelpManager implements CommandListener, CallbackListener {
|
||||
* @param 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
|
||||
* @param array $commands
|
||||
* @param bool $isHelpAll
|
||||
* @param Player $player
|
||||
* @return string|void
|
||||
*/
|
||||
* Parse list with commands from array
|
||||
*
|
||||
* @param array $commands
|
||||
* @param bool $isHelpAll
|
||||
* @param Player $player
|
||||
* @return string|void
|
||||
*/
|
||||
private function parseHelpList(array $commands, $isHelpAll = false, Player $player = null) {
|
||||
$showCommands = array();
|
||||
$registeredMethods = array();
|
||||
$message = '';
|
||||
$message = '';
|
||||
foreach (array_reverse($commands) as $command) {
|
||||
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']];
|
||||
$showCommands[$name]['Name'] .= '|' . $command['Name'];
|
||||
} else {
|
||||
@ -125,20 +125,17 @@ class HelpManager implements CommandListener, CallbackListener {
|
||||
return strcmp($commandA['Name'], $commandB['Name']);
|
||||
});
|
||||
|
||||
if(!$isHelpAll){
|
||||
if (!$isHelpAll) {
|
||||
foreach ($showCommands as $command) {
|
||||
$message .= $command['Name'] . ',';
|
||||
}
|
||||
$message = substr($message, 0, -1);
|
||||
|
||||
return $message;
|
||||
}else{
|
||||
if($player != NULL){
|
||||
} else {
|
||||
if ($player != null) {
|
||||
$this->showHelpAllList($showCommands, $player);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -221,7 +218,7 @@ class HelpManager implements CommandListener, CallbackListener {
|
||||
* @param 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();
|
||||
$manialink->add($frame);
|
||||
$frame->setPosition($menuPosX, $menuPosY, 10);
|
||||
$frame->setPosition($menuPosX, $menuPosY, 34);
|
||||
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$backgroundQuad->setZ(-10)->setSize($menuWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
||||
$backgroundQuad->setZ(-2)->setSize($menuWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
$menuItemsFrame = new Frame();
|
||||
$frame->add($menuItemsFrame);
|
||||
@ -211,7 +211,7 @@ class Configurator implements CallbackListener, CommandListener, ManialinkPageAn
|
||||
|
||||
$itemsBackgroundQuad = new Quad();
|
||||
$menuItemsFrame->add($itemsBackgroundQuad);
|
||||
$backgroundQuad->setZ(-9);
|
||||
$backgroundQuad->setZ(-1);
|
||||
$itemsBackgroundQuad->setSize($menuListWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
$menusFrame = new Frame();
|
||||
|
@ -14,6 +14,9 @@ use FML\Script\Script;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Communication\CommunicationAnswer;
|
||||
use ManiaControl\Communication\CommunicationListener;
|
||||
use ManiaControl\Communication\CommunicationMethods;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
@ -26,7 +29,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
||||
class ScriptSettings implements ConfiguratorMenu, CallbackListener, CommunicationListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
@ -61,6 +64,10 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
||||
|
||||
// Permissions
|
||||
$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
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
@ -282,8 +288,7 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||
*/
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -327,6 +332,7 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Apply the Array of new Script Settings
|
||||
*
|
||||
@ -406,6 +412,63 @@ class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
||||
if (is_bool($value)) {
|
||||
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;
|
||||
|
||||
use cURL\Event;
|
||||
use cURL\Request;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
@ -38,10 +37,10 @@ class AsynchronousFileReader {
|
||||
|
||||
public static function newRequestTest($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
|
||||
$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;
|
||||
}
|
||||
@ -66,93 +65,15 @@ class AsynchronousFileReader {
|
||||
* @param callable $function
|
||||
* @param string $contentType
|
||||
* @param int $keepAlive
|
||||
* @param array $headers Additional Headers
|
||||
* @deprecated @see ManiaControl\Files\AsyncHttpRequest
|
||||
*/
|
||||
public function loadFile($url, callable $function, $contentType = 'UTF-8', $keepAlive = 0) {
|
||||
$headers = array();
|
||||
array_push($headers, 'Content-Type: ' . $contentType);
|
||||
if ($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);
|
||||
public function loadFile($url, callable $function, $contentType = 'UTF-8', $keepAlive = 0, $headers = array()) {
|
||||
$httpRequest = new AsyncHttpRequest($this->maniaControl, $url);
|
||||
$httpRequest->setCallable($function)->setContentType($contentType)->setHeaders($headers);
|
||||
$httpRequest->getData($keepAlive);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
@ -161,36 +82,21 @@ class AsynchronousFileReader {
|
||||
* @param string $content
|
||||
* @param bool $compression
|
||||
* @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);
|
||||
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 = $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);
|
||||
/**
|
||||
* Add a Request to the queue, DO NOT CALL MANUALLY!
|
||||
*
|
||||
* @param Request $request
|
||||
*/
|
||||
public function addRequest(Request $request) {
|
||||
array_push($this->requests, $request);
|
||||
}
|
||||
}
|
||||
|
@ -8,10 +8,15 @@ use ManiaControl\Bills\BillManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Callbacks\EchoManager;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Callbacks\TimerManager;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
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\Database\Database;
|
||||
use ManiaControl\Files\AsynchronousFileReader;
|
||||
@ -38,11 +43,11 @@ use Maniaplanet\DedicatedServer\Xmlrpc\TransportException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @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
|
||||
*/
|
||||
const VERSION = '0.155';
|
||||
const VERSION = '0.163';
|
||||
const API_VERSION = '2013-04-16';
|
||||
const MIN_DEDIVERSION = '2014-04-02_18_00';
|
||||
const SCRIPT_TIMEOUT = 10;
|
||||
@ -164,6 +169,10 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
||||
*/
|
||||
private $requestQuitMessage = null;
|
||||
|
||||
/** @var EchoManager $echoManager */
|
||||
private $echoManager = null;
|
||||
private $communicationManager = null;
|
||||
|
||||
/**
|
||||
* Construct a new ManiaControl instance
|
||||
*/
|
||||
@ -176,6 +185,8 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
||||
|
||||
// Load ManiaControl Modules
|
||||
$this->callbackManager = new CallbackManager($this);
|
||||
$this->echoManager = new EchoManager($this);
|
||||
$this->communicationManager = new CommunicationManager($this);
|
||||
$this->timerManager = new TimerManager($this);
|
||||
$this->database = new Database($this);
|
||||
$this->fileReader = new AsynchronousFileReader($this);
|
||||
@ -194,6 +205,7 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
||||
$this->pluginManager = new PluginManager($this);
|
||||
$this->updateManager = new UpdateManager($this);
|
||||
|
||||
|
||||
$this->getErrorHandler()->init();
|
||||
|
||||
// Permissions
|
||||
@ -207,6 +219,18 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
||||
|
||||
// Check connection every 30 seconds
|
||||
$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 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
|
||||
*
|
||||
@ -465,6 +507,9 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
||||
* @param string $message
|
||||
*/
|
||||
public function restart($message = null) {
|
||||
// Trigger callback on Restart
|
||||
$this->getCallbackManager()->triggerCallback(Callbacks::ONRESTART);
|
||||
|
||||
// Announce restart
|
||||
try {
|
||||
$this->getChat()->sendInformation('Restarting ManiaControl...');
|
||||
|
@ -130,14 +130,18 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
|
||||
}
|
||||
}
|
||||
|
||||
// search for matching maps
|
||||
$this->maniaControl->getMapManager()->getMXManager()->fetchMapsAsync(function (array $maps) use (&$player) {
|
||||
//Search the Maps
|
||||
$mxSearch = new ManiaExchangeMapSearch($this->maniaControl);
|
||||
$mxSearch->setAuthorName($author);
|
||||
$mxSearch->setEnvironments($environment);
|
||||
$mxSearch->setMapName($searchString);
|
||||
$mxSearch->fetchMapsAsync(function (array $maps) use (&$player) {
|
||||
if (!$maps) {
|
||||
$this->maniaControl->getChat()->sendError('No maps found, or MX is down!', $player->login);
|
||||
return;
|
||||
}
|
||||
$this->showManiaExchangeList($maps, $player);
|
||||
}, $searchString, $author, $environment);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -9,7 +9,7 @@ use ManiaControl\Maps\MapManager;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
|
||||
/**
|
||||
* Mania Exchange Info Searcher Class
|
||||
* Mania Exchange Manager Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
@ -18,8 +18,9 @@ use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
class ManiaExchangeManager {
|
||||
/*
|
||||
* 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_TRACK_NAME = 0;
|
||||
const SEARCH_ORDER_AUTHOR = 1;
|
||||
@ -47,7 +48,7 @@ class ManiaExchangeManager {
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $maniaControl = null;
|
||||
private $mxIdUidVector = array();
|
||||
|
||||
/**
|
||||
@ -269,9 +270,9 @@ class ManiaExchangeManager {
|
||||
|
||||
/**
|
||||
* @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);
|
||||
return true;
|
||||
}
|
||||
@ -285,73 +286,22 @@ class ManiaExchangeManager {
|
||||
* @param string $env
|
||||
* @param int $maxMapsReturned
|
||||
* @param int $searchOrder
|
||||
*
|
||||
* @deprecated
|
||||
* @see \ManiaControl\ManiaExchange\ManiaExchangeMapSearch
|
||||
*/
|
||||
public function fetchMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = self::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||
// TODO: remove $env because it's not really used?
|
||||
public function fetchMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $sortOrder = ManiaExchangeMapSearch::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||
$mapSearch = new ManiaExchangeMapSearch($this->maniaControl);
|
||||
$mapSearch->setMapName($name);
|
||||
$mapSearch->setAuthorName($author);
|
||||
$mapSearch->setMapLimit($maxMapsReturned);
|
||||
$mapSearch->setPrioritySortOrder($sortOrder);
|
||||
|
||||
// Get Title Id
|
||||
$titleId = $this->maniaControl->getServer()->titleId;
|
||||
$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;
|
||||
if($env){
|
||||
$mapSearch->setEnvironments($env);
|
||||
}
|
||||
|
||||
$url .= '&priord=' . $searchOrder;
|
||||
$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);
|
||||
$mapSearch->fetchMapsAsync($function);
|
||||
}
|
||||
|
||||
/**
|
||||
|
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;
|
||||
|
||||
/**
|
||||
* Class managing the Custom UI in TrackMania
|
||||
* Class managing the Custom UI in ManiaPlanet
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
@ -28,7 +28,7 @@ class CustomUIManager implements CallbackListener, TimerListener {
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var customUI $customUI */
|
||||
private $customUI = null;
|
||||
private $customUI = null;
|
||||
private $updateManialink = false;
|
||||
|
||||
/**
|
||||
|
@ -262,7 +262,7 @@ class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener
|
||||
}
|
||||
} catch (UnknownPlayerException $e) {
|
||||
return false;
|
||||
} catch (FaultException $e){
|
||||
} catch (FaultException $e) {
|
||||
//TODO added 17.01.2015, remove later:
|
||||
$this->maniaControl->getErrorHandler()->triggerDebugNotice("Fault Exception: ManiaLink Manager, Message: " . $e->getMessage());
|
||||
return false;
|
||||
@ -349,8 +349,11 @@ class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener
|
||||
return $success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 array $labelStrings
|
||||
@ -366,21 +369,49 @@ class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener
|
||||
$profile = (isset($properties['profile']) ? $properties['profile'] : false);
|
||||
|
||||
$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) {
|
||||
$label->addPlayerProfileFeature($profile);
|
||||
//If you call LabelLine with array(array(positions), array(texts))
|
||||
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;
|
||||
|
@ -161,6 +161,13 @@ class StyleManager {
|
||||
$frame = new Frame();
|
||||
$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
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use ManiaControl\Communication\CommunicationAnswer;
|
||||
use ManiaControl\Communication\CommunicationListener;
|
||||
use ManiaControl\Communication\CommunicationMethods;
|
||||
use ManiaControl\ManiaControl;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
||||
|
||||
@ -12,7 +15,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MapActions {
|
||||
class MapActions implements CommunicationListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
@ -26,12 +29,79 @@ class MapActions {
|
||||
*/
|
||||
public function __construct(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
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function skipMap() {
|
||||
//TODO message
|
||||
|
||||
// Force an EndMap on the MapQueue to set the next Map
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->endMap(null);
|
||||
|
||||
@ -42,6 +112,27 @@ class MapActions {
|
||||
try {
|
||||
$this->maniaControl->getClient()->nextMap();
|
||||
} 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) {
|
||||
/** @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) {
|
||||
//Sort by Mx Karma in Maplist
|
||||
if ($displayMxKarma) { //TODO
|
||||
|
||||
//Sort by Local Karma in Maplist
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
$maps = $this->maniaControl->getMapManager()->getMaps();
|
||||
$mapList = array();
|
||||
foreach ($maps as $map) {
|
||||
|
@ -122,7 +122,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
|
||||
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);
|
||||
$queueBuffer = $this->maniaControl->getMapManager()->getMapQueue()->getQueueBuffer();
|
||||
@ -441,9 +441,20 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
|
||||
|
||||
// Display Karma bar
|
||||
if ($karmaPlugin) {
|
||||
$karma = $karmaPlugin->getMapKarma($map);
|
||||
$votes = $karmaPlugin->getMapVotes($map);
|
||||
if (is_numeric($karma)) {
|
||||
$displayMxKarma = $this->maniaControl->getSettingManager()->getSettingValue($karmaPlugin, $karmaPlugin::SETTING_WIDGET_DISPLAY_MX);
|
||||
|
||||
//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)
|
||||
) {
|
||||
$karmaText = ' ' . round($karma * 100.) . '% (' . $votes['count'] . ')';
|
||||
@ -692,7 +703,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
|
||||
default:
|
||||
if (substr($actionId, 0, strlen(self::ACTION_PAGING_CHUNKS)) === self::ACTION_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);
|
||||
}
|
||||
break;
|
||||
|
@ -6,6 +6,9 @@ use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Communication\CommunicationAnswer;
|
||||
use ManiaControl\Communication\CommunicationListener;
|
||||
use ManiaControl\Communication\CommunicationMethods;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
@ -30,7 +33,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnavailableFeatureException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MapManager implements CallbackListener {
|
||||
class MapManager implements CallbackListener, CommunicationListener {
|
||||
/*
|
||||
* 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_MAPLIST_FILE, "MatchSettings/tracklist.txt");
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_WRITE_OWN_MAPLIST_FILE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
//Initlaize Communication Listenings
|
||||
$this->initalizeCommunicationListenings();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -213,14 +191,16 @@ class MapManager implements CallbackListener {
|
||||
/**
|
||||
* Update a Map from Mania Exchange
|
||||
*
|
||||
* @param Player $admin
|
||||
* @param string $uid
|
||||
* @param Player|null $admin
|
||||
* @param string $uid
|
||||
*/
|
||||
public function updateMap(Player $admin, $uid) {
|
||||
public function updateMap($admin, $uid) {
|
||||
$this->updateMapTimestamp($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;
|
||||
}
|
||||
|
||||
@ -229,7 +209,11 @@ class MapManager implements CallbackListener {
|
||||
|
||||
$mxId = $map->mx->id;
|
||||
$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
|
||||
*
|
||||
* @param Player $admin
|
||||
* @param string $uid
|
||||
* @param bool $eraseFile
|
||||
* @param bool $message
|
||||
* @param Player|null $admin
|
||||
* @param string $uid
|
||||
* @param bool $eraseFile
|
||||
* @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])) {
|
||||
$this->maniaControl->getChat()->sendError('Map does not exist!', $admin);
|
||||
return;
|
||||
if ($admin) {
|
||||
$this->maniaControl->getChat()->sendError('Map does not exist!', $admin);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var Map $map */
|
||||
@ -296,26 +283,35 @@ class MapManager implements CallbackListener {
|
||||
if ($eraseFile) {
|
||||
// Check if ManiaControl can even write to the maps dir
|
||||
$mapDir = $this->maniaControl->getClient()->getMapsDirectory();
|
||||
if ($this->maniaControl->getServer()->checkAccess($mapDir)
|
||||
) {
|
||||
if ($this->maniaControl->getServer()->checkAccess($mapDir)) {
|
||||
// Delete map file
|
||||
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;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Show Message
|
||||
if ($message) {
|
||||
$action = ($eraseFile ? 'erased' : 'removed');
|
||||
$message = $admin->getEscapedNickname() . ' ' . $action . ' ' . $map->getEscapedName() . '!';
|
||||
$action = ($eraseFile ? 'erased' : 'removed');
|
||||
if ($admin) {
|
||||
$message = $admin->getEscapedNickname() . ' ' . $action . ' ' . $map->getEscapedName() . '!';
|
||||
} else {
|
||||
$message = $map->getEscapedName() . ' got ' . $action . '!';
|
||||
}
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -342,6 +338,7 @@ class MapManager implements CallbackListener {
|
||||
* @param int $mapId
|
||||
* @param string $login
|
||||
* @param bool $update
|
||||
* @param bool $displayMessage
|
||||
*/
|
||||
public function addMapFromMx($mapId, $login, $update = false) {
|
||||
if (is_numeric($mapId)) {
|
||||
@ -350,8 +347,10 @@ class MapManager implements CallbackListener {
|
||||
&$login, &$update
|
||||
) {
|
||||
if (!$mapInfo || !isset($mapInfo->uploaded)) {
|
||||
// Invalid id
|
||||
$this->maniaControl->getChat()->sendError('Invalid MX-Id!', $login);
|
||||
if ($login) {
|
||||
// Invalid id
|
||||
$this->maniaControl->getChat()->sendError('Invalid MX-Id!', $login);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -360,14 +359,17 @@ class MapManager implements CallbackListener {
|
||||
&$login, &$mapInfo, &$update
|
||||
) {
|
||||
if (!$file || $error) {
|
||||
// Download error
|
||||
$this->maniaControl->getChat()->sendError("Download failed: '{$error}'!", $login);
|
||||
if ($login) {
|
||||
// Download error
|
||||
$this->maniaControl->getChat()->sendError("Download failed: '{$error}'!", $login);
|
||||
}
|
||||
return;
|
||||
}
|
||||
$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();
|
||||
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
|
||||
if (!$update) {
|
||||
// Message
|
||||
$message = $player->getEscapedNickname() . ' added $<' . $mapInfo->name . '$>!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
// Queue requested Map
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($login, $mapInfo->uid);
|
||||
} else {
|
||||
$message = $player->getEscapedNickname() . ' updated $<' . $mapInfo->name . '$>!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
//TODO messages for communication
|
||||
if ($login) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$update) {
|
||||
// Message
|
||||
$message = $player->getEscapedNickname() . ' added $<' . $mapInfo->name . '$>!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
// Queue requested Map
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($login, $mapInfo->uid);
|
||||
} else {
|
||||
$message = $player->getEscapedNickname() . ' updated $<' . $mapInfo->name . '$>!';
|
||||
$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);
|
||||
|
||||
// Write 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_AUTOSAVE_MAPLIST)) {
|
||||
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_WRITE_OWN_MAPLIST_FILE)) {
|
||||
$serverLogin = $this->maniaControl->getServer()->login;
|
||||
$matchSettingsFileName = "MatchSettings/{$serverLogin}.txt";
|
||||
} else {
|
||||
@ -884,4 +886,102 @@ class MapManager implements CallbackListener {
|
||||
public function getMapsCount() {
|
||||
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 */
|
||||
private $maniaControl = null;
|
||||
private $queuedMaps = array();
|
||||
private $nextMap = null;
|
||||
private $buffer = array();
|
||||
private $nextNoQueue = false;
|
||||
private $queuedMaps = array();
|
||||
private $nextMap = null;
|
||||
private $buffer = array();
|
||||
private $nextNoQueue = false;
|
||||
|
||||
/**
|
||||
* Construct a new map queue instance
|
||||
@ -108,8 +108,7 @@ class MapQueue implements CallbackListener, CommandListener {
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -223,8 +222,8 @@ class MapQueue implements CallbackListener, CommandListener {
|
||||
if (array_key_exists($map->uid, $this->queuedMaps)) {
|
||||
unset($this->queuedMaps[$map->uid]);
|
||||
}
|
||||
|
||||
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
|
||||
if (in_array($uid, $this->buffer)) {
|
||||
$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;
|
||||
}
|
||||
}
|
||||
@ -329,10 +327,10 @@ class MapQueue implements CallbackListener, CommandListener {
|
||||
/**
|
||||
* Remove a Map from the Map queue
|
||||
*
|
||||
* @param Player $player
|
||||
* @param string $uid
|
||||
* @param Player|null $player
|
||||
* @param string $uid
|
||||
*/
|
||||
public function removeFromMapQueue(Player $player, $uid) {
|
||||
public function removeFromMapQueue($player, $uid) {
|
||||
if (!isset($this->queuedMaps[$uid])) {
|
||||
return;
|
||||
}
|
||||
@ -340,7 +338,9 @@ class MapQueue implements CallbackListener, CommandListener {
|
||||
$map = $this->queuedMaps[$uid][1];
|
||||
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
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('remove', $map));
|
||||
@ -359,8 +359,7 @@ class MapQueue implements CallbackListener, CommandListener {
|
||||
}
|
||||
|
||||
$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
|
||||
foreach ($this->queuedMaps as $queuedMap) {
|
||||
$player = $queuedMap[0];
|
||||
@ -423,8 +422,7 @@ class MapQueue implements CallbackListener, CommandListener {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ namespace ManiaControl\Players;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Utils\ClassUtil;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use Maniaplanet\DedicatedServer\Structures\LadderStats;
|
||||
|
||||
/**
|
||||
* Player Model Class
|
||||
@ -17,55 +18,56 @@ class Player {
|
||||
/*
|
||||
* Public Properties
|
||||
*/
|
||||
public $index = -1;
|
||||
public $pid = -1;
|
||||
public $login = null;
|
||||
public $nickname = null;
|
||||
public $index = -1;
|
||||
public $pid = -1;
|
||||
public $login = null;
|
||||
public $nickname = null;
|
||||
public $rawNickname = null;
|
||||
public $path = null;
|
||||
public $authLevel = 0;
|
||||
public $language = null;
|
||||
public $avatar = null;
|
||||
public $allies = array();
|
||||
public $clubLink = null;
|
||||
public $teamId = -1;
|
||||
public $isOfficial = null;
|
||||
public $path = null;
|
||||
public $authLevel = 0;
|
||||
public $language = null;
|
||||
public $avatar = null;
|
||||
public $allies = array();
|
||||
public $clubLink = null;
|
||||
public $teamId = -1;
|
||||
public $isOfficial = null;
|
||||
public $ladderScore = -1.;
|
||||
public $ladderRank = -1;
|
||||
public $ladderStats = null;
|
||||
public $joinTime = -1;
|
||||
public $ipAddress = null;
|
||||
public $isConnected = true;
|
||||
public $clientVersion = null;
|
||||
public $downloadRate = -1;
|
||||
public $uploadRate = -1;
|
||||
public $skins = null;
|
||||
public $ladderRank = -1;
|
||||
/** @var LadderStats $ladderStats */
|
||||
public $ladderStats = null;
|
||||
public $joinTime = -1;
|
||||
public $ipAddress = null;
|
||||
public $isConnected = true;
|
||||
public $clientVersion = null;
|
||||
public $downloadRate = -1;
|
||||
public $uploadRate = -1;
|
||||
public $skins = null;
|
||||
public $daysSinceZoneInscription = -1;
|
||||
|
||||
//Flags details
|
||||
public $forcedSpectatorState = 0;
|
||||
public $isReferee = false;
|
||||
public $isPodiumReady = false;
|
||||
public $isUsingStereoscopy = false;
|
||||
public $forcedSpectatorState = 0;
|
||||
public $isReferee = false;
|
||||
public $isPodiumReady = false;
|
||||
public $isUsingStereoscopy = false;
|
||||
public $isManagedByAnOtherServer = false;
|
||||
public $isServer = false;
|
||||
public $hasPlayerSlot = false;
|
||||
public $isBroadcasting = false;
|
||||
public $hasJoinedGame = false;
|
||||
public $isServer = false;
|
||||
public $hasPlayerSlot = false;
|
||||
public $isBroadcasting = false;
|
||||
public $hasJoinedGame = false;
|
||||
|
||||
//SpectatorStatus details
|
||||
public $isSpectator = false;
|
||||
public $isSpectator = false;
|
||||
public $isTemporarySpectator = false;
|
||||
public $isPureSpectator = false;
|
||||
public $autoTarget = false;
|
||||
public $currentTargetId = 0;
|
||||
public $isPureSpectator = false;
|
||||
public $autoTarget = false;
|
||||
public $currentTargetId = 0;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $cache = array();
|
||||
private $cache = array();
|
||||
|
||||
/**
|
||||
* Construct a new Player
|
||||
@ -75,7 +77,7 @@ class Player {
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl, $connected) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->isConnected = (bool)$connected;
|
||||
$this->isConnected = (bool) $connected;
|
||||
if ($connected) {
|
||||
$this->joinTime = time();
|
||||
}
|
||||
@ -89,9 +91,9 @@ class Player {
|
||||
*/
|
||||
public static function parseLogin($player) {
|
||||
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) {
|
||||
//Detail flags
|
||||
$this->forcedSpectatorState = $flags % 10; // 0, 1 or 2
|
||||
$this->isReferee = (bool)(intval($flags / 10) % 10);
|
||||
$this->isPodiumReady = (bool)(intval($flags / 100) % 10);
|
||||
$this->isUsingStereoscopy = (bool)(intval($flags / 1000) % 10);
|
||||
$this->isManagedByAnOtherServer = (bool)(intval($flags / 10000) % 10);
|
||||
$this->isServer = (bool)(intval($flags / 100000) % 10);
|
||||
$this->hasPlayerSlot = (bool)(intval($flags / 1000000) % 10);
|
||||
$this->isBroadcasting = (bool)(intval($flags / 10000000) % 10);
|
||||
$this->hasJoinedGame = (bool)(intval($flags / 100000000) % 10);
|
||||
$this->isReferee = (bool) (intval($flags / 10) % 10);
|
||||
$this->isPodiumReady = (bool) (intval($flags / 100) % 10);
|
||||
$this->isUsingStereoscopy = (bool) (intval($flags / 1000) % 10);
|
||||
$this->isManagedByAnOtherServer = (bool) (intval($flags / 10000) % 10);
|
||||
$this->isServer = (bool) (intval($flags / 100000) % 10);
|
||||
$this->hasPlayerSlot = (bool) (intval($flags / 1000000) % 10);
|
||||
$this->isBroadcasting = (bool) (intval($flags / 10000000) % 10);
|
||||
$this->hasJoinedGame = (bool) (intval($flags / 100000000) % 10);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -252,10 +254,10 @@ class Player {
|
||||
*/
|
||||
public function updateSpectatorStatus($spectatorStatus) {
|
||||
//Details spectatorStatus
|
||||
$this->isSpectator = (bool)($spectatorStatus % 10);
|
||||
$this->isTemporarySpectator = (bool)(intval($spectatorStatus / 10) % 10);
|
||||
$this->isPureSpectator = (bool)(intval($spectatorStatus / 100) % 10);
|
||||
$this->autoTarget = (bool)(intval($spectatorStatus / 1000) % 10);
|
||||
$this->isSpectator = (bool) ($spectatorStatus % 10);
|
||||
$this->isTemporarySpectator = (bool) (intval($spectatorStatus / 10) % 10);
|
||||
$this->isPureSpectator = (bool) (intval($spectatorStatus / 100) % 10);
|
||||
$this->autoTarget = (bool) (intval($spectatorStatus / 1000) % 10);
|
||||
$this->currentTargetId = intval($spectatorStatus / 10000);
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,10 @@ use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\ManiaLink;
|
||||
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\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
@ -26,7 +30,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerActions {
|
||||
class PlayerActions implements EchoListener, CommunicationListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
@ -36,6 +40,7 @@ class PlayerActions {
|
||||
const SPECTATOR_SPECTATOR = 1;
|
||||
const SPECTATOR_PLAYER = 2;
|
||||
const SPECTATOR_BUT_KEEP_SELECTABLE = 3;
|
||||
const ECHO_WARN_PLAYER = 'ManiaControl.PlayerManager.WarnPlayer';
|
||||
|
||||
/*
|
||||
* Permission Setting Constants
|
||||
@ -48,6 +53,7 @@ class PlayerActions {
|
||||
const SETTING_PERMISSION_KICK_PLAYER = 'Kick Player';
|
||||
const SETTING_PERMISSION_BAN_PLAYER = 'Ban Player';
|
||||
|
||||
|
||||
/*
|
||||
* 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_TEAM, 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 $targetLogin
|
||||
* @param int $teamId
|
||||
* @param bool $calledByAdmin
|
||||
* @return bool
|
||||
*/
|
||||
public function forcePlayerToTeam($adminLogin, $targetLogin, $teamId) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_TEAM)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return;
|
||||
public function forcePlayerToTeam($adminLogin, $targetLogin, $teamId, $calledByAdmin = true) {
|
||||
if ($calledByAdmin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_TEAM)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
}
|
||||
if (!$admin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$target || !$admin) {
|
||||
return;
|
||||
if (!$target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($target->isSpectator) {
|
||||
try {
|
||||
if (!$this->forcePlayerToPlay($adminLogin, $targetLogin, true, false)) {
|
||||
return;
|
||||
if (!$this->forcePlayerToPlay($adminLogin, $targetLogin, true, false, $calledByAdmin)) {
|
||||
return false;
|
||||
}
|
||||
} 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);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->forcePlayerToPlay($adminLogin, $targetLogin);
|
||||
return;
|
||||
return false;
|
||||
} catch (UnknownPlayerException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
return;
|
||||
if ($calledByAdmin) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
}
|
||||
return false;
|
||||
} catch (GameModeException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
return;
|
||||
if ($calledByAdmin) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$chatMessage = false;
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
if ($teamId === self::TEAM_BLUE) {
|
||||
$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!';
|
||||
|
||||
if ($calledByAdmin) {
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
if ($teamId === self::TEAM_BLUE) {
|
||||
$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) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,15 +234,18 @@ class PlayerActions {
|
||||
* @param string $targetLogin
|
||||
* @param bool $userIsAbleToSelect
|
||||
* @param bool $displayAnnouncement
|
||||
* @param bool $calledByAdmin
|
||||
* @return bool
|
||||
*/
|
||||
public function forcePlayerToPlay($adminLogin, $targetLogin, $userIsAbleToSelect = true, $displayAnnouncement = true) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_PLAY)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
public function forcePlayerToPlay($adminLogin, $targetLogin, $userIsAbleToSelect = true, $displayAnnouncement = true, $calledByAdmin = true) {
|
||||
if ($calledByAdmin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_PLAY)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$target) {
|
||||
return false;
|
||||
@ -152,7 +254,9 @@ class PlayerActions {
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_PLAYER);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
if ($calledByAdmin) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -160,14 +264,22 @@ class PlayerActions {
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_USER_SELECTABLE);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
if ($calledByAdmin) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Announce force
|
||||
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);
|
||||
}
|
||||
|
||||
@ -181,29 +293,43 @@ class PlayerActions {
|
||||
* @param string $targetLogin
|
||||
* @param int $spectatorState
|
||||
* @param bool $releaseSlot
|
||||
* @param bool $calledByAdmin
|
||||
* @return bool
|
||||
*/
|
||||
public function forcePlayerToSpectator($adminLogin, $targetLogin, $spectatorState = self::SPECTATOR_BUT_KEEP_SELECTABLE, $releaseSlot = true) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_SPEC)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return;
|
||||
public function forcePlayerToSpectator($adminLogin, $targetLogin, $spectatorState = self::SPECTATOR_BUT_KEEP_SELECTABLE, $releaseSlot = true, $calledByAdmin = true) {
|
||||
if ($calledByAdmin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_FORCE_PLAYER_SPEC)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$admin) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$admin || !$target || $target->isSpectator) {
|
||||
return;
|
||||
if (!$target || $target->isSpectator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($target->login, $spectatorState);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin->login);
|
||||
return;
|
||||
if ($calledByAdmin) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin->login);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' to Spectator!';
|
||||
if ($calledByAdmin) {
|
||||
$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);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
|
||||
@ -215,39 +341,50 @@ class PlayerActions {
|
||||
} catch (UnknownPlayerException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* UnMute a Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param $adminLogin
|
||||
* @param $targetLogin
|
||||
* @param bool $calledByAdmin
|
||||
* @return bool
|
||||
*/
|
||||
public function unMutePlayer($adminLogin, $targetLogin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return;
|
||||
public function unMutePlayer($adminLogin, $targetLogin, $calledByAdmin = true) {
|
||||
if ($calledByAdmin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->unIgnore($targetLogin);
|
||||
} catch (NotInListException $e) {
|
||||
$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);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -255,32 +392,42 @@ class PlayerActions {
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param bool $calledByAdmin
|
||||
* @return bool
|
||||
*/
|
||||
public function mutePlayer($adminLogin, $targetLogin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return;
|
||||
public function mutePlayer($adminLogin, $targetLogin, $calledByAdmin = true) {
|
||||
if ($calledByAdmin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_MUTE_PLAYER)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->ignore($targetLogin);
|
||||
} catch (AlreadyInListException $e) {
|
||||
$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);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -288,19 +435,22 @@ class PlayerActions {
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param bool $calledByAdmin
|
||||
* @return bool
|
||||
*/
|
||||
public function warnPlayer($adminLogin, $targetLogin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_WARN_PLAYER)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return;
|
||||
public function warnPlayer($adminLogin, $targetLogin, $calledByAdmin = true) {
|
||||
if ($calledByAdmin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_WARN_PLAYER)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Display warning message
|
||||
@ -360,49 +510,78 @@ class PlayerActions {
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $target);
|
||||
|
||||
// Announce warning
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' warned ' . $target->getEscapedNickname() . '!';
|
||||
if ($calledByAdmin) {
|
||||
$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);
|
||||
Logger::log($chatMessage, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Kick a Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param $adminLogin
|
||||
* @param $targetLogin
|
||||
* @param string $message
|
||||
* @param bool $calledByAdmin
|
||||
* @return bool
|
||||
*/
|
||||
public function kickPlayer($adminLogin, $targetLogin, $message = '') {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_KICK_PLAYER)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return;
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$target) {
|
||||
return;
|
||||
public function kickPlayer($adminLogin, $targetLogin, $message = '', $calledByAdmin = true) {
|
||||
if ($calledByAdmin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_KICK_PLAYER)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ($target->isFakePlayer()) {
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($target->isFakePlayer()) {
|
||||
try {
|
||||
$this->maniaControl->getClient()->disconnectFakePlayer($target->login);
|
||||
} else {
|
||||
$this->maniaControl->getClient()->kick($target->login, $message);
|
||||
} catch (PlayerStateException $e) {
|
||||
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
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' kicked ' . $target->getEscapedNickname() . '!';
|
||||
if ($calledByAdmin) {
|
||||
$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);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Ban a Player
|
||||
*
|
||||
@ -412,17 +591,18 @@ class PlayerActions {
|
||||
*/
|
||||
public function banPlayer($adminLogin, $targetLogin, $message = '') {
|
||||
$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);
|
||||
return;
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$target) {
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -450,8 +630,7 @@ class PlayerActions {
|
||||
*/
|
||||
public function unBanPlayer($adminLogin, $targetLogin) {
|
||||
$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);
|
||||
return;
|
||||
}
|
||||
@ -485,14 +664,12 @@ class PlayerActions {
|
||||
}
|
||||
|
||||
$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);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -523,15 +700,13 @@ class PlayerActions {
|
||||
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);
|
||||
$this->maniaControl->getChat()->sendError("You can't revoke the Rights of a {$title}!", $admin);
|
||||
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);
|
||||
return;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $maniaControl = null;
|
||||
private $playersListShown = array();
|
||||
|
||||
/**
|
||||
@ -163,9 +163,9 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
$headFrame = new Frame();
|
||||
$frame->add($headFrame);
|
||||
$headFrame->setY($posY - 5);
|
||||
|
||||
$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;
|
||||
}
|
||||
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $labelLineArray);
|
||||
@ -195,8 +195,9 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
$lineQuad->setZ(0.001);
|
||||
}
|
||||
|
||||
$array = array($index => $posX + 5, $listPlayer->nickname => $posX + 18, $listPlayer->login => $posX + 70, $path => $posX + 101);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, $array);
|
||||
$positions = array($posX + 5, $posX + 18, $posX + 70, $posX + 101);
|
||||
$texts = array($index, $listPlayer->nickname, $listPlayer->login, $path);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, array($positions, $texts));
|
||||
|
||||
$playerFrame->setY($posY);
|
||||
|
||||
@ -304,8 +305,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
$description = 'View Player Profile of $<' . $listPlayer->nickname . '$>';
|
||||
$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
|
||||
$playerQuad = new Quad_Icons64x64_1();
|
||||
$playerFrame->add($playerQuad);
|
||||
@ -320,10 +320,8 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getServer()->isTeamMode()
|
||||
) {
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_TEAM)
|
||||
) {
|
||||
if ($this->maniaControl->getServer()->isTeamMode()) {
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_TEAM)) {
|
||||
// Force to Red-Team Quad
|
||||
$redQuad = new Quad_Emblems();
|
||||
$playerFrame->add($redQuad);
|
||||
@ -350,8 +348,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
$description = 'Force $<' . $listPlayer->nickname . '$> to Blue Team!';
|
||||
$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
|
||||
$kickQuad = new Quad_UIConstruction_Buttons();
|
||||
$playerFrame->add($kickQuad);
|
||||
@ -365,8 +362,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
$kickQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
} 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
|
||||
$playQuad = new Quad_Emblems();
|
||||
$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
|
||||
$spectatorQuad = new Quad_BgRaceScore2();
|
||||
$playerFrame->add($spectatorQuad);
|
||||
@ -395,8 +390,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
// Force to Spectator Description Label
|
||||
$description = 'Force $<' . $listPlayer->nickname . '$> to Spectator!';
|
||||
$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
|
||||
$spectatorQuad = new Quad_BgRaceScore2();
|
||||
$playerFrame->add($spectatorQuad);
|
||||
@ -451,7 +445,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
// mainframe
|
||||
$frame = new Frame();
|
||||
$frame->setSize($width, $height);
|
||||
$frame->setPosition($posX + $width / 2, 0);
|
||||
$frame->setPosition($posX + $width / 2, 0, 31);
|
||||
|
||||
// Add Close Quad (X)
|
||||
$closeQuad = new Quad_Icons64x64_1();
|
||||
@ -467,14 +461,14 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
|
||||
$backgroundQuad->setSize($width, $height);
|
||||
$backgroundQuad->setImage('https://dl.dropboxusercontent.com/u/105352981/Stuff/CAM%20SM%20BORDER%20PNG.png'); //TODO just a test
|
||||
//$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
$backgroundQuad->setZ(0.2);
|
||||
$backgroundQuad->setZ(-0.3);
|
||||
|
||||
// Background Quad
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$backgroundQuad->setSize($width - 2, $height - 2);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
$backgroundQuad->setZ(0.1);
|
||||
$backgroundQuad->setZ(-0.4);
|
||||
|
||||
// Show headline
|
||||
$label = new Label_Text();
|
||||
|
@ -7,6 +7,9 @@ use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Communication\CommunicationAnswer;
|
||||
use ManiaControl\Communication\CommunicationListener;
|
||||
use ManiaControl\Communication\CommunicationMethods;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Statistics\StatisticManager;
|
||||
@ -20,7 +23,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerManager implements CallbackListener, TimerListener {
|
||||
class PlayerManager implements CallbackListener, TimerListener, CommunicationListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
@ -105,6 +108,12 @@ class PlayerManager implements CallbackListener, TimerListener {
|
||||
// Player stats
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_JOIN_COUNT);
|
||||
$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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle OnInit callback
|
||||
*/
|
||||
@ -374,15 +384,24 @@ class PlayerManager implements CallbackListener, TimerListener {
|
||||
* Get the count of all Players
|
||||
*
|
||||
* @param bool $withoutSpectators
|
||||
* @param bool $withoutBots
|
||||
* @return int
|
||||
*/
|
||||
public function getPlayerCount($withoutSpectators = true) {
|
||||
if (!$withoutSpectators) {
|
||||
return count($this->players);
|
||||
}
|
||||
public function getPlayerCount($withoutSpectators = true, $withoutBots = true) {
|
||||
$count = 0;
|
||||
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++;
|
||||
}
|
||||
}
|
||||
@ -516,6 +535,22 @@ class PlayerManager implements CallbackListener, TimerListener {
|
||||
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
|
||||
*
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace ManiaControl\Plugins;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\EchoListener;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
@ -141,6 +142,9 @@ class PluginManager {
|
||||
|
||||
$plugin->unload();
|
||||
|
||||
if ($plugin instanceof EchoListener) {
|
||||
$this->maniaControl->getEchoManager()->unregisterEchoListener($plugin);
|
||||
}
|
||||
if ($plugin instanceof CallbackListener) {
|
||||
$this->maniaControl->getCallbackManager()->unregisterCallbackListener($plugin);
|
||||
$this->maniaControl->getCallbackManager()->unregisterScriptCallbackListener($plugin);
|
||||
|
@ -40,13 +40,14 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
const SETTING_PERMISSION_CHANGE_SERVERSETTINGS = 'Change ServerSettings';
|
||||
const COMMAND_EXTEND_WARMUP = 'WarmUp_Extend';
|
||||
const COMMAND_FORCE_WARMUP = 'Command_ForceWarmUp';
|
||||
const COMMAND_SET_PAUSE = 'Command_SetPause';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $serverShutdownTime = -1;
|
||||
private $maniaControl = null;
|
||||
private $serverShutdownTime = -1;
|
||||
private $serverShutdownEmpty = false;
|
||||
|
||||
/**
|
||||
@ -113,7 +114,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
try {
|
||||
$scriptInfos = $this->maniaControl->getClient()->getModeScriptInfo();
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@ -163,14 +164,12 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getClient()->cancelVote()
|
||||
) {
|
||||
if ($this->maniaControl->getClient()->cancelVote()) {
|
||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' cancelled the Vote!');
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendInformation("There's no vote running currently!", $player);
|
||||
@ -187,8 +186,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -207,8 +205,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -227,16 +224,27 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
|
||||
//Normal Gamemodes
|
||||
try {
|
||||
$this->maniaControl->getClient()->sendModeScriptCommands(array('Command_ForceWarmUp' => true));
|
||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' paused the Game!');
|
||||
} 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
|
||||
// Empty shutdown
|
||||
if ($this->serverShutdownEmpty) {
|
||||
if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) <= 0
|
||||
) {
|
||||
if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) <= 0) {
|
||||
$this->shutdownServer('empty');
|
||||
}
|
||||
}
|
||||
@ -277,8 +284,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -294,8 +300,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -312,7 +317,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
$this->maniaControl->getChat()->sendInformation("Empty-shutdown cancelled!", $player);
|
||||
return;
|
||||
}
|
||||
$delay = (int)$param;
|
||||
$delay = (int) $param;
|
||||
if ($delay <= 0) {
|
||||
// Cancel shutdown
|
||||
$this->serverShutdownTime = -1;
|
||||
@ -334,8 +339,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -356,8 +360,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -379,8 +382,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -402,8 +404,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -417,7 +418,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxplayers 16', $player);
|
||||
return;
|
||||
}
|
||||
$amount = (int)$amount;
|
||||
$amount = (int) $amount;
|
||||
if ($amount < 0) {
|
||||
$amount = 0;
|
||||
}
|
||||
@ -433,8 +434,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
* @param 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);
|
||||
return;
|
||||
}
|
||||
@ -448,7 +448,7 @@ class Commands implements CallbackListener, CommandListener, ManialinkPageAnswer
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxspectators 16', $player);
|
||||
return;
|
||||
}
|
||||
$amount = (int)$amount;
|
||||
$amount = (int) $amount;
|
||||
if ($amount < 0) {
|
||||
$amount = 0;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ namespace ManiaControl\Server;
|
||||
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
|
||||
/**
|
||||
* Manager for Game Mode Script related Stuff
|
||||
@ -39,13 +40,18 @@ class ScriptManager {
|
||||
if (!$this->isScriptMode()) {
|
||||
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)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$scriptSettings['S_UseScriptCallbacks'] = (bool)$enable;
|
||||
$scriptSettings['S_UseScriptCallbacks'] = (bool) $enable;
|
||||
$actionName = ($enable ? 'en' : 'dis');
|
||||
|
||||
$this->maniaControl->getClient()->setModeScriptSettings($scriptSettings);
|
||||
|
@ -4,6 +4,7 @@ namespace ManiaControl\Server;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
@ -17,7 +18,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\Exception;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Server implements CallbackListener {
|
||||
class Server implements CallbackListener, CommandListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
@ -85,6 +86,30 @@ class Server implements CallbackListener {
|
||||
|
||||
// Callbacks
|
||||
$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;
|
||||
}
|
||||
|
||||
/** 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
|
||||
*/
|
||||
|
@ -14,6 +14,9 @@ use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Communication\CommunicationAnswer;
|
||||
use ManiaControl\Communication\CommunicationListener;
|
||||
use ManiaControl\Communication\CommunicationMethods;
|
||||
use ManiaControl\Configurator\ConfiguratorMenu;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
@ -28,7 +31,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\ServerOptionsException;
|
||||
* @copyright 2014-2015 ManiaControl Team
|
||||
* @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
|
||||
*/
|
||||
@ -64,6 +67,10 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
|
||||
|
||||
// Permissions
|
||||
$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()
|
||||
*/
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -376,4 +382,43 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
|
||||
|
||||
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!');
|
||||
}
|
||||
|
||||
// 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) {
|
||||
// Missing requirements
|
||||
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))
|
||||
{
|
||||
$filename = $this->stripBom($filename);
|
||||
if(mb_check_encoding($filename, 'ascii'))
|
||||
return $filename;
|
||||
return "\xEF\xBB\xBF".$filename;
|
||||
if(preg_match('/[^\x09\x0A\x0D\x20-\x7E]/', $filename))
|
||||
return "\xEF\xBB\xBF".$filename;
|
||||
return $filename;
|
||||
}
|
||||
return array_map(array($this, 'secureUtf8'), $filename);
|
||||
}
|
||||
|
@ -7,12 +7,9 @@
|
||||
|
||||
namespace Maniaplanet\DedicatedServer\Xmlrpc;
|
||||
|
||||
class FaultException extends Exception
|
||||
{
|
||||
static function create($faultString, $faultCode)
|
||||
{
|
||||
switch($faultString)
|
||||
{
|
||||
class FaultException extends Exception {
|
||||
static function create($faultString, $faultCode) {
|
||||
switch ($faultString) {
|
||||
case 'Password incorrect.':
|
||||
case 'Permission denied.':
|
||||
return new AuthenticationException($faultString, $faultCode);
|
||||
@ -34,6 +31,7 @@ class FaultException extends Exception
|
||||
return new LockedFeatureException($faultString, $faultCode);
|
||||
case 'Login or Uid unknown.':
|
||||
case 'Login unknown.':
|
||||
case 'Payer login unknown.':
|
||||
return new UnknownPlayerException($faultString, $faultCode);
|
||||
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 'There are too many players':
|
||||
case 'There are too many spectators':
|
||||
case 'Unknown hideserver value':
|
||||
return new ServerOptionsException($faultString, $faultCode);
|
||||
case 'New mode unknown.':
|
||||
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 Rounds or Laps mode.':
|
||||
case 'The scores must be decreasing.':
|
||||
case 'No current script.':
|
||||
return new GameModeException($faultString, $faultCode);
|
||||
case 'Unable to write the black list file.':
|
||||
case 'Unable to write the guest list file.':
|
||||
@ -90,26 +90,55 @@ class FaultException extends Exception
|
||||
case 'Invalid url.':
|
||||
return new FileException($faultString, $faultCode);
|
||||
}
|
||||
if(preg_match('~^Unknown setting \'.*\'\.$~iu', $faultString))
|
||||
if (preg_match('~^Unknown setting \'.*\'\.$~iu', $faultString)) {
|
||||
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 self($faultString, $faultCode);
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationException extends FaultException {}
|
||||
class UnavailableFeatureException extends FaultException {}
|
||||
class LockedFeatureException extends FaultException {}
|
||||
class UnknownPlayerException extends FaultException {}
|
||||
class PlayerStateException 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 {}
|
||||
class AuthenticationException extends FaultException {
|
||||
}
|
||||
|
||||
class UnavailableFeatureException extends FaultException {
|
||||
}
|
||||
|
||||
class LockedFeatureException extends FaultException {
|
||||
}
|
||||
|
||||
class UnknownPlayerException extends FaultException {
|
||||
}
|
||||
|
||||
class PlayerStateException 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;
|
||||
|
||||
private $socket;
|
||||
private $readTimeout = array('sec' => 5, 'usec' => 0);
|
||||
private $writeTimeout = array('sec' => 5, 'usec' => 0);
|
||||
private $readTimeout = array('sec' => 30, 'usec' => 0);
|
||||
private $writeTimeout = array('sec' => 30, 'usec' => 0);
|
||||
private $requestHandle;
|
||||
private $callbacksBuffer = 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)
|
||||
{
|
||||
if (null === $eventName) {
|
||||
foreach (array_keys($this->listenerIds) as $serviceEventName) {
|
||||
foreach ($this->listenerIds as $serviceEventName => $args) {
|
||||
$this->lazyLoad($serviceEventName);
|
||||
}
|
||||
} else {
|
||||
|
@ -31,6 +31,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
||||
|
||||
private $called;
|
||||
private $dispatcher;
|
||||
private $wrappedListeners;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@ -45,6 +46,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->logger = $logger;
|
||||
$this->called = array();
|
||||
$this->wrappedListeners = array();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,6 +70,16 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
@ -146,7 +158,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
||||
$allListeners = $this->getListeners();
|
||||
} catch (\Exception $e) {
|
||||
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
|
||||
@ -216,12 +228,15 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
|
||||
$this->dispatcher->removeListener($eventName, $listener);
|
||||
$info = $this->getListenerInfo($listener, $eventName);
|
||||
$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)
|
||||
{
|
||||
unset($this->wrappedListeners[$eventName]);
|
||||
$skipped = false;
|
||||
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
|
||||
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 string $eventName The event name
|
||||
|
@ -25,12 +25,14 @@ class WrappedListener
|
||||
private $called;
|
||||
private $stoppedPropagation;
|
||||
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->name = $name;
|
||||
$this->stopwatch = $stopwatch;
|
||||
$this->dispatcher = $dispatcher;
|
||||
$this->called = false;
|
||||
$this->stoppedPropagation = false;
|
||||
}
|
||||
@ -56,7 +58,7 @@ class WrappedListener
|
||||
|
||||
$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()) {
|
||||
$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));
|
||||
}
|
||||
|
||||
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
|
||||
$class = $def->getClass();
|
||||
$class = $container->getParameterBag()->resolveValue($def->getClass());
|
||||
|
||||
$refClass = new \ReflectionClass($class);
|
||||
$interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
|
||||
|
@ -77,7 +77,7 @@ class Event
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
@ -91,12 +91,14 @@ class Event
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
@ -105,12 +107,14 @@ class Event
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
@ -119,7 +123,7 @@ class Event
|
||||
*
|
||||
* @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
|
||||
*/
|
||||
|
@ -68,7 +68,7 @@ class EventDispatcher implements EventDispatcherInterface
|
||||
return $this->sorted[$eventName];
|
||||
}
|
||||
|
||||
foreach (array_keys($this->listeners) as $eventName) {
|
||||
foreach ($this->listeners as $eventName => $eventListeners) {
|
||||
if (!isset($this->sorted[$eventName])) {
|
||||
$this->sortListeners($eventName);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ interface EventDispatcherInterface
|
||||
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
|
||||
*
|
||||
|
@ -71,7 +71,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate
|
||||
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:
|
||||
|
||||
$ cd path/to/Symfony/Component/EventDispatcher/
|
||||
$ composer.phar install
|
||||
$ composer install
|
||||
$ phpunit
|
||||
|
@ -118,10 +118,21 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo));
|
||||
$event = new Event();
|
||||
$return = $this->dispatcher->dispatch(self::preFoo, $event);
|
||||
$this->assertEquals('pre.foo', $event->getName());
|
||||
$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()
|
||||
{
|
||||
$invoked = 0;
|
||||
@ -239,8 +250,13 @@ abstract class AbstractEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$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;
|
||||
$this->dispatcher->addListener('test', function ($event) use (&$dispatcher) {
|
||||
$dispatcher = $event->getDispatcher();
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\EventDispatcher\Tests\Debug;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
@ -86,6 +87,20 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$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()
|
||||
{
|
||||
$logger = $this->getMock('Psr\Log\LoggerInterface');
|
||||
@ -160,6 +175,19 @@ class TraceableEventDispatcherTest extends \PHPUnit_Framework_TestCase
|
||||
$dispatcher->dispatch('foo');
|
||||
$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
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user