removed 'application' folder to have everything in the root directory
This commit is contained in:
318
core/Admin/ActionsMenu.php
Normal file
318
core/Admin/ActionsMenu.php
Normal file
@ -0,0 +1,318 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Admin;
|
||||
|
||||
use FML\Controls\Control;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\ManiaLink;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
|
||||
/**
|
||||
* Class managing Actions Menus
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ActionsMenu implements CallbackListener, ManialinkPageAnswerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const MLID_MENU = 'ActionsMenu.MLID';
|
||||
const SETTING_MENU_POSX = 'Menu Position: X';
|
||||
const SETTING_MENU_POSY = 'Menu Position: Y';
|
||||
const SETTING_MENU_ITEMSIZE = 'Menu Item Size';
|
||||
const ACTION_OPEN_ADMIN_MENU = 'ActionsMenu.OpenAdminMenu';
|
||||
const ACTION_OPEN_PLAYER_MENU = 'ActionsMenu.OpenPlayerMenu';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $adminMenuItems = array();
|
||||
private $playerMenuItems = array();
|
||||
private $initCompleted = false;
|
||||
|
||||
/**
|
||||
* Construct a new Actions Menu instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_POSX, 156.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_POSY, -17.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_ITEMSIZE, 6.);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERCONNECT, $this, 'handlePlayerJoined');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(AuthenticationManager::CB_AUTH_LEVEL_CHANGED, $this, 'handlePlayerJoined');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Menu Item
|
||||
*
|
||||
* @param Control $control
|
||||
* @param bool $playerAction
|
||||
* @param int $order
|
||||
* @param string $description
|
||||
*/
|
||||
public function addMenuItem(Control $control, $playerAction = true, $order = 0, $description = null) {
|
||||
if ($playerAction) {
|
||||
$this->addPlayerMenuItem($control, $order, $description);
|
||||
} else {
|
||||
$this->addAdminMenuItem($control, $order, $description);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Player Menu Item
|
||||
*
|
||||
* @param Control $control
|
||||
* @param int $order
|
||||
* @param string $description
|
||||
*/
|
||||
public function addPlayerMenuItem(Control $control, $order = 0, $description = null) {
|
||||
if (!isset($this->playerMenuItems[$order])) {
|
||||
$this->playerMenuItems[$order] = array();
|
||||
}
|
||||
array_push($this->playerMenuItems[$order], array($control, $description));
|
||||
krsort($this->playerMenuItems);
|
||||
$this->rebuildAndShowMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and show the menus to everyone (if a menu get made after the init)
|
||||
*/
|
||||
public function rebuildAndShowMenu() {
|
||||
if (!$this->initCompleted) {
|
||||
return;
|
||||
}
|
||||
$players = $this->maniaControl->getPlayerManager()->getPlayers();
|
||||
foreach ($players as $player) {
|
||||
$manialink = $this->buildMenuIconsManialink($player);
|
||||
$this->maniaControl->getManialinkManager()->sendManialink($manialink, $player->login);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the Manialink
|
||||
*
|
||||
* @param Player $player
|
||||
* @return ManiaLink
|
||||
*/
|
||||
private function buildMenuIconsManialink(Player $player) {
|
||||
$posX = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSX);
|
||||
$posY = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSY);
|
||||
$itemSize = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_ITEMSIZE);
|
||||
$shootManiaOffset = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultIconOffsetSM();
|
||||
$quadStyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultQuadStyle();
|
||||
$quadSubstyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultQuadSubstyle();
|
||||
$itemMarginFactorX = 1.3;
|
||||
$itemMarginFactorY = 1.2;
|
||||
|
||||
// If game is shootmania lower the icons position by 20
|
||||
if ($this->maniaControl->getMapManager()->getCurrentMap()->getGame() === 'sm'
|
||||
) {
|
||||
$posY -= $shootManiaOffset;
|
||||
}
|
||||
|
||||
$manialink = new ManiaLink(self::MLID_MENU);
|
||||
|
||||
/*
|
||||
* Admin Menu
|
||||
*/
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)
|
||||
) {
|
||||
// Admin Menu Icon Frame
|
||||
$iconFrame = new Frame();
|
||||
$manialink->add($iconFrame);
|
||||
$iconFrame->setPosition($posX, $posY);
|
||||
|
||||
$backgroundQuad = new Quad();
|
||||
$iconFrame->add($backgroundQuad);
|
||||
$backgroundQuad->setSize($itemSize * $itemMarginFactorX, $itemSize * $itemMarginFactorY);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
$itemQuad = new Quad_Icons64x64_1();
|
||||
$iconFrame->add($itemQuad);
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_IconServers);
|
||||
$itemQuad->setSize($itemSize, $itemSize);
|
||||
|
||||
// Admin Menu Description
|
||||
$descriptionLabel = new Label();
|
||||
$manialink->add($descriptionLabel);
|
||||
$descriptionLabel->setPosition($posX - count($this->adminMenuItems) * $itemSize * 1.15 - 6, $posY);
|
||||
$descriptionLabel->setAlign($descriptionLabel::RIGHT, $descriptionLabel::TOP);
|
||||
$descriptionLabel->setSize(40, 4);
|
||||
$descriptionLabel->setTextSize(1.4);
|
||||
$descriptionLabel->setTextColor('fff');
|
||||
|
||||
// Admin Menu
|
||||
$popoutFrame = new Frame();
|
||||
$manialink->add($popoutFrame);
|
||||
$popoutFrame->setPosition($posX - $itemSize * 0.5, $posY);
|
||||
$popoutFrame->setHAlign($popoutFrame::RIGHT);
|
||||
$popoutFrame->setSize(4 * $itemSize * $itemMarginFactorX, $itemSize * $itemMarginFactorY);
|
||||
$popoutFrame->setVisible(false);
|
||||
|
||||
$backgroundQuad = new Quad();
|
||||
$popoutFrame->add($backgroundQuad);
|
||||
$backgroundQuad->setHAlign($backgroundQuad::RIGHT);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
$backgroundQuad->setSize(count($this->adminMenuItems) * $itemSize * 1.15 + 2, $itemSize * $itemMarginFactorY);
|
||||
|
||||
$itemQuad->addToggleFeature($popoutFrame);
|
||||
|
||||
// Add items
|
||||
$itemPosX = -1;
|
||||
foreach ($this->adminMenuItems as $menuItems) {
|
||||
foreach ($menuItems as $menuItem) {
|
||||
$menuQuad = $menuItem[0];
|
||||
/** @var Quad $menuQuad */
|
||||
$popoutFrame->add($menuQuad);
|
||||
$menuQuad->setSize($itemSize, $itemSize);
|
||||
$menuQuad->setX($itemPosX);
|
||||
$menuQuad->setHAlign($menuQuad::RIGHT);
|
||||
$itemPosX -= $itemSize * 1.05;
|
||||
|
||||
if ($menuItem[1]) {
|
||||
$menuQuad->removeScriptFeatures();
|
||||
$description = '$s' . $menuItem[1];
|
||||
$menuQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Player Menu
|
||||
*/
|
||||
// Player Menu Icon Frame
|
||||
$iconFrame = new Frame();
|
||||
$manialink->add($iconFrame);
|
||||
$iconFrame->setPosition($posX, $posY - $itemSize * $itemMarginFactorY);
|
||||
|
||||
$backgroundQuad = new Quad();
|
||||
$iconFrame->add($backgroundQuad);
|
||||
$backgroundQuad->setSize($itemSize * $itemMarginFactorX, $itemSize * $itemMarginFactorY);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
$itemQuad = new Quad_Icons64x64_1();
|
||||
$iconFrame->add($itemQuad);
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_IconPlayers);
|
||||
$itemQuad->setSize($itemSize, $itemSize);
|
||||
|
||||
// Player Menu Description
|
||||
$descriptionLabel = new Label();
|
||||
$manialink->add($descriptionLabel);
|
||||
$descriptionLabel->setPosition($posX - count($this->playerMenuItems) * $itemSize * 1.15 - 6, $posY - $itemSize * $itemMarginFactorY);
|
||||
$descriptionLabel->setAlign($descriptionLabel::RIGHT, $descriptionLabel::TOP);
|
||||
$descriptionLabel->setSize(40, 4);
|
||||
$descriptionLabel->setTextSize(1.4);
|
||||
$descriptionLabel->setTextColor('fff');
|
||||
|
||||
// Player Menu
|
||||
$popoutFrame = new Frame();
|
||||
$manialink->add($popoutFrame);
|
||||
$popoutFrame->setPosition($posX - $itemSize * 0.5, $posY - $itemSize * $itemMarginFactorY);
|
||||
$popoutFrame->setHAlign($popoutFrame::RIGHT);
|
||||
$popoutFrame->setSize(4 * $itemSize * $itemMarginFactorX, $itemSize * $itemMarginFactorY);
|
||||
$popoutFrame->setVisible(false);
|
||||
|
||||
$backgroundQuad = new Quad();
|
||||
$popoutFrame->add($backgroundQuad);
|
||||
$backgroundQuad->setHAlign($backgroundQuad::RIGHT);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
$backgroundQuad->setSize(count($this->playerMenuItems) * $itemSize * 1.15 + 2, $itemSize * $itemMarginFactorY);
|
||||
|
||||
$itemQuad->addToggleFeature($popoutFrame);
|
||||
|
||||
// Add items
|
||||
$itemPosX = -1;
|
||||
foreach ($this->playerMenuItems as $menuItems) {
|
||||
foreach ($menuItems as $menuItem) {
|
||||
$menuQuad = $menuItem[0];
|
||||
/** @var Quad $menuQuad */
|
||||
$popoutFrame->add($menuQuad);
|
||||
$menuQuad->setSize($itemSize, $itemSize);
|
||||
$menuQuad->setX($itemPosX);
|
||||
$menuQuad->setHAlign($menuQuad::RIGHT);
|
||||
$itemPosX -= $itemSize * 1.05;
|
||||
|
||||
if ($menuItem[1]) {
|
||||
$menuQuad->removeScriptFeatures();
|
||||
$description = '$s' . $menuItem[1];
|
||||
$menuQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $manialink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new Admin Menu Item
|
||||
*
|
||||
* @param Control $control
|
||||
* @param int $order
|
||||
* @param string $description
|
||||
*/
|
||||
public function addAdminMenuItem(Control $control, $order = 0, $description = null) {
|
||||
if (!isset($this->adminMenuItems[$order])) {
|
||||
$this->adminMenuItems[$order] = array();
|
||||
}
|
||||
array_push($this->adminMenuItems[$order], array($control, $description));
|
||||
krsort($this->adminMenuItems);
|
||||
$this->rebuildAndShowMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a Menu Item
|
||||
*
|
||||
* @param int $order
|
||||
* @param bool $playerAction
|
||||
*/
|
||||
public function removeMenuItem($order, $playerAction = true) {
|
||||
if ($playerAction) {
|
||||
if ($this->playerMenuItems[$order]) {
|
||||
unset($this->playerMenuItems[$order]);
|
||||
}
|
||||
} else {
|
||||
if ($this->playerMenuItems[$order]) {
|
||||
unset($this->adminMenuItems[$order]);
|
||||
}
|
||||
}
|
||||
$this->rebuildAndShowMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManiaControl AfterInit callback
|
||||
*/
|
||||
public function handleAfterInit() {
|
||||
$this->initCompleted = true;
|
||||
$this->rebuildAndShowMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PlayerJoined callback
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handlePlayerJoined(Player $player) {
|
||||
$maniaLink = $this->buildMenuIconsManialink($player);
|
||||
$this->maniaControl->getManialinkManager()->sendManialink($maniaLink, $player);
|
||||
}
|
||||
}
|
257
core/Admin/AdminLists.php
Normal file
257
core/Admin/AdminLists.php
Normal file
@ -0,0 +1,257 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Admin;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Button;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quads\Quad_BgRaceScore2;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use FML\ManiaLink;
|
||||
use FML\Script\Features\Paging;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
* Widget Class listing Authorized Players
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class AdminLists implements ManialinkPageAnswerListener, CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_OPEN_ADMIN_LIST = 'AdminList.OpenAdminList';
|
||||
const ACTION_REVOKE_RIGHTS = 'AdminList.RevokeRights';
|
||||
const MAX_PLAYERS_PER_PAGE = 15;
|
||||
|
||||
/*
|
||||
* Private Properties
|
||||
*/
|
||||
private $adminListShown = array();
|
||||
|
||||
/**
|
||||
* Construct a new PlayerList instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_CLOSED, $this, 'closeWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_OPENED, $this, 'handleWidgetOpened');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(AuthenticationManager::CB_AUTH_LEVEL_CHANGED, $this, 'updateWidget');
|
||||
|
||||
// Menu Entry AdminList
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_OPEN_ADMIN_LIST, $this, 'openAdminList');
|
||||
$itemQuad = new Quad_UIConstruction_Buttons();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_Author);
|
||||
$itemQuad->setAction(self::ACTION_OPEN_ADMIN_LIST);
|
||||
$this->maniaControl->getActionsMenu()->addMenuItem($itemQuad, false, 50, 'Open AdminList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Admin List Action
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function openAdminList(array $callback, Player $player) {
|
||||
$this->showAdminLists($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Admin List
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function showAdminLists(Player $player) {
|
||||
$this->adminListShown[$player->login] = true;
|
||||
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
|
||||
// get Admins
|
||||
$admins = $this->maniaControl->getAuthenticationManager()->getAdmins();
|
||||
|
||||
//Create ManiaLink
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$script = $maniaLink->getScript();
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
|
||||
// Main frame
|
||||
$frame = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultListFrame($script, $paging);
|
||||
$maniaLink->add($frame);
|
||||
|
||||
// Start offsets
|
||||
$posX = -$width / 2;
|
||||
$posY = $height / 2;
|
||||
|
||||
//Predefine description Label
|
||||
$descriptionLabel = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultDescriptionLabel();
|
||||
$frame->add($descriptionLabel);
|
||||
|
||||
// Headline
|
||||
$headFrame = new Frame();
|
||||
$frame->add($headFrame);
|
||||
$headFrame->setY($posY - 5);
|
||||
$array = array('Id' => $posX + 5, 'Nickname' => $posX + 18, 'Login' => $posX + 70, 'Actions' => $posX + 120);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $array);
|
||||
|
||||
$index = 1;
|
||||
$posY -= 10;
|
||||
$pageFrame = null;
|
||||
|
||||
foreach ($admins as $admin) {
|
||||
if ($index % self::MAX_PLAYERS_PER_PAGE === 1) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
|
||||
$paging->addPage($pageFrame);
|
||||
$posY = $height / 2 - 10;
|
||||
}
|
||||
|
||||
$playerFrame = new Frame();
|
||||
$pageFrame->add($playerFrame);
|
||||
$playerFrame->setY($posY);
|
||||
|
||||
if ($index % 2 !== 0) {
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$playerFrame->add($lineQuad);
|
||||
$lineQuad->setSize($width, 4);
|
||||
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$lineQuad->setZ(0.001);
|
||||
}
|
||||
|
||||
$array = array($index => $posX + 5, $admin->nickname => $posX + 18, $admin->login => $posX + 70);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, $array);
|
||||
|
||||
|
||||
// Level Quad
|
||||
$rightQuad = new Quad_BgRaceScore2();
|
||||
$playerFrame->add($rightQuad);
|
||||
$rightQuad->setX($posX + 13);
|
||||
$rightQuad->setZ(5);
|
||||
$rightQuad->setSubStyle($rightQuad::SUBSTYLE_CupFinisher);
|
||||
$rightQuad->setSize(7, 3.5);
|
||||
|
||||
$rightLabel = new Label_Text();
|
||||
$playerFrame->add($rightLabel);
|
||||
$rightLabel->setX($posX + 13.9);
|
||||
$rightLabel->setTextSize(0.8);
|
||||
$rightLabel->setZ(10);
|
||||
$rightLabel->setText($this->maniaControl->getAuthenticationManager()->getAuthLevelAbbreviation($admin));
|
||||
$description = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin) . " " . $admin->nickname;
|
||||
$rightLabel->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
//Revoke Button
|
||||
if ($admin->authLevel > 0
|
||||
&& $this->maniaControl->getAuthenticationManager()->checkRight($player, $admin->authLevel + 1)
|
||||
) {
|
||||
//Settings
|
||||
$style = Label_Text::STYLE_TextCardSmall;
|
||||
$textColor = 'FFF';
|
||||
$quadWidth = 24;
|
||||
$quadHeight = 3.4;
|
||||
|
||||
// Quad
|
||||
$quad = new Quad_BgsPlayerCard();
|
||||
$playerFrame->add($quad);
|
||||
$quad->setZ(11);
|
||||
$quad->setX($posX + 130);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_BgPlayerCardBig);
|
||||
$quad->setSize($quadWidth, $quadHeight);
|
||||
$quad->setAction(self::ACTION_REVOKE_RIGHTS . "." . $admin->login);
|
||||
|
||||
//Label
|
||||
$label = new Label_Button();
|
||||
$playerFrame->add($label);
|
||||
$label->setX($posX + 130);
|
||||
$quad->setZ(12);
|
||||
$label->setStyle($style);
|
||||
$label->setTextSize(1);
|
||||
$label->setTextColor($textColor);
|
||||
$label->setText("Revoke Rights");
|
||||
}
|
||||
|
||||
$posY -= 4;
|
||||
$index++;
|
||||
}
|
||||
|
||||
// Render and display xml
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'AdminList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on ManialinkPageAnswer
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$actionArray = explode('.', $actionId, 3);
|
||||
if (count($actionArray) <= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = $actionArray[0] . '.' . $actionArray[1];
|
||||
$adminLogin = $callback[1][1];
|
||||
$targetLogin = $actionArray[2];
|
||||
|
||||
switch ($action) {
|
||||
case self::ACTION_REVOKE_RIGHTS:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->revokeAuthLevel($adminLogin, $targetLogin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reopen the widget on Map Begin, MapListChanged, etc.
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function updateWidget(Player $player) {
|
||||
foreach ($this->adminListShown as $login => $shown) {
|
||||
if ($shown) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if ($player) {
|
||||
$this->showAdminLists($player);
|
||||
} else {
|
||||
unset($this->adminListShown[$login]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the widget
|
||||
*
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function closeWidget(Player $player) {
|
||||
unset($this->adminListShown[$player->login]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the player if he opened another Main Widget
|
||||
*
|
||||
* @param Player $player
|
||||
* @param $openedWidget
|
||||
*/
|
||||
public function handleWidgetOpened(Player $player, $openedWidget) {
|
||||
//unset when another main widget got opened
|
||||
if ($openedWidget !== 'AdminList') {
|
||||
unset($this->adminListShown[$player->login]);
|
||||
}
|
||||
}
|
||||
}
|
162
core/Admin/AuthCommands.php
Normal file
162
core/Admin/AuthCommands.php
Normal file
@ -0,0 +1,162 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Admin;
|
||||
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
* Class offering Commands to grant Authorizations to Players
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class AuthCommands implements CommandListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new AuthCommands instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Commands
|
||||
$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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //addsuperadmin command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_AddSuperAdmin(array $chatCallback, Player $player) {
|
||||
if (!AuthenticationManager::checkRight($player, AuthenticationManager::AUTH_LEVEL_MASTERADMIN)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$text = $chatCallback[1][2];
|
||||
$commandParts = explode(' ', $text);
|
||||
if (!array_key_exists(1, $commandParts)) {
|
||||
$this->sendAddSuperAdminUsageInfo($player);
|
||||
return;
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($commandParts[1]);
|
||||
if (!$target) {
|
||||
$this->maniaControl->getChat()->sendError("Player '{$commandParts[1]}' not found!", $player);
|
||||
return;
|
||||
}
|
||||
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
if (!$success) {
|
||||
$this->maniaControl->getChat()->sendError('Error occurred.', $player);
|
||||
return;
|
||||
}
|
||||
$message = $player->getEscapedNickname() . ' added ' . $target->getEscapedNickname() . ' as SuperAdmin!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send usage example for //addsuperadmin command
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function sendAddSuperAdminUsageInfo(Player $player) {
|
||||
$message = "Usage Example: '//addsuperadmin login'";
|
||||
return $this->maniaControl->getChat()->sendUsageInfo($message, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //addadmin command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_AddAdmin(array $chatCallback, Player $player) {
|
||||
if (!AuthenticationManager::checkRight($player, AuthenticationManager::AUTH_LEVEL_SUPERADMIN)) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$text = $chatCallback[1][2];
|
||||
$commandParts = explode(' ', $text);
|
||||
if (!array_key_exists(1, $commandParts)) {
|
||||
$this->sendAddAdminUsageInfo($player);
|
||||
return;
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($commandParts[1]);
|
||||
if (!$target) {
|
||||
$this->maniaControl->getChat()->sendError("Player '{$commandParts[1]}' not found!", $player);
|
||||
return;
|
||||
}
|
||||
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
if (!$success) {
|
||||
$this->maniaControl->getChat()->sendError('Error occurred.', $player);
|
||||
return;
|
||||
}
|
||||
$message = $player->getEscapedNickname() . ' added ' . $target->getEscapedNickname() . ' as Admin!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send usage example for //addadmin command
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function sendAddAdminUsageInfo(Player $player) {
|
||||
$message = "Usage Example: '//addadmin login'";
|
||||
return $this->maniaControl->getChat()->sendUsageInfo($message, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //addmod command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_AddModerator(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->sendAddModeratorUsageInfo($player);
|
||||
return;
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($commandParts[1]);
|
||||
if (!$target) {
|
||||
$this->maniaControl->getChat()->sendError("Player '{$commandParts[1]}' not found!", $player);
|
||||
return;
|
||||
}
|
||||
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
if (!$success) {
|
||||
$this->maniaControl->getChat()->sendError('Error occurred.', $player);
|
||||
return;
|
||||
}
|
||||
$message = $player->getEscapedNickname() . ' added ' . $target->getEscapedNickname() . ' as Moderator!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send usage example for //addmod command
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function sendAddModeratorUsageInfo(Player $player) {
|
||||
$message = "Usage Example: '//addmod login'";
|
||||
return $this->maniaControl->getChat()->sendUsageInfo($message, $player);
|
||||
}
|
||||
}
|
361
core/Admin/AuthenticationManager.php
Normal file
361
core/Admin/AuthenticationManager.php
Normal file
@ -0,0 +1,361 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Admin;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
use ManiaControl\Settings\Setting;
|
||||
|
||||
/**
|
||||
* Class managing Authentication Levels
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class AuthenticationManager implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const AUTH_LEVEL_PLAYER = 0;
|
||||
const AUTH_LEVEL_MODERATOR = 1;
|
||||
const AUTH_LEVEL_ADMIN = 2;
|
||||
const AUTH_LEVEL_SUPERADMIN = 3;
|
||||
const AUTH_LEVEL_MASTERADMIN = 4;
|
||||
const AUTH_NAME_PLAYER = 'Player';
|
||||
const AUTH_NAME_MODERATOR = 'Moderator';
|
||||
const AUTH_NAME_ADMIN = 'Admin';
|
||||
const AUTH_NAME_SUPERADMIN = 'SuperAdmin';
|
||||
const AUTH_NAME_MASTERADMIN = 'MasterAdmin';
|
||||
const CB_AUTH_LEVEL_CHANGED = 'AuthenticationManager.AuthLevelChanged';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var AuthCommands $authCommands */
|
||||
private $authCommands = null;
|
||||
|
||||
/**
|
||||
* Construct a new Authentication Manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->authCommands = new AuthCommands($maniaControl);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Name of the Authentication Level from Level Int
|
||||
*
|
||||
* @param mixed $authLevelInt
|
||||
* @return string
|
||||
*/
|
||||
public static function getAuthLevelName($authLevelInt) {
|
||||
$authLevelInt = self::getAuthLevelInt($authLevelInt);
|
||||
switch ($authLevelInt) {
|
||||
case self::AUTH_LEVEL_MASTERADMIN:
|
||||
return self::AUTH_NAME_MASTERADMIN;
|
||||
case self::AUTH_LEVEL_SUPERADMIN:
|
||||
return self::AUTH_NAME_SUPERADMIN;
|
||||
case self::AUTH_LEVEL_ADMIN:
|
||||
return self::AUTH_NAME_ADMIN;
|
||||
case self::AUTH_LEVEL_MODERATOR:
|
||||
return self::AUTH_NAME_MODERATOR;
|
||||
}
|
||||
return self::AUTH_NAME_PLAYER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Authentication Level Int from the given Param
|
||||
*
|
||||
* @param mixed $authLevelParam
|
||||
* @return int
|
||||
*/
|
||||
public static function getAuthLevelInt($authLevelParam) {
|
||||
if (is_object($authLevelParam) && property_exists($authLevelParam, 'authLevel')) {
|
||||
return (int)$authLevelParam->authLevel;
|
||||
}
|
||||
if (is_string($authLevelParam)) {
|
||||
return self::getAuthLevel($authLevelParam);
|
||||
}
|
||||
return (int)$authLevelParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Authentication Level Int from Level Name
|
||||
*
|
||||
* @param string $authLevelName
|
||||
* @return int
|
||||
*/
|
||||
public static function getAuthLevel($authLevelName) {
|
||||
$authLevelName = (string)$authLevelName;
|
||||
switch ($authLevelName) {
|
||||
case self::AUTH_NAME_MASTERADMIN:
|
||||
return self::AUTH_LEVEL_MASTERADMIN;
|
||||
case self::AUTH_NAME_SUPERADMIN:
|
||||
return self::AUTH_LEVEL_SUPERADMIN;
|
||||
case self::AUTH_NAME_ADMIN:
|
||||
return self::AUTH_LEVEL_ADMIN;
|
||||
case self::AUTH_NAME_MODERATOR:
|
||||
return self::AUTH_LEVEL_MODERATOR;
|
||||
}
|
||||
return self::AUTH_LEVEL_PLAYER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Abbreviation of the Authentication Level from Level Int
|
||||
*
|
||||
* @param mixed $authLevelInt
|
||||
* @return string
|
||||
*/
|
||||
public static function getAuthLevelAbbreviation($authLevelInt) {
|
||||
$authLevelInt = self::getAuthLevelInt($authLevelInt);
|
||||
switch ($authLevelInt) {
|
||||
case self::AUTH_LEVEL_MASTERADMIN:
|
||||
return 'MA';
|
||||
case self::AUTH_LEVEL_SUPERADMIN:
|
||||
return 'SA';
|
||||
case self::AUTH_LEVEL_ADMIN:
|
||||
return 'AD';
|
||||
case self::AUTH_LEVEL_MODERATOR:
|
||||
return 'MOD';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManiaControl OnInit Callback
|
||||
*/
|
||||
public function handleOnInit() {
|
||||
$this->updateMasterAdmins();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update MasterAdmins based on Config
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function updateMasterAdmins() {
|
||||
$masterAdminsElements = $this->maniaControl->getConfig()->xpath('masteradmins');
|
||||
if (!$masterAdminsElements) {
|
||||
Logger::logError('Missing MasterAdmins configuration!');
|
||||
return false;
|
||||
}
|
||||
$masterAdminsElement = $masterAdminsElements[0];
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
|
||||
// Remove all MasterAdmins
|
||||
$adminQuery = "UPDATE `" . PlayerManager::TABLE_PLAYERS . "`
|
||||
SET `authLevel` = ?
|
||||
WHERE `authLevel` = ?;";
|
||||
$adminStatement = $mysqli->prepare($adminQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$adminLevel = self::AUTH_LEVEL_SUPERADMIN;
|
||||
$masterAdminLevel = self::AUTH_LEVEL_MASTERADMIN;
|
||||
$adminStatement->bind_param('ii', $adminLevel, $masterAdminLevel);
|
||||
$adminStatement->execute();
|
||||
if ($adminStatement->error) {
|
||||
trigger_error($adminStatement->error);
|
||||
}
|
||||
$adminStatement->close();
|
||||
|
||||
// Set configured MasterAdmins
|
||||
$loginElements = $masterAdminsElement->xpath('login');
|
||||
$adminQuery = "INSERT INTO `" . PlayerManager::TABLE_PLAYERS . "` (
|
||||
`login`,
|
||||
`authLevel`
|
||||
) VALUES (
|
||||
?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`authLevel` = VALUES(`authLevel`);";
|
||||
$adminStatement = $mysqli->prepare($adminQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$success = true;
|
||||
foreach ($loginElements as $loginElement) {
|
||||
$login = (string)$loginElement;
|
||||
$adminStatement->bind_param('si', $login, $masterAdminLevel);
|
||||
$adminStatement->execute();
|
||||
if ($adminStatement->error) {
|
||||
trigger_error($adminStatement->error);
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
$adminStatement->close();
|
||||
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all connected Players with at least the given Auth Level
|
||||
*
|
||||
* @param int $authLevel
|
||||
* @return Player[]
|
||||
*/
|
||||
public function getConnectedAdmins($authLevel = self::AUTH_LEVEL_MODERATOR) {
|
||||
$players = $this->maniaControl->getPlayerManager()->getPlayers();
|
||||
$admins = array();
|
||||
foreach ($players as $player) {
|
||||
if (self::checkRight($player, $authLevel)) {
|
||||
array_push($admins, $player);
|
||||
}
|
||||
}
|
||||
return $admins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the Player has enough Rights
|
||||
*
|
||||
* @param Player $player
|
||||
* @param int|Setting $neededAuthLevel
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkRight(Player $player, $neededAuthLevel) {
|
||||
if ($neededAuthLevel instanceof Setting) {
|
||||
$neededAuthLevel = $neededAuthLevel->value;
|
||||
}
|
||||
return ($player->authLevel >= $neededAuthLevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a List of all Admins
|
||||
*
|
||||
* @param int $authLevel
|
||||
* @return Player[]
|
||||
*/
|
||||
public function getAdmins($authLevel = self::AUTH_LEVEL_MODERATOR) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "SELECT `login` FROM `" . PlayerManager::TABLE_PLAYERS . "`
|
||||
WHERE `authLevel` > " . $authLevel . "
|
||||
ORDER BY `authLevel` DESC;";
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
$admins = array();
|
||||
while ($row = $result->fetch_object()) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($row->login, false);
|
||||
if ($player) {
|
||||
array_push($admins, $player);
|
||||
}
|
||||
}
|
||||
$result->free();
|
||||
return $admins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant the Auth Level to the Player
|
||||
*
|
||||
* @param Player $player
|
||||
* @param int $authLevel
|
||||
* @return bool
|
||||
*/
|
||||
public function grantAuthLevel(Player &$player, $authLevel) {
|
||||
if (!$player || !is_numeric($authLevel)) {
|
||||
return false;
|
||||
}
|
||||
$authLevel = (int)$authLevel;
|
||||
if ($authLevel >= self::AUTH_LEVEL_MASTERADMIN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$authQuery = "INSERT INTO `" . PlayerManager::TABLE_PLAYERS . "` (
|
||||
`login`,
|
||||
`authLevel`
|
||||
) VALUES (
|
||||
?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`authLevel` = VALUES(`authLevel`);";
|
||||
$authStatement = $mysqli->prepare($authQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$authStatement->bind_param('si', $player->login, $authLevel);
|
||||
$authStatement->execute();
|
||||
if ($authStatement->error) {
|
||||
trigger_error($authStatement->error);
|
||||
$authStatement->close();
|
||||
return false;
|
||||
}
|
||||
$authStatement->close();
|
||||
|
||||
$player->authLevel = $authLevel;
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_AUTH_LEVEL_CHANGED, $player);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an Error Message to the Player
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
public function sendNotAllowed(Player $player) {
|
||||
if (!$player) {
|
||||
return false;
|
||||
}
|
||||
return $this->maniaControl->getChat()->sendError('You do not have the required Rights to perform this Action!', $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the permission by a right name
|
||||
*
|
||||
* @param Player $player
|
||||
* @param $rightName
|
||||
* @return bool
|
||||
*/
|
||||
public function checkPermission(Player $player, $rightName) {
|
||||
$right = $this->maniaControl->getSettingManager()->getSettingValue($this, $rightName);
|
||||
return $this->checkRight($player, $this->getAuthLevel($right));
|
||||
}
|
||||
|
||||
/**
|
||||
* Define a Minimum Right Level needed for an Action
|
||||
*
|
||||
* @param string $rightName
|
||||
* @param int $authLevelNeeded
|
||||
*/
|
||||
public function definePermissionLevel($rightName, $authLevelNeeded) {
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, $rightName, $this->getPermissionLevelNameArray($authLevelNeeded));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PermissionLevelNameArray
|
||||
*
|
||||
* @param $authLevelNeeded
|
||||
* @return array[]
|
||||
*/
|
||||
private function getPermissionLevelNameArray($authLevelNeeded) {
|
||||
switch ($authLevelNeeded) {
|
||||
case self::AUTH_LEVEL_MODERATOR:
|
||||
return array(self::AUTH_NAME_MODERATOR, self::AUTH_NAME_ADMIN, self::AUTH_NAME_SUPERADMIN, self::AUTH_NAME_MASTERADMIN);
|
||||
case self::AUTH_LEVEL_ADMIN:
|
||||
return array(self::AUTH_NAME_ADMIN, self::AUTH_NAME_SUPERADMIN, self::AUTH_NAME_MASTERADMIN, self::AUTH_NAME_MODERATOR);
|
||||
case self::AUTH_LEVEL_SUPERADMIN:
|
||||
return array(self::AUTH_NAME_SUPERADMIN, self::AUTH_NAME_MASTERADMIN, self::AUTH_NAME_MODERATOR, self::AUTH_NAME_ADMIN);
|
||||
case self::AUTH_LEVEL_MASTERADMIN:
|
||||
return array(self::AUTH_NAME_MASTERADMIN, self::AUTH_NAME_MODERATOR, self::AUTH_NAME_ADMIN, self::AUTH_NAME_SUPERADMIN);
|
||||
}
|
||||
return array("-");
|
||||
}
|
||||
}
|
47
core/AutoLoader.php
Normal file
47
core/AutoLoader.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl;
|
||||
|
||||
/**
|
||||
* ManiaControl AutoLoader
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class AutoLoader {
|
||||
|
||||
/**
|
||||
* Register the Auto Loader
|
||||
*/
|
||||
public static function register() {
|
||||
spl_autoload_register(array(get_class(), 'autoload'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to autoload the Class with the given Name
|
||||
*
|
||||
* @param string $className
|
||||
*/
|
||||
public static function autoload($className) {
|
||||
$classPath = str_replace('\\', DIRECTORY_SEPARATOR, $className);
|
||||
|
||||
// Core file
|
||||
$coreClassPath = preg_replace('/ManiaControl/', 'core', $classPath, 1);
|
||||
$coreFilePath = MANIACONTROL_PATH . $coreClassPath . '.php';
|
||||
if (file_exists($coreFilePath)) {
|
||||
include_once $coreFilePath;
|
||||
return;
|
||||
}
|
||||
|
||||
// Other file
|
||||
$paths = array('plugins', 'libs', 'libs' . DIRECTORY_SEPARATOR . 'curl-easy');
|
||||
foreach ($paths as $path) {
|
||||
$filePath = MANIACONTROL_PATH . $path . DIRECTORY_SEPARATOR . $classPath . '.php';
|
||||
if (file_exists($filePath)) {
|
||||
include_once $filePath;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
42
core/Bills/BillData.php
Normal file
42
core/Bills/BillData.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Bills;
|
||||
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
* ManiaControl BillData Structure
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class BillData {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $function = null;
|
||||
public $pay = false;
|
||||
public $player = null;
|
||||
public $receiverLogin = null;
|
||||
public $amount = 0;
|
||||
public $creationTime = -1;
|
||||
|
||||
/**
|
||||
* Construct new Bill Data Model
|
||||
*
|
||||
* @param callable $function
|
||||
* @param Player|string $player
|
||||
* @param int $amount
|
||||
* @param bool $pay
|
||||
* @param string $receiverLogin
|
||||
*/
|
||||
public function __construct(callable $function, $player, $amount, $pay = false, $receiverLogin = null) {
|
||||
$this->function = $function;
|
||||
$this->player = $player;
|
||||
$this->amount = $amount;
|
||||
$this->pay = $pay;
|
||||
$this->receiverLogin = $receiverLogin;
|
||||
$this->creationTime = time();
|
||||
}
|
||||
}
|
115
core/Bills/BillManager.php
Normal file
115
core/Bills/BillManager.php
Normal file
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Bills;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Structures\Bill;
|
||||
|
||||
/**
|
||||
* ManiaControl Bill Manager Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class BillManager implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const DONATED_TO_SERVER = 1;
|
||||
const DONATED_TO_RECEIVER = 2;
|
||||
const PAYED_FROM_SERVER = 3;
|
||||
const PLAYER_REFUSED_DONATION = 4;
|
||||
const ERROR_WHILE_TRANSACTION = 5;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var BillData[] $openBills */
|
||||
private $openBills = array();
|
||||
|
||||
/**
|
||||
* Construct a new Bill Manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_BILLUPDATED, $this, 'handleBillUpdated');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a bill to a player
|
||||
*
|
||||
* @param callable $function
|
||||
* @param Player $player
|
||||
* @param int $amount
|
||||
* @param string $message
|
||||
* @param string $receiver
|
||||
* @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);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send planets from the server to a player
|
||||
*
|
||||
* @param callable $function
|
||||
* @param string $receiverLogin
|
||||
* @param int $amount
|
||||
* @param string $message
|
||||
* @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);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle bill updated callback
|
||||
*
|
||||
* @param array $callback
|
||||
* @return bool
|
||||
*/
|
||||
public function handleBillUpdated(array $callback) {
|
||||
$billId = $callback[1][0];
|
||||
if (!isset($this->openBills[$billId])) {
|
||||
return;
|
||||
}
|
||||
$billData = $this->openBills[$billId];
|
||||
|
||||
switch ($callback[1][1]) {
|
||||
case Bill::STATE_PAYED:
|
||||
if ($billData->pay) {
|
||||
call_user_func($billData->function, $billData, self::PAYED_FROM_SERVER);
|
||||
} else {
|
||||
if ($billData->receiverLogin) {
|
||||
call_user_func($billData->function, $billData, self::DONATED_TO_RECEIVER);
|
||||
} else {
|
||||
call_user_func($billData->function, $billData, self::DONATED_TO_SERVER);
|
||||
}
|
||||
}
|
||||
unset($this->openBills[$billId]);
|
||||
break;
|
||||
case Bill::STATE_REFUSED:
|
||||
call_user_func($billData->function, $billData, self::PLAYER_REFUSED_DONATION);
|
||||
unset($this->openBills[$billId]);
|
||||
break;
|
||||
case Bill::STATE_ERROR:
|
||||
call_user_func($billData->function, $callback[1][2], self::ERROR_WHILE_TRANSACTION);
|
||||
unset($this->openBills[$billId]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
13
core/Callbacks/CallbackListener.php
Normal file
13
core/Callbacks/CallbackListener.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
/**
|
||||
* Interface for Callback Listener
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
interface CallbackListener {
|
||||
}
|
319
core/Callbacks/CallbackManager.php
Normal file
319
core/Callbacks/CallbackManager.php
Normal file
@ -0,0 +1,319 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
use ManiaControl\Callbacks\Models\BaseCallback;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Class for managing Server and ManiaControl Callbacks
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class CallbackManager {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
// ManiaPlanet callbacks
|
||||
const CB_MP_SERVERSTART = 'ManiaPlanet.ServerStart';
|
||||
const CB_MP_SERVERSTOP = 'ManiaPlanet.ServerStop';
|
||||
const CB_MP_BEGINMATCH = 'ManiaPlanet.BeginMatch';
|
||||
const CB_MP_ENDMATCH = 'ManiaPlanet.EndMatch';
|
||||
const CB_MP_BEGINMAP = 'ManiaPlanet.BeginMap';
|
||||
const CB_MP_ENDMAP = 'ManiaPlanet.EndMap';
|
||||
const CB_MP_MAPLISTMODIFIED = 'ManiaPlanet.MapListModified';
|
||||
const CB_MP_ECHO = 'ManiaPlanet.Echo';
|
||||
const CB_MP_BILLUPDATED = 'ManiaPlanet.BillUpdated';
|
||||
const CB_MP_PLAYERCHAT = 'ManiaPlanet.PlayerChat';
|
||||
const CB_MP_PLAYERCONNECT = 'ManiaPlanet.PlayerConnect';
|
||||
const CB_MP_PLAYERDISCONNECT = 'ManiaPlanet.PlayerDisconnect';
|
||||
const CB_MP_PLAYERMANIALINKPAGEANSWER = 'ManiaPlanet.PlayerManialinkPageAnswer';
|
||||
const CB_MP_PLAYERINFOCHANGED = 'ManiaPlanet.PlayerInfoChanged';
|
||||
const CB_MP_PLAYERALLIESCHANGED = 'ManiaPlanet.PlayerAlliesChanged';
|
||||
const CB_MP_VOTEUPDATED = 'ManiaPlanet.VoteUpdated';
|
||||
const CB_MP_STATUSCHANGED = 'ManiaPlanet.StatusChanged';
|
||||
const CB_MP_MODESCRIPTCALLBACK = 'ManiaPlanet.ModeScriptCallback';
|
||||
const CB_MP_MODESCRIPTCALLBACKARRAY = 'ManiaPlanet.ModeScriptCallbackArray';
|
||||
const CB_MP_TUNNELDATARECEIVED = 'ManiaPlanet.TunnelDataReceived';
|
||||
|
||||
// TrackMania callbacks
|
||||
const CB_TM_PLAYERCHECKPOINT = 'TrackMania.PlayerCheckpoint';
|
||||
const CB_TM_PLAYERFINISH = 'TrackMania.PlayerFinish';
|
||||
const CB_TM_PLAYERINCOHERENCE = 'TrackMania.PlayerIncoherence';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $libXmlRpcCallbacks = null;
|
||||
public $shootManiaCallbacks = null;
|
||||
public $trackManiaCallbacks = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var Listening[][] $callbackListenings */
|
||||
private $callbackListenings = array();
|
||||
/** @var Listening[][] $scriptCallbackListenings */
|
||||
private $scriptCallbackListenings = array();
|
||||
|
||||
/**
|
||||
* Construct a new callbacks manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
$this->libXmlRpcCallbacks = new LibXmlRpcCallbacks($maniaControl, $this);
|
||||
$this->shootManiaCallbacks = new ShootManiaCallbacks($maniaControl, $this);
|
||||
$this->trackManiaCallbacks = new TrackManiaCallbacks($maniaControl, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new Callback Listener
|
||||
*
|
||||
* @param string $callbackName
|
||||
* @param CallbackListener $listener
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function registerCallbackListener($callbackName, CallbackListener $listener, $method) {
|
||||
if (is_array($callbackName)) {
|
||||
$success = false;
|
||||
foreach ($callbackName as $callback) {
|
||||
if ($this->registerCallbackListener($callback, $listener, $method)) {
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
if (!Listening::checkValidCallback($listener, $method)) {
|
||||
$listenerClass = get_class($listener);
|
||||
trigger_error("Given Listener '{$listenerClass}' can't handle Callback '{$callbackName}': No callable Method '{$method}'!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!array_key_exists($callbackName, $this->callbackListenings)) {
|
||||
$this->callbackListenings[$callbackName] = array();
|
||||
}
|
||||
|
||||
$listening = new Listening($listener, $method);
|
||||
array_push($this->callbackListenings[$callbackName], $listening);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new Script Callback Listener
|
||||
*
|
||||
* @param string $callbackName
|
||||
* @param CallbackListener $listener
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function registerScriptCallbackListener($callbackName, CallbackListener $listener, $method) {
|
||||
if (is_array($callbackName)) {
|
||||
$success = false;
|
||||
foreach ($callbackName as $callback) {
|
||||
if ($this->registerScriptCallbackListener($callback, $listener, $method)) {
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
if (!Listening::checkValidCallback($listener, $method)) {
|
||||
$listenerClass = get_class($listener);
|
||||
trigger_error("Given Listener '{$listenerClass}' can't handle Script Callback '{$callbackName}': No callable Method '{$method}'!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!array_key_exists($callbackName, $this->scriptCallbackListenings)) {
|
||||
$this->scriptCallbackListenings[$callbackName] = array();
|
||||
}
|
||||
|
||||
$listening = new Listening($listener, $method);
|
||||
array_push($this->scriptCallbackListenings[$callbackName], $listening);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a Callback Listener
|
||||
*
|
||||
* @param CallbackListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
public function unregisterCallbackListener(CallbackListener $listener) {
|
||||
return $this->removeCallbackListener($this->callbackListenings, $listener);
|
||||
}
|
||||
|
||||
//TODO better name (used only in customvotesPlugin)
|
||||
|
||||
/**
|
||||
* Remove the Callback Listener from the given Listeners Array
|
||||
*
|
||||
* @param Listening[] $listeningsArray
|
||||
* @param CallbackListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
private function removeCallbackListener(array &$listeningsArray, CallbackListener $listener) {
|
||||
$removed = false;
|
||||
foreach ($listeningsArray as &$listenings) {
|
||||
foreach ($listenings as $key => &$listening) {
|
||||
if ($listening->listener === $listener) {
|
||||
unset($listenings[$key]);
|
||||
$removed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a single Callback Listening from an Callback Listener
|
||||
*
|
||||
* @param String $callbackName
|
||||
* @param CallbackListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
public function unregisterCallbackListening($callbackName, CallbackListener $listener) {
|
||||
$removed = false;
|
||||
foreach ($this->callbackListenings as &$listenings) {
|
||||
foreach ($listenings as $key => &$listening) {
|
||||
if ($key === $callbackName && $listening->listener === $listener) {
|
||||
unset($listenings[$key]);
|
||||
$removed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a Script Callback Listener
|
||||
*
|
||||
* @param CallbackListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
public function unregisterScriptCallbackListener(CallbackListener $listener) {
|
||||
return $this->removeCallbackListener($this->scriptCallbackListenings, $listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger internal Callbacks and manage Server Callbacks
|
||||
*/
|
||||
public function manageCallbacks() {
|
||||
// Manage Timings
|
||||
$this->maniaControl->getTimerManager()->manageTimings();
|
||||
|
||||
// Server Callbacks
|
||||
if (!$this->maniaControl->getClient()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle callbacks
|
||||
$callbacks = $this->maniaControl->getClient()->executeCallbacks();
|
||||
foreach ($callbacks as $callback) {
|
||||
$this->handleCallback($callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
private function handleCallback(array $callback) {
|
||||
$callbackName = $callback[0];
|
||||
switch ($callbackName) {
|
||||
case self::CB_MP_BEGINMATCH:
|
||||
$this->triggerCallback($callbackName, $callback);
|
||||
break;
|
||||
case self::CB_MP_BEGINMAP:
|
||||
$this->maniaControl->getMapManager()->handleBeginMap($callback);
|
||||
$this->triggerCallback($callbackName, $callback);
|
||||
break;
|
||||
case self::CB_MP_ENDMATCH:
|
||||
$this->triggerCallback($callbackName, $callback);
|
||||
break;
|
||||
case self::CB_MP_ENDMAP:
|
||||
$this->maniaControl->getMapManager()->handleEndMap($callback);
|
||||
$this->triggerCallback($callbackName, $callback);
|
||||
break;
|
||||
case self::CB_MP_MODESCRIPTCALLBACK:
|
||||
$this->handleScriptCallback($callback);
|
||||
$this->triggerCallback($callbackName, $callback);
|
||||
break;
|
||||
case self::CB_MP_MODESCRIPTCALLBACKARRAY:
|
||||
$this->handleScriptCallback($callback);
|
||||
$this->triggerCallback($callbackName, $callback);
|
||||
break;
|
||||
default:
|
||||
$this->triggerCallback($callbackName, $callback);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a specific Callback
|
||||
*
|
||||
* @param mixed $callback
|
||||
*/
|
||||
public function triggerCallback($callback) {
|
||||
if ($callback instanceof BaseCallback) {
|
||||
$callbackName = $callback->name;
|
||||
} else {
|
||||
$callbackName = $callback;
|
||||
}
|
||||
if (!array_key_exists($callbackName, $this->callbackListenings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$params = func_get_args();
|
||||
if (!($callback instanceof BaseCallback)) {
|
||||
$params = array_slice($params, 1, null, true);
|
||||
}
|
||||
|
||||
foreach ($this->callbackListenings[$callbackName] as $listening) {
|
||||
/** @var Listening $listening */
|
||||
$listening->triggerCallbackWithParams($params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the given Script Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
private function handleScriptCallback(array $callback) {
|
||||
$scriptCallbackData = $callback[1];
|
||||
$scriptCallbackName = $scriptCallbackData[0];
|
||||
$this->triggerScriptCallback($scriptCallbackName, $scriptCallbackData);
|
||||
$this->triggerCallback(Callbacks::SCRIPTCALLBACK, $scriptCallbackName, $scriptCallbackData[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a specific Script Callback
|
||||
*
|
||||
* @param string $callbackName
|
||||
*/
|
||||
public function triggerScriptCallback($callbackName) {
|
||||
if (!array_key_exists($callbackName, $this->scriptCallbackListenings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$params = func_get_args();
|
||||
$params = array_slice($params, 1, null, true);
|
||||
|
||||
foreach ($this->scriptCallbackListenings[$callbackName] as $listening) {
|
||||
/** @var Listening $listening */
|
||||
$listening->triggerCallbackWithParams($params);
|
||||
}
|
||||
}
|
||||
}
|
100
core/Callbacks/Callbacks.php
Normal file
100
core/Callbacks/Callbacks.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
// TODO: method class for all the libxmlrpc get Methods, to fetch the callback asnyc
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
/**
|
||||
* Callbacks Interface
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
interface Callbacks {
|
||||
/*
|
||||
* ManiaControl Callbacks
|
||||
*/
|
||||
const ONINIT = 'Callbacks.OnInit';
|
||||
const AFTERINIT = 'Callbacks.AfterInit';
|
||||
const ONSHUTDOWN = 'Callbacks.OnShutdown';
|
||||
|
||||
/** Script Callback: CallbackName, CallbackData */
|
||||
const SCRIPTCALLBACK = 'Callbacks.ScriptCallback';
|
||||
|
||||
/*
|
||||
* Common Callbacks
|
||||
*/
|
||||
/** BeginMatch Callback: MatchNumber */
|
||||
const BEGINMATCH = 'Callbacks.BeginMatch';
|
||||
/** LoadingMap Callback: MapNumber */
|
||||
const LOADINGMAP = 'Callbacks.LoadingMap';
|
||||
/** BeginMap Callback: Map */
|
||||
const BEGINMAP = 'Callbacks.BeginMap';
|
||||
/** BeginSubMatch Callback: SubmatchNumber */
|
||||
const BEGINSUBMATCH = 'Callbacks.BeginSubmatch';
|
||||
/** BeginRound Callback: RoundNumber */
|
||||
const BEGINROUND = 'Callbacks.BeginRound';
|
||||
/** BeginTurn Callback: TurnNumber */
|
||||
const BEGINTURN = 'Callbacks.BeginTurn';
|
||||
/** BeginPlaying Callback */
|
||||
const BEGINPLAYING = 'Callbacks.BeginPlaying';
|
||||
/** EndPlaying Callback */
|
||||
const ENDPLAYING = 'Callbacks.EndPlaying';
|
||||
/** EndTurn Callback: TurnNumber */
|
||||
const ENDTURN = 'Callbacks.EndTurn';
|
||||
/** EndRound Callback: RoundNumber */
|
||||
const ENDROUND = 'Callbacks.EndRound';
|
||||
/** EndSubmatch Callback: SubmatchNumber */
|
||||
const ENDSUBMATCH = 'Callbacks.EndSubmatch';
|
||||
/** EndMap Callback: Map */
|
||||
const ENDMAP = 'Callbacks.EndMap';
|
||||
/** BeginPodium Callback */
|
||||
const BEGINPODIUM = 'Callbacks.BeginPodium';
|
||||
/** EndPodium Callback */
|
||||
const ENDPODIUM = 'Callbacks.EndPodium';
|
||||
/** UnloadingMap Callback */
|
||||
const UNLOADINGMAP = 'Callbacks.UnloadingMap';
|
||||
/** EndMatch Callback: MatchNumber */
|
||||
const ENDMATCH = 'Callbacks.EndMatch';
|
||||
|
||||
/** BeginWarmup Callback */
|
||||
const BEGINWARMUP = 'Callbacks.BeginWarmUp';
|
||||
/** EndWarmup Callback */
|
||||
const ENDWARMUP = 'Callbacks.EndWarmUp';
|
||||
|
||||
/** PlayerRanking Callback, returned after LibXmlRpc_PlayerRanking
|
||||
* try to avoid to use this, just use the Get function of the RankingsManager instead
|
||||
* param1 Player $player
|
||||
* param2 int $rank
|
||||
* param3 int $currentPoints
|
||||
* param4 int AFKStatus */
|
||||
const PLAYERRANKING = 'Callbacks.PlayerRanking';
|
||||
|
||||
/*
|
||||
* ShootMania 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';
|
||||
/** Returns if the GameMode has Warmup activated, returned after param1 Scores */ //returned after TODO
|
||||
const WARMUPSTATUS = 'Callbacks.WarmupStatus';
|
||||
|
||||
/*
|
||||
* TrackMania Callbacks
|
||||
*/
|
||||
/** OnStartLine Callback */
|
||||
const ONSTARTLINE = 'Callbacks.OnStartLine';
|
||||
/** OnWayPoint Callback */
|
||||
const ONWAYPOINT = 'Callbacks.OnWayPoint';
|
||||
/** OnGiveUp Callback */
|
||||
const ONGIVEUP = 'Callbacks.OnGiveUp';
|
||||
/** OnRespawn Callback */
|
||||
const ONRESPAWN = 'Callbacks.OnRespawn';
|
||||
/** OnStunt Callback */
|
||||
const ONSTUNT = 'Callbacks.OnStunt';
|
||||
}
|
128
core/Callbacks/LibXmlRpcCallbacks.php
Normal file
128
core/Callbacks/LibXmlRpcCallbacks.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Class converting LibXmlRpc Callbacks
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class LibXmlRpcCallbacks implements CallbackListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new LibXmlRpc Callbacks Instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
* @param CallbackManager $callbackManager
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl, CallbackManager $callbackManager) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
$callbackManager->registerCallbackListener(Callbacks::SCRIPTCALLBACK, $this, 'handleScriptCallback');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Script Callback
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function handleScriptCallback($name, $data) {
|
||||
switch ($name) {
|
||||
case 'LibXmlRpc_BeginMatch':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::BEGINMATCH, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_LoadingMap':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::LOADINGMAP, $data[0]);
|
||||
break;
|
||||
case 'BeginMap':
|
||||
case 'LibXmlRpc_BeginMap':
|
||||
if (!isset($data[2])) {
|
||||
$data[2] = 'False';
|
||||
}
|
||||
$this->maniaControl->getMapManager()->handleScriptBeginMap($data[1], $data[2]);
|
||||
break;
|
||||
case 'LibXmlRpc_BeginSubmatch':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::BEGINSUBMATCH, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_BeginTurn':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::BEGINTURN, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_BeginPlaying':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::BEGINPLAYING);
|
||||
break;
|
||||
case 'LibXmlRpc_EndPlaying':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDPLAYING);
|
||||
break;
|
||||
case 'LibXmlRpc_EndTurn':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDTURN, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_EndRound':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDROUND, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_EndSubmatch':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDSUBMATCH, $data[0]);
|
||||
break;
|
||||
case 'EndMap':
|
||||
case 'LibXmlRpc_EndMap':
|
||||
$this->maniaControl->getMapManager()->handleScriptEndMap();
|
||||
break;
|
||||
case 'LibXmlRpc_BeginPodium':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::BEGINPODIUM);
|
||||
break;
|
||||
case 'LibXmlRpc_EndPodium':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDPODIUM);
|
||||
break;
|
||||
case 'LibXmlRpc_UnloadingMap':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::UNLOADINGMAP, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_EndMatch':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDMATCH, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_BeginWarmUp':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::BEGINWARMUP);
|
||||
break;
|
||||
case 'LibXmlRpc_EndWarmUp':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDWARMUP);
|
||||
break;
|
||||
case 'LibXmlRpc_PlayerRanking':
|
||||
//TODO really useful? what does it have what RankingsManager not have?
|
||||
$this->triggerPlayerRanking($data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_OnStartLine':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONSTARTLINE, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_OnWayPoint':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONWAYPOINT, $data);
|
||||
break;
|
||||
case 'LibXmlRpc_OnGiveUp':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONGIVEUP, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_OnRespawn':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONRESPAWN, $data[0]);
|
||||
break;
|
||||
case 'LibXmlRpc_OnStunt':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ONSTUNT, $data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the Ranking of a Player
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
private function triggerPlayerRanking(array $data) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($data[1]);
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::PLAYERRANKING, $player, $data[0], $data[6], $data[5]);
|
||||
}
|
||||
}
|
76
core/Callbacks/Listening.php
Normal file
76
core/Callbacks/Listening.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
/**
|
||||
* Model Class for a Basic Listening
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Listening {
|
||||
/*
|
||||
* Public Properties
|
||||
*/
|
||||
public $listener = null;
|
||||
public $method = null;
|
||||
|
||||
/**
|
||||
* Construct a new Timer Listening
|
||||
*
|
||||
* @param object $listener
|
||||
* @param mixed $method
|
||||
*/
|
||||
public function __construct($listener, $method) {
|
||||
$this->listener = $listener;
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Listener and Method build a valid Callback
|
||||
*
|
||||
* @param object $listener
|
||||
* @param mixed $method
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkValidCallback($listener, $method) {
|
||||
if (is_callable($method)) {
|
||||
return true;
|
||||
}
|
||||
$listenerCallback = array($listener, $method);
|
||||
if (is_callable($listenerCallback)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the Listener's Method
|
||||
*/
|
||||
public function triggerCallback() {
|
||||
$params = func_get_args();
|
||||
$this->triggerCallbackWithParams($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger the Listener's Method with the given Array of Params
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function triggerCallbackWithParams(array $params) {
|
||||
call_user_func_array($this->getUserFunction(), $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Callable User Function
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function getUserFunction() {
|
||||
if (is_callable($this->method)) {
|
||||
return $this->method;
|
||||
}
|
||||
return array($this->listener, $this->method);
|
||||
}
|
||||
}
|
37
core/Callbacks/Models/BaseCallback.php
Normal file
37
core/Callbacks/Models/BaseCallback.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks\Models;
|
||||
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
* Base Model Class for Callbacks
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class BaseCallback {
|
||||
/*
|
||||
* Public Properties
|
||||
*/
|
||||
public $name = null;
|
||||
public $rawCallback = null;
|
||||
public $isLegacyCallback = null;
|
||||
|
||||
public $pid = null;
|
||||
public $login = null;
|
||||
/** @var Player $player */
|
||||
public $player = null;
|
||||
|
||||
/**
|
||||
* Set the corresponding Player
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function setPlayer(Player $player) {
|
||||
$this->pid = $player->pid;
|
||||
$this->login = $player->login;
|
||||
$this->player = $player;
|
||||
}
|
||||
}
|
31
core/Callbacks/Models/RecordCallback.php
Normal file
31
core/Callbacks/Models/RecordCallback.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks\Models;
|
||||
|
||||
/**
|
||||
* Base Model Class for Callbacks
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class RecordCallback extends BaseCallback {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CHECKPOINT = 'RecordCallback.Checkpoint';
|
||||
const FINISH = 'RecordCallback.Finish';
|
||||
const LAPFINISH = 'RecordCallback.LapFinish';
|
||||
|
||||
/*
|
||||
* Public Properties
|
||||
*/
|
||||
public $isEndRace = null;
|
||||
public $isEndLap = null;
|
||||
public $time = null;
|
||||
public $lapTime = null;
|
||||
public $checkpoint = null;
|
||||
public $lapCheckpoint = null;
|
||||
public $lap = null;
|
||||
public $blockId = null;
|
||||
}
|
127
core/Callbacks/ShootManiaCallbacks.php
Normal file
127
core/Callbacks/ShootManiaCallbacks.php
Normal file
@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
use ManiaControl\Callbacks\Models\RecordCallback;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Class handling and parsing ShootMania Callbacks
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ShootManiaCallbacks implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CB_TIMEATTACK_ONSTART = 'TimeAttack_OnStart';
|
||||
const CB_TIMEATTACK_ONRESTART = 'TimeAttack_OnRestart';
|
||||
const CB_TIMEATTACK_ONCHECKPOINT = 'TimeAttack_OnCheckpoint';
|
||||
const CB_TIMEATTACK_ONFINISH = 'TimeAttack_OnFinish';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new ShootMania Callbacks Instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
* @param CallbackManager $callbackManager
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl, CallbackManager $callbackManager) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Register for script callbacks
|
||||
$callbackManager->registerCallbackListener(Callbacks::SCRIPTCALLBACK, $this, 'handleScriptCallbacks');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Script Callbacks
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function handleScriptCallbacks($name, $data) {
|
||||
switch ($name) {
|
||||
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;
|
||||
case 'WarmUp_Status':
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::WARMUPSTATUS, $data[0]);
|
||||
break;
|
||||
case self::CB_TIMEATTACK_ONCHECKPOINT:
|
||||
$this->handleTimeAttackOnCheckpoint($name, $data);
|
||||
break;
|
||||
case self::CB_TIMEATTACK_ONFINISH:
|
||||
$this->handleTimeAttackOnFinish($name, $data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers the AFK Status of an Player
|
||||
*
|
||||
* @param string $login
|
||||
*/
|
||||
private function triggerAfkStatus($login) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::AFKSTATUS, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle TimeAttack OnCheckpoint Callback
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
*/
|
||||
public function handleTimeAttackOnCheckpoint($name, array $data) {
|
||||
$login = $data[0];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger checkpoint callback
|
||||
$checkpointCallback = new RecordCallback();
|
||||
$checkpointCallback->rawCallback = array($name, $data);
|
||||
$checkpointCallback->name = $checkpointCallback::CHECKPOINT;
|
||||
$checkpointCallback->setPlayer($player);
|
||||
$checkpointCallback->time = (int)$data[1];
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback($checkpointCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle TimeAttack OnFinish Callback
|
||||
*
|
||||
* @param string $name
|
||||
* @param array $data
|
||||
*/
|
||||
public function handleTimeAttackOnFinish($name, array $data) {
|
||||
$login = $data[0];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger finish callback
|
||||
$finishCallback = new RecordCallback();
|
||||
$finishCallback->rawCallback = array($name, $data);
|
||||
$finishCallback->name = $finishCallback::FINISH;
|
||||
$finishCallback->setPlayer($player);
|
||||
$finishCallback->time = (int)$data[1];
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback($finishCallback);
|
||||
}
|
||||
}
|
13
core/Callbacks/TimerListener.php
Normal file
13
core/Callbacks/TimerListener.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
/**
|
||||
* Interface for TimerListener
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
interface TimerListener {
|
||||
}
|
70
core/Callbacks/TimerListening.php
Normal file
70
core/Callbacks/TimerListening.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
/**
|
||||
* Model Class for a Timer Listening
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class TimerListening extends Listening {
|
||||
/*
|
||||
* Public Properties
|
||||
*/
|
||||
public $deltaTime = null;
|
||||
public $oneTime = null;
|
||||
public $lastTrigger = null;
|
||||
public $instantCall = null;
|
||||
|
||||
/**
|
||||
* Construct a new Timer Listening
|
||||
*
|
||||
* @param TimerListener $listener
|
||||
* @param mixed $method
|
||||
* @param float $milliSeconds
|
||||
* @param bool $oneTime
|
||||
* @param bool $instantCall
|
||||
*/
|
||||
public function __construct(TimerListener $listener, $method, $milliSeconds, $oneTime = false, $instantCall = true) {
|
||||
parent::__construct($listener, $method);
|
||||
|
||||
$this->deltaTime = $milliSeconds / 1000.;
|
||||
$this->oneTime = (bool)$oneTime;
|
||||
if ($this->oneTime) {
|
||||
$this->lastTrigger = time(true);
|
||||
}
|
||||
$this->instantCall = (bool)$instantCall;
|
||||
if (!$this->instantCall) {
|
||||
$this->lastTrigger = microtime(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase last Trigger Time
|
||||
*/
|
||||
public function tick() {
|
||||
if ($this->lastTrigger === null) {
|
||||
$this->lastTrigger = microtime(true);
|
||||
} else {
|
||||
$this->lastTrigger += $this->deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the desired Time is reached
|
||||
*
|
||||
* @param float $time
|
||||
* @return bool
|
||||
*/
|
||||
public function isTimeReached($time = null) {
|
||||
if ($this->lastTrigger === null) {
|
||||
return true;
|
||||
}
|
||||
if (!$time) {
|
||||
$time = microtime(true);
|
||||
}
|
||||
return ($this->lastTrigger + $this->deltaTime <= $time);
|
||||
}
|
||||
}
|
133
core/Callbacks/TimerManager.php
Normal file
133
core/Callbacks/TimerManager.php
Normal file
@ -0,0 +1,133 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Class for managing Timed Callbacks
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class TimerManager {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var TimerListening[] $timerListenings */
|
||||
private $timerListenings = array();
|
||||
|
||||
/**
|
||||
* Construct a new Timer Manager
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a One Time Listening
|
||||
*
|
||||
* @param TimerListener $listener
|
||||
* @param string $method
|
||||
* @param float $milliSeconds
|
||||
*/
|
||||
public function registerOneTimeListening(TimerListener $listener, $method, $milliSeconds) {
|
||||
$this->registerTimerListening($listener, $method, $milliSeconds, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a Timer Listening, note < 10ms it can get inaccurate
|
||||
*
|
||||
* @param TimerListener $listener
|
||||
* @param string $method
|
||||
* @param float $milliSeconds
|
||||
* @param bool $oneTime
|
||||
* @return bool
|
||||
*/
|
||||
public function registerTimerListening(TimerListener $listener, $method, $milliSeconds, $oneTime = false) {
|
||||
if ((!is_string($method) || !method_exists($listener, $method)) && !is_callable($method)) {
|
||||
trigger_error("Given Listener (" . get_class($listener) . ") can't handle Timer Callback (No Method '{$method}')!");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build Timer Listening
|
||||
$listening = new TimerListening($listener, $method, $milliSeconds, $oneTime);
|
||||
$this->addTimerListening($listening);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Listening to the current List of managed Timers
|
||||
*
|
||||
* @param TimerListening $timerListening
|
||||
*/
|
||||
public function addTimerListening(TimerListening $timerListening) {
|
||||
array_push($this->timerListenings, $timerListening);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a Timer Listening
|
||||
*
|
||||
* @param TimerListener $listener
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function unregisterTimerListening(TimerListener $listener, $method) {
|
||||
$removed = false;
|
||||
foreach ($this->timerListenings as $key => &$listening) {
|
||||
if ($listening->listener === $listener && $listening->method === $method) {
|
||||
unset($this->timerListenings[$key]);
|
||||
$removed = true;
|
||||
}
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a Timer Listener
|
||||
*
|
||||
* @param TimerListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
public function unregisterTimerListenings(TimerListener $listener) {
|
||||
$removed = false;
|
||||
foreach ($this->timerListenings as $key => &$listening) {
|
||||
if ($listening->listener === $listener) {
|
||||
unset($this->timerListenings[$key]);
|
||||
$removed = true;
|
||||
}
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the Timings on every ms
|
||||
*/
|
||||
public function manageTimings() {
|
||||
$time = microtime(true);
|
||||
|
||||
foreach ($this->timerListenings as $key => $listening) {
|
||||
/** @var TimerListening $listening */
|
||||
|
||||
if (!$listening->isTimeReached($time)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($listening->oneTime) {
|
||||
// Unregister one time Listening
|
||||
unset($this->timerListenings[$key]);
|
||||
}
|
||||
|
||||
$listening->tick();
|
||||
|
||||
// Call the User Function
|
||||
$listening->triggerCallback($time);
|
||||
}
|
||||
}
|
||||
}
|
139
core/Callbacks/TrackManiaCallbacks.php
Normal file
139
core/Callbacks/TrackManiaCallbacks.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Callbacks;
|
||||
|
||||
use ManiaControl\Callbacks\Models\RecordCallback;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* Class handling and parsing TrackMania Callbacks
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class TrackManiaCallbacks implements CallbackListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new TrackMania Callbacks Instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
* @param CallbackManager $callbackManager
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl, CallbackManager $callbackManager) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Register for callbacks
|
||||
$callbackManager->registerCallbackListener(Callbacks::ONWAYPOINT, $this, 'handleOnWayPointCallback');
|
||||
$callbackManager->registerCallbackListener(CallbackManager::CB_TM_PLAYERCHECKPOINT, $this, 'handlePlayerCheckpointCallback');
|
||||
$callbackManager->registerCallbackListener(CallbackManager::CB_TM_PLAYERFINISH, $this, 'handlePlayerFinishCallback');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle OnWayPoint Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleOnWayPointCallback(array $callback) {
|
||||
$login = $callback[0];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build callback
|
||||
$wayPointCallback = new RecordCallback();
|
||||
$wayPointCallback->rawCallback = $callback;
|
||||
$wayPointCallback->setPlayer($player);
|
||||
$wayPointCallback->blockId = $callback[1];
|
||||
$wayPointCallback->time = (int)$callback[2];
|
||||
$wayPointCallback->checkpoint = (int)$callback[3];
|
||||
$wayPointCallback->isEndRace = Formatter::parseBoolean($callback[4]);
|
||||
$wayPointCallback->lapTime = (int)$callback[5];
|
||||
$wayPointCallback->lapCheckpoint = (int)$callback[6];
|
||||
$wayPointCallback->lap = 0;
|
||||
$wayPointCallback->isEndLap = Formatter::parseBoolean($callback[7]);
|
||||
|
||||
if ($wayPointCallback->checkpoint > 0) {
|
||||
$currentMap = $this->maniaControl->getMapManager()->getCurrentMap();
|
||||
$wayPointCallback->lap += $wayPointCallback->checkpoint / $currentMap->nbCheckpoints;
|
||||
}
|
||||
|
||||
if ($wayPointCallback->isEndRace) {
|
||||
$wayPointCallback->name = $wayPointCallback::FINISH;
|
||||
} else if ($wayPointCallback->isEndLap) {
|
||||
$wayPointCallback->name = $wayPointCallback::LAPFINISH;
|
||||
} else {
|
||||
$wayPointCallback->name = $wayPointCallback::CHECKPOINT;
|
||||
}
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback($wayPointCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Hard-Coded Player Checkpoint Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handlePlayerCheckpointCallback(array $callback) {
|
||||
$data = $callback[1];
|
||||
$login = $data[1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build checkpoint callback
|
||||
$checkpointCallback = new RecordCallback();
|
||||
$checkpointCallback->isLegacyCallback = true;
|
||||
$checkpointCallback->rawCallback = $callback;
|
||||
$checkpointCallback->setPlayer($player);
|
||||
$checkpointCallback->time = (int)$data[2];
|
||||
$checkpointCallback->lap = (int)$data[3];
|
||||
$checkpointCallback->checkpoint = (int)$data[4];
|
||||
$checkpointCallback->lapCheckpoint = $checkpointCallback->checkpoint;
|
||||
|
||||
if ($checkpointCallback->lap > 0) {
|
||||
$currentMap = $this->maniaControl->getMapManager()->getCurrentMap();
|
||||
$checkpointCallback->lapCheckpoint -= $checkpointCallback->lap * $currentMap->nbCheckpoints;
|
||||
}
|
||||
|
||||
if ($checkpointCallback->lapCheckpoint === 0) {
|
||||
$checkpointCallback->name = $checkpointCallback::LAPFINISH;
|
||||
} else {
|
||||
$checkpointCallback->name = $checkpointCallback::CHECKPOINT;
|
||||
}
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback($checkpointCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Hard-Coded Player Finish Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handlePlayerFinishCallback(array $callback) {
|
||||
$data = $callback[1];
|
||||
$login = $data[1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build finish callback
|
||||
$finishCallback = new RecordCallback();
|
||||
$finishCallback->name = $finishCallback::FINISH;
|
||||
$finishCallback->isLegacyCallback = true;
|
||||
$finishCallback->rawCallback = $callback;
|
||||
$finishCallback->setPlayer($player);
|
||||
$finishCallback->time = (int)$data[2];
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback($finishCallback);
|
||||
}
|
||||
}
|
229
core/Chat.php
Normal file
229
core/Chat.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl;
|
||||
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
|
||||
/**
|
||||
* Chat Utility Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Chat {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const SETTING_PREFIX = 'Messages Prefix';
|
||||
const SETTING_FORMAT_INFORMATION = 'Information Format';
|
||||
const SETTING_FORMAT_SUCCESS = 'Success Format';
|
||||
const SETTING_FORMAT_ERROR = 'Error Format';
|
||||
const SETTING_FORMAT_USAGEINFO = 'UsageInfo Format';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct chat utility
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_PREFIX, '» ');
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_FORMAT_INFORMATION, '$fff');
|
||||
$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');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an information message to the given login
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $login
|
||||
* @param string|bool $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendInformation($message, $login = null, $prefix = true) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_INFORMATION);
|
||||
return $this->sendChat($format . $message, $login, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a chat message to the given login
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $login
|
||||
* @param string|bool $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendChat($message, $login = null, $prefix = true) {
|
||||
if (!$this->maniaControl->getClient()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$prefix = $this->buildPrefix($prefix, $login);
|
||||
$chatMessage = '$<$z$ff0' . $prefix . $message . '$>';
|
||||
|
||||
if ($login) {
|
||||
if (!is_array($login)) {
|
||||
$login = Player::parseLogin($login);
|
||||
}
|
||||
try {
|
||||
return $this->maniaControl->getClient()->chatSendServerMessage($chatMessage, $login);
|
||||
} catch (UnknownPlayerException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->maniaControl->getClient()->chatSendServerMessage($chatMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the chat message prefix
|
||||
*
|
||||
* @param string|bool $prefixParam
|
||||
* @param string|array $login
|
||||
* @return string
|
||||
*/
|
||||
private function buildPrefix($prefixParam, $login = null) {
|
||||
if (is_string($prefixParam)) {
|
||||
return $prefixParam;
|
||||
}
|
||||
if ($prefixParam === true) {
|
||||
$prefix = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_PREFIX);
|
||||
if ($login) {
|
||||
// Private - Doubled default prefix
|
||||
$prefix .= $prefix;
|
||||
// TODO: validate whether to use specific private & public prefixes instead of just doubling a default one
|
||||
}
|
||||
return $prefix;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an Error Message to all Connected Admins
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $minLevel
|
||||
* @param bool $prefix
|
||||
*/
|
||||
public function sendErrorToAdmins($message, $minLevel = AuthenticationManager::AUTH_LEVEL_MODERATOR, $prefix = true) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_ERROR);
|
||||
$this->sendMessageToAdmins($format . $message, $minLevel, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Message to all connected Admins
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $minLevel
|
||||
* @param bool|string $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendMessageToAdmins($message, $minLevel = AuthenticationManager::AUTH_LEVEL_MODERATOR, $prefix = true) {
|
||||
$admins = $this->maniaControl->getAuthenticationManager()->getConnectedAdmins($minLevel);
|
||||
return $this->sendChat($message, $admins, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a success message to the given login
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $login
|
||||
* @param bool|string $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendSuccess($message, $login = null, $prefix = true) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_SUCCESS);
|
||||
return $this->sendChat($format . $message, $login, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a Information Message to all connected Admins
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $minLevel
|
||||
* @param bool|string $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendInformationToAdmins($message, $minLevel = AuthenticationManager::AUTH_LEVEL_MODERATOR, $prefix = true) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_INFORMATION);
|
||||
return $this->sendMessageToAdmins($format . $message, $minLevel, $prefix);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sends a Success Message to all connected Admins
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $minLevel
|
||||
* @param bool|string $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendSuccessToAdmins($message, $minLevel = AuthenticationManager::AUTH_LEVEL_MODERATOR, $prefix = true) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_SUCCESS);
|
||||
return $this->sendMessageToAdmins($format . $message, $minLevel, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the Exception Information to the Chat
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param string $login
|
||||
* @return bool
|
||||
*/
|
||||
public function sendException(\Exception $exception, $login = null) {
|
||||
$message = "Exception occurred: '{$exception->getMessage()}' ({$exception->getCode()})";
|
||||
return $this->sendError($message, $login);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an Error Message to the Chat
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $login
|
||||
* @param string|bool $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendError($message, $login = null, $prefix = true) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_ERROR);
|
||||
return $this->sendChat($format . $message, $login, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a Exception Message to all Connected Admins
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param int $minLevel
|
||||
* @param bool|string $prefix
|
||||
*/
|
||||
public function sendExceptionToAdmins(\Exception $exception, $minLevel = AuthenticationManager::AUTH_LEVEL_MODERATOR, $prefix = true) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_ERROR);
|
||||
$message = $format . "Exception: '{$exception->getMessage()}' ({$exception->getCode()})";
|
||||
$this->sendMessageToAdmins($message, $minLevel, $prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an usage info message to the given login
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $login
|
||||
* @param string|bool $prefix
|
||||
* @return bool
|
||||
*/
|
||||
public function sendUsageInfo($message, $login = null, $prefix = false) {
|
||||
$format = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_FORMAT_USAGEINFO);
|
||||
return $this->sendChat($format . $message, $login, $prefix);
|
||||
}
|
||||
}
|
13
core/Commands/CommandListener.php
Normal file
13
core/Commands/CommandListener.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Commands;
|
||||
|
||||
/**
|
||||
* Interface for Command Listeners
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
interface CommandListener {
|
||||
}
|
220
core/Commands/CommandManager.php
Normal file
220
core/Commands/CommandManager.php
Normal file
@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Commands;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Listening;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Class for handling Chat Commands
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class CommandManager implements CallbackListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var HelpManager $helpManager */
|
||||
private $helpManager = array();
|
||||
/** @var Listening[][] $commandListenings */
|
||||
private $commandListenings = array();
|
||||
/** @var Listening[][] $adminCommandListenings */
|
||||
private $adminCommandListenings = array();
|
||||
|
||||
/**
|
||||
* Construct a new Commands Manager
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Children
|
||||
$this->helpManager = new HelpManager($this->maniaControl);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERCHAT, $this, 'handleChatCallback');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the help manager instance
|
||||
*
|
||||
* @return HelpManager
|
||||
*/
|
||||
public function getHelpManager() {
|
||||
return $this->helpManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a Command Listener
|
||||
*
|
||||
* @param string $commandName
|
||||
* @param CommandListener $listener
|
||||
* @param string $method
|
||||
* @param bool $adminCommand
|
||||
* @param string $description
|
||||
* @return bool
|
||||
*/
|
||||
public function registerCommandListener($commandName, CommandListener $listener, $method, $adminCommand = false, $description = null) {
|
||||
if (is_array($commandName)) {
|
||||
$success = false;
|
||||
foreach ($commandName as $command) {
|
||||
if ($this->registerCommandListener($command, $listener, $method, $adminCommand, $description)) {
|
||||
$success = true;
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
if (!Listening::checkValidCallback($listener, $method)) {
|
||||
$listenerClass = get_class($listener);
|
||||
trigger_error("Given Listener '{$listenerClass}' can't handle Command '{$commandName}': No callable Method '{$method}'!");
|
||||
return false;
|
||||
}
|
||||
|
||||
$command = strtolower($commandName);
|
||||
$listening = new Listening($listener, $method);
|
||||
|
||||
if ($adminCommand) {
|
||||
$this->addListening($this->adminCommandListenings, $listening, $command);
|
||||
} else {
|
||||
$this->addListening($this->commandListenings, $listening, $command);
|
||||
}
|
||||
|
||||
// TODO: description(?)
|
||||
if ($description) {
|
||||
$this->helpManager->registerCommand($command, $adminCommand, $description, get_class($listener) . '\\' . $method);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Listening to the given Listenings Array
|
||||
*
|
||||
* @param array $listeningsArray
|
||||
* @param Listening $listening
|
||||
* @param string $command
|
||||
*/
|
||||
private function addListening(array &$listeningsArray, Listening $listening, $command) {
|
||||
if (!array_key_exists($command, $listeningsArray) || !is_array($listeningsArray[$command])) {
|
||||
// Init listenings array
|
||||
$listeningsArray[$command] = array();
|
||||
}
|
||||
|
||||
// Register command listening
|
||||
array_push($listeningsArray[$command], $listening);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister a Command Listener
|
||||
*
|
||||
* @param CommandListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
public function unregisterCommandListener(CommandListener $listener) {
|
||||
$removed = false;
|
||||
if ($this->removeCommandListener($this->commandListenings, $listener)) {
|
||||
$removed = true;
|
||||
}
|
||||
if ($this->removeCommandListener($this->adminCommandListenings, $listener)) {
|
||||
$removed = true;
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the Command Listener from the given Listenings Array
|
||||
*
|
||||
* @param array $listeningsArray
|
||||
* @param CommandListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
private function removeCommandListener(array &$listeningsArray, CommandListener $listener) {
|
||||
$removed = false;
|
||||
foreach ($listeningsArray as &$listenings) {
|
||||
foreach ($listenings as $key => &$listening) {
|
||||
if ($listening->listener === $listener) {
|
||||
unset($listenings[$key]);
|
||||
$removed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Chat Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleChatCallback(array $callback) {
|
||||
// Check for command
|
||||
if (!$this->isCommandMessage($callback)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for valid player
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse command
|
||||
$message = $callback[1][2];
|
||||
$commandArray = explode(' ', $message);
|
||||
$command = ltrim(strtolower($commandArray[0]), '/');
|
||||
if (!$command) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (substr($message, 0, 2) === '//' || $command === 'admin') {
|
||||
// Admin command
|
||||
$commandListenings = $this->adminCommandListenings;
|
||||
|
||||
if ($command === 'admin') {
|
||||
// Strip 'admin' keyword
|
||||
if (isset($commandArray[1])) {
|
||||
$command = $commandArray[1];
|
||||
unset($commandArray[1]);
|
||||
}
|
||||
}
|
||||
unset($commandArray[0]);
|
||||
|
||||
// Compose uniformed message
|
||||
$message = '//' . $command . ' ' . implode(' ', $commandArray);
|
||||
$callback[1][2] = $message;
|
||||
} else {
|
||||
// User command
|
||||
$commandListenings = $this->commandListenings;
|
||||
}
|
||||
|
||||
if (!array_key_exists($command, $commandListenings) || !is_array($commandListenings[$command])) {
|
||||
// No command listener registered
|
||||
return;
|
||||
}
|
||||
|
||||
// Inform command listeners
|
||||
foreach ($commandListenings[$command] as $listening) {
|
||||
/** @var Listening $listening */
|
||||
$listening->triggerCallback($callback, $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Chat Callback is a Command Message
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @return bool
|
||||
*/
|
||||
private function isCommandMessage(array $chatCallback) {
|
||||
return (bool)$chatCallback[1][3];
|
||||
}
|
||||
}
|
255
core/Commands/HelpManager.php
Normal file
255
core/Commands/HelpManager.php
Normal file
@ -0,0 +1,255 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Commands;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\ManiaLink;
|
||||
use FML\Script\Features\Paging;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
* ManiaControl Help Manager Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
// TODO: refactor code - i see duplicated code all over the place..
|
||||
class HelpManager implements CommandListener, CallbackListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $playerCommands = array();
|
||||
private $adminCommands = array();
|
||||
|
||||
/**
|
||||
* Construct a new Commands Manager
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManiaControl OnInit Callback
|
||||
*/
|
||||
public function handleOnInit() {
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('help', $this, 'command_playerHelp', false, 'Shows all commands in chat.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('helpall', $this, 'command_playerHelpAll', false, 'Shows all commands in ManiaLink with description.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('help', $this, 'command_adminHelp', true, 'Shows all admin commands in chat.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('helpall', $this, 'command_adminHelpAll', true, 'Shows all admin commands in ManiaLink with description.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of Admin Commands
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_adminHelp(array $chatCallback, Player $player) {
|
||||
$showCommands = array();
|
||||
$registeredMethods = array();
|
||||
foreach (array_reverse($this->adminCommands) as $command) {
|
||||
if (array_key_exists($command['Method'], $registeredMethods) && $showCommands[$registeredMethods[$command['Method']]]['Description'] === $command['Description']) {
|
||||
$name = $registeredMethods[$command['Method']];
|
||||
$showCommands[$name]['Name'] .= '|' . $command['Name'];
|
||||
} else {
|
||||
$showCommands[$command['Name']] = $command;
|
||||
$registeredMethods[$command['Method']] = $command['Name'];
|
||||
}
|
||||
}
|
||||
|
||||
usort($showCommands, function ($commandA, $commandB) {
|
||||
return strcmp($commandA['Name'], $commandB['Name']);
|
||||
});
|
||||
|
||||
$message = 'Supported Admin Commands: ';
|
||||
foreach ($showCommands as $command) {
|
||||
$message .= $command['Name'] . ',';
|
||||
}
|
||||
$message = substr($message, 0, -1);
|
||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of Player Commands
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_playerHelp(array $chatCallback, Player $player) {
|
||||
$showCommands = array();
|
||||
$registeredMethods = array();
|
||||
foreach (array_reverse($this->playerCommands) as $command) {
|
||||
if (array_key_exists($command['Method'], $registeredMethods) && $showCommands[$registeredMethods[$command['Method']]]['Description'] === $command['Description']) {
|
||||
$name = $registeredMethods[$command['Method']];
|
||||
$showCommands[$name]['Name'] .= '|' . $command['Name'];
|
||||
} else {
|
||||
$showCommands[$command['Name']] = $command;
|
||||
$registeredMethods[$command['Method']] = $command['Name'];
|
||||
}
|
||||
}
|
||||
|
||||
usort($showCommands, function ($commandA, $commandB) {
|
||||
return strcmp($commandA['Name'], $commandB['Name']);
|
||||
});
|
||||
|
||||
$message = 'Supported Player Commands: ';
|
||||
foreach ($showCommands as $command) {
|
||||
$message .= $command['Name'] . ',';
|
||||
}
|
||||
$message = substr($message, 0, -1);
|
||||
$this->maniaControl->getChat()->sendChat($message, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a ManiaLink list of Player Commands
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_playerHelpAll(array $chatCallback, Player $player) {
|
||||
$this->prepareHelpAll($this->playerCommands, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the commands for the HelpAll ManiaLink.
|
||||
*
|
||||
* @param array $commands
|
||||
* @param mixed $player
|
||||
*/
|
||||
private function prepareHelpAll(array $commands, $player) {
|
||||
$showCommands = array();
|
||||
$registeredMethods = array();
|
||||
foreach (array_reverse($commands) as $command) {
|
||||
if (array_key_exists($command['Method'], $registeredMethods)) {
|
||||
if ($showCommands[$registeredMethods[$command['Method']]]['Description'] === $command['Description']) {
|
||||
$name = $registeredMethods[$command['Method']];
|
||||
$showCommands[$name]['Name'] .= '|' . $command['Name'];
|
||||
} else {
|
||||
$showCommands[$command['Name']] = $command;
|
||||
$registeredMethods[$command['Method']] = $command['Name'];
|
||||
}
|
||||
} else {
|
||||
$showCommands[$command['Name']] = $command;
|
||||
$registeredMethods[$command['Method']] = $command['Name'];
|
||||
}
|
||||
}
|
||||
|
||||
usort($showCommands, function ($commandA, $commandB) {
|
||||
return strcmp($commandA['Name'], $commandB['Name']);
|
||||
});
|
||||
|
||||
$this->showHelpAllList($showCommands, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the HelpAll list to the player.
|
||||
*
|
||||
* @param array $commands
|
||||
* @param mixed $player
|
||||
*/
|
||||
private function showHelpAllList(array $commands, $player) {
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
|
||||
// create manialink
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$script = $maniaLink->getScript();
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
|
||||
// Main frame
|
||||
$frame = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultListFrame($script, $paging);
|
||||
$maniaLink->add($frame);
|
||||
|
||||
// Start offsets
|
||||
$posX = -$width / 2;
|
||||
$posY = $height / 2;
|
||||
|
||||
//Predefine description Label
|
||||
$descriptionLabel = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultDescriptionLabel();
|
||||
$frame->add($descriptionLabel);
|
||||
|
||||
// Headline
|
||||
$headFrame = new Frame();
|
||||
$frame->add($headFrame);
|
||||
$headFrame->setY($posY - 5);
|
||||
$array = array('Command' => $posX + 5, 'Description' => $posX + 50);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $array);
|
||||
|
||||
$index = 1;
|
||||
$posY -= 10;
|
||||
$pageFrame = null;
|
||||
|
||||
foreach ($commands as $command) {
|
||||
if ($index % 15 === 1) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$posY = $height / 2 - 10;
|
||||
$paging->addPage($pageFrame);
|
||||
}
|
||||
|
||||
$playerFrame = new Frame();
|
||||
$pageFrame->add($playerFrame);
|
||||
$playerFrame->setY($posY);
|
||||
|
||||
if ($index % 2 !== 0) {
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$playerFrame->add($lineQuad);
|
||||
$lineQuad->setSize($width, 4);
|
||||
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$lineQuad->setZ(0.001);
|
||||
}
|
||||
|
||||
$array = array($command['Name'] => $posX + 5, $command['Description'] => $posX + 50);
|
||||
$labels = $this->maniaControl->getManialinkManager()->labelLine($playerFrame, $array);
|
||||
|
||||
$label = $labels[0];
|
||||
$label->setWidth(40);
|
||||
|
||||
$posY -= 4;
|
||||
$index++;
|
||||
}
|
||||
|
||||
// Render and display xml
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'HelpAllList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a ManiaLink list of Admin Commands
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_adminHelpAll(array $chatCallback, Player $player) {
|
||||
$this->prepareHelpAll($this->adminCommands, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new Command
|
||||
*
|
||||
* @param string $name
|
||||
* @param bool $adminCommand
|
||||
* @param string $description
|
||||
* @param string $method
|
||||
*/
|
||||
public function registerCommand($name, $adminCommand = false, $description = '', $method) {
|
||||
if ($adminCommand) {
|
||||
array_push($this->adminCommands, array("Name" => $name, "Description" => $description, "Method" => $method));
|
||||
} else {
|
||||
array_push($this->playerCommands, array("Name" => $name, "Description" => $description, "Method" => $method));
|
||||
}
|
||||
}
|
||||
}
|
350
core/Configurator/Configurator.php
Normal file
350
core/Configurator/Configurator.php
Normal file
@ -0,0 +1,350 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Configurator;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_BgRaceScore2;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use FML\ManiaLink;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Server\ServerOptionsMenu;
|
||||
use ManiaControl\Server\VoteRatiosMenu;
|
||||
|
||||
/**
|
||||
* Class managing ingame ManiaControl Configuration
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Configurator implements CallbackListener, CommandListener, ManialinkPageAnswerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_TOGGLEMENU = 'Configurator.ToggleMenuAction';
|
||||
const ACTION_SAVECONFIG = 'Configurator.SaveConfigAction';
|
||||
const ACTION_SELECTMENU = 'Configurator.SelectMenu.';
|
||||
const SETTING_MENU_POSX = 'Menu Widget Position: X';
|
||||
const SETTING_MENU_POSY = 'Menu Widget Position: Y';
|
||||
const SETTING_MENU_WIDTH = 'Menu Widget Width';
|
||||
const SETTING_MENU_HEIGHT = 'Menu Widget Height';
|
||||
const SETTING_MENU_STYLE = 'Menu Widget BackgroundQuad Style';
|
||||
const SETTING_MENU_SUBSTYLE = 'Menu Widget BackgroundQuad Substyle';
|
||||
const SETTING_PERMISSION_OPEN_CONFIGURATOR = 'Open Configurator';
|
||||
const CACHE_MENU_SHOWN = 'MenuShown';
|
||||
const MENU_NAME = 'Configurator';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var ServerOptionsMenu $serverOptionsMenu */
|
||||
private $serverOptionsMenu = null;
|
||||
/** @var ScriptSettings $scriptSettings */
|
||||
private $scriptSettings = null;
|
||||
/** @var VoteRatiosMenu $voteRatiosMenu */
|
||||
private $voteRatiosMenu = null;
|
||||
/** @var ManiaControlSettings $maniaControlSettings */
|
||||
private $maniaControlSettings = null;
|
||||
/** @var ConfiguratorMenu[] $menus */
|
||||
private $menus = array();
|
||||
|
||||
/**
|
||||
* Create a new configurator instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->addActionsMenuItem();
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_POSX, 0.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_POSY, 3.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_WIDTH, 170.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_HEIGHT, 81.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_STYLE, Quad_BgRaceScore2::STYLE);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MENU_SUBSTYLE, Quad_BgRaceScore2::SUBSTYLE_HandleSelectable);
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_OPEN_CONFIGURATOR, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
|
||||
// Page answers
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_TOGGLEMENU, $this, 'handleToggleMenuAction');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SAVECONFIG, $this, 'handleSaveConfigAction');
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_OPENED, $this, 'handleWidgetOpened');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_CLOSED, $this, 'closeWidget');
|
||||
|
||||
// Create server options menu
|
||||
$this->serverOptionsMenu = new ServerOptionsMenu($maniaControl);
|
||||
$this->addMenu($this->serverOptionsMenu);
|
||||
|
||||
// Create script settings
|
||||
$this->scriptSettings = new ScriptSettings($maniaControl);
|
||||
$this->addMenu($this->scriptSettings);
|
||||
|
||||
// Create vote ratios menu
|
||||
$this->voteRatiosMenu = new VoteRatiosMenu($maniaControl);
|
||||
$this->addMenu($this->voteRatiosMenu);
|
||||
|
||||
// Create Mania Control Settings
|
||||
$this->maniaControlSettings = new ManiaControlSettings($maniaControl);
|
||||
$this->addMenu($this->maniaControlSettings);
|
||||
|
||||
// Chat commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('config', $this, 'handleConfigCommand', true, 'Loads Config panel.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Menu Item to the Actions Menu
|
||||
*/
|
||||
private function addActionsMenuItem() {
|
||||
$itemQuad = new Quad_UIConstruction_Buttons();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_Tools)->setAction(self::ACTION_TOGGLEMENU);
|
||||
$this->maniaControl->getActionsMenu()->addAdminMenuItem($itemQuad, 100, 'Settings');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a configurator menu
|
||||
*
|
||||
* @param ConfiguratorMenu $menu
|
||||
*/
|
||||
public function addMenu(ConfiguratorMenu $menu) {
|
||||
array_push($this->menus, $menu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Config Admin Command
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleConfigCommand(array $callback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_OPEN_CONFIGURATOR)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->showMenu($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Menu to the Player
|
||||
*
|
||||
* @param Player $player
|
||||
* @param mixed $menuId
|
||||
*/
|
||||
public function showMenu(Player $player, $menuId = 0) {
|
||||
if ($menuId instanceof ConfiguratorMenu) {
|
||||
$menuId = $this->getMenuId($menuId->getTitle());
|
||||
}
|
||||
$manialink = $this->buildManialink($menuId, $player);
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($manialink, $player, self::MENU_NAME);
|
||||
$player->setCache($this, self::CACHE_MENU_SHOWN, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Menu Id
|
||||
*
|
||||
* @param string $title
|
||||
* @return int
|
||||
*/
|
||||
public function getMenuId($title) {
|
||||
$index = 0;
|
||||
foreach ($this->menus as $menu) {
|
||||
if ($menu === $title || $menu->getTitle() === $title) {
|
||||
return $index;
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Menu ManiaLink if necessary
|
||||
*
|
||||
* @param int $menuIdShown
|
||||
* @param Player $player
|
||||
* @return \FML\ManiaLink
|
||||
*/
|
||||
private function buildManialink($menuIdShown = 0, Player $player = null) {
|
||||
$menuPosX = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSX);
|
||||
$menuPosY = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSY);
|
||||
$menuWidth = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_WIDTH);
|
||||
$menuHeight = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_HEIGHT);
|
||||
$quadStyle = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_STYLE);
|
||||
$quadSubstyle = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_SUBSTYLE);
|
||||
|
||||
$menuListWidth = $menuWidth * 0.3;
|
||||
$menuItemHeight = 10.;
|
||||
$subMenuWidth = $menuWidth - $menuListWidth;
|
||||
$subMenuHeight = $menuHeight;
|
||||
|
||||
$manialink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
|
||||
$frame = new Frame();
|
||||
$manialink->add($frame);
|
||||
$frame->setPosition($menuPosX, $menuPosY, 10);
|
||||
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$backgroundQuad->setZ(-10)->setSize($menuWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
$menuItemsFrame = new Frame();
|
||||
$frame->add($menuItemsFrame);
|
||||
$menuItemsFrame->setX($menuWidth * -0.5 + $menuListWidth * 0.5);
|
||||
|
||||
$itemsBackgroundQuad = new Quad();
|
||||
$menuItemsFrame->add($itemsBackgroundQuad);
|
||||
$backgroundQuad->setZ(-9);
|
||||
$itemsBackgroundQuad->setSize($menuListWidth, $menuHeight)->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
$menusFrame = new Frame();
|
||||
$frame->add($menusFrame);
|
||||
$menusFrame->setX($menuWidth * -0.5 + $menuListWidth + $subMenuWidth * 0.5);
|
||||
|
||||
// Create script and features
|
||||
$script = $manialink->getScript();
|
||||
|
||||
$menuItemY = $menuHeight * 0.42;
|
||||
$menuId = 0;
|
||||
foreach ($this->menus as $menu) {
|
||||
// Add title
|
||||
$menuItemLabel = new Label_Text();
|
||||
$menuItemsFrame->add($menuItemLabel);
|
||||
$menuItemLabel->setY($menuItemY)->setSize($menuListWidth * 0.9, $menuItemHeight * 0.9)->setStyle($menuItemLabel::STYLE_TextCardRaceRank)->setText($menu->getTitle())->setAction(self::ACTION_SELECTMENU . $menuId);
|
||||
|
||||
// Show the menu
|
||||
if ($menuId === $menuIdShown) {
|
||||
$menuControl = $menu->getMenu($subMenuWidth, $subMenuHeight, $script, $player);
|
||||
if ($menuControl) {
|
||||
$menusFrame->add($menuControl);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('Error loading Menu!', $player);
|
||||
}
|
||||
}
|
||||
|
||||
$menuItemY -= $menuItemHeight * 1.1;
|
||||
$menuId++;
|
||||
}
|
||||
|
||||
// Add Close Quad (X)
|
||||
$closeQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($closeQuad);
|
||||
$closeQuad->setPosition($menuWidth * 0.483, $menuHeight * 0.467, 3)->setSize(6, 6)->setSubStyle($closeQuad::SUBSTYLE_QuitRace)->setAction(ManialinkManager::ACTION_CLOSEWIDGET);
|
||||
|
||||
// Add close button
|
||||
$closeButton = new Label_Text();
|
||||
$frame->add($closeButton);
|
||||
$closeButton->setPosition($menuWidth * -0.5 + $menuListWidth * 0.29, $menuHeight * -0.43)->setSize($menuListWidth * 0.3, $menuListWidth * 0.1)->setStyle($closeButton::STYLE_TextButtonNavBack)->setTextPrefix('$999')->setTranslate(true)->setText('Close')->setAction(self::ACTION_TOGGLEMENU);
|
||||
|
||||
// Add save button
|
||||
$saveButton = new Label_Text();
|
||||
$frame->add($saveButton);
|
||||
$saveButton->setPosition($menuWidth * -0.5 + $menuListWidth * 0.71, $menuHeight * -0.43)->setSize($menuListWidth * 0.3, $menuListWidth * 0.1)->setStyle($saveButton::STYLE_TextButtonNavBack)->setTextPrefix('$0f5')->setTranslate(true)->setText('Save')->setAction(self::ACTION_SAVECONFIG);
|
||||
|
||||
return $manialink;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle toggle menu action
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleToggleMenuAction(array $callback, Player $player) {
|
||||
$this->toggleMenu($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the Menu for the Player
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function toggleMenu(Player $player) {
|
||||
if ($player->getCache($this, self::CACHE_MENU_SHOWN)) {
|
||||
$this->hideMenu($player);
|
||||
} else {
|
||||
$this->showMenu($player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the Menu for the Player
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function hideMenu(Player $player) {
|
||||
$this->closeWidget($player);
|
||||
$this->maniaControl->getManialinkManager()->closeWidget($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle widget being closed
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function closeWidget(Player $player) {
|
||||
$player->destroyCache($this, self::CACHE_MENU_SHOWN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the config data received from the manialink
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleSaveConfigAction(array $callback, Player $player) {
|
||||
foreach ($this->menus as $menu) {
|
||||
$menu->saveConfigData($callback[1], $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the player if he opened another Main Widget
|
||||
*
|
||||
* @param Player $player
|
||||
* @param string $openedWidget
|
||||
*/
|
||||
public function handleWidgetOpened(Player $player, $openedWidget) {
|
||||
if ($openedWidget !== self::MENU_NAME) {
|
||||
$player->destroyCache($this, self::CACHE_MENU_SHOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManialinkPageAnswer Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$boolSelectMenu = (strpos($actionId, self::ACTION_SELECTMENU) === 0);
|
||||
if (!$boolSelectMenu) {
|
||||
return;
|
||||
}
|
||||
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
|
||||
if ($player) {
|
||||
$actionArray = explode('.', $callback[1][2]);
|
||||
$this->showMenu($player, intval($actionArray[2]));
|
||||
}
|
||||
}
|
||||
}
|
42
core/Configurator/ConfiguratorMenu.php
Normal file
42
core/Configurator/ConfiguratorMenu.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Configurator;
|
||||
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
* Interface for Configurator Menus
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
interface ConfiguratorMenu {
|
||||
|
||||
/**
|
||||
* Get the menu title
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getTitle();
|
||||
|
||||
/**
|
||||
* Get the configurator menu frame
|
||||
*
|
||||
* @param float $width
|
||||
* @param float $height
|
||||
* @param Script $script
|
||||
* @param Player $player
|
||||
* @return \FML\Controls\Frame
|
||||
*/
|
||||
public function getMenu($width, $height, Script $script, Player $player);
|
||||
|
||||
/**
|
||||
* Save the config data
|
||||
*
|
||||
* @param array $configData
|
||||
* @param Player $player
|
||||
*/
|
||||
public function saveConfigData(array $configData, Player $player);
|
||||
}
|
352
core/Configurator/ManiaControlSettings.php
Normal file
352
core/Configurator/ManiaControlSettings.php
Normal file
@ -0,0 +1,352 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Configurator;
|
||||
|
||||
use FML\Components\CheckBox;
|
||||
use FML\Components\ValuePicker;
|
||||
use FML\Controls\Entry;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Button;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Script\Features\Paging;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Settings\Setting;
|
||||
|
||||
/**
|
||||
* Class offering a Configurator for ManiaControl Settings
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TITLE = 'ManiaControl Settings';
|
||||
const ACTION_PREFIX_SETTING = 'MCSetting.';
|
||||
const ACTION_PREFIX_SETTINGCLASS = 'MCSettingClass.';
|
||||
const ACTION_SETTINGCLASS_BACK = 'MCSettingClassBack';
|
||||
const SETTING_PERMISSION_CHANGE_MC_SETTINGS = 'Change ManiaControl Settings';
|
||||
const CACHE_CLASS_OPENED = 'ClassOpened';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new ManiaControl Settings instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_MC_SETTINGS, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getTitle()
|
||||
*/
|
||||
public static function getTitle() {
|
||||
return self::TITLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getMenu()
|
||||
*/
|
||||
public function getMenu($width, $height, Script $script, Player $player) {
|
||||
$openedClass = $player->getCache($this, self::CACHE_CLASS_OPENED);
|
||||
if ($openedClass) {
|
||||
return $this->getMenuSettingsForClass($openedClass, $width, $height, $script, $player);
|
||||
}
|
||||
return $this->getMenuSettingClasses($width, $height, $script, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Menu showing the Settings for the given Class
|
||||
*
|
||||
* @param string $settingClass
|
||||
* @param float $width
|
||||
* @param float $height
|
||||
* @param Script $script
|
||||
* @param Player $player
|
||||
* @return \FML\Controls\Frame
|
||||
*/
|
||||
private function getMenuSettingsForClass($settingClass, $width, $height, Script $script, Player $player) {
|
||||
$settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass);
|
||||
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$frame = new Frame();
|
||||
|
||||
// Config
|
||||
$pagerSize = 9.;
|
||||
$settingHeight = 5.;
|
||||
$labelTextSize = 2;
|
||||
$pageMaxCount = 11;
|
||||
|
||||
// Pagers
|
||||
$pagerPrev = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerPrev);
|
||||
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2);
|
||||
$pagerPrev->setSize($pagerSize, $pagerSize);
|
||||
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
|
||||
|
||||
$pagerNext = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerNext);
|
||||
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2);
|
||||
$pagerNext->setSize($pagerSize, $pagerSize);
|
||||
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
|
||||
|
||||
$paging->addButton($pagerNext);
|
||||
$paging->addButton($pagerPrev);
|
||||
|
||||
$pageCountLabel = new Label_Text();
|
||||
$frame->add($pageCountLabel);
|
||||
$pageCountLabel->setHAlign($pageCountLabel::RIGHT);
|
||||
$pageCountLabel->setPosition($width * 0.35, $height * -0.44);
|
||||
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
|
||||
$pageCountLabel->setTextSize(2);
|
||||
|
||||
$paging->setLabel($pageCountLabel);
|
||||
|
||||
$backLabel = new Label_Button();
|
||||
$frame->add($backLabel);
|
||||
$backLabel->setStyle($backLabel::STYLE_CardMain_Quit);
|
||||
$backLabel->setPosition(-$width / 2 + 7, -$height / 2 + 7);
|
||||
$backLabel->setHAlign($backLabel::LEFT);
|
||||
$backLabel->setTextSize(2);
|
||||
$backLabel->setText('Back');
|
||||
$backLabel->setAction(self::ACTION_SETTINGCLASS_BACK);
|
||||
|
||||
$headLabel = new Label_Text();
|
||||
$frame->add($headLabel);
|
||||
$headLabel->setHAlign($headLabel::LEFT);
|
||||
$headLabel->setPosition($width * -0.46, $height * 0.41);
|
||||
$headLabel->setSize($width * 0.6, $settingHeight);
|
||||
$headLabel->setStyle($headLabel::STYLE_TextCardSmall);
|
||||
$headLabel->setTextSize(3);
|
||||
$headLabel->setText($settingClass);
|
||||
$headLabel->setTextColor('ff0');
|
||||
|
||||
$pageFrame = null;
|
||||
$index = 0;
|
||||
$posY = 0;
|
||||
foreach ($settings as $setting) {
|
||||
if ($index % $pageMaxCount === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$paging->addPage($pageFrame);
|
||||
$posY = $height * 0.41 - $settingHeight * 1.5;
|
||||
}
|
||||
|
||||
$settingFrame = new Frame();
|
||||
$pageFrame->add($settingFrame);
|
||||
$settingFrame->setY($posY);
|
||||
|
||||
$nameLabel = new Label_Text();
|
||||
$settingFrame->add($nameLabel);
|
||||
$nameLabel->setHAlign($nameLabel::LEFT);
|
||||
$nameLabel->setX($width * -0.46);
|
||||
$nameLabel->setSize($width * 0.6, $settingHeight);
|
||||
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
|
||||
$nameLabel->setTextSize($labelTextSize);
|
||||
$nameLabel->setText($setting->setting);
|
||||
$nameLabel->setTextColor('fff');
|
||||
|
||||
$settingName = self::ACTION_PREFIX_SETTING . $setting->index;
|
||||
if ($setting->type === Setting::TYPE_BOOL) {
|
||||
// Boolean checkbox
|
||||
$quad = new Quad();
|
||||
$quad->setPosition($width * 0.33, 0, -0.01);
|
||||
$quad->setSize(4, 4);
|
||||
$checkBox = new CheckBox($settingName, $setting->value, $quad);
|
||||
$settingFrame->add($checkBox);
|
||||
} else if ($setting->type === Setting::TYPE_SET) {
|
||||
// SET value picker
|
||||
$label = new Label_Text();
|
||||
$label->setX($width * 0.33);
|
||||
$label->setSize($width * 0.3, $settingHeight * 0.9);
|
||||
$label->setStyle($label::STYLE_TextValueSmall);
|
||||
$label->setTextSize(1);
|
||||
$valuePicker = new ValuePicker($settingName, $setting->set, $setting->value, $label);
|
||||
$settingFrame->add($valuePicker);
|
||||
} else {
|
||||
// Standard entry
|
||||
$entry = new Entry();
|
||||
$settingFrame->add($entry);
|
||||
$entry->setX($width * 0.33);
|
||||
$entry->setSize($width * 0.3, $settingHeight * 0.9);
|
||||
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
|
||||
$entry->setTextSize(1);
|
||||
$entry->setName($settingName);
|
||||
$entry->setDefault($setting->value);
|
||||
}
|
||||
|
||||
$posY -= $settingHeight;
|
||||
$index++;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Menu showing all possible Classes
|
||||
*
|
||||
* @param float $width
|
||||
* @param float $height
|
||||
* @param Script $script
|
||||
* @param Player $player
|
||||
* @return \FML\Controls\Frame
|
||||
*/
|
||||
private function getMenuSettingClasses($width, $height, Script $script, Player $player) {
|
||||
$settingClasses = $this->maniaControl->getSettingManager()->getSettingClasses(true);
|
||||
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$frame = new Frame();
|
||||
|
||||
// Config
|
||||
$pagerSize = 9.;
|
||||
$settingHeight = 5.;
|
||||
$pageMaxCount = 13;
|
||||
$posY = 0;
|
||||
|
||||
// Pagers
|
||||
$pagerPrev = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerPrev);
|
||||
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2);
|
||||
$pagerPrev->setSize($pagerSize, $pagerSize);
|
||||
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
|
||||
|
||||
$pagerNext = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerNext);
|
||||
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2);
|
||||
$pagerNext->setSize($pagerSize, $pagerSize);
|
||||
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
|
||||
|
||||
$paging->addButton($pagerNext);
|
||||
$paging->addButton($pagerPrev);
|
||||
|
||||
$pageCountLabel = new Label_Text();
|
||||
$frame->add($pageCountLabel);
|
||||
$pageCountLabel->setHAlign($pageCountLabel::RIGHT);
|
||||
$pageCountLabel->setPosition($width * 0.35, $height * -0.44, 1);
|
||||
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
|
||||
$pageCountLabel->setTextSize(2);
|
||||
|
||||
$paging->setLabel($pageCountLabel);
|
||||
|
||||
$pageFrame = null;
|
||||
$index = 0;
|
||||
foreach ($settingClasses as $settingClass) {
|
||||
if ($index % $pageMaxCount === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$posY = $height * 0.41;
|
||||
$paging->addPage($pageFrame);
|
||||
}
|
||||
|
||||
$classLabel = new Label_Text();
|
||||
|
||||
$settingClassArray = explode('\\', $settingClass);
|
||||
$className = '';
|
||||
for ($i = 1; $i < count($settingClassArray); $i++) {
|
||||
$className .= $settingClassArray[$i] . ' - ';
|
||||
}
|
||||
$className = substr($className, 0, -3);
|
||||
|
||||
$pageFrame->add($classLabel);
|
||||
$classLabel->setHAlign($classLabel::LEFT);
|
||||
$classLabel->setPosition($width * -0.45, $posY);
|
||||
$classLabel->setSize($width * 0.9, $settingHeight * 0.9);
|
||||
$classLabel->setStyle($classLabel::STYLE_TextCardSmall);
|
||||
$classLabel->setTextSize(2);
|
||||
$classLabel->setText($className);
|
||||
$classLabel->setTextColor('fff');
|
||||
$classLabel->setAction(self::ACTION_PREFIX_SETTINGCLASS . $settingClass);
|
||||
|
||||
$posY -= $settingHeight;
|
||||
$index++;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManialinkPageAnswer Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
if ($actionId === self::ACTION_SETTINGCLASS_BACK) {
|
||||
// Back to classes list
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
$player->destroyCache($this, self::CACHE_CLASS_OPENED);
|
||||
$menuId = $this->maniaControl->getConfigurator()->getMenuId($this);
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $menuId);
|
||||
} else if (strpos($actionId, self::ACTION_PREFIX_SETTINGCLASS) === 0) {
|
||||
// Setting class selected
|
||||
$settingClass = substr($actionId, strlen(self::ACTION_PREFIX_SETTINGCLASS));
|
||||
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
$player->setCache($this, self::CACHE_CLASS_OPENED, $settingClass);
|
||||
|
||||
$menuId = $this->maniaControl->getConfigurator()->getMenuId($this);
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $menuId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||
*/
|
||||
public function saveConfigData(array $configData, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_MC_SETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
if (!$configData[3] || strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prefixLength = strlen(self::ACTION_PREFIX_SETTING);
|
||||
|
||||
foreach ($configData[3] as $settingData) {
|
||||
$settingIndex = (int)substr($settingData['Name'], $prefixLength);
|
||||
$settingObject = $this->maniaControl->getSettingManager()->getSettingObjectByIndex($settingIndex);
|
||||
if (!$settingObject) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$settingData || $settingData['Value'] == $settingObject->value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$settingObject->value = $settingData['Value'];
|
||||
$this->maniaControl->getSettingManager()->saveSetting($settingObject);
|
||||
}
|
||||
|
||||
$this->maniaControl->getChat()->sendSuccess('Settings saved!', $player);
|
||||
|
||||
// Reopen the Menu
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
}
|
411
core/Configurator/ScriptSettings.php
Normal file
411
core/Configurator/ScriptSettings.php
Normal file
@ -0,0 +1,411 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Configurator;
|
||||
|
||||
use FML\Components\CheckBox;
|
||||
use FML\Controls\Entry;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Script\Features\Paging;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
|
||||
/**
|
||||
* Class offering a Configurator for Script Settings
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ScriptSettings implements ConfiguratorMenu, CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_PREFIX_SETTING = 'ScriptSetting.';
|
||||
const CB_SCRIPTSETTING_CHANGED = 'ScriptSettings.SettingChanged';
|
||||
const CB_SCRIPTSETTINGS_CHANGED = 'ScriptSettings.SettingsChanged';
|
||||
const TABLE_SCRIPT_SETTINGS = 'mc_scriptsettings';
|
||||
const SETTING_LOAD_DEFAULT_SETTINGS_MAP_BEGIN = 'Load Stored Script-Settings on Map-Begin';
|
||||
const SETTING_PERMISSION_CHANGE_SCRIPT_SETTINGS = 'Change Script-Settings';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new script settings instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::BEGINMAP, $this, 'onBeginMap');
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_LOAD_DEFAULT_SETTINGS_MAP_BEGIN, false);
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_SCRIPT_SETTINGS, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create all necessary database tables
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_SCRIPT_SETTINGS . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`serverIndex` int(11) NOT NULL,
|
||||
`settingName` varchar(100) NOT NULL,
|
||||
`settingValue` varchar(500) NOT NULL,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `setting` (`serverIndex`, `settingName`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Script Settings' AUTO_INCREMENT=1;";
|
||||
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getTitle()
|
||||
*/
|
||||
public static function getTitle() {
|
||||
return 'Script Settings';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle OnInit callback
|
||||
*/
|
||||
public function onInit() {
|
||||
$this->loadSettingsFromDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Settings from Database
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function loadSettingsFromDatabase() {
|
||||
try {
|
||||
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||||
} catch (GameModeException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$serverIndex = $this->maniaControl->getServer()->index;
|
||||
$query = "SELECT * FROM `" . self::TABLE_SCRIPT_SETTINGS . "`
|
||||
WHERE serverIndex = {$serverIndex};";
|
||||
$result = $mysqli->query($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
$loadedSettings = array();
|
||||
while ($row = $result->fetch_object()) {
|
||||
if (!isset($scriptSettings[$row->settingName])) {
|
||||
continue;
|
||||
}
|
||||
$loadedSettings[$row->settingName] = $row->settingValue;
|
||||
settype($loadedSettings[$row->settingName], gettype($scriptSettings[$row->settingName]));
|
||||
}
|
||||
$result->free();
|
||||
if (empty($loadedSettings)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return $this->maniaControl->getClient()->setModeScriptSettings($loadedSettings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Begin Map Callback
|
||||
*/
|
||||
public function onBeginMap() {
|
||||
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_LOAD_DEFAULT_SETTINGS_MAP_BEGIN)
|
||||
) {
|
||||
$this->loadSettingsFromDatabase();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getMenu()
|
||||
*/
|
||||
public function getMenu($width, $height, Script $script, Player $player) {
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$frame = new Frame();
|
||||
|
||||
try {
|
||||
$scriptInfo = $this->maniaControl->getClient()->getModeScriptInfo();
|
||||
} catch (GameModeException $e) {
|
||||
$label = new Label();
|
||||
$frame->add($label);
|
||||
$label->setText($e->getMessage());
|
||||
return $frame;
|
||||
}
|
||||
|
||||
$scriptParams = $scriptInfo->paramDescs;
|
||||
|
||||
try {
|
||||
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||||
} catch (GameModeException $e) {
|
||||
}
|
||||
|
||||
// Config
|
||||
$pagerSize = 9.;
|
||||
$settingHeight = 5.;
|
||||
$labelTextSize = 2;
|
||||
|
||||
// Pagers
|
||||
$pagerPrev = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerPrev);
|
||||
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2);
|
||||
$pagerPrev->setSize($pagerSize, $pagerSize);
|
||||
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
|
||||
|
||||
$pagerNext = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerNext);
|
||||
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2);
|
||||
$pagerNext->setSize($pagerSize, $pagerSize);
|
||||
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
|
||||
|
||||
$paging->addButton($pagerNext);
|
||||
$paging->addButton($pagerPrev);
|
||||
|
||||
$pageCountLabel = new Label_Text();
|
||||
$frame->add($pageCountLabel);
|
||||
$pageCountLabel->setHAlign($pageCountLabel::RIGHT);
|
||||
$pageCountLabel->setPosition($width * 0.35, $height * -0.44, 1);
|
||||
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
|
||||
$pageCountLabel->setTextSize(2);
|
||||
|
||||
$paging->setLabel($pageCountLabel);
|
||||
|
||||
// Setting pages
|
||||
$pageFrame = null;
|
||||
$posY = 0.;
|
||||
|
||||
foreach ($scriptParams as $index => $scriptParam) {
|
||||
/** @var \Maniaplanet\DedicatedServer\Structures\ScriptSettings $scriptParam */
|
||||
$settingName = $scriptParam->name;
|
||||
|
||||
if (!isset($scriptSettings[$settingName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($index % 13 === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$posY = $height * 0.41;
|
||||
$paging->addPage($pageFrame);
|
||||
}
|
||||
|
||||
$settingFrame = new Frame();
|
||||
$pageFrame->add($settingFrame);
|
||||
$settingFrame->setY($posY);
|
||||
|
||||
$nameLabel = new Label_Text();
|
||||
$settingFrame->add($nameLabel);
|
||||
$nameLabel->setHAlign($nameLabel::LEFT);
|
||||
$nameLabel->setX($width * -0.46);
|
||||
$nameLabel->setSize($width * 0.4, $settingHeight);
|
||||
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
|
||||
$nameLabel->setTextSize($labelTextSize);
|
||||
$nameLabel->setText($settingName);
|
||||
|
||||
$settingValue = $scriptSettings[$settingName];
|
||||
|
||||
if (is_bool($settingValue)) {
|
||||
// Boolean checkbox
|
||||
$quad = new Quad();
|
||||
$quad->setX($width / 2 * 0.545);
|
||||
$quad->setSize(4, 4);
|
||||
$checkBox = new CheckBox(self::ACTION_PREFIX_SETTING . $settingName, $settingValue, $quad);
|
||||
$settingFrame->add($checkBox);
|
||||
} else {
|
||||
// Value entry
|
||||
$entry = new Entry();
|
||||
$settingFrame->add($entry);
|
||||
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
|
||||
$entry->setX($width / 2 * 0.55);
|
||||
$entry->setTextSize(1);
|
||||
$entry->setSize($width * 0.3, $settingHeight * 0.9);
|
||||
$entry->setName(self::ACTION_PREFIX_SETTING . $settingName);
|
||||
$entry->setDefault($settingValue);
|
||||
}
|
||||
|
||||
$descriptionLabel = new Label();
|
||||
$pageFrame->add($descriptionLabel);
|
||||
$descriptionLabel->setHAlign($descriptionLabel::LEFT);
|
||||
$descriptionLabel->setPosition($width * -0.45, $height * -0.44);
|
||||
$descriptionLabel->setSize($width * 0.7, $settingHeight);
|
||||
$descriptionLabel->setTextSize($labelTextSize);
|
||||
$descriptionLabel->setTranslate(true);
|
||||
$descriptionLabel->setText($scriptParam->desc);
|
||||
$nameLabel->addTooltipFeature($descriptionLabel);
|
||||
|
||||
$posY -= $settingHeight;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||
*/
|
||||
public function saveConfigData(array $configData, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SCRIPT_SETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
if (!$configData[3] || strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||||
} catch (GameModeException $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prefixLength = strlen(self::ACTION_PREFIX_SETTING);
|
||||
|
||||
$newSettings = array();
|
||||
foreach ($configData[3] as $setting) {
|
||||
$settingName = substr($setting['Name'], $prefixLength);
|
||||
if (!isset($scriptSettings[$settingName])) {
|
||||
var_dump('no setting ' . $settingName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($setting['Value'] == $scriptSettings[$settingName]) {
|
||||
// Not changed
|
||||
continue;
|
||||
}
|
||||
|
||||
$newSettings[$settingName] = $setting['Value'];
|
||||
settype($newSettings[$settingName], gettype($scriptSettings[$settingName]));
|
||||
}
|
||||
|
||||
$success = $this->applyNewScriptSettings($newSettings, $player);
|
||||
if ($success) {
|
||||
$this->maniaControl->getChat()->sendSuccess('Script Settings saved!', $player);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('Script Settings Saving failed!', $player);
|
||||
}
|
||||
|
||||
// Reopen the Menu
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Array of new Script Settings
|
||||
*
|
||||
* @param array $newSettings
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function applyNewScriptSettings(array $newSettings, Player $player) {
|
||||
if (empty($newSettings)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->maniaControl->getClient()->setModeScriptSettings($newSettings);
|
||||
|
||||
// Save Settings into Database
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "INSERT INTO `" . self::TABLE_SCRIPT_SETTINGS . "` (
|
||||
`serverIndex`,
|
||||
`settingName`,
|
||||
`settingValue`
|
||||
) VALUES (
|
||||
?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`settingValue` = VALUES(`settingValue`);";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$settingName = null;
|
||||
$settingValue = null;
|
||||
$statement->bind_param('iss', $this->maniaControl->getServer()->index, $settingName, $settingValue);
|
||||
|
||||
// Notifications
|
||||
$settingsCount = count($newSettings);
|
||||
$settingIndex = 0;
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($player);
|
||||
$chatMessage = '$ff0' . $title . ' ' . $player->getEscapedNickname() . ' set ScriptSetting' . ($settingsCount > 1 ? 's' : '') . ' ';
|
||||
foreach ($newSettings as $setting => $value) {
|
||||
$chatMessage .= '$<' . '$fff' . preg_replace('/^S_/', '', $setting) . '$z$s$ff0 ';
|
||||
$chatMessage .= 'to $fff' . $this->parseSettingValue($value) . '$>';
|
||||
|
||||
if ($settingIndex <= $settingsCount - 2) {
|
||||
$chatMessage .= ', ';
|
||||
}
|
||||
|
||||
// Add To Database
|
||||
$settingName = $setting;
|
||||
$settingValue = $value;
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
}
|
||||
|
||||
// Trigger own callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SCRIPTSETTING_CHANGED, $setting, $value);
|
||||
|
||||
$settingIndex++;
|
||||
}
|
||||
$statement->close();
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SCRIPTSETTINGS_CHANGED);
|
||||
|
||||
$chatMessage .= '!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Setting Value to a String Representation
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
private function parseSettingValue($value) {
|
||||
if (is_bool($value)) {
|
||||
return ($value ? 'True' : 'False');
|
||||
}
|
||||
return (string)$value;
|
||||
}
|
||||
}
|
56
core/Database/Config.php
Normal file
56
core/Database/Config.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Database;
|
||||
|
||||
/**
|
||||
* Model Class holding the Database Config
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Config {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $host = null;
|
||||
public $port = null;
|
||||
public $user = null;
|
||||
public $pass = null;
|
||||
public $name = null;
|
||||
|
||||
/**
|
||||
* Create a new Database Config Instance
|
||||
*
|
||||
* @param string $host
|
||||
* @param string $port
|
||||
* @param string $user
|
||||
* @param string $pass
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct($host = null, $port = null, $user = null, $pass = null, $name = null) {
|
||||
$this->host = (string)$host;
|
||||
$this->port = (int)$port;
|
||||
$this->user = (string)$user;
|
||||
$this->pass = (string)$pass;
|
||||
$this->name = (string)$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the Config Data
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function validate() {
|
||||
if (!$this->host || !$this->port || !$this->user || !$this->pass || !$this->name) {
|
||||
return false;
|
||||
}
|
||||
if ($this->user === 'mysql_user' || $this->pass === 'mysql_password') {
|
||||
return false;
|
||||
}
|
||||
if ($this->name === 'database_name') {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
235
core/Database/Database.php
Normal file
235
core/Database/Database.php
Normal file
@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Database;
|
||||
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Database Connection Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Database implements TimerListener {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var \mysqli $mysqli */
|
||||
/** @deprecated see getMysqli() */
|
||||
public $mysqli = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var Config $config */
|
||||
private $config = null;
|
||||
/** @var MigrationHelper $migrationHelper */
|
||||
private $migrationHelper = null;
|
||||
|
||||
/**
|
||||
* Construct a new Database Connection
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Enable mysqli Reconnect
|
||||
ini_set('mysqli.reconnect', 'on');
|
||||
|
||||
// Open database connection
|
||||
$this->loadConfig();
|
||||
$this->mysqli = @new \mysqli($this->config->host, $this->config->user, $this->config->pass, null, $this->config->port);
|
||||
if ($connectError = $this->getMysqli()->connect_error) {
|
||||
$message = "Couldn't connect to Database: '{$connectError}'";
|
||||
$this->maniaControl->quit($message, true);
|
||||
}
|
||||
$this->getMysqli()->set_charset("utf8");
|
||||
|
||||
$this->initDatabase();
|
||||
$this->optimizeTables();
|
||||
|
||||
// Register Method which checks the Database Connection every 5 seconds
|
||||
$this->maniaControl->getTimerManager()->registerTimerListening($this, 'checkConnection', 5000);
|
||||
|
||||
// Children
|
||||
$this->migrationHelper = new MigrationHelper($maniaControl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the Database Config
|
||||
*/
|
||||
private function loadConfig() {
|
||||
$databaseElements = $this->maniaControl->getConfig()->xpath('database');
|
||||
if (!$databaseElements) {
|
||||
$this->maniaControl->quit('No Database configured!', true);
|
||||
}
|
||||
$databaseElement = $databaseElements[0];
|
||||
|
||||
// Host
|
||||
$hostElements = $databaseElement->xpath('host');
|
||||
if (!$hostElements) {
|
||||
$this->maniaControl->quit("Invalid database configuration (Host).", true);
|
||||
}
|
||||
$host = (string)$hostElements[0];
|
||||
|
||||
// Port
|
||||
$portElements = $databaseElement->xpath('port');
|
||||
if (!$portElements) {
|
||||
$this->maniaControl->quit("Invalid database configuration (Port).", true);
|
||||
}
|
||||
$port = (string)$portElements[0];
|
||||
|
||||
// User
|
||||
$userElements = $databaseElement->xpath('user');
|
||||
if (!$userElements) {
|
||||
$this->maniaControl->quit("Invalid database configuration (User).", true);
|
||||
}
|
||||
$user = (string)$userElements[0];
|
||||
|
||||
// Pass
|
||||
$passElements = $databaseElement->xpath('pass');
|
||||
if (!$passElements) {
|
||||
$this->maniaControl->quit("Invalid database configuration (Pass).", true);
|
||||
}
|
||||
$pass = (string)$passElements[0];
|
||||
|
||||
// Name
|
||||
$nameElements = $databaseElement->xpath('name');
|
||||
if (!$nameElements) {
|
||||
$nameElements = $databaseElement->xpath('db_name');
|
||||
}
|
||||
if (!$nameElements) {
|
||||
$this->maniaControl->quit("Invalid database configuration (Name).", true);
|
||||
}
|
||||
$name = (string)$nameElements[0];
|
||||
|
||||
// Create config object
|
||||
$config = new Config($host, $port, $user, $pass, $name);
|
||||
if (!$config->validate()) {
|
||||
$this->maniaControl->quit("Your config file doesn't seem to be maintained properly. Please check the database configuration again!", true);
|
||||
}
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the defined Database
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initDatabase() {
|
||||
// Try to connect
|
||||
$result = $this->getMysqli()->select_db($this->config->name);
|
||||
if ($result) {
|
||||
return true;
|
||||
}
|
||||
Logger::logInfo("Database '{$this->config->name}' doesn't exist! Trying to create it...");
|
||||
|
||||
// Create database
|
||||
$databaseQuery = "CREATE DATABASE " . $this->getMysqli()->escape_string($this->config->name) . ";";
|
||||
$this->getMysqli()->query($databaseQuery);
|
||||
if ($this->getMysqli()->error) {
|
||||
$this->maniaControl->quit($this->getMysqli()->error, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connect to new database
|
||||
$this->getMysqli()->select_db($this->config->name);
|
||||
if ($error = $this->getMysqli()->error) {
|
||||
$message = "Couldn't select database '{$this->config->name}'. {$error}";
|
||||
$this->maniaControl->quit($message, true);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize all existing Tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function optimizeTables() {
|
||||
$showQuery = 'SHOW TABLES;';
|
||||
$result = $this->getMysqli()->query($showQuery);
|
||||
if ($error = $this->getMysqli()->error) {
|
||||
Logger::logError($error);
|
||||
return false;
|
||||
}
|
||||
$count = $result->num_rows;
|
||||
if ($count <= 0) {
|
||||
$result->free();
|
||||
return true;
|
||||
}
|
||||
$optimizeQuery = 'OPTIMIZE TABLE ';
|
||||
$index = 0;
|
||||
while ($row = $result->fetch_row()) {
|
||||
$tableName = $row[0];
|
||||
$optimizeQuery .= "`{$tableName}`";
|
||||
if ($index < $count - 1) {
|
||||
$optimizeQuery .= ',';
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
$result->free();
|
||||
$optimizeQuery .= ';';
|
||||
$this->getMysqli()->query($optimizeQuery);
|
||||
if ($error = $this->getMysqli()->error) {
|
||||
Logger::logError($error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mysqli instance
|
||||
*
|
||||
* @return \mysqli
|
||||
*/
|
||||
public function getMysqli() {
|
||||
return $this->mysqli;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database config
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function getConfig() {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the migration helper
|
||||
*
|
||||
* @return MigrationHelper
|
||||
*/
|
||||
public function getMigrationHelper() {
|
||||
return $this->migrationHelper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the Database Connection is still open
|
||||
*/
|
||||
public function checkConnection() {
|
||||
if (!$this->getMysqli()
|
||||
|| !$this->getMysqli()->ping()
|
||||
) {
|
||||
$this->maniaControl->quit('The MySQL Server has gone away!', true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Destruct Database Connection
|
||||
*/
|
||||
public function __destruct() {
|
||||
if ($this->getMysqli() && !$this->getMysqli()->connect_error) {
|
||||
$this->getMysqli()->close();
|
||||
}
|
||||
}
|
||||
}
|
65
core/Database/MigrationHelper.php
Normal file
65
core/Database/MigrationHelper.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Database;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Settings\SettingManager;
|
||||
use ManiaControl\Utils\ClassUtil;
|
||||
|
||||
/**
|
||||
* Database Migration Assistant
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MigrationHelper {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new migration helper instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer the Settings of the given Class to a new One
|
||||
*
|
||||
* @param mixed $sourceClass
|
||||
* @param mixed $targetClass
|
||||
* @return bool
|
||||
*/
|
||||
public function transferSettings($sourceClass, $targetClass) {
|
||||
$sourceClass = ClassUtil::getClass($sourceClass);
|
||||
$targetClass = ClassUtil::getClass($targetClass);
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
|
||||
$query = "INSERT IGNORE INTO `" . SettingManager::TABLE_SETTINGS . "`
|
||||
(`class`, `setting`, `type`, `value`, `default`)
|
||||
SELECT ?, `setting`, `type`, `value`, `default`
|
||||
FROM `" . SettingManager::TABLE_SETTINGS . "`
|
||||
WHERE `class` = ?;";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$statement->bind_param('ss', $targetClass, $sourceClass);
|
||||
$success = $statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
$statement->close();
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return $success;
|
||||
}
|
||||
}
|
476
core/ErrorHandler.php
Normal file
476
core/ErrorHandler.php
Normal file
@ -0,0 +1,476 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl;
|
||||
|
||||
use ManiaControl\Plugins\PluginManager;
|
||||
use ManiaControl\Update\UpdateManager;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use ManiaControl\Utils\WebReader;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\TransportException;
|
||||
|
||||
/**
|
||||
* Error and Exception Manager Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ErrorHandler {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const MC_DEBUG_NOTICE = 'ManiaControl.DebugNotice';
|
||||
const SETTING_RESTART_ON_EXCEPTION = 'Automatically restart on Exceptions';
|
||||
const LOG_SUPPRESSED_ERRORS = false;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $handlingError = null;
|
||||
|
||||
/**
|
||||
* Construct a new error handler instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
set_error_handler(array(&$this, 'handleError'), -1);
|
||||
set_exception_handler(array(&$this, 'handleException'));
|
||||
register_shutdown_function(array(&$this, 'handleShutdown'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize error handler features
|
||||
*/
|
||||
public function init() {
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_RESTART_ON_EXCEPTION, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a Debug Notice to the ManiaControl Website
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function triggerDebugNotice($message) {
|
||||
$this->handleError(self::MC_DEBUG_NOTICE, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* ManiaControl Error Handler
|
||||
*
|
||||
* @param int $errorNumber
|
||||
* @param string $errorString
|
||||
* @param string $errorFile
|
||||
* @param int $errorLine
|
||||
* @param array $errorContext
|
||||
* @param bool $onShutdown
|
||||
* @return bool
|
||||
*/
|
||||
public function handleError($errorNumber, $errorString, $errorFile = null, $errorLine = -1, array $errorContext = array(), $onShutdown = false) {
|
||||
$suppressed = (error_reporting() === 0);
|
||||
if ($suppressed && !self::LOG_SUPPRESSED_ERRORS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$this->handlingError) {
|
||||
// Reset error handler for safety
|
||||
$this->handlingError = true;
|
||||
set_error_handler(array(&$this, 'handleError'), -1);
|
||||
}
|
||||
|
||||
// Build log message
|
||||
$errorTag = $this->getErrorTag($errorNumber);
|
||||
$isUserError = self::isUserErrorNumber($errorNumber);
|
||||
$isFatalError = self::isFatalError($errorNumber);
|
||||
|
||||
$traceString = null;
|
||||
$sourceClass = null;
|
||||
$traceSourceClass = null;
|
||||
$fileLine = null;
|
||||
|
||||
$message = $errorTag . ': ' . $errorString;
|
||||
if (!$onShutdown) {
|
||||
$traceString = $this->parseBackTrace(array_slice(debug_backtrace(), 1), $traceSourceClass);
|
||||
}
|
||||
if ($errorFile) {
|
||||
$fileLine = $errorFile . ': ' . $errorLine;
|
||||
$sourceClass = $this->getSourceClass($errorFile);
|
||||
}
|
||||
if (!$sourceClass && $traceSourceClass) {
|
||||
$sourceClass = $traceSourceClass;
|
||||
}
|
||||
|
||||
$logMessage = $message . PHP_EOL . 'File&Line: ' . $fileLine;
|
||||
if (!$isUserError && $traceString) {
|
||||
$logMessage .= PHP_EOL . 'Trace: ' . PHP_EOL . $traceString;
|
||||
}
|
||||
Logger::log($logMessage);
|
||||
|
||||
if (!DEV_MODE && !$isUserError && !$suppressed) {
|
||||
// Report error
|
||||
$report = array();
|
||||
$report['Type'] = 'Error';
|
||||
$report['Message'] = $message;
|
||||
if ($fileLine) {
|
||||
$report['FileLine'] = self::stripBaseDir($fileLine);
|
||||
}
|
||||
if ($sourceClass) {
|
||||
$report['SourceClass'] = $sourceClass;
|
||||
$pluginId = PluginManager::getPluginId($sourceClass);
|
||||
if ($pluginId > 0) {
|
||||
$report['PluginId'] = $pluginId;
|
||||
if ($isFatalError) {
|
||||
$this->maniaControl->getPluginManager()->deactivatePlugin($sourceClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($traceString) {
|
||||
$report['Backtrace'] = $traceString;
|
||||
}
|
||||
$report['OperatingSystem'] = php_uname();
|
||||
$report['PHPVersion'] = phpversion();
|
||||
|
||||
if ($this->maniaControl->getServer()) {
|
||||
$report['ServerLogin'] = $this->maniaControl->getServer()->login;
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getSettingManager() && $this->maniaControl->getUpdateManager()) {
|
||||
$report['UpdateChannel'] = $this->maniaControl->getSettingManager()->getSettingValue($this->maniaControl->getUpdateManager(), UpdateManager::SETTING_UPDATECHECK_CHANNEL);
|
||||
$report['ManiaControlVersion'] = ManiaControl::VERSION . ' ' . $this->maniaControl->getUpdateManager()->getBuildDate();
|
||||
} else {
|
||||
$report['ManiaControlVersion'] = ManiaControl::VERSION;
|
||||
}
|
||||
|
||||
$json = json_encode(Formatter::utf8($report));
|
||||
$info = base64_encode($json);
|
||||
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'errorreport?error=' . urlencode($info);
|
||||
$response = WebReader::getUrl($url);
|
||||
$content = $response->getContent();
|
||||
$success = json_decode($content);
|
||||
if ($success) {
|
||||
Logger::log('Error-Report successful!');
|
||||
} else {
|
||||
Logger::log('Error-Report failed! ' . print_r($content, true));
|
||||
}
|
||||
}
|
||||
|
||||
if ($isFatalError) {
|
||||
$this->maniaControl->quit('Quitting ManiaControl after Fatal Error.');
|
||||
}
|
||||
|
||||
// Disable safety state
|
||||
$this->handlingError = false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Prefix for the given Error Level
|
||||
*
|
||||
* @param int $errorLevel
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorTag($errorLevel) {
|
||||
switch ($errorLevel) {
|
||||
case E_ERROR:
|
||||
return '[PHP ERROR]';
|
||||
case E_WARNING:
|
||||
return '[PHP WARNING]';
|
||||
case E_PARSE:
|
||||
return '[PHP PARSE ERROR]';
|
||||
case E_NOTICE:
|
||||
return '[PHP NOTICE]';
|
||||
case E_CORE_ERROR:
|
||||
return '[PHP CORE ERROR]';
|
||||
case E_COMPILE_ERROR:
|
||||
return '[PHP COMPILE ERROR]';
|
||||
case E_USER_ERROR:
|
||||
return '[ManiaControl ERROR]';
|
||||
case E_USER_WARNING:
|
||||
return '[ManiaControl WARNING]';
|
||||
case E_USER_NOTICE:
|
||||
return '[ManiaControl NOTICE]';
|
||||
case E_RECOVERABLE_ERROR:
|
||||
return '[PHP RECOVERABLE ERROR]';
|
||||
case self::MC_DEBUG_NOTICE:
|
||||
return '[ManiaControl DEBUG]';
|
||||
}
|
||||
return "[PHP ERROR '{$errorLevel}']";
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Error Number is a User Error
|
||||
*
|
||||
* @param int $errorNumber
|
||||
* @return bool
|
||||
*/
|
||||
private static function isUserErrorNumber($errorNumber) {
|
||||
return ($errorNumber & E_USER_ERROR || $errorNumber & E_USER_WARNING || $errorNumber & E_USER_NOTICE
|
||||
|| $errorNumber & E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether the given Error Number represents a Fatal Error
|
||||
*
|
||||
* @param int $errorNumber
|
||||
* @return bool
|
||||
*/
|
||||
public static function isFatalError($errorNumber) {
|
||||
$fatalError = (E_ERROR | E_PARSE | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR);
|
||||
return ($errorNumber & $fatalError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the Debug Backtrace into a String for the Error Report
|
||||
*
|
||||
* @param array $backtrace
|
||||
* @param string $sourceClass
|
||||
* @return string
|
||||
*/
|
||||
private function parseBackTrace(array $backtrace, &$sourceClass = null) {
|
||||
$traceString = '';
|
||||
$stepCount = 0;
|
||||
foreach ($backtrace as $traceStep) {
|
||||
$skipStep = $this->shouldSkipTraceStep($traceStep);
|
||||
$traceString .= '#' . $stepCount . ': ';
|
||||
if (isset($traceStep['class'])) {
|
||||
if (!$sourceClass && !$skipStep && !$this->isIgnoredSourceClass($traceStep['class'])) {
|
||||
$sourceClass = $traceStep['class'];
|
||||
}
|
||||
$traceString .= $traceStep['class'];
|
||||
}
|
||||
if (isset($traceStep['type'])) {
|
||||
$traceString .= $traceStep['type'];
|
||||
}
|
||||
if (isset($traceStep['function'])) {
|
||||
$traceString .= $traceStep['function'] . '(';
|
||||
if (isset($traceStep['args']) && !$skipStep) {
|
||||
$traceString .= $this->parseArgumentsArray($traceStep['args']);
|
||||
}
|
||||
$traceString .= ')';
|
||||
}
|
||||
if (isset($traceStep['file']) && !$skipStep) {
|
||||
$traceString .= ' in File ';
|
||||
$traceString .= self::stripBaseDir($traceStep['file']);
|
||||
}
|
||||
if (isset($traceStep['line']) && !$skipStep) {
|
||||
$traceString .= ' on Line ';
|
||||
$traceString .= $traceStep['line'];
|
||||
}
|
||||
$traceString .= PHP_EOL;
|
||||
if (strlen($traceString) > 2500) {
|
||||
// Too long...
|
||||
$traceString .= '...';
|
||||
break;
|
||||
}
|
||||
$stepCount++;
|
||||
}
|
||||
return $traceString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Trace Step should be skipped
|
||||
*
|
||||
* @param array $traceStep
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldSkipTraceStep(array $traceStep) {
|
||||
if (isset($traceStep['class'])) {
|
||||
$skippedClasses = array('Symfony\\Component\\EventDispatcher\\EventDispatcher', 'cURL\\Request');
|
||||
foreach ($skippedClasses as $skippedClass) {
|
||||
if ($traceStep['class'] === $skippedClass) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($traceStep['file'])) {
|
||||
$skippedFiles = array('Symfony', 'curl-easy');
|
||||
foreach ($skippedFiles as $skippedFile) {
|
||||
if (strpos($traceStep['file'], $skippedFile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Class Name should be ignored as possible Error Source Class
|
||||
*
|
||||
* @param string $class
|
||||
* @return bool
|
||||
*/
|
||||
private function isIgnoredSourceClass($class) {
|
||||
$ignoredClasses = array('Maniaplanet\\', '\\ErrorHandler');
|
||||
foreach ($ignoredClasses as $ignoredClass) {
|
||||
if (strpos($class, $ignoredClass) !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a string from an arguments array
|
||||
*
|
||||
* @param array $args
|
||||
* @return string
|
||||
*/
|
||||
private function parseArgumentsArray(array $args) {
|
||||
$string = '';
|
||||
$argsCount = count($args);
|
||||
foreach ($args as $index => $arg) {
|
||||
if (is_object($arg)) {
|
||||
$string .= 'object(' . get_class($arg) . ')';
|
||||
} else if (is_array($arg)) {
|
||||
$string .= 'array(' . $this->parseArgumentsArray($arg) . ')';
|
||||
} else {
|
||||
$type = gettype($arg);
|
||||
$string .= $type . '(';
|
||||
if (is_string($arg)) {
|
||||
$param = $arg;
|
||||
if (strlen($param) > 40) {
|
||||
$param = substr($param, 0, 40) . '..';
|
||||
}
|
||||
$string .= print_r($param, true);
|
||||
} else {
|
||||
$string .= print_r($arg, true);
|
||||
}
|
||||
$string .= ')';
|
||||
}
|
||||
if ($index < $argsCount - 1) {
|
||||
$string .= ', ';
|
||||
}
|
||||
if (strlen($string) > 150) {
|
||||
// Too long...
|
||||
$string .= '...';
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip the ManiaControl path from the given path to ensure privacy
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
private static function stripBaseDir($path) {
|
||||
return str_replace(MANIACONTROL_PATH, '', $path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the source class via the error file
|
||||
*
|
||||
* @param string $errorFile
|
||||
* @return string
|
||||
*/
|
||||
private function getSourceClass($errorFile) {
|
||||
if (!$errorFile) {
|
||||
return null;
|
||||
}
|
||||
$filePath = substr($errorFile, strlen(MANIACONTROL_PATH));
|
||||
$filePath = str_replace('plugins' . DIRECTORY_SEPARATOR, '', $filePath);
|
||||
$filePath = str_replace('core' . DIRECTORY_SEPARATOR, 'ManiaControl\\', $filePath);
|
||||
$className = str_replace('.php', '', $filePath);
|
||||
$className = str_replace(DIRECTORY_SEPARATOR, '\\', $className);
|
||||
if (!class_exists($className, false)) {
|
||||
return null;
|
||||
}
|
||||
return $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PHP Process Shutdown
|
||||
*/
|
||||
public function handleShutdown() {
|
||||
// Check if the Shutdown was caused by a Fatal Error and report it
|
||||
$error = error_get_last();
|
||||
if ($error && self::isFatalError($error['type'])) {
|
||||
$this->handleError($error['type'], $error['message'], $error['file'], $error['line'], array(), true);
|
||||
}
|
||||
|
||||
$this->maniaControl->quit('Quitting ManiaControl!');
|
||||
}
|
||||
|
||||
/**
|
||||
* ManiaControl Exception Handler
|
||||
*
|
||||
* @param \Exception $exception
|
||||
* @param bool $shutdown
|
||||
*/
|
||||
public function handleException(\Exception $exception, $shutdown = true) {
|
||||
$message = "[ManiaControl EXCEPTION]: {$exception->getMessage()}";
|
||||
|
||||
$exceptionClass = get_class($exception);
|
||||
$sourceClass = null;
|
||||
$traceString = $this->parseBackTrace($exception->getTrace(), $sourceClass);
|
||||
|
||||
$logMessage = $message . PHP_EOL . 'Class: ' . $exceptionClass . PHP_EOL . 'Trace:' . PHP_EOL . $traceString;
|
||||
Logger::log($logMessage);
|
||||
|
||||
if (!DEV_MODE) {
|
||||
$report = array();
|
||||
$report['Type'] = 'Exception';
|
||||
$report['Message'] = $message;
|
||||
$report['Class'] = $exceptionClass;
|
||||
$report['FileLine'] = self::stripBaseDir($exception->getFile()) . ': ' . $exception->getLine();
|
||||
$report['SourceClass'] = $sourceClass;
|
||||
$report['PluginId'] = PluginManager::getPluginId($sourceClass);
|
||||
$report['Backtrace'] = $traceString;
|
||||
$report['OperatingSystem'] = php_uname();
|
||||
$report['PHPVersion'] = phpversion();
|
||||
|
||||
if ($server = $this->maniaControl->getServer()) {
|
||||
$report['ServerLogin'] = $server->login;
|
||||
}
|
||||
|
||||
if (($settingManager = $this->maniaControl->getSettingManager()) && ($updateManager = $this->maniaControl->getUpdateManager())) {
|
||||
$report['UpdateChannel'] = $settingManager->getSettingValue($updateManager, $updateManager::SETTING_UPDATECHECK_CHANNEL);
|
||||
$report['ManiaControlVersion'] = ManiaControl::VERSION . ' #' . $updateManager->getBuildDate();
|
||||
} else {
|
||||
$report['ManiaControlVersion'] = ManiaControl::VERSION;
|
||||
}
|
||||
|
||||
$errorReport = json_encode(Formatter::utf8($report));
|
||||
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'errorreport';
|
||||
$response = WebReader::postUrl($url, $errorReport);
|
||||
$content = $response->getContent();
|
||||
$success = json_decode($content);
|
||||
if ($success) {
|
||||
Logger::log('Exception successfully reported!');
|
||||
} else {
|
||||
Logger::log('Exception-Report failed! ' . print_r($content, true));
|
||||
}
|
||||
}
|
||||
|
||||
if ($shutdown) {
|
||||
if ($this->shouldRestart()) {
|
||||
$this->maniaControl->restart();
|
||||
}
|
||||
try {
|
||||
$this->maniaControl->quit('Quitting ManiaControl after Exception.');
|
||||
} catch (TransportException $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if ManiaControl should restart automatically
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function shouldRestart() {
|
||||
if (!$this->maniaControl || !$this->maniaControl->getSettingManager() || DEV_MODE) {
|
||||
return false;
|
||||
}
|
||||
$setting = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_RESTART_ON_EXCEPTION, true);
|
||||
return $setting;
|
||||
}
|
||||
}
|
196
core/Files/AsynchronousFileReader.php
Normal file
196
core/Files/AsynchronousFileReader.php
Normal file
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Files;
|
||||
|
||||
use cURL\Event;
|
||||
use cURL\Request;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Asynchronous File Reader
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class AsynchronousFileReader {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CONTENT_TYPE_JSON = 'application/json';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var Request[] $requests */
|
||||
private $requests = array();
|
||||
|
||||
/**
|
||||
* Construct a new Asynchronous File Reader Instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
}
|
||||
|
||||
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
|
||||
->set(CURLOPT_RETURNTRANSFER, true); // return instead of output content
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append available Data of active Requests
|
||||
*/
|
||||
public function appendData() {
|
||||
foreach ($this->requests as $key => $request) {
|
||||
if ($request->socketPerform()) {
|
||||
$request->socketSelect();
|
||||
} else {
|
||||
unset($this->requests[$key]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a Remote File
|
||||
*
|
||||
* @param string $url
|
||||
* @param callable $function
|
||||
* @param string $contentType
|
||||
* @param int $keepAlive
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @param string $url
|
||||
* @param callable $function
|
||||
* @param string $content
|
||||
* @param bool $compression
|
||||
* @param string $contentType
|
||||
*/
|
||||
public function postData($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 = $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);
|
||||
}
|
||||
}
|
131
core/Files/BackupUtil.php
Normal file
131
core/Files/BackupUtil.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Files;
|
||||
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Backup Utility Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class BackupUtil {
|
||||
|
||||
/**
|
||||
* Perform a Full Backup of ManiaControl
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function performFullBackup() {
|
||||
$backupFolder = self::getBackupFolder();
|
||||
if (!$backupFolder) {
|
||||
return false;
|
||||
}
|
||||
$backupFileName = $backupFolder . 'backup_' . ManiaControl::VERSION . '_' . date('y-m-d_H-i') . '_' . time() . '.zip';
|
||||
$backupZip = new \ZipArchive();
|
||||
if ($backupZip->open($backupFileName, \ZipArchive::CREATE) !== true) {
|
||||
Logger::logError("Couldn't create backup zip!");
|
||||
return false;
|
||||
}
|
||||
$excludes = array();
|
||||
$baseFileNames = array('configs', 'core', 'plugins', 'ManiaControl.php');
|
||||
$pathInfo = pathInfo(MANIACONTROL_PATH);
|
||||
$parentPath = $pathInfo['dirname'] . DIRECTORY_SEPARATOR;
|
||||
$dirName = $pathInfo['basename'];
|
||||
$backupZip->addEmptyDir($dirName);
|
||||
self::zipDirectory($backupZip, MANIACONTROL_PATH, strlen($parentPath), $excludes, $baseFileNames);
|
||||
return $backupZip->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Backup Folder Path and create it if necessary
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
private static function getBackupFolder() {
|
||||
$backupFolder = MANIACONTROL_PATH . 'backup' . DIRECTORY_SEPARATOR;
|
||||
if (!is_dir($backupFolder) && !mkdir($backupFolder)) {
|
||||
Logger::logError("Couldn't create backup folder!");
|
||||
return false;
|
||||
}
|
||||
if (!is_writeable($backupFolder)) {
|
||||
Logger::logError("ManiaControl doesn't have the necessary write rights for the backup folder!");
|
||||
return false;
|
||||
}
|
||||
return $backupFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Directory to the ZipArchive
|
||||
*
|
||||
* @param \ZipArchive $zipArchive
|
||||
* @param string $folderName
|
||||
* @param int $prefixLength
|
||||
* @param array $excludes
|
||||
* @param array $baseFileNames
|
||||
* @return bool
|
||||
*/
|
||||
private static function zipDirectory(\ZipArchive &$zipArchive, $folderName, $prefixLength, array $excludes = array(), array $baseFileNames = array()) {
|
||||
$folderHandle = opendir($folderName);
|
||||
if (!is_resource($folderHandle)) {
|
||||
Logger::logError("Couldn't open folder '{$folderName}' for backup!");
|
||||
return false;
|
||||
}
|
||||
$useBaseFileNames = !empty($baseFileNames);
|
||||
while (false !== ($file = readdir($folderHandle))) {
|
||||
if (substr($file, 0, 1) === '.') {
|
||||
// Skip such .files
|
||||
continue;
|
||||
}
|
||||
if (in_array($file, $excludes)) {
|
||||
// Excluded
|
||||
continue;
|
||||
}
|
||||
if ($useBaseFileNames && !in_array($file, $baseFileNames)) {
|
||||
// Not one of the base files
|
||||
continue;
|
||||
}
|
||||
$filePath = $folderName . DIRECTORY_SEPARATOR . $file;
|
||||
$localPath = substr($filePath, $prefixLength);
|
||||
if (is_file($filePath)) {
|
||||
$zipArchive->addFile($filePath, $localPath);
|
||||
continue;
|
||||
}
|
||||
if (is_dir($filePath)) {
|
||||
$zipArchive->addEmptyDir($localPath);
|
||||
self::zipDirectory($zipArchive, $filePath, $prefixLength, $excludes);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
closedir($folderHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a Backup of the Plugins
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function performPluginsBackup() {
|
||||
$backupFolder = self::getBackupFolder();
|
||||
if (!$backupFolder) {
|
||||
return false;
|
||||
}
|
||||
$backupFileName = $backupFolder . 'backup_plugins_' . ManiaControl::VERSION . date('y-m-d_H-i') . '_' . time() . '.zip';
|
||||
$backupZip = new \ZipArchive();
|
||||
if ($backupZip->open($backupFileName, \ZipArchive::CREATE) !== true) {
|
||||
Logger::logError("Couldn't create backup zip!");
|
||||
return false;
|
||||
}
|
||||
$directory = MANIACONTROL_PATH . 'plugins';
|
||||
$pathInfo = pathInfo($directory);
|
||||
$parentPath = $pathInfo['dirname'] . DIRECTORY_SEPARATOR;
|
||||
$dirName = $pathInfo['basename'];
|
||||
$backupZip->addEmptyDir($dirName);
|
||||
self::zipDirectory($backupZip, $directory, strlen($parentPath));
|
||||
return $backupZip->close();
|
||||
}
|
||||
}
|
210
core/Files/FileUtil.php
Normal file
210
core/Files/FileUtil.php
Normal file
@ -0,0 +1,210 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Files;
|
||||
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use ManiaControl\Utils\WebReader;
|
||||
|
||||
/**
|
||||
* Files Utility Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class FileUtil {
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \ManiaControl\Utils\WebReader::loadUrl()
|
||||
*/
|
||||
public static function loadFile($url) {
|
||||
$response = WebReader::getUrl($url);
|
||||
return $response->getContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load Config XML File
|
||||
*
|
||||
* @param string $fileName
|
||||
* @return \SimpleXMLElement
|
||||
*/
|
||||
public static function loadConfig($fileName) {
|
||||
$fileLocation = MANIACONTROL_PATH . 'configs' . DIRECTORY_SEPARATOR . $fileName;
|
||||
if (!file_exists($fileLocation)) {
|
||||
Logger::log("Config file doesn't exist! ({$fileName})");
|
||||
return null;
|
||||
}
|
||||
if (!is_readable($fileLocation)) {
|
||||
Logger::log("Config file isn't readable! Please check the file permissions. ({$fileName})");
|
||||
return null;
|
||||
}
|
||||
$configXml = @simplexml_load_file($fileLocation);
|
||||
if (!$configXml) {
|
||||
Logger::log("Config file isn't maintained properly! ({$fileName})");
|
||||
return null;
|
||||
}
|
||||
return $configXml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return file name cleared from special characters
|
||||
*
|
||||
* @param string $fileName
|
||||
* @return string
|
||||
*/
|
||||
public static function getClearedFileName($fileName) {
|
||||
$fileName = Formatter::stripCodes($fileName);
|
||||
$fileName = Formatter::utf8($fileName);
|
||||
$fileName = preg_replace('/[^0-9A-Za-z\-\+\.\_\ ]/', null, $fileName);
|
||||
$fileName = preg_replace('/ /', '_', $fileName);
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the temporary folder if it's empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteTempFolder() {
|
||||
return self::deleteFolder(self::getTempFolder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given folder if it's empty
|
||||
*
|
||||
* @param string $folderPath
|
||||
* @param bool $onlyIfEmpty
|
||||
* @return bool
|
||||
*/
|
||||
public static function deleteFolder($folderPath, $onlyIfEmpty = true) {
|
||||
if ($onlyIfEmpty && !self::isFolderEmpty($folderPath)) {
|
||||
return false;
|
||||
}
|
||||
return rmdir($folderPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given folder is empty
|
||||
*
|
||||
* @param string $folderPath
|
||||
* @return bool
|
||||
*/
|
||||
public static function isFolderEmpty($folderPath) {
|
||||
if (!is_readable($folderPath) || !is_dir($folderPath)) {
|
||||
return false;
|
||||
}
|
||||
$files = scandir($folderPath);
|
||||
return (count($files) <= 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the temporary folder and create it if necessary
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public static function getTempFolder() {
|
||||
$tempFolder = MANIACONTROL_PATH . 'temp' . DIRECTORY_SEPARATOR;
|
||||
if (!is_dir($tempFolder) && !mkdir($tempFolder)) {
|
||||
trigger_error("Couldn't create the temp folder!");
|
||||
return false;
|
||||
}
|
||||
if (!is_writeable($tempFolder)) {
|
||||
trigger_error("ManiaControl doesn't have the necessary write rights for the temp folder!");
|
||||
return false;
|
||||
}
|
||||
return $tempFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if ManiaControl has sufficient Access to write to Files in the given Directories
|
||||
*
|
||||
* @param mixed $directories
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkWritePermissions($directories) {
|
||||
if (!is_array($directories)) {
|
||||
$directories = array($directories);
|
||||
}
|
||||
foreach ($directories as $directory) {
|
||||
$dir = new \RecursiveDirectoryIterator(MANIACONTROL_PATH . $directory);
|
||||
foreach (new \RecursiveIteratorIterator($dir) as $fileName => $file) {
|
||||
if (substr($fileName, 0, 1) === '.') {
|
||||
continue;
|
||||
}
|
||||
if (!is_writable($fileName)) {
|
||||
Logger::log("Write access missing for file '{$fileName}'!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the given directory by deleting old files
|
||||
*
|
||||
* @param string $directory
|
||||
* @param float $maxFileAgeInDays
|
||||
* @param bool $recursive
|
||||
* @return bool
|
||||
*/
|
||||
public static function cleanDirectory($directory, $maxFileAgeInDays = 10., $recursive = false) {
|
||||
if (!$directory || !is_dir($directory) || !is_readable($directory)) {
|
||||
return false;
|
||||
}
|
||||
$dirHandle = opendir($directory);
|
||||
if (!is_resource($dirHandle)) {
|
||||
return false;
|
||||
}
|
||||
$directory = self::appendDirectorySeparator($directory);
|
||||
$time = time();
|
||||
while ($fileName = readdir($dirHandle)) {
|
||||
$filePath = $directory . $fileName;
|
||||
if (!is_readable($filePath)) {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($filePath) && $recursive) {
|
||||
// Directory
|
||||
self::cleanDirectory($filePath . DIRECTORY_SEPARATOR, $maxFileAgeInDays, $recursive);
|
||||
} else if (is_file($filePath)) {
|
||||
// File
|
||||
if (!is_writable($filePath)) {
|
||||
continue;
|
||||
}
|
||||
$fileModTime = filemtime($filePath);
|
||||
$timeDeltaDays = ($time - $fileModTime) / (24. * 3600.);
|
||||
if ($timeDeltaDays > $maxFileAgeInDays) {
|
||||
unlink($filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dirHandle);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append the directory separator to the given path if necessary
|
||||
*
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
public static function appendDirectorySeparator($path) {
|
||||
if (substr($path, -1, 1) !== DIRECTORY_SEPARATOR) {
|
||||
$path .= DIRECTORY_SEPARATOR;
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given file name is a PHP file
|
||||
*
|
||||
* @param string $fileName
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPhpFileName($fileName) {
|
||||
$extension = substr($fileName, -4);
|
||||
return (strtolower($extension) === '.php');
|
||||
}
|
||||
}
|
134
core/Logger.php
Normal file
134
core/Logger.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl;
|
||||
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* ManiaControl Logger Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class Logger {
|
||||
|
||||
/**
|
||||
* Setup the logging mechanism
|
||||
*/
|
||||
public static function setup() {
|
||||
self::setupErrorLogFileName();
|
||||
self::cleanLogsFolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the error log file name
|
||||
*/
|
||||
private static function setupErrorLogFileName() {
|
||||
$logsFolder = self::getLogsFolder();
|
||||
if ($logsFolder) {
|
||||
$logFileName = $logsFolder . 'ManiaControl';
|
||||
if (!defined('LOG_NAME_USE_DATE') || LOG_NAME_USE_DATE) {
|
||||
$logFileName .= '_' . date('Y-m-d');
|
||||
}
|
||||
if (!defined('LOG_NAME_USE_PID') || LOG_NAME_USE_PID) {
|
||||
$logFileName .= '_' . getmypid();
|
||||
}
|
||||
$logFileName .= '.log';
|
||||
ini_set('error_log', $logFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the logs folder and create it if necessary
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getLogsFolder() {
|
||||
$logsFolder = MANIACONTROL_PATH . 'logs' . DIRECTORY_SEPARATOR;
|
||||
if (!is_dir($logsFolder) && !mkdir($logsFolder)) {
|
||||
self::logError("Couldn't create the logs folder!");
|
||||
return null;
|
||||
}
|
||||
if (!is_writeable($logsFolder)) {
|
||||
self::logError("ManiaControl doesn't have the necessary write rights for the logs folder!");
|
||||
return null;
|
||||
}
|
||||
return $logsFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete old ManiaControl log files
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function cleanLogsFolder() {
|
||||
$logsFolderPath = self::getLogsFolder();
|
||||
return FileUtil::cleanDirectory($logsFolderPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log and output the given Error message
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $stripCodes
|
||||
* @param bool $eol
|
||||
*/
|
||||
public static function logError($message, $stripCodes = false, $eol = true) {
|
||||
$message = '[ERROR] ' . $message;
|
||||
self::log($message, $stripCodes, $eol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log and output the given message
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $stripCodes
|
||||
* @param bool $eol
|
||||
*/
|
||||
public static function log($message, $stripCodes = false, $eol = true) {
|
||||
if ($stripCodes) {
|
||||
$message = Formatter::stripCodes($message);
|
||||
}
|
||||
error_log($message);
|
||||
self::output($message, $eol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Echo the given message
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $eol
|
||||
*/
|
||||
private static function output($message, $eol = true) {
|
||||
if ($eol) {
|
||||
$message = '[' . date('d-M-Y H:i:s e') . '] ' . $message . PHP_EOL;
|
||||
}
|
||||
echo $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log and output the given Info message
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $stripCodes
|
||||
* @param bool $eol
|
||||
*/
|
||||
public static function logInfo($message, $stripCodes = false, $eol = true) {
|
||||
$message = '[INFO] ' . $message;
|
||||
self::log($message, $stripCodes, $eol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log and output the given Warning message
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $stripCodes
|
||||
* @param bool $eol
|
||||
*/
|
||||
public static function logWarning($message, $stripCodes = false, $eol = true) {
|
||||
$message = '[WARNING] ' . $message;
|
||||
self::log($message, $stripCodes, $eol);
|
||||
}
|
||||
}
|
636
core/ManiaControl.php
Normal file
636
core/ManiaControl.php
Normal file
@ -0,0 +1,636 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl;
|
||||
|
||||
use ManiaControl\Admin\ActionsMenu;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Bills\BillManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Callbacks\TimerManager;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Commands\CommandManager;
|
||||
use ManiaControl\Configurator\Configurator;
|
||||
use ManiaControl\Database\Database;
|
||||
use ManiaControl\Files\AsynchronousFileReader;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Maps\MapManager;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
use ManiaControl\Plugins\PluginManager;
|
||||
use ManiaControl\Server\Server;
|
||||
use ManiaControl\Settings\SettingManager;
|
||||
use ManiaControl\Statistics\StatisticManager;
|
||||
use ManiaControl\Update\UpdateManager;
|
||||
use ManiaControl\Utils\CommandLineHelper;
|
||||
use ManiaControl\Utils\SystemUtil;
|
||||
use Maniaplanet\DedicatedServer\Connection;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\AuthenticationException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\TransportException;
|
||||
|
||||
/**
|
||||
* ManiaControl Server Controller for ManiaPlanet Server
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ManiaControl implements CallbackListener, CommandListener, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const VERSION = '0.154';
|
||||
const API_VERSION = '2013-04-16';
|
||||
const MIN_DEDIVERSION = '2014-04-02_18_00';
|
||||
const SCRIPT_TIMEOUT = 10;
|
||||
const URL_WEBSERVICE = 'http://ws.maniacontrol.com/';
|
||||
const SETTING_PERMISSION_SHUTDOWN = 'Shutdown ManiaControl';
|
||||
const SETTING_PERMISSION_RESTART = 'Restart ManiaControl';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var ActionsMenu $actionsMenu
|
||||
* @deprecated see getActionsMenu()
|
||||
*/
|
||||
public $actionsMenu = null;
|
||||
/** @var AuthenticationManager $authenticationManager
|
||||
* @deprecated see getAuthenticationManager()
|
||||
*/
|
||||
public $authenticationManager = null;
|
||||
/** @var CallbackManager $callbackManager
|
||||
* @deprecated see getCallbackManager()
|
||||
*/
|
||||
public $callbackManager = null;
|
||||
/** @var Chat $chat
|
||||
* @deprecated see getChat()
|
||||
*/
|
||||
public $chat = null;
|
||||
/** @var \SimpleXMLElement $config
|
||||
* @deprecated see getConfig()
|
||||
*/
|
||||
public $config = null;
|
||||
/** @var Configurator $configurator
|
||||
* @deprecated see getConfigurator()
|
||||
*/
|
||||
public $configurator = null;
|
||||
/** @var Connection $client
|
||||
* @deprecated see getClient()
|
||||
*/
|
||||
public $client = null;
|
||||
/** @var CommandManager $commandManager
|
||||
* @deprecated see getCommandManager()
|
||||
*/
|
||||
public $commandManager = null;
|
||||
/** @var Database $database
|
||||
* @deprecated see getDatabase()
|
||||
*/
|
||||
public $database = null;
|
||||
/** @var ManialinkManager $manialinkManager
|
||||
* @deprecated see getManialinkManager
|
||||
*/
|
||||
public $manialinkManager = null;
|
||||
/** @var MapManager $mapManager
|
||||
* @deprecated see getMapManager()
|
||||
*/
|
||||
public $mapManager = null;
|
||||
/** @var PlayerManager $playerManager
|
||||
* @deprecated see getPlayerManager()
|
||||
*/
|
||||
public $playerManager = null;
|
||||
/** @var PluginManager $pluginManager
|
||||
* @deprecated see getPluginManager()
|
||||
*/
|
||||
public $pluginManager = null;
|
||||
/** @var Server $server
|
||||
* @deprecated see getServer()
|
||||
*/
|
||||
public $server = null;
|
||||
/** @var SettingManager $settingManager
|
||||
* @deprecated see getSettingManager()
|
||||
*/
|
||||
public $settingManager = null;
|
||||
/** @var StatisticManager $statisticManager
|
||||
* @deprecated see getStatisticManager()
|
||||
*/
|
||||
public $statisticManager = null;
|
||||
/** @var UpdateManager $updateManager
|
||||
* @deprecated see getUpdateManager()
|
||||
*/
|
||||
public $updateManager = null;
|
||||
/** @var ErrorHandler $errorHandler
|
||||
* @deprecated see getErrorHandler()
|
||||
*/
|
||||
public $errorHandler = null;
|
||||
/** @var TimerManager $timerManager
|
||||
* @deprecated see getTimerManager()
|
||||
*/
|
||||
public $timerManager = null;
|
||||
/** @var AsynchronousFileReader $fileReader
|
||||
* @deprecated see getFileReader()
|
||||
*/
|
||||
public $fileReader = null;
|
||||
/** @var BillManager $billManager
|
||||
* @deprecated see getBillManager()
|
||||
*/
|
||||
public $billManager = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
private $requestQuitMessage = null;
|
||||
|
||||
/**
|
||||
* Construct a new ManiaControl instance
|
||||
*/
|
||||
public function __construct() {
|
||||
Logger::log('Loading ManiaControl v' . self::VERSION . ' ...');
|
||||
|
||||
$this->errorHandler = new ErrorHandler($this);
|
||||
|
||||
$this->loadConfig();
|
||||
|
||||
// Load ManiaControl Modules
|
||||
$this->callbackManager = new CallbackManager($this);
|
||||
$this->timerManager = new TimerManager($this);
|
||||
$this->database = new Database($this);
|
||||
$this->fileReader = new AsynchronousFileReader($this);
|
||||
$this->billManager = new BillManager($this);
|
||||
$this->settingManager = new SettingManager($this);
|
||||
$this->statisticManager = new StatisticManager($this);
|
||||
$this->manialinkManager = new ManialinkManager($this);
|
||||
$this->actionsMenu = new ActionsMenu($this);
|
||||
$this->chat = new Chat($this);
|
||||
$this->commandManager = new CommandManager($this);
|
||||
$this->server = new Server($this);
|
||||
$this->authenticationManager = new AuthenticationManager($this);
|
||||
$this->playerManager = new PlayerManager($this);
|
||||
$this->mapManager = new MapManager($this);
|
||||
$this->configurator = new Configurator($this);
|
||||
$this->pluginManager = new PluginManager($this);
|
||||
$this->updateManager = new UpdateManager($this);
|
||||
|
||||
$this->getErrorHandler()->init();
|
||||
|
||||
// Permissions
|
||||
$this->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_SHUTDOWN, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
$this->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_RESTART, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
|
||||
// Commands
|
||||
$this->getCommandManager()->registerCommandListener('version', $this, 'commandVersion', false, 'Shows ManiaControl version.');
|
||||
$this->getCommandManager()->registerCommandListener('restart', $this, 'commandRestart', true, 'Restarts ManiaControl.');
|
||||
$this->getCommandManager()->registerCommandListener('shutdown', $this, 'commandShutdown', true, 'Shuts ManiaControl down.');
|
||||
|
||||
// Check connection every 30 seconds
|
||||
$this->getTimerManager()->registerTimerListening($this, 'checkConnection', 1000 * 30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the Config XML-File
|
||||
*/
|
||||
private function loadConfig() {
|
||||
$configId = CommandLineHelper::getParameter('-config');
|
||||
$configFileName = ($configId ? $configId : 'server.xml');
|
||||
$config = FileUtil::loadConfig($configFileName);
|
||||
if (!$config) {
|
||||
$this->quit("Error loading Configuration XML-File! ('{$configFileName}')", true);
|
||||
}
|
||||
if ($config->count() < 3) {
|
||||
$this->quit("Your Configuration File ('{$configFileName}') doesn't seem to be maintained properly. Please check it again!", true);
|
||||
}
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Quit ManiaControl and log the given message
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $errorPrefix
|
||||
*/
|
||||
public function quit($message = null, $errorPrefix = false) {
|
||||
if ($this->getClient()) {
|
||||
if ($this->getCallbackManager()) {
|
||||
// OnShutdown callback
|
||||
$this->getCallbackManager()->triggerCallback(Callbacks::ONSHUTDOWN);
|
||||
}
|
||||
|
||||
if ($chat = $this->getChat()) {
|
||||
// Announce quit
|
||||
try {
|
||||
$chat->sendInformation('ManiaControl shutting down.');
|
||||
} catch (TransportException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
// Hide UI
|
||||
try {
|
||||
$this->getClient()->sendHideManialinkPage();
|
||||
} catch (TransportException $e) {
|
||||
}
|
||||
|
||||
// Delete client
|
||||
Connection::delete($this->getClient());
|
||||
$this->client = null;
|
||||
}
|
||||
|
||||
SystemUtil::quit($message, $errorPrefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the client
|
||||
*
|
||||
* @return Connection
|
||||
*/
|
||||
public function getClient() {
|
||||
return $this->client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the callback manager
|
||||
*
|
||||
* @return CallbackManager
|
||||
*/
|
||||
public function getCallbackManager() {
|
||||
return $this->callbackManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the chat
|
||||
*
|
||||
* @return Chat
|
||||
*/
|
||||
public function getChat() {
|
||||
return $this->chat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the error handler
|
||||
*
|
||||
* @return ErrorHandler
|
||||
*/
|
||||
public function getErrorHandler() {
|
||||
return $this->errorHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the authentication manager
|
||||
*
|
||||
* @return AuthenticationManager
|
||||
*/
|
||||
public function getAuthenticationManager() {
|
||||
return $this->authenticationManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the command manager
|
||||
*
|
||||
* @return CommandManager
|
||||
*/
|
||||
public function getCommandManager() {
|
||||
return $this->commandManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timer manager
|
||||
*
|
||||
* @return TimerManager
|
||||
*/
|
||||
public function getTimerManager() {
|
||||
return $this->timerManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a message to console and log
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $stripCodes
|
||||
* @deprecated
|
||||
* @see Logger::log()
|
||||
*/
|
||||
public function log($message, $stripCodes = false) {
|
||||
Logger::log($message, $stripCodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the actions menu
|
||||
*
|
||||
* @return ActionsMenu
|
||||
*/
|
||||
public function getActionsMenu() {
|
||||
return $this->actionsMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the config
|
||||
*
|
||||
* @return \SimpleXMLElement
|
||||
*/
|
||||
public function getConfig() {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configurator
|
||||
*
|
||||
* @return Configurator
|
||||
*/
|
||||
public function getConfigurator() {
|
||||
return $this->configurator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the database
|
||||
*
|
||||
* @return Database
|
||||
*/
|
||||
public function getDatabase() {
|
||||
return $this->database;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the manialink manager
|
||||
*
|
||||
* @return ManialinkManager
|
||||
*/
|
||||
public function getManialinkManager() {
|
||||
return $this->manialinkManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map manager
|
||||
*
|
||||
* @return MapManager
|
||||
*/
|
||||
public function getMapManager() {
|
||||
return $this->mapManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the player manager
|
||||
*
|
||||
* @return PlayerManager
|
||||
*/
|
||||
public function getPlayerManager() {
|
||||
return $this->playerManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the setting manager
|
||||
*
|
||||
* @return SettingManager
|
||||
*/
|
||||
public function getSettingManager() {
|
||||
return $this->settingManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the statistic manager
|
||||
*
|
||||
* @return StatisticManager
|
||||
*/
|
||||
public function getStatisticManager() {
|
||||
return $this->statisticManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the bill manager
|
||||
*
|
||||
* @return BillManager
|
||||
*/
|
||||
public function getBillManager() {
|
||||
return $this->billManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check connection
|
||||
*/
|
||||
public function checkConnection() {
|
||||
if ($this->getClient()->getIdleTime() > 180) {
|
||||
$this->getClient()->getServerName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Version Command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandVersion(array $chatCallback, Player $player) {
|
||||
$message = 'This server is using ManiaControl v' . ManiaControl::VERSION . '!';
|
||||
$this->getChat()->sendInformation($message, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Restart AdminCommand
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandRestart(array $chatCallback, Player $player) {
|
||||
if (!$this->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_RESTART)) {
|
||||
$this->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$this->restart("ManiaControl Restart requested by '{$player->login}'!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart ManiaControl
|
||||
*
|
||||
* @param string $message
|
||||
*/
|
||||
public function restart($message = null) {
|
||||
// Announce restart
|
||||
try {
|
||||
$this->getChat()->sendInformation('Restarting ManiaControl...');
|
||||
} catch (TransportException $e) {
|
||||
}
|
||||
Logger::log('Restarting ManiaControl... ' . $message);
|
||||
|
||||
// Start new instance
|
||||
SystemUtil::restart();
|
||||
|
||||
// Quit old instance
|
||||
$this->quit('Quitting ManiaControl to restart.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Shutdown Command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandShutdown(array $chat, Player $player) {
|
||||
if (!$this->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SHUTDOWN)) {
|
||||
$this->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$this->requestQuit("ManiaControl Shutdown requested by '{$player->login}'!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Request ManiaControl to quit
|
||||
*
|
||||
* @param mixed $message
|
||||
*/
|
||||
public function requestQuit($message = true) {
|
||||
$this->requestQuitMessage = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run ManiaControl
|
||||
*/
|
||||
public function run() {
|
||||
Logger::log('Starting ManiaControl v' . self::VERSION . '!');
|
||||
|
||||
try {
|
||||
// Connect to server
|
||||
$this->connect();
|
||||
|
||||
// Check if the version of the server is high enough
|
||||
$version = $this->getClient()->getVersion();
|
||||
if ($version->build < self::MIN_DEDIVERSION) {
|
||||
$this->quit("The Server has Version '{$version->build}', while at least '" . self::MIN_DEDIVERSION . "' is required!", true);
|
||||
}
|
||||
|
||||
// Listen for shutdown
|
||||
$this->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_SERVERSTOP, $this, 'handleServerStopCallback');
|
||||
|
||||
// OnInit callback
|
||||
$this->getCallbackManager()->triggerCallback(Callbacks::ONINIT);
|
||||
|
||||
// Load plugins
|
||||
$this->getPluginManager()->loadPlugins();
|
||||
$this->getUpdateManager()->getPluginUpdateManager()->checkPluginsUpdate();
|
||||
|
||||
// AfterInit callback
|
||||
$this->getCallbackManager()->triggerCallback(Callbacks::AFTERINIT);
|
||||
|
||||
// Loading finished
|
||||
Logger::log('Loading completed!');
|
||||
Logger::log('Link: ' . $this->getServer()->getJoinLink());
|
||||
$this->getChat()->sendInformation('ManiaControl v' . self::VERSION . ' successfully started!');
|
||||
|
||||
// Main loop
|
||||
while (!$this->requestQuitMessage) {
|
||||
$this->loop();
|
||||
}
|
||||
|
||||
// Shutdown
|
||||
$this->quit($this->requestQuitMessage);
|
||||
|
||||
} catch (TransportException $exception) {
|
||||
Logger::logError('Connection interrupted!');
|
||||
$this->getErrorHandler()->handleException($exception);
|
||||
SystemUtil::quit($exception->getMessage(), true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to ManiaPlanet server
|
||||
*/
|
||||
private function connect() {
|
||||
// Load remote client
|
||||
$serverConfig = $this->getServer()->loadConfig();
|
||||
|
||||
Logger::log("Connecting to Server at {$serverConfig->host}:{$serverConfig->port}...");
|
||||
|
||||
try {
|
||||
$this->client = Connection::factory($serverConfig->host, $serverConfig->port, self::SCRIPT_TIMEOUT, $serverConfig->user, $serverConfig->pass, self::API_VERSION);
|
||||
} catch (TransportException $exception) {
|
||||
$message = "Couldn't connect to the server: '{$exception->getMessage()}'";
|
||||
$this->quit($message, true);
|
||||
} catch (AuthenticationException $exception) {
|
||||
$message = "Couldn't authenticate on Server with User '{$serverConfig->user}' & Pass '{$serverConfig->pass}'! " . $exception->getMessage();
|
||||
$this->quit($message, true);
|
||||
}
|
||||
|
||||
// Enable callback system
|
||||
$this->getClient()->enableCallbacks(true);
|
||||
|
||||
// Wait for server to be ready
|
||||
if (!$this->getServer()->waitForStatus(4)) {
|
||||
$this->quit("Server couldn't get ready!");
|
||||
}
|
||||
|
||||
// Connect finished
|
||||
Logger::log('Server Connection successfully established!');
|
||||
|
||||
// Hide old widgets
|
||||
$this->getClient()->sendHideManialinkPage();
|
||||
|
||||
// Enable script callbacks
|
||||
$this->getServer()->getScriptManager()->enableScriptCallbacks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server
|
||||
*
|
||||
* @return Server
|
||||
*/
|
||||
public function getServer() {
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the plugin manager
|
||||
*
|
||||
* @return PluginManager
|
||||
*/
|
||||
public function getPluginManager() {
|
||||
return $this->pluginManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the update manager
|
||||
*
|
||||
* @return UpdateManager
|
||||
*/
|
||||
public function getUpdateManager() {
|
||||
return $this->updateManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the Main Loop
|
||||
*/
|
||||
private function loop() {
|
||||
$loopStart = microtime(true);
|
||||
|
||||
// Extend script timeout
|
||||
set_time_limit(self::SCRIPT_TIMEOUT);
|
||||
|
||||
// Manage callbacks
|
||||
$this->getCallbackManager()->manageCallbacks();
|
||||
|
||||
// Manage async file reader
|
||||
$this->getFileReader()->appendData();
|
||||
|
||||
// Yield for next tick
|
||||
$loopEnd = microtime(true);
|
||||
$loopDuration = $loopEnd - $loopStart;
|
||||
$sleepTime = (int)(2500 - $loopDuration * 1000000);
|
||||
if ($sleepTime > 0) {
|
||||
usleep($sleepTime);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the file reader
|
||||
*
|
||||
* @return AsynchronousFileReader
|
||||
*/
|
||||
public function getFileReader() {
|
||||
return $this->fileReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Server Stop Callback
|
||||
*/
|
||||
public function handleServerStopCallback() {
|
||||
$this->requestQuit('The Server has been shut down!');
|
||||
}
|
||||
}
|
117
core/ManiaExchange/MXMapInfo.php
Normal file
117
core/ManiaExchange/MXMapInfo.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\ManiaExchange;
|
||||
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* Mania Exchange Map Info Object
|
||||
*
|
||||
* @author Xymph
|
||||
* @updated kremsy <kremsy@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MXMapInfo {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $prefix, $id, $uid, $name, $userid, $author, $uploaded, $updated, $type, $maptype;
|
||||
public $titlepack, $style, $envir, $mood, $dispcost, $lightmap, $modname, $exever;
|
||||
public $exebld, $routes, $length, $unlimiter, $laps, $difficulty, $lbrating, $trkvalue;
|
||||
public $replaytyp, $replayid, $replaycnt, $authorComment, $commentCount, $awards;
|
||||
public $pageurl, $replayurl, $imageurl, $thumburl, $downloadurl, $dir;
|
||||
public $ratingVoteCount, $ratingVoteAverage, $vehicleName;
|
||||
|
||||
/**
|
||||
* Returns map object with all available data from MX map data
|
||||
*
|
||||
* @param String $prefix MX URL prefix
|
||||
* @param $mx
|
||||
* @return MXMapInfo
|
||||
*/
|
||||
public function __construct($prefix, $mx) {
|
||||
$this->prefix = $prefix;
|
||||
|
||||
if (!$mx) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->prefix === 'tm') {
|
||||
$this->dir = 'tracks';
|
||||
$this->id = $mx->TrackID;
|
||||
$this->uid = isset($mx->TrackUID) ? $mx->TrackUID : '';
|
||||
} else {
|
||||
$this->dir = 'maps';
|
||||
$this->id = $mx->MapID;
|
||||
$this->uid = isset($mx->MapUID) ? $mx->MapUID : '';
|
||||
}
|
||||
|
||||
if (!isset($mx->GbxMapName) || $mx->GbxMapName === '?') {
|
||||
$this->name = $mx->Name;
|
||||
} else {
|
||||
$this->name = Formatter::stripDirtyCodes($mx->GbxMapName);
|
||||
}
|
||||
|
||||
$this->userid = $mx->UserID;
|
||||
$this->author = $mx->Username;
|
||||
$this->uploaded = $mx->UploadedAt;
|
||||
$this->updated = $mx->UpdatedAt;
|
||||
$this->type = $mx->TypeName;
|
||||
$this->maptype = isset($mx->MapType) ? $mx->MapType : '';
|
||||
$this->titlepack = isset($mx->TitlePack) ? $mx->TitlePack : '';
|
||||
$this->style = isset($mx->StyleName) ? $mx->StyleName : '';
|
||||
$this->envir = $mx->EnvironmentName;
|
||||
$this->mood = $mx->Mood;
|
||||
$this->dispcost = $mx->DisplayCost;
|
||||
$this->lightmap = $mx->Lightmap;
|
||||
$this->modname = isset($mx->ModName) ? $mx->ModName : '';
|
||||
$this->exever = $mx->ExeVersion;
|
||||
$this->exebld = $mx->ExeBuild;
|
||||
$this->routes = isset($mx->RouteName) ? $mx->RouteName : '';
|
||||
$this->length = isset($mx->LengthName) ? $mx->LengthName : '';
|
||||
$this->unlimiter = isset($mx->UnlimiterRequired) ? $mx->UnlimiterRequired : false;
|
||||
$this->laps = isset($mx->Laps) ? $mx->Laps : 0;
|
||||
$this->difficulty = $mx->DifficultyName;
|
||||
$this->lbrating = isset($mx->LBRating) ? $mx->LBRating : 0;
|
||||
$this->trkvalue = isset($mx->TrackValue) ? $mx->TrackValue : 0;
|
||||
$this->replaytyp = isset($mx->ReplayTypeName) ? $mx->ReplayTypeName : '';
|
||||
$this->replayid = isset($mx->ReplayWRID) ? $mx->ReplayWRID : 0;
|
||||
$this->replaycnt = isset($mx->ReplayCount) ? $mx->ReplayCount : 0;
|
||||
$this->awards = isset($mx->AwardCount) ? $mx->AwardCount : 0;
|
||||
$this->vehicleName = isset($mx->VehicleName) ? $mx->VehicleName : '';
|
||||
|
||||
$this->authorComment = $mx->Comments;
|
||||
$this->commentCount = $mx->CommentCount;
|
||||
|
||||
$this->ratingVoteCount = isset($mx->RatingVoteCount) ? $mx->RatingVoteCount : 0;
|
||||
$this->ratingVoteAverage = isset($mx->RatingVoteAverage) ? $mx->RatingVoteAverage : 0;
|
||||
|
||||
if (!$this->trkvalue && $this->lbrating > 0) {
|
||||
$this->trkvalue = $this->lbrating;
|
||||
} elseif (!$this->lbrating && $this->trkvalue > 0) {
|
||||
$this->lbrating = $this->trkvalue;
|
||||
}
|
||||
|
||||
$this->pageurl = 'http://' . $this->prefix . '.mania-exchange.com/' . $this->dir . '/view/' . $this->id;
|
||||
$this->downloadurl = 'http://' . $this->prefix . '.mania-exchange.com/' . $this->dir . '/download/' . $this->id;
|
||||
|
||||
if ($mx->HasScreenshot) {
|
||||
$this->imageurl = 'http://' . $this->prefix . '.mania-exchange.com/' . $this->dir . '/screenshot/normal/' . $this->id;
|
||||
} else {
|
||||
$this->imageurl = '';
|
||||
}
|
||||
|
||||
if ($mx->HasThumbnail) {
|
||||
$this->thumburl = 'http://' . $this->prefix . '.mania-exchange.com/' . $this->dir . '/screenshot/small/' . $this->id;
|
||||
} else {
|
||||
$this->thumburl = '';
|
||||
}
|
||||
|
||||
if ($this->prefix === 'tm' && $this->replayid > 0) {
|
||||
$this->replayurl = 'http://' . $this->prefix . '.mania-exchange.com/replays/download/' . $this->replayid;
|
||||
} else {
|
||||
$this->replayurl = '';
|
||||
}
|
||||
}
|
||||
}
|
356
core/ManiaExchange/ManiaExchangeList.php
Normal file
356
core/ManiaExchange/ManiaExchangeList.php
Normal file
@ -0,0 +1,356 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\ManiaExchange;
|
||||
|
||||
use FML\Controls\Entry;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Gauge;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Button;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\ManiaLink;
|
||||
use FML\Script\Features\Paging;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\IconManager;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Maps\MapCommands;
|
||||
use ManiaControl\Maps\MapManager;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Utils\ColorUtil;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* ManiaExchange List Widget Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_ADD_MAP = 'ManiaExchangeList.AddMap';
|
||||
const ACTION_SEARCH_MAPNAME = 'ManiaExchangeList.SearchMapName';
|
||||
const ACTION_SEARCH_AUTHOR = 'ManiaExchangeList.SearchAuthor';
|
||||
const ACTION_GET_MAPS_FROM_AUTHOR = 'ManiaExchangeList.GetMapsFromAuthor';
|
||||
const MAX_MX_MAPS_PER_PAGE = 14;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $mapListShown = array();
|
||||
|
||||
/**
|
||||
* Construct a new MX List instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_CLOSED, $this, 'closeWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_OPENED, $this, 'handleWidgetOpened');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SEARCH_MAPNAME, $this, 'showList');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SEARCH_AUTHOR, $this, 'showList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManialinkPageAnswer Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$actionArray = explode('.', $actionId);
|
||||
if (count($actionArray) <= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = $actionArray[0] . '.' . $actionArray[1];
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
$mapId = (int)$actionArray[2];
|
||||
|
||||
switch ($action) {
|
||||
case self::ACTION_GET_MAPS_FROM_AUTHOR:
|
||||
$callback[1][2] = 'auth:' . $actionArray[2];
|
||||
$this->showList($callback, $player);
|
||||
break;
|
||||
case self::ACTION_ADD_MAP:
|
||||
$this->maniaControl->getMapManager()->addMapFromMx($mapId, $player->login);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the List
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function showList(array $chatCallback, Player $player) {
|
||||
$this->mapListShown[$player->login] = true;
|
||||
$params = explode(' ', $chatCallback[1][2]);
|
||||
$searchString = '';
|
||||
$author = '';
|
||||
$environment = '';
|
||||
if (count($params) >= 1) {
|
||||
foreach ($params as $param) {
|
||||
if ($param === '/xlist' || $param === MapCommands::ACTION_OPEN_XLIST) {
|
||||
continue;
|
||||
}
|
||||
if ($param === self::ACTION_SEARCH_MAPNAME) {
|
||||
$searchString = $chatCallback[1][3][0]['Value'];
|
||||
} else if ($param === self::ACTION_SEARCH_AUTHOR) {
|
||||
$author = $chatCallback[1][3][0]['Value'];
|
||||
} else if (strtolower(substr($param, 0, 5)) === 'auth:') {
|
||||
$author = substr($param, 5);
|
||||
} else if (strtolower(substr($param, 0, 4)) === 'env:') {
|
||||
$environment = substr($param, 4);
|
||||
} else {
|
||||
if (!$searchString) {
|
||||
$searchString = $param;
|
||||
} else {
|
||||
// concatenate words in name
|
||||
$searchString .= '%20' . $param;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// search for matching maps
|
||||
$this->maniaControl->getMapManager()->getMXManager()->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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the Mania Exchange List
|
||||
*
|
||||
* @param MXMapInfo[] $maps
|
||||
* @param Player $player
|
||||
* @internal param array $chatCallback
|
||||
*/
|
||||
private function showManiaExchangeList(array $maps, Player $player) {
|
||||
// Start offsets
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
$posX = -$width / 2;
|
||||
$posY = $height / 2;
|
||||
|
||||
//Create ManiaLink
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$script = $maniaLink->getScript();
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
|
||||
// Main frame
|
||||
$frame = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultListFrame($script, $paging);
|
||||
$maniaLink->add($frame);
|
||||
|
||||
//Predefine description Label
|
||||
$descriptionLabel = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultDescriptionLabel();
|
||||
$frame->add($descriptionLabel);
|
||||
|
||||
// Headline
|
||||
$headFrame = new Frame();
|
||||
$frame->add($headFrame);
|
||||
$headFrame->setY($posY - 12);
|
||||
$array = array('$oId' => $posX + 3.5, '$oName' => $posX + 12.5, '$oAuthor' => $posX + 59, '$oKarma' => $posX + 85, '$oType' => $posX + 103, '$oMood' => $posX + 118, '$oLast Update' => $posX + 130);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $array);
|
||||
|
||||
$index = 0;
|
||||
$posY = $height / 2 - 16;
|
||||
$pageFrame = null;
|
||||
|
||||
foreach ($maps as $map) {
|
||||
//TODO order possibilities
|
||||
if ($index % self::MAX_MX_MAPS_PER_PAGE === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$posY = $height / 2 - 16;
|
||||
$paging->addPage($pageFrame);
|
||||
}
|
||||
|
||||
// Map Frame
|
||||
$mapFrame = new Frame();
|
||||
$pageFrame->add($mapFrame);
|
||||
|
||||
if ($index % 2 === 0) {
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$mapFrame->add($lineQuad);
|
||||
$lineQuad->setSize($width, 4);
|
||||
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$lineQuad->setZ(0.001);
|
||||
}
|
||||
|
||||
$time = Formatter::time_elapsed_string(strtotime($map->updated));
|
||||
$array = array('$s' . $map->id => $posX + 3.5, '$s' . $map->name => $posX + 12.5, '$s' . $map->author => $posX + 59, '$s' . str_replace('Arena', '', $map->maptype) => $posX + 103, '$s' . $map->mood => $posX + 118, '$s' . $time => $posX + 130);
|
||||
$labels = $this->maniaControl->getManialinkManager()->labelLine($mapFrame, $array);
|
||||
$authorLabel = $labels[2];
|
||||
$authorLabel->setAction(self::ACTION_GET_MAPS_FROM_AUTHOR . '.' . $map->author);
|
||||
|
||||
$mapFrame->setY($posY);
|
||||
|
||||
$mxQuad = new Quad();
|
||||
$mapFrame->add($mxQuad);
|
||||
$mxQuad->setSize(3, 3);
|
||||
$mxQuad->setImage($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON));
|
||||
$mxQuad->setImageFocus($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_MOVER));
|
||||
$mxQuad->setX($posX + 56);
|
||||
$mxQuad->setUrl($map->pageurl);
|
||||
$mxQuad->setZ(0.01);
|
||||
$description = 'View $<' . $map->name . '$> on Mania-Exchange';
|
||||
$mxQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)
|
||||
) {
|
||||
$addQuad = new Quad_Icons64x64_1();
|
||||
$mapFrame->add($addQuad);
|
||||
$addQuad->setX($posX + 53);
|
||||
$addQuad->setZ(-0.1);
|
||||
$addQuad->setSubStyle($addQuad::SUBSTYLE_Add);
|
||||
$addQuad->setSize(4, 4);
|
||||
$addQuad->setAction(self::ACTION_ADD_MAP . '.' . $map->id);
|
||||
$addQuad->setZ(0.01);
|
||||
|
||||
$description = 'Add-Map: $<' . $map->name . '$>';
|
||||
$addQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
|
||||
//Award Quad
|
||||
if ($map->awards > 0) {
|
||||
$awardQuad = new Quad_Icons64x64_1();
|
||||
$mapFrame->add($awardQuad);
|
||||
$awardQuad->setSize(3, 3);
|
||||
$awardQuad->setSubStyle($awardQuad::SUBSTYLE_OfficialRace);
|
||||
$awardQuad->setX($posX + 97);
|
||||
$awardQuad->setZ(0.01);
|
||||
|
||||
$awardLabel = new Label_Text();
|
||||
$mapFrame->add($awardLabel);
|
||||
$awardLabel->setX($posX + 98.5);
|
||||
$awardLabel->setHAlign($awardLabel::LEFT);
|
||||
$awardLabel->setText($map->awards);
|
||||
$awardLabel->setTextSize(1.3);
|
||||
}
|
||||
|
||||
//Map Karma
|
||||
$karma = $map->ratingVoteAverage / 100;
|
||||
$voteCount = $map->ratingVoteCount;
|
||||
if (is_numeric($karma) && $voteCount > 0) {
|
||||
$karmaGauge = new Gauge();
|
||||
$mapFrame->add($karmaGauge);
|
||||
$karmaGauge->setZ(2);
|
||||
$karmaGauge->setX($posX + 89);
|
||||
$karmaGauge->setSize(16.5, 9);
|
||||
$karmaGauge->setDrawBg(false);
|
||||
$karma = floatval($karma);
|
||||
$karmaGauge->setRatio($karma + 0.15 - $karma * 0.15);
|
||||
$karmaColor = ColorUtil::floatToStatusColor($karma);
|
||||
$karmaGauge->setColor($karmaColor . '9');
|
||||
|
||||
$karmaLabel = new Label();
|
||||
$mapFrame->add($karmaLabel);
|
||||
$karmaLabel->setZ(2);
|
||||
$karmaLabel->setX($posX + 89);
|
||||
$karmaLabel->setSize(16.5 * 0.9, 5);
|
||||
$karmaLabel->setTextSize(0.9);
|
||||
$karmaLabel->setTextColor('000');
|
||||
$karmaLabel->setText(' ' . round($karma * 100.) . '% (' . $voteCount . ')');
|
||||
}
|
||||
|
||||
|
||||
$posY -= 4;
|
||||
$index++;
|
||||
}
|
||||
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setPosition(-$width / 2 + 5, $height / 2 - 5);
|
||||
$label->setHAlign($label::LEFT);
|
||||
$label->setTextSize(1.3);
|
||||
$label->setText('Search: ');
|
||||
|
||||
$entry = new Entry();
|
||||
$frame->add($entry);
|
||||
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
|
||||
$entry->setHAlign($entry::LEFT);
|
||||
$entry->setPosition(-$width / 2 + 15, $height / 2 - 5);
|
||||
$entry->setTextSize(1);
|
||||
$entry->setSize($width * 0.25, 4);
|
||||
$entry->setName('SearchString');
|
||||
|
||||
|
||||
//Search for Map-Name
|
||||
$label = new Label_Button();
|
||||
$frame->add($label);
|
||||
$label->setPosition(-$width / 2 + 63, $height / 2 - 5);
|
||||
$label->setText('MapName');
|
||||
$label->setTextSize(1.3);
|
||||
|
||||
$quad = new Quad_BgsPlayerCard();
|
||||
$frame->add($quad);
|
||||
$quad->setPosition(-$width / 2 + 63, $height / 2 - 5, 0.01);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_BgPlayerCardBig);
|
||||
$quad->setSize(18, 5);
|
||||
$quad->setAction(self::ACTION_SEARCH_MAPNAME);
|
||||
|
||||
//Search for Author
|
||||
$label = new Label_Button();
|
||||
$frame->add($label);
|
||||
$label->setPosition(-$width / 2 + 82, $height / 2 - 5);
|
||||
$label->setText('Author');
|
||||
$label->setTextSize(1.3);
|
||||
|
||||
$quad = new Quad_BgsPlayerCard();
|
||||
$frame->add($quad);
|
||||
$quad->setPosition(-$width / 2 + 82, $height / 2 - 5, 0.01);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_BgPlayerCardBig);
|
||||
$quad->setSize(18, 5);
|
||||
$quad->setAction(self::ACTION_SEARCH_AUTHOR);
|
||||
|
||||
// render and display xml
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'ManiaExchangeList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the player if he opened another Main Widget
|
||||
*
|
||||
* @param Player $player
|
||||
* @param $openedWidget
|
||||
*/
|
||||
public function handleWidgetOpened(Player $player, $openedWidget) {
|
||||
//unset when another main widget got opened
|
||||
if ($openedWidget !== 'ManiaExchangeList') {
|
||||
unset($this->mapListShown[$player->login]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the widget
|
||||
*
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
* @internal param array $callback
|
||||
*/
|
||||
public function closeWidget(Player $player) {
|
||||
unset($this->mapListShown[$player->login]);
|
||||
}
|
||||
|
||||
}
|
375
core/ManiaExchange/ManiaExchangeManager.php
Normal file
375
core/ManiaExchange/ManiaExchangeManager.php
Normal file
@ -0,0 +1,375 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\ManiaExchange;
|
||||
|
||||
use ManiaControl\Files\AsynchronousFileReader;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Maps\Map;
|
||||
use ManiaControl\Maps\MapManager;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
|
||||
/**
|
||||
* Mania Exchange Info Searcher Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ManiaExchangeManager {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
//Search others
|
||||
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;
|
||||
|
||||
//Maximum Maps per request
|
||||
const MAPS_PER_MX_FETCH = 50;
|
||||
|
||||
const MIN_EXE_BUILD = "2014-04-01_00_00";
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $mxIdUidVector = array();
|
||||
|
||||
/**
|
||||
* Construct map manager
|
||||
*
|
||||
* @param \ManiaControl\ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset Map by Mx Id
|
||||
*
|
||||
* @param int $mxId
|
||||
*/
|
||||
public function unsetMap($mxId) {
|
||||
if (isset($this->mxIdUidVector[$mxId])) {
|
||||
unset($this->mxIdUidVector[$mxId]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Map Information from Mania Exchange
|
||||
*
|
||||
* @param mixed $maps
|
||||
*/
|
||||
public function fetchManiaExchangeMapInformation($maps = null) {
|
||||
if ($maps) {
|
||||
// Fetch Information for a single map
|
||||
$maps = array($maps);
|
||||
} else {
|
||||
// Fetch Information for whole MapList
|
||||
$maps = $this->maniaControl->getMapManager()->getMaps();
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$mapIdString = '';
|
||||
|
||||
// Fetch mx ids
|
||||
$fetchMapQuery = "SELECT `mxid`, `changed` FROM `" . MapManager::TABLE_MAPS . "`
|
||||
WHERE `index` = ?;";
|
||||
$fetchMapStatement = $mysqli->prepare($fetchMapQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return;
|
||||
}
|
||||
|
||||
$index = 0;
|
||||
foreach ($maps as $map) {
|
||||
if (!$map) {
|
||||
// TODO: remove after resolving of error report about "non-object"
|
||||
$this->maniaControl->getErrorHandler()->triggerDebugNotice('Non-Object-Map', $map, $maps);
|
||||
continue;
|
||||
}
|
||||
/** @var Map $map */
|
||||
$fetchMapStatement->bind_param('i', $map->index);
|
||||
$fetchMapStatement->execute();
|
||||
if ($fetchMapStatement->error) {
|
||||
trigger_error($fetchMapStatement->error);
|
||||
continue;
|
||||
}
|
||||
$fetchMapStatement->store_result();
|
||||
$fetchMapStatement->bind_result($mxId, $changed);
|
||||
$fetchMapStatement->fetch();
|
||||
$fetchMapStatement->free_result();
|
||||
|
||||
//Set changed time into the map object
|
||||
$map->lastUpdate = strtotime($changed);
|
||||
|
||||
if ($mxId) {
|
||||
$appendString = $mxId . ',';
|
||||
//Set the mx id to the mxidmapvektor
|
||||
$this->mxIdUidVector[$mxId] = $map->uid;
|
||||
} else {
|
||||
$appendString = $map->uid . ',';
|
||||
}
|
||||
|
||||
$index++;
|
||||
|
||||
//If Max Maplimit is reached, or string gets too long send the request
|
||||
if ($index % self::MAPS_PER_MX_FETCH === 0) {
|
||||
$mapIdString = substr($mapIdString, 0, -1);
|
||||
$this->fetchMaplistByMixedUidIdString($mapIdString);
|
||||
$mapIdString = '';
|
||||
}
|
||||
|
||||
$mapIdString .= $appendString;
|
||||
}
|
||||
|
||||
if ($mapIdString) {
|
||||
$mapIdString = substr($mapIdString, 0, -1);
|
||||
$this->fetchMaplistByMixedUidIdString($mapIdString);
|
||||
}
|
||||
|
||||
$fetchMapStatement->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the whole Map List from MX via mixed Uid and Id Strings
|
||||
*
|
||||
* @param string $string
|
||||
*/
|
||||
public function fetchMaplistByMixedUidIdString($string) {
|
||||
// Get Title Prefix
|
||||
$titlePrefix = $this->maniaControl->getMapManager()->getCurrentMap()->getGame();
|
||||
|
||||
// compile search URL
|
||||
$url = "http://api.mania-exchange.com/{$titlePrefix}/maps/?ids={$string}";
|
||||
|
||||
$this->maniaControl->getFileReader()->loadFile($url, function ($mapInfo, $error) use ($titlePrefix, $url) {
|
||||
if ($error) {
|
||||
trigger_error("Error: '{$error}' for Url '{$url}'");
|
||||
return;
|
||||
}
|
||||
if (!$mapInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mxMapList = json_decode($mapInfo);
|
||||
if ($mxMapList === null) {
|
||||
trigger_error("Can't decode searched JSON Data from Url '{$url}'");
|
||||
return;
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
foreach ($mxMapList as $map) {
|
||||
if ($map) {
|
||||
$mxMapObject = new MXMapInfo($titlePrefix, $map);
|
||||
if ($mxMapObject) {
|
||||
array_push($maps, $mxMapObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->updateMapObjectsWithManiaExchangeIds($maps);
|
||||
}, AsynchronousFileReader::CONTENT_TYPE_JSON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store MX Map Info in the Database and the MX Info in the Map Object
|
||||
*
|
||||
* @param array $mxMapInfos
|
||||
*/
|
||||
public function updateMapObjectsWithManiaExchangeIds(array $mxMapInfos) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
// Save map data
|
||||
$saveMapQuery = "UPDATE `" . MapManager::TABLE_MAPS . "`
|
||||
SET `mxid` = ?
|
||||
WHERE `uid` = ?;";
|
||||
$saveMapStatement = $mysqli->prepare($saveMapQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return;
|
||||
}
|
||||
$saveMapStatement->bind_param('is', $mapMxId, $mapUId);
|
||||
foreach ($mxMapInfos as $mxMapInfo) {
|
||||
/** @var MXMapInfo $mxMapInfo */
|
||||
$mapMxId = $mxMapInfo->id;
|
||||
$mapUId = $mxMapInfo->uid;
|
||||
$saveMapStatement->execute();
|
||||
if ($saveMapStatement->error) {
|
||||
trigger_error($saveMapStatement->error);
|
||||
}
|
||||
|
||||
//Take the uid out of the vector
|
||||
if (isset($this->mxIdUidVector[$mxMapInfo->id])) {
|
||||
$uid = $this->mxIdUidVector[$mxMapInfo->id];
|
||||
} else {
|
||||
$uid = $mxMapInfo->uid;
|
||||
}
|
||||
$map = $this->maniaControl->getMapManager()->getMapByUid($uid);
|
||||
if ($map) {
|
||||
// TODO: how does it come that $map can be empty here? we got an error report for that
|
||||
/** @var Map $map */
|
||||
$map->mx = $mxMapInfo;
|
||||
}
|
||||
}
|
||||
$saveMapStatement->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \ManiaControl\ManiaExchange\ManiaExchangeManager::fetchMaplistByMixedUidIdString()
|
||||
*/
|
||||
public function getMaplistByMixedUidIdString($string) {
|
||||
$this->fetchMaplistByMixedUidIdString($string);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch Map Info asynchronously
|
||||
*
|
||||
* @param int $mapId
|
||||
* @param callable $function
|
||||
*/
|
||||
public function fetchMapInfo($mapId, callable $function) {
|
||||
// Get Title Prefix
|
||||
$titlePrefix = $this->maniaControl->getMapManager()->getCurrentMap()->getGame();
|
||||
|
||||
// compile search URL
|
||||
$url = 'http://api.mania-exchange.com/' . $titlePrefix . '/maps/?ids=' . $mapId;
|
||||
|
||||
$this->maniaControl->getFileReader()->loadFile($url, function ($mapInfo, $error) use (&$function, $titlePrefix, $url) {
|
||||
$mxMapInfo = null;
|
||||
if ($error) {
|
||||
trigger_error($error);
|
||||
} else {
|
||||
$mxMapList = json_decode($mapInfo);
|
||||
if (!is_array($mxMapList)) {
|
||||
trigger_error('Cannot decode searched JSON data from ' . $url);
|
||||
} else if (!empty($mxMapList)) {
|
||||
$mxMapInfo = new MXMapInfo($titlePrefix, $mxMapList[0]);
|
||||
}
|
||||
}
|
||||
call_user_func($function, $mxMapInfo);
|
||||
}, AsynchronousFileReader::CONTENT_TYPE_JSON);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see \ManiaControl\ManiaExchange\ManiaExchangeManager::fetchMapsAsync()
|
||||
*/
|
||||
public function getMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $searchOrder = self::SEARCH_ORDER_UPDATED_NEWEST) {
|
||||
$this->fetchMapsAsync($function, $name, $author, $env, $maxMapsReturned, $searchOrder);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a MapList Asynchronously
|
||||
*
|
||||
* @param callable $function
|
||||
* @param string $name
|
||||
* @param string $author
|
||||
* @param string $env
|
||||
* @param int $maxMapsReturned
|
||||
* @param int $searchOrder
|
||||
*/
|
||||
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?
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
173
core/Manialinks/CustomUIManager.php
Normal file
173
core/Manialinks/CustomUIManager.php
Normal file
@ -0,0 +1,173 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Manialinks;
|
||||
|
||||
use FML\CustomUI;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
|
||||
/**
|
||||
* Class managing the Custom UI in TrackMania
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class CustomUIManager implements CallbackListener, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CUSTOMUI_MLID = 'CustomUI.MLID';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var customUI $customUI */
|
||||
private $customUI = null;
|
||||
private $updateManialink = false;
|
||||
|
||||
/**
|
||||
* Create a custom UI manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->prepareManialink();
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERCONNECT, $this, 'handlePlayerJoined');
|
||||
$this->maniaControl->getTimerManager()->registerTimerListening($this, 'handle1Second', 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the ManiaLink and CustomUI instances
|
||||
*/
|
||||
private function prepareManialink() {
|
||||
$this->customUI = new CustomUI();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 1 Second Callback
|
||||
*/
|
||||
public function handle1Second() {
|
||||
if (!$this->updateManialink) {
|
||||
return;
|
||||
}
|
||||
$this->updateManialink = false;
|
||||
$this->updateManialink();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the CustomUI Manialink
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function updateManialink(Player $player = null) {
|
||||
if ($player) {
|
||||
$this->maniaControl->getManialinkManager()->sendManialink($this->customUI, $player);
|
||||
return;
|
||||
}
|
||||
$this->maniaControl->getManialinkManager()->sendManialink($this->customUI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PlayerJoined Callback
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handlePlayerJoined(Player $player) {
|
||||
$this->updateManialink($player);
|
||||
|
||||
//TODO: validate necessity
|
||||
//send it again after 500ms
|
||||
$this->maniaControl->getTimerManager()->registerOneTimeListening($this, function () use (&$player) {
|
||||
$this->updateManialink($player);
|
||||
}, 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Showing of Notices
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setNoticeVisible($visible) {
|
||||
$this->customUI->setNoticeVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Showing of the Challenge Info
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setChallengeInfoVisible($visible) {
|
||||
$this->customUI->setChallengeInfoVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Showing of the Net Infos
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setNetInfosVisible($visible) {
|
||||
$this->customUI->setNetInfosVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Showing of the Chat
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setChatVisible($visible) {
|
||||
$this->customUI->setChatVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Showing of the Checkpoint List
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setCheckpointListVisible($visible) {
|
||||
$this->customUI->setCheckpointListVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Showing of Round Scores
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setRoundScoresVisible($visible) {
|
||||
$this->customUI->setRoundScoresVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Showing of the Scoretable
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setScoretableVisible($visible) {
|
||||
$this->customUI->setScoretableVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Global Showing
|
||||
*
|
||||
* @param bool $visible
|
||||
*/
|
||||
public function setGlobalVisible($visible) {
|
||||
$this->customUI->setGlobalVisible($visible);
|
||||
$this->updateManialink = true;
|
||||
}
|
||||
}
|
128
core/Manialinks/IconManager.php
Normal file
128
core/Manialinks/IconManager.php
Normal file
@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Manialinks;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Quad;
|
||||
use FML\ManiaLink;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
|
||||
/**
|
||||
* Class managing Icons
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class IconManager implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const DEFAULT_IMG_URL = 'http://images.maniacontrol.com/icons/';
|
||||
const PRELOAD_MLID = 'IconManager.Preload.MLID';
|
||||
|
||||
/*
|
||||
* Default icons
|
||||
*/
|
||||
const MX_ICON = 'ManiaExchange.png';
|
||||
const MX_ICON_MOVER = 'ManiaExchange_logo_press.png';
|
||||
|
||||
const MX_ICON_GREEN = 'ManiaExchangeGreen.png';
|
||||
const MX_ICON_GREEN_MOVER = 'ManiaExchange_logo_pressGreen.png';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $icons = array();
|
||||
|
||||
/**
|
||||
* Construct a new icon manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->addDefaultIcons();
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERCONNECT, $this, 'handlePlayerConnect');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the set of default icons
|
||||
*/
|
||||
private function addDefaultIcons() {
|
||||
$this->addIcon(self::MX_ICON);
|
||||
$this->addIcon(self::MX_ICON_MOVER);
|
||||
$this->addIcon(self::MX_ICON_GREEN);
|
||||
$this->addIcon(self::MX_ICON_GREEN_MOVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an Icon
|
||||
*
|
||||
* @param string $iconName
|
||||
* @param string $iconLink
|
||||
*/
|
||||
public function addIcon($iconName, $iconLink = self::DEFAULT_IMG_URL) {
|
||||
$this->icons[$iconName] = $iconLink . '/' . $iconName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an Icon by its Name
|
||||
*
|
||||
* @param string $iconName
|
||||
* @return string
|
||||
*/
|
||||
public function getIcon($iconName) {
|
||||
if (!isset($this->icons[$iconName])) {
|
||||
return null;
|
||||
}
|
||||
return $this->icons[$iconName];
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle OnInit Callback
|
||||
*/
|
||||
public function handleAfterInit() {
|
||||
$this->preloadIcons();
|
||||
}
|
||||
|
||||
/**
|
||||
* Preload Icons
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function preloadIcons($player = null) {
|
||||
$maniaLink = new ManiaLink(self::PRELOAD_MLID);
|
||||
$frame = new Frame();
|
||||
$maniaLink->add($frame);
|
||||
$frame->setPosition(500, 500);
|
||||
|
||||
foreach ($this->icons as $iconUrl) {
|
||||
$iconQuad = new Quad();
|
||||
$iconQuad->setImage($iconUrl);
|
||||
$iconQuad->setSize(1, 1);
|
||||
$frame->add($iconQuad);
|
||||
}
|
||||
|
||||
// Send manialink
|
||||
$this->maniaControl->getManialinkManager()->sendManialink($maniaLink, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PlayerConnect Callback
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handlePlayerConnect(Player $player) {
|
||||
$this->preloadIcons($player);
|
||||
}
|
||||
}
|
377
core/Manialinks/ManialinkManager.php
Normal file
377
core/Manialinks/ManialinkManager.php
Normal file
@ -0,0 +1,377 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Manialinks;
|
||||
|
||||
use FML\Controls\Control;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\ManiaLink;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
|
||||
/**
|
||||
* Manialink Manager Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const MAIN_MLID = 'Main.ManiaLinkId';
|
||||
const ACTION_CLOSEWIDGET = 'ManiaLinkManager.CloseWidget';
|
||||
const CB_MAIN_WINDOW_CLOSED = 'ManialinkManagerCallback.MainWindowClosed';
|
||||
const CB_MAIN_WINDOW_OPENED = 'ManialinkManagerCallback.MainWindowOpened';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var StyleManager $styleManager */
|
||||
/** @deprecated see getStyleManager() */
|
||||
public $styleManager = null;
|
||||
/** @var CustomUIManager $customUIManager */
|
||||
/** @deprecated see getCustomUIManager() */
|
||||
public $customUIManager = null;
|
||||
/** @var IconManager $iconManager */
|
||||
/** @deprecated see getIconManager() */
|
||||
public $iconManager = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
// TODO: use listening class
|
||||
private $pageAnswerListeners = array();
|
||||
private $pageAnswerRegexListener = array();
|
||||
|
||||
/**
|
||||
* Construct a new manialink manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Children
|
||||
$this->styleManager = new StyleManager($maniaControl);
|
||||
$this->customUIManager = new CustomUIManager($maniaControl);
|
||||
$this->iconManager = new IconManager($maniaControl);
|
||||
|
||||
// Callbacks
|
||||
$this->registerManialinkPageAnswerListener(self::ACTION_CLOSEWIDGET, $this, 'closeWidgetCallback');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new manialink page answer listener
|
||||
*
|
||||
* @param string $actionId
|
||||
* @param ManialinkPageAnswerListener $listener
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function registerManialinkPageAnswerListener($actionId, ManialinkPageAnswerListener $listener, $method) {
|
||||
if (!method_exists($listener, $method)) {
|
||||
trigger_error("Given listener for actionId '{$actionId}' doesn't have callback method '{$method}'!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!array_key_exists($actionId, $this->pageAnswerListeners) || !is_array($this->pageAnswerListeners[$actionId])) {
|
||||
// Init listeners array
|
||||
$this->pageAnswerListeners[$actionId] = array();
|
||||
}
|
||||
|
||||
// Register page answer listener
|
||||
array_push($this->pageAnswerListeners[$actionId], array($listener, $method));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the style manager
|
||||
*
|
||||
* @return StyleManager
|
||||
*/
|
||||
public function getStyleManager() {
|
||||
return $this->styleManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the custom UI manager
|
||||
*
|
||||
* @return CustomUIManager
|
||||
*/
|
||||
public function getCustomUIManager() {
|
||||
return $this->customUIManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the icon manager
|
||||
*
|
||||
* @return IconManager
|
||||
*/
|
||||
public function getIconManager() {
|
||||
return $this->iconManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new manialink page answer reg ex listener
|
||||
*
|
||||
* @param string $actionIdRegex
|
||||
* @param ManialinkPageAnswerListener $listener
|
||||
* @param string $method
|
||||
* @return bool
|
||||
*/
|
||||
public function registerManialinkPageAnswerRegexListener($actionIdRegex, ManialinkPageAnswerListener $listener, $method) {
|
||||
if (!method_exists($listener, $method)) {
|
||||
trigger_error("Given listener for actionIdRegex '{$actionIdRegex}' doesn't have callback method '{$method}'!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!array_key_exists($actionIdRegex, $this->pageAnswerRegexListener) || !is_array($this->pageAnswerRegexListener[$actionIdRegex])) {
|
||||
// Init regex listeners array
|
||||
$this->pageAnswerRegexListener[$actionIdRegex] = array();
|
||||
}
|
||||
|
||||
// Register page answer regex listener
|
||||
array_push($this->pageAnswerRegexListener[$actionIdRegex], array($listener, $method));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a Manialink Page Answer Listener
|
||||
*
|
||||
* @param ManialinkPageAnswerListener $listener
|
||||
* @return bool
|
||||
*/
|
||||
public function unregisterManialinkPageAnswerListener(ManialinkPageAnswerListener $listener) {
|
||||
$removed = false;
|
||||
$allListeners = array_merge($this->pageAnswerListeners, $this->pageAnswerRegexListener);
|
||||
foreach ($allListeners as &$listeners) {
|
||||
foreach ($listeners as $key => &$listenerCallback) {
|
||||
if ($listenerCallback[0] !== $listener) {
|
||||
continue;
|
||||
}
|
||||
unset($listeners[$key]);
|
||||
$removed = true;
|
||||
}
|
||||
}
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManialinkPageAnswer callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
|
||||
if (array_key_exists($actionId, $this->pageAnswerListeners) && is_array($this->pageAnswerListeners[$actionId])) {
|
||||
// Inform page answer listeners
|
||||
foreach ($this->pageAnswerListeners[$actionId] as $listener) {
|
||||
call_user_func($listener, $callback, $player);
|
||||
}
|
||||
}
|
||||
|
||||
// Check regex listeners
|
||||
foreach ($this->pageAnswerRegexListener as $actionIdRegex => $pageAnswerRegexListeners) {
|
||||
if (preg_match($actionIdRegex, $actionId)) {
|
||||
// Inform page answer regex listeners
|
||||
foreach ($pageAnswerRegexListeners as $listener) {
|
||||
call_user_func($listener, $callback, $player);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a ManiaLink Widget to a certain Player (Should only be used on Main Widgets)
|
||||
*
|
||||
* @param mixed $maniaLink
|
||||
* @param mixed $player
|
||||
* @param string $widgetName
|
||||
*/
|
||||
public function displayWidget($maniaLink, $player, $widgetName = null) {
|
||||
// render and display xml
|
||||
$this->sendManialink($maniaLink, $player);
|
||||
|
||||
if ($widgetName) {
|
||||
// TODO make check by manialinkId, getter is needed to avoid uses on non main widgets
|
||||
$this->disableAltMenu($player);
|
||||
// Trigger callback
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($player);
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAIN_WINDOW_OPENED, $player, $widgetName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send the given manialink to players
|
||||
*
|
||||
* @param string $manialinkText
|
||||
* @param mixed $logins
|
||||
* @param int $timeout
|
||||
* @param bool $hideOnClick
|
||||
* @return bool
|
||||
*/
|
||||
public function sendManialink($manialinkText, $logins = null, $timeout = 0, $hideOnClick = false) {
|
||||
$manialinkText = (string)$manialinkText;
|
||||
|
||||
if (!$manialinkText) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!$logins) {
|
||||
return $this->maniaControl->getClient()->sendDisplayManialinkPage(null, $manialinkText, $timeout, $hideOnClick);
|
||||
}
|
||||
if (is_string($logins)) {
|
||||
$success = $this->maniaControl->getClient()->sendDisplayManialinkPage($logins, $manialinkText, $timeout, $hideOnClick);
|
||||
return $success;
|
||||
}
|
||||
if ($logins instanceof Player) {
|
||||
$success = $this->maniaControl->getClient()->sendDisplayManialinkPage($logins->login, $manialinkText, $timeout, $hideOnClick);
|
||||
return $success;
|
||||
}
|
||||
if (is_array($logins)) {
|
||||
$success = true;
|
||||
foreach ($logins as $login) {
|
||||
$subSuccess = $this->sendManialink($manialinkText, $login, $timeout, $hideOnClick);
|
||||
if (!$subSuccess) {
|
||||
$success = false;
|
||||
}
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
} catch (UnknownPlayerException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the alt menu for the player
|
||||
*
|
||||
* @param mixed $player
|
||||
* @return bool
|
||||
*/
|
||||
public function disableAltMenu($player) {
|
||||
$login = Player::parseLogin($player);
|
||||
try {
|
||||
$success = $this->maniaControl->getClient()->triggerModeScriptEvent('LibXmlRpc_DisableAltMenu', $login);
|
||||
} catch (GameModeException $e) {
|
||||
return false;
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a widget via the callback
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function closeWidgetCallback(array $callback, Player $player) {
|
||||
$this->closeWidget($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a Manialink Widget
|
||||
*
|
||||
* @param mixed $player
|
||||
* @param bool $widgetId
|
||||
*/
|
||||
public function closeWidget($player, $widgetId = false) {
|
||||
if (!$widgetId) {
|
||||
$this->hideManialink(self::MAIN_MLID, $player);
|
||||
$this->enableAltMenu($player);
|
||||
|
||||
// Trigger callback
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($player);
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAIN_WINDOW_CLOSED, $player);
|
||||
} else {
|
||||
$this->hideManialink($widgetId, $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the Manialink with the given Id
|
||||
*
|
||||
* @param mixed $manialinkId
|
||||
* @param mixed $logins
|
||||
*/
|
||||
public function hideManialink($manialinkId, $logins = null) {
|
||||
if (is_array($manialinkId)) {
|
||||
foreach ($manialinkId as $mlId) {
|
||||
$this->hideManialink($mlId, $logins);
|
||||
}
|
||||
} else {
|
||||
$emptyManialink = new ManiaLink($manialinkId);
|
||||
$this->sendManialink($emptyManialink, $logins);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the alt menu for the player
|
||||
*
|
||||
* @param mixed $player
|
||||
* @return bool
|
||||
*/
|
||||
public function enableAltMenu($player) {
|
||||
$login = Player::parseLogin($player);
|
||||
try {
|
||||
$success = $this->maniaControl->getClient()->triggerModeScriptEvent('LibXmlRpc_EnableAltMenu', $login);
|
||||
} catch (GameModeException $e) {
|
||||
return false;
|
||||
}
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a line of labels
|
||||
*
|
||||
* @param Frame $frame
|
||||
* @param array $labelStrings
|
||||
* @param array $properties
|
||||
* @return Label_Text[]
|
||||
*/
|
||||
public function labelLine(Frame $frame, array $labelStrings, array $properties = array()) {
|
||||
// define standard properties
|
||||
$hAlign = (isset($properties['hAlign']) ? $properties['hAlign'] : Control::LEFT);
|
||||
$style = (isset($properties['style']) ? $properties['style'] : Label_Text::STYLE_TextCardSmall);
|
||||
$textSize = (isset($properties['textSize']) ? $properties['textSize'] : 1.5);
|
||||
$textColor = (isset($properties['textColor']) ? $properties['textColor'] : 'FFF');
|
||||
$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);
|
||||
}
|
||||
|
||||
array_push($labels, $label);
|
||||
}
|
||||
|
||||
return $labels;
|
||||
}
|
||||
}
|
13
core/Manialinks/ManialinkPageAnswerListener.php
Normal file
13
core/Manialinks/ManialinkPageAnswerListener.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Manialinks;
|
||||
|
||||
/**
|
||||
* Interface for Manialink Page Answer Listeners
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
interface ManialinkPageAnswerListener {
|
||||
}
|
213
core/Manialinks/StyleManager.php
Normal file
213
core/Manialinks/StyleManager.php
Normal file
@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Manialinks;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_BgRaceScore2;
|
||||
use FML\Controls\Quads\Quad_Bgs1InRace;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Script\Features\Paging;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Class managing default Control Styles
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class StyleManager {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const SETTING_LABEL_DEFAULT_STYLE = 'Default Label Style';
|
||||
const SETTING_QUAD_DEFAULT_STYLE = 'Default Quad Style';
|
||||
const SETTING_QUAD_DEFAULT_SUBSTYLE = 'Default Quad SubStyle';
|
||||
|
||||
const SETTING_MAIN_WIDGET_DEFAULT_STYLE = 'Main Widget Default Quad Style';
|
||||
const SETTING_MAIN_WIDGET_DEFAULT_SUBSTYLE = 'Main Widget Default Quad SubStyle';
|
||||
const SETTING_LIST_WIDGETS_WIDTH = 'List Widgets Width';
|
||||
const SETTING_LIST_WIDGETS_HEIGHT = 'List Widgets Height';
|
||||
|
||||
const SETTING_ICON_DEFAULT_OFFSET_SM = 'Default Icon Offset in ShootMania';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new style manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_LABEL_DEFAULT_STYLE, Label_Text::STYLE_TextTitle1);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_QUAD_DEFAULT_STYLE, Quad_Bgs1InRace::STYLE);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_QUAD_DEFAULT_SUBSTYLE, Quad_Bgs1InRace::SUBSTYLE_BgTitleShadow);
|
||||
|
||||
// Main Widget
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAIN_WIDGET_DEFAULT_STYLE, Quad_BgRaceScore2::STYLE);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAIN_WIDGET_DEFAULT_SUBSTYLE, Quad_BgRaceScore2::SUBSTYLE_HandleSelectable);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_LIST_WIDGETS_WIDTH, 150.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_LIST_WIDGETS_HEIGHT, 80.);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_ICON_DEFAULT_OFFSET_SM, 20.);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default Icon Offset for shootmania
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getDefaultIconOffsetSM() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ICON_DEFAULT_OFFSET_SM);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default label style
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultLabelStyle() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_LABEL_DEFAULT_STYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default quad style
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultQuadStyle() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_QUAD_DEFAULT_STYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default quad substyle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultQuadSubstyle() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_QUAD_DEFAULT_SUBSTYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Default Description Label
|
||||
*
|
||||
* @return \FML\Controls\Label
|
||||
*/
|
||||
public function getDefaultDescriptionLabel() {
|
||||
$width = $this->getListWidgetsWidth();
|
||||
$height = $this->getListWidgetsHeight();
|
||||
|
||||
// Predefine Description Label
|
||||
$descriptionLabel = new Label();
|
||||
$descriptionLabel->setAlign($descriptionLabel::LEFT, $descriptionLabel::TOP)->setPosition($width * -0.5 + 10, $height * -0.5 + 5)->setSize($width * 0.7, 4)->setTextSize(2)->setVisible(false);
|
||||
|
||||
return $descriptionLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Default List Widgets Width
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getListWidgetsWidth() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_LIST_WIDGETS_WIDTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default list widget height
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getListWidgetsHeight() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_LIST_WIDGETS_HEIGHT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the Default List Frame
|
||||
*
|
||||
* @param mixed $script
|
||||
* @param mixed $paging
|
||||
* @return \FML\Controls\Frame
|
||||
*/
|
||||
public function getDefaultListFrame($script = null, $paging = null) {
|
||||
$args = func_get_args();
|
||||
$script = null;
|
||||
$paging = null;
|
||||
foreach ($args as $arg) {
|
||||
if ($arg instanceof Script) {
|
||||
$script = $arg;
|
||||
}
|
||||
if ($arg instanceof Paging) {
|
||||
$paging = $arg;
|
||||
}
|
||||
}
|
||||
|
||||
$width = $this->getListWidgetsWidth();
|
||||
$height = $this->getListWidgetsHeight();
|
||||
$quadStyle = $this->getDefaultMainWindowStyle();
|
||||
$quadSubstyle = $this->getDefaultMainWindowSubStyle();
|
||||
|
||||
// mainframe
|
||||
$frame = new Frame();
|
||||
$frame->setSize($width, $height)->setZ(35); //TODO place before scoreboards
|
||||
|
||||
// Background Quad
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$backgroundQuad->setZ(-2)->setSize($width, $height)->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
// Add Close Quad (X)
|
||||
$closeQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($closeQuad);
|
||||
$closeQuad->setPosition($width * 0.483, $height * 0.467, 3)->setSize(6, 6)->setSubStyle($closeQuad::SUBSTYLE_QuitRace)->setAction(ManialinkManager::ACTION_CLOSEWIDGET);
|
||||
|
||||
if ($script) {
|
||||
$pagerSize = 6.;
|
||||
$pagerPrev = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerPrev);
|
||||
$pagerPrev->setPosition($width * 0.42, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
|
||||
|
||||
$pagerNext = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerNext);
|
||||
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
|
||||
|
||||
$pageCountLabel = new Label_Text();
|
||||
$frame->add($pageCountLabel);
|
||||
$pageCountLabel->setHAlign($pageCountLabel::RIGHT)->setPosition($width * 0.40, $height * -0.44, 1)->setStyle($pageCountLabel::STYLE_TextTitle1)->setTextSize(1.3);
|
||||
|
||||
if ($paging) {
|
||||
$paging->addButton($pagerNext)->addButton($pagerPrev)->setLabel($pageCountLabel);
|
||||
}
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default main window style
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultMainWindowStyle() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MAIN_WIDGET_DEFAULT_STYLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default main window substyle
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultMainWindowSubStyle() {
|
||||
return $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MAIN_WIDGET_DEFAULT_SUBSTYLE);
|
||||
}
|
||||
}
|
392
core/Maps/DirectoryBrowser.php
Normal file
392
core/Maps/DirectoryBrowser.php
Normal file
@ -0,0 +1,392 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use FML\Controls\Quads\Quad_UIConstructionBullet_Buttons;
|
||||
use FML\ManiaLink;
|
||||
use FML\Script\Features\Paging;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\AlreadyInListException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\FileException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\InvalidMapException;
|
||||
|
||||
/**
|
||||
* Maps Directory Browser
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class DirectoryBrowser implements ManialinkPageAnswerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_SHOW = 'MapsDirBrowser.Show';
|
||||
const ACTION_NAVIGATE_UP = 'MapsDirBrowser.NavigateUp';
|
||||
const ACTION_NAVIGATE_ROOT = 'MapsDirBrowser.NavigateRoot';
|
||||
const ACTION_OPEN_FOLDER = 'MapsDirBrowser.OpenFolder.';
|
||||
const ACTION_INSPECT_FILE = 'MapsDirBrowser.InspectFile.';
|
||||
const ACTION_ADD_FILE = 'MapsDirBrowser.AddFile.';
|
||||
const ACTION_ERASE_FILE = 'MapsDirBrowser.EraseFile.';
|
||||
const WIDGET_NAME = 'MapsDirBrowser.Widget';
|
||||
const CACHE_FOLDER_PATH = 'FolderPath';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new directory browser instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// ManiaLink Actions
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SHOW, $this, 'handleActionShow');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_NAVIGATE_UP, $this, 'handleNavigateUp');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_NAVIGATE_ROOT, $this, 'handleNavigateRoot');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_OPEN_FOLDER), $this, 'handleOpenFolder');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_INSPECT_FILE), $this, 'handleInspectFile');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_ADD_FILE), $this, 'handleAddFile');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_ERASE_FILE), $this, 'handleEraseFile');
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the regex to register for the given action
|
||||
*
|
||||
* @param string $actionName
|
||||
* @return string
|
||||
*/
|
||||
private function buildActionRegex($actionName) {
|
||||
return '/' . $actionName . '*/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'Show' action
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleActionShow(array $actionCallback, Player $player) {
|
||||
$this->showManiaLink($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and show the Browser ManiaLink to the given Player
|
||||
*
|
||||
* @param Player $player
|
||||
* @param mixed $nextFolder
|
||||
*/
|
||||
public function showManiaLink(Player $player, $nextFolder = null) {
|
||||
$oldFolderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
|
||||
$isInMapsFolder = false;
|
||||
if (!$oldFolderPath) {
|
||||
$oldFolderPath = $this->maniaControl->getServer()->getDirectory()->getMapsFolder();
|
||||
$isInMapsFolder = true;
|
||||
}
|
||||
$folderPath = $oldFolderPath;
|
||||
if (is_string($nextFolder)) {
|
||||
$newFolderPath = realpath($oldFolderPath . $nextFolder);
|
||||
if ($newFolderPath) {
|
||||
$folderPath = $newFolderPath . DIRECTORY_SEPARATOR;
|
||||
$folderName = basename($newFolderPath);
|
||||
switch ($folderName) {
|
||||
case 'Maps':
|
||||
$mapsDir = dirname($this->maniaControl->getServer()->getDirectory()->getMapsFolder());
|
||||
$folderDir = dirname($folderPath);
|
||||
$isInMapsFolder = ($mapsDir === $folderDir);
|
||||
break;
|
||||
case 'UserData':
|
||||
$dataDir = dirname($this->maniaControl->getServer()->getDirectory()->getGameDataFolder());
|
||||
$folderDir = dirname($folderPath);
|
||||
if ($dataDir === $folderDir) {
|
||||
// Prevent navigation out of maps directory
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
$player->setCache($this, self::CACHE_FOLDER_PATH, $folderPath);
|
||||
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$script = $maniaLink->getScript();
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$frame = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultListFrame($script, $paging);
|
||||
$maniaLink->add($frame);
|
||||
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
$index = 0;
|
||||
$posY = $height / 2 - 10;
|
||||
$pageFrame = null;
|
||||
|
||||
$navigateRootQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($navigateRootQuad);
|
||||
$navigateRootQuad->setPosition($width * -0.47, $height * 0.45)->setSize(4, 4)->setSubStyle($navigateRootQuad::SUBSTYLE_ToolRoot);
|
||||
|
||||
$navigateUpQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($navigateUpQuad);
|
||||
$navigateUpQuad->setPosition($width * -0.44, $height * 0.45)->setSize(4, 4)->setSubStyle($navigateUpQuad::SUBSTYLE_ToolUp);
|
||||
|
||||
if (!$isInMapsFolder) {
|
||||
$navigateRootQuad->setAction(self::ACTION_NAVIGATE_ROOT);
|
||||
$navigateUpQuad->setAction(self::ACTION_NAVIGATE_UP);
|
||||
}
|
||||
|
||||
$directoryLabel = new Label_Text();
|
||||
$frame->add($directoryLabel);
|
||||
$dataFolder = $this->maniaControl->getServer()->getDirectory()->getGameDataFolder();
|
||||
$directoryText = substr($folderPath, strlen($dataFolder));
|
||||
$directoryLabel->setPosition($width * -0.41, $height * 0.45)->setSize($width * 0.85, 4)->setHAlign($directoryLabel::LEFT)->setText($directoryText)->setTextSize(2);
|
||||
|
||||
$tooltipLabel = new Label();
|
||||
$frame->add($tooltipLabel);
|
||||
$tooltipLabel->setPosition($width * -0.48, $height * -0.44)->setSize($width * 0.8, 5)->setHAlign($tooltipLabel::LEFT)->setTextSize(1)->setText('tooltip');
|
||||
|
||||
$mapFiles = $this->scanMapFiles($folderPath);
|
||||
|
||||
if (is_array($mapFiles)) {
|
||||
if (empty($mapFiles)) {
|
||||
$emptyLabel = new Label();
|
||||
$frame->add($emptyLabel);
|
||||
$emptyLabel->setY(20)->setTextColor('aaa')->setText('No files found.')->setTranslate(true);
|
||||
} else {
|
||||
$canAddMaps = $this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP);
|
||||
$canEraseMaps = $this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ERASE_MAP);
|
||||
|
||||
foreach ($mapFiles as $filePath => $fileName) {
|
||||
$shortFilePath = substr($filePath, strlen($folderPath));
|
||||
|
||||
if ($index % 15 === 0) {
|
||||
// New Page
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$posY = $height / 2 - 10;
|
||||
$paging->addPage($pageFrame);
|
||||
}
|
||||
|
||||
// Map Frame
|
||||
$mapFrame = new Frame();
|
||||
$pageFrame->add($mapFrame);
|
||||
$mapFrame->setY($posY);
|
||||
|
||||
if ($index % 2 === 0) {
|
||||
// Striped background line
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$mapFrame->add($lineQuad);
|
||||
$lineQuad->setZ(-1)->setSize($width, 4)->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
}
|
||||
|
||||
// File name Label
|
||||
$nameLabel = new Label_Text();
|
||||
$mapFrame->add($nameLabel);
|
||||
$nameLabel->setX($width * -0.48)->setSize($width * 0.79, 4)->setHAlign($nameLabel::LEFT)->setStyle($nameLabel::STYLE_TextCardRaceRank)->setTextSize(1)->setText($fileName);
|
||||
|
||||
if (is_dir($filePath)) {
|
||||
// Folder
|
||||
$nameLabel->setAction(self::ACTION_OPEN_FOLDER . substr($shortFilePath, 0, -1))->addTooltipLabelFeature($tooltipLabel, 'Open folder ' . $fileName);
|
||||
} else {
|
||||
// File
|
||||
$nameLabel->setAction(self::ACTION_INSPECT_FILE . $fileName)->addTooltipLabelFeature($tooltipLabel, 'Inspect file ' . $fileName);
|
||||
|
||||
if ($canAddMaps) {
|
||||
// 'Add' button
|
||||
$addButton = new Quad_UIConstructionBullet_Buttons();
|
||||
$mapFrame->add($addButton);
|
||||
$addButton->setX($width * 0.42)->setSize(4, 4)->setSubStyle($addButton::SUBSTYLE_NewBullet)->setAction(self::ACTION_ADD_FILE . $fileName)->addTooltipLabelFeature($tooltipLabel, 'Add map ' . $fileName);
|
||||
}
|
||||
|
||||
if ($canEraseMaps) {
|
||||
// 'Erase' button
|
||||
$eraseButton = new Quad_UIConstruction_Buttons();
|
||||
$mapFrame->add($eraseButton);
|
||||
$eraseButton->setX($width * 0.46)->setSize(4, 4)->setSubStyle($eraseButton::SUBSTYLE_Erase)->setAction(self::ACTION_ERASE_FILE . $fileName)->addTooltipLabelFeature($tooltipLabel, 'Erase file ' . $fileName);
|
||||
}
|
||||
}
|
||||
|
||||
$posY -= 4;
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$errorLabel = new Label();
|
||||
$frame->add($errorLabel);
|
||||
$errorLabel->setY(20)->setTextColor('f30')->setText('No access to the directory.')->setTranslate(true);
|
||||
}
|
||||
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, self::WIDGET_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the given directory for Map files
|
||||
*
|
||||
* @param string $directory
|
||||
* @return array|bool
|
||||
*/
|
||||
protected function scanMapFiles($directory) {
|
||||
if (!is_readable($directory) || !is_dir($directory)) {
|
||||
return false;
|
||||
}
|
||||
$mapFiles = array();
|
||||
$dirFiles = scandir($directory);
|
||||
foreach ($dirFiles as $fileName) {
|
||||
if (substr($fileName, 0, 1) === '.') {
|
||||
continue;
|
||||
}
|
||||
$fullFileName = $directory . $fileName;
|
||||
if (!is_readable($fullFileName)) {
|
||||
continue;
|
||||
}
|
||||
if (is_dir($fullFileName)) {
|
||||
$mapFiles[$fullFileName . DIRECTORY_SEPARATOR] = $fileName . DIRECTORY_SEPARATOR;
|
||||
continue;
|
||||
} else {
|
||||
if ($this->isMapFileName($fileName)) {
|
||||
$mapFiles[$fullFileName] = $fileName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $mapFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given file name represents a Map file
|
||||
*
|
||||
* @param string $fileName
|
||||
* @return bool
|
||||
*/
|
||||
protected function isMapFileName($fileName) {
|
||||
$mapFileNameEnding = '.map.gbx';
|
||||
$fileNameEnding = strtolower(substr($fileName, -strlen($mapFileNameEnding)));
|
||||
return ($fileNameEnding === $mapFileNameEnding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'NavigateRoot' action
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleNavigateRoot(array $actionCallback, Player $player) {
|
||||
$player->destroyCache($this, self::CACHE_FOLDER_PATH);
|
||||
$this->showManiaLink($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'NavigateUp' action
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleNavigateUp(array $actionCallback, Player $player) {
|
||||
$this->showManiaLink($player, '..');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'OpenFolder' page action
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleOpenFolder(array $actionCallback, Player $player) {
|
||||
$actionName = $actionCallback[1][2];
|
||||
$folderName = substr($actionName, strlen(self::ACTION_OPEN_FOLDER));
|
||||
$this->showManiaLink($player, $folderName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'InspectFile' page action
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleInspectFile(array $actionCallback, Player $player) {
|
||||
$actionName = $actionCallback[1][2];
|
||||
$fileName = substr($actionName, strlen(self::ACTION_INSPECT_FILE));
|
||||
// TODO: show inspect file view
|
||||
var_dump($fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'AddFile' page action
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleAddFile(array $actionCallback, Player $player) {
|
||||
$actionName = $actionCallback[1][2];
|
||||
$fileName = substr($actionName, strlen(self::ACTION_ADD_FILE));
|
||||
$folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
|
||||
$filePath = $folderPath . $fileName;
|
||||
|
||||
$mapsFolder = $this->maniaControl->getServer()->getDirectory()->getMapsFolder();
|
||||
$relativeFilePath = substr($filePath, strlen($mapsFolder));
|
||||
|
||||
// Check for valid map
|
||||
try {
|
||||
$this->maniaControl->getClient()->checkMapForCurrentServerParams($relativeFilePath);
|
||||
} catch (InvalidMapException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $player);
|
||||
return;
|
||||
} catch (FileException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add map to map list
|
||||
try {
|
||||
$this->maniaControl->getClient()->insertMap($relativeFilePath);
|
||||
} catch (AlreadyInListException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $player);
|
||||
return;
|
||||
}
|
||||
$map = $this->maniaControl->getMapManager()->fetchMapByFileName($relativeFilePath);
|
||||
if (!$map) {
|
||||
$this->maniaControl->getChat()->sendError('Error occurred.', $player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Message
|
||||
$message = $player->getEscapedNickname() . ' added ' . $map->getEscapedName() . '!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
|
||||
// Queue requested Map
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($player, $map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle 'EraseFile' page action
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleEraseFile(array $actionCallback, Player $player) {
|
||||
$actionName = $actionCallback[1][2];
|
||||
$fileName = substr($actionName, strlen(self::ACTION_ERASE_FILE));
|
||||
$folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
|
||||
$filePath = $folderPath . $fileName;
|
||||
if (@unlink($filePath)) {
|
||||
$this->maniaControl->getChat()->sendSuccess("Erased {$fileName}!");
|
||||
$this->showManiaLink($player);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError("Couldn't erase {$fileName}!");
|
||||
}
|
||||
}
|
||||
}
|
113
core/Maps/Map.php
Normal file
113
core/Maps/Map.php
Normal file
@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use ManiaControl\ManiaExchange\MXMapInfo;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* ManiaControl Map Model Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Map {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $index = -1;
|
||||
public $name = 'undefined';
|
||||
public $rawName = null;
|
||||
public $uid = null;
|
||||
public $fileName = null;
|
||||
public $environment = null;
|
||||
public $authorTime = -1;
|
||||
public $goldTime = -1;
|
||||
public $copperPrice = -1;
|
||||
public $mapType = null;
|
||||
public $mapStyle = null;
|
||||
public $nbCheckpoints = -1;
|
||||
public $nbLaps = -1;
|
||||
/** @var MXMapInfo $mx */
|
||||
public $mx = null;
|
||||
public $authorLogin = null;
|
||||
public $authorNick = null;
|
||||
public $authorZone = null;
|
||||
public $authorEInfo = null;
|
||||
public $comment = null;
|
||||
public $titleUid = null;
|
||||
public $startTime = -1;
|
||||
public $lastUpdate = 0;
|
||||
public $karma = null;
|
||||
|
||||
/**
|
||||
* Construct a new map instance from xmlrpc data
|
||||
*
|
||||
* @param \Maniaplanet\DedicatedServer\Structures\Map $mpMap
|
||||
*/
|
||||
public function __construct($mpMap = null) {
|
||||
$this->startTime = time();
|
||||
|
||||
if (!$mpMap) {
|
||||
return;
|
||||
}
|
||||
$this->name = Formatter::stripDirtyCodes($mpMap->name);
|
||||
$this->rawName = $mpMap->name;
|
||||
$this->uid = $mpMap->uId;
|
||||
$this->fileName = $mpMap->fileName;
|
||||
$this->authorLogin = $mpMap->author;
|
||||
$this->environment = $mpMap->environnement;
|
||||
$this->authorTime = $mpMap->authorTime;
|
||||
$this->goldTime = $mpMap->goldTime;
|
||||
$this->copperPrice = $mpMap->copperPrice;
|
||||
$this->mapType = $mpMap->mapType;
|
||||
$this->mapStyle = $mpMap->mapStyle;
|
||||
$this->nbCheckpoints = $mpMap->nbCheckpoints;
|
||||
$this->nbLaps = $mpMap->nbLaps;
|
||||
|
||||
$this->authorNick = $this->authorLogin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the escaped map name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEscapedName() {
|
||||
return Formatter::escapeText($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the game type of the map
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGame() {
|
||||
switch ($this->environment) {
|
||||
case 'Storm':
|
||||
return 'sm';
|
||||
case 'Canyon':
|
||||
case 'Stadium':
|
||||
case 'Valley':
|
||||
return 'tm';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a map update is available
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function updateAvailable() {
|
||||
return ($this->mx && ($this->lastUpdate < strtotime($this->mx->updated) || $this->uid !== $this->mx->uid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Var_Dump the Map
|
||||
*/
|
||||
public function dump() {
|
||||
var_dump(json_decode(json_encode($this)));
|
||||
}
|
||||
}
|
47
core/Maps/MapActions.php
Normal file
47
core/Maps/MapActions.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
||||
|
||||
/**
|
||||
* ManiaControl Map Actions Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MapActions {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a map actions instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skip the current Map
|
||||
*/
|
||||
public function skipMap() {
|
||||
// Force an EndMap on the MapQueue to set the next Map
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->endMap(null);
|
||||
|
||||
// Ignore EndMap on MapQueue
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->dontQueueNextMapChange();
|
||||
|
||||
// Switch The Map
|
||||
try {
|
||||
$this->maniaControl->getClient()->nextMap();
|
||||
} catch (ChangeInProgressException $e) {
|
||||
}
|
||||
}
|
||||
}
|
511
core/Maps/MapCommands.php
Normal file
511
core/Maps/MapCommands.php
Normal file
@ -0,0 +1,511 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\IconManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\FaultException;
|
||||
|
||||
/**
|
||||
* Class offering Commands to manage Maps
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MapCommands implements CommandListener, ManialinkPageAnswerListener, CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_OPEN_MAPLIST = 'MapCommands.OpenMapList';
|
||||
const ACTION_OPEN_XLIST = 'MapCommands.OpenMXList';
|
||||
const ACTION_RESTART_MAP = 'MapCommands.RestartMap';
|
||||
const ACTION_SKIP_MAP = 'MapCommands.NextMap';
|
||||
const ACTION_SHOW_AUTHOR = 'MapList.ShowAuthorList.';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new map commands instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initActionsMenuButtons();
|
||||
|
||||
// Admin commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('nextmap', 'next', 'skip'), $this, 'command_NextMap', true, 'Skips to the next map.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('restartmap', 'resmap', 'res'), $this, 'command_RestartMap', true, 'Restarts the current map.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('replaymap', 'replay'), $this, 'command_ReplayMap', true, 'Replays the current map (after the end of the map).');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('addmap', 'add'), $this, 'command_AddMap', true, 'Adds map from ManiaExchange.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('removemap', 'removethis'), $this, 'command_RemoveMap', true, 'Removes the current map.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('erasemap', 'erasethis'), $this, 'command_EraseMap', true, 'Erases the current map.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('shufflemaps', 'shuffle'), $this, 'command_ShuffleMaps', true, 'Shuffles the maplist.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('writemaplist', 'wml'), $this, 'command_WriteMapList', true, 'Writes the current maplist to a file.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('readmaplist', 'rml'), $this, 'command_ReadMapList', true, 'Loads a maplist into the server.');
|
||||
|
||||
// Player commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('nextmap', $this, 'command_showNextMap', false, 'Shows which map is next.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('maps', 'list'), $this, 'command_List', false, 'Shows the current maplist (or variations).');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('xmaps', 'xlist'), $this, 'command_xList', false, 'Shows maps from ManiaExchange.');
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_OPEN_XLIST, $this, 'command_xList');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_OPEN_MAPLIST, $this, 'command_List');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_RESTART_MAP, $this, 'command_RestartMap');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SKIP_MAP, $this, 'command_NextMap');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all Actions Menu Buttons
|
||||
*/
|
||||
private function initActionsMenuButtons() {
|
||||
// Menu Open xList
|
||||
$itemQuad = new Quad();
|
||||
$itemQuad->setImage($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON));
|
||||
$itemQuad->setImageFocus($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_MOVER));
|
||||
$itemQuad->setAction(self::ACTION_OPEN_XLIST);
|
||||
$this->maniaControl->getActionsMenu()->addPlayerMenuItem($itemQuad, 5, 'Open MX List');
|
||||
|
||||
// Menu Open List
|
||||
$itemQuad = new Quad_Icons64x64_1();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_ToolRoot);
|
||||
$itemQuad->setAction(self::ACTION_OPEN_MAPLIST);
|
||||
$this->maniaControl->getActionsMenu()->addPlayerMenuItem($itemQuad, 10, 'Open MapList');
|
||||
|
||||
// Menu RestartMap
|
||||
$itemQuad = new Quad_UIConstruction_Buttons();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_Reload);
|
||||
$itemQuad->setAction(self::ACTION_RESTART_MAP);
|
||||
$this->maniaControl->getActionsMenu()->addAdminMenuItem($itemQuad, 10, 'Restart Map');
|
||||
|
||||
// Menu NextMap
|
||||
$itemQuad = new Quad_Icons64x64_1();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_ArrowFastNext);
|
||||
$itemQuad->setAction(self::ACTION_SKIP_MAP);
|
||||
$this->maniaControl->getActionsMenu()->addAdminMenuItem($itemQuad, 20, 'Skip Map');
|
||||
}
|
||||
|
||||
/**
|
||||
* Show which map is the next
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_ShowNextMap(array $chatCallback, Player $player) {
|
||||
$nextQueued = $this->maniaControl->getMapManager()->getMapQueue()->getNextQueuedMap();
|
||||
if ($nextQueued) {
|
||||
/** @var Player $requester */
|
||||
$requester = $nextQueued[0];
|
||||
/** @var Map $map */
|
||||
$map = $nextQueued[1];
|
||||
$this->maniaControl->getChat()->sendInformation("Next Map is $<{$map->name}$> from $<{$map->authorNick}$> requested by $<{$requester->nickname}$>.", $player);
|
||||
} else {
|
||||
$mapIndex = $this->maniaControl->getClient()->getNextMapIndex();
|
||||
$maps = $this->maniaControl->getMapManager()->getMaps();
|
||||
$map = $maps[$mapIndex];
|
||||
$this->maniaControl->getChat()->sendInformation("Next Map is $<{$map->name}$> from $<{$map->authorNick}$>.", $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //removemap command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_RemoveMap(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_REMOVE_MAP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
// Get map
|
||||
$map = $this->maniaControl->getMapManager()->getCurrentMap();
|
||||
if (!$map) {
|
||||
$this->maniaControl->getChat()->sendError("Couldn't remove map.", $player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove map
|
||||
$this->maniaControl->getMapManager()->removeMap($player, $map->uid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //erasemap command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_EraseMap(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ERASE_MAP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
// Get map
|
||||
$map = $this->maniaControl->getMapManager()->getCurrentMap();
|
||||
if (!$map) {
|
||||
$this->maniaControl->getChat()->sendError("Couldn't erase map.", $player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Erase map
|
||||
$this->maniaControl->getMapManager()->removeMap($player, $map->uid, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle shufflemaps command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function command_ShuffleMaps(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_SHUFFLE_MAPS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
// Shuffles the maps
|
||||
$this->maniaControl->getMapManager()->shuffleMapList($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle addmap command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function command_AddMap(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chatCallback[1][2], 2);
|
||||
if (count($params) < 2) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //addmap 1234', $player);
|
||||
return;
|
||||
}
|
||||
|
||||
// add Map from Mania Exchange
|
||||
$this->maniaControl->getMapManager()->addMapFromMx($params[1], $player->login);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /nextmap Command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function command_NextMap(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_SKIP_MAP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->maniaControl->getMapManager()->getMapActions()->skipMap();
|
||||
|
||||
$message = $player->getEscapedNickname() . ' skipped the current Map!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle restartmap command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function command_RestartMap(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_RESTART_MAP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$message = $player->getEscapedNickname() . ' restarted the current Map!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->restartMap();
|
||||
} catch (ChangeInProgressException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
////$this->maniaControl->mapManager->mapQueue->addFirstMapToMapQueue($this->currentVote->voter, $this->maniaControl->mapManager->getCurrentMap());
|
||||
/**
|
||||
* Handle replaymap command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function command_ReplayMap(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_RESTART_MAP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$message = $player->getEscapedNickname() . ' replays the current Map!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->addFirstMapToMapQueue($player, $this->maniaControl->getMapManager()->getCurrentMap());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle writemaplist command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function command_WriteMapList(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_SUPERADMIN)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$chatCommand = explode(' ', $chat[1][2]);
|
||||
if (isset($chatCommand[1])) {
|
||||
if (strstr($chatCommand[1], '.txt')) {
|
||||
$maplist = $chatCommand[1];
|
||||
} else {
|
||||
$maplist = $chatCommand[1] . '.txt';
|
||||
}
|
||||
} else {
|
||||
$maplist = 'maplist.txt';
|
||||
}
|
||||
|
||||
$maplist = 'MatchSettings' . DIRECTORY_SEPARATOR . $maplist;
|
||||
try {
|
||||
$this->maniaControl->getClient()->saveMatchSettings($maplist);
|
||||
|
||||
$message = 'Maplist $<$fff' . $maplist . '$> written.';
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
Logger::logInfo($message, true);
|
||||
} catch (FaultException $e) {
|
||||
$this->maniaControl->getChat()->sendError('Cannot write maplist $<$fff' . $maplist . '$>!', $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle readmaplist command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param \ManiaControl\Players\Player $player
|
||||
*/
|
||||
public function command_ReadMapList(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_SUPERADMIN)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$chatCommand = explode(' ', $chat[1][2]);
|
||||
if (isset($chatCommand[1])) {
|
||||
if (strstr($chatCommand[1], '.txt')) {
|
||||
$maplist = $chatCommand[1];
|
||||
} else {
|
||||
$maplist = $chatCommand[1] . '.txt';
|
||||
}
|
||||
} else {
|
||||
$maplist = 'maplist.txt';
|
||||
}
|
||||
|
||||
$maplist = 'MatchSettings' . DIRECTORY_SEPARATOR . $maplist;
|
||||
try {
|
||||
$this->maniaControl->getClient()->loadMatchSettings($maplist);
|
||||
|
||||
$message = 'Maplist $<$fff' . $maplist . '$> loaded.';
|
||||
$this->maniaControl->getMapManager()->restructureMapList();
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
Logger::logInfo($message, true);
|
||||
} catch (FaultException $e) {
|
||||
$this->maniaControl->getChat()->sendError('Cannot load maplist $<$fff' . $maplist . '$>!', $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManialinkPageAnswer Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
|
||||
if (strstr($actionId, self::ACTION_SHOW_AUTHOR)) {
|
||||
$login = str_replace(self::ACTION_SHOW_AUTHOR, '', $actionId);
|
||||
$this->maniaControl->getMapManager()->getMapList()->playerCloseWidget($player);
|
||||
$this->showMapListAuthor($login, $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the Player a List of Maps from the given Author
|
||||
*
|
||||
* @param string $author
|
||||
* @param Player $player
|
||||
*/
|
||||
private function showMapListAuthor($author, Player $player) {
|
||||
$maps = $this->maniaControl->getMapManager()->getMaps();
|
||||
$mapList = array();
|
||||
/** @var Map $map */
|
||||
foreach ($maps as $map) {
|
||||
if ($map->authorLogin == $author) {
|
||||
array_push($mapList, $map);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($mapList)) {
|
||||
$this->maniaControl->getChat()->sendError('There are no maps to show!', $player->login);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->maniaControl->getMapManager()->getMapList()->showMapList($player, $mapList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle /maps command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_List(array $chatCallback, Player $player) {
|
||||
$chatCommands = explode(' ', $chatCallback[1][2]);
|
||||
$this->maniaControl->getMapManager()->getMapList()->playerCloseWidget($player);
|
||||
|
||||
if (isset($chatCommands[1])) {
|
||||
$listParam = strtolower($chatCommands[1]);
|
||||
switch ($listParam) {
|
||||
case 'best':
|
||||
$this->showMapListKarma(true, $player);
|
||||
break;
|
||||
case 'worst':
|
||||
$this->showMapListKarma(false, $player);
|
||||
break;
|
||||
case 'newest':
|
||||
$this->showMapListDate(true, $player);
|
||||
break;
|
||||
case 'oldest':
|
||||
$this->showMapListDate(false, $player);
|
||||
break;
|
||||
case 'author':
|
||||
if (isset($chatCommands[2])) {
|
||||
$this->showMaplistAuthor($chatCommands[2], $player);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('Missing Author Login!', $player);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->maniaControl->getMapManager()->getMapList()->showMapList($player);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$this->maniaControl->getMapManager()->getMapList()->showMapList($player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a Karma based MapList
|
||||
*
|
||||
* @param bool $best
|
||||
* @param Player $player
|
||||
*/
|
||||
private function showMapListKarma($best, Player $player) {
|
||||
/** @var \MCTeam\KarmaPlugin $karmaPlugin */
|
||||
$karmaPlugin = $this->maniaControl->getPluginManager()->getPlugin(MapList::DEFAULT_KARMA_PLUGIN);
|
||||
if ($karmaPlugin) {
|
||||
$maps = $this->maniaControl->getMapManager()->getMaps();
|
||||
$mapList = array();
|
||||
foreach ($maps as $map) {
|
||||
if ($map instanceof Map) {
|
||||
if ($this->maniaControl->getSettingManager()->getSettingValue($karmaPlugin, $karmaPlugin::SETTING_NEWKARMA) === true
|
||||
) {
|
||||
$karma = $karmaPlugin->getMapKarma($map);
|
||||
$map->karma = round($karma * 100.);
|
||||
} else {
|
||||
$votes = $karmaPlugin->getMapVotes($map);
|
||||
$min = 0;
|
||||
$plus = 0;
|
||||
foreach ($votes as $vote) {
|
||||
if (isset($vote->vote)) {
|
||||
if ($vote->vote !== 0.5) {
|
||||
if ($vote->vote < 0.5) {
|
||||
$min = $min + $vote->count;
|
||||
} else {
|
||||
$plus = $plus + $vote->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$map->karma = $plus - $min;
|
||||
}
|
||||
$mapList[] = $map;
|
||||
}
|
||||
}
|
||||
|
||||
usort($mapList, function (Map $mapA, Map $mapB) {
|
||||
return ($mapA->karma - $mapB->karma);
|
||||
});
|
||||
if ($best) {
|
||||
$mapList = array_reverse($mapList);
|
||||
}
|
||||
|
||||
$this->maniaControl->getMapManager()->getMapList()->showMapList($player, $mapList);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('KarmaPlugin is not enabled!', $player->login);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a Date based MapList
|
||||
*
|
||||
* @param bool $newest
|
||||
* @param Player $player
|
||||
*/
|
||||
private function showMapListDate($newest, Player $player) {
|
||||
$maps = $this->maniaControl->getMapManager()->getMaps();
|
||||
|
||||
usort($maps, function (Map $mapA, Map $mapB) {
|
||||
return ($mapA->index - $mapB->index);
|
||||
});
|
||||
if ($newest) {
|
||||
$maps = array_reverse($maps);
|
||||
}
|
||||
|
||||
$this->maniaControl->getMapManager()->getMapList()->showMapList($player, $maps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManiaExchange list command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_xList(array $chatCallback, Player $player) {
|
||||
$this->maniaControl->getMapManager()->getMXList()->showList($chatCallback, $player);
|
||||
}
|
||||
}
|
724
core/Maps/MapList.php
Normal file
724
core/Maps/MapList.php
Normal file
@ -0,0 +1,724 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Gauge;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Button;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use FML\ManiaLink;
|
||||
use FML\Script\Features\Paging;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\IconManager;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Utils\ColorUtil;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\ChangeInProgressException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\FileException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\NextMapException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\NotInListException;
|
||||
use MCTeam\CustomVotesPlugin;
|
||||
use MCTeam\KarmaPlugin;
|
||||
|
||||
/**
|
||||
* MapList Widget Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MapList implements ManialinkPageAnswerListener, CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_UPDATE_MAP = 'MapList.UpdateMap';
|
||||
const ACTION_REMOVE_MAP = 'MapList.RemoveMap';
|
||||
const ACTION_SWITCH_MAP = 'MapList.SwitchMap';
|
||||
const ACTION_START_SWITCH_VOTE = 'MapList.StartMapSwitchVote';
|
||||
const ACTION_QUEUED_MAP = 'MapList.QueueMap';
|
||||
const ACTION_UNQUEUE_MAP = 'MapList.UnQueueMap';
|
||||
const ACTION_CHECK_UPDATE = 'MapList.CheckUpdate';
|
||||
const ACTION_CLEAR_MAPQUEUE = 'MapList.ClearMapQueue';
|
||||
const ACTION_PAGING_CHUNKS = 'MapList.PagingChunk.';
|
||||
const MAX_MAPS_PER_PAGE = 15;
|
||||
const MAX_PAGES_PER_CHUNK = 2;
|
||||
const DEFAULT_KARMA_PLUGIN = 'MCTeam\KarmaPlugin';
|
||||
const DEFAULT_CUSTOM_VOTE_PLUGIN = 'MCTeam\CustomVotesPlugin';
|
||||
const CACHE_CURRENT_PAGE = 'CurrentPage';
|
||||
const WIDGET_NAME = 'MapList';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new map list instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_CLOSED, $this, 'closeWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_OPENED, $this, 'handleWidgetOpened');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(MapQueue::CB_MAPQUEUE_CHANGED, $this, 'updateWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(MapManager::CB_MAPS_UPDATED, $this, 'updateWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(MapManager::CB_KARMA_UPDATED, $this, 'updateWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::BEGINMAP, $this, 'updateWidget');
|
||||
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_CHECK_UPDATE, $this, 'checkUpdates');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_CLEAR_MAPQUEUE, $this, 'clearMapQueue');
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the Map Queue
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function clearMapQueue(array $chatCallback, Player $player) {
|
||||
// Clears the Map Queue
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->clearMapQueue($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for Map Updates
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function checkUpdates(array $chatCallback, Player $player) {
|
||||
// Update Mx Infos
|
||||
$this->maniaControl->getMapManager()->getMXManager()->fetchManiaExchangeMapInformation();
|
||||
|
||||
// Reshow the Maplist
|
||||
$this->showMapList($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a MapList on the Screen
|
||||
*
|
||||
* @param Player $player
|
||||
* @param Map[] $mapList
|
||||
* @param int $pageIndex
|
||||
*/
|
||||
public function showMapList(Player $player, $mapList = null, $pageIndex = -1) {
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
|
||||
if ($pageIndex < 0) {
|
||||
$pageIndex = (int)$player->getCache($this, self::CACHE_CURRENT_PAGE);
|
||||
}
|
||||
$player->setCache($this, self::CACHE_CURRENT_PAGE, $pageIndex);
|
||||
$queueBuffer = $this->maniaControl->getMapManager()->getMapQueue()->getQueueBuffer();
|
||||
|
||||
$chunkIndex = $this->getChunkIndexFromPageNumber($pageIndex);
|
||||
$mapsBeginIndex = $this->getChunkMapsBeginIndex($chunkIndex);
|
||||
|
||||
// Get Maps
|
||||
if (!is_array($mapList)) {
|
||||
$mapList = $this->maniaControl->getMapManager()->getMaps();
|
||||
}
|
||||
$mapList = array_slice($mapList, $mapsBeginIndex, self::MAX_PAGES_PER_CHUNK * self::MAX_MAPS_PER_PAGE);
|
||||
|
||||
$totalMapsCount = $this->maniaControl->getMapManager()->getMapsCount();
|
||||
$pagesCount = ceil($totalMapsCount / self::MAX_MAPS_PER_PAGE);
|
||||
|
||||
// Create ManiaLink
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$script = $maniaLink->getScript();
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$paging->setCustomMaxPageNumber($pagesCount);
|
||||
$paging->setChunkActionAppendsPageNumber(true);
|
||||
$paging->setChunkActions(self::ACTION_PAGING_CHUNKS);
|
||||
|
||||
// Main frame
|
||||
$frame = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultListFrame($script, $paging);
|
||||
$maniaLink->add($frame);
|
||||
|
||||
// Admin Buttons
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapQueue::SETTING_PERMISSION_CLEAR_MAPQUEUE)
|
||||
) {
|
||||
// Clear Map-Queue
|
||||
$label = new Label_Button();
|
||||
$frame->add($label);
|
||||
$label->setText('Clear Map-Queue');
|
||||
$label->setTextSize(1);
|
||||
$label->setPosition($width / 2 - 8, -$height / 2 + 9);
|
||||
$label->setHAlign($label::RIGHT);
|
||||
|
||||
$quad = new Quad_BgsPlayerCard();
|
||||
$frame->add($quad);
|
||||
$quad->setPosition($width / 2 - 5, -$height / 2 + 9, 0.01);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_BgPlayerCardBig);
|
||||
$quad->setHAlign($quad::RIGHT);
|
||||
$quad->setSize(29, 4);
|
||||
$quad->setAction(self::ACTION_CLEAR_MAPQUEUE);
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_CHECK_UPDATE)
|
||||
) {
|
||||
// Check Update
|
||||
$label = new Label_Button();
|
||||
$frame->add($label);
|
||||
$label->setText('Check MX for Updates');
|
||||
$label->setTextSize(1);
|
||||
$label->setPosition($width / 2 - 41, -$height / 2 + 9, 0.01);
|
||||
$label->setHAlign($label::RIGHT);
|
||||
|
||||
$quad = new Quad_BgsPlayerCard();
|
||||
$frame->add($quad);
|
||||
$quad->setPosition($width / 2 - 37, -$height / 2 + 9, 0.01);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_BgPlayerCardBig);
|
||||
$quad->setHAlign($quad::RIGHT);
|
||||
$quad->setSize(35, 4);
|
||||
$quad->setAction(self::ACTION_CHECK_UPDATE);
|
||||
|
||||
$mxQuad = new Quad();
|
||||
$frame->add($mxQuad);
|
||||
$mxQuad->setSize(3, 3);
|
||||
$mxQuad->setImage($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_GREEN));
|
||||
$mxQuad->setImageFocus($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_GREEN_MOVER));
|
||||
$mxQuad->setPosition($width / 2 - 67, -$height / 2 + 9);
|
||||
$mxQuad->setZ(0.01);
|
||||
$mxQuad->setAction(self::ACTION_CHECK_UPDATE);
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)
|
||||
) {
|
||||
// Directory browser
|
||||
$browserButton = new Label_Button();
|
||||
$frame->add($browserButton);
|
||||
$browserButton->setPosition($width / -2 + 20, -$height / 2 + 9, 0.01);
|
||||
$browserButton->setTextSize(1);
|
||||
$browserButton->setText('Directory Browser');
|
||||
|
||||
$browserQuad = new Quad_BgsPlayerCard();
|
||||
$frame->add($browserQuad);
|
||||
$browserQuad->setPosition($width / -2 + 20, -$height / 2 + 9, 0.01);
|
||||
$browserQuad->setSubStyle($browserQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$browserQuad->setSize(35, 4);
|
||||
$browserQuad->setAction(DirectoryBrowser::ACTION_SHOW);
|
||||
}
|
||||
|
||||
// Headline
|
||||
$headFrame = new Frame();
|
||||
$frame->add($headFrame);
|
||||
$headFrame->setY($height / 2 - 5);
|
||||
$posX = -$width / 2;
|
||||
$array = array('Id' => $posX + 5, 'Mx Id' => $posX + 10, 'Map Name' => $posX + 20, 'Author' => $posX + 68, 'Karma' => $posX + 115, 'Actions' => $width / 2 - 16);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $array);
|
||||
|
||||
// Predefine description Label
|
||||
$descriptionLabel = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultDescriptionLabel();
|
||||
$frame->add($descriptionLabel);
|
||||
|
||||
$queuedMaps = $this->maniaControl->getMapManager()->getMapQueue()->getQueuedMapsRanking();
|
||||
/** @var KarmaPlugin $karmaPlugin */
|
||||
$karmaPlugin = $this->maniaControl->getPluginManager()->getPlugin(self::DEFAULT_KARMA_PLUGIN);
|
||||
|
||||
$pageNumber = 1 + $chunkIndex * self::MAX_PAGES_PER_CHUNK;
|
||||
$paging->setStartPageNumber($pageIndex + 1);
|
||||
|
||||
$index = 0;
|
||||
$mapListId = 1 + $mapsBeginIndex;
|
||||
$posY = $height / 2 - 10;
|
||||
$pageFrame = null;
|
||||
|
||||
$currentMap = $this->maniaControl->getMapManager()->getCurrentMap();
|
||||
$mxIcon = $this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON);
|
||||
$mxIconHover = $this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_MOVER);
|
||||
$mxIconGreen = $this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_GREEN);
|
||||
$mxIconGreenHover = $this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_GREEN_MOVER);
|
||||
|
||||
foreach ($mapList as $map) {
|
||||
/** @var Map $map */
|
||||
if ($index % self::MAX_MAPS_PER_PAGE === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$posY = $height / 2 - 10;
|
||||
$paging->addPage($pageFrame, $pageNumber);
|
||||
$pageNumber++;
|
||||
}
|
||||
|
||||
// Map Frame
|
||||
$mapFrame = new Frame();
|
||||
$pageFrame->add($mapFrame);
|
||||
$mapFrame->setY($posY);
|
||||
$mapFrame->setZ(0.1);
|
||||
|
||||
if ($mapListId % 2 !== 0) {
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$mapFrame->add($lineQuad);
|
||||
$lineQuad->setSize($width, 4);
|
||||
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$lineQuad->setZ(0.001);
|
||||
}
|
||||
|
||||
if ($currentMap === $map) {
|
||||
$currentQuad = new Quad_Icons64x64_1();
|
||||
$mapFrame->add($currentQuad);
|
||||
$currentQuad->setX($posX + 3.5);
|
||||
$currentQuad->setZ(0.2);
|
||||
$currentQuad->setSize(4, 4);
|
||||
$currentQuad->setSubStyle($currentQuad::SUBSTYLE_ArrowBlue);
|
||||
}
|
||||
|
||||
$mxId = '-';
|
||||
if (isset($map->mx->id)) {
|
||||
$mxId = $map->mx->id;
|
||||
|
||||
$mxQuad = new Quad();
|
||||
$mapFrame->add($mxQuad);
|
||||
$mxQuad->setSize(3, 3);
|
||||
$mxQuad->setImage($mxIcon);
|
||||
$mxQuad->setImageFocus($mxIconHover);
|
||||
$mxQuad->setX($posX + 65);
|
||||
$mxQuad->setUrl($map->mx->pageurl);
|
||||
$mxQuad->setZ(0.01);
|
||||
$description = 'View ' . $map->getEscapedName() . ' on Mania-Exchange';
|
||||
$mxQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
if ($map->updateAvailable()) {
|
||||
$mxQuad = new Quad();
|
||||
$mapFrame->add($mxQuad);
|
||||
$mxQuad->setSize(3, 3);
|
||||
$mxQuad->setImage($mxIconGreen);
|
||||
$mxQuad->setImageFocus($mxIconGreenHover);
|
||||
$mxQuad->setX($posX + 62);
|
||||
$mxQuad->setUrl($map->mx->pageurl);
|
||||
$mxQuad->setZ(0.01);
|
||||
$description = 'Update for ' . $map->getEscapedName() . ' available on Mania-Exchange!';
|
||||
$mxQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
// Update Button
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)
|
||||
) {
|
||||
$mxQuad->setAction(self::ACTION_UPDATE_MAP . '.' . $map->uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display Maps
|
||||
$array = array($mapListId => $posX + 5, $mxId => $posX + 10, Formatter::stripDirtyCodes($map->name) => $posX + 20, $map->authorNick => $posX + 68);
|
||||
$labels = $this->maniaControl->getManialinkManager()->labelLine($mapFrame, $array);
|
||||
if (isset($labels[3])) {
|
||||
/** @var Label $label */
|
||||
$label = $labels[3];
|
||||
$description = 'Click to checkout all maps by $<' . $map->authorLogin . '$>!';
|
||||
$label->setAction(MapCommands::ACTION_SHOW_AUTHOR . $map->authorLogin);
|
||||
$label->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
|
||||
// TODO action detailed map info including mx info
|
||||
|
||||
// Map-Queue-Map-Label
|
||||
if (isset($queuedMaps[$map->uid])) {
|
||||
$label = new Label_Text();
|
||||
$mapFrame->add($label);
|
||||
$label->setX($width / 2 - 13);
|
||||
$label->setZ(0.2);
|
||||
$label->setTextSize(1.5);
|
||||
$label->setText($queuedMaps[$map->uid]);
|
||||
$label->setTextColor('fff');
|
||||
|
||||
// Checks if the Player who opened the Widget has queued the map
|
||||
$queuer = $this->maniaControl->getMapManager()->getMapQueue()->getQueuer($map->uid);
|
||||
if ($queuer && $queuer->login == $player->login) {
|
||||
$description = 'Remove ' . $map->getEscapedName() . ' from the Map Queue';
|
||||
$label->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
$label->setAction(self::ACTION_UNQUEUE_MAP . '.' . $map->uid);
|
||||
} else {
|
||||
$description = $map->getEscapedName() . ' is on Map-Queue Position: ' . $queuedMaps[$map->uid];
|
||||
$label->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
} else {
|
||||
// Map-Queue-Map-Button
|
||||
$queueLabel = new Label_Button();
|
||||
$mapFrame->add($queueLabel);
|
||||
$queueLabel->setX($width / 2 - 13);
|
||||
$queueLabel->setZ(0.2);
|
||||
$queueLabel->setSize(3, 3);
|
||||
$queueLabel->setText('+');
|
||||
|
||||
if (in_array($map->uid, $queueBuffer)) {
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapQueue::SETTING_PERMISSION_CLEAR_MAPQUEUE)
|
||||
) {
|
||||
$queueLabel->setAction(self::ACTION_QUEUED_MAP . '.' . $map->uid);
|
||||
}
|
||||
$queueLabel->setTextColor('f00');
|
||||
$description = $map->getEscapedName() . ' has recently been played!';
|
||||
$queueLabel->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
} else {
|
||||
$queueLabel->setTextColor('09f');
|
||||
$queueLabel->setAction(self::ACTION_QUEUED_MAP . '.' . $map->uid);
|
||||
$description = 'Add ' . $map->getEscapedName() . ' to the Map Queue';
|
||||
$queueLabel->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_REMOVE_MAP)
|
||||
) {
|
||||
// remove map button
|
||||
$removeButton = new Label_Button();
|
||||
$mapFrame->add($removeButton);
|
||||
$removeButton->setX($width / 2 - 5);
|
||||
$removeButton->setZ(0.2);
|
||||
$removeButton->setSize(3, 3);
|
||||
$removeButton->setTextSize(1);
|
||||
$removeButton->setText('x');
|
||||
$removeButton->setTextColor('a00');
|
||||
|
||||
$confirmFrame = $this->buildConfirmFrame($maniaLink, $posY, $map->uid, true);
|
||||
$removeButton->addToggleFeature($confirmFrame);
|
||||
$description = 'Remove Map: ' . $map->getEscapedName();
|
||||
$removeButton->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)
|
||||
) {
|
||||
// Switch to button
|
||||
$switchLabel = new Label_Button();
|
||||
$mapFrame->add($switchLabel);
|
||||
$switchLabel->setX($width / 2 - 9);
|
||||
$switchLabel->setZ(0.2);
|
||||
$switchLabel->setSize(3, 3);
|
||||
$switchLabel->setTextSize(2);
|
||||
$switchLabel->setText('»');
|
||||
$switchLabel->setTextColor('0f0');
|
||||
|
||||
$confirmFrame = $this->buildConfirmFrame($maniaLink, $posY, $map->uid);
|
||||
$switchLabel->addToggleFeature($confirmFrame);
|
||||
|
||||
$description = 'Switch Directly to Map: ' . $map->getEscapedName();
|
||||
$switchLabel->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
if ($this->maniaControl->getPluginManager()->isPluginActive(self::DEFAULT_CUSTOM_VOTE_PLUGIN)
|
||||
) {
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)
|
||||
) {
|
||||
// Switch Map Voting for Admins
|
||||
$switchQuad = new Quad_UIConstruction_Buttons();
|
||||
$mapFrame->add($switchQuad);
|
||||
$switchQuad->setX($width / 2 - 17);
|
||||
$switchQuad->setZ(0.2);
|
||||
$switchQuad->setSubStyle($switchQuad::SUBSTYLE_Validate_Step2);
|
||||
$switchQuad->setSize(3.8, 3.8);
|
||||
$switchQuad->setAction(self::ACTION_START_SWITCH_VOTE . '.' . $map->uid);
|
||||
$description = 'Start Map-Switch Vote: $<' . $map->name . '$>';
|
||||
$switchQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
} else {
|
||||
// Switch Map Voting for Player
|
||||
$switchLabel = new Label_Button();
|
||||
$mapFrame->add($switchLabel);
|
||||
$switchLabel->setX($width / 2 - 7);
|
||||
$switchLabel->setZ(0.2);
|
||||
$switchLabel->setSize(3, 3);
|
||||
$switchLabel->setTextSize(2);
|
||||
$switchLabel->setText('»');
|
||||
$switchLabel->setTextColor('0f0');
|
||||
$switchLabel->setAction(self::ACTION_START_SWITCH_VOTE . '.' . $map->uid);
|
||||
$description = 'Start Map-Switch Vote: ' . $map->getEscapedName();
|
||||
$switchLabel->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
}
|
||||
|
||||
// Display Karma bar
|
||||
if ($karmaPlugin) {
|
||||
$karma = $karmaPlugin->getMapKarma($map);
|
||||
$votes = $karmaPlugin->getMapVotes($map);
|
||||
if (is_numeric($karma)) {
|
||||
if ($this->maniaControl->getSettingManager()->getSettingValue($karmaPlugin, $karmaPlugin::SETTING_NEWKARMA)
|
||||
) {
|
||||
$karmaText = ' ' . round($karma * 100.) . '% (' . $votes['count'] . ')';
|
||||
} else {
|
||||
$min = 0;
|
||||
$plus = 0;
|
||||
foreach ($votes as $vote) {
|
||||
if (isset($vote->vote)) {
|
||||
if ($vote->vote !== 0.5) {
|
||||
if ($vote->vote < 0.5) {
|
||||
$min = $min + $vote->count;
|
||||
} else {
|
||||
$plus = $plus + $vote->count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$endKarma = $plus - $min;
|
||||
$karmaText = ' ' . $endKarma . ' (' . $votes['count'] . 'x / ' . round($karma * 100.) . '%)';
|
||||
}
|
||||
|
||||
$karmaGauge = new Gauge();
|
||||
$mapFrame->add($karmaGauge);
|
||||
$karmaGauge->setZ(2);
|
||||
$karmaGauge->setX($posX + 120);
|
||||
$karmaGauge->setSize(20, 9);
|
||||
$karmaGauge->setDrawBg(false);
|
||||
$karma = floatval($karma);
|
||||
$karmaGauge->setRatio($karma + 0.15 - $karma * 0.15);
|
||||
$karmaColor = ColorUtil::floatToStatusColor($karma);
|
||||
$karmaGauge->setColor($karmaColor . '9');
|
||||
|
||||
$karmaLabel = new Label();
|
||||
$mapFrame->add($karmaLabel);
|
||||
$karmaLabel->setZ(2);
|
||||
$karmaLabel->setX($posX + 120);
|
||||
$karmaLabel->setSize(20 * 0.9, 5);
|
||||
$karmaLabel->setTextSize(0.9);
|
||||
$karmaLabel->setTextColor('000');
|
||||
$karmaLabel->setText($karmaText);
|
||||
}
|
||||
}
|
||||
|
||||
$posY -= 4;
|
||||
$mapListId++;
|
||||
$index++;
|
||||
}
|
||||
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, self::WIDGET_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Chunk Index with the given Page Index
|
||||
*
|
||||
* @param int $pageIndex
|
||||
* @return int
|
||||
*/
|
||||
private function getChunkIndexFromPageNumber($pageIndex) {
|
||||
$mapsCount = $this->maniaControl->getMapManager()->getMapsCount();
|
||||
$pagesCount = ceil($mapsCount / self::MAX_MAPS_PER_PAGE);
|
||||
if ($pageIndex > $pagesCount - 1) {
|
||||
$pageIndex = $pagesCount - 1;
|
||||
}
|
||||
return floor($pageIndex / self::MAX_PAGES_PER_CHUNK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the First Map Index to show for the given Chunk
|
||||
*
|
||||
* @param int $chunkIndex
|
||||
* @return int
|
||||
*/
|
||||
private function getChunkMapsBeginIndex($chunkIndex) {
|
||||
return $chunkIndex * self::MAX_PAGES_PER_CHUNK * self::MAX_MAPS_PER_PAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the confirmation frame
|
||||
*
|
||||
* @param ManiaLink $maniaLink
|
||||
* @param float $posY
|
||||
* @param bool $mapUid
|
||||
* @param bool $remove
|
||||
* @return Frame
|
||||
*/
|
||||
public function buildConfirmFrame(Manialink $maniaLink, $posY, $mapUid, $remove = false) {
|
||||
// TODO: get rid of the confirm frame to decrease xml size & network usage
|
||||
// SUGGESTION: just send them as own manialink again on clicking?
|
||||
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$quadStyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowStyle();
|
||||
$quadSubstyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowSubStyle();
|
||||
|
||||
$confirmFrame = new Frame();
|
||||
$maniaLink->add($confirmFrame);
|
||||
$confirmFrame->setPosition($width / 2 + 6, $posY);
|
||||
$confirmFrame->setVisible(false);
|
||||
|
||||
$quad = new Quad();
|
||||
$confirmFrame->add($quad);
|
||||
$quad->setStyles($quadStyle, $quadSubstyle);
|
||||
$quad->setSize(12, 4);
|
||||
|
||||
$quad = new Quad_BgsPlayerCard();
|
||||
$confirmFrame->add($quad);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_BgCardSystem);
|
||||
$quad->setSize(11, 3.5);
|
||||
|
||||
$label = new Label_Button();
|
||||
$confirmFrame->add($label);
|
||||
$label->setText('Sure?');
|
||||
$label->setTextSize(1);
|
||||
$label->setScale(0.90);
|
||||
$label->setX(-1.3);
|
||||
|
||||
$buttLabel = new Label_Button();
|
||||
$confirmFrame->add($buttLabel);
|
||||
$buttLabel->setPosition(3.2, 0.4, 0.2);
|
||||
$buttLabel->setSize(3, 3);
|
||||
|
||||
if ($remove) {
|
||||
$buttLabel->setTextSize(1);
|
||||
$buttLabel->setTextColor('a00');
|
||||
$buttLabel->setText('x');
|
||||
$quad->setAction(self::ACTION_REMOVE_MAP . '.' . $mapUid);
|
||||
} else {
|
||||
$buttLabel->setTextSize(2);
|
||||
$buttLabel->setTextColor('0f0');
|
||||
$buttLabel->setText('»');
|
||||
$quad->setAction(self::ACTION_SWITCH_MAP . '.' . $mapUid);
|
||||
}
|
||||
return $confirmFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the player if he opened another Main Widget
|
||||
*
|
||||
* @param Player $player
|
||||
* @param string $openedWidget
|
||||
*/
|
||||
public function handleWidgetOpened(Player $player, $openedWidget) {
|
||||
// unset when another main widget got opened
|
||||
if ($openedWidget !== self::WIDGET_NAME) {
|
||||
$player->destroyCache($this, self::CACHE_CURRENT_PAGE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the widget
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function closeWidget(Player $player) {
|
||||
// TODO: resolve duplicate with 'playerCloseWidget'
|
||||
$player->destroyCache($this, self::CACHE_CURRENT_PAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManialinkPageAnswer Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$actionArray = explode('.', $actionId);
|
||||
if (count($actionArray) <= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = $actionArray[0] . '.' . $actionArray[1];
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
$mapUid = $actionArray[2];
|
||||
|
||||
switch ($action) {
|
||||
case self::ACTION_UPDATE_MAP:
|
||||
$this->maniaControl->getMapManager()->updateMap($player, $mapUid);
|
||||
$this->showMapList($player);
|
||||
break;
|
||||
case self::ACTION_REMOVE_MAP:
|
||||
try {
|
||||
$this->maniaControl->getMapManager()->removeMap($player, $mapUid);
|
||||
} catch (FileException $e) {
|
||||
$this->maniaControl->getChat()->sendException($e, $player);
|
||||
}
|
||||
break;
|
||||
case self::ACTION_SWITCH_MAP:
|
||||
// Don't queue on Map-Change
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->dontQueueNextMapChange();
|
||||
try {
|
||||
$this->maniaControl->getClient()->jumpToMapIdent($mapUid);
|
||||
} catch (NextMapException $exception) {
|
||||
$this->maniaControl->getChat()->sendError('Error on Jumping to Map Ident: ' . $exception->getMessage(), $player);
|
||||
break;
|
||||
} catch (NotInListException $exception) {
|
||||
// TODO: "Map not found." -> how is that possible?
|
||||
$this->maniaControl->getChat()->sendError('Error on Jumping to Map Ident: ' . $exception->getMessage(), $player);
|
||||
break;
|
||||
}
|
||||
|
||||
$map = $this->maniaControl->getMapManager()->getMapByUid($mapUid);
|
||||
|
||||
$message = $player->getEscapedNickname() . ' skipped to Map $z' . $map->getEscapedName() . '!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
|
||||
$this->playerCloseWidget($player);
|
||||
break;
|
||||
case self::ACTION_START_SWITCH_VOTE:
|
||||
/** @var CustomVotesPlugin $votesPlugin */
|
||||
$votesPlugin = $this->maniaControl->getPluginManager()->getPlugin(self::DEFAULT_CUSTOM_VOTE_PLUGIN);
|
||||
$map = $this->maniaControl->getMapManager()->getMapByUid($mapUid);
|
||||
|
||||
$message = $player->getEscapedNickname() . '$s started a vote to switch to ' . $map->getEscapedName() . '!';
|
||||
|
||||
$votesPlugin->defineVote('switchmap', 'Goto ' . $map->name, true, $message)->setStopCallback(Callbacks::ENDMAP);
|
||||
|
||||
$votesPlugin->startVote($player, 'switchmap', function ($result) use (&$votesPlugin, &$map) {
|
||||
$votesPlugin->undefineVote('switchmap');
|
||||
|
||||
//Don't queue on Map-Change
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->dontQueueNextMapChange();
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->JumpToMapIdent($map->uid);
|
||||
} catch (NextMapException $exception) {
|
||||
return;
|
||||
} catch (NotInListException $exception) {
|
||||
return;
|
||||
} catch (ChangeInProgressException $exception) {
|
||||
// TODO: delay skip if change is in progress
|
||||
return;
|
||||
}
|
||||
|
||||
$this->maniaControl->getChat()->sendInformation('$sVote Successful -> Map switched!');
|
||||
});
|
||||
break;
|
||||
case self::ACTION_QUEUED_MAP:
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($callback[1][1], $mapUid);
|
||||
$this->showMapList($player);
|
||||
break;
|
||||
case self::ACTION_UNQUEUE_MAP:
|
||||
$this->maniaControl->getMapManager()->getMapQueue()->removeFromMapQueue($player, $mapUid);
|
||||
$this->showMapList($player);
|
||||
break;
|
||||
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));
|
||||
$this->showMapList($player, null, $neededPage - 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the widget for
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function playerCloseWidget(Player $player) {
|
||||
$player->destroyCache($this, self::CACHE_CURRENT_PAGE);
|
||||
$this->maniaControl->getManialinkManager()->closeWidget($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reopen the widget on Map Begin, MapListChanged, etc.
|
||||
*/
|
||||
public function updateWidget() {
|
||||
$players = $this->maniaControl->getPlayerManager()->getPlayers();
|
||||
foreach ($players as $player) {
|
||||
$currentPage = $player->getCache($this, self::CACHE_CURRENT_PAGE);
|
||||
if ($currentPage !== null) {
|
||||
$this->showMapList($player, null, $currentPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
869
core/Maps/MapManager.php
Normal file
869
core/Maps/MapManager.php
Normal file
@ -0,0 +1,869 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\ManiaExchange\ManiaExchangeList;
|
||||
use ManiaControl\ManiaExchange\ManiaExchangeManager;
|
||||
use ManiaControl\ManiaExchange\MXMapInfo;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use Maniaplanet\DedicatedServer\InvalidArgumentException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\AlreadyInListException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\Exception;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\FileException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\IndexOutOfBoundException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\InvalidMapException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\NotInListException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnavailableFeatureException;
|
||||
|
||||
/**
|
||||
* ManiaControl Map Manager Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MapManager implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TABLE_MAPS = 'mc_maps';
|
||||
const CB_MAPS_UPDATED = 'MapManager.MapsUpdated';
|
||||
const CB_KARMA_UPDATED = 'MapManager.KarmaUpdated';
|
||||
const SETTING_PERMISSION_ADD_MAP = 'Add Maps';
|
||||
const SETTING_PERMISSION_REMOVE_MAP = 'Remove Maps';
|
||||
const SETTING_PERMISSION_ERASE_MAP = 'Erase Maps';
|
||||
const SETTING_PERMISSION_SHUFFLE_MAPS = 'Shuffle Maps';
|
||||
const SETTING_PERMISSION_CHECK_UPDATE = 'Check Map Update';
|
||||
const SETTING_PERMISSION_SKIP_MAP = 'Skip Map';
|
||||
const SETTING_PERMISSION_RESTART_MAP = 'Restart Map';
|
||||
const SETTING_AUTOSAVE_MAPLIST = 'Autosave Maplist file';
|
||||
const SETTING_MAPLIST_FILE = 'File to write Maplist in';
|
||||
const SETTING_WRITE_OWN_MAPLIST_FILE = 'Write a own Maplist File for every Server called serverlogin.txt';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var MapQueue $mapQueue */
|
||||
/** @deprecated see getMapQueue() */
|
||||
public $mapQueue = null;
|
||||
/** @var MapCommands $mapCommands */
|
||||
/** @deprecated see getMapCommands() */
|
||||
public $mapCommands = null;
|
||||
/** @var MapActions $mapActions */
|
||||
/** @deprecated see getMapActions() */
|
||||
public $mapActions = null;
|
||||
/** @var MapList $mapList */
|
||||
/** @deprecated see getMapList() */
|
||||
public $mapList = null;
|
||||
/** @var DirectoryBrowser $directoryBrowser */
|
||||
/** @deprecated see getDirectoryBrowser() */
|
||||
public $directoryBrowser = null;
|
||||
/** @var ManiaExchangeList $mxList */
|
||||
/** @deprecated see getMXList() */
|
||||
public $mxList = null;
|
||||
/** @var ManiaExchangeManager $mxManager */
|
||||
/** @deprecated see getMXManager() */
|
||||
public $mxManager = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var Map[] $maps */
|
||||
private $maps = array();
|
||||
/** @var Map $currentMap */
|
||||
private $currentMap = null;
|
||||
private $mapEnded = false;
|
||||
private $mapBegan = false;
|
||||
|
||||
/**
|
||||
* Construct a new map manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
// Children
|
||||
$this->mxManager = new ManiaExchangeManager($this->maniaControl);
|
||||
$this->mapList = new MapList($this->maniaControl);
|
||||
$this->directoryBrowser = new DirectoryBrowser($this->maniaControl);
|
||||
$this->mxList = new ManiaExchangeList($this->maniaControl);
|
||||
$this->mapCommands = new MapCommands($maniaControl);
|
||||
$this->mapQueue = new MapQueue($this->maniaControl);
|
||||
$this->mapActions = new MapActions($maniaControl);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_MAPLISTMODIFIED, $this, 'mapsModified');
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_ADD_MAP, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_REMOVE_MAP, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_ERASE_MAP, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_SHUFFLE_MAPS, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHECK_UPDATE, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_SKIP_MAP, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_RESTART_MAP, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
|
||||
// Settings
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map commands
|
||||
*
|
||||
* @return MapCommands
|
||||
*/
|
||||
public function getMapCommands() {
|
||||
return $this->mapCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map actions
|
||||
*
|
||||
* @return MapActions
|
||||
*/
|
||||
public function getMapActions() {
|
||||
return $this->mapActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map list
|
||||
*
|
||||
* @return MapList
|
||||
*/
|
||||
public function getMapList() {
|
||||
return $this->mapList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the directory browser
|
||||
*
|
||||
* @return DirectoryBrowser
|
||||
*/
|
||||
public function getDirectoryBrowser() {
|
||||
return $this->directoryBrowser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mx list
|
||||
*
|
||||
* @return ManiaExchangeList
|
||||
*/
|
||||
public function getMXList() {
|
||||
return $this->mxList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a Map from Mania Exchange
|
||||
*
|
||||
* @param Player $admin
|
||||
* @param string $uid
|
||||
*/
|
||||
public function updateMap(Player $admin, $uid) {
|
||||
$this->updateMapTimestamp($uid);
|
||||
|
||||
if (!isset($uid) || !isset($this->maps[$uid])) {
|
||||
$this->maniaControl->getChat()->sendError("Error updating Map: Unknown UID '{$uid}'!", $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Map $map */
|
||||
$map = $this->maps[$uid];
|
||||
|
||||
$mxId = $map->mx->id;
|
||||
$this->removeMap($admin, $uid, true, false);
|
||||
$this->addMapFromMx($mxId, $admin->login, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Timestamp of a Map
|
||||
*
|
||||
* @param string $uid
|
||||
* @return bool
|
||||
*/
|
||||
private function updateMapTimestamp($uid) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$mapQuery = "UPDATE `" . self::TABLE_MAPS . "` SET
|
||||
mxid = 0,
|
||||
changed = NOW()
|
||||
WHERE 'uid' = ?";
|
||||
$mapStatement = $mysqli->prepare($mapQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$mapStatement->bind_param('s', $uid);
|
||||
$mapStatement->execute();
|
||||
if ($mapStatement->error) {
|
||||
trigger_error($mapStatement->error);
|
||||
$mapStatement->close();
|
||||
return false;
|
||||
}
|
||||
$mapStatement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a Map
|
||||
*
|
||||
* @param Player $admin
|
||||
* @param string $uid
|
||||
* @param bool $eraseFile
|
||||
* @param bool $message
|
||||
*/
|
||||
public function removeMap(Player $admin, $uid, $eraseFile = false, $message = true) {
|
||||
if (!isset($this->maps[$uid])) {
|
||||
$this->maniaControl->getChat()->sendError('Map does not exist!', $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var Map $map */
|
||||
$map = $this->maps[$uid];
|
||||
|
||||
// Unset the Map everywhere
|
||||
$this->getMapQueue()->removeFromMapQueue($admin, $map->uid);
|
||||
|
||||
if ($map->mx) {
|
||||
$this->getMXManager()->unsetMap($map->mx->id);
|
||||
}
|
||||
|
||||
// Remove map
|
||||
try {
|
||||
$this->maniaControl->getClient()->removeMap($map->fileName);
|
||||
} catch (NotInListException $e) {
|
||||
} catch (FileException $e) {
|
||||
}
|
||||
|
||||
unset($this->maps[$uid]);
|
||||
|
||||
if ($eraseFile) {
|
||||
// Check if ManiaControl can even write to the maps dir
|
||||
$mapDir = $this->maniaControl->getClient()->getMapsDirectory();
|
||||
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);
|
||||
$eraseFile = false;
|
||||
}
|
||||
} else {
|
||||
$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() . '!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the map queue
|
||||
*
|
||||
* @return MapQueue
|
||||
*/
|
||||
public function getMapQueue() {
|
||||
return $this->mapQueue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the mx manager
|
||||
*
|
||||
* @return ManiaExchangeManager
|
||||
*/
|
||||
public function getMXManager() {
|
||||
return $this->mxManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Map from Mania Exchange
|
||||
*
|
||||
* @param int $mapId
|
||||
* @param string $login
|
||||
* @param bool $update
|
||||
*/
|
||||
public function addMapFromMx($mapId, $login, $update = false) {
|
||||
if (is_numeric($mapId)) {
|
||||
// Check if map exists
|
||||
$this->maniaControl->getMapManager()->getMXManager()->fetchMapInfo($mapId, function (MXMapInfo $mapInfo = null) use (
|
||||
&$login, &$update
|
||||
) {
|
||||
if (!$mapInfo || !isset($mapInfo->uploaded)) {
|
||||
// Invalid id
|
||||
$this->maniaControl->getChat()->sendError('Invalid MX-Id!', $login);
|
||||
return;
|
||||
}
|
||||
|
||||
// Download the file
|
||||
$this->maniaControl->getFileReader()->loadFile($mapInfo->downloadurl, function ($file, $error) use (
|
||||
&$login, &$mapInfo, &$update
|
||||
) {
|
||||
if (!$file || $error) {
|
||||
// Download error
|
||||
$this->maniaControl->getChat()->sendError("Download failed: '{$error}'!", $login);
|
||||
return;
|
||||
}
|
||||
$this->processMapFile($file, $mapInfo, $login, $update);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the MapFile
|
||||
*
|
||||
* @param string $file
|
||||
* @param MXMapInfo $mapInfo
|
||||
* @param string $login
|
||||
* @param bool $update
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function processMapFile($file, MXMapInfo $mapInfo, $login, $update) {
|
||||
// Check if map is already on the server
|
||||
if ($this->getMapByUid($mapInfo->uid)) {
|
||||
$this->maniaControl->getChat()->sendError('Map is already on the server!', $login);
|
||||
return;
|
||||
}
|
||||
|
||||
// Save map
|
||||
$fileName = $mapInfo->id . '_' . $mapInfo->name . '.Map.Gbx';
|
||||
$fileName = FileUtil::getClearedFileName($fileName);
|
||||
|
||||
$downloadFolderName = $this->maniaControl->getSettingManager()->getSettingValue($this, 'MapDownloadDirectory', 'MX');
|
||||
$relativeMapFileName = $downloadFolderName . DIRECTORY_SEPARATOR . $fileName;
|
||||
$mapDir = $this->maniaControl->getServer()->getDirectory()->getMapsFolder();
|
||||
$downloadDirectory = $mapDir . $downloadFolderName . DIRECTORY_SEPARATOR;
|
||||
$fullMapFileName = $downloadDirectory . $fileName;
|
||||
|
||||
// Check if it can get written locally
|
||||
if ($this->maniaControl->getServer()->checkAccess($mapDir)) {
|
||||
// Create download directory if necessary
|
||||
if (!is_dir($downloadDirectory) && !mkdir($downloadDirectory) || !is_writable($downloadDirectory)) {
|
||||
$this->maniaControl->getChat()->sendError("ManiaControl doesn't have to rights to save maps in '{$downloadDirectory}'.", $login);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file_put_contents($fullMapFileName, $file)) {
|
||||
// Save error
|
||||
$this->maniaControl->getChat()->sendError('Saving map failed!', $login);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Write map via write file method
|
||||
try {
|
||||
$this->maniaControl->getClient()->writeFile($relativeMapFileName, $file);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
if ($e->getMessage() === 'data are too big') {
|
||||
$this->maniaControl->getChat()->sendError("Map is too big for a remote save.", $login);
|
||||
return;
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for valid map
|
||||
try {
|
||||
$this->maniaControl->getClient()->checkMapForCurrentServerParams($relativeMapFileName);
|
||||
} catch (InvalidMapException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $login);
|
||||
return;
|
||||
} catch (FileException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $login);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add map to map list
|
||||
try {
|
||||
$this->maniaControl->getClient()->insertMap($relativeMapFileName);
|
||||
} catch (AlreadyInListException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $login);
|
||||
return;
|
||||
}
|
||||
$this->updateFullMapList();
|
||||
|
||||
// Update Mx MapInfo
|
||||
$this->maniaControl->getMapManager()->getMXManager()->updateMapObjectsWithManiaExchangeIds(array($mapInfo));
|
||||
|
||||
// Update last updated time
|
||||
$map = $this->getMapByUid($mapInfo->uid);
|
||||
if (!$map) {
|
||||
// TODO: improve this - error reports about not existing maps
|
||||
$this->maniaControl->getErrorHandler()->triggerDebugNotice('Map not in List after Insert!');
|
||||
$this->maniaControl->getChat()->sendError('Server Error!', $login);
|
||||
return;
|
||||
}
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Map by UID
|
||||
*
|
||||
* @param string $uid
|
||||
* @return Map
|
||||
*/
|
||||
public function getMapByUid($uid) {
|
||||
if (isset($this->maps[$uid])) {
|
||||
return $this->maps[$uid];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the full Map list, needed on Init, addMap and on ShuffleMaps
|
||||
*/
|
||||
private function updateFullMapList() {
|
||||
$tempList = array();
|
||||
|
||||
try {
|
||||
$offset = 0;
|
||||
while ($this->maniaControl->getClient()) {
|
||||
$maps = $this->maniaControl->getClient()->getMapList(150, $offset);
|
||||
|
||||
foreach ($maps as $rpcMap) {
|
||||
if (array_key_exists($rpcMap->uId, $this->maps)) {
|
||||
// Map already exists, only update index
|
||||
$tempList[$rpcMap->uId] = $this->maps[$rpcMap->uId];
|
||||
} else {
|
||||
// Insert Map Object
|
||||
$map = $this->initializeMap($rpcMap);
|
||||
$tempList[$map->uid] = $map;
|
||||
}
|
||||
}
|
||||
|
||||
$offset += 150;
|
||||
}
|
||||
} catch (IndexOutOfBoundException $e) {
|
||||
}
|
||||
|
||||
// restore Sorted MapList
|
||||
$this->maps = $tempList;
|
||||
|
||||
// Trigger own callback
|
||||
$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)
|
||||
) {
|
||||
$serverLogin = $this->maniaControl->getServer()->login;
|
||||
$matchSettingsFileName = "MatchSettings/{$serverLogin}.txt";
|
||||
} else {
|
||||
$matchSettingsFileName = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MAPLIST_FILE);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->saveMatchSettings($matchSettingsFileName);
|
||||
} catch (FileException $e) {
|
||||
Logger::logError("Unable to write the playlist file, please checkout your MX-Folders File permissions!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a Map
|
||||
*
|
||||
* @param mixed $rpcMap
|
||||
* @return Map
|
||||
*/
|
||||
public function initializeMap($rpcMap) {
|
||||
$map = new Map($rpcMap);
|
||||
$this->saveMap($map);
|
||||
return $map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a Map in the Database
|
||||
*
|
||||
* @param Map $map
|
||||
* @return bool
|
||||
*/
|
||||
private function saveMap(Map &$map) {
|
||||
//TODO saveMaps for whole maplist at once (usage of prepared statements)
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$mapQuery = "INSERT INTO `" . self::TABLE_MAPS . "` (
|
||||
`uid`,
|
||||
`name`,
|
||||
`authorLogin`,
|
||||
`fileName`,
|
||||
`environment`,
|
||||
`mapType`
|
||||
) VALUES (
|
||||
?, ?, ?, ?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`index` = LAST_INSERT_ID(`index`),
|
||||
`fileName` = VALUES(`fileName`),
|
||||
`environment` = VALUES(`environment`),
|
||||
`mapType` = VALUES(`mapType`);";
|
||||
|
||||
$mapStatement = $mysqli->prepare($mapQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$mapStatement->bind_param('ssssss', $map->uid, $map->rawName, $map->authorLogin, $map->fileName, $map->environment, $map->mapType);
|
||||
$mapStatement->execute();
|
||||
if ($mapStatement->error) {
|
||||
trigger_error($mapStatement->error);
|
||||
$mapStatement->close();
|
||||
return false;
|
||||
}
|
||||
$map->index = $mapStatement->insert_id;
|
||||
$mapStatement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get's a Map by it's Mania-Exchange Id
|
||||
*
|
||||
* @param int $mxId
|
||||
* @return Map
|
||||
*/
|
||||
public function getMapByMxId($mxId) {
|
||||
foreach ($this->maps as $map) {
|
||||
if ($map->mx && $map->mx->id == $mxId) {
|
||||
return $map;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuffles the MapList
|
||||
*
|
||||
* @param Player $admin
|
||||
* @return bool
|
||||
*/
|
||||
public function shuffleMapList($admin = null) {
|
||||
$shuffledMaps = $this->maps;
|
||||
shuffle($shuffledMaps);
|
||||
|
||||
$mapArray = array();
|
||||
|
||||
foreach ($shuffledMaps as $map) {
|
||||
/** @var Map $map */
|
||||
$mapArray[] = $map->fileName;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->chooseNextMapList($mapArray);
|
||||
} catch (Exception $e) {
|
||||
//TODO temp added 19.04.2014
|
||||
$this->maniaControl->getErrorHandler()->triggerDebugNotice("Exception line 331 MapManager" . $e->getMessage());
|
||||
trigger_error("Couldn't shuffle mapList. " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->fetchCurrentMap();
|
||||
|
||||
if ($admin) {
|
||||
$message = $admin->getEscapedNickname() . ' shuffled the Maplist!';
|
||||
$this->maniaControl->getChat()->sendSuccess($message);
|
||||
Logger::logInfo($message, true);
|
||||
}
|
||||
|
||||
// Restructure if needed
|
||||
$this->restructureMapList();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Freshly fetch current Map
|
||||
*
|
||||
* @return Map
|
||||
*/
|
||||
private function fetchCurrentMap() {
|
||||
try {
|
||||
$rpcMap = $this->maniaControl->getClient()->getCurrentMapInfo();
|
||||
} catch (UnavailableFeatureException $exception) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (array_key_exists($rpcMap->uId, $this->maps)) {
|
||||
$this->currentMap = $this->maps[$rpcMap->uId];
|
||||
$this->currentMap->nbCheckpoints = $rpcMap->nbCheckpoints;
|
||||
$this->currentMap->nbLaps = $rpcMap->nbLaps;
|
||||
return $this->currentMap;
|
||||
}
|
||||
|
||||
$this->currentMap = $this->initializeMap($rpcMap);
|
||||
$this->maps[$this->currentMap->uid] = $this->currentMap;
|
||||
return $this->currentMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restructures the Maplist
|
||||
*/
|
||||
public function restructureMapList() {
|
||||
$currentIndex = $this->getMapIndex($this->getCurrentMap());
|
||||
|
||||
// No RestructureNeeded
|
||||
if ($currentIndex < Maplist::MAX_MAPS_PER_PAGE - 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$lowerMapArray = array();
|
||||
$higherMapArray = array();
|
||||
|
||||
$index = 0;
|
||||
foreach ($this->maps as $map) {
|
||||
if ($index < $currentIndex) {
|
||||
$lowerMapArray[] = $map->fileName;
|
||||
} else {
|
||||
$higherMapArray[] = $map->fileName;
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
|
||||
$mapArray = array_merge($higherMapArray, $lowerMapArray);
|
||||
array_shift($mapArray);
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->chooseNextMapList($mapArray);
|
||||
} catch (Exception $e) {
|
||||
trigger_error("Error restructuring the Maplist. " . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the MapIndex of a given map
|
||||
*
|
||||
* @param Map $map
|
||||
* @return int
|
||||
*/
|
||||
public function getMapIndex(Map $map) {
|
||||
$maps = $this->getMaps();
|
||||
return array_search($map, $maps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Maps
|
||||
*
|
||||
* @param int $offset
|
||||
* @param int $length
|
||||
* @return Map[]
|
||||
*/
|
||||
public function getMaps($offset = null, $length = null) {
|
||||
if ($offset === null) {
|
||||
return array_values($this->maps);
|
||||
}
|
||||
if ($length === null) {
|
||||
return array_slice($this->maps, $offset);
|
||||
}
|
||||
return array_slice($this->maps, $offset, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Current Map
|
||||
*
|
||||
* @return Map
|
||||
*/
|
||||
public function getCurrentMap() {
|
||||
if (!$this->currentMap) {
|
||||
return $this->fetchCurrentMap();
|
||||
}
|
||||
return $this->currentMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle OnInit callback
|
||||
*/
|
||||
public function handleOnInit() {
|
||||
$this->updateFullMapList();
|
||||
$this->fetchCurrentMap();
|
||||
|
||||
// Restructure Maplist
|
||||
$this->restructureMapList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle AfterInit callback
|
||||
*/
|
||||
public function handleAfterInit() {
|
||||
// Fetch MX infos
|
||||
$this->getMXManager()->fetchManiaExchangeMapInformation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Script BeginMap callback
|
||||
*
|
||||
* @param string $mapUid
|
||||
* @param string $restart
|
||||
*/
|
||||
public function handleScriptBeginMap($mapUid, $restart) {
|
||||
$this->beginMap($mapUid, Formatter::parseBoolean($restart));
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the Begin of a Map
|
||||
*
|
||||
* @param string $uid
|
||||
* @param bool $restart
|
||||
*/
|
||||
private function beginMap($uid, $restart = false) {
|
||||
//If a restart occurred, first call the endMap to set variables back
|
||||
if ($restart) {
|
||||
$this->endMap();
|
||||
}
|
||||
|
||||
if ($this->mapBegan) {
|
||||
return;
|
||||
}
|
||||
$this->mapBegan = true;
|
||||
$this->mapEnded = false;
|
||||
|
||||
if (array_key_exists($uid, $this->maps)) {
|
||||
// Map already exists, only update index
|
||||
$this->currentMap = $this->maps[$uid];
|
||||
if (!$this->currentMap->nbCheckpoints || !$this->currentMap->nbLaps) {
|
||||
$rpcMap = $this->maniaControl->getClient()->getCurrentMapInfo();
|
||||
$this->currentMap->nbLaps = $rpcMap->nbLaps;
|
||||
$this->currentMap->nbCheckpoints = $rpcMap->nbCheckpoints;
|
||||
}
|
||||
}
|
||||
|
||||
// Restructure MapList if id is over 15
|
||||
$this->restructureMapList();
|
||||
|
||||
// Update the mx of the map (for update checks, etc.)
|
||||
$this->getMXManager()->fetchManiaExchangeMapInformation($this->currentMap);
|
||||
|
||||
// Trigger own BeginMap callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::BEGINMAP, $this->currentMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the End of a Map
|
||||
*/
|
||||
private function endMap() {
|
||||
if ($this->mapEnded) {
|
||||
return;
|
||||
}
|
||||
$this->mapEnded = true;
|
||||
$this->mapBegan = false;
|
||||
|
||||
// Trigger own EndMap callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::ENDMAP, $this->currentMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a map by its file path
|
||||
*
|
||||
* @param string $relativeFileName
|
||||
* @return Map
|
||||
*/
|
||||
public function fetchMapByFileName($relativeFileName) {
|
||||
$mapInfo = $this->maniaControl->getClient()->getMapInfo($relativeFileName);
|
||||
if (!$mapInfo) {
|
||||
return null;
|
||||
}
|
||||
return $this->initializeMap($mapInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle BeginMap callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleBeginMap(array $callback) {
|
||||
$this->beginMap($callback[1][0]["UId"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Script EndMap Callback
|
||||
*/
|
||||
public function handleScriptEndMap() {
|
||||
$this->endMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle EndMap Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleEndMap(array $callback) {
|
||||
$this->endMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Maps Modified Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function mapsModified(array $callback) {
|
||||
$this->updateFullMapList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Number of Maps
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getMapsCount() {
|
||||
return count($this->maps);
|
||||
}
|
||||
}
|
491
core/Maps/MapQueue.php
Normal file
491
core/Maps/MapQueue.php
Normal file
@ -0,0 +1,491 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Maps;
|
||||
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\NextMapException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\NotInListException;
|
||||
|
||||
/**
|
||||
* ManiaControl Map Queue Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class MapQueue implements CallbackListener, CommandListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CB_MAPQUEUE_CHANGED = 'MapQueue.MapQueueBoxChanged';
|
||||
|
||||
const SETTING_SKIP_MAP_ON_LEAVE = 'Skip Map when the requester leaves';
|
||||
const SETTING_SKIP_MAPQUEUE_ADMIN = 'Skip Map when admin leaves';
|
||||
const SETTING_MAPLIMIT_PLAYER = 'Maximum maps per player in the Map-Queue (-1 = unlimited)';
|
||||
const SETTING_MAPLIMIT_ADMIN = 'Maximum maps per admin (Admin+) in the Map-Queue (-1 = unlimited)';
|
||||
const SETTING_BUFFERSIZE = 'Size of the Map-Queue buffer (recently played maps)';
|
||||
const SETTING_PERMISSION_CLEAR_MAPQUEUE = 'Clear MapQueue';
|
||||
const SETTING_PERMISSION_QUEUE_BUFFER = 'Queue maps in buffer';
|
||||
|
||||
const ADMIN_COMMAND_CLEAR_MAPQUEUE = 'clearmapqueue';
|
||||
const ADMIN_COMMAND_CLEAR_JUKEBOX = 'clearjukebox';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $queuedMaps = array();
|
||||
private $nextMap = null;
|
||||
private $buffer = array();
|
||||
private $nextNoQueue = false;
|
||||
|
||||
/**
|
||||
* Construct a new map queue instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ENDMAP, $this, 'endMap');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::BEGINMAP, $this, 'beginMap');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_SKIP_MAP_ON_LEAVE, true);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_SKIP_MAPQUEUE_ADMIN, false);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAPLIMIT_PLAYER, 1);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAPLIMIT_ADMIN, -1);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_BUFFERSIZE, 10);
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CLEAR_MAPQUEUE, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_QUEUE_BUFFER, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
|
||||
// Admin Commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(self::ADMIN_COMMAND_CLEAR_JUKEBOX, $this, 'command_ClearMapQueue', true, 'Clears the Map-Queue.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(self::ADMIN_COMMAND_CLEAR_MAPQUEUE, $this, 'command_ClearMapQueue', true, 'Clears the Map-Queue.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('jb', 'jukebox', 'mapqueue'), $this, 'command_MapQueue', false, 'Shows current maps in Map-Queue.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't queue on the next MapChange
|
||||
*/
|
||||
public function dontQueueNextMapChange() {
|
||||
$this->nextNoQueue = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add current map to buffer on startup
|
||||
*/
|
||||
public function handleAfterInit() {
|
||||
$currentMap = $this->maniaControl->getMapManager()->getCurrentMap();
|
||||
$this->buffer[] = $currentMap->uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the map-queue via admin command clear map queue
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $admin
|
||||
*/
|
||||
public function command_ClearMapQueue(array $chatCallback, Player $admin) {
|
||||
$this->clearMapQueue($admin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the Map Queue
|
||||
*
|
||||
* @param Player $admin |null
|
||||
*/
|
||||
public function clearMapQueue(Player $admin = null) {
|
||||
if ($admin && !$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($admin && empty($this->queuedMaps)) {
|
||||
$this->maniaControl->getChat()->sendError('$fa0There are no maps in the jukebox!', $admin->login);
|
||||
return;
|
||||
}
|
||||
|
||||
//Destroy map - queue list
|
||||
$this->queuedMaps = array();
|
||||
|
||||
if ($admin) {
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$message = '$fa0' . $title . ' $<$fff' . $admin->nickname . '$> cleared the Map-Queue!';
|
||||
$this->maniaControl->getChat()->sendInformation($message);
|
||||
Logger::logInfo($message, true);
|
||||
}
|
||||
|
||||
// Trigger callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('clear'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the mapqueue/jukebox command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_MapQueue(array $chatCallback, Player $player) {
|
||||
$chatCommands = explode(' ', $chatCallback[1][2]);
|
||||
|
||||
if (isset($chatCommands[1])) {
|
||||
$listParam = strtolower($chatCommands[1]);
|
||||
switch ($listParam) {
|
||||
case 'list':
|
||||
$this->showMapQueue($player);
|
||||
break;
|
||||
case 'display':
|
||||
$this->showMapQueueManialink($player);
|
||||
break;
|
||||
case 'clear':
|
||||
$this->clearMapQueue($player);
|
||||
break;
|
||||
default:
|
||||
$this->showMapQueue($player);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$this->showMapQueue($player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show current mapqueue in the chat
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function showMapQueue(Player $player) {
|
||||
if (empty($this->queuedMaps)) {
|
||||
$this->maniaControl->getChat()->sendError('$fa0There are no maps in the jukebox!', $player->login);
|
||||
return;
|
||||
}
|
||||
|
||||
$message = '$fa0Upcoming maps in the Map-Queue:';
|
||||
$index = 1;
|
||||
foreach ($this->queuedMaps as $queuedMap) {
|
||||
$message .= ' $<$fff' . $index . '$>. [$<$fff' . Formatter::stripCodes($queuedMap[1]->name) . '$>]';
|
||||
$index++;
|
||||
}
|
||||
|
||||
$this->maniaControl->getChat()->sendInformation($message, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show current mapqueue in a manialink
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function showMapQueueManialink(Player $player) {
|
||||
if (empty($this->queuedMaps)) {
|
||||
$this->maniaControl->getChat()->sendError('There are no Maps in the Jukebox!', $player);
|
||||
return;
|
||||
}
|
||||
|
||||
$maps = array();
|
||||
foreach ($this->queuedMaps as $queuedMap) {
|
||||
array_push($maps, $queuedMap[1]);
|
||||
}
|
||||
|
||||
$this->maniaControl->getMapManager()->getMapList()->showMapList($player, $maps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current queue buffer
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getQueueBuffer() {
|
||||
return $this->buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add map as first map in queue (for /replay)
|
||||
*
|
||||
* @param Player $player
|
||||
* @param Map $map
|
||||
*/
|
||||
public function addFirstMapToMapQueue(Player $player, Map $map) {
|
||||
if ($map) {
|
||||
if (array_key_exists($map->uid, $this->queuedMaps)) {
|
||||
unset($this->queuedMaps[$map->uid]);
|
||||
}
|
||||
|
||||
array_unshift($this->queuedMaps, array($player, $map, true));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Map to the Map-Queue from Plugins or whatever
|
||||
*
|
||||
* @param $uid
|
||||
* @return bool
|
||||
*/
|
||||
public function serverAddMapToMapQueue($uid) {
|
||||
$map = $this->maniaControl->getMapManager()->getMapByUid($uid);
|
||||
|
||||
if (!$map) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->queuedMaps[$uid] = array(null, $map);
|
||||
|
||||
$this->maniaControl->getChat()->sendInformation('$fa0$<$fff' . $map->name . '$> has been added to the Map-Queue by the Server.');
|
||||
|
||||
// Trigger callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('add', $this->queuedMaps[$uid]));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Map to the map-queue
|
||||
*
|
||||
* @param string $login
|
||||
* @param string $uid
|
||||
*/
|
||||
public function addMapToMapQueue($login, $uid) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the Player is muted
|
||||
if ($player->isMuted()) {
|
||||
$this->maniaControl->getChat()->sendError('Muted Players are not allowed to queue a map.', $player);
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if player is allowed to add (another) map
|
||||
$isModerator = $this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
|
||||
$mapsForPlayer = 0;
|
||||
foreach ($this->queuedMaps as $queuedMap) {
|
||||
if ($queuedMap[0]->login == $login) {
|
||||
$mapsForPlayer++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($isModerator) {
|
||||
$maxAdmin = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MAPLIMIT_ADMIN);
|
||||
if ($maxAdmin >= 0 && $mapsForPlayer >= $maxAdmin) {
|
||||
$this->maniaControl->getChat()->sendError('You already have $<$fff' . $maxAdmin . '$> map(s) in the Map-Queue!', $login);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
$maxPlayer = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MAPLIMIT_PLAYER);
|
||||
if ($maxPlayer >= 0 && $mapsForPlayer >= $maxPlayer) {
|
||||
$this->maniaControl->getChat()->sendError('You already have $<$fff' . $maxPlayer . '$> map(s) in the Map-Queue!', $login);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the map is already juked
|
||||
$map = null;
|
||||
if ($uid instanceof Map) {
|
||||
$map = $uid;
|
||||
$uid = $map->uid;
|
||||
}
|
||||
if (array_key_exists($uid, $this->queuedMaps)) {
|
||||
$this->maniaControl->getChat()->sendError('That map is already in the Map-Queue!', $login);
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO recently maps not able to add to queue-amps setting, and management
|
||||
// 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)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$map) {
|
||||
$map = $this->maniaControl->getMapManager()->getMapByUid($uid);
|
||||
}
|
||||
|
||||
$this->queuedMaps[$uid] = array($player, $map);
|
||||
|
||||
$this->maniaControl->getChat()->sendInformation('$fa0$<$fff' . $map->name . '$> has been added to the Map-Queue by $<$fff' . $player->nickname . '$>.');
|
||||
|
||||
// Trigger callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('add', $this->queuedMaps[$uid]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a Map from the Map queue
|
||||
*
|
||||
* @param Player $player
|
||||
* @param string $uid
|
||||
*/
|
||||
public function removeFromMapQueue(Player $player, $uid) {
|
||||
if (!isset($this->queuedMaps[$uid])) {
|
||||
return;
|
||||
}
|
||||
/** @var Map $map */
|
||||
$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 . '$>.');
|
||||
|
||||
// Trigger callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('remove', $map));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on endmap
|
||||
*
|
||||
* @param Map $map
|
||||
*/
|
||||
public function endMap(Map $map = null) {
|
||||
//Don't queue next map (for example on skip to map)
|
||||
if ($this->nextNoQueue) {
|
||||
$this->nextNoQueue = false;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->nextMap = null;
|
||||
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];
|
||||
|
||||
// Check if map is added via replay vote/command
|
||||
if (isset($queuedMap[2]) && $queuedMap[2] === true) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Player found, so play this map (or if it got juked by the server)
|
||||
if ($player == null || $this->maniaControl->getPlayerManager()->getPlayer($player->login)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_SKIP_MAPQUEUE_ADMIN)) {
|
||||
//Check if the queuer is a admin
|
||||
if ($player->authLevel > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_MAPQUEUE_CHANGED, array('skip', $queuedMap[0]));
|
||||
|
||||
// Player not found, so remove the map from the mapqueue
|
||||
array_shift($this->queuedMaps);
|
||||
|
||||
$this->maniaControl->getChat()->sendInformation('$fa0$<$fff' . $queuedMap[0]->name . '$> is skipped because $<' . $player->nickname . '$> left the game!');
|
||||
}
|
||||
}
|
||||
|
||||
$this->nextMap = array_shift($this->queuedMaps);
|
||||
|
||||
//Check if Map Queue is empty
|
||||
if (!$this->nextMap || !isset($this->nextMap[1])) {
|
||||
return;
|
||||
}
|
||||
$map = $this->nextMap[1];
|
||||
|
||||
//Message only if it's juked by a player (not by the server)
|
||||
if ($this->nextMap[0]) {
|
||||
/** @var Map $map */
|
||||
$this->maniaControl->getChat()->sendInformation('$fa0Next map will be $<$fff' . $map->name . '$> as requested by $<' . $this->nextMap[0]->nickname . '$>.');
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->setNextMapIdent($map->uid);
|
||||
} catch (NextMapException $e) {
|
||||
} catch (NotInListException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on begin map
|
||||
*
|
||||
* @param Map $map
|
||||
*/
|
||||
public function beginMap(Map $map) {
|
||||
if (in_array($map->uid, $this->buffer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (count($this->buffer) >= $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_BUFFERSIZE)
|
||||
) {
|
||||
array_shift($this->buffer);
|
||||
}
|
||||
|
||||
$this->buffer[] = $map->uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the next Map if the next map is a queuedmap or null if it's not
|
||||
*
|
||||
* @return Map
|
||||
*/
|
||||
public function getNextMap() {
|
||||
return $this->nextMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first Queued Map
|
||||
*
|
||||
* @return array(Player $player, Map $map)
|
||||
*/
|
||||
public function getNextQueuedMap() {
|
||||
foreach ($this->queuedMaps as $queuedMap) {
|
||||
//return the first Queued Map
|
||||
return $queuedMap;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list with the indexes of the queued maps
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getQueuedMapsRanking() {
|
||||
$index = 1;
|
||||
$queuedMaps = array();
|
||||
foreach ($this->queuedMaps as $queuedMap) {
|
||||
$map = $queuedMap[1];
|
||||
$queuedMaps[$map->uid] = $index;
|
||||
$index++;
|
||||
}
|
||||
return $queuedMaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Queuer of a Map
|
||||
*
|
||||
* @param string $uid
|
||||
* @return mixed
|
||||
*/
|
||||
public function getQueuer($uid) {
|
||||
return $this->queuedMaps[$uid][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy Function for testing
|
||||
*/
|
||||
public function printAllMaps() {
|
||||
foreach ($this->queuedMaps as $map) {
|
||||
$map = $map[1];
|
||||
var_dump($map->name);
|
||||
}
|
||||
}
|
||||
}
|
360
core/Players/Player.php
Normal file
360
core/Players/Player.php
Normal file
@ -0,0 +1,360 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Players;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Utils\ClassUtil;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* Player Model Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Player {
|
||||
/*
|
||||
* Public Properties
|
||||
*/
|
||||
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 $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 $daysSinceZoneInscription = -1;
|
||||
|
||||
//Flags details
|
||||
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;
|
||||
|
||||
//SpectatorStatus details
|
||||
public $isSpectator = false;
|
||||
public $isTemporarySpectator = false;
|
||||
public $isPureSpectator = false;
|
||||
public $autoTarget = false;
|
||||
public $currentTargetId = 0;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $cache = array();
|
||||
|
||||
/**
|
||||
* Construct a new Player
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
* @param bool $connected
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl, $connected) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->isConnected = (bool)$connected;
|
||||
if ($connected) {
|
||||
$this->joinTime = time();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Login of the Player
|
||||
*
|
||||
* @param mixed $player
|
||||
* @return string
|
||||
*/
|
||||
public static function parseLogin($player) {
|
||||
if (is_object($player) && property_exists($player, 'login')) {
|
||||
return (string)$player->login;
|
||||
}
|
||||
return (string)$player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Escaped Nickname
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEscapedNickname() {
|
||||
$nickname = $this->nickname;
|
||||
if (!$nickname) {
|
||||
$nickname = $this->login;
|
||||
}
|
||||
return Formatter::escapeText($nickname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update from ManiaPlanet PlayerInfo structure
|
||||
*
|
||||
* @param \Maniaplanet\DedicatedServer\Structures\PlayerInfo $mpPlayer
|
||||
*/
|
||||
public function setInfo($mpPlayer) {
|
||||
$this->pid = $mpPlayer->playerId;
|
||||
$this->login = $mpPlayer->login;
|
||||
$this->nickname = Formatter::stripDirtyCodes($mpPlayer->nickName);
|
||||
$this->rawNickname = $mpPlayer->nickName;
|
||||
$this->teamId = $mpPlayer->teamId;
|
||||
$this->isOfficial = $mpPlayer->isInOfficialMode;
|
||||
|
||||
//Flag Details
|
||||
$this->forcedSpectatorState = $mpPlayer->forceSpectator;
|
||||
$this->isReferee = $mpPlayer->isReferee;
|
||||
$this->isPodiumReady = $mpPlayer->isPodiumReady;
|
||||
$this->isUsingStereoscopy = $mpPlayer->isUsingStereoscopy;
|
||||
$this->isServer = $mpPlayer->isServer;
|
||||
$this->isManagedByAnOtherServer = $mpPlayer->isManagedByAnOtherServer;
|
||||
$this->hasPlayerSlot = $mpPlayer->hasPlayerSlot;
|
||||
$this->hasJoinedGame = $mpPlayer->hasJoinedGame;
|
||||
$this->isBroadcasting = $mpPlayer->isBroadcasting;
|
||||
|
||||
//Spectator Status
|
||||
$this->isSpectator = $mpPlayer->spectator;
|
||||
$this->isTemporarySpectator = $mpPlayer->temporarySpectator;
|
||||
$this->isPureSpectator = $mpPlayer->pureSpectator;
|
||||
$this->autoTarget = $mpPlayer->autoTarget;
|
||||
$this->currentTargetId = $mpPlayer->currentTargetId;
|
||||
|
||||
if (!$this->nickname) {
|
||||
$this->nickname = $this->login;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update from ManiaPlanet PlayerDetailedInfo structure
|
||||
*
|
||||
* @param \Maniaplanet\DedicatedServer\Structures\PlayerDetailedInfo $mpPlayer
|
||||
*/
|
||||
public function setDetailedInfo($mpPlayer) {
|
||||
$this->pid = $mpPlayer->playerId;
|
||||
$this->login = $mpPlayer->login;
|
||||
$this->nickname = Formatter::stripDirtyCodes($mpPlayer->nickName);
|
||||
$this->rawNickname = $mpPlayer->nickName;
|
||||
$this->path = $mpPlayer->path;
|
||||
$this->language = $mpPlayer->language;
|
||||
$this->avatar = $mpPlayer->avatar->fileName;
|
||||
$this->allies = $mpPlayer->allies;
|
||||
$this->clubLink = $mpPlayer->clubLink;
|
||||
$this->teamId = $mpPlayer->teamId;
|
||||
$this->isOfficial = $mpPlayer->isInOfficialMode;
|
||||
$this->ladderScore = $mpPlayer->ladderStats->playerRankings[0]->score;
|
||||
$this->ladderRank = $mpPlayer->ladderStats->playerRankings[0]->ranking;
|
||||
$this->ladderStats = $mpPlayer->ladderStats;
|
||||
$this->daysSinceZoneInscription = $mpPlayer->hoursSinceZoneInscription / 24;
|
||||
$this->ipAddress = $mpPlayer->iPAddress;
|
||||
$this->clientVersion = $mpPlayer->clientVersion;
|
||||
$this->downloadRate = $mpPlayer->downloadRate;
|
||||
$this->uploadRate = $mpPlayer->uploadRate;
|
||||
$this->skins = $mpPlayer->skins;
|
||||
|
||||
if (!$this->nickname) {
|
||||
$this->nickname = $this->login;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if player is not a real player
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFakePlayer() {
|
||||
return ($this->pid <= 0 || substr($this->login, 0, 1) === '*');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get province
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProvince() {
|
||||
return $this->getPathPart(3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the specified Part of the Path
|
||||
*
|
||||
* @param int $partNumber
|
||||
* @return string
|
||||
*/
|
||||
public function getPathPart($partNumber) {
|
||||
$pathParts = explode('|', $this->path);
|
||||
for ($partIndex = $partNumber; $partIndex >= 0; $partIndex--) {
|
||||
if (isset($pathParts[$partIndex])) {
|
||||
return $pathParts[$partIndex];
|
||||
}
|
||||
}
|
||||
return $this->path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Country
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCountry() {
|
||||
return $this->getPathPart(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Continent
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContinent() {
|
||||
return $this->getPathPart(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Flags of the Player
|
||||
*
|
||||
* @param $flags
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the Spectator Status of the player
|
||||
*
|
||||
* @param $spectatorStatus
|
||||
*/
|
||||
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->currentTargetId = intval($spectatorStatus / 10000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Cache with the given Name
|
||||
*
|
||||
* @param $object
|
||||
* @param string $cacheName
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCache($object, $cacheName) {
|
||||
$className = ClassUtil::getClass($object);
|
||||
if (isset($this->cache[$className . $cacheName])) {
|
||||
return $this->cache[$className . $cacheName];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Cache Data for the given Name
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $cacheName
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function setCache($object, $cacheName, $data) {
|
||||
$className = ClassUtil::getClass($object);
|
||||
$this->cache[$className . $cacheName] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy a Cache
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $cacheName
|
||||
*/
|
||||
public function destroyCache($object, $cacheName) {
|
||||
$className = ClassUtil::getClass($object);
|
||||
unset($this->cache[$className . $cacheName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the Player's Temporary Data
|
||||
*/
|
||||
public function clearCache() {
|
||||
$this->cache = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Player Data
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $dataName
|
||||
* @param int $serverIndex
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlayerData($object, $dataName, $serverIndex = -1) {
|
||||
return $this->maniaControl->getPlayerManager()->getPlayerDataManager()->getPlayerData($object, $dataName, $this, $serverIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Player Data and stores it in the Database
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $dataName
|
||||
* @param mixed $value
|
||||
* @param int $serverIndex
|
||||
* @return bool
|
||||
*/
|
||||
public function setPlayerData($object, $dataName, $value, $serverIndex = -1) {
|
||||
return $this->maniaControl->getPlayerManager()->getPlayerDataManager()->setPlayerData($object, $dataName, $this, $value, $serverIndex);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if a Player is muted
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMuted() {
|
||||
$ignoreList = $this->maniaControl->getClient()->getIgnoreList(100, 0);
|
||||
foreach ($ignoreList as $ignoredPlayers) {
|
||||
if ($ignoredPlayers->login === $this->login) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Var_Dump the Player
|
||||
*/
|
||||
public function dump() {
|
||||
var_dump(json_decode(json_encode($this)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Var_Dump the Players Cache
|
||||
*/
|
||||
public function dumpCache() {
|
||||
var_dump($this->cache);
|
||||
}
|
||||
}
|
523
core/Players/PlayerActions.php
Normal file
523
core/Players/PlayerActions.php
Normal file
@ -0,0 +1,523 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Players;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\ManiaLink;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\AlreadyInListException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\FaultException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\NotInListException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\PlayerStateException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\ServerOptionsException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
|
||||
/**
|
||||
* Player Actions Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerActions {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TEAM_BLUE = 0;
|
||||
const TEAM_RED = 1;
|
||||
const SPECTATOR_USER_SELECTABLE = 0;
|
||||
const SPECTATOR_SPECTATOR = 1;
|
||||
const SPECTATOR_PLAYER = 2;
|
||||
const SPECTATOR_BUT_KEEP_SELECTABLE = 3;
|
||||
|
||||
/*
|
||||
* Permission Setting Constants
|
||||
*/
|
||||
const SETTING_PERMISSION_FORCE_PLAYER_PLAY = 'Force Player to Play';
|
||||
const SETTING_PERMISSION_FORCE_PLAYER_TEAM = 'Force Player to Team';
|
||||
const SETTING_PERMISSION_FORCE_PLAYER_SPEC = 'Force Player to Spec';
|
||||
const SETTING_PERMISSION_MUTE_PLAYER = 'Mute Player';
|
||||
const SETTING_PERMISSION_WARN_PLAYER = 'Warn Player';
|
||||
const SETTING_PERMISSION_KICK_PLAYER = 'Kick Player';
|
||||
const SETTING_PERMISSION_BAN_PLAYER = 'Ban Player';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new PlayerActions instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_BAN_PLAYER, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_KICK_PLAYER, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_WARN_PLAYER, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_MUTE_PLAYER, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_PLAY, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_TEAM, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_FORCE_PLAYER_SPEC, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a Player to a certain Team
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param int $teamId
|
||||
*/
|
||||
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;
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$target || !$admin) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($target->isSpectator) {
|
||||
try {
|
||||
if (!$this->forcePlayerToPlay($adminLogin, $targetLogin, true, false)) {
|
||||
return;
|
||||
}
|
||||
} catch (FaultException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->forcePlayerTeam($target->login, $teamId);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->forcePlayerToPlay($adminLogin, $targetLogin);
|
||||
return;
|
||||
} catch (GameModeException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
$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 (!$chatMessage) {
|
||||
return;
|
||||
}
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a Player to Play
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param bool $userIsAbleToSelect
|
||||
* @param bool $displayAnnouncement
|
||||
* @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;
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$target) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_PLAYER);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($userIsAbleToSelect) {
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($target->login, self::SPECTATOR_USER_SELECTABLE);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Announce force
|
||||
if ($displayAnnouncement) {
|
||||
$chatMessage = $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' to Play!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force a Player to Spectator
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param int $spectatorState
|
||||
* @param bool $releaseSlot
|
||||
*/
|
||||
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;
|
||||
}
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$admin || !$target || $target->isSpectator) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($target->login, $spectatorState);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $admin->login);
|
||||
return;
|
||||
}
|
||||
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' forced ' . $target->getEscapedNickname() . ' to Spectator!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
|
||||
if ($releaseSlot) {
|
||||
// Free player slot
|
||||
try {
|
||||
$this->maniaControl->getClient()->spectatorReleasePlayerSlot($target->login);
|
||||
} catch (PlayerStateException $e) {
|
||||
} catch (UnknownPlayerException $e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UnMute a Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->unIgnore($targetLogin);
|
||||
} catch (NotInListException $e) {
|
||||
$this->maniaControl->getChat()->sendError('Player is not ignored!', $adminLogin);
|
||||
return;
|
||||
}
|
||||
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' un-muted ' . $target->getEscapedNickname() . '!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mute a Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->ignore($targetLogin);
|
||||
} catch (AlreadyInListException $e) {
|
||||
$this->maniaControl->getChat()->sendError("Player already ignored!", $adminLogin);
|
||||
return;
|
||||
}
|
||||
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' muted ' . $target->getEscapedNickname() . '!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Warn a Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
if (!$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Display warning message
|
||||
$message = '$s$f00This is an administrative warning.{br}{br}$gWhatever you wrote or you have done is against {br} our server\'s policy.
|
||||
{br}Not respecting other players, or{br}using offensive language might result in a{br}$f00kick, or ban $ff0the next time.
|
||||
{br}{br}$gThe server administrators.';
|
||||
$message = preg_split('/{br}/', $message);
|
||||
|
||||
// Build Manialink
|
||||
$width = 80;
|
||||
$height = 50;
|
||||
$quadStyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowStyle();
|
||||
$quadSubstyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowSubStyle();
|
||||
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$frame = new Frame();
|
||||
$maniaLink->add($frame);
|
||||
$frame->setPosition(0, 10);
|
||||
|
||||
// Background
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$backgroundQuad->setSize($width, $height);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
// Close Quad (X)
|
||||
$closeQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($closeQuad);
|
||||
$closeQuad->setPosition($width * 0.473, $height * 0.457, 3);
|
||||
$closeQuad->setSize(6, 6);
|
||||
$closeQuad->setSubStyle($closeQuad::SUBSTYLE_QuitRace);
|
||||
$closeQuad->setAction(ManialinkManager::ACTION_CLOSEWIDGET);
|
||||
|
||||
// Headline
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setY($height / 2 - 5);
|
||||
$label->setStyle($label::STYLE_TextCardMedium);
|
||||
$label->setTextSize(4);
|
||||
$label->setText('Administrative Warning');
|
||||
$label->setTextColor('f00');
|
||||
|
||||
$posY = $height / 2 - 15;
|
||||
foreach ($message as $line) {
|
||||
// Message lines
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setStyle($label::STYLE_TextCardMedium);
|
||||
$label->setText($line);
|
||||
$label->setTextColor('ff0');
|
||||
$label->setTextSize(1.3);
|
||||
$posY -= 4;
|
||||
}
|
||||
|
||||
// Display manialink
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $target);
|
||||
|
||||
// Announce warning
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' warned ' . $target->getEscapedNickname() . '!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::log($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick a Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param string $message
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
try {
|
||||
if ($target->isFakePlayer()) {
|
||||
$this->maniaControl->getClient()->disconnectFakePlayer($target->login);
|
||||
} else {
|
||||
$this->maniaControl->getClient()->kick($target->login, $message);
|
||||
}
|
||||
} 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() . '!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban a Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param string $message
|
||||
*/
|
||||
public function banPlayer($adminLogin, $targetLogin, $message = '') {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
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()) {
|
||||
$this->maniaControl->getChat()->sendError('It is not possible to Ban a bot', $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->maniaControl->getClient()->ban($target->login, $message);
|
||||
|
||||
// Announce ban
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' banned ' . $target->getEscapedNickname() . '!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grands the Player an Authorization Level
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
* @param int $authLevel
|
||||
*/
|
||||
public function grandAuthLevel($adminLogin, $targetLogin, $authLevel) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$admin || !$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
$authLevelName = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($authLevel);
|
||||
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)
|
||||
) {
|
||||
$this->maniaControl->getChat()->sendError("This Player is already {$authLevelName}!", $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, $authLevel);
|
||||
if (!$success) {
|
||||
$this->maniaControl->getChat()->sendError('Error occurred.', $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Announce granting
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' added ' . $target->getEscapedNickname() . ' as $< ' . $authLevelName . '$>!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes all Rights from the Player
|
||||
*
|
||||
* @param string $adminLogin
|
||||
* @param string $targetLogin
|
||||
*/
|
||||
public function revokeAuthLevel($adminLogin, $targetLogin) {
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
if (!$admin || !$target) {
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
) {
|
||||
$this->maniaControl->getChat()->sendError("MasterAdmins can't be removed!", $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, AuthenticationManager::AUTH_LEVEL_PLAYER);
|
||||
if (!$success) {
|
||||
$this->maniaControl->getChat()->sendError('Error occurred.', $admin);
|
||||
return;
|
||||
}
|
||||
|
||||
// Announce revoke
|
||||
$title = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($admin->authLevel);
|
||||
$chatMessage = $title . ' ' . $admin->getEscapedNickname() . ' revoked the Rights of ' . $target->getEscapedNickname() . '!';
|
||||
$this->maniaControl->getChat()->sendInformation($chatMessage);
|
||||
Logger::logInfo($chatMessage, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a Player is muted
|
||||
*
|
||||
* @deprecated see Player/isMuted()
|
||||
*/
|
||||
public function isPlayerMuted($login) {
|
||||
return $this->maniaControl->getPlayerManager()->getPlayer($login)->isMuted();
|
||||
}
|
||||
}
|
368
core/Players/PlayerCommands.php
Normal file
368
core/Players/PlayerCommands.php
Normal file
@ -0,0 +1,368 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Players;
|
||||
|
||||
use FML\Controls\Quads\Quad_Icons128x32_1;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Server\Server;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnavailableFeatureException;
|
||||
|
||||
/**
|
||||
* Class offering various Admin Commands related to Players
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerCommands implements CommandListener, ManialinkPageAnswerListener, CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_BALANCE_TEAMS = 'PlayerCommands.BalanceTeams';
|
||||
const ACTION_OPEN_PLAYERLIST = 'PlayerCommands.OpenPlayerList';
|
||||
const SETTING_PERMISSION_ADD_BOT = 'Add Bot';
|
||||
const SETTING_PERMISSION_TEAM_BALANCE = 'Balance Teams';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new Player Commands Instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Admin commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('balance', 'teambalance', 'autoteambalance'), $this, 'command_TeamBalance', true, 'Balances the teams.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('kick', $this, 'command_Kick', true, 'Kicks player from the server.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('ban', $this, 'command_Ban', true, 'Bans player from the server.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('forcespec', 'forcespectator'), $this, 'command_ForceSpectator', true, 'Forces player into spectator.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('forceplay', $this, 'command_ForcePlay', true, 'Forces player into Play mode.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('forceblue', $this, 'command_ForceBlue', true, 'Forces player into blue team.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('forcered', $this, 'command_ForceRed', true, 'Forces player into red team.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('addbots', 'addbot'), $this, 'command_AddFakePlayers', true, 'Adds bots to the game.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('removebot', 'removebots'), $this, 'command_RemoveFakePlayers', true, 'Removes bots from the game.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('mute', $this, 'command_MutePlayer', true, 'Mutes a player (prevents player from chatting).');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('unmute', $this, 'command_UnmutePlayer', true, 'Unmute a player (enables player to chat again).');
|
||||
|
||||
// Player commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener(array('player', 'players'), $this, 'command_playerList', false, 'Shows players currently on the server.');
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_ADD_BOT, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_TEAM_BALANCE, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Server::CB_TEAM_MODE_CHANGED, $this, 'teamStatusChanged');
|
||||
|
||||
// Action Open PlayerList
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_OPEN_PLAYERLIST, $this, 'command_playerList');
|
||||
$itemQuad = new Quad_UIConstruction_Buttons();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_Author);
|
||||
$itemQuad->setAction(self::ACTION_OPEN_PLAYERLIST);
|
||||
$this->maniaControl->getActionsMenu()->addMenuItem($itemQuad, true, 15, 'Open PlayerList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle TeamStatusChanged
|
||||
*
|
||||
* @param bool $teamMode
|
||||
*/
|
||||
public function teamStatusChanged($teamMode) {
|
||||
//Add Balance Team Icon if it's a teamMode
|
||||
if ($teamMode) {
|
||||
// Action Balance Teams
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_BALANCE_TEAMS, $this, 'command_TeamBalance');
|
||||
$itemQuad = new Quad_Icons128x32_1();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_RT_Team);
|
||||
$itemQuad->setAction(self::ACTION_BALANCE_TEAMS);
|
||||
$this->maniaControl->getActionsMenu()->addMenuItem($itemQuad, false, 40, 'Balance Teams');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //teambalance command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_TeamBalance(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_TEAM_BALANCE)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->autoTeamBalance();
|
||||
} catch (GameModeException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' balanced Teams!');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //kick command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_Kick(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_KICK_PLAYER)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chat[1][2], 3);
|
||||
if (count($params) <= 1) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No Login given! Example: '//kick login'", $player->login);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $params[1];
|
||||
$message = '';
|
||||
if (isset($params[2])) {
|
||||
$message = $params[2];
|
||||
}
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->kickPlayer($player->login, $targetLogin, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //ban command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_Ban(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_BAN_PLAYER)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chat[1][2], 3);
|
||||
if (count($params) <= 1) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No Login given! Example: '//ban login'", $player->login);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $params[1];
|
||||
$message = '';
|
||||
if (isset($params[2])) {
|
||||
$message = $params[2];
|
||||
}
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->banPlayer($player->login, $targetLogin, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //warn Command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_Warn(array $chatCallback, Player $player) {
|
||||
$params = explode(' ', $chatCallback[1][2], 3);
|
||||
if (count($params) <= 1) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No Login given! Example: '//warn login'", $player->login);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $params[1];
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->warnPlayer($player->login, $targetLogin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //forcespec command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_ForceSpectator(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_SPEC)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chat[1][2]);
|
||||
if (count($params) <= 1) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No Login given! Example: '//forcespec login'", $player->login);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $params[1];
|
||||
|
||||
if (isset($params[2]) && is_numeric($params[2])) {
|
||||
$type = (int)$params[2];
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToSpectator($player->login, $targetLogin, $type);
|
||||
} else {
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToSpectator($player->login, $targetLogin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //forceplay command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_ForcePlay(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_PLAY)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chat[1][2]);
|
||||
if (!isset($params[1])) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No Login given! Example: '//forceplay login'", $player->login);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $params[1];
|
||||
|
||||
$type = 2;
|
||||
if (isset($params[2]) && is_numeric($params[2])) {
|
||||
$type = (int)$params[2];
|
||||
}
|
||||
$selectable = ($type === 2);
|
||||
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToPlay($player->login, $targetLogin, $selectable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //forceblue command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_ForceBlue(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_TEAM)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chat[1][2]);
|
||||
if (!isset($params[1])) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No Login given! Example: '//forceblue login'", $player->login);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $params[1];
|
||||
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToTeam($player->login, $targetLogin, PlayerActions::TEAM_BLUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //forcered command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_ForceRed(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_TEAM)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chat[1][2]);
|
||||
if (!isset($params[1])) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No Login given! Example: '//forcered login'", $player->login);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $params[1];
|
||||
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToTeam($player->login, $targetLogin, PlayerActions::TEAM_RED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //addfakeplayers command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_AddFakePlayers(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_ADD_BOT)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$amount = 1;
|
||||
$messageParts = explode(' ', $chatCallback[1][2]);
|
||||
if (isset($messageParts[1]) && is_numeric($messageParts[1])) {
|
||||
$amount = intval($messageParts[1]);
|
||||
}
|
||||
|
||||
try {
|
||||
for ($i = 0; $i < $amount; $i++) {
|
||||
$this->maniaControl->getClient()->connectFakePlayer();
|
||||
}
|
||||
$this->maniaControl->getChat()->sendSuccess('Fake players connected!', $player);
|
||||
} catch (UnavailableFeatureException $e) {
|
||||
$this->maniaControl->getChat()->sendSuccess('Error while connecting a Fake-Player.', $player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //removefakeplayers command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_RemoveFakePlayers(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_ADD_BOT)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$this->maniaControl->getClient()->disconnectFakePlayer('*');
|
||||
$this->maniaControl->getChat()->sendSuccess('Fake players disconnected!', $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //mute Command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $admin
|
||||
*/
|
||||
public function command_MutePlayer(array $chatCallback, Player $admin) {
|
||||
$commandParts = explode(' ', $chatCallback[1][2]);
|
||||
if (count($commandParts) <= 1) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No login specified! Example: '//mute login'", $admin);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $commandParts[1];
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->mutePlayer($admin->login, $targetLogin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //unmute Command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $admin
|
||||
*/
|
||||
public function command_UnmutePlayer(array $chatCallback, Player $admin) {
|
||||
$commandParts = explode(' ', $chatCallback[1][2]);
|
||||
if (count($commandParts) <= 1) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo("No login specified! Example: '//unmute login'", $admin);
|
||||
return;
|
||||
}
|
||||
$targetLogin = $commandParts[1];
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->unMutePlayer($admin->login, $targetLogin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Player list command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_playerList(array $chatCallback, Player $player) {
|
||||
$this->maniaControl->getPlayerManager()->getPlayerList()->addPlayerToShownList($player, PlayerList::SHOWN_MAIN_WINDOW);
|
||||
$this->maniaControl->getPlayerManager()->getPlayerList()->showPlayerList($player);
|
||||
}
|
||||
}
|
352
core/Players/PlayerDataManager.php
Normal file
352
core/Players/PlayerDataManager.php
Normal file
@ -0,0 +1,352 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Players;
|
||||
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Utils\ClassUtil;
|
||||
|
||||
/**
|
||||
* Player Data Manager
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerDataManager {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TABLE_PLAYERDATAMETADATA = 'mc_playerdata_metadata';
|
||||
const TABLE_PLAYERDATA = 'mc_playerdata';
|
||||
const TYPE_STRING = 'string';
|
||||
const TYPE_INT = 'int';
|
||||
const TYPE_REAL = 'real';
|
||||
const TYPE_BOOL = 'bool';
|
||||
const TYPE_ARRAY = 'array';
|
||||
const ARRAY_DELIMITER = ';;';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $metaData = array();
|
||||
private $storedData = array();
|
||||
|
||||
/**
|
||||
* Construct a new player manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
// Store Stats MetaData
|
||||
$this->storeMetaData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize necessary database tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$defaultType = "'" . self::TYPE_STRING . "'";
|
||||
$typeSet = $defaultType . ",'" . self::TYPE_INT . "','" . self::TYPE_REAL . "','" . self::TYPE_BOOL . "','" . self::TYPE_ARRAY . "'";
|
||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLAYERDATAMETADATA . "` (
|
||||
`dataId` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`class` varchar(100) NOT NULL,
|
||||
`dataName` varchar(100) NOT NULL,
|
||||
`type` set({$typeSet}) NOT NULL DEFAULT {$defaultType},
|
||||
`defaultValue` varchar(150) NOT NULL,
|
||||
`description` varchar(150) NOT NULL,
|
||||
PRIMARY KEY (`dataId`),
|
||||
UNIQUE KEY `name` (`class`, `dataName`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Player-Data MetaData' AUTO_INCREMENT=1;";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
|
||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLAYERDATA . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`serverIndex` int(11) NOT NULL,
|
||||
`playerId` int(11) NOT NULL,
|
||||
`dataId` int(11) NOT NULL,
|
||||
`value` varchar(150) NOT NULL,
|
||||
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `unique` (`dataId`,`playerId`,`serverIndex`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Player Data' AUTO_INCREMENT=1;";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store Meta Data from the Database in the Ram
|
||||
*/
|
||||
private function storeMetaData() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
|
||||
$query = "SELECT * FROM `" . self::TABLE_PLAYERDATAMETADATA . "`;";
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return;
|
||||
}
|
||||
|
||||
while ($row = $result->fetch_object()) {
|
||||
$this->metaData[$row->class . $row->dataName] = $row;
|
||||
}
|
||||
$result->free();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys the stored PlayerData (Method get called by PlayerManager, so don't call it anywhere else)
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function destroyPlayerData(Player $player) {
|
||||
unset($this->storedData[$player->index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the Player-Data MetaData
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $dataName
|
||||
* @param mixed $default
|
||||
* @param string $dataDescription (optional)
|
||||
* @return bool
|
||||
*/
|
||||
public function defineMetaData($object, $dataName, $default, $dataDescription = '') {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$className = ClassUtil::getClass($object);
|
||||
|
||||
$query = "INSERT INTO `" . self::TABLE_PLAYERDATAMETADATA . "` (
|
||||
`class`,
|
||||
`dataName`,
|
||||
`type`,
|
||||
`defaultValue`,
|
||||
`description`
|
||||
) VALUES (
|
||||
?, ?, ?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`type` = VALUES(`type`),
|
||||
`defaultValue` = VALUES(`defaultValue`),
|
||||
`description` = VALUES(`description`);";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$type = $this->getType($default);
|
||||
|
||||
$statement->bind_param('sssss', $className, $dataName, $type, $default, $dataDescription);
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
$statement->close();
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Type of a Parameter
|
||||
*
|
||||
* @param mixed $param
|
||||
* @return string
|
||||
*/
|
||||
private function getType($param) {
|
||||
if (is_int($param)) {
|
||||
return self::TYPE_INT;
|
||||
}
|
||||
if (is_real($param)) {
|
||||
return self::TYPE_REAL;
|
||||
}
|
||||
if (is_bool($param)) {
|
||||
return self::TYPE_BOOL;
|
||||
}
|
||||
if (is_string($param)) {
|
||||
return self::TYPE_STRING;
|
||||
}
|
||||
if (is_array($param)) {
|
||||
return self::TYPE_ARRAY;
|
||||
}
|
||||
trigger_error('Unsupported data type. ' . print_r($param, true));
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Player Data
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $dataName
|
||||
* @param Player $player
|
||||
* @param int $serverIndex
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPlayerData($object, $dataName, Player $player, $serverIndex = -1) {
|
||||
$className = ClassUtil::getClass($object);
|
||||
|
||||
$meta = $this->metaData[$className . $dataName];
|
||||
|
||||
// Check if data is already in the ram
|
||||
if (isset($this->storedData[$player->index]) && isset($this->storedData[$player->index][$meta->dataId])) {
|
||||
return $this->storedData[$player->index][$meta->dataId];
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$dataQuery = "SELECT `value` FROM `" . self::TABLE_PLAYERDATA . "`
|
||||
WHERE `dataId` = ?
|
||||
AND `playerId` = ?
|
||||
AND `serverIndex` = ?;";
|
||||
$dataStatement = $mysqli->prepare($dataQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
$dataStatement->bind_param('iii', $meta->dataId, $player->index, $serverIndex);
|
||||
$dataStatement->execute();
|
||||
if ($dataStatement->error) {
|
||||
trigger_error($dataStatement->error);
|
||||
return null;
|
||||
}
|
||||
$dataStatement->store_result();
|
||||
if ($dataStatement->num_rows <= 0) {
|
||||
$this->setPlayerData($object, $dataName, $player, $meta->defaultValue, $serverIndex);
|
||||
return $meta->defaultValue;
|
||||
}
|
||||
$dataStatement->bind_result($value);
|
||||
$dataStatement->fetch();
|
||||
$dataStatement->free_result();
|
||||
$dataStatement->close();
|
||||
$data = $this->castSetting($meta->type, $value);
|
||||
|
||||
// Store setting in the ram
|
||||
if (!isset($this->storedData[$player->index])) {
|
||||
$this->storedData[$player->index] = array();
|
||||
}
|
||||
$this->storedData[$player->index][$meta->dataId] = $data;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a PlayerData to a specific defined statMetaData
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $dataName
|
||||
* @param Player $player
|
||||
* @param mixed $value
|
||||
* @param int $serverIndex (empty if it's global)
|
||||
* @return bool
|
||||
*/
|
||||
public function setPlayerData($object, $dataName, Player $player, $value, $serverIndex = -1) {
|
||||
$className = ClassUtil::getClass($object);
|
||||
if (!$player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$dataId = $this->getMetaDataId($className, $dataName);
|
||||
if (!$dataId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "INSERT INTO `" . self::TABLE_PLAYERDATA . "` (
|
||||
`serverIndex`,
|
||||
`playerId`,
|
||||
`dataId`,
|
||||
`value`
|
||||
) VALUES (
|
||||
?, ?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`value` = VALUES(`value`);";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$statement->bind_param('iiis', $serverIndex, $player->index, $dataId, $value);
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
$statement->close();
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
|
||||
// Store changed value
|
||||
if (!isset($this->storedData[$player->index])) {
|
||||
$this->storedData[$player->index] = array();
|
||||
}
|
||||
$this->storedData[$player->index][$dataId] = $value;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Id of the MetaData
|
||||
*
|
||||
* @param string $className
|
||||
* @param string $statName
|
||||
* @return int
|
||||
*/
|
||||
private function getMetaDataId($className, $statName) {
|
||||
if (isset($this->metaData[$className . $statName])) {
|
||||
$stat = $this->metaData[$className . $statName];
|
||||
return (int)$stat->dataId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast a Setting to the given Type
|
||||
*
|
||||
* @param string $type
|
||||
* @param mixed $value
|
||||
* @return mixed
|
||||
*/
|
||||
private function castSetting($type, $value) {
|
||||
if ($type === self::TYPE_INT) {
|
||||
return (int)$value;
|
||||
}
|
||||
if ($type === self::TYPE_REAL) {
|
||||
return (float)$value;
|
||||
}
|
||||
if ($type === self::TYPE_BOOL) {
|
||||
return (bool)$value;
|
||||
}
|
||||
if ($type === self::TYPE_STRING) {
|
||||
return (string)$value;
|
||||
}
|
||||
if ($type === self::TYPE_ARRAY) {
|
||||
return explode(self::ARRAY_DELIMITER, $value);
|
||||
}
|
||||
trigger_error('Unsupported data type. ' . print_r($type, true));
|
||||
return $value;
|
||||
}
|
||||
}
|
278
core/Players/PlayerDetailed.php
Normal file
278
core/Players/PlayerDetailed.php
Normal file
@ -0,0 +1,278 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Players;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Button;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\ManiaLink;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Statistics\StatisticManager;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* Player Detailed Page
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerDetailed {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const STATS_PER_COLUMN = 13;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new Player Detailed Instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Settings
|
||||
$this->width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$this->height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
$this->quadStyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowStyle();
|
||||
$this->quadSubstyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowSubStyle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a Frame with detailed Information about the Target Player
|
||||
*
|
||||
* @param Player $player
|
||||
* @param string $targetLogin
|
||||
*/
|
||||
public function showPlayerDetailed(Player $player, $targetLogin) {
|
||||
/** @var Player $target */
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
// Create ManiaLink
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$script = $maniaLink->getScript();
|
||||
|
||||
// Main frame
|
||||
$frame = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultListFrame($script);
|
||||
$maniaLink->add($frame);
|
||||
|
||||
// Create script and features
|
||||
$script = new Script();
|
||||
$maniaLink->setScript($script);
|
||||
|
||||
$posY = $this->height / 2 - 7;
|
||||
|
||||
//Nation Quad
|
||||
$countryQuad = new Quad();
|
||||
$frame->add($countryQuad);
|
||||
$countryQuad->setImage("file://ZoneFlags/Login/{$targetLogin}/country");
|
||||
$countryQuad->setPosition(-$this->width / 2 + 10, $posY);
|
||||
$countryQuad->setSize(5, 5);
|
||||
$countryQuad->setZ(-0.1);
|
||||
$countryQuad->setHAlign($countryQuad::LEFT);
|
||||
|
||||
//Nickname
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setPosition(-$this->width / 2 + 15, $posY);
|
||||
$label->setText($target->nickname);
|
||||
$label->setHAlign($label::LEFT);
|
||||
|
||||
|
||||
//Define MainLabel (Login)
|
||||
$posY -= 8;
|
||||
$mainLabel = new Label_Text();
|
||||
$frame->add($mainLabel);
|
||||
$mainLabel->setPosition(-$this->width / 2 + 10, $posY);
|
||||
$mainLabel->setTextSize(1.2);
|
||||
$mainLabel->setHAlign($mainLabel::LEFT);
|
||||
$mainLabel->setText('Login: ');
|
||||
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Nation: ');
|
||||
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Province: ');
|
||||
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Authorization: ');
|
||||
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText("Ladder Rank:");
|
||||
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Ladder Score: ');
|
||||
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Inscribed Zone: ');
|
||||
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Avatar');
|
||||
|
||||
//Login
|
||||
$posY = $this->height / 2 - 15;
|
||||
$mainLabel = new Label_Text();
|
||||
$frame->add($mainLabel);
|
||||
$mainLabel->setPosition(-$this->width / 2 + 30, $posY);
|
||||
$mainLabel->setText($target->login);
|
||||
$mainLabel->setTextSize(1.2);
|
||||
$mainLabel->setHAlign($mainLabel::LEFT);
|
||||
|
||||
//Country
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText($target->getCountry());
|
||||
|
||||
//Province
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText($target->getProvince());
|
||||
|
||||
//AuthLevel
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText($this->maniaControl->getAuthenticationManager()->getAuthLevelName($target->authLevel));
|
||||
|
||||
//LadderRank
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText($target->ladderRank);
|
||||
|
||||
//LadderScore
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText(round($target->ladderScore, 2));
|
||||
|
||||
//Played Since
|
||||
$posY -= 5;
|
||||
$label = clone $mainLabel;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText(date('d M Y', time() - 3600 * 24 * $target->daysSinceZoneInscription));
|
||||
|
||||
$quad = new Quad();
|
||||
$frame->add($quad);
|
||||
$quad->setImage('file://Avatars/' . $targetLogin . "/default");
|
||||
$quad->setPosition(-$this->width / 2 + 50, -$this->height / 2 + 34);
|
||||
$quad->setAlign($quad::RIGHT, $quad::TOP);
|
||||
$quad->setSize(20, 20);
|
||||
|
||||
//Statistics
|
||||
$frame->add($this->statisticsFrame($target));
|
||||
|
||||
|
||||
$quad = new Label_Button();
|
||||
$frame->add($quad);
|
||||
$quad->setStyle($quad::STYLE_CardMain_Quit);
|
||||
$quad->setHAlign($quad::LEFT);
|
||||
$quad->setScale(0.75);
|
||||
$quad->setText('Back');
|
||||
$quad->setPosition(-$this->width / 2 + 7, -$this->height / 2 + 7);
|
||||
$quad->setAction(PlayerCommands::ACTION_OPEN_PLAYERLIST);
|
||||
|
||||
// render and display xml
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'PlayerDetailed');
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a Frame with Statistics about the given Player
|
||||
*
|
||||
* @param Player $player
|
||||
* @return Frame
|
||||
*/
|
||||
public function statisticsFrame(Player $player) {
|
||||
$frame = new Frame();
|
||||
|
||||
$playerStats = $this->maniaControl->getStatisticManager()->getAllPlayerStats($player);
|
||||
$posY = $this->height / 2 - 15;
|
||||
$posX = -$this->width / 2 + 52;
|
||||
$index = 1;
|
||||
|
||||
foreach ($playerStats as $stat) {
|
||||
$value = (float)$stat[1];
|
||||
if (!$value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$statProperties = $stat[0];
|
||||
if ($statProperties->type === StatisticManager::STAT_TYPE_TIME) {
|
||||
$value = Formatter::formatTimeH($value);
|
||||
} else if ($statProperties->type === StatisticManager::STAT_TYPE_FLOAT) {
|
||||
$value = round($value, 2);
|
||||
}
|
||||
|
||||
if ($index % 2 !== 0) {
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$frame->add($lineQuad);
|
||||
$lineQuad->setSize(49, 4);
|
||||
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$lineQuad->setPosition($posX, $posY, 0.001);
|
||||
$lineQuad->setHAlign($lineQuad::LEFT);
|
||||
}
|
||||
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setPosition($posX + 4, $posY);
|
||||
$label->setText($statProperties->name);
|
||||
$label->setHAlign($label::LEFT);
|
||||
$label->setTextSize(1.5);
|
||||
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setPosition($posX + 40, $posY);
|
||||
$label->setText($value);
|
||||
$label->setTextSize(1.5);
|
||||
|
||||
$posY -= 4;
|
||||
$index++;
|
||||
|
||||
if ($index > self::STATS_PER_COLUMN) {
|
||||
$posY = $this->height / 2 - 15;
|
||||
$posX += 47;
|
||||
$index = 0;
|
||||
}
|
||||
}
|
||||
return $frame;
|
||||
}
|
||||
}
|
788
core/Players/PlayerList.php
Normal file
788
core/Players/PlayerList.php
Normal file
@ -0,0 +1,788 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Players;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_BgRaceScore2;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\Controls\Quads\Quad_Emblems;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use FML\ManiaLink;
|
||||
use FML\Script\Features\Paging;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\PlayerStateException;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
use MCTeam\CustomVotesPlugin;
|
||||
|
||||
/**
|
||||
* PlayerList Widget Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerList implements ManialinkPageAnswerListener, CallbackListener, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_FORCE_RED = 'PlayerList.ForceRed';
|
||||
const ACTION_FORCE_BLUE = 'PlayerList.ForceBlue';
|
||||
const ACTION_FORCE_SPEC = 'PlayerList.ForceSpec';
|
||||
const ACTION_FORCE_SPEC_VOTE = 'PlayerList.ForceSpecVote';
|
||||
const ACTION_FORCE_PLAY = 'PlayerList.ForcePlay';
|
||||
const ACTION_PLAYER_ADV = 'PlayerList.PlayerAdvancedActions';
|
||||
const ACTION_CLOSE_PLAYER_ADV = 'PlayerList.ClosePlayerAdvWidget';
|
||||
const ACTION_MUTE_PLAYER = 'PlayerList.MutePlayer';
|
||||
const ACTION_UNMUTE_PLAYER = 'PlayerList.UnMutePlayer';
|
||||
const ACTION_WARN_PLAYER = 'PlayerList.WarnPlayer';
|
||||
const ACTION_KICK_PLAYER = 'PlayerList.KickPlayer';
|
||||
const ACTION_KICK_PLAYER_VOTE = 'PlayerList.KickPlayerVote';
|
||||
const ACTION_BAN_PLAYER = 'PlayerList.BanPlayer';
|
||||
const ACTION_ADD_AS_MASTER = 'PlayerList.PlayerAddAsMaster';
|
||||
const ACTION_ADD_AS_ADMIN = 'PlayerList.PlayerAddAsAdmin';
|
||||
const ACTION_ADD_AS_MOD = 'PlayerList.PlayerAddAsModerator';
|
||||
const ACTION_REVOKE_RIGHTS = 'PlayerList.RevokeRights';
|
||||
const ACTION_OPEN_PLAYER_DETAILED = 'PlayerList.OpenPlayerDetailed';
|
||||
const ACTION_SPECTATE_PLAYER = 'PlayerList.SpectatePlayer';
|
||||
const DEFAULT_CUSTOM_VOTE_PLUGIN = 'MCTeam\CustomVotesPlugin';
|
||||
const SHOWN_MAIN_WINDOW = -1;
|
||||
const MAX_PLAYERS_PER_PAGE = 15;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $playersListShown = array();
|
||||
|
||||
/**
|
||||
* Construct a new PlayerList instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_CLOSE_PLAYER_ADV, $this, 'closePlayerAdvancedWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_CLOSED, $this, 'closeWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_OPENED, $this, 'handleWidgetOpened');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
|
||||
// Update Widget Events
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERINFOCHANGED, $this, 'updateWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERDISCONNECT, $this, 'updateWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERCONNECT, $this, 'updateWidget');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(AuthenticationManager::CB_AUTH_LEVEL_CHANGED, $this, 'updateWidget');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Player to Shown List
|
||||
*
|
||||
* @param Player $player
|
||||
* @param int $showStatus
|
||||
*/
|
||||
public function addPlayerToShownList(Player $player, $showStatus = self::SHOWN_MAIN_WINDOW) {
|
||||
$this->playersListShown[$player->login] = $showStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unset the player if he opened another Main Widget
|
||||
*
|
||||
* @param Player $player
|
||||
* @param $openedWidget
|
||||
*/
|
||||
public function handleWidgetOpened(Player $player, $openedWidget) {
|
||||
//unset when another main widget got opened
|
||||
if ($openedWidget !== 'PlayerList') {
|
||||
unset($this->playersListShown[$player->login]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the widget
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function closeWidget(Player $player) {
|
||||
unset($this->playersListShown[$player->login]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the player advanced widget widget
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function closePlayerAdvancedWidget(array $callback, Player $player) {
|
||||
$this->playersListShown[$player->login] = self::SHOWN_MAIN_WINDOW;
|
||||
$this->showPlayerList($player); // overwrite the manialink
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the PlayerList Widget to the Player
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function showPlayerList(Player $player) {
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
|
||||
// get PlayerList
|
||||
$players = $this->maniaControl->getPlayerManager()->getPlayers();
|
||||
|
||||
//create manialink
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$script = $maniaLink->getScript();
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
|
||||
// Main frame
|
||||
$frame = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultListFrame($script, $paging);
|
||||
$maniaLink->add($frame);
|
||||
|
||||
// Start offsets
|
||||
$posX = -$width / 2;
|
||||
$posY = $height / 2;
|
||||
|
||||
// Predefine Description Label
|
||||
$descriptionLabel = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultDescriptionLabel();
|
||||
$frame->add($descriptionLabel);
|
||||
|
||||
// Headline
|
||||
$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)
|
||||
) {
|
||||
$labelLineArray['Actions'] = $posX + 135;
|
||||
}
|
||||
$this->maniaControl->getManialinkManager()->labelLine($headFrame, $labelLineArray);
|
||||
|
||||
$index = 1;
|
||||
$posY = $height / 2 - 10;
|
||||
$pageFrame = null;
|
||||
|
||||
foreach ($players as $listPlayer) {
|
||||
if ($index % self::MAX_PLAYERS_PER_PAGE === 1) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
|
||||
$paging->addPage($pageFrame);
|
||||
$posY = $height / 2 - 10;
|
||||
}
|
||||
|
||||
$path = $listPlayer->getProvince();
|
||||
$playerFrame = new Frame();
|
||||
$pageFrame->add($playerFrame);
|
||||
|
||||
if ($index % 2 !== 0) {
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$playerFrame->add($lineQuad);
|
||||
$lineQuad->setSize($width, 4);
|
||||
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$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);
|
||||
|
||||
$playerFrame->setY($posY);
|
||||
|
||||
// Show current Player Arrow
|
||||
if ($listPlayer->index === $player->index) {
|
||||
$currentQuad = new Quad_Icons64x64_1();
|
||||
$playerFrame->add($currentQuad);
|
||||
$currentQuad->setX($posX + 3.5);
|
||||
$currentQuad->setZ(0.2);
|
||||
$currentQuad->setSize(4, 4);
|
||||
$currentQuad->setSubStyle($currentQuad::SUBSTYLE_ArrowBlue);
|
||||
}
|
||||
|
||||
// Team Emblem
|
||||
if ($listPlayer->teamId >= 0) {
|
||||
// Player is in a Team
|
||||
$teamQuad = new Quad_Emblems();
|
||||
$playerFrame->add($teamQuad);
|
||||
$teamQuad->setX($posX + 10);
|
||||
$teamQuad->setZ(0.1);
|
||||
$teamQuad->setSize(3.8, 3.8);
|
||||
|
||||
switch ($listPlayer->teamId) {
|
||||
case 0:
|
||||
$teamQuad->setSubStyle($teamQuad::SUBSTYLE_1);
|
||||
break;
|
||||
case 1:
|
||||
$teamQuad->setSubStyle($teamQuad::SUBSTYLE_2);
|
||||
break;
|
||||
}
|
||||
} else if ($listPlayer->isSpectator) {
|
||||
// Player is in Spectator Mode
|
||||
$specQuad = new Quad_BgRaceScore2();
|
||||
$playerFrame->add($specQuad);
|
||||
$specQuad->setX($posX + 10);
|
||||
$specQuad->setZ(0.1);
|
||||
$specQuad->setSubStyle($specQuad::SUBSTYLE_Spectator);
|
||||
$specQuad->setSize(3.8, 3.8);
|
||||
}
|
||||
|
||||
$countryCode = Formatter::mapCountry($listPlayer->getCountry());
|
||||
if ($countryCode !== 'OTH') {
|
||||
// Nation Quad
|
||||
$countryQuad = new Quad();
|
||||
$playerFrame->add($countryQuad);
|
||||
$countryQuad->setImage("file://ZoneFlags/Login/{$listPlayer->login}/country");
|
||||
$countryQuad->setX($posX + 98);
|
||||
$countryQuad->setZ(1);
|
||||
$countryQuad->setSize(4, 4);
|
||||
|
||||
$countryQuad->addTooltipLabelFeature($descriptionLabel, '$<' . $listPlayer->nickname . '$> from ' . $listPlayer->path);
|
||||
}
|
||||
|
||||
// Level Quad
|
||||
$rightQuad = new Quad_BgRaceScore2();
|
||||
$playerFrame->add($rightQuad);
|
||||
$rightQuad->setX($posX + 13);
|
||||
$rightQuad->setZ(3);
|
||||
$rightQuad->setSize(7, 3.5);
|
||||
$rightQuad->setSubStyle($rightQuad::SUBSTYLE_CupFinisher);
|
||||
|
||||
$rightLabel = new Label_Text();
|
||||
$playerFrame->add($rightLabel);
|
||||
$rightLabel->setX($posX + 13.9);
|
||||
$rightLabel->setZ(3.1);
|
||||
$rightLabel->setText($this->maniaControl->getAuthenticationManager()->getAuthLevelAbbreviation($listPlayer->authLevel));
|
||||
$rightLabel->setTextSize(0.8);
|
||||
$rightLabel->setTextColor('fff');
|
||||
|
||||
$description = $this->maniaControl->getAuthenticationManager()->getAuthLevelName($listPlayer) . ' ' . $listPlayer->nickname;
|
||||
$rightLabel->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
// Player Statistics
|
||||
$playerQuad = new Quad_Icons64x64_1();
|
||||
$playerFrame->add($playerQuad);
|
||||
$playerQuad->setX($posX + 61);
|
||||
$playerQuad->setZ(3);
|
||||
$playerQuad->setSize(2.7, 2.7);
|
||||
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_TrackInfo);
|
||||
$playerQuad->setAction(self::ACTION_OPEN_PLAYER_DETAILED . '.' . $listPlayer->login);
|
||||
$description = 'View Statistics of $<' . $listPlayer->nickname . '$>';
|
||||
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
// Camera Quad
|
||||
$playerQuad = new Quad_UIConstruction_Buttons();
|
||||
$playerFrame->add($playerQuad);
|
||||
$playerQuad->setX($posX + 64.5);
|
||||
$playerQuad->setZ(3);
|
||||
$playerQuad->setSize(3.8, 3.8);
|
||||
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_Camera);
|
||||
$description = 'Spectate $<' . $listPlayer->nickname . '$>';
|
||||
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
$playerQuad->setAction(self::ACTION_SPECTATE_PLAYER . '.' . $listPlayer->login);
|
||||
|
||||
// Player Profile Quad
|
||||
$playerQuad = new Quad_UIConstruction_Buttons();
|
||||
$playerFrame->add($playerQuad);
|
||||
$playerQuad->setX($posX + 68);
|
||||
$playerQuad->setZ(3);
|
||||
$playerQuad->setSize(3.8, 3.8);
|
||||
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_Author);
|
||||
$playerQuad->addPlayerProfileFeature($listPlayer->login);
|
||||
|
||||
// Description Label
|
||||
$description = 'View Player Profile of $<' . $listPlayer->nickname . '$>';
|
||||
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkRight($player, AuthenticationManager::AUTH_LEVEL_MODERATOR)
|
||||
) {
|
||||
// Further Player actions Quad
|
||||
$playerQuad = new Quad_Icons64x64_1();
|
||||
$playerFrame->add($playerQuad);
|
||||
$playerQuad->setX($posX + 132);
|
||||
$playerQuad->setZ(0.1);
|
||||
$playerQuad->setSize(3.8, 3.8);
|
||||
$playerQuad->setSubStyle($playerQuad::SUBSTYLE_Buddy);
|
||||
$playerQuad->setAction(self::ACTION_PLAYER_ADV . '.' . $listPlayer->login);
|
||||
|
||||
// Description Label
|
||||
$description = 'Advanced Player Actions for $<' . $listPlayer->nickname . '$>';
|
||||
$playerQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
|
||||
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);
|
||||
$redQuad->setX($posX + 145);
|
||||
$redQuad->setZ(0.1);
|
||||
$redQuad->setSize(3.8, 3.8);
|
||||
$redQuad->setSubStyle($redQuad::SUBSTYLE_2);
|
||||
$redQuad->setAction(self::ACTION_FORCE_RED . '.' . $listPlayer->login);
|
||||
|
||||
// Force to Red-Team Description Label
|
||||
$description = 'Force $<' . $listPlayer->nickname . '$> to Red Team!';
|
||||
$redQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
// Force to Blue-Team Quad
|
||||
$blueQuad = new Quad_Emblems();
|
||||
$playerFrame->add($blueQuad);
|
||||
$blueQuad->setX($posX + 141);
|
||||
$blueQuad->setZ(0.1);
|
||||
$blueQuad->setSize(3.8, 3.8);
|
||||
$blueQuad->setSubStyle($blueQuad::SUBSTYLE_1);
|
||||
$blueQuad->setAction(self::ACTION_FORCE_BLUE . '.' . $listPlayer->login);
|
||||
|
||||
// Force to Blue-Team Description Label
|
||||
$description = 'Force $<' . $listPlayer->nickname . '$> to Blue Team!';
|
||||
$blueQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
|
||||
} else if ($this->maniaControl->getPluginManager()->isPluginActive(self::DEFAULT_CUSTOM_VOTE_PLUGIN)
|
||||
) {
|
||||
// Kick Player Vote
|
||||
$kickQuad = new Quad_UIConstruction_Buttons();
|
||||
$playerFrame->add($kickQuad);
|
||||
$kickQuad->setX($posX + 141);
|
||||
$kickQuad->setZ(0.1);
|
||||
$kickQuad->setSize(3.8, 3.8);
|
||||
$kickQuad->setSubStyle($kickQuad::SUBSTYLE_Validate_Step2);
|
||||
$kickQuad->setAction(self::ACTION_KICK_PLAYER_VOTE . '.' . $listPlayer->login);
|
||||
|
||||
$description = 'Start a Kick Vote on $<' . $listPlayer->nickname . '$>!';
|
||||
$kickQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
} else {
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_PLAY)
|
||||
) {
|
||||
// Force to Play
|
||||
$playQuad = new Quad_Emblems();
|
||||
$playerFrame->add($playQuad);
|
||||
$playQuad->setX($posX + 143);
|
||||
$playQuad->setZ(0.1);
|
||||
$playQuad->setSize(3.8, 3.8);
|
||||
$playQuad->setSubStyle($playQuad::SUBSTYLE_2);
|
||||
$playQuad->setAction(self::ACTION_FORCE_PLAY . '.' . $listPlayer->login);
|
||||
|
||||
$description = 'Force $<' . $listPlayer->nickname . '$> to Play!';
|
||||
$playQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, PlayerActions::SETTING_PERMISSION_FORCE_PLAYER_SPEC)
|
||||
) {
|
||||
// Force to Spectator Quad
|
||||
$spectatorQuad = new Quad_BgRaceScore2();
|
||||
$playerFrame->add($spectatorQuad);
|
||||
$spectatorQuad->setX($posX + 137);
|
||||
$spectatorQuad->setZ(0.1);
|
||||
$spectatorQuad->setSize(3.8, 3.8);
|
||||
$spectatorQuad->setSubStyle($spectatorQuad::SUBSTYLE_Spectator);
|
||||
$spectatorQuad->setAction(self::ACTION_FORCE_SPEC . '.' . $listPlayer->login);
|
||||
|
||||
// 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)
|
||||
) {
|
||||
// Force to Spectator Quad
|
||||
$spectatorQuad = new Quad_BgRaceScore2();
|
||||
$playerFrame->add($spectatorQuad);
|
||||
$spectatorQuad->setX($posX + 137);
|
||||
$spectatorQuad->setZ(0.1);
|
||||
$spectatorQuad->setSize(3.8, 3.8);
|
||||
$spectatorQuad->setSubStyle($spectatorQuad::SUBSTYLE_Spectator);
|
||||
$spectatorQuad->setAction(self::ACTION_FORCE_SPEC_VOTE . '.' . $listPlayer->login);
|
||||
|
||||
// Force to Spectator Description Label
|
||||
$description = 'Start a Vote to force $<' . $listPlayer->nickname . '$> to Spectator!';
|
||||
$spectatorQuad->addTooltipLabelFeature($descriptionLabel, $description);
|
||||
}
|
||||
|
||||
$posY -= 4;
|
||||
$index++;
|
||||
}
|
||||
|
||||
// Show advanced window
|
||||
$listShownValue = $this->playersListShown[$player->login];
|
||||
if ($listShownValue && $listShownValue !== self::SHOWN_MAIN_WINDOW) {
|
||||
$frame = $this->showAdvancedPlayerWidget($player, $listShownValue);
|
||||
$maniaLink->add($frame);
|
||||
}
|
||||
|
||||
// Render and display xml
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'PlayerList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra window with special actions on players like warn,kick, ban, authorization levels...
|
||||
*
|
||||
* @param Player $admin
|
||||
* @param string $login
|
||||
* @return Frame
|
||||
*/
|
||||
public function showAdvancedPlayerWidget(Player $admin, $login) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
$quadStyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowStyle();
|
||||
$quadSubstyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowSubStyle();
|
||||
|
||||
//Settings
|
||||
$posX = $width / 2 + 2.5;
|
||||
$width = 35;
|
||||
$height = $height * 0.75;
|
||||
$textSize = 1.5;
|
||||
$textColor = 'fff';
|
||||
$quadWidth = $width - 7;
|
||||
|
||||
// mainframe
|
||||
$frame = new Frame();
|
||||
$frame->setSize($width, $height);
|
||||
$frame->setPosition($posX + $width / 2, 0);
|
||||
|
||||
// Add Close Quad (X)
|
||||
$closeQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($closeQuad);
|
||||
$closeQuad->setPosition($width * 0.4, $height * 0.43, 3);
|
||||
$closeQuad->setSize(6, 6);
|
||||
$closeQuad->setSubStyle($closeQuad::SUBSTYLE_QuitRace);
|
||||
$closeQuad->setAction(self::ACTION_CLOSE_PLAYER_ADV);
|
||||
|
||||
// Background Quad
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$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);
|
||||
|
||||
// Background Quad
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$backgroundQuad->setSize($width - 2, $height - 2);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
$backgroundQuad->setZ(0.1);
|
||||
|
||||
// Show headline
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setHAlign($label::LEFT);
|
||||
$label->setX(-$width / 2 + 5);
|
||||
$label->setY($height / 2 - 5);
|
||||
$label->setStyle($label::STYLE_TextCardSmall);
|
||||
$label->setTextSize($textSize);
|
||||
$label->setText('Advanced Actions');
|
||||
$label->setTextColor($textColor);
|
||||
|
||||
// Show Nickname
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setHAlign($label::LEFT);
|
||||
$label->setX(0);
|
||||
$label->setY($height / 2 - 8);
|
||||
$label->setStyle($label::STYLE_TextCardSmall);
|
||||
$label->setTextSize($textSize);
|
||||
$label->setText($player->nickname);
|
||||
$label->setTextColor($textColor);
|
||||
|
||||
// Mute Player
|
||||
$posY = $height / 2 - 14;
|
||||
$quad = new Quad_BgsPlayerCard();
|
||||
$frame->add($quad);
|
||||
$quad->setX(0);
|
||||
$quad->setY($posY);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_BgPlayerCardBig);
|
||||
$quad->setSize($quadWidth, 5);
|
||||
|
||||
$label = new Label_Text();
|
||||
$frame->add($label);
|
||||
$label->setX(0);
|
||||
$label->setY($posY);
|
||||
$label->setStyle($label::STYLE_TextCardSmall);
|
||||
$label->setTextSize($textSize);
|
||||
$label->setTextColor($textColor);
|
||||
|
||||
if (!$player->isMuted()) {
|
||||
$label->setText('Mute');
|
||||
$quad->setAction(self::ACTION_MUTE_PLAYER . '.' . $login);
|
||||
} else {
|
||||
$label->setText('UnMute');
|
||||
$quad->setAction(self::ACTION_UNMUTE_PLAYER . '.' . $login);
|
||||
}
|
||||
|
||||
// Warn Player
|
||||
$posY -= 5;
|
||||
$quad = clone $quad;
|
||||
$frame->add($quad);
|
||||
$quad->setY($posY);
|
||||
$quad->setAction(self::ACTION_WARN_PLAYER . '.' . $login);
|
||||
|
||||
$label = clone $label;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Warn');
|
||||
$label->setTextColor($textColor);
|
||||
|
||||
$posY -= 5;
|
||||
|
||||
// Show Kick
|
||||
$quad = clone $quad;
|
||||
$frame->add($quad);
|
||||
$quad->setY($posY);
|
||||
$quad->setAction(self::ACTION_KICK_PLAYER . '.' . $login);
|
||||
|
||||
$label = clone $label;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Kick');
|
||||
$label->setTextColor('f90');
|
||||
|
||||
$posY -= 5;
|
||||
// Show Ban
|
||||
$quad = clone $quad;
|
||||
$frame->add($quad);
|
||||
$quad->setY($posY);
|
||||
$quad->setAction(self::ACTION_BAN_PLAYER . '.' . $login);
|
||||
|
||||
$label = clone $label;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Ban');
|
||||
$label->setTextColor('700');
|
||||
|
||||
$posY -= 10;
|
||||
// Show Add as Master-Admin
|
||||
$quad = clone $quad;
|
||||
$frame->add($quad);
|
||||
$quad->setY($posY);
|
||||
$quad->setAction(self::ACTION_ADD_AS_MASTER . '.' . $login);
|
||||
|
||||
$label = clone $label;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Set SuperAdmin');
|
||||
$label->setTextColor($textColor);
|
||||
|
||||
$posY -= 5;
|
||||
// Show Add as Admin
|
||||
$quad = clone $quad;
|
||||
$frame->add($quad);
|
||||
$quad->setY($posY);
|
||||
$quad->setAction(self::ACTION_ADD_AS_ADMIN . '.' . $login);
|
||||
|
||||
$label = clone $label;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Set Admin');
|
||||
$label->setTextColor($textColor);
|
||||
|
||||
$posY -= 5;
|
||||
// Show Add as Moderator
|
||||
$quad = clone $quad;
|
||||
$frame->add($quad);
|
||||
$quad->setY($posY);
|
||||
$quad->setAction(self::ACTION_ADD_AS_MOD . '.' . $login);
|
||||
|
||||
$label = clone $label;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Set Moderator');
|
||||
$label->setTextColor($textColor);
|
||||
|
||||
if ($player->authLevel > 0
|
||||
&& $this->maniaControl->getAuthenticationManager()->checkRight($admin, $player->authLevel + 1)
|
||||
) {
|
||||
$posY -= 5;
|
||||
// Revoke Rights
|
||||
$quad = clone $quad;
|
||||
$frame->add($quad);
|
||||
$quad->setY($posY);
|
||||
$quad->setAction(self::ACTION_REVOKE_RIGHTS . '.' . $login);
|
||||
|
||||
$label = clone $label;
|
||||
$frame->add($label);
|
||||
$label->setY($posY);
|
||||
$label->setText('Revoke Rights');
|
||||
$label->setTextColor('700');
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on ManialinkPageAnswer
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$actionArray = explode('.', $actionId, 3);
|
||||
if (count($actionArray) <= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = $actionArray[0] . '.' . $actionArray[1];
|
||||
$adminLogin = $callback[1][1];
|
||||
$targetLogin = $actionArray[2];
|
||||
|
||||
switch ($action) {
|
||||
case self::ACTION_SPECTATE_PLAYER:
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($adminLogin, PlayerActions::SPECTATOR_BUT_KEEP_SELECTABLE);
|
||||
$this->maniaControl->getClient()->forceSpectatorTarget($adminLogin, $targetLogin, 1);
|
||||
} catch (PlayerStateException $e) {
|
||||
} catch (UnknownPlayerException $e) {
|
||||
}
|
||||
break;
|
||||
case self::ACTION_OPEN_PLAYER_DETAILED:
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
$this->maniaControl->getPlayerManager()->getPlayerDetailed()->showPlayerDetailed($player, $targetLogin);
|
||||
unset($this->playersListShown[$player->login]);
|
||||
break;
|
||||
case self::ACTION_FORCE_BLUE:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToTeam($adminLogin, $targetLogin, PlayerActions::TEAM_BLUE);
|
||||
break;
|
||||
case self::ACTION_FORCE_RED:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToTeam($adminLogin, $targetLogin, PlayerActions::TEAM_RED);
|
||||
break;
|
||||
case self::ACTION_FORCE_SPEC:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToSpectator($adminLogin, $targetLogin, PlayerActions::SPECTATOR_BUT_KEEP_SELECTABLE);
|
||||
break;
|
||||
case self::ACTION_FORCE_PLAY:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->forcePlayerToPlay($adminLogin, $targetLogin);
|
||||
break;
|
||||
case self::ACTION_MUTE_PLAYER:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->mutePlayer($adminLogin, $targetLogin);
|
||||
$this->showPlayerList($this->maniaControl->getPlayerManager()->getPlayer($adminLogin));
|
||||
break;
|
||||
case self::ACTION_UNMUTE_PLAYER:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->unMutePlayer($adminLogin, $targetLogin);
|
||||
$this->showPlayerList($this->maniaControl->getPlayerManager()->getPlayer($adminLogin));
|
||||
break;
|
||||
case self::ACTION_WARN_PLAYER:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->warnPlayer($adminLogin, $targetLogin);
|
||||
break;
|
||||
case self::ACTION_KICK_PLAYER:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->kickPlayer($adminLogin, $targetLogin);
|
||||
break;
|
||||
case self::ACTION_BAN_PLAYER:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->banPlayer($adminLogin, $targetLogin);
|
||||
break;
|
||||
case self::ACTION_PLAYER_ADV:
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
$this->advancedPlayerWidget($admin, $targetLogin);
|
||||
break;
|
||||
case self::ACTION_ADD_AS_MASTER:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->grandAuthLevel($adminLogin, $targetLogin, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
break;
|
||||
case self::ACTION_ADD_AS_ADMIN:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->grandAuthLevel($adminLogin, $targetLogin, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
break;
|
||||
case self::ACTION_ADD_AS_MOD:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->grandAuthLevel($adminLogin, $targetLogin, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
break;
|
||||
case self::ACTION_REVOKE_RIGHTS:
|
||||
$this->maniaControl->getPlayerManager()->getPlayerActions()->revokeAuthLevel($adminLogin, $targetLogin);
|
||||
break;
|
||||
case self::ACTION_FORCE_SPEC_VOTE:
|
||||
/** @var $votesPlugin CustomVotesPlugin */
|
||||
$votesPlugin = $this->maniaControl->getPluginManager()->getPlugin(self::DEFAULT_CUSTOM_VOTE_PLUGIN);
|
||||
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
$startMessage = $admin->getEscapedNickname() . '$s started a vote to force $<' . $target->nickname . '$> into spectator!';
|
||||
|
||||
$votesPlugin->defineVote('forcespec', 'Force ' . $target->getEscapedNickname() . ' Spec', true, $startMessage);
|
||||
|
||||
$votesPlugin->startVote($admin, 'forcespec', function ($result) use (&$votesPlugin, &$target) {
|
||||
$this->maniaControl->getChat()->sendInformation('$sVote successful -> Player ' . $target->getEscapedNickname() . ' forced to Spectator!');
|
||||
$votesPlugin->undefineVote('forcespec');
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->forceSpectator($target->login, PlayerActions::SPECTATOR_BUT_KEEP_SELECTABLE);
|
||||
$this->maniaControl->getClient()->spectatorReleasePlayerSlot($target->login);
|
||||
} catch (PlayerStateException $e) {
|
||||
} catch (UnknownPlayerException $e) {
|
||||
}
|
||||
});
|
||||
break;
|
||||
case self::ACTION_KICK_PLAYER_VOTE:
|
||||
/** @var $votesPlugin CustomVotesPlugin */
|
||||
$votesPlugin = $this->maniaControl->getPluginManager()->getPlugin(self::DEFAULT_CUSTOM_VOTE_PLUGIN);
|
||||
|
||||
$admin = $this->maniaControl->getPlayerManager()->getPlayer($adminLogin);
|
||||
$target = $this->maniaControl->getPlayerManager()->getPlayer($targetLogin);
|
||||
|
||||
$startMessage = $admin->getEscapedNickname() . '$s started a vote to kick $<' . $target->nickname . '$>!';
|
||||
|
||||
|
||||
$votesPlugin->defineVote('kick', 'Kick ' . $target->getEscapedNickname(), true, $startMessage);
|
||||
|
||||
$votesPlugin->startVote($admin, 'kick', function ($result) use (&$votesPlugin, &$target) {
|
||||
$this->maniaControl->getChat()->sendInformation('$sVote successful -> ' . $target->getEscapedNickname() . ' got Kicked!');
|
||||
$votesPlugin->undefineVote('kick');
|
||||
|
||||
$message = '$39F You got kicked due to a Public Vote!$z ';
|
||||
try {
|
||||
$this->maniaControl->getClient()->kick($target->login, $message);
|
||||
} catch (UnknownPlayerException $e) {
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the Advanced Player Window
|
||||
*
|
||||
* @param Player $caller
|
||||
* @param string $login
|
||||
*/
|
||||
public function advancedPlayerWidget(Player $caller, $login) {
|
||||
// Set status to target player login
|
||||
$this->playersListShown[$caller->login] = $login;
|
||||
|
||||
// Reopen PlayerList
|
||||
$this->showPlayerList($caller);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reopen the widget on PlayerInfoChanged / Player Connect and Disconnect
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function updateWidget(Player $player) {
|
||||
foreach ($this->playersListShown as $login => $shown) {
|
||||
if (!$shown) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if shown player still exists
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
unset($this->playersListShown[$login]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reopen widget
|
||||
if ($shown !== self::SHOWN_MAIN_WINDOW) {
|
||||
$this->playersListShown[$login] = false;
|
||||
}
|
||||
$this->showPlayerList($player);
|
||||
}
|
||||
}
|
||||
}
|
581
core/Players/PlayerManager.php
Normal file
581
core/Players/PlayerManager.php
Normal file
@ -0,0 +1,581 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Players;
|
||||
|
||||
use ManiaControl\Admin\AdminLists;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Statistics\StatisticManager;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\UnknownPlayerException;
|
||||
|
||||
/**
|
||||
* Class managing Players
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PlayerManager implements CallbackListener, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CB_PLAYERCONNECT = 'PlayerManagerCallback.PlayerConnect';
|
||||
const CB_PLAYERDISCONNECT = 'PlayerManagerCallback.PlayerDisconnect';
|
||||
const CB_PLAYERINFOCHANGED = 'PlayerManagerCallback.PlayerInfoChanged';
|
||||
const CB_SERVER_EMPTY = 'PlayerManagerCallback.ServerEmpty';
|
||||
const TABLE_PLAYERS = 'mc_players';
|
||||
const SETTING_JOIN_LEAVE_MESSAGES = 'Enable Join & Leave Messages';
|
||||
const SETTING_JOIN_LEAVE_MESSAGES_SPECTATOR = 'Enable Join & Leave Messages for Spectators';
|
||||
const STAT_JOIN_COUNT = 'Joins';
|
||||
const STAT_SERVERTIME = 'Servertime';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var PlayerActions $playerActions */
|
||||
/** @deprecated see getPlayerActions() */
|
||||
public $playerActions = null;
|
||||
/** @var PlayerCommands $playerCommands */
|
||||
/** @deprecated see getPlayerCommands() */
|
||||
public $playerCommands = null;
|
||||
/** @var PlayerDetailed $playerDetailed */
|
||||
/** @deprecated see getPlayerDetailed() */
|
||||
public $playerDetailed = null;
|
||||
/** @var PlayerDataManager $playerDataManager */
|
||||
/** @deprecated see getPlayerDataManager() */
|
||||
public $playerDataManager = null;
|
||||
/** @var PlayerList $playerList */
|
||||
/** @deprecated see getPlayerList() */
|
||||
public $playerList = null;
|
||||
/** @var AdminLists $adminLists */
|
||||
/** @deprecated see getAdminLists() */
|
||||
public $adminLists = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var Player[] $players */
|
||||
private $players = array();
|
||||
|
||||
/**
|
||||
* Construct a new Player Manager
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
$this->playerCommands = new PlayerCommands($maniaControl);
|
||||
$this->playerActions = new PlayerActions($maniaControl);
|
||||
$this->playerDetailed = new PlayerDetailed($maniaControl);
|
||||
$this->playerDataManager = new PlayerDataManager($maniaControl);
|
||||
$this->playerList = new PlayerList($maniaControl);
|
||||
$this->adminLists = new AdminLists($maniaControl);
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_JOIN_LEAVE_MESSAGES, true);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_JOIN_LEAVE_MESSAGES_SPECTATOR, true);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERCONNECT, $this, 'playerConnect');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERDISCONNECT, $this, 'playerDisconnect');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERINFOCHANGED, $this, 'playerInfoChanged');
|
||||
|
||||
// Player stats
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_JOIN_COUNT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_SERVERTIME, StatisticManager::STAT_TYPE_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize necessary database tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$playerTableQuery = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLAYERS . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`login` varchar(100) NOT NULL,
|
||||
`nickname` varchar(150) NOT NULL,
|
||||
`path` varchar(100) NOT NULL,
|
||||
`authLevel` int(11) NOT NULL DEFAULT '0',
|
||||
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `login` (`login`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Player Data' AUTO_INCREMENT=1;";
|
||||
$playerTableStatement = $mysqli->prepare($playerTableQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$playerTableStatement->execute();
|
||||
if ($playerTableStatement->error) {
|
||||
trigger_error($playerTableStatement->error, E_USER_ERROR);
|
||||
$playerTableStatement->close();
|
||||
return false;
|
||||
}
|
||||
$playerTableStatement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the player actions
|
||||
*
|
||||
* @return PlayerActions
|
||||
*/
|
||||
public function getPlayerActions() {
|
||||
return $this->playerActions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the player commands
|
||||
*
|
||||
* @return PlayerCommands
|
||||
*/
|
||||
public function getPlayerCommands() {
|
||||
return $this->playerCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the player detailed
|
||||
*
|
||||
* @return PlayerDetailed
|
||||
*/
|
||||
public function getPlayerDetailed() {
|
||||
return $this->playerDetailed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the player data manager
|
||||
*
|
||||
* @return PlayerDataManager
|
||||
*/
|
||||
public function getPlayerDataManager() {
|
||||
return $this->playerDataManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the player list
|
||||
*
|
||||
* @return PlayerList
|
||||
*/
|
||||
public function getPlayerList() {
|
||||
return $this->playerList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the admin lists
|
||||
*
|
||||
* @return AdminLists
|
||||
*/
|
||||
public function getAdminLists() {
|
||||
return $this->adminLists;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle OnInit callback
|
||||
*/
|
||||
public function onInit() {
|
||||
// Add all players
|
||||
$players = $this->maniaControl->getClient()->getPlayerList(300, 0, 2);
|
||||
foreach ($players as $playerItem) {
|
||||
if ($playerItem->playerId <= 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$detailedPlayerInfo = $this->maniaControl->getClient()->getDetailedPlayerInfo($playerItem->login);
|
||||
} catch (UnknownPlayerException $exception) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check if the Player is in a Team, to notify if its a TeamMode or not
|
||||
if ($playerItem->teamId >= 0) {
|
||||
$this->maniaControl->getServer()->setTeamMode(true);
|
||||
}
|
||||
|
||||
$player = new Player($this->maniaControl, true);
|
||||
$player->setInfo($playerItem);
|
||||
$player->setDetailedInfo($detailedPlayerInfo);
|
||||
$player->hasJoinedGame = true;
|
||||
$this->addPlayer($player);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a player
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function addPlayer(Player $player) {
|
||||
$this->savePlayer($player);
|
||||
$this->players[$player->login] = $player;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save player in database and fill up properties
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function savePlayer(Player &$player) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
|
||||
// Save player
|
||||
$playerQuery = "INSERT INTO `" . self::TABLE_PLAYERS . "` (
|
||||
`login`,
|
||||
`nickname`,
|
||||
`path`
|
||||
) VALUES (
|
||||
?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`index` = LAST_INSERT_ID(`index`),
|
||||
`nickname` = VALUES(`nickname`),
|
||||
`path` = VALUES(`path`);";
|
||||
$playerStatement = $mysqli->prepare($playerQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$playerStatement->bind_param('sss', $player->login, $player->rawNickname, $player->path);
|
||||
$playerStatement->execute();
|
||||
if ($playerStatement->error) {
|
||||
trigger_error($playerStatement->error);
|
||||
$playerStatement->close();
|
||||
return false;
|
||||
}
|
||||
$player->index = $playerStatement->insert_id;
|
||||
$playerStatement->close();
|
||||
|
||||
// Get Player Auth Level from DB
|
||||
$playerQuery = "SELECT `authLevel` FROM `" . self::TABLE_PLAYERS . "` WHERE `index` = ?;";
|
||||
$playerStatement = $mysqli->prepare($playerQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$playerStatement->bind_param('i', $player->index);
|
||||
$playerStatement->execute();
|
||||
if ($playerStatement->error) {
|
||||
trigger_error($playerStatement->error);
|
||||
$playerStatement->close();
|
||||
return false;
|
||||
}
|
||||
$playerStatement->store_result();
|
||||
$playerStatement->bind_result($player->authLevel);
|
||||
$playerStatement->fetch();
|
||||
$playerStatement->free_result();
|
||||
$playerStatement->close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PlayerConnect Callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function playerConnect(array $callback) {
|
||||
$login = $callback[1][0];
|
||||
try {
|
||||
$playerInfo = $this->maniaControl->getClient()->getDetailedPlayerInfo($login);
|
||||
$player = new Player($this->maniaControl, true);
|
||||
$player->setDetailedInfo($playerInfo);
|
||||
|
||||
$this->addPlayer($player);
|
||||
} catch (UnknownPlayerException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PlayerDisconnect callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function playerDisconnect(array $callback) {
|
||||
$login = $callback[1][0];
|
||||
$player = $this->removePlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger own callbacks
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYERDISCONNECT, $player);
|
||||
if ($this->getPlayerCount(false) <= 0) {
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SERVER_EMPTY);
|
||||
}
|
||||
|
||||
if ($player->isFakePlayer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$played = Formatter::formatTimeH(time() - $player->joinTime);
|
||||
$logMessage = "Player left: {$player->login} / {$player->nickname} Playtime: {$played}";
|
||||
Logger::logInfo($logMessage, true);
|
||||
|
||||
if (!$player->isSpectator && $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_JOIN_LEAVE_MESSAGES) && !$player->isFakePlayer()
|
||||
|| $player->isSpectator && $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_JOIN_LEAVE_MESSAGES_SPECTATOR)
|
||||
) {
|
||||
$this->maniaControl->getChat()->sendChat('$0f0$<$fff' . $player->nickname . '$> has left the game');
|
||||
}
|
||||
|
||||
//Destroys stored PlayerData, after all Disconnect Callbacks got Handled
|
||||
$this->getPlayerDataManager()->destroyPlayerData($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a Player
|
||||
*
|
||||
* @param string $login
|
||||
* @param bool $savePlayedTime
|
||||
* @return Player $player
|
||||
*/
|
||||
private function removePlayer($login, $savePlayedTime = true) {
|
||||
if (!isset($this->players[$login])) {
|
||||
return null;
|
||||
}
|
||||
$player = $this->players[$login];
|
||||
unset($this->players[$login]);
|
||||
if ($savePlayedTime) {
|
||||
$this->updatePlayedTime($player);
|
||||
}
|
||||
return $player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update total played time of the player
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function updatePlayedTime(Player $player) {
|
||||
if (!$player) {
|
||||
return false;
|
||||
}
|
||||
$playedTime = time() - $player->joinTime;
|
||||
|
||||
return $this->maniaControl->getStatisticManager()->insertStat(self::STAT_SERVERTIME, $player, $this->maniaControl->getServer()->index, $playedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of all Players
|
||||
*
|
||||
* @param bool $withoutSpectators
|
||||
* @return int
|
||||
*/
|
||||
public function getPlayerCount($withoutSpectators = true) {
|
||||
if (!$withoutSpectators) {
|
||||
return count($this->players);
|
||||
}
|
||||
$count = 0;
|
||||
foreach ($this->players as $player) {
|
||||
if (!$player->isSpectator) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update PlayerInfo
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function playerInfoChanged(array $callback) {
|
||||
$player = $this->getPlayer($callback[1][0]['Login']);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
$player->ladderRank = $callback[1][0]["LadderRanking"];
|
||||
$player->teamId = $callback[1][0]["TeamId"];
|
||||
|
||||
//Check if the Player is in a Team, to notify if its a TeamMode or not
|
||||
if ($player->teamId >= 0) {
|
||||
$this->maniaControl->getServer()->setTeamMode(true);
|
||||
}
|
||||
|
||||
$prevJoinState = $player->hasJoinedGame;
|
||||
|
||||
$player->updatePlayerFlags($callback[1][0]["Flags"]);
|
||||
$player->updateSpectatorStatus($callback[1][0]["SpectatorStatus"]);
|
||||
|
||||
//Check if Player finished joining the game
|
||||
if ($player->hasJoinedGame && !$prevJoinState) {
|
||||
|
||||
if (!$player->isSpectator && $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_JOIN_LEAVE_MESSAGES) && !$player->isFakePlayer()
|
||||
) {
|
||||
$string = array(0 => '$0f0Player', 1 => '$0f0Moderator', 2 => '$0f0Admin', 3 => '$0f0SuperAdmin', 4 => '$0f0MasterAdmin');
|
||||
$chatMessage = '$0f0' . $string[$player->authLevel] . ' $<$fff' . $player->nickname . '$> Nation: $<$fff' . $player->getCountry() . '$> joined!';
|
||||
$this->maniaControl->getChat()->sendChat($chatMessage);
|
||||
} else if ($player->isSpectator && $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_JOIN_LEAVE_MESSAGES_SPECTATOR)) {
|
||||
$string = array(0 => '$0f0Player', 1 => '$0f0Moderator', 2 => '$0f0Admin', 3 => '$0f0SuperAdmin', 4 => '$0f0MasterAdmin');
|
||||
$chatMessage = '$0f0' . $string[$player->authLevel] . ' $<$fff' . $player->nickname . '$> Nation: $<$fff' . $player->getCountry() . '$> joined as Spectator!';
|
||||
$this->maniaControl->getChat()->sendChat($chatMessage);
|
||||
}
|
||||
|
||||
$this->maniaControl->getChat()->sendInformation('This server uses ManiaControl v' . ManiaControl::VERSION . '!', $player->login);
|
||||
|
||||
$logMessage = "Player joined: {$player->login} / {$player->nickname} Nation: " . $player->getCountry() . " IP: {$player->ipAddress}";
|
||||
Logger::logInfo($logMessage, true);
|
||||
|
||||
// Increment the Player Join Count
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_JOIN_COUNT, $player, $this->maniaControl->getServer()->index);
|
||||
|
||||
// Trigger own PlayerJoined callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYERCONNECT, $player);
|
||||
}
|
||||
|
||||
// Trigger own callback
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYERINFOCHANGED, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Player by login
|
||||
*
|
||||
* @param mixed $login
|
||||
* @param bool $connectedPlayersOnly
|
||||
* @return Player
|
||||
*/
|
||||
public function getPlayer($login, $connectedPlayersOnly = false) {
|
||||
if ($login instanceof Player) {
|
||||
return $login;
|
||||
}
|
||||
if (!isset($this->players[$login])) {
|
||||
if ($connectedPlayersOnly) {
|
||||
return null;
|
||||
}
|
||||
return $this->getPlayerFromDatabaseByLogin($login);
|
||||
}
|
||||
return $this->players[$login];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Player from the database
|
||||
*
|
||||
* @param string $playerLogin
|
||||
* @return Player
|
||||
*/
|
||||
private function getPlayerFromDatabaseByLogin($playerLogin) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
|
||||
$query = "SELECT * FROM `" . self::TABLE_PLAYERS . "`
|
||||
WHERE `login` LIKE '" . $mysqli->escape_string($playerLogin) . "';";
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
|
||||
$row = $result->fetch_object();
|
||||
$result->free();
|
||||
|
||||
if (!isset($row)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$player = new Player($this->maniaControl, false);
|
||||
$player->index = $row->index;
|
||||
$player->login = $row->login;
|
||||
$player->rawNickname = $row->nickname;
|
||||
$player->nickname = Formatter::stripDirtyCodes($player->rawNickname);
|
||||
$player->path = $row->path;
|
||||
$player->authLevel = $row->authLevel;
|
||||
|
||||
return $player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Players
|
||||
*
|
||||
* @return Player[]
|
||||
*/
|
||||
public function getPlayers() {
|
||||
return $this->players;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the count of all spectators
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getSpectatorCount() {
|
||||
$count = 0;
|
||||
foreach ($this->players as $player) {
|
||||
if ($player->isSpectator) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Player by index
|
||||
*
|
||||
* @param int $index
|
||||
* @param bool $connectedPlayersOnly
|
||||
* @return Player
|
||||
*/
|
||||
public function getPlayerByIndex($index, $connectedPlayersOnly = false) {
|
||||
foreach ($this->players as $player) {
|
||||
if ($player->index === $index) {
|
||||
return $player;
|
||||
}
|
||||
}
|
||||
|
||||
// Player is not online - Get Player from Database
|
||||
if (!$connectedPlayersOnly) {
|
||||
return $this->getPlayerFromDatabaseByIndex($index);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Player out of the database
|
||||
*
|
||||
* @param int $playerIndex
|
||||
* @return Player
|
||||
*/
|
||||
private function getPlayerFromDatabaseByIndex($playerIndex) {
|
||||
if (!is_numeric($playerIndex)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "SELECT * FROM `" . self::TABLE_PLAYERS . "`
|
||||
WHERE `index` = {$playerIndex};";
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
|
||||
$row = $result->fetch_object();
|
||||
$result->free();
|
||||
|
||||
if (!$row) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$player = new Player($this->maniaControl, false);
|
||||
$player->index = $playerIndex;
|
||||
$player->login = $row->login;
|
||||
$player->rawNickname = $row->nickname;
|
||||
$player->nickname = Formatter::stripDirtyCodes($player->rawNickname);
|
||||
$player->path = $row->path;
|
||||
$player->authLevel = $row->authLevel;
|
||||
|
||||
return $player;
|
||||
}
|
||||
}
|
238
core/Plugins/InstallMenu.php
Normal file
238
core/Plugins/InstallMenu.php
Normal file
@ -0,0 +1,238 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Plugins;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Button;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Script\Features\Paging;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Configurator\ConfiguratorMenu;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Utils\WebReader;
|
||||
|
||||
/**
|
||||
* Configurator for installing Plugins
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class InstallMenu implements ConfiguratorMenu, ManialinkPageAnswerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const SETTING_PERMISSION_INSTALL_PLUGINS = 'Install Plugins';
|
||||
const ACTION_PREFIX_INSTALL_PLUGIN = 'PluginInstallMenu.Install.';
|
||||
const ACTION_REFRESH_LIST = 'PluginInstallMenu.RefreshList';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new plugin install menu instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_INSTALL_PLUGINS, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_REFRESH_LIST, $this, 'handleRefreshListAction');
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getTitle()
|
||||
*/
|
||||
public static function getTitle() {
|
||||
return 'Install Plugins';
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getMenu()
|
||||
*/
|
||||
public function getMenu($width, $height, Script $script, Player $player) {
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$frame = new Frame();
|
||||
|
||||
// Config
|
||||
$pagerSize = 9.;
|
||||
$entryHeight = 5.;
|
||||
$posY = 0.;
|
||||
$pageFrame = null;
|
||||
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'plugins';
|
||||
$response = WebReader::getUrl($url);
|
||||
$dataJson = $response->getContent();
|
||||
$pluginList = json_decode($dataJson);
|
||||
$index = 0;
|
||||
|
||||
if (!is_array($pluginList)) {
|
||||
// Error text
|
||||
$errorFrame = $this->getErrorFrame();
|
||||
$frame->add($errorFrame);
|
||||
} else if (empty($pluginList)) {
|
||||
// Empty text
|
||||
$emptyFrame = $this->getEmptyFrame();
|
||||
$frame->add($emptyFrame);
|
||||
} else {
|
||||
// Build plugin list
|
||||
// Pagers
|
||||
$pagerPrev = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerPrev);
|
||||
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
|
||||
|
||||
$pagerNext = clone $pagerPrev;
|
||||
$frame->add($pagerNext);
|
||||
$pagerNext->setX($width * 0.45);
|
||||
|
||||
$pageCountLabel = new Label_Text();
|
||||
$frame->add($pageCountLabel);
|
||||
$pageCountLabel->setHAlign($pageCountLabel::RIGHT)->setPosition($width * 0.35, $height * -0.44, 1)->setStyle($pageCountLabel::STYLE_TextTitle1)->setTextSize(2);
|
||||
|
||||
$paging->addButton($pagerNext)->addButton($pagerPrev)->setLabel($pageCountLabel);
|
||||
|
||||
// Info tooltip
|
||||
$infoTooltipLabel = new Label();
|
||||
$frame->add($infoTooltipLabel);
|
||||
$infoTooltipLabel->setAlign($infoTooltipLabel::LEFT, $infoTooltipLabel::TOP)->setPosition($width * -0.45, $height * -0.22)->setSize($width * 0.7, $entryHeight)->setTextSize(1)->setTranslate(true)->setVisible(false)->setAutoNewLine(true)->setMaxLines(5);
|
||||
|
||||
// List plugins
|
||||
foreach ($pluginList as $plugin) {
|
||||
if ($this->maniaControl->getPluginManager()->isPluginIdInstalled($plugin->id)
|
||||
) {
|
||||
// Already installed -> Skip
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($index % 10 === 0) {
|
||||
// New page
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$paging->addPage($pageFrame);
|
||||
$posY = $height * 0.41;
|
||||
}
|
||||
|
||||
$pluginFrame = new Frame();
|
||||
$pageFrame->add($pluginFrame);
|
||||
$pluginFrame->setY($posY);
|
||||
|
||||
$nameLabel = new Label_Text();
|
||||
$pluginFrame->add($nameLabel);
|
||||
$nameLabel->setHAlign($nameLabel::LEFT)->setX($width * -0.46)->setSize($width * 0.62, $entryHeight)->setStyle($nameLabel::STYLE_TextCardSmall)->setTextSize(2)->setText($plugin->name);
|
||||
|
||||
$description = "Author: {$plugin->author}\nVersion: {$plugin->currentVersion->version}\nDesc: {$plugin->description}";
|
||||
$nameLabel->addTooltipLabelFeature($infoTooltipLabel, $description);
|
||||
|
||||
if (!$this->isPluginCompatible($plugin)) {
|
||||
// Incompatibility label
|
||||
$infoLabel = new Label_Text();
|
||||
$pluginFrame->add($infoLabel);
|
||||
$infoLabel->setHAlign($infoLabel::RIGHT)->setX($width * 0.47)->setSize($width * 0.33, $entryHeight)->setTextSize(1)->setTextColor('f30');
|
||||
if ($plugin->currentVersion->min_mc_version > ManiaControl::VERSION) {
|
||||
$infoLabel->setText("Needs at least MC-Version '{$plugin->currentVersion->min_mc_version}'");
|
||||
} else {
|
||||
$infoLabel->setText("Needs at most MC-Version '{$plugin->currentVersion->max_mc_version}'");
|
||||
}
|
||||
} else {
|
||||
// Install button
|
||||
$installButton = new Label_Button();
|
||||
$pluginFrame->add($installButton);
|
||||
$installButton->setHAlign($installButton::RIGHT)->setX($width * 0.47)->setStyle($installButton::STYLE_CardButtonSmall)->setText('Install')->setTranslate(true)->setAction(self::ACTION_PREFIX_INSTALL_PLUGIN . $plugin->id);
|
||||
}
|
||||
|
||||
if ($plugin->currentVersion->verified > 0) {
|
||||
// Suggested quad
|
||||
$suggestedQuad = new Quad_Icons64x64_1();
|
||||
$pluginFrame->add($suggestedQuad);
|
||||
$suggestedQuad->setPosition($width * 0.45, $entryHeight * 0.12, 2)->setSize(4, 4)->setSubStyle($suggestedQuad::SUBSTYLE_StateSuggested);
|
||||
}
|
||||
|
||||
$posY -= $entryHeight;
|
||||
$index++;
|
||||
}
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Frame to display when an Error occurred
|
||||
*
|
||||
* @return Frame
|
||||
*/
|
||||
private function getErrorFrame() {
|
||||
$frame = new Frame();
|
||||
|
||||
$infoLabel = new Label_Text();
|
||||
$frame->add($infoLabel);
|
||||
$infoLabel->setVAlign($infoLabel::BOTTOM)->setY(2)->setSize(100, 25)->setTextColor('f30')->setTranslate(true)->setText('An error occurred. Please try again later.');
|
||||
|
||||
$refreshQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($refreshQuad);
|
||||
$refreshQuad->setY(-4)->setSize(8, 8)->setSubStyle($refreshQuad::SUBSTYLE_Refresh)->setAction(self::ACTION_REFRESH_LIST);
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the Frame to display when no Plugins are left to install
|
||||
*
|
||||
* @return Frame
|
||||
*/
|
||||
private function getEmptyFrame() {
|
||||
$frame = new Frame();
|
||||
|
||||
$infoLabel = new Label_Text();
|
||||
$frame->add($infoLabel);
|
||||
$infoLabel->setSize(100, 50)->setTextColor('0f3')->setTranslate(true)->setText('No other plugins available.');
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Plugin can be installed without Issues
|
||||
*
|
||||
* @param object $plugin
|
||||
* @return bool
|
||||
*/
|
||||
private function isPluginCompatible($plugin) {
|
||||
if ($plugin->currentVersion->min_mc_version > 0 && $plugin->currentVersion->min_mc_version > ManiaControl::VERSION) {
|
||||
// ManiaControl needs to be updated
|
||||
return false;
|
||||
}
|
||||
if ($plugin->currentVersion->max_mc_version > 0 && $plugin->currentVersion->max_mc_version < ManiaControl::VERSION) {
|
||||
// Plugin is outdated
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||
*/
|
||||
public function saveConfigData(array $configData, Player $player) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the Refresh MLAction
|
||||
*
|
||||
* @param array $actionCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handleRefreshListAction(array $actionCallback, Player $player) {
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
}
|
74
core/Plugins/Plugin.php
Normal file
74
core/Plugins/Plugin.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Plugins;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Interface for ManiaControl Plugins
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
interface Plugin {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const PLUGIN_INTERFACE = __CLASS__;
|
||||
|
||||
/**
|
||||
* Prepare the Plugin
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public static function prepare(ManiaControl $maniaControl);
|
||||
|
||||
/**
|
||||
* Get plugin id
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public static function getId();
|
||||
|
||||
/**
|
||||
* Get Plugin Name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getName();
|
||||
|
||||
/**
|
||||
* Get Plugin Version
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getVersion();
|
||||
|
||||
/**
|
||||
* Get Plugin Author
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getAuthor();
|
||||
|
||||
/**
|
||||
* Get Plugin Description
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getDescription();
|
||||
|
||||
/**
|
||||
* Load the plugin
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
* @return bool
|
||||
*/
|
||||
public function load(ManiaControl $maniaControl);
|
||||
|
||||
/**
|
||||
* Unload the plugin and its Resources
|
||||
*/
|
||||
public function unload();
|
||||
}
|
482
core/Plugins/PluginManager.php
Normal file
482
core/Plugins/PluginManager.php
Normal file
@ -0,0 +1,482 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Plugins;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Utils\ClassUtil;
|
||||
|
||||
/**
|
||||
* Class managing Plugins
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PluginManager {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TABLE_PLUGINS = 'mc_plugins';
|
||||
const CB_PLUGIN_LOADED = 'PluginManager.PluginLoaded';
|
||||
const CB_PLUGIN_UNLOADED = 'PluginManager.PluginUnloaded';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var PluginMenu $pluginMenu */
|
||||
private $pluginMenu = null;
|
||||
/** @var InstallMenu $pluginInstallMenu */
|
||||
private $pluginInstallMenu = null;
|
||||
/** @var Plugin[] $activePlugins */
|
||||
private $activePlugins = array();
|
||||
/** @var string[] $pluginClasses */
|
||||
private $pluginClasses = array();
|
||||
|
||||
/**
|
||||
* Construct a new plugin manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
$this->pluginMenu = new PluginMenu($maniaControl);
|
||||
$this->maniaControl->getConfigurator()->addMenu($this->pluginMenu);
|
||||
|
||||
$this->pluginInstallMenu = new InstallMenu($maniaControl);
|
||||
$this->maniaControl->getConfigurator()->addMenu($this->pluginInstallMenu);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize necessary database tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$pluginsTableQuery = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLUGINS . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`className` varchar(100) NOT NULL,
|
||||
`active` tinyint(1) NOT NULL DEFAULT '0',
|
||||
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `className` (`className`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='ManiaControl plugin status' AUTO_INCREMENT=1;";
|
||||
$tableStatement = $mysqli->prepare($pluginsTableQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$tableStatement->execute();
|
||||
if ($tableStatement->error) {
|
||||
trigger_error($tableStatement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$tableStatement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Plugin Id if the given Class is a Plugin
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return int
|
||||
*/
|
||||
public static function getPluginId($pluginClass) {
|
||||
if (self::isPluginClass($pluginClass)) {
|
||||
/** @var Plugin $pluginClass */
|
||||
return $pluginClass::getId();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given class implements the plugin interface
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return bool
|
||||
*/
|
||||
public static function isPluginClass($pluginClass) {
|
||||
$pluginClass = ClassUtil::getClass($pluginClass);
|
||||
if (!class_exists($pluginClass, false)) {
|
||||
return false;
|
||||
}
|
||||
$interfaces = class_implements($pluginClass, false);
|
||||
if (!$interfaces) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array(Plugin::PLUGIN_INTERFACE, $interfaces)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivate the Plugin with the given Class
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return bool
|
||||
*/
|
||||
public function deactivatePlugin($pluginClass) {
|
||||
$pluginClass = $this->getPluginClass($pluginClass);
|
||||
if (!$pluginClass) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->isPluginActive($pluginClass)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var Plugin $plugin */
|
||||
$plugin = $this->activePlugins[$pluginClass];
|
||||
unset($this->activePlugins[$pluginClass]);
|
||||
|
||||
$plugin->unload();
|
||||
|
||||
if ($plugin instanceof CallbackListener) {
|
||||
$this->maniaControl->getCallbackManager()->unregisterCallbackListener($plugin);
|
||||
$this->maniaControl->getCallbackManager()->unregisterScriptCallbackListener($plugin);
|
||||
}
|
||||
if ($plugin instanceof CommandListener) {
|
||||
$this->maniaControl->getCommandManager()->unregisterCommandListener($plugin);
|
||||
}
|
||||
if ($plugin instanceof ManialinkPageAnswerListener) {
|
||||
$this->maniaControl->getManialinkManager()->unregisterManialinkPageAnswerListener($plugin);
|
||||
}
|
||||
if ($plugin instanceof TimerListener) {
|
||||
$this->maniaControl->getTimerManager()->unregisterTimerListenings($plugin);
|
||||
}
|
||||
|
||||
$this->savePluginStatus($pluginClass, false);
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLUGIN_UNLOADED, $pluginClass, $plugin);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Class of the Plugin
|
||||
*
|
||||
* @param mixed $pluginClass
|
||||
* @return string
|
||||
*/
|
||||
public static function getPluginClass($pluginClass) {
|
||||
$pluginClass = ClassUtil::getClass($pluginClass);
|
||||
if (!self::isPluginClass($pluginClass)) {
|
||||
return null;
|
||||
}
|
||||
return $pluginClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Plugin is currently running
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return bool
|
||||
*/
|
||||
public function isPluginActive($pluginClass) {
|
||||
$pluginClass = $this->getPluginClass($pluginClass);
|
||||
return isset($this->activePlugins[$pluginClass]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Plugin Status in Database
|
||||
*
|
||||
* @param string $className
|
||||
* @param bool $active
|
||||
* @return bool
|
||||
*/
|
||||
private function savePluginStatus($className, $active) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$pluginStatusQuery = "INSERT INTO `" . self::TABLE_PLUGINS . "` (
|
||||
`className`,
|
||||
`active`
|
||||
) VALUES (
|
||||
?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`active` = VALUES(`active`);";
|
||||
$pluginStatement = $mysqli->prepare($pluginStatusQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$activeInt = ($active ? 1 : 0);
|
||||
$pluginStatement->bind_param('si', $className, $activeInt);
|
||||
$pluginStatement->execute();
|
||||
if ($pluginStatement->error) {
|
||||
trigger_error($pluginStatement->error);
|
||||
$pluginStatement->close();
|
||||
return false;
|
||||
}
|
||||
$pluginStatement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load complete Plugins Directory and start all configured Plugins
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function loadPlugins() {
|
||||
$pluginsDirectory = MANIACONTROL_PATH . 'plugins' . DIRECTORY_SEPARATOR;
|
||||
|
||||
$classesBefore = get_declared_classes();
|
||||
$this->loadPluginFiles($pluginsDirectory);
|
||||
$classesAfter = get_declared_classes();
|
||||
|
||||
$newPluginClasses = array();
|
||||
|
||||
$newClasses = array_diff($classesAfter, $classesBefore);
|
||||
foreach ($newClasses as $className) {
|
||||
if (!self::isPluginClass($className)) {
|
||||
continue;
|
||||
}
|
||||
if (!self::validatePluginClass($className)) {
|
||||
$message = "The plugin class '{$className}' isn't correctly implemented: You need to return a proper ID by registering it on maniacontrol.com!";
|
||||
Logger::logWarning($message);
|
||||
if (!DEV_MODE) {
|
||||
$message = 'Fix the plugin or turn on DEV_MODE!';
|
||||
$this->maniaControl->quit($message, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->addPluginClass($className)) {
|
||||
continue;
|
||||
}
|
||||
array_push($newPluginClasses, $className);
|
||||
|
||||
/** @var Plugin $className */
|
||||
$className::prepare($this->maniaControl);
|
||||
|
||||
if ($this->getSavedPluginStatus($className)) {
|
||||
$this->activatePlugin($className);
|
||||
}
|
||||
}
|
||||
|
||||
return $newPluginClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all Plugin Files from the Directory
|
||||
*
|
||||
* @param string $directory
|
||||
*/
|
||||
public function loadPluginFiles($directory = '') {
|
||||
if (!is_readable($directory) || !is_dir($directory)) {
|
||||
return;
|
||||
}
|
||||
$pluginFiles = scandir($directory);
|
||||
foreach ($pluginFiles as $pluginFile) {
|
||||
if (substr($pluginFile, 0, 1) === '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$filePath = $directory . $pluginFile;
|
||||
if (is_file($filePath)) {
|
||||
if (!FileUtil::isPhpFileName($pluginFile)) {
|
||||
continue;
|
||||
}
|
||||
$success = include_once $filePath;
|
||||
if (!$success) {
|
||||
Logger::logError("Couldn't load file '{$filePath}'!");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
$dirPath = $directory . $pluginFile;
|
||||
if (is_dir($dirPath)) {
|
||||
$this->loadPluginFiles($dirPath . DIRECTORY_SEPARATOR);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the given class is a correctly implemented plugin class
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return bool
|
||||
*/
|
||||
private static function validatePluginClass($pluginClass) {
|
||||
if (!self::isPluginClass($pluginClass)) {
|
||||
return false;
|
||||
}
|
||||
/** @var Plugin $pluginClass */
|
||||
return ($pluginClass::getId() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the class to array of loaded plugin classes
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return bool
|
||||
*/
|
||||
public function addPluginClass($pluginClass) {
|
||||
$pluginClass = $this->getPluginClass($pluginClass);
|
||||
if (in_array($pluginClass, $this->pluginClasses)) {
|
||||
return false;
|
||||
}
|
||||
if (!$this->isPluginClass($pluginClass)) {
|
||||
return false;
|
||||
}
|
||||
array_push($this->pluginClasses, $pluginClass);
|
||||
sort($this->pluginClasses);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get plugin status from database
|
||||
*
|
||||
* @param string $className
|
||||
* @return bool
|
||||
*/
|
||||
public function getSavedPluginStatus($className) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$pluginStatusQuery = "SELECT `active` FROM `" . self::TABLE_PLUGINS . "`
|
||||
WHERE `className` = ?;";
|
||||
$pluginStatement = $mysqli->prepare($pluginStatusQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$pluginStatement->bind_param('s', $className);
|
||||
$pluginStatement->execute();
|
||||
if ($pluginStatement->error) {
|
||||
trigger_error($pluginStatement->error);
|
||||
$pluginStatement->close();
|
||||
return false;
|
||||
}
|
||||
$pluginStatement->store_result();
|
||||
if ($pluginStatement->num_rows <= 0) {
|
||||
$pluginStatement->free_result();
|
||||
$pluginStatement->close();
|
||||
$this->savePluginStatus($className, false);
|
||||
return false;
|
||||
}
|
||||
$pluginStatement->bind_result($activeInt);
|
||||
$pluginStatement->fetch();
|
||||
$active = ($activeInt === 1);
|
||||
$pluginStatement->free_result();
|
||||
$pluginStatement->close();
|
||||
return $active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate and start the plugin with the given name
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @param string $adminLogin
|
||||
* @return bool
|
||||
*/
|
||||
public function activatePlugin($pluginClass, $adminLogin = null) {
|
||||
if (!$this->isPluginClass($pluginClass)) {
|
||||
return false;
|
||||
}
|
||||
if ($this->isPluginActive($pluginClass)) {
|
||||
return false;
|
||||
}
|
||||
/** @var Plugin $plugin */
|
||||
$plugin = new $pluginClass();
|
||||
|
||||
try {
|
||||
$plugin->load($this->maniaControl);
|
||||
} catch (\Exception $e) {
|
||||
$message = "Error during Plugin Activation of '{$pluginClass}': '{$e->getMessage()}'";
|
||||
$this->maniaControl->getChat()->sendError($message, $adminLogin);
|
||||
Logger::logError($message);
|
||||
$this->savePluginStatus($pluginClass, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->activePlugins[$pluginClass] = $plugin;
|
||||
$this->savePluginStatus($pluginClass, true);
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLUGIN_LOADED, $pluginClass, $plugin);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Plugin with the given ID is already installed and loaded
|
||||
*
|
||||
* @param int $pluginId
|
||||
* @return bool
|
||||
*/
|
||||
public function isPluginIdInstalled($pluginId) {
|
||||
foreach ($this->pluginClasses as $pluginClass) {
|
||||
/** @var Plugin $pluginClass */
|
||||
if ($pluginClass::getId() == $pluginId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Plugin if it is activated
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return Plugin
|
||||
*/
|
||||
public function getPlugin($pluginClass) {
|
||||
if ($this->isPluginActive($pluginClass)) {
|
||||
return $this->activePlugins[$pluginClass];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all declared plugin class names
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getPluginClasses() {
|
||||
return $this->pluginClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Ids of all active Plugins
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getActivePluginsIds() {
|
||||
$pluginsIds = array();
|
||||
foreach ($this->getActivePlugins() as $plugin) {
|
||||
$pluginId = $plugin::getId();
|
||||
if (is_numeric($pluginId)) {
|
||||
array_push($pluginsIds, $pluginId);
|
||||
}
|
||||
}
|
||||
return $pluginsIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all active Plugins
|
||||
*
|
||||
* @return Plugin[]
|
||||
*/
|
||||
public function getActivePlugins() {
|
||||
return $this->activePlugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the Plugins List from the ManiaControl Website
|
||||
*
|
||||
* @param callable $function
|
||||
*/
|
||||
public function fetchPluginList(callable $function) {
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'plugins';
|
||||
$this->maniaControl->getFileReader()->loadFile($url, function ($dataJson, $error) use (&$function) {
|
||||
$data = json_decode($dataJson);
|
||||
call_user_func($function, $data, $error);
|
||||
});
|
||||
}
|
||||
}
|
429
core/Plugins/PluginMenu.php
Normal file
429
core/Plugins/PluginMenu.php
Normal file
@ -0,0 +1,429 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Plugins;
|
||||
|
||||
use FML\Components\CheckBox;
|
||||
use FML\Components\ValuePicker;
|
||||
use FML\Controls\Entry;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Button;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons128x128_1;
|
||||
use FML\Controls\Quads\Quad_Icons128x32_1;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Script\Features\Paging;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Configurator\ConfiguratorMenu;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Settings\Setting;
|
||||
|
||||
/**
|
||||
* Configurator for enabling and disabling Plugins
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAnswerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_PREFIX_ENABLEPLUGIN = 'PluginMenu.Enable.';
|
||||
const ACTION_PREFIX_DISABLEPLUGIN = 'PluginMenu.Disable.';
|
||||
const ACTION_PREFIX_SETTINGS = 'PluginMenu.Settings.';
|
||||
const ACTION_PREFIX_SETTING = 'PluginMenuSetting.';
|
||||
const ACTION_BACK_TO_PLUGINS = 'PluginMenu.BackToPlugins';
|
||||
const ACTION_PREFIX_UPDATEPLUGIN = 'PluginMenu.Update.';
|
||||
const ACTION_UPDATEPLUGINS = 'PluginMenu.Update.All';
|
||||
const SETTING_PERMISSION_CHANGE_PLUGIN_SETTINGS = 'Change Plugin Settings';
|
||||
const CACHE_SETTING_CLASS = 'PluginMenuCache.SettingClass';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new plugin menu instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_BACK_TO_PLUGINS, $this, 'backToPlugins');
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_PLUGIN_SETTINGS, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getTitle()
|
||||
*/
|
||||
public static function getTitle() {
|
||||
return 'Plugins';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return back to the plugins overview page
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function backToPlugins($callback, Player $player) {
|
||||
$player->destroyCache($this, self::CACHE_SETTING_CLASS);
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getMenu()
|
||||
*/
|
||||
public function getMenu($width, $height, Script $script, Player $player) {
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$frame = new Frame();
|
||||
|
||||
$pluginClasses = $this->maniaControl->getPluginManager()->getPluginClasses();
|
||||
|
||||
// Config
|
||||
$pagerSize = 9.;
|
||||
$entryHeight = 5.;
|
||||
$pageMaxCount = 10;
|
||||
|
||||
// Pagers
|
||||
$pagerPrev = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerPrev);
|
||||
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2);
|
||||
$pagerPrev->setSize($pagerSize, $pagerSize);
|
||||
$pagerPrev->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_ArrowPrev);
|
||||
|
||||
$pagerNext = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerNext);
|
||||
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2);
|
||||
$pagerNext->setSize($pagerSize, $pagerSize);
|
||||
$pagerNext->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_ArrowNext);
|
||||
|
||||
$paging->addButton($pagerNext);
|
||||
$paging->addButton($pagerPrev);
|
||||
|
||||
$pageCountLabel = new Label_Text();
|
||||
$frame->add($pageCountLabel);
|
||||
$pageCountLabel->setHAlign($pageCountLabel::RIGHT);
|
||||
$pageCountLabel->setPosition($width * 0.35, $height * -0.44, 1);
|
||||
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
|
||||
$pageCountLabel->setTextSize(2);
|
||||
|
||||
$paging->setLabel($pageCountLabel);
|
||||
|
||||
$settingClass = $player->getCache($this, self::CACHE_SETTING_CLASS);
|
||||
if ($settingClass) {
|
||||
// Show Settings Menu
|
||||
return $this->getPluginSettingsMenu($frame, $width, $height, $paging, $player, $settingClass);
|
||||
}
|
||||
|
||||
// Display normal Plugin List
|
||||
// Plugin pages
|
||||
$posY = 0.;
|
||||
$pluginUpdates = $this->maniaControl->getUpdateManager()->getPluginUpdateManager()->getPluginsUpdates();
|
||||
|
||||
usort($pluginClasses, function ($pluginClassA, $pluginClassB) {
|
||||
/** @var Plugin $pluginClassA */
|
||||
/** @var Plugin $pluginClassB */
|
||||
return strcmp($pluginClassA::getName(), $pluginClassB::getName());
|
||||
});
|
||||
|
||||
$pageFrame = null;
|
||||
foreach ($pluginClasses as $index => $pluginClass) {
|
||||
/** @var Plugin $pluginClass */
|
||||
if ($index % $pageMaxCount === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$paging->addPage($pageFrame);
|
||||
$posY = $height * 0.41;
|
||||
}
|
||||
|
||||
$active = $this->maniaControl->getPluginManager()->isPluginActive($pluginClass);
|
||||
|
||||
$pluginFrame = new Frame();
|
||||
$pageFrame->add($pluginFrame);
|
||||
$pluginFrame->setY($posY);
|
||||
|
||||
$activeQuad = new Quad_Icons64x64_1();
|
||||
$pluginFrame->add($activeQuad);
|
||||
$activeQuad->setPosition($width * -0.45, -0.1, 1);
|
||||
$activeQuad->setSize($entryHeight * 0.9, $entryHeight * 0.9);
|
||||
if ($active) {
|
||||
$activeQuad->setSubStyle($activeQuad::SUBSTYLE_LvlGreen);
|
||||
} else {
|
||||
$activeQuad->setSubStyle($activeQuad::SUBSTYLE_LvlRed);
|
||||
}
|
||||
|
||||
$nameLabel = new Label_Text();
|
||||
$pluginFrame->add($nameLabel);
|
||||
$nameLabel->setHAlign($nameLabel::LEFT);
|
||||
$nameLabel->setX($width * -0.4);
|
||||
$nameLabel->setSize($width * 0.5, $entryHeight);
|
||||
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
|
||||
$nameLabel->setTextSize(2);
|
||||
$nameLabel->setText($pluginClass::getName());
|
||||
|
||||
$descriptionLabel = new Label();
|
||||
$pageFrame->add($descriptionLabel);
|
||||
$descriptionLabel->setAlign($descriptionLabel::LEFT, $descriptionLabel::TOP);
|
||||
$descriptionLabel->setPosition($width * -0.45, $height * -0.22);
|
||||
$descriptionLabel->setSize($width * 0.7, $entryHeight);
|
||||
$descriptionLabel->setTextSize(2);
|
||||
$descriptionLabel->setTranslate(true);
|
||||
$descriptionLabel->setVisible(false);
|
||||
$descriptionLabel->setAutoNewLine(true);
|
||||
$descriptionLabel->setMaxLines(5);
|
||||
$description = "Author: {$pluginClass::getAuthor()}\nVersion: {$pluginClass::getVersion()}\nDesc: {$pluginClass::getDescription()}";
|
||||
$descriptionLabel->setText($description);
|
||||
$nameLabel->addTooltipFeature($descriptionLabel);
|
||||
|
||||
$quad = new Quad_Icons128x32_1();
|
||||
$pluginFrame->add($quad);
|
||||
$quad->setSubStyle($quad::SUBSTYLE_Settings);
|
||||
$quad->setX(15);
|
||||
$quad->setZ(1);
|
||||
$quad->setSize(5, 5);
|
||||
$quad->setAction(self::ACTION_PREFIX_SETTINGS . $pluginClass);
|
||||
|
||||
$statusChangeButton = new Label_Button();
|
||||
$pluginFrame->add($statusChangeButton);
|
||||
$statusChangeButton->setHAlign($statusChangeButton::RIGHT);
|
||||
$statusChangeButton->setX($width * 0.45);
|
||||
$statusChangeButton->setStyle($statusChangeButton::STYLE_CardButtonSmall);
|
||||
if ($active) {
|
||||
$statusChangeButton->setTextPrefix('$f00');
|
||||
$statusChangeButton->setText('Deactivate');
|
||||
$statusChangeButton->setAction(self::ACTION_PREFIX_DISABLEPLUGIN . $pluginClass);
|
||||
} else {
|
||||
$statusChangeButton->setTextPrefix('a');
|
||||
$statusChangeButton->setText('Activate');
|
||||
$statusChangeButton->setAction(self::ACTION_PREFIX_ENABLEPLUGIN . $pluginClass);
|
||||
}
|
||||
|
||||
if ($pluginUpdates && array_key_exists($pluginClass::getId(), $pluginUpdates)) {
|
||||
$quadUpdate = new Quad_Icons128x128_1();
|
||||
$pluginFrame->add($quadUpdate);
|
||||
$quadUpdate->setSubStyle($quadUpdate::SUBSTYLE_ProfileVehicle);
|
||||
$quadUpdate->setX(56);
|
||||
$quadUpdate->setZ(2);
|
||||
$quadUpdate->setSize(5, 5);
|
||||
$quadUpdate->setAction(self::ACTION_PREFIX_UPDATEPLUGIN . $pluginClass);
|
||||
}
|
||||
|
||||
$posY -= $entryHeight;
|
||||
}
|
||||
|
||||
if ($pluginUpdates) {
|
||||
$updatePluginsButton = new Label_Button();
|
||||
$frame->add($updatePluginsButton);
|
||||
$updatePluginsButton->setHAlign($updatePluginsButton::RIGHT);
|
||||
$updatePluginsButton->setPosition($width * 0.5, -29, 2);
|
||||
$updatePluginsButton->setWidth(10);
|
||||
$updatePluginsButton->setStyle($updatePluginsButton::STYLE_CardButtonSmallS);
|
||||
$updatePluginsButton->setText(count($pluginUpdates) . ' update(s)');
|
||||
$updatePluginsButton->setAction(self::ACTION_UPDATEPLUGINS);
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Frame with the Plugin Settings
|
||||
*
|
||||
* @param Frame $frame
|
||||
* @param float $width
|
||||
* @param float $height
|
||||
* @param Paging $paging
|
||||
* @param Player $player
|
||||
* @param string $settingClass
|
||||
* @return Frame
|
||||
*/
|
||||
private function getPluginSettingsMenu(Frame $frame, $width, $height, Paging $paging, Player $player, $settingClass) {
|
||||
// TODO: centralize menu code to use by mc settings and plugin settings
|
||||
$settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass);
|
||||
|
||||
$pageSettingsMaxCount = 11;
|
||||
$posY = 0;
|
||||
$index = 0;
|
||||
$settingHeight = 5.;
|
||||
$pageFrame = null;
|
||||
|
||||
//Headline Label
|
||||
$headLabel = new Label_Text();
|
||||
$frame->add($headLabel);
|
||||
$headLabel->setHAlign($headLabel::LEFT);
|
||||
$headLabel->setPosition($width * -0.46, $height * 0.41);
|
||||
$headLabel->setSize($width * 0.6, $settingHeight);
|
||||
$headLabel->setStyle($headLabel::STYLE_TextCardSmall);
|
||||
$headLabel->setTextSize(3);
|
||||
$headLabel->setText($settingClass);
|
||||
$headLabel->setTextColor('ff0');
|
||||
|
||||
foreach ($settings as $setting) {
|
||||
if ($index % $pageSettingsMaxCount === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$paging->addPage($pageFrame);
|
||||
$posY = $height * 0.41 - $settingHeight * 1.5;
|
||||
}
|
||||
|
||||
$settingFrame = new Frame();
|
||||
$pageFrame->add($settingFrame);
|
||||
$settingFrame->setY($posY);
|
||||
|
||||
$nameLabel = new Label_Text();
|
||||
$settingFrame->add($nameLabel);
|
||||
$nameLabel->setHAlign($nameLabel::LEFT);
|
||||
$nameLabel->setX($width * -0.46);
|
||||
$nameLabel->setSize($width * 0.6, $settingHeight);
|
||||
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
|
||||
$nameLabel->setTextSize(2);
|
||||
$nameLabel->setText($setting->setting);
|
||||
$nameLabel->setTextColor('fff');
|
||||
|
||||
if ($setting->type === Setting::TYPE_BOOL) {
|
||||
// Boolean checkbox
|
||||
$quad = new Quad();
|
||||
$quad->setPosition($width * 0.33, 0, -0.01);
|
||||
$quad->setSize(4, 4);
|
||||
$checkBox = new CheckBox(self::ACTION_PREFIX_SETTING . $setting->index, $setting->value, $quad);
|
||||
$settingFrame->add($checkBox);
|
||||
} else if ($setting->type === Setting::TYPE_SET) {
|
||||
// SET value picker
|
||||
$label = new Label_Text();
|
||||
$label->setX($width * 0.33);
|
||||
$label->setSize($width * 0.3, $settingHeight * 0.9);
|
||||
$label->setStyle($label::STYLE_TextValueSmall);
|
||||
$label->setTextSize(1);
|
||||
$valuePicker = new ValuePicker(self::ACTION_PREFIX_SETTING . $setting->index, $setting->set, $setting->value, $label);
|
||||
$settingFrame->add($valuePicker);
|
||||
} else {
|
||||
// Value entry
|
||||
$entry = new Entry();
|
||||
$settingFrame->add($entry);
|
||||
$entry->setX($width * 0.33);
|
||||
$entry->setSize($width * 0.3, $settingHeight * 0.9);
|
||||
$entry->setTextSize(1);
|
||||
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
|
||||
$entry->setName(self::ACTION_PREFIX_SETTING . $setting->index);
|
||||
$entry->setDefault($setting->value);
|
||||
}
|
||||
|
||||
$posY -= $settingHeight;
|
||||
|
||||
$index++;
|
||||
}
|
||||
|
||||
$backButton = new Label_Button();
|
||||
$frame->add($backButton);
|
||||
$backButton->setStyle($backButton::STYLE_CardMain_Quit);
|
||||
$backButton->setHAlign($backButton::LEFT);
|
||||
$backButton->setScale(0.75);
|
||||
$backButton->setText('Back');
|
||||
$backButton->setPosition(-$width / 2 + 7, -$height / 2 + 7);
|
||||
$backButton->setAction(self::ACTION_BACK_TO_PLUGINS);
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PlayerManialinkPageAnswer callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
return;
|
||||
}
|
||||
|
||||
$actionId = $callback[1][2];
|
||||
$enable = (strpos($actionId, self::ACTION_PREFIX_ENABLEPLUGIN) === 0);
|
||||
$disable = (strpos($actionId, self::ACTION_PREFIX_DISABLEPLUGIN) === 0);
|
||||
$settings = (strpos($actionId, self::ACTION_PREFIX_SETTINGS) === 0);
|
||||
if (!$enable && !$disable && !$settings) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($enable) {
|
||||
$pluginClass = substr($actionId, strlen(self::ACTION_PREFIX_ENABLEPLUGIN));
|
||||
/** @var Plugin $pluginClass */
|
||||
$activated = $this->maniaControl->getPluginManager()->activatePlugin($pluginClass, $player->login);
|
||||
if ($activated) {
|
||||
$this->maniaControl->getChat()->sendSuccess($pluginClass::getName() . ' activated!', $player);
|
||||
Logger::logInfo("{$player->login} activated '{$pluginClass}'!", true);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('Error activating ' . $pluginClass::getName() . '!', $player);
|
||||
}
|
||||
} else if ($disable) {
|
||||
$pluginClass = substr($actionId, strlen(self::ACTION_PREFIX_DISABLEPLUGIN));
|
||||
/** @var Plugin $pluginClass */
|
||||
$deactivated = $this->maniaControl->getPluginManager()->deactivatePlugin($pluginClass);
|
||||
if ($deactivated) {
|
||||
$this->maniaControl->getChat()->sendSuccess($pluginClass::getName() . ' deactivated!', $player);
|
||||
Logger::logInfo("{$player->login} deactivated '{$pluginClass}'!", true);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('Error deactivating ' . $pluginClass::getName() . '!', $player);
|
||||
}
|
||||
} else if ($settings) {
|
||||
// Open Settings Menu
|
||||
$pluginClass = substr($actionId, strlen(self::ACTION_PREFIX_SETTINGS));
|
||||
$player->setCache($this, self::CACHE_SETTING_CLASS, $pluginClass);
|
||||
}
|
||||
|
||||
// Reopen the Menu
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||
*/
|
||||
public function saveConfigData(array $configData, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_PLUGIN_SETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
if (!$configData[3] || strpos($configData[3][0]['Name'], self::ACTION_PREFIX_SETTING) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prefixLength = strlen(self::ACTION_PREFIX_SETTING);
|
||||
|
||||
foreach ($configData[3] as $settingData) {
|
||||
$settingIndex = (int)substr($settingData['Name'], $prefixLength);
|
||||
$settingObject = $this->maniaControl->getSettingManager()->getSettingObjectByIndex($settingIndex);
|
||||
if (!$settingObject) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$settingData || $settingData['Value'] == $settingObject->value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$settingObject->value = $settingData['Value'];
|
||||
$this->maniaControl->getSettingManager()->saveSetting($settingObject);
|
||||
}
|
||||
|
||||
$this->maniaControl->getChat()->sendSuccess('Plugin Settings saved!', $player);
|
||||
|
||||
// Reopen the Menu
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
}
|
459
core/Server/Commands.php
Normal file
459
core/Server/Commands.php
Normal file
@ -0,0 +1,459 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use FML\Controls\Quads\Quad_BgRaceScore2;
|
||||
use FML\Controls\Quads\Quad_Icons128x32_1;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
|
||||
/**
|
||||
* Class offering various Commands related to the Dedicated Server
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Commands implements CallbackListener, CommandListener, ManialinkPageAnswerListener, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_SET_PAUSE = 'ServerCommands.SetPause';
|
||||
const ACTION_EXTEND_WARMUP = 'ServerCommands.ExtendWarmup';
|
||||
const ACTION_END_WARMUP = 'ServerCommands.EndWarmup';
|
||||
const ACTION_CANCEL_VOTE = 'ServerCommands.CancelVote';
|
||||
const CB_VOTE_CANCELLED = 'ServerCommands.VoteCancelled';
|
||||
const SETTING_PERMISSION_CANCEL_VOTE = 'Cancel Vote';
|
||||
const SETTING_PERMISSION_SET_PAUSE = 'Set Pause';
|
||||
const SETTING_PERMISSION_HANDLE_WARMUP = 'Handle Warmup';
|
||||
const SETTING_PERMISSION_SHOW_SYSTEMINFO = 'Show SystemInfo';
|
||||
const SETTING_PERMISSION_SHUTDOWN_SERVER = 'Shutdown Server';
|
||||
const SETTING_PERMISSION_CHANGE_SERVERSETTINGS = 'Change ServerSettings';
|
||||
const COMMAND_EXTEND_WARMUP = 'WarmUp_Extend';
|
||||
const COMMAND_FORCE_WARMUP = 'Command_ForceWarmUp';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $serverShutdownTime = -1;
|
||||
private $serverShutdownEmpty = false;
|
||||
|
||||
/**
|
||||
* Create a new server commands instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getTimerManager()->registerTimerListening($this, 'each5Seconds', 5000);
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::WARMUPSTATUS, $this, 'handleWarmUpStatus');
|
||||
|
||||
// Chat commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('setservername', $this, 'commandSetServerName', true, 'Sets the ServerName.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('setpwd', $this, 'commandSetPwd', true, 'Sets play password.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('setspecpwd', $this, 'commandSetSpecPwd', true, 'Sets spectator password.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('setmaxplayers', $this, 'commandSetMaxPlayers', true, 'Sets the maximum number of players.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('setmaxspectators', $this, 'commandSetMaxSpectators', true, 'Sets the maximum number of spectators.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('shutdownserver', $this, 'commandShutdownServer', true, 'Shuts down the ManiaPlanet server.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('systeminfo', $this, 'commandSystemInfo', true, 'Shows system information.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('cancel', $this, 'commandCancelVote', true, 'Cancels the current vote.');
|
||||
|
||||
// Page actions
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SET_PAUSE, $this, 'setPause');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_EXTEND_WARMUP, $this, 'commandExtendWarmup');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_END_WARMUP, $this, 'commandEndWarmup');
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_CANCEL_VOTE, $this, 'commandCancelVote');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManiaControl OnInit Callback
|
||||
*/
|
||||
public function handleOnInit() {
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_SHUTDOWN_SERVER, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_SHOW_SYSTEMINFO, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_SET_PAUSE, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CANCEL_VOTE, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_HANDLE_WARMUP, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
|
||||
$this->updateCancelVoteMenuItem();
|
||||
$this->updateWarmUpMenuItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the cancel vote menu item
|
||||
*/
|
||||
private function updateCancelVoteMenuItem() {
|
||||
$itemQuad = new Quad_Icons64x64_1();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_ArrowRed);
|
||||
$itemQuad->setAction(self::ACTION_CANCEL_VOTE);
|
||||
$this->maniaControl->getActionsMenu()->addMenuItem($itemQuad, false, 30, 'Cancel Vote');
|
||||
}
|
||||
|
||||
/**
|
||||
* Manage the WarmUp related menu items
|
||||
*/
|
||||
private function updateWarmUpMenuItems() {
|
||||
$pauseExists = false;
|
||||
try {
|
||||
$scriptInfos = $this->maniaControl->getClient()->getModeScriptInfo();
|
||||
foreach ($scriptInfos->commandDescs as $param) {
|
||||
if ($param->name === self::COMMAND_FORCE_WARMUP) {
|
||||
$pauseExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->maniaControl->getClient()->triggerModeScriptEvent("WarmUp_GetStatus");
|
||||
} catch (GameModeException $e) {
|
||||
}
|
||||
|
||||
// Add pause menu item
|
||||
if ($pauseExists) {
|
||||
$itemQuad = new Quad_Icons128x32_1();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_ManiaLinkSwitch);
|
||||
$itemQuad->setAction(self::ACTION_SET_PAUSE);
|
||||
$this->maniaControl->getActionsMenu()->addAdminMenuItem($itemQuad, 13, 'Pause the current game');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the WarmupStatus Callback, and removes or adds the Menu Items for extending / Stopping warmup
|
||||
*
|
||||
* @param $warmupEnabled
|
||||
*/
|
||||
public function handleWarmUpStatus($warmupEnabled) {
|
||||
if ($warmupEnabled) {
|
||||
// Extend WarmUp menu item
|
||||
$itemQuad = new Quad_BgRaceScore2();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_SendScore);
|
||||
$itemQuad->setAction(self::ACTION_EXTEND_WARMUP);
|
||||
$this->maniaControl->getActionsMenu()->addMenuItem($itemQuad, false, 14, 'Extend Warmup');
|
||||
|
||||
// Stop WarmUp menu item
|
||||
$itemQuad = new Quad_Icons64x64_1();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_ArrowGreen);
|
||||
$itemQuad->setAction(self::ACTION_END_WARMUP);
|
||||
$this->maniaControl->getActionsMenu()->addMenuItem($itemQuad, false, 15, 'End Warmup');
|
||||
} else {
|
||||
$this->maniaControl->getActionsMenu()->removeMenuItem(14, false);
|
||||
$this->maniaControl->getActionsMenu()->removeMenuItem(15, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //cancelvote command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandCancelVote(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CANCEL_VOTE)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_VOTE_CANCELLED, $player);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extend the WarmUp
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandExtendWarmup(array $callback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_HANDLE_WARMUP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->triggerModeScriptEvent('WarmUp_Extend', '10');
|
||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' extended the WarmUp by 10 seconds!');
|
||||
} catch (GameModeException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End the WarmUp
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandEndWarmup(array $callback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_HANDLE_WARMUP)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->maniaControl->getClient()->triggerModeScriptEvent('WarmUp_Stop', '');
|
||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' stopped the WarmUp!');
|
||||
} catch (GameModeException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pause the current game
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function setPause(array $callback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SET_PAUSE)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$this->maniaControl->getClient()->sendModeScriptCommands(array('Command_ForceWarmUp' => true));
|
||||
$this->maniaControl->getChat()->sendInformation($player->getEscapedNickname() . ' paused the Game!');
|
||||
} catch (GameModeException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check Stuff each 5 Seconds
|
||||
*/
|
||||
public function each5Seconds() {
|
||||
// TODO: move empty & delayed shutdown code into server class
|
||||
// Empty shutdown
|
||||
if ($this->serverShutdownEmpty) {
|
||||
if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) <= 0
|
||||
) {
|
||||
$this->shutdownServer('empty');
|
||||
}
|
||||
}
|
||||
|
||||
// Delayed shutdown
|
||||
if ($this->serverShutdownTime > 0) {
|
||||
if (time() >= $this->serverShutdownTime) {
|
||||
$this->shutdownServer('delayed');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform server shutdown
|
||||
*
|
||||
* @param string $login
|
||||
*/
|
||||
private function shutdownServer($login = '-') {
|
||||
Logger::logInfo("Server shutdown requested by '{$login}'!");
|
||||
$this->maniaControl->getClient()->stopServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //systeminfo command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandSystemInfo(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SHOW_SYSTEMINFO)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$systemInfo = $this->maniaControl->getClient()->getSystemInfo();
|
||||
$message = 'SystemInfo: ip=' . $systemInfo->publishedIp . ', port=' . $systemInfo->port . ', p2pPort=' . $systemInfo->p2PPort . ', title=' . $systemInfo->titleId . ', login=' . $systemInfo->serverLogin . '.';
|
||||
$this->maniaControl->getChat()->sendInformation($message, $player->login);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //shutdownserver command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandShutdownServer(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_SHUTDOWN_SERVER)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
// Check for delayed shutdown
|
||||
$params = explode(' ', $chat[1][2]);
|
||||
if (count($params) >= 2) {
|
||||
$param = $params[1];
|
||||
if (strtolower($param) === 'empty') {
|
||||
$this->serverShutdownEmpty = !$this->serverShutdownEmpty;
|
||||
if ($this->serverShutdownEmpty) {
|
||||
$this->maniaControl->getChat()->sendInformation("The server will shutdown as soon as it's empty!", $player);
|
||||
return;
|
||||
}
|
||||
$this->maniaControl->getChat()->sendInformation("Empty-shutdown cancelled!", $player);
|
||||
return;
|
||||
}
|
||||
$delay = (int)$param;
|
||||
if ($delay <= 0) {
|
||||
// Cancel shutdown
|
||||
$this->serverShutdownTime = -1;
|
||||
$this->maniaControl->getChat()->sendInformation("Delayed shutdown cancelled!", $player);
|
||||
return;
|
||||
}
|
||||
// Trigger delayed shutdown
|
||||
$this->serverShutdownTime = time() + $delay * 60.;
|
||||
$this->maniaControl->getChat()->sendInformation("The server will shut down in {$delay} minutes!", $player);
|
||||
return;
|
||||
}
|
||||
$this->shutdownServer($player->login);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //setservername command
|
||||
*
|
||||
* @param array $chat
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandSetServerName(array $chat, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$params = explode(' ', $chat[1][2], 2);
|
||||
if (count($params) < 2) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setservername ManiaPlanet Server', $player);
|
||||
return;
|
||||
}
|
||||
$serverName = $params[1];
|
||||
$this->maniaControl->getClient()->setServerName($serverName);
|
||||
$this->maniaControl->getChat()->sendSuccess("Server name changed to: '{$serverName}'!", $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //setpwd command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandSetPwd(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$messageParts = explode(' ', $chatCallback[1][2], 2);
|
||||
$password = '';
|
||||
$successMessage = 'Password removed!';
|
||||
if (isset($messageParts[1])) {
|
||||
$password = $messageParts[1];
|
||||
$successMessage = "Password changed to: '{$password}'!";
|
||||
}
|
||||
$this->maniaControl->getClient()->setServerPassword($password);
|
||||
$this->maniaControl->getChat()->sendSuccess($successMessage, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //setspecpwd command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandSetSpecPwd(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$messageParts = explode(' ', $chatCallback[1][2], 2);
|
||||
$password = '';
|
||||
$successMessage = 'Spectator password removed!';
|
||||
if (isset($messageParts[1])) {
|
||||
$password = $messageParts[1];
|
||||
$successMessage = "Spectator password changed to: '{$password}'!";
|
||||
}
|
||||
$this->maniaControl->getClient()->setServerPasswordForSpectator($password);
|
||||
$this->maniaControl->getChat()->sendSuccess($successMessage, $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //setmaxplayers command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandSetMaxPlayers(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$messageParts = explode(' ', $chatCallback[1][2], 2);
|
||||
if (!isset($messageParts[1])) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxplayers 16', $player);
|
||||
return;
|
||||
}
|
||||
$amount = $messageParts[1];
|
||||
if (!is_numeric($amount)) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxplayers 16', $player);
|
||||
return;
|
||||
}
|
||||
$amount = (int)$amount;
|
||||
if ($amount < 0) {
|
||||
$amount = 0;
|
||||
}
|
||||
|
||||
$this->maniaControl->getClient()->setMaxPlayers($amount);
|
||||
$this->maniaControl->getChat()->sendSuccess("Changed max players to: {$amount}", $player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //setmaxspectators command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function commandSetMaxSpectators(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVERSETTINGS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
$messageParts = explode(' ', $chatCallback[1][2], 2);
|
||||
if (!isset($messageParts[1])) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxspectators 16', $player);
|
||||
return;
|
||||
}
|
||||
$amount = $messageParts[1];
|
||||
if (!is_numeric($amount)) {
|
||||
$this->maniaControl->getChat()->sendUsageInfo('Usage example: //setmaxspectators 16', $player);
|
||||
return;
|
||||
}
|
||||
$amount = (int)$amount;
|
||||
if ($amount < 0) {
|
||||
$amount = 0;
|
||||
}
|
||||
|
||||
$this->maniaControl->getClient()->setMaxSpectators($amount);
|
||||
$this->maniaControl->getChat()->sendSuccess("Changed max spectators to: {$amount}", $player);
|
||||
}
|
||||
}
|
89
core/Server/Config.php
Normal file
89
core/Server/Config.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
/**
|
||||
* Model Class holding the Server Config
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Config {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $id = null;
|
||||
public $host = null;
|
||||
public $port = null;
|
||||
public $user = null;
|
||||
public $pass = null;
|
||||
|
||||
/**
|
||||
* Create a new server config instance
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param mixed $host
|
||||
* @param mixed $port
|
||||
* @param mixed $user
|
||||
* @param mixed $pass
|
||||
*/
|
||||
public function __construct($id = null, $host = null, $port = null, $user = null, $pass = null) {
|
||||
$this->id = $this->extractConfigData($id);
|
||||
$this->host = $this->extractConfigData($host);
|
||||
$this->port = $this->extractConfigData($port);
|
||||
$this->user = $this->extractConfigData($user);
|
||||
$this->pass = $this->extractConfigData($pass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the actual Data from the given Config Param
|
||||
*
|
||||
* @param mixed $configParam
|
||||
* @return string
|
||||
*/
|
||||
private function extractConfigData($configParam) {
|
||||
if (is_array($configParam)) {
|
||||
return (string)reset($configParam);
|
||||
}
|
||||
return (string)$configParam;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the Config Data
|
||||
*
|
||||
* @param string $message
|
||||
* @return bool
|
||||
*/
|
||||
public function validate(&$message = null) {
|
||||
// Host
|
||||
if (!$this->host) {
|
||||
$message = 'Missing Host!';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Port
|
||||
if (!$this->port || $this->port === 'port') {
|
||||
$message = 'Missing Port!';
|
||||
return false;
|
||||
}
|
||||
|
||||
// User
|
||||
if (!$this->user) {
|
||||
$message = 'Missing User!';
|
||||
return false;
|
||||
}
|
||||
if (!in_array($this->user, array('SuperAdmin', 'Admin', 'User'))) {
|
||||
$message = 'Invalid User!';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Pass
|
||||
if (!$this->pass) {
|
||||
$message = 'Missing Pass!';
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
104
core/Server/Directory.php
Normal file
104
core/Server/Directory.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Class offering Operations for the Server Directory
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Directory implements CallbackListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct new server directory instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_SERVERSTOP, $this, 'handleServerStopCallback');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Maps Folder Path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getMapsFolder() {
|
||||
return $this->maniaControl->getClient()->getMapsDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Skins Folder Path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSkinsFolder() {
|
||||
return $this->maniaControl->getClient()->getSkinsDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Server Stop Callback
|
||||
*/
|
||||
public function handleServerStopCallback() {
|
||||
$this->cleanLogsFolder();
|
||||
$this->cleanCacheFolder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the server logs folder
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function cleanLogsFolder() {
|
||||
return FileUtil::cleanDirectory($this->getLogsFolder());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Logs Folder Path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLogsFolder() {
|
||||
return $this->getGameDataFolder() . '..' . DIRECTORY_SEPARATOR . 'Logs' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Game Data Folder Path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGameDataFolder() {
|
||||
return $this->maniaControl->getClient()->gameDataDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function cleanCacheFolder() {
|
||||
return FileUtil::cleanDirectory($this->getCacheFolder(), 50);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Cache Folder Path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCacheFolder() {
|
||||
return $this->getGameDataFolder() . '..' . DIRECTORY_SEPARATOR . 'CommonData' . DIRECTORY_SEPARATOR . 'Cache' . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
}
|
138
core/Server/RankingManager.php
Normal file
138
core/Server/RankingManager.php
Normal file
@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Maps\Map;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
|
||||
/**
|
||||
* Class managing Rankings
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class RankingManager implements CallbackListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
private $rankings = array();
|
||||
|
||||
/**
|
||||
* Construct a new ranking manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_MODESCRIPTCALLBACK, $this, 'handleCallbacks');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_MODESCRIPTCALLBACKARRAY, $this, 'handleCallbacks');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::BEGINMAP, $this, 'handleBeginMap');
|
||||
//TODO won message at end of the map (disable as setting) (and public announce only all %50 (setting) players)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Rankings (never call this Method)
|
||||
*/
|
||||
public function onInit() {
|
||||
try {
|
||||
$this->maniaControl->getClient()->triggerModeScriptEvent('LibXmlRpc_GetRankings', '');
|
||||
} catch (GameModeException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle stats on callbacks (never call this Method)
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleCallbacks(array $callback) {
|
||||
$callbackName = $callback[1][0];
|
||||
|
||||
//TODO not tested in TrackMania
|
||||
switch ($callbackName) {
|
||||
case 'updateRankings':
|
||||
$this->updateRankings($callback[1][1][0]);
|
||||
break;
|
||||
case 'endRound':
|
||||
case 'beginRound':
|
||||
case 'endMap':
|
||||
case 'endMap1':
|
||||
$this->updateRankings($callback[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the rankings on the Begin of a Map
|
||||
*
|
||||
* @param Map $map
|
||||
*/
|
||||
public function handleBeginMap(Map $map) {
|
||||
$this->rankings = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Game Rankings (never call this Method)
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
public function updateRankings($data) {
|
||||
if (!is_string($data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO in legacy mode, no data is in parameter -> fetch via method getCurrentRanking
|
||||
|
||||
$scores = explode(';', $data);
|
||||
foreach ($scores as $player) {
|
||||
if (strpos($player, ':') !== false) {
|
||||
$tmp = explode(':', $player);
|
||||
$this->rankings[$tmp[0]] = $tmp[1];
|
||||
}
|
||||
}
|
||||
array_multisort($this->rankings, SORT_DESC, SORT_NUMERIC);
|
||||
|
||||
//TODO if Local Records activated-> sort asc
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(Callbacks::RANKINGSUPDATED, $this->getRankings());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Rankings
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRankings() {
|
||||
return $this->rankings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Current Leading Players (as Login Array)
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getLeaders() {
|
||||
$leaders = array();
|
||||
$prev = -1;
|
||||
foreach ($this->rankings as $score) {
|
||||
if ($prev !== -1 && $prev < $score) {
|
||||
return $leaders;
|
||||
}
|
||||
// FIXME: $leader doesn't exist
|
||||
array_push($leaders, $leader);
|
||||
$prev = $score;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPlayerRanking() {
|
||||
//TODO complete this
|
||||
}
|
||||
}
|
68
core/Server/ScriptManager.php
Normal file
68
core/Server/ScriptManager.php
Normal file
@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Manager for Game Mode Script related Stuff
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ScriptManager {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $isScriptMode = null;
|
||||
|
||||
/**
|
||||
* Construct a new script manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable script callbacks
|
||||
*
|
||||
* @param bool $enable
|
||||
* @return bool
|
||||
*/
|
||||
public function enableScriptCallbacks($enable = true) {
|
||||
if (!$this->isScriptMode()) {
|
||||
return false;
|
||||
}
|
||||
$scriptSettings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||||
|
||||
if (!array_key_exists('S_UseScriptCallbacks', $scriptSettings)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$scriptSettings['S_UseScriptCallbacks'] = (bool)$enable;
|
||||
$actionName = ($enable ? 'en' : 'dis');
|
||||
|
||||
$this->maniaControl->getClient()->setModeScriptSettings($scriptSettings);
|
||||
Logger::logInfo("Script Callbacks successfully {$actionName}abled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the Server is running in Script Mode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isScriptMode() {
|
||||
if (is_null($this->isScriptMode)) {
|
||||
$gameMode = $this->maniaControl->getClient()->getGameMode();
|
||||
$this->isScriptMode = ($gameMode === 0);
|
||||
}
|
||||
return $this->isScriptMode;
|
||||
}
|
||||
}
|
459
core/Server/Server.php
Normal file
459
core/Server/Server.php
Normal file
@ -0,0 +1,459 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Utils\CommandLineHelper;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\Exception;
|
||||
|
||||
/**
|
||||
* Class providing access to the connected ManiaPlanet Server
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Server implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TABLE_SERVERS = 'mc_servers';
|
||||
const CB_TEAM_MODE_CHANGED = 'Server.TeamModeChanged';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var Config $config */
|
||||
public $config = null;
|
||||
public $index = -1;
|
||||
public $ip = null;
|
||||
public $port = -1;
|
||||
public $p2pPort = -1;
|
||||
public $login = null;
|
||||
public $titleId = null;
|
||||
/** @var Directory $directory */
|
||||
/** @deprecated see getDirectory() */
|
||||
public $directory = null;
|
||||
/** @var Commands $commands */
|
||||
/** @deprecated see getCommands() */
|
||||
public $commands = null;
|
||||
/** @var UsageReporter $usageReporter */
|
||||
/** @deprecated see getUsageReporter() */
|
||||
public $usageReporter = null;
|
||||
/** @var RankingManager $rankingManager */
|
||||
/** @deprecated see getRankingManager() */
|
||||
public $rankingManager = null;
|
||||
/** @var ScriptManager $scriptManager */
|
||||
/** @deprecated see getScriptManager() */
|
||||
public $scriptManager = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $teamMode = null;
|
||||
|
||||
/**
|
||||
* Construct a new Server
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
$this->directory = new Directory($maniaControl);
|
||||
$this->commands = new Commands($maniaControl);
|
||||
$this->usageReporter = new UsageReporter($maniaControl);
|
||||
$this->rankingManager = new RankingManager($maniaControl);
|
||||
$this->scriptManager = new ScriptManager($maniaControl);
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize necessary Database Tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_SERVERS . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`login` varchar(100) NOT NULL,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `login` (`login`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Servers' AUTO_INCREMENT=1;";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server config
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function getConfig() {
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server directory
|
||||
*
|
||||
* @return Directory
|
||||
*/
|
||||
public function getDirectory() {
|
||||
return $this->directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the server commands
|
||||
*
|
||||
* @return Commands
|
||||
*/
|
||||
public function getCommands() {
|
||||
return $this->commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the usage reporter
|
||||
*
|
||||
* @return UsageReporter
|
||||
*/
|
||||
public function getUsageReporter() {
|
||||
return $this->usageReporter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ranking manager
|
||||
*
|
||||
* @return RankingManager
|
||||
*/
|
||||
public function getRankingManager() {
|
||||
return $this->rankingManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the script manager
|
||||
*
|
||||
* @return ScriptManager
|
||||
*/
|
||||
public function getScriptManager() {
|
||||
return $this->scriptManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the server configuration from the config XML
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function loadConfig() {
|
||||
// Server id parameter
|
||||
$serverId = CommandLineHelper::getParameter('-id');
|
||||
|
||||
// Server xml element with given id
|
||||
$serverElement = null;
|
||||
if ($serverId) {
|
||||
$serverElements = $this->maniaControl->getConfig()->xpath("server[@id='{$serverId}']");
|
||||
if (!$serverElements) {
|
||||
$this->maniaControl->quit("No Server configured with the ID '{$serverId}'!", true);
|
||||
}
|
||||
$serverElement = $serverElements[0];
|
||||
} else {
|
||||
$serverElements = $this->maniaControl->getConfig()->xpath('server');
|
||||
if (!$serverElements) {
|
||||
$this->maniaControl->quit('Invalid server configuration (No Server configured).', true);
|
||||
}
|
||||
$serverElement = $serverElements[0];
|
||||
}
|
||||
|
||||
// Get config elements
|
||||
$hostElements = $serverElement->xpath('host');
|
||||
$portElements = $serverElement->xpath('port');
|
||||
$userElements = $serverElement->xpath('user');
|
||||
if (!$userElements) {
|
||||
$userElements = $serverElement->xpath('login');
|
||||
}
|
||||
$passElements = $serverElement->xpath('pass');
|
||||
|
||||
// Create config object
|
||||
$config = new Config($serverId, $hostElements, $portElements, $userElements, $passElements);
|
||||
$message = null;
|
||||
if (!$config->validate($message)) {
|
||||
$this->maniaControl->quit("Your config file doesn't seem to be maintained properly. Please check the server configuration again! {$message}", true);
|
||||
}
|
||||
$this->config = $config;
|
||||
return $this->config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all Servers from the Database
|
||||
*
|
||||
* @return \stdClass[]
|
||||
*/
|
||||
public function getAllServers() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "SELECT * FROM `" . self::TABLE_SERVERS . "`;";
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return array();
|
||||
}
|
||||
|
||||
$servers = array();
|
||||
while ($row = $result->fetch_object()) {
|
||||
array_push($servers, $row);
|
||||
}
|
||||
$result->free();
|
||||
|
||||
return $servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle OnInit Callback
|
||||
*/
|
||||
public function onInit() {
|
||||
$this->updateProperties();
|
||||
}
|
||||
|
||||
/**
|
||||
* Refetch the Server Properties
|
||||
*/
|
||||
private function updateProperties() {
|
||||
// System info
|
||||
$systemInfo = $this->maniaControl->getClient()->getSystemInfo();
|
||||
$this->ip = $systemInfo->publishedIp;
|
||||
$this->port = $systemInfo->port;
|
||||
$this->p2pPort = $systemInfo->p2PPort;
|
||||
$this->login = $systemInfo->serverLogin;
|
||||
$this->titleId = $systemInfo->titleId;
|
||||
|
||||
// Database index
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "INSERT INTO `" . self::TABLE_SERVERS . "` (
|
||||
`login`
|
||||
) VALUES (
|
||||
?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`index` = LAST_INSERT_ID(`index`);";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return;
|
||||
}
|
||||
$statement->bind_param('s', $this->login);
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
$statement->close();
|
||||
return;
|
||||
}
|
||||
$this->index = $statement->insert_id;
|
||||
$statement->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Server Player Info
|
||||
*
|
||||
* @return \Maniaplanet\DedicatedServer\Structures\PlayerDetailedInfo
|
||||
*/
|
||||
public function getInfo() {
|
||||
return $this->maniaControl->getClient()->getDetailedPlayerInfo($this->login);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Validation Replay for the given Player
|
||||
*
|
||||
* @param string $login
|
||||
* @return string
|
||||
*/
|
||||
public function getValidationReplay($login) {
|
||||
$login = Player::parseLogin($login);
|
||||
try {
|
||||
$replay = $this->maniaControl->getClient()->getValidationReplay($login);
|
||||
} catch (Exception $e) {
|
||||
// TODO temp added 19.04.2014
|
||||
$this->maniaControl->getErrorHandler()->triggerDebugNotice("Exception line 330 Server.php" . $e->getMessage());
|
||||
trigger_error("Couldn't get validation replay of '{$login}'. " . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
return $replay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve Ghost Replay for the given Player
|
||||
*
|
||||
* @param string $login
|
||||
* @return string
|
||||
*/
|
||||
public function getGhostReplay($login) {
|
||||
$dataDir = $this->getDirectory()->getGameDataFolder();
|
||||
if (!$this->checkAccess($dataDir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Build file name
|
||||
$login = Player::parseLogin($login);
|
||||
$map = $this->maniaControl->getMapManager()->getCurrentMap();
|
||||
$gameMode = $this->getGameMode();
|
||||
$time = time();
|
||||
$fileName = "GhostReplays/Ghost.{$login}.{$gameMode}.{$time}.{$map->uid}.Replay.Gbx";
|
||||
|
||||
// Save ghost replay
|
||||
try {
|
||||
$this->maniaControl->getClient()->saveBestGhostsReplay($login, $fileName);
|
||||
} catch (Exception $e) {
|
||||
// TODO temp added 19.04.2014
|
||||
$this->maniaControl->getErrorHandler()->triggerDebugNotice("Exception line 360 Server.php" . $e->getMessage());
|
||||
|
||||
trigger_error("Couldn't save ghost replay. " . $e->getMessage());
|
||||
return null;
|
||||
}
|
||||
|
||||
// Load replay file
|
||||
$ghostReplay = file_get_contents("{$dataDir}Replays/{$fileName}");
|
||||
if (!$ghostReplay) {
|
||||
trigger_error("Couldn't retrieve saved ghost replay.");
|
||||
return null;
|
||||
}
|
||||
return $ghostReplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if ManiaControl has Access to the given Directory
|
||||
*
|
||||
* @param string $directory
|
||||
* @return bool
|
||||
*/
|
||||
public function checkAccess($directory) {
|
||||
return (is_dir($directory) && is_writable($directory));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the current Game Mode
|
||||
*
|
||||
* @param bool $stringValue
|
||||
* @param int $parseValue
|
||||
* @return int | string
|
||||
*/
|
||||
public function getGameMode($stringValue = false, $parseValue = null) {
|
||||
if (is_int($parseValue)) {
|
||||
$gameMode = $parseValue;
|
||||
} else {
|
||||
$gameMode = $this->maniaControl->getClient()->getGameMode();
|
||||
}
|
||||
if ($stringValue) {
|
||||
switch ($gameMode) {
|
||||
case 0:
|
||||
return 'Script';
|
||||
case 1:
|
||||
return 'Rounds';
|
||||
case 2:
|
||||
return 'TimeAttack';
|
||||
case 3:
|
||||
return 'Team';
|
||||
case 4:
|
||||
return 'Laps';
|
||||
case 5:
|
||||
return 'Cup';
|
||||
case 6:
|
||||
return 'Stunts';
|
||||
default:
|
||||
return 'Unknown';
|
||||
}
|
||||
}
|
||||
return $gameMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the Server to have the given Status
|
||||
*
|
||||
* @param int $statusCode
|
||||
* @return bool
|
||||
*/
|
||||
public function waitForStatus($statusCode = 4) {
|
||||
$response = $this->maniaControl->getClient()->getStatus();
|
||||
// Check if server has the given status
|
||||
if ($response->code === 4) {
|
||||
return true;
|
||||
}
|
||||
// Server not yet in given status - Wait for it...
|
||||
$waitBegin = time();
|
||||
$maxWaitTime = 50;
|
||||
$lastStatus = $response->name;
|
||||
Logger::log("Waiting for server to reach status {$statusCode}...");
|
||||
Logger::log("Current Status: {$lastStatus}");
|
||||
while ($response->code !== 4) {
|
||||
sleep(1);
|
||||
$response = $this->maniaControl->getClient()->getStatus();
|
||||
if ($lastStatus !== $response->name) {
|
||||
Logger::log("New Status: {$response->name}");
|
||||
$lastStatus = $response->name;
|
||||
}
|
||||
if (time() - $maxWaitTime > $waitBegin) {
|
||||
// It took too long to reach the status
|
||||
Logger::logError("Server couldn't reach status {$statusCode} after {$maxWaitTime} seconds! ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the Server Runs a Team-Based Mode or not
|
||||
*
|
||||
* @param bool $teamMode
|
||||
*/
|
||||
public function setTeamMode($teamMode = true) {
|
||||
$oldStatus = $this->teamMode;
|
||||
$this->teamMode = (bool)$teamMode;
|
||||
|
||||
// Trigger callback
|
||||
if ($oldStatus !== $this->teamMode | $oldStatus === null) {
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_TEAM_MODE_CHANGED, $teamMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Server Runs a Team-Based Mode
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isTeamMode() {
|
||||
return $this->teamMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the join link
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getJoinLink() {
|
||||
return 'maniaplanet://#join=' . $this->login . '@' . $this->titleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Servers is empty
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEmpty() {
|
||||
return ($this->maniaControl->getPlayerManager()->getPlayerCount(false) === 0);
|
||||
}
|
||||
}
|
379
core/Server/ServerOptionsMenu.php
Normal file
379
core/Server/ServerOptionsMenu.php
Normal file
@ -0,0 +1,379 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use FML\Components\CheckBox;
|
||||
use FML\Controls\Entry;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Script\Features\Paging;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Configurator\ConfiguratorMenu;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Structures\ServerOptions;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\ServerOptionsException;
|
||||
|
||||
/**
|
||||
* Class offering a Configurator Menu for Server Options
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CB_SERVER_OPTION_CHANGED = 'ServerOptionsMenu.OptionChanged';
|
||||
const CB_SERVER_OPTIONS_CHANGED = 'ServerOptionsMenu.OptionsChanged';
|
||||
const SETTING_PERMISSION_CHANGE_SERVER_OPTIONS = 'Change Server Options';
|
||||
const TABLE_SERVER_OPTIONS = 'mc_server_options';
|
||||
const ACTION_PREFIX_OPTION = 'ServerOptionsMenu.';
|
||||
|
||||
/** @deprecated */
|
||||
const CB_SERVERSETTING_CHANGED = self::CB_SERVER_OPTION_CHANGED;
|
||||
/** @deprecated */
|
||||
const CB_SERVERSETTINGS_CHANGED = self::CB_SERVER_OPTIONS_CHANGED;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new server options menu instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
||||
$this->maniaControl->getTimerManager()->registerTimerListening($this, 'saveCurrentServerOptions', 6 * 3600 * 1000);
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_SERVER_OPTIONS, AuthenticationManager::AUTH_LEVEL_SUPERADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize necessary database tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_SERVER_OPTIONS . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`serverIndex` int(11) NOT NULL,
|
||||
`optionName` varchar(100) NOT NULL,
|
||||
`optionValue` varchar(500) NOT NULL,
|
||||
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `option` (`serverIndex`, `optionName`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Server Options' AUTO_INCREMENT=1;";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getTitle()
|
||||
*/
|
||||
public static function getTitle() {
|
||||
return 'Server Options';
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current server options in case they have been changed by an external tool
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function saveCurrentServerOptions() {
|
||||
$serverOptions = $this->maniaControl->getClient()->getServerOptions();
|
||||
return $this->saveServerOptions($serverOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the given server options in the database
|
||||
*
|
||||
* @param ServerOptions $serverOptions
|
||||
* @param bool $triggerCallbacks
|
||||
* @return bool
|
||||
*/
|
||||
private function saveServerOptions(ServerOptions $serverOptions, $triggerCallbacks = false) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "INSERT INTO `" . self::TABLE_SERVER_OPTIONS . "` (
|
||||
`serverIndex`,
|
||||
`optionName`,
|
||||
`optionValue`
|
||||
) VALUES (
|
||||
?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`optionValue` = VALUES(`optionValue`);";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
$optionName = null;
|
||||
$optionValue = null;
|
||||
$statement->bind_param('iss', $this->maniaControl->getServer()->index, $optionName, $optionValue);
|
||||
|
||||
$serverOptionsArray = $serverOptions->toArray();
|
||||
foreach ($serverOptionsArray as $optionName => $optionValue) {
|
||||
if ($optionValue === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
$statement->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($triggerCallbacks) {
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SERVER_OPTION_CHANGED, array(self::CB_SERVER_OPTION_CHANGED, $optionName, $optionValue));
|
||||
}
|
||||
}
|
||||
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle OnInit callback
|
||||
*/
|
||||
public function onInit() {
|
||||
$this->loadOptionsFromDatabase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Load options from database
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function loadOptionsFromDatabase() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$serverIndex = $this->maniaControl->getServer()->index;
|
||||
$query = "SELECT * FROM `" . self::TABLE_SERVER_OPTIONS . "`
|
||||
WHERE `serverIndex` = {$serverIndex};";
|
||||
$result = $mysqli->query($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
$oldServerOptions = $this->maniaControl->getClient()->getServerOptions();
|
||||
$newServerOptions = new ServerOptions();
|
||||
|
||||
while ($row = $result->fetch_object()) {
|
||||
$optionName = lcfirst($row->optionName);
|
||||
if (!property_exists($oldServerOptions, $optionName)) {
|
||||
continue;
|
||||
}
|
||||
$newServerOptions->$optionName = $row->optionValue;
|
||||
settype($newServerOptions->$optionName, gettype($oldServerOptions->$optionName));
|
||||
}
|
||||
$result->free();
|
||||
|
||||
$this->fillUpMandatoryOptions($newServerOptions, $oldServerOptions);
|
||||
|
||||
$loaded = false;
|
||||
try {
|
||||
$loaded = $this->maniaControl->getClient()->setServerOptions($newServerOptions);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendExceptionToAdmins($exception);
|
||||
}
|
||||
|
||||
if ($loaded) {
|
||||
Logger::logInfo('Server Options successfully loaded!');
|
||||
} else {
|
||||
Logger::logError('Error loading Server Options!');
|
||||
}
|
||||
|
||||
return $loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill up the new server options object with the necessary options based on the old options object
|
||||
*
|
||||
* @param ServerOptions $newServerOptions
|
||||
* @param ServerOptions $oldServerOptions
|
||||
* @return ServerOptions
|
||||
*/
|
||||
private function fillUpMandatoryOptions(ServerOptions &$newServerOptions, ServerOptions $oldServerOptions) {
|
||||
$mandatoryOptions = array('name', 'comment', 'password', 'passwordForSpectator', 'nextCallVoteTimeOut', 'callVoteRatio');
|
||||
foreach ($mandatoryOptions as $optionName) {
|
||||
if (!isset($newServerOptions->$optionName) && isset($oldServerOptions->$optionName)) {
|
||||
$newServerOptions->$optionName = $oldServerOptions->$optionName;
|
||||
}
|
||||
}
|
||||
return $newServerOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getMenu()
|
||||
*/
|
||||
public function getMenu($width, $height, Script $script, Player $player) {
|
||||
$paging = new Paging();
|
||||
$script->addFeature($paging);
|
||||
$frame = new Frame();
|
||||
|
||||
$serverOptions = $this->maniaControl->getClient()->getServerOptions();
|
||||
$serverOptionsArray = $serverOptions->toArray();
|
||||
|
||||
// Config
|
||||
$pagerSize = 9.;
|
||||
$optionHeight = 5.;
|
||||
$labelTextSize = 2;
|
||||
|
||||
// Pagers
|
||||
$pagerPrev = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerPrev);
|
||||
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
|
||||
|
||||
$pagerNext = new Quad_Icons64x64_1();
|
||||
$frame->add($pagerNext);
|
||||
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
|
||||
|
||||
$pageCountLabel = new Label_Text();
|
||||
$frame->add($pageCountLabel);
|
||||
$pageCountLabel->setHAlign($pageCountLabel::RIGHT)->setPosition($width * 0.35, $height * -0.44, 1)->setStyle($pageCountLabel::STYLE_TextTitle1)->setTextSize(2);
|
||||
|
||||
$paging->addButton($pagerNext)->addButton($pagerPrev)->setLabel($pageCountLabel);
|
||||
|
||||
// Pages
|
||||
$posY = 0.;
|
||||
$index = 0;
|
||||
$pageFrame = null;
|
||||
|
||||
foreach ($serverOptionsArray as $name => $value) {
|
||||
// Continue on CurrentMaxPlayers...
|
||||
$pos = strpos($name, 'Current'); // TODO: display 'Current...' somewhere
|
||||
if ($pos !== false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($index % 13 === 0) {
|
||||
$pageFrame = new Frame();
|
||||
$frame->add($pageFrame);
|
||||
$posY = $height * 0.41;
|
||||
$paging->addPage($pageFrame);
|
||||
}
|
||||
|
||||
$optionsFrame = new Frame();
|
||||
$pageFrame->add($optionsFrame);
|
||||
$optionsFrame->setY($posY);
|
||||
|
||||
$nameLabel = new Label_Text();
|
||||
$optionsFrame->add($nameLabel);
|
||||
$nameLabel->setHAlign($nameLabel::LEFT)->setX($width * -0.46)->setSize($width * 0.4, $optionHeight)->setStyle($nameLabel::STYLE_TextCardSmall)->setTextSize($labelTextSize)->setText($name)->setTextColor('fff');
|
||||
|
||||
if (is_bool($value)) {
|
||||
// Boolean checkbox
|
||||
$quad = new Quad();
|
||||
$quad->setPosition($width * 0.23, 0, -0.01)->setSize(4, 4);
|
||||
$checkBox = new CheckBox(self::ACTION_PREFIX_OPTION . $name, $value, $quad);
|
||||
$optionsFrame->add($checkBox);
|
||||
} else {
|
||||
// Other
|
||||
$entry = new Entry();
|
||||
$optionsFrame->add($entry);
|
||||
$entry->setStyle(Label_Text::STYLE_TextValueSmall)->setX($width * 0.23)->setTextSize(1)->setSize($width * 0.48, $optionHeight * 0.9)->setName(self::ACTION_PREFIX_OPTION . $name)->setDefault($value);
|
||||
|
||||
if ($name === 'Comment') {
|
||||
$entry->setSize($width * 0.48, $optionHeight * 3. + $optionHeight * 0.9)->setAutoNewLine(true);
|
||||
$optionsFrame->setY($posY - $optionHeight * 1.5);
|
||||
$posY -= $optionHeight * 3.;
|
||||
$index += 3;
|
||||
}
|
||||
}
|
||||
|
||||
$posY -= $optionHeight;
|
||||
$index++;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||
*/
|
||||
public function saveConfigData(array $configData, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_SERVER_OPTIONS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
if (!$configData[3] || strpos($configData[3][0]['Name'], self::ACTION_PREFIX_OPTION) !== 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$prefixLength = strlen(self::ACTION_PREFIX_OPTION);
|
||||
|
||||
$oldServerOptions = $this->maniaControl->getClient()->getServerOptions();
|
||||
$newServerOptions = new ServerOptions();
|
||||
|
||||
foreach ($configData[3] as $option) {
|
||||
$optionName = lcfirst(substr($option['Name'], $prefixLength));
|
||||
$newServerOptions->$optionName = $option['Value'];
|
||||
settype($newServerOptions->$optionName, gettype($oldServerOptions->$optionName));
|
||||
}
|
||||
|
||||
$this->fillUpMandatoryOptions($newServerOptions, $oldServerOptions);
|
||||
|
||||
$success = $this->applyNewServerOptions($newServerOptions, $player);
|
||||
if ($success) {
|
||||
$this->maniaControl->getChat()->sendSuccess('Server Options saved!', $player);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('Server Options saving failed!', $player);
|
||||
}
|
||||
|
||||
// Reopen the Menu
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the array of new Server Options
|
||||
*
|
||||
* @param ServerOptions $newServerOptions
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
private function applyNewServerOptions(ServerOptions $newServerOptions, Player $player) {
|
||||
try {
|
||||
$this->maniaControl->getClient()->setServerOptions($newServerOptions);
|
||||
} catch (ServerOptionsException $exception) {
|
||||
$this->maniaControl->getChat()->sendException($exception, $player);
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->saveServerOptions($newServerOptions, true);
|
||||
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SERVER_OPTIONS_CHANGED, array(self::CB_SERVER_OPTIONS_CHANGED));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
89
core/Server/UsageReporter.php
Normal file
89
core/Server/UsageReporter.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
|
||||
|
||||
/**
|
||||
* Class reporting ManiaControl Usage for the Server
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class UsageReporter implements TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const UPDATE_MINUTE_COUNT = 10;
|
||||
const SETTING_REPORT_USAGE = 'Report Usage to $lManiaControl.com$l';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new Usage Reporter Instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_REPORT_USAGE, true);
|
||||
|
||||
$this->maniaControl->getTimerManager()->registerTimerListening($this, 'reportUsage', 1000 * 60 * self::UPDATE_MINUTE_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Report Usage of ManiaControl on the current Server
|
||||
*/
|
||||
public function reportUsage() {
|
||||
if (DEV_MODE
|
||||
|| !$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_REPORT_USAGE)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$properties = array();
|
||||
$properties['ManiaControlVersion'] = ManiaControl::VERSION;
|
||||
$properties['OperatingSystem'] = php_uname();
|
||||
$properties['PHPVersion'] = phpversion();
|
||||
$properties['ServerLogin'] = $this->maniaControl->getServer()->login;
|
||||
$properties['TitleId'] = $this->maniaControl->getServer()->titleId;
|
||||
$properties['ServerName'] = Formatter::stripDirtyCodes($this->maniaControl->getClient()->getServerName());
|
||||
$properties['UpdateChannel'] = $this->maniaControl->getUpdateManager()->getCurrentUpdateChannelSetting();
|
||||
|
||||
$properties['PlayerCount'] = $this->maniaControl->getPlayerManager()->getPlayerCount();
|
||||
$properties['MemoryUsage'] = memory_get_usage();
|
||||
$properties['MemoryPeakUsage'] = memory_get_peak_usage();
|
||||
|
||||
$maxPlayers = $this->maniaControl->getClient()->getMaxPlayers();
|
||||
$properties['MaxPlayers'] = $maxPlayers['CurrentValue'];
|
||||
|
||||
try {
|
||||
$scriptName = $this->maniaControl->getClient()->getScriptName();
|
||||
$properties['ScriptName'] = $scriptName['CurrentValue'];
|
||||
} catch (GameModeException $e) {
|
||||
$properties['ScriptName'] = '';
|
||||
}
|
||||
|
||||
$properties['ActivePlugins'] = $this->maniaControl->getPluginManager()->getActivePluginsIds();
|
||||
|
||||
$usageReport = json_encode($properties);
|
||||
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'usagereport';
|
||||
$this->maniaControl->getFileReader()->postData($url, function ($response, $error) {
|
||||
$response = json_decode($response);
|
||||
if ($error || !$response) {
|
||||
Logger::logError('Error while Sending data: ' . print_r($error, true));
|
||||
}
|
||||
}, $usageReport);
|
||||
}
|
||||
}
|
177
core/Server/VoteRatiosMenu.php
Normal file
177
core/Server/VoteRatiosMenu.php
Normal file
@ -0,0 +1,177 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Server;
|
||||
|
||||
use FML\Controls\Entry;
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Script\Script;
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Configurator\ConfiguratorMenu;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use Maniaplanet\DedicatedServer\Structures\VoteRatio;
|
||||
|
||||
/**
|
||||
* Class offering a Configurator Menu for Vote Ratios
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class VoteRatiosMenu implements CallbackListener, ConfiguratorMenu, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const SETTING_PERMISSION_CHANGE_VOTE_RATIOS = 'Change Vote Ratios';
|
||||
const ACTION_PREFIX_VOTE_RATIO = 'VoteRatiosMenu.VoteRatio.';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Construct a new vote ratios menu instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CHANGE_VOTE_RATIOS, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getTitle()
|
||||
*/
|
||||
public static function getTitle() {
|
||||
return 'Vote Ratios';
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::getMenu()
|
||||
*/
|
||||
public function getMenu($width, $height, Script $script, Player $player) {
|
||||
$frame = new Frame();
|
||||
$posY = $height * 0.41;
|
||||
$lineHeight = 5.;
|
||||
$index = 0;
|
||||
|
||||
$voteRatioCommands = $this->getVoteCommands();
|
||||
$voteRatios = $this->maniaControl->getClient()->getCallVoteRatios();
|
||||
foreach ($voteRatioCommands as $voteRatioCommand => $voteRatioDescription) {
|
||||
$voteRatioFrame = new Frame();
|
||||
$frame->add($voteRatioFrame);
|
||||
$voteRatioFrame->setY($posY);
|
||||
|
||||
$nameLabel = new Label_Text();
|
||||
$voteRatioFrame->add($nameLabel);
|
||||
$nameLabel->setHAlign($nameLabel::LEFT)->setX($width * -0.46)->setSize($width * 0.7, $lineHeight)->setTextSize(2)->setTranslate(true)->setText($voteRatioDescription);
|
||||
|
||||
$entry = new Entry();
|
||||
$voteRatioFrame->add($entry);
|
||||
$entry->setX($width * 0.35)->setSize($width * 0.14, $lineHeight * 0.9)->setStyle(Label_Text::STYLE_TextValueSmall)->setTextSize($index === 0 ? 2 : 1)->setName(self::ACTION_PREFIX_VOTE_RATIO . $voteRatioCommand);
|
||||
|
||||
$voteRatio = $this->getVoteRatioForCommand($voteRatios, $voteRatioCommand);
|
||||
if ($voteRatio) {
|
||||
$entry->setDefault($voteRatio->ratio);
|
||||
}
|
||||
|
||||
$posY -= $lineHeight;
|
||||
if ($index === 0) {
|
||||
$posY -= $lineHeight;
|
||||
}
|
||||
$index++;
|
||||
}
|
||||
|
||||
return $frame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of available vote commands
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
private function getVoteCommands() {
|
||||
return array(VoteRatio::COMMAND_DEFAULT => 'Default', VoteRatio::COMMAND_RESTART_MAP => 'Restart Map', VoteRatio::COMMAND_NEXT_MAP => 'Skip Map', VoteRatio::COMMAND_SET_NEXT_MAP => 'Set next Map', VoteRatio::COMMAND_JUMP_MAP => 'Jump to Map', VoteRatio::COMMAND_TEAM_BALANCE => 'Balance Teams', VoteRatio::COMMAND_SCRIPT_SETTINGS => 'Change Script Settings and Commands', VoteRatio::COMMAND_KICK => 'Kick Players', VoteRatio::COMMAND_BAN => 'Ban Players');
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the vote ratio for the given command
|
||||
*
|
||||
* @param VoteRatio[] $voteRatios
|
||||
* @param string $command
|
||||
* @return VoteRatio
|
||||
*/
|
||||
private function getVoteRatioForCommand(array $voteRatios, $command) {
|
||||
foreach ($voteRatios as $voteRatio) {
|
||||
if ($voteRatio->command === $command) {
|
||||
return $voteRatio;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \ManiaControl\Configurators\ConfiguratorMenu::saveConfigData()
|
||||
*/
|
||||
public function saveConfigData(array $configData, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CHANGE_VOTE_RATIOS)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
if (!$configData[3] || strpos($configData[3][0]['Name'], self::ACTION_PREFIX_VOTE_RATIO) !== 0) {
|
||||
return;
|
||||
}
|
||||
$prefixLength = strlen(self::ACTION_PREFIX_VOTE_RATIO);
|
||||
|
||||
$newVoteRatios = array();
|
||||
foreach ($configData[3] as $voteRatioEntry) {
|
||||
$voteRatioName = substr($voteRatioEntry['Name'], $prefixLength);
|
||||
$voteRatioValue = $voteRatioEntry['Value'];
|
||||
if ($voteRatioValue === '') {
|
||||
continue;
|
||||
}
|
||||
if (!is_numeric($voteRatioValue)) {
|
||||
$this->sendInvalidValueError($player, $voteRatioName);
|
||||
continue;
|
||||
}
|
||||
|
||||
$voteRatio = new VoteRatio();
|
||||
$voteRatio->command = $voteRatioName;
|
||||
$voteRatio->ratio = (float)$voteRatioValue;
|
||||
|
||||
if (!$voteRatio->isValid()) {
|
||||
$this->sendInvalidValueError($player, $voteRatioName);
|
||||
continue;
|
||||
}
|
||||
array_push($newVoteRatios, $voteRatio);
|
||||
}
|
||||
|
||||
$success = $this->maniaControl->getClient()->setCallVoteRatios($newVoteRatios);
|
||||
if ($success) {
|
||||
$this->maniaControl->getChat()->sendSuccess('Vote Ratios saved!', $player);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendError('Vote Ratios saving failed!', $player);
|
||||
}
|
||||
|
||||
// Reopen the Menu
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inform the player that his entered value is invalid
|
||||
*
|
||||
* @param Player $player
|
||||
* @param string $commandName
|
||||
*/
|
||||
private function sendInvalidValueError(Player $player, $commandName) {
|
||||
$this->maniaControl->getChat()->sendError("Invalid Value given for '{$commandName}'!", $player);
|
||||
}
|
||||
}
|
195
core/Settings/Setting.php
Normal file
195
core/Settings/Setting.php
Normal file
@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Settings;
|
||||
|
||||
use ManiaControl\Utils\ClassUtil;
|
||||
|
||||
/**
|
||||
* ManiaControl Setting Model Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class Setting {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CLASS_NAME = __CLASS__;
|
||||
const TYPE_STRING = 'string';
|
||||
const TYPE_INT = 'int';
|
||||
const TYPE_REAL = 'real';
|
||||
const TYPE_BOOL = 'bool';
|
||||
const TYPE_SET = 'set';
|
||||
const VALUE_DELIMITER = ';;';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $index = null;
|
||||
public $class = null;
|
||||
public $setting = null;
|
||||
public $type = null;
|
||||
public $value = null;
|
||||
public $default = null;
|
||||
public $set = null;
|
||||
public $fetchTime = null;
|
||||
|
||||
/**
|
||||
* Construct a new setting instance
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $settingName
|
||||
* @param mixed $defaultValue
|
||||
*/
|
||||
public function __construct($object, $settingName, $defaultValue) {
|
||||
if ($object === false) {
|
||||
// Fetched from Database
|
||||
$this->value = $this->castValue($this->value);
|
||||
$this->default = $this->castValue($this->default);
|
||||
if ($this->set) {
|
||||
$this->set = $this->castValue($this->set, $this->type);
|
||||
}
|
||||
$this->fetchTime = time();
|
||||
} else {
|
||||
// Created by Values
|
||||
$this->class = ClassUtil::getClass($object);
|
||||
$this->setting = (string)$settingName;
|
||||
$this->type = self::getValueType($defaultValue);
|
||||
if ($this->type === self::TYPE_SET) {
|
||||
// Save Set and use first Value as Default
|
||||
$this->set = $defaultValue;
|
||||
$this->value = reset($defaultValue);
|
||||
} else {
|
||||
$this->value = $defaultValue;
|
||||
}
|
||||
$this->default = $this->value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast the Value based on the Setting Type
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string $type
|
||||
* @return mixed
|
||||
*/
|
||||
private static function castValue($value, $type = null) {
|
||||
if ($type === null) {
|
||||
$type = self::getValueType($value);
|
||||
}
|
||||
if ($type === self::TYPE_INT) {
|
||||
return (int)$value;
|
||||
}
|
||||
if ($type === self::TYPE_REAL) {
|
||||
return (float)$value;
|
||||
}
|
||||
if ($type === self::TYPE_BOOL) {
|
||||
return (bool)$value;
|
||||
}
|
||||
if ($type === self::TYPE_STRING) {
|
||||
return (string)$value;
|
||||
}
|
||||
if ($type === self::TYPE_SET) {
|
||||
return explode(self::VALUE_DELIMITER, $value);
|
||||
}
|
||||
trigger_error("Unsupported Setting Value Type: '" . print_r($type, true) . "'!");
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Type of a Value Parameter
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return string
|
||||
*/
|
||||
private static function getValueType($value) {
|
||||
if (is_int($value)) {
|
||||
return self::TYPE_INT;
|
||||
}
|
||||
if (is_real($value)) {
|
||||
return self::TYPE_REAL;
|
||||
}
|
||||
if (is_bool($value)) {
|
||||
return self::TYPE_BOOL;
|
||||
}
|
||||
if (is_string($value)) {
|
||||
return self::TYPE_STRING;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
return self::TYPE_SET;
|
||||
}
|
||||
trigger_error("Unsupported Setting Value Type: '" . print_r($value, true) . "'!");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether the Setting has been persisted at some point
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPersisted() {
|
||||
return ($this->index > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Formatted Value of the Setting
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedValue() {
|
||||
return self::formatValue($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given Value based on the Type
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string $type
|
||||
* @return string
|
||||
*/
|
||||
private static function formatValue($value, $type = null) {
|
||||
if ($type === null) {
|
||||
$type = self::getValueType($value);
|
||||
}
|
||||
if ($type === self::TYPE_BOOL) {
|
||||
return ($value ? 1 : 0);
|
||||
}
|
||||
if ($type === self::TYPE_SET) {
|
||||
return implode(self::VALUE_DELIMITER, $value);
|
||||
}
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Formatted Default of the Setting
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedDefault() {
|
||||
return self::formatValue($this->default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Formatted Set of the Setting
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFormattedSet() {
|
||||
if ($this->type === self::TYPE_SET) {
|
||||
return self::formatValue($this->set);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Settings belongs to the given Class
|
||||
*
|
||||
* @param mixed $object
|
||||
* @return bool
|
||||
*/
|
||||
public function belongsToClass($object) {
|
||||
$className = ClassUtil::getClass($object);
|
||||
return ($className === $this->class);
|
||||
}
|
||||
}
|
488
core/Settings/SettingManager.php
Normal file
488
core/Settings/SettingManager.php
Normal file
@ -0,0 +1,488 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Settings;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Plugins\PluginManager;
|
||||
use ManiaControl\Utils\ClassUtil;
|
||||
|
||||
/**
|
||||
* Class managing ManiaControl Settings and Configurations
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class SettingManager implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TABLE_SETTINGS = 'mc_settings';
|
||||
const CB_SETTING_CHANGED = 'SettingManager.SettingChanged';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
/** @var Setting[] $storedSettings */
|
||||
private $storedSettings = array();
|
||||
|
||||
/**
|
||||
* Construct a new setting manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the necessary database tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$settingTableQuery = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_SETTINGS . "` (
|
||||
`index` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`class` VARCHAR(100) NOT NULL,
|
||||
`setting` VARCHAR(150) NOT NULL,
|
||||
`type` VARCHAR(50) NOT NULL,
|
||||
`value` VARCHAR(100) NOT NULL,
|
||||
`default` VARCHAR(100) NOT NULL,
|
||||
`set` VARCHAR(100) NOT NULL,
|
||||
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `settingId` (`class`,`setting`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Settings and Configurations' AUTO_INCREMENT=1;";
|
||||
$result = $mysqli->query($settingTableQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle After Init Callback
|
||||
*/
|
||||
public function handleAfterInit() {
|
||||
$this->deleteUnusedSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all unused Settings that haven't been initialized during the current Startup
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function deleteUnusedSettings() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$settingQuery = "DELETE FROM `" . self::TABLE_SETTINGS . "`
|
||||
WHERE `changed` < NOW() - INTERVAL 1 HOUR;";
|
||||
$result = $mysqli->query($settingQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
if ($result) {
|
||||
$this->clearStorage();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the Settings Storage
|
||||
*/
|
||||
public function clearStorage() {
|
||||
$this->storedSettings = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see SettingManager::getSettingValueByIndex()
|
||||
*/
|
||||
public function getSettingByIndex($settingIndex, $defaultValue = null) {
|
||||
return $this->getSettingValueByIndex($settingIndex, $defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Setting Value by its Index
|
||||
*
|
||||
* @param int $settingIndex
|
||||
* @param mixed $defaultValue
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSettingValueByIndex($settingIndex, $defaultValue = null) {
|
||||
$setting = $this->getSettingObjectByIndex($settingIndex);
|
||||
if (!$setting) {
|
||||
return $defaultValue;
|
||||
}
|
||||
return $setting->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Setting Object by its Index
|
||||
*
|
||||
* @param int $settingIndex
|
||||
* @return Setting
|
||||
*/
|
||||
public function getSettingObjectByIndex($settingIndex) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$settingQuery = "SELECT * FROM `" . self::TABLE_SETTINGS . "`
|
||||
WHERE `index` = {$settingIndex};";
|
||||
$result = $mysqli->query($settingQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
if ($result->num_rows <= 0) {
|
||||
$result->free();
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var Setting $setting */
|
||||
$setting = $result->fetch_object(Setting::CLASS_NAME, array(false, null, null));
|
||||
$result->free();
|
||||
|
||||
$this->storeSetting($setting);
|
||||
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store the given Setting
|
||||
*
|
||||
* @param Setting $setting
|
||||
*/
|
||||
private function storeSetting(Setting $setting) {
|
||||
$this->storedSettings[$setting->class . $setting->setting] = $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a Setting for the given Object
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $settingName
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public function setSetting($object, $settingName, $value) {
|
||||
//TODO nowhere used, everywhere saveSettings used, is it depreciated?
|
||||
$setting = $this->getSettingObject($object, $settingName);
|
||||
if ($setting) {
|
||||
$setting->value = $value;
|
||||
$saved = $this->saveSetting($setting);
|
||||
if (!$saved) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$saved = $this->initSetting($object, $settingName, $value);
|
||||
if (!$saved) {
|
||||
return false;
|
||||
}
|
||||
$setting = $this->getSettingObject($object, $settingName, $value);
|
||||
}
|
||||
|
||||
$this->storeSetting($setting);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Setting by Name for the given Object
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $settingName
|
||||
* @param mixed $default
|
||||
* @return Setting
|
||||
*/
|
||||
public function getSettingObject($object, $settingName, $default = null) {
|
||||
$settingClass = ClassUtil::getClass($object);
|
||||
|
||||
// Retrieve from Storage if possible
|
||||
$storedSetting = $this->getStoredSetting($object, $settingName);
|
||||
if ($storedSetting) {
|
||||
return $storedSetting;
|
||||
}
|
||||
|
||||
// Fetch setting
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$settingQuery = "SELECT * FROM `" . self::TABLE_SETTINGS . "`
|
||||
WHERE `class` = '" . $mysqli->escape_string($settingClass) . "'
|
||||
AND `setting` = '" . $mysqli->escape_string($settingName) . "';";
|
||||
$result = $mysqli->query($settingQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
if ($result->num_rows <= 0) {
|
||||
$result->free();
|
||||
if ($default === null) {
|
||||
return null;
|
||||
}
|
||||
$saved = $this->initSetting($object, $settingName, $default);
|
||||
if ($saved) {
|
||||
return $this->getSettingObject($object, $settingName, $default);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/** @var Setting $setting */
|
||||
$setting = $result->fetch_object(Setting::CLASS_NAME, array(false, null, null));
|
||||
$result->free();
|
||||
|
||||
$this->storeSetting($setting);
|
||||
|
||||
return $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a stored Setting
|
||||
*
|
||||
* @param mixed $settingClass
|
||||
* @param string $settingName
|
||||
* @return Setting
|
||||
*/
|
||||
private function getStoredSetting($settingClass, $settingName) {
|
||||
$settingClass = ClassUtil::getClass($settingClass);
|
||||
if (isset($this->storedSettings[$settingClass . $settingName])) {
|
||||
return $this->storedSettings[$settingClass . $settingName];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a Setting for the given Object
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $settingName
|
||||
* @param mixed $defaultValue
|
||||
* @return bool
|
||||
*/
|
||||
public function initSetting($object, $settingName, $defaultValue) {
|
||||
$setting = new Setting($object, $settingName, $defaultValue);
|
||||
return $this->saveSetting($setting, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the given Setting in the Database
|
||||
*
|
||||
* @param Setting $setting
|
||||
* @param bool $init
|
||||
* @return bool
|
||||
*/
|
||||
public function saveSetting(Setting $setting, $init = false) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
if ($init) {
|
||||
// Init - Keep old value if the default didn't change
|
||||
$valueUpdateString = '`value` = IF(`default` = VALUES(`default`), `value`, VALUES(`default`))';
|
||||
} else {
|
||||
// Set - Update value in any case
|
||||
$valueUpdateString = '`value` = VALUES(`value`)';
|
||||
}
|
||||
$settingQuery = "INSERT INTO `" . self::TABLE_SETTINGS . "` (
|
||||
`class`,
|
||||
`setting`,
|
||||
`type`,
|
||||
`value`,
|
||||
`default`,
|
||||
`set`
|
||||
) VALUES (
|
||||
?, ?, ?, ?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`index` = LAST_INSERT_ID(`index`),
|
||||
`type` = VALUES(`type`),
|
||||
{$valueUpdateString},
|
||||
`default` = VALUES(`default`),
|
||||
`set` = VALUES(`set`),
|
||||
`changed` = NOW();";
|
||||
$settingStatement = $mysqli->prepare($settingQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$formattedValue = $setting->getFormattedValue();
|
||||
$formattedDefault = $setting->getFormattedDefault();
|
||||
$formattedSet = $setting->getFormattedSet();
|
||||
$settingStatement->bind_param('ssssss', $setting->class, $setting->setting, $setting->type, $formattedValue, $formattedDefault, $formattedSet);
|
||||
$settingStatement->execute();
|
||||
if ($settingStatement->error) {
|
||||
trigger_error($settingStatement->error);
|
||||
$settingStatement->close();
|
||||
return false;
|
||||
}
|
||||
$settingStatement->close();
|
||||
|
||||
// Trigger Settings Changed Callback
|
||||
if (!$init) {
|
||||
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SETTING_CHANGED, $setting);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see SettingManager::getSettingValue()
|
||||
*/
|
||||
public function getSetting($object, $settingName, $default = null) {
|
||||
return $this->getSettingValue($object, $settingName, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Setting Value directly
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $settingName
|
||||
* @param mixed $default
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSettingValue($object, $settingName, $default = null) {
|
||||
$setting = $this->getSettingObject($object, $settingName, $default);
|
||||
if ($setting) {
|
||||
return $setting->value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset a Setting to its Default Value
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $settingName
|
||||
* @return bool
|
||||
*/
|
||||
public function resetSetting($object, $settingName = null) {
|
||||
if ($object instanceof Setting) {
|
||||
$className = $object->class;
|
||||
$settingName = $object->setting;
|
||||
} else {
|
||||
$className = ClassUtil::getClass($object);
|
||||
}
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$settingQuery = "UPDATE `" . self::TABLE_SETTINGS . "`
|
||||
SET `value` = `default`
|
||||
WHERE `class` = '" . $mysqli->escape_string($className) . "'
|
||||
AND `setting` = '" . $mysqli->escape_string($settingName) . "';";
|
||||
$result = $mysqli->query($settingQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
if (isset($this->storedSettings[$className . $settingName])) {
|
||||
unset($this->storedSettings[$className . $settingName]);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a Setting
|
||||
*
|
||||
* @param mixed $object
|
||||
* @param string $settingName
|
||||
* @return bool
|
||||
*/
|
||||
public function deleteSetting($object, $settingName = null) {
|
||||
if ($object instanceof Setting) {
|
||||
$className = $object->class;
|
||||
$settingName = $object->setting;
|
||||
} else {
|
||||
$className = ClassUtil::getClass($object);
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$settingQuery = "DELETE FROM `" . self::TABLE_SETTINGS . "`
|
||||
WHERE `class` = '" . $mysqli->escape_string($className) . "'
|
||||
AND `setting` = '" . $mysqli->escape_string($settingName) . "';";
|
||||
$result = $mysqli->query($settingQuery);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($this->storedSettings[$className . $settingName])) {
|
||||
unset($this->storedSettings[$className . $settingName]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Settings for the given Class
|
||||
*
|
||||
* @param mixed $object
|
||||
* @return Setting[]
|
||||
*/
|
||||
public function getSettingsByClass($object) {
|
||||
$className = ClassUtil::getClass($object);
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "SELECT * FROM `" . self::TABLE_SETTINGS . "`
|
||||
WHERE `class` = '" . $mysqli->escape_string($className) . "'
|
||||
ORDER BY `setting` ASC;";
|
||||
$result = $mysqli->query($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
$settings = array();
|
||||
while ($setting = $result->fetch_object(Setting::CLASS_NAME, array(false, null, null))) {
|
||||
$settings[$setting->index] = $setting;
|
||||
}
|
||||
$result->free();
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Settings
|
||||
*
|
||||
* @return Setting[]
|
||||
*/
|
||||
public function getSettings() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "SELECT * FROM `" . self::TABLE_SETTINGS . "`
|
||||
ORDER BY `class` ASC, `setting` ASC;";
|
||||
$result = $mysqli->query($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
$settings = array();
|
||||
while ($setting = $result->fetch_object(Setting::CLASS_NAME, array(false, null, null))) {
|
||||
$settings[$setting->index] = $setting;
|
||||
}
|
||||
$result->free();
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all Setting Classes
|
||||
*
|
||||
* @param bool $hidePluginClasses
|
||||
* @return string[]
|
||||
*/
|
||||
public function getSettingClasses($hidePluginClasses = false) {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "SELECT DISTINCT `class` FROM `" . self::TABLE_SETTINGS . "`
|
||||
ORDER BY `class` ASC;";
|
||||
$result = $mysqli->query($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
$settingClasses = array();
|
||||
while ($row = $result->fetch_object()) {
|
||||
if (!$hidePluginClasses || !PluginManager::isPluginClass($row->class)) {
|
||||
array_push($settingClasses, $row->class);
|
||||
}
|
||||
}
|
||||
$result->free();
|
||||
return $settingClasses;
|
||||
}
|
||||
}
|
307
core/Statistics/SimpleStatsList.php
Normal file
307
core/Statistics/SimpleStatsList.php
Normal file
@ -0,0 +1,307 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Statistics;
|
||||
|
||||
use FML\Controls\Frame;
|
||||
use FML\Controls\Label;
|
||||
use FML\Controls\Labels\Label_Text;
|
||||
use FML\Controls\Quad;
|
||||
use FML\Controls\Quads\Quad_BgsPlayerCard;
|
||||
use FML\Controls\Quads\Quad_Icons64x64_1;
|
||||
use FML\Controls\Quads\Quad_UIConstruction_Buttons;
|
||||
use FML\ManiaLink;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Manialinks\ManialinkManager;
|
||||
use ManiaControl\Manialinks\ManialinkPageAnswerListener;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
use ManiaControl\Utils\Formatter;
|
||||
|
||||
/**
|
||||
* Simple Stats List Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class SimpleStatsList implements ManialinkPageAnswerListener, CallbackListener, CommandListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const ACTION_OPEN_STATSLIST = 'SimpleStatsList.OpenStatsList';
|
||||
const ACTION_SORT_STATS = 'SimpleStatsList.SortStats';
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $statArray = array();
|
||||
private $statsWidth = 0;
|
||||
|
||||
/**
|
||||
* Construct a new simple stats list instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the menu entry
|
||||
*/
|
||||
public function handleOnInit() {
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('stats', $this, 'command_ShowStatsList', false, 'Shows statistics.');
|
||||
|
||||
// Action Open StatsList
|
||||
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_OPEN_STATSLIST, $this, 'command_ShowStatsList');
|
||||
|
||||
$itemQuad = new Quad_UIConstruction_Buttons();
|
||||
$itemQuad->setSubStyle($itemQuad::SUBSTYLE_Stats);
|
||||
$itemQuad->setAction(self::ACTION_OPEN_STATSLIST);
|
||||
$this->maniaControl->getActionsMenu()->addMenuItem($itemQuad, true, 14, 'Open Statistics');
|
||||
|
||||
//TODO settings if a stat get shown
|
||||
$this->registerStat(PlayerManager::STAT_SERVERTIME, 10, "ST", 20, StatisticManager::STAT_TYPE_TIME);
|
||||
$this->registerStat(StatisticCollector::STAT_ON_HIT, 20, "H");
|
||||
$this->registerStat(StatisticCollector::STAT_ON_NEARMISS, 30, "NM");
|
||||
$this->registerStat(StatisticCollector::STAT_ON_KILL, 40, "K");
|
||||
$this->registerStat(StatisticCollector::STAT_ON_DEATH, 50, "D");
|
||||
$this->registerStat(StatisticCollector::STAT_ON_CAPTURE, 60, "C");
|
||||
|
||||
$this->registerStat(StatisticManager::SPECIAL_STAT_KD_RATIO, 70, "K/D", 12, StatisticManager::STAT_TYPE_FLOAT);
|
||||
$this->registerStat(StatisticManager::SPECIAL_STAT_LASER_ACC, 80, "LAcc", 15, StatisticManager::STAT_TYPE_FLOAT);
|
||||
$this->registerStat(StatisticManager::SPECIAL_STAT_HITS_PH, 85, "H/h", 15, StatisticManager::STAT_TYPE_FLOAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a Certain Stat
|
||||
*
|
||||
* @param string $statName
|
||||
* @param int $order
|
||||
* @param string $headShortCut
|
||||
* @param int $width
|
||||
* @param string $format
|
||||
*/
|
||||
public function registerStat($statName, $order, $headShortCut, $width = 10, $format = StatisticManager::STAT_TYPE_INT) {
|
||||
// TODO: use own model class
|
||||
$this->statArray[$order] = array();
|
||||
$this->statArray[$order]["Name"] = $statName;
|
||||
$this->statArray[$order]["HeadShortCut"] = '$o' . $headShortCut;
|
||||
$this->statArray[$order]["Width"] = $width;
|
||||
$this->statArray[$order]["Format"] = $format;
|
||||
$this->statsWidth += $width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the stat List
|
||||
*
|
||||
* @param array $callback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function command_ShowStatsList(array $callback, Player $player) {
|
||||
$this->showStatsList($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the StatsList Widget to the Player
|
||||
*
|
||||
* @param Player $player
|
||||
* @param string $order
|
||||
*/
|
||||
public function showStatsList(Player $player, $order = PlayerManager::STAT_SERVERTIME) {
|
||||
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
|
||||
$quadStyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowStyle();
|
||||
$quadSubstyle = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultMainWindowSubStyle();
|
||||
|
||||
|
||||
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
|
||||
$width = $this->statsWidth + 60;
|
||||
//TODO handle size when stats are empty
|
||||
|
||||
// Main frame
|
||||
$frame = new Frame();
|
||||
$maniaLink->add($frame);
|
||||
$frame->setSize($width, $height);
|
||||
$frame->setPosition(0, 0, 10);
|
||||
|
||||
// Background
|
||||
$backgroundQuad = new Quad();
|
||||
$frame->add($backgroundQuad);
|
||||
$backgroundQuad->setSize($width, $height);
|
||||
$backgroundQuad->setStyles($quadStyle, $quadSubstyle);
|
||||
|
||||
// Close Quad (X)
|
||||
$closeQuad = new Quad_Icons64x64_1();
|
||||
$frame->add($closeQuad);
|
||||
$closeQuad->setPosition($width * 0.483, $height * 0.467, 3);
|
||||
$closeQuad->setSize(6, 6);
|
||||
$closeQuad->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_QuitRace);
|
||||
$closeQuad->setAction(ManialinkManager::ACTION_CLOSEWIDGET);
|
||||
|
||||
// Start offsets
|
||||
$xStart = -$width / 2;
|
||||
$posY = $height / 2;
|
||||
|
||||
// Predefine Description Label
|
||||
$descriptionLabel = new Label();
|
||||
$frame->add($descriptionLabel);
|
||||
$descriptionLabel->setAlign($descriptionLabel::LEFT, $descriptionLabel::TOP);
|
||||
$descriptionLabel->setPosition($xStart + 10, -$height / 2 + 5);
|
||||
$descriptionLabel->setSize($width * 0.7, 4);
|
||||
$descriptionLabel->setTextSize(2);
|
||||
$descriptionLabel->setVisible(false);
|
||||
|
||||
// Headline
|
||||
$headFrame = new Frame();
|
||||
$frame->add($headFrame);
|
||||
$headFrame->setY($posY - 5);
|
||||
|
||||
$posX = $xStart;
|
||||
$array['$oId'] = $posX + 5;
|
||||
$array['$oNickname'] = $posX + 14;
|
||||
|
||||
// Headline
|
||||
$posX = $xStart + 55;
|
||||
$statRankings = array();
|
||||
foreach ($this->statArray as $key => $stat) {
|
||||
$ranking = $this->maniaControl->getStatisticManager()->getStatsRanking($stat["Name"]);
|
||||
if (!empty($ranking)) {
|
||||
$statRankings[$stat["Name"]] = $ranking;
|
||||
$array[$stat['HeadShortCut']] = $posX;
|
||||
$posX += $stat["Width"];
|
||||
} else {
|
||||
unset($this->statArray[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$labels = $this->maniaControl->getManialinkManager()->labelLine($headFrame, $array);
|
||||
|
||||
// Description Label
|
||||
$index = 2;
|
||||
foreach ($this->statArray as $statArray) {
|
||||
if (!isset($labels[$index])) {
|
||||
break;
|
||||
}
|
||||
|
||||
/** @var Label_Text $label */
|
||||
$label = $labels[$index];
|
||||
|
||||
$label->setAction(self::ACTION_SORT_STATS . '.' . $statArray["Name"]);
|
||||
$label->addTooltipLabelFeature($descriptionLabel, '$o ' . $statArray["Name"]);
|
||||
$index++;
|
||||
}
|
||||
|
||||
// define standard properties
|
||||
$textSize = 1.5;
|
||||
$textColor = 'fff';
|
||||
$index = 1;
|
||||
$posY -= 10;
|
||||
|
||||
if (!isset($statRankings[$order])) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($statRankings[$order] as $playerId => $value) {
|
||||
$listPlayer = $this->maniaControl->getPlayerManager()->getPlayerByIndex($playerId);
|
||||
if (!$listPlayer) {
|
||||
continue;
|
||||
}
|
||||
if ($index === 15) {
|
||||
break;
|
||||
}
|
||||
|
||||
$playerFrame = new Frame();
|
||||
$frame->add($playerFrame);
|
||||
|
||||
// Show current Player Arrow
|
||||
if ($playerId == $player->index) {
|
||||
$currentQuad = new Quad_Icons64x64_1();
|
||||
$playerFrame->add($currentQuad);
|
||||
$currentQuad->setX($xStart + 3.5);
|
||||
$currentQuad->setZ(0.2);
|
||||
$currentQuad->setSize(4, 4);
|
||||
$currentQuad->setSubStyle($currentQuad::SUBSTYLE_ArrowBlue);
|
||||
}
|
||||
|
||||
$displayArray = array();
|
||||
|
||||
foreach ($this->statArray as $stat) {
|
||||
$statValue = 0;
|
||||
if (isset($statRankings[$stat['Name']][$playerId])) {
|
||||
$statValue = $statRankings[$stat['Name']][$playerId];
|
||||
if ($stat['Format'] == StatisticManager::STAT_TYPE_TIME) {
|
||||
$statValue = Formatter::formatTimeH($statValue);
|
||||
} else if ($stat['Format'] == StatisticManager::STAT_TYPE_FLOAT) {
|
||||
$statValue = round(floatval($statValue), 2);
|
||||
}
|
||||
}
|
||||
$displayArray[$stat['Name']] = array('Value' => strval($statValue), 'Width' => $stat['Width']);
|
||||
}
|
||||
|
||||
$array = array($index => $xStart + 5, $listPlayer->nickname => $xStart + 14);
|
||||
$this->maniaControl->getManialinkManager()->labelLine($playerFrame, $array);
|
||||
|
||||
$posX = $xStart + 55;
|
||||
foreach ($displayArray as $key => $array) {
|
||||
$label = new Label_Text();
|
||||
$playerFrame->add($label);
|
||||
$label->setHAlign($label::LEFT);
|
||||
$label->setX($posX);
|
||||
$label->setStyle($label::STYLE_TextCardSmall);
|
||||
$label->setTextSize($textSize);
|
||||
$label->setText($array['Value']);
|
||||
$label->setTextColor($textColor);
|
||||
$label->addTooltipLabelFeature($descriptionLabel, '$o ' . $key);
|
||||
$posX += $array['Width'];
|
||||
}
|
||||
|
||||
$playerFrame->setY($posY);
|
||||
|
||||
if ($index % 2 !== 0) {
|
||||
$lineQuad = new Quad_BgsPlayerCard();
|
||||
$playerFrame->add($lineQuad);
|
||||
$lineQuad->setSize($width, 4);
|
||||
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
|
||||
$lineQuad->setZ(0.001);
|
||||
}
|
||||
|
||||
$index++;
|
||||
$posY -= 4;
|
||||
}
|
||||
|
||||
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'SimpleStatsList');
|
||||
}
|
||||
|
||||
/**
|
||||
* Called on ManialinkPageAnswer
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$actionArray = explode('.', $actionId, 3);
|
||||
if (count($actionArray) <= 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$action = $actionArray[0] . '.' . $actionArray[1];
|
||||
|
||||
switch ($action) {
|
||||
case self::ACTION_SORT_STATS:
|
||||
$playerLogin = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($playerLogin);
|
||||
$this->showStatsList($player, $actionArray[2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
371
core/Statistics/StatisticCollector.php
Normal file
371
core/Statistics/StatisticCollector.php
Normal file
@ -0,0 +1,371 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Statistics;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\Callbacks;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
|
||||
/**
|
||||
* Statistic Collector Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class StatisticCollector implements CallbackListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const SETTING_COLLECT_STATS_ENABLED = 'Collect Stats Enabled';
|
||||
const SETTING_COLLECT_STATS_MINPLAYERS = 'Minimum Player Count for Collecting Stats';
|
||||
const SETTING_ON_SHOOT_PRESTORE = 'Prestore Shots before Insert into Database';
|
||||
/*
|
||||
* Statistics
|
||||
*/
|
||||
const STAT_PLAYTIME = 'Play Time';
|
||||
const STAT_MAP_WINS = 'Map Wins';
|
||||
const STAT_ON_SHOOT = 'Shots';
|
||||
const STAT_ON_NEARMISS = 'Near Misses';
|
||||
const STAT_ON_CAPTURE = 'Captures';
|
||||
const STAT_ON_HIT = 'Hits';
|
||||
const STAT_ON_GOT_HIT = 'Got Hits';
|
||||
const STAT_ON_DEATH = 'Deaths';
|
||||
const STAT_ON_PLAYER_REQUEST_RESPAWN = 'Respawns';
|
||||
const STAT_ON_KILL = 'Kills';
|
||||
const STAT_LASER_SHOT = 'Laser Shots';
|
||||
const STAT_LASER_HIT = 'Laser Hits';
|
||||
const STAT_ROCKET_SHOT = 'Rocket Shots';
|
||||
const STAT_ROCKET_HIT = 'Rocket Hits';
|
||||
const STAT_ARROW_SHOT = 'Arrow Shots';
|
||||
const STAT_ARROW_HIT = 'Arrow Hits';
|
||||
const STAT_NUCLEUS_SHOT = 'Nucleus Shots';
|
||||
const STAT_NUCLEUS_HIT = 'Nucleus Hits';
|
||||
|
||||
const SPECIAL_STAT_KILL_DEATH_RATIO = 'Kill / Death';
|
||||
|
||||
const WEAPON_LASER = 1;
|
||||
const WEAPON_ROCKET = 2;
|
||||
const WEAPON_NUCLEUS = 3;
|
||||
const WEAPON_ARROW = 5;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $onShootArray = array();
|
||||
|
||||
/**
|
||||
* Construct a new statistic collector instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_MODESCRIPTCALLBACK, $this, 'handleCallbacks');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_MODESCRIPTCALLBACKARRAY, $this, 'handleCallbacks');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'onInit');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERDISCONNECT, $this, 'onPlayerDisconnect');
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_COLLECT_STATS_ENABLED, true);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_COLLECT_STATS_MINPLAYERS, 4);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_ON_SHOOT_PRESTORE, 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManiaControl OnInit Callback
|
||||
*/
|
||||
public function onInit() {
|
||||
// Define Stats MetaData
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_PLAYTIME, StatisticManager::STAT_TYPE_TIME);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_MAP_WINS);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_SHOOT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_NEARMISS);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_CAPTURE);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_HIT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_GOT_HIT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_DEATH);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_PLAYER_REQUEST_RESPAWN);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ON_KILL);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_LASER_HIT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_LASER_SHOT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_NUCLEUS_HIT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_NUCLEUS_SHOT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ROCKET_HIT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ROCKET_SHOT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ARROW_HIT);
|
||||
$this->maniaControl->getStatisticManager()->defineStatMetaData(self::STAT_ARROW_SHOT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle EndMap
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function onEndMap(array $callback) {
|
||||
//Check for Minimum PlayerCount
|
||||
if ($this->maniaControl->getPlayerManager()->getPlayerCount() < $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_COLLECT_STATS_MINPLAYERS)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$leaders = $this->maniaControl->getServer()->getRankingManager()->getLeaders();
|
||||
|
||||
foreach ($leaders as $leaderLogin) {
|
||||
$leader = $this->maniaControl->getPlayerManager()->getPlayer($leaderLogin);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_MAP_WINS, $leader);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert OnShoot Statistic when a player leaves
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function onPlayerDisconnect(Player $player) {
|
||||
// Check if Stat Collecting is enabled
|
||||
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_COLLECT_STATS_ENABLED)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Insert Data into Database, and destroy player
|
||||
if (isset($this->onShootArray[$player->login])) {
|
||||
if ($this->onShootArray[$player->login] > 0) {
|
||||
$this->maniaControl->getStatisticManager()->insertStat(self::STAT_ON_SHOOT, $player, $this->maniaControl->getServer()->index, $this->onShootArray[$player->login]);
|
||||
}
|
||||
unset($this->onShootArray[$player->login]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle stats on callbacks
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleCallbacks(array $callback) {
|
||||
//TODO survivals
|
||||
// Check if Stat Collecting is enabled
|
||||
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_COLLECT_STATS_ENABLED)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for Minimum PlayerCount
|
||||
if ($this->maniaControl->getPlayerManager()->getPlayerCount() < $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_COLLECT_STATS_MINPLAYERS)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$callbackName = $callback[1][0];
|
||||
|
||||
switch ($callbackName) {
|
||||
case 'LibXmlRpc_OnShoot':
|
||||
$this->handleOnShoot($callback[1][1][0], $callback[1][1][1]);
|
||||
break;
|
||||
case 'LibXmlRpc_OnHit':
|
||||
$shooter = $this->maniaControl->getPlayerManager()->getPlayer($callback[1][1][0]);
|
||||
$victim = $this->maniaControl->getPlayerManager()->getPlayer($callback[1][1][1]);
|
||||
$weapon = $callback[1][1][3];
|
||||
if ($shooter) {
|
||||
$this->maniaControl->getStatisticManager()->incrementStat($this->getWeaponStat(intval($weapon), false), $shooter);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_HIT, $shooter);
|
||||
}
|
||||
if ($victim) {
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_GOT_HIT, $victim);
|
||||
}
|
||||
break;
|
||||
case 'LibXmlRpc_OnNearMiss':
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($callback[1][1][0]);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_NEARMISS, $player);
|
||||
break;
|
||||
case 'LibXmlRpc_OnCapture':
|
||||
$logins = $callback[1][1][0];
|
||||
$logins = explode(';', $logins);
|
||||
foreach ($logins as $login) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
if (!$player) {
|
||||
continue;
|
||||
}
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_CAPTURE, $player);
|
||||
}
|
||||
break;
|
||||
case 'LibXmlRpc_OnArmorEmpty':
|
||||
$victim = $this->maniaControl->getPlayerManager()->getPlayer($callback[1][1][1]);
|
||||
if (isset($callback[1][1][0])) {
|
||||
$shooter = $this->maniaControl->getPlayerManager()->getPlayer($callback[1][1][0]);
|
||||
if ($shooter) {
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_KILL, $shooter);
|
||||
}
|
||||
}
|
||||
if ($victim) {
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_DEATH, $victim);
|
||||
}
|
||||
break;
|
||||
case 'LibXmlRpc_OnPlayerRequestRespawn':
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($callback[1][1][0]);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_PLAYER_REQUEST_RESPAWN, $player);
|
||||
break;
|
||||
case 'OnShoot':
|
||||
$paramsObject = json_decode($callback[1][1]);
|
||||
if ($paramsObject && isset($paramsObject->Event)) {
|
||||
$this->handleOnShoot($paramsObject->Event->Shooter->Login, $paramsObject->Event->WeaponNum);
|
||||
}
|
||||
break;
|
||||
case 'OnNearMiss':
|
||||
$paramsObject = json_decode($callback[1][1]);
|
||||
if ($paramsObject && isset($paramsObject->Event)) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($paramsObject->Event->Shooter->Login);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_NEARMISS, $player);
|
||||
}
|
||||
break;
|
||||
case 'OnCapture':
|
||||
$paramsObject = json_decode($callback[1][1]);
|
||||
if ($paramsObject && isset($paramsObject->Event)) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($paramsObject->Event->Player->Login);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_CAPTURE, $player);
|
||||
}
|
||||
break;
|
||||
case 'OnHit':
|
||||
$paramsObject = json_decode($callback[1][1]);
|
||||
if ($paramsObject && isset($paramsObject->Event)) {
|
||||
$weapon = (int)$paramsObject->Event->WeaponNum;
|
||||
if (isset($paramsObject->Event->Shooter)) {
|
||||
$shooter = $this->maniaControl->getPlayerManager()->getPlayer($paramsObject->Event->Shooter->Login);
|
||||
if ($shooter) {
|
||||
$this->maniaControl->getStatisticManager()->incrementStat($this->getWeaponStat($weapon, false), $shooter);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_HIT, $shooter);
|
||||
}
|
||||
}
|
||||
if (isset($paramsObject->Event->Victim)) {
|
||||
$victim = $this->maniaControl->getPlayerManager()->getPlayer($paramsObject->Event->Victim->Login);
|
||||
if ($victim) {
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_GOT_HIT, $victim);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'OnArmorEmpty':
|
||||
$paramsObject = json_decode($callback[1][1]);
|
||||
if ($paramsObject && isset($paramsObject->Event)) {
|
||||
$victim = $this->maniaControl->getPlayerManager()->getPlayer($paramsObject->Event->Victim->Login);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_DEATH, $victim);
|
||||
if (isset($paramsObject->Event->Shooter->Login)) {
|
||||
$shooter = $this->maniaControl->getPlayerManager()->getPlayer($paramsObject->Event->Shooter->Login);
|
||||
if ($shooter) {
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_KILL, $shooter);
|
||||
}
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_KILL, $shooter);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'OnRequestRespawn':
|
||||
$paramsObject = json_decode($callback[1][1]);
|
||||
if ($paramsObject && isset($paramsObject->Event)) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($paramsObject->Event->Player->Login);
|
||||
$this->maniaControl->getStatisticManager()->incrementStat(self::STAT_ON_PLAYER_REQUEST_RESPAWN, $player);
|
||||
}
|
||||
break;
|
||||
case 'EndTurn': //TODO make it for other modes working
|
||||
$paramsObject = json_decode($callback[1][1]);
|
||||
if ($paramsObject && is_array($paramsObject->ScoresTable)) {
|
||||
$durationTime = (int)(($paramsObject->EndTime - $paramsObject->StartTime) / 1000);
|
||||
foreach ($paramsObject->ScoresTable as $score) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($score->Login);
|
||||
$this->maniaControl->getStatisticManager()->insertStat(self::STAT_PLAYTIME, $player, -1, $durationTime);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Player Shots
|
||||
*
|
||||
* @param string $login
|
||||
* @param int $weaponNumber
|
||||
*/
|
||||
private function handleOnShoot($login, $weaponNumber) {
|
||||
if (!isset($this->onShootArray[$login])) {
|
||||
$this->onShootArray[$login] = array(self::WEAPON_ROCKET => 0, self::WEAPON_ARROW => 0, self::WEAPON_NUCLEUS => 0, self::WEAPON_LASER => 0);
|
||||
}
|
||||
if (!isset($this->onShootArray[$login][$weaponNumber])) {
|
||||
$this->onShootArray[$login][$weaponNumber] = 0;
|
||||
}
|
||||
$this->onShootArray[$login][$weaponNumber]++;
|
||||
|
||||
//Write Shoot Data into database
|
||||
if (array_sum($this->onShootArray[$login]) > $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ON_SHOOT_PRESTORE)
|
||||
) {
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
|
||||
$rocketShots = $this->onShootArray[$login][self::WEAPON_ROCKET];
|
||||
$laserShots = $this->onShootArray[$login][self::WEAPON_LASER];
|
||||
$arrowShots = $this->onShootArray[$login][self::WEAPON_ARROW];
|
||||
$nucleusShots = $this->onShootArray[$login][self::WEAPON_NUCLEUS];
|
||||
|
||||
if ($rocketShots > 0) {
|
||||
$this->maniaControl->getStatisticManager()->insertStat(self::STAT_ROCKET_SHOT, $player, $this->maniaControl->getServer()->index, $rocketShots);
|
||||
$this->onShootArray[$login][self::WEAPON_ROCKET] = 0;
|
||||
}
|
||||
if ($laserShots > 0) {
|
||||
$this->maniaControl->getStatisticManager()->insertStat(self::STAT_LASER_SHOT, $player, $this->maniaControl->getServer()->index, $laserShots);
|
||||
$this->onShootArray[$login][self::WEAPON_LASER] = 0;
|
||||
}
|
||||
if ($arrowShots > 0) {
|
||||
$this->maniaControl->getStatisticManager()->insertStat(self::STAT_ARROW_SHOT, $player, $this->maniaControl->getServer()->index, $arrowShots);
|
||||
$this->onShootArray[$login][self::WEAPON_ARROW] = 0;
|
||||
}
|
||||
if ($nucleusShots > 0) {
|
||||
$this->maniaControl->getStatisticManager()->insertStat(self::STAT_NUCLEUS_SHOT, $player, $this->maniaControl->getServer()->index, $nucleusShots);
|
||||
$this->onShootArray[$login][self::WEAPON_NUCLEUS] = 0;
|
||||
}
|
||||
|
||||
$this->maniaControl->getStatisticManager()->insertStat(self::STAT_ON_SHOOT, $player, $this->maniaControl->getServer()->index, $rocketShots + $laserShots + $arrowShots + $nucleusShots);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Weapon stat
|
||||
*
|
||||
* @param int $weaponNumber
|
||||
* @param bool $shot
|
||||
* @return string
|
||||
*/
|
||||
private function getWeaponStat($weaponNumber, $shot = true) {
|
||||
if ($shot) {
|
||||
switch ($weaponNumber) {
|
||||
case self::WEAPON_ROCKET:
|
||||
return self::STAT_ROCKET_SHOT;
|
||||
case self::WEAPON_LASER:
|
||||
return self::STAT_LASER_SHOT;
|
||||
case self::WEAPON_ARROW:
|
||||
return self::STAT_ARROW_SHOT;
|
||||
case self::WEAPON_NUCLEUS:
|
||||
return self::STAT_NUCLEUS_SHOT;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
switch ($weaponNumber) {
|
||||
case self::WEAPON_ROCKET:
|
||||
return self::STAT_ROCKET_HIT;
|
||||
case self::WEAPON_LASER:
|
||||
return self::STAT_LASER_HIT;
|
||||
case self::WEAPON_ARROW:
|
||||
return self::STAT_ARROW_HIT;
|
||||
case self::WEAPON_NUCLEUS:
|
||||
return self::STAT_NUCLEUS_HIT;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
626
core/Statistics/StatisticManager.php
Normal file
626
core/Statistics/StatisticManager.php
Normal file
@ -0,0 +1,626 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Statistics;
|
||||
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
|
||||
/**
|
||||
* Statistic Manager Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class StatisticManager {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const TABLE_STATMETADATA = 'mc_statmetadata';
|
||||
const TABLE_STATISTICS = 'mc_statistics';
|
||||
const STAT_TYPE_INT = '0';
|
||||
const STAT_TYPE_TIME = '1';
|
||||
const STAT_TYPE_FLOAT = '2';
|
||||
|
||||
const SPECIAL_STAT_KD_RATIO = 'Kill Death Ratio'; //TODO dynamic later
|
||||
const SPECIAL_STAT_HITS_PH = 'Hits Per Hour';
|
||||
const SPECIAL_STAT_LASER_ACC = 'Laser Accuracy';
|
||||
const SPECIAL_STAT_NUCLEUS_ACC = 'Nucleus Accuracy';
|
||||
const SPECIAL_STAT_ROCKET_ACC = 'Rocket Accuracy';
|
||||
const SPECIAL_STAT_ARROW_ACC = 'Arrow Accuracy';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var StatisticCollector $statisticCollector */
|
||||
/** @deprecated see getStatisticCollector() */
|
||||
public $statisticCollector = null;
|
||||
/** @var SimpleStatsList $simpleStatsList */
|
||||
/** @deprecated see getSimpleStatsList() */
|
||||
public $simpleStatsList = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $stats = array();
|
||||
private $specialStats = array();
|
||||
|
||||
/**
|
||||
* Construct a new statistic manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
$this->initTables();
|
||||
|
||||
$this->statisticCollector = new StatisticCollector($maniaControl);
|
||||
$this->simpleStatsList = new SimpleStatsList($maniaControl);
|
||||
|
||||
// Store Stats MetaData
|
||||
$this->storeStatMetaData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize necessary database tables
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function initTables() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_STATMETADATA . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) NOT NULL,
|
||||
`type` int(5) NOT NULL,
|
||||
`description` varchar(150) NOT NULL,
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `name` (`name`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Statistics Meta Data' AUTO_INCREMENT=1;";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
|
||||
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_STATISTICS . "` (
|
||||
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`serverIndex` int(11) NOT NULL,
|
||||
`playerId` int(11) NOT NULL,
|
||||
`statId` int(11) NOT NULL,
|
||||
`value` int(20) NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`index`),
|
||||
UNIQUE KEY `unique` (`statId`,`playerId`,`serverIndex`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Statistics' AUTO_INCREMENT=1;";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error, E_USER_ERROR);
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store Stats Meta Data from the Database
|
||||
*/
|
||||
private function storeStatMetaData() {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
|
||||
$query = "SELECT * FROM `" . self::TABLE_STATMETADATA . "`;";
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return;
|
||||
}
|
||||
|
||||
while ($row = $result->fetch_object()) {
|
||||
$this->stats[$row->name] = $row;
|
||||
}
|
||||
$result->free();
|
||||
|
||||
// TODO: own model class
|
||||
|
||||
//Define Special Stat Kill / Death Ratio
|
||||
$stat = new \stdClass();
|
||||
$stat->name = self::SPECIAL_STAT_KD_RATIO;
|
||||
$stat->type = self::STAT_TYPE_FLOAT;
|
||||
$this->specialStats[self::SPECIAL_STAT_KD_RATIO] = $stat;
|
||||
|
||||
//Hits Per Hour
|
||||
$stat = new \stdClass();
|
||||
$stat->name = self::SPECIAL_STAT_HITS_PH;
|
||||
$stat->type = self::STAT_TYPE_FLOAT;
|
||||
$this->specialStats[self::SPECIAL_STAT_HITS_PH] = $stat;
|
||||
|
||||
//Laser Accuracy
|
||||
$stat = new \stdClass();
|
||||
$stat->name = self::SPECIAL_STAT_LASER_ACC;
|
||||
$stat->type = self::STAT_TYPE_FLOAT;
|
||||
$this->specialStats[self::SPECIAL_STAT_LASER_ACC] = $stat;
|
||||
|
||||
//Nucleus Accuracy
|
||||
$stat = new \stdClass();
|
||||
$stat->name = self::SPECIAL_STAT_NUCLEUS_ACC;
|
||||
$stat->type = self::STAT_TYPE_FLOAT;
|
||||
$this->specialStats[self::SPECIAL_STAT_NUCLEUS_ACC] = $stat;
|
||||
|
||||
//Arrow Accuracy
|
||||
$stat = new \stdClass();
|
||||
$stat->name = self::SPECIAL_STAT_ARROW_ACC;
|
||||
$stat->type = self::STAT_TYPE_FLOAT;
|
||||
$this->specialStats[self::SPECIAL_STAT_ARROW_ACC] = $stat;
|
||||
|
||||
//Rocket Accuracy
|
||||
$stat = new \stdClass();
|
||||
$stat->name = self::SPECIAL_STAT_ROCKET_ACC;
|
||||
$stat->type = self::STAT_TYPE_FLOAT;
|
||||
$this->specialStats[self::SPECIAL_STAT_ROCKET_ACC] = $stat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the statistic collector
|
||||
*
|
||||
* @return StatisticCollector
|
||||
*/
|
||||
public function getStatisticCollector() {
|
||||
return $this->statisticCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the simple stats list
|
||||
*
|
||||
* @return SimpleStatsList
|
||||
*/
|
||||
public function getSimpleStatsList() {
|
||||
return $this->simpleStatsList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get All statistics ordered by an given name
|
||||
*
|
||||
* @param string $statName
|
||||
* @param $serverIndex
|
||||
* @param $minValue
|
||||
* @internal param $orderedBy
|
||||
* @return array
|
||||
*/
|
||||
public function getStatsRanking($statName = '', $serverIndex = -1, $minValue = -1) {
|
||||
if (isset($this->specialStats[$statName])) {
|
||||
return $this->getStatsRankingOfSpecialStat($statName, $serverIndex);
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$statId = $this->getStatId($statName);
|
||||
|
||||
$query = "SELECT `playerId`, `serverIndex`, `value` FROM `" . self::TABLE_STATISTICS . "`
|
||||
WHERE `statId` = {$statId} ";
|
||||
if ($minValue >= 0) {
|
||||
$query .= "AND `value` >= {$minValue} ";
|
||||
}
|
||||
$query .= "ORDER BY `value` DESC;";
|
||||
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return null;
|
||||
}
|
||||
|
||||
$stats = array();
|
||||
while ($row = $result->fetch_object()) {
|
||||
if ($serverIndex < 0) {
|
||||
if (!isset($stats[$row->playerId])) {
|
||||
$stats[$row->playerId] = $row->value;
|
||||
} else {
|
||||
$stats[$row->playerId] += $row->value;
|
||||
}
|
||||
} else if ($serverIndex == $row->serverIndex) {
|
||||
$stats[$row->playerId] = $row->value;
|
||||
}
|
||||
}
|
||||
$result->free();
|
||||
|
||||
arsort($stats);
|
||||
return $stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets The Ranking of an Special Stat
|
||||
*
|
||||
* @param string $statName
|
||||
* @param $serverIndex
|
||||
* @return array
|
||||
*/
|
||||
public function getStatsRankingOfSpecialStat($statName = '', $serverIndex = -1) {
|
||||
$statsArray = array();
|
||||
switch ($statName) {
|
||||
case self::SPECIAL_STAT_KD_RATIO:
|
||||
$kills = $this->getStatsRanking(StatisticCollector::STAT_ON_KILL, $serverIndex);
|
||||
$deaths = $this->getStatsRanking(StatisticCollector::STAT_ON_DEATH, $serverIndex);
|
||||
if (!$kills || !$deaths) {
|
||||
return array();
|
||||
}
|
||||
foreach ($deaths as $key => $death) {
|
||||
if (!$death || !isset($kills[$key])) {
|
||||
continue;
|
||||
}
|
||||
$statsArray[$key] = intval($kills[$key]) / intval($death);
|
||||
}
|
||||
arsort($statsArray);
|
||||
break;
|
||||
case self::SPECIAL_STAT_HITS_PH:
|
||||
$hits = $this->getStatsRanking(StatisticCollector::STAT_ON_HIT, $serverIndex);
|
||||
$times = $this->getStatsRanking(StatisticCollector::STAT_PLAYTIME, $serverIndex);
|
||||
if (!$hits || !$times) {
|
||||
return array();
|
||||
}
|
||||
foreach ($times as $key => $time) {
|
||||
if (!$time || !isset($hits[$key])) {
|
||||
continue;
|
||||
}
|
||||
$statsArray[$key] = intval($hits[$key]) / (intval($time) / 3600);
|
||||
}
|
||||
arsort($statsArray);
|
||||
break;
|
||||
case self::SPECIAL_STAT_ARROW_ACC:
|
||||
$hits = $this->getStatsRanking(StatisticCollector::STAT_ARROW_HIT, $serverIndex);
|
||||
$shots = $this->getStatsRanking(StatisticCollector::STAT_ARROW_SHOT, $serverIndex);
|
||||
if (!$hits || !$shots) {
|
||||
return array();
|
||||
}
|
||||
foreach ($shots as $key => $shot) {
|
||||
if (!$shot || !isset($hits[$key])) {
|
||||
continue;
|
||||
}
|
||||
$statsArray[$key] = intval($hits[$key]) / (intval($shot));
|
||||
}
|
||||
arsort($statsArray);
|
||||
break;
|
||||
case self::SPECIAL_STAT_LASER_ACC:
|
||||
$hits = $this->getStatsRanking(StatisticCollector::STAT_LASER_HIT, $serverIndex);
|
||||
$shots = $this->getStatsRanking(StatisticCollector::STAT_LASER_SHOT, $serverIndex);
|
||||
if (!$hits || !$shots) {
|
||||
return array();
|
||||
}
|
||||
foreach ($shots as $key => $shot) {
|
||||
if (!$shot || !isset($hits[$key])) {
|
||||
continue;
|
||||
}
|
||||
$statsArray[$key] = intval($hits[$key]) / (intval($shot));
|
||||
}
|
||||
arsort($statsArray);
|
||||
break;
|
||||
case self::SPECIAL_STAT_ROCKET_ACC:
|
||||
$hits = $this->getStatsRanking(StatisticCollector::STAT_ROCKET_HIT, $serverIndex);
|
||||
$shots = $this->getStatsRanking(StatisticCollector::STAT_ROCKET_SHOT, $serverIndex);
|
||||
if (!$hits || !$shots) {
|
||||
return array();
|
||||
}
|
||||
foreach ($shots as $key => $shot) {
|
||||
if (!$shot || !isset($hits[$key])) {
|
||||
continue;
|
||||
}
|
||||
$statsArray[$key] = intval($hits[$key]) / (intval($shot));
|
||||
}
|
||||
arsort($statsArray);
|
||||
break;
|
||||
case self::SPECIAL_STAT_NUCLEUS_ACC:
|
||||
$hits = $this->getStatsRanking(StatisticCollector::STAT_NUCLEUS_HIT, $serverIndex);
|
||||
$shots = $this->getStatsRanking(StatisticCollector::STAT_NUCLEUS_SHOT, $serverIndex);
|
||||
if (!$hits || !$shots) {
|
||||
return array();
|
||||
}
|
||||
foreach ($shots as $key => $shot) {
|
||||
if (!$shot || !isset($hits[$key])) {
|
||||
continue;
|
||||
}
|
||||
$statsArray[$key] = intval($hits[$key]) / (intval($shot));
|
||||
}
|
||||
arsort($statsArray);
|
||||
break;
|
||||
}
|
||||
return $statsArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Stat Id
|
||||
*
|
||||
* @param string $statName
|
||||
* @return int
|
||||
*/
|
||||
private function getStatId($statName) {
|
||||
if (isset($this->stats[$statName])) {
|
||||
$stat = $this->stats[$statName];
|
||||
return (int)$stat->index;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all statistics of a certain player
|
||||
*
|
||||
* @param Player $player
|
||||
* @param int $serverIndex
|
||||
* @return array
|
||||
*/
|
||||
public function getAllPlayerStats(Player $player, $serverIndex = -1) {
|
||||
// TODO improve performance of the foreach
|
||||
$playerStats = array();
|
||||
foreach ($this->stats as $stat) {
|
||||
$value = $this->getStatisticData($stat->name, $player->index, $serverIndex);
|
||||
$playerStats[$stat->name] = array($stat, $value);
|
||||
}
|
||||
|
||||
foreach ($this->specialStats as $stat) {
|
||||
switch ($stat->name) {
|
||||
case self::SPECIAL_STAT_KD_RATIO:
|
||||
if (!isset($playerStats[StatisticCollector::STAT_ON_KILL]) || !isset($playerStats[StatisticCollector::STAT_ON_DEATH])) {
|
||||
continue;
|
||||
}
|
||||
$kills = intval($playerStats[StatisticCollector::STAT_ON_KILL][1]);
|
||||
$deaths = intval($playerStats[StatisticCollector::STAT_ON_DEATH][1]);
|
||||
if (!$deaths) {
|
||||
continue;
|
||||
}
|
||||
$playerStats[$stat->name] = array($stat, $kills / $deaths);
|
||||
break;
|
||||
case self::SPECIAL_STAT_HITS_PH:
|
||||
if (!isset($playerStats[StatisticCollector::STAT_PLAYTIME]) || !isset($playerStats[StatisticCollector::STAT_ON_HIT])) {
|
||||
continue;
|
||||
}
|
||||
$hits = intval($playerStats[StatisticCollector::STAT_ON_HIT][1]);
|
||||
$time = intval($playerStats[StatisticCollector::STAT_PLAYTIME][1]);
|
||||
if (!$time) {
|
||||
continue;
|
||||
}
|
||||
$playerStats[$stat->name] = array($stat, $hits / ($time / 3600));
|
||||
break;
|
||||
case self::SPECIAL_STAT_ARROW_ACC:
|
||||
if (!isset($playerStats[StatisticCollector::STAT_ARROW_HIT]) || !isset($playerStats[StatisticCollector::STAT_ARROW_SHOT])) {
|
||||
continue;
|
||||
}
|
||||
$hits = intval($playerStats[StatisticCollector::STAT_ARROW_HIT][1]);
|
||||
$shots = intval($playerStats[StatisticCollector::STAT_ARROW_SHOT][1]);
|
||||
if (!$shots) {
|
||||
continue;
|
||||
}
|
||||
$playerStats[$stat->name] = array($stat, $hits / $shots);
|
||||
break;
|
||||
case self::SPECIAL_STAT_LASER_ACC:
|
||||
if (!isset($playerStats[StatisticCollector::STAT_LASER_HIT]) || !isset($playerStats[StatisticCollector::STAT_LASER_SHOT])) {
|
||||
continue;
|
||||
}
|
||||
$hits = intval($playerStats[StatisticCollector::STAT_LASER_HIT][1]);
|
||||
$shots = intval($playerStats[StatisticCollector::STAT_LASER_SHOT][1]);
|
||||
if (!$shots) {
|
||||
continue;
|
||||
}
|
||||
$playerStats[$stat->name] = array($stat, $hits / $shots);
|
||||
break;
|
||||
case self::SPECIAL_STAT_ROCKET_ACC:
|
||||
if (!isset($playerStats[StatisticCollector::STAT_ROCKET_HIT]) || !isset($playerStats[StatisticCollector::STAT_ROCKET_SHOT])) {
|
||||
continue;
|
||||
}
|
||||
$hits = intval($playerStats[StatisticCollector::STAT_ROCKET_HIT][1]);
|
||||
$shots = intval($playerStats[StatisticCollector::STAT_ROCKET_SHOT][1]);
|
||||
if (!$shots) {
|
||||
continue;
|
||||
}
|
||||
$playerStats[$stat->name] = array($stat, $hits / $shots);
|
||||
break;
|
||||
case self::SPECIAL_STAT_NUCLEUS_ACC:
|
||||
if (!isset($playerStats[StatisticCollector::STAT_NUCLEUS_HIT]) || !isset($playerStats[StatisticCollector::STAT_NUCLEUS_SHOT])) {
|
||||
continue;
|
||||
}
|
||||
$hits = intval($playerStats[StatisticCollector::STAT_NUCLEUS_HIT][1]);
|
||||
$shots = intval($playerStats[StatisticCollector::STAT_NUCLEUS_SHOT][1]);
|
||||
if (!$shots) {
|
||||
continue;
|
||||
}
|
||||
$playerStats[$stat->name] = array($stat, (float)($hits / $shots));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $playerStats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of an statistic
|
||||
*
|
||||
* @param $statName
|
||||
* @param $playerId
|
||||
* @param int $serverIndex
|
||||
* @return int
|
||||
*/
|
||||
public function getStatisticData($statName, $playerId, $serverIndex = -1) {
|
||||
//Handle Special Stats
|
||||
switch ($statName) {
|
||||
case self::SPECIAL_STAT_KD_RATIO:
|
||||
$kills = $this->getStatisticData(StatisticCollector::STAT_ON_KILL, $playerId, $serverIndex);
|
||||
$deaths = $this->getStatisticData(StatisticCollector::STAT_ON_DEATH, $playerId, $serverIndex);
|
||||
if (!$deaths) {
|
||||
return -1;
|
||||
}
|
||||
return intval($kills) / intval($deaths);
|
||||
case self::SPECIAL_STAT_HITS_PH:
|
||||
$hits = $this->getStatisticData(StatisticCollector::STAT_ON_HIT, $playerId, $serverIndex);
|
||||
$time = $this->getStatisticData(StatisticCollector::STAT_PLAYTIME, $playerId, $serverIndex);
|
||||
if (!$time) {
|
||||
return -1;
|
||||
}
|
||||
return intval($hits) / (intval($time) / 3600);
|
||||
case self::SPECIAL_STAT_ARROW_ACC:
|
||||
$hits = $this->getStatisticData(StatisticCollector::STAT_ARROW_HIT, $playerId, $serverIndex);
|
||||
$shots = $this->getStatisticData(StatisticCollector::STAT_ARROW_SHOT, $playerId, $serverIndex);
|
||||
if (!$shots) {
|
||||
return -1;
|
||||
}
|
||||
return intval($hits) / intval($shots);
|
||||
case self::SPECIAL_STAT_LASER_ACC:
|
||||
$hits = $this->getStatisticData(StatisticCollector::STAT_LASER_HIT, $playerId, $serverIndex);
|
||||
$shots = $this->getStatisticData(StatisticCollector::STAT_LASER_SHOT, $playerId, $serverIndex);
|
||||
if (!$shots) {
|
||||
return -1;
|
||||
}
|
||||
return intval($hits) / intval($shots);
|
||||
case self::SPECIAL_STAT_NUCLEUS_ACC:
|
||||
$hits = $this->getStatisticData(StatisticCollector::STAT_NUCLEUS_HIT, $playerId, $serverIndex);
|
||||
$shots = $this->getStatisticData(StatisticCollector::STAT_NUCLEUS_SHOT, $playerId, $serverIndex);
|
||||
if (!$shots) {
|
||||
return -1;
|
||||
}
|
||||
return intval($hits) / intval($shots);
|
||||
case self::SPECIAL_STAT_ROCKET_ACC:
|
||||
$hits = $this->getStatisticData(StatisticCollector::STAT_ROCKET_HIT, $playerId, $serverIndex);
|
||||
$shots = $this->getStatisticData(StatisticCollector::STAT_ROCKET_SHOT, $playerId, $serverIndex);
|
||||
if (!$shots) {
|
||||
return -1;
|
||||
}
|
||||
return intval($hits) / intval($shots);
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$statId = $this->getStatId($statName);
|
||||
|
||||
if (!$statId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ($serverIndex < 0) {
|
||||
$query = "SELECT SUM(`value`) as `value` FROM `" . self::TABLE_STATISTICS . "`
|
||||
WHERE `statId` = {$statId}
|
||||
AND `playerId` = {$playerId};";
|
||||
} else {
|
||||
$query = "SELECT `value` FROM `" . self::TABLE_STATISTICS . "`
|
||||
WHERE `statId` = {$statId}
|
||||
AND `playerId` = {$playerId}
|
||||
AND `serverIndex` = {$serverIndex};";
|
||||
}
|
||||
|
||||
$result = $mysqli->query($query);
|
||||
if (!$result) {
|
||||
trigger_error($mysqli->error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
$row = $result->fetch_object();
|
||||
|
||||
$result->free();
|
||||
return $row->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments a Statistic by one
|
||||
*
|
||||
* @param string $statName
|
||||
* @param Player $player
|
||||
* @param int $serverIndex
|
||||
* @return bool
|
||||
*/
|
||||
public function incrementStat($statName, Player $player, $serverIndex = -1) {
|
||||
return $this->insertStat($statName, $player, $serverIndex, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a Stat into the database
|
||||
*
|
||||
* @param string $statName
|
||||
* @param Player $player
|
||||
* @param int $serverIndex
|
||||
* @param mixed $value , value to Add
|
||||
* @param string $statType
|
||||
* @return bool
|
||||
*/
|
||||
public function insertStat($statName, Player $player, $serverIndex = -1, $value, $statType = self::STAT_TYPE_INT) {
|
||||
// TODO: statType isn't used
|
||||
if (!$player) {
|
||||
return false;
|
||||
}
|
||||
if ($player->isFakePlayer()) {
|
||||
return true;
|
||||
}
|
||||
$statId = $this->getStatId($statName);
|
||||
if (!$statId) {
|
||||
return false;
|
||||
}
|
||||
if ($value < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($serverIndex) {
|
||||
$serverIndex = $this->maniaControl->getServer()->index;
|
||||
}
|
||||
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "INSERT INTO `" . self::TABLE_STATISTICS . "` (
|
||||
`serverIndex`,
|
||||
`playerId`,
|
||||
`statId`,
|
||||
`value`
|
||||
) VALUES (
|
||||
?, ?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`value` = `value` + VALUES(`value`);";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$statement->bind_param('iiii', $serverIndex, $player->index, $statId, $value);
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
$statement->close();
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a Stat
|
||||
*
|
||||
* @param $statName
|
||||
* @param string $type
|
||||
* @param string $statDescription
|
||||
* @return bool
|
||||
*/
|
||||
public function defineStatMetaData($statName, $type = self::STAT_TYPE_INT, $statDescription = '') {
|
||||
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||||
$query = "INSERT INTO `" . self::TABLE_STATMETADATA . "` (
|
||||
`name`,
|
||||
`type`,
|
||||
`description`
|
||||
) VALUES (
|
||||
?, ?, ?
|
||||
) ON DUPLICATE KEY UPDATE
|
||||
`type` = VALUES(`type`),
|
||||
`description` = VALUES(`description`);";
|
||||
$statement = $mysqli->prepare($query);
|
||||
if ($mysqli->error) {
|
||||
trigger_error($mysqli->error);
|
||||
return false;
|
||||
}
|
||||
$statement->bind_param('sis', $statName, $type, $statDescription);
|
||||
$statement->execute();
|
||||
if ($statement->error) {
|
||||
trigger_error($statement->error);
|
||||
$statement->close();
|
||||
return false;
|
||||
}
|
||||
$statement->close();
|
||||
return true;
|
||||
}
|
||||
}
|
55
core/Update/PluginUpdateData.php
Normal file
55
core/Update/PluginUpdateData.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Update;
|
||||
|
||||
/**
|
||||
* Plugin Update Data Model Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PluginUpdateData {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $pluginId = null;
|
||||
public $pluginName = null;
|
||||
public $pluginAuthor = null;
|
||||
public $pluginDescription = null;
|
||||
public $id = null;
|
||||
public $version = null;
|
||||
public $zipfile = null;
|
||||
public $url = null;
|
||||
|
||||
/**
|
||||
* Construct new plugin update data instance
|
||||
*
|
||||
* @param object $updateData
|
||||
*/
|
||||
public function __construct($updateData) {
|
||||
$this->pluginId = $updateData->id;
|
||||
$this->pluginName = $updateData->name;
|
||||
$this->pluginAuthor = $updateData->author;
|
||||
$this->pluginDescription = $updateData->description;
|
||||
if ($updateData->currentVersion) {
|
||||
$this->id = $updateData->currentVersion->id;
|
||||
$this->version = $updateData->currentVersion->version;
|
||||
$this->zipfile = $updateData->currentVersion->zipfile;
|
||||
$this->url = $updateData->currentVersion->url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the plugin update data is newer than the given plugin version
|
||||
*
|
||||
* @param float $version
|
||||
* @return bool
|
||||
*/
|
||||
public function isNewerThan($version) {
|
||||
if (!$version) {
|
||||
return true;
|
||||
}
|
||||
return ($this->version > $version);
|
||||
}
|
||||
}
|
402
core/Update/PluginUpdateManager.php
Normal file
402
core/Update/PluginUpdateManager.php
Normal file
@ -0,0 +1,402 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Update;
|
||||
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\CallbackManager;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Files\BackupUtil;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Plugins\InstallMenu;
|
||||
use ManiaControl\Plugins\Plugin;
|
||||
use ManiaControl\Plugins\PluginManager;
|
||||
use ManiaControl\Plugins\PluginMenu;
|
||||
use ManiaControl\Utils\WebReader;
|
||||
|
||||
/**
|
||||
* Manager checking for ManiaControl Plugin Updates
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class PluginUpdateManager implements CallbackListener, CommandListener, TimerListener {
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
|
||||
/**
|
||||
* Create a new plugin update manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Callbacks
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
|
||||
|
||||
// Chat commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('checkpluginsupdate', $this, 'handle_CheckPluginsUpdate', true, 'Check for Plugin Updates.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('pluginsupdate', $this, 'handle_PluginsUpdate', true, 'Perform the Plugin Updates.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //checkpluginsupdate command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handle_CheckPluginsUpdate(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, UpdateManager::SETTING_PERMISSION_UPDATECHECK)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->checkPluginsUpdate($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if there are Outdated Plugins installed
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function checkPluginsUpdate(Player $player = null) {
|
||||
$message = 'Checking Plugins for newer Versions...';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendInformation($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
|
||||
$this->maniaControl->getPluginManager()->fetchPluginList(function ($data, $error) use (&$player) {
|
||||
if (!$data || $error) {
|
||||
$message = 'Error while checking Plugins for newer Versions!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return;
|
||||
}
|
||||
|
||||
$pluginsData = $this->parsePluginsData($data);
|
||||
$pluginClasses = $this->maniaControl->getPluginManager()->getPluginClasses();
|
||||
$pluginUpdates = array();
|
||||
|
||||
foreach ($pluginClasses as $pluginClass) {
|
||||
/** @var Plugin $pluginClass */
|
||||
$pluginId = $pluginClass::getId();
|
||||
if (!isset($pluginsData[$pluginId])) {
|
||||
continue;
|
||||
}
|
||||
/** @var PluginUpdateData $pluginData */
|
||||
$pluginData = $pluginsData[$pluginId];
|
||||
$pluginVersion = $pluginClass::getVersion();
|
||||
if ($pluginData->isNewerThan($pluginVersion)) {
|
||||
$pluginUpdates[$pluginId] = $pluginData;
|
||||
$message = "There is an Update of '{$pluginData->pluginName}' available! ('{$pluginClass}' - Version {$pluginData->version})";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($pluginUpdates)) {
|
||||
$message = 'Plugins Update Check completed: All Plugins are up-to-date!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
} else {
|
||||
$updatesCount = count($pluginUpdates);
|
||||
$message = "Plugins Update Check completed: There are {$updatesCount} Updates available!";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an Array of Plugin Update Data from the given Web Service Result
|
||||
*
|
||||
* @param mixed $webServiceResult
|
||||
* @return mixed
|
||||
*/
|
||||
public function parsePluginsData($webServiceResult) {
|
||||
if (!$webServiceResult || !is_array($webServiceResult)) {
|
||||
return false;
|
||||
}
|
||||
$pluginsData = array();
|
||||
foreach ($webServiceResult as $pluginResult) {
|
||||
$pluginData = new PluginUpdateData($pluginResult);
|
||||
$pluginsData[$pluginData->pluginId] = $pluginData;
|
||||
}
|
||||
return $pluginsData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //pluginsupdate command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handle_PluginsUpdate(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, UpdateManager::SETTING_PERMISSION_UPDATE)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->performPluginsUpdate($player);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an Update of all outdated Plugins
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function performPluginsUpdate(Player $player = null) {
|
||||
$pluginsUpdates = $this->getPluginsUpdates();
|
||||
if (empty($pluginsUpdates)) {
|
||||
$message = 'There are no Plugin Updates available!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendInformation($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
return;
|
||||
}
|
||||
|
||||
$message = "Starting Plugins Updating...";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendInformation($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
|
||||
$performBackup = $this->maniaControl->getSettingManager()->getSettingValue($this->maniaControl->getUpdateManager(), UpdateManager::SETTING_PERFORM_BACKUPS);
|
||||
if ($performBackup && !BackupUtil::performPluginsBackup()) {
|
||||
$message = 'Creating Backup before Plugins Update failed!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
}
|
||||
|
||||
foreach ($pluginsUpdates as $pluginUpdateData) {
|
||||
$this->installPlugin($pluginUpdateData, $player, true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for Plugin Updates
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPluginsUpdates() {
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'plugins';
|
||||
$response = WebReader::getUrl($url);
|
||||
$dataJson = $response->getContent();
|
||||
$pluginData = json_decode($dataJson);
|
||||
if (!$pluginData || empty($pluginData)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pluginsUpdates = $this->parsePluginsData($pluginData);
|
||||
|
||||
$updates = array();
|
||||
$pluginClasses = $this->maniaControl->getPluginManager()->getPluginClasses();
|
||||
foreach ($pluginClasses as $pluginClass) {
|
||||
/** @var Plugin $pluginClass */
|
||||
$pluginId = $pluginClass::getId();
|
||||
if (isset($pluginsUpdates[$pluginId])) {
|
||||
/** @var PluginUpdateData $pluginUpdateData */
|
||||
$pluginUpdateData = $pluginsUpdates[$pluginId];
|
||||
$pluginVersion = $pluginClass::getVersion();
|
||||
if ($pluginUpdateData->isNewerThan($pluginVersion)) {
|
||||
$updates[$pluginId] = $pluginUpdateData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($updates)) {
|
||||
return false;
|
||||
}
|
||||
return $updates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given Plugin Update Data
|
||||
*
|
||||
* @param PluginUpdateData $pluginUpdateData
|
||||
* @param Player $player
|
||||
* @param bool $update
|
||||
*/
|
||||
private function installPlugin(PluginUpdateData $pluginUpdateData, Player $player = null, $update = false) {
|
||||
$this->maniaControl->getFileReader()->loadFile($pluginUpdateData->url, function ($updateFileContent, $error) use (
|
||||
&$pluginUpdateData, &$player, &$update
|
||||
) {
|
||||
if (!$updateFileContent || $error) {
|
||||
$message = "Error loading Update Data for '{$pluginUpdateData->pluginName}': {$error}!";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendInformation($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return;
|
||||
}
|
||||
|
||||
$actionNoun = ($update ? 'Update' : 'Install');
|
||||
$actionVerb = ($update ? 'Updating' : 'Installing');
|
||||
$actionVerbDone = ($update ? 'updated' : 'installed');
|
||||
|
||||
$message = "Now {$actionVerb} '{$pluginUpdateData->pluginName}'...";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendInformation($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
|
||||
$tempDir = FileUtil::getTempFolder();
|
||||
$updateFileName = $tempDir . $pluginUpdateData->zipfile;
|
||||
|
||||
$bytes = file_put_contents($updateFileName, $updateFileContent);
|
||||
if (!$bytes || $bytes <= 0) {
|
||||
$message = "Plugin {$actionNoun} failed: Couldn't save {$actionNoun} Zip!";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return;
|
||||
}
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
$result = $zip->open($updateFileName);
|
||||
if ($result !== true) {
|
||||
$message = "Plugin {$actionNoun} failed: Couldn't open {$actionNoun} Zip! ({$result})";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return;
|
||||
}
|
||||
|
||||
$zip->extractTo(MANIACONTROL_PATH . 'plugins' . DIRECTORY_SEPARATOR);
|
||||
$zip->close();
|
||||
unlink($updateFileName);
|
||||
FileUtil::deleteTempFolder();
|
||||
|
||||
$messageExtra = '';
|
||||
if ($update) {
|
||||
$messageExtra = ' (Restart ManiaControl to load the new Version!)';
|
||||
}
|
||||
$message = "Successfully {$actionVerbDone} '{$pluginUpdateData->pluginName}'!{$messageExtra}";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
|
||||
if (!$update) {
|
||||
$newPluginClasses = $this->maniaControl->getPluginManager()->loadPlugins();
|
||||
if (empty($newPluginClasses)) {
|
||||
$message = "Loading fresh installed Plugin '{$pluginUpdateData->pluginName}' failed!";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
} else {
|
||||
$message = "Successfully loaded fresh installed Plugin '{$pluginUpdateData->pluginName}'!";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
|
||||
$this->maniaControl->getConfigurator()->showMenu($player, InstallMenu::getTitle());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle PlayerManialinkPageAnswer callback
|
||||
*
|
||||
* @param array $callback
|
||||
*/
|
||||
public function handleManialinkPageAnswer(array $callback) {
|
||||
$actionId = $callback[1][2];
|
||||
$update = (strpos($actionId, PluginMenu::ACTION_PREFIX_UPDATEPLUGIN) === 0);
|
||||
$install = (strpos($actionId, InstallMenu::ACTION_PREFIX_INSTALL_PLUGIN) === 0);
|
||||
if (!$update && !$install) {
|
||||
return;
|
||||
}
|
||||
|
||||
$login = $callback[1][1];
|
||||
$player = $this->maniaControl->getPlayerManager()->getPlayer($login);
|
||||
|
||||
if ($update) {
|
||||
$pluginClass = substr($actionId, strlen(PluginMenu::ACTION_PREFIX_UPDATEPLUGIN));
|
||||
if ($pluginClass === 'All') {
|
||||
$this->performPluginsUpdate($player);
|
||||
} else {
|
||||
$pluginUpdateData = $this->getPluginUpdate($pluginClass);
|
||||
if ($pluginUpdateData) {
|
||||
$this->installPlugin($pluginUpdateData, $player, true);
|
||||
} else {
|
||||
$message = 'Error loading Plugin Update Data!';
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$pluginId = substr($actionId, strlen(InstallMenu::ACTION_PREFIX_INSTALL_PLUGIN));
|
||||
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'plugins/' . $pluginId;
|
||||
$this->maniaControl->getFileReader()->loadFile($url, function ($data, $error) use (&$player) {
|
||||
if ($error || !$data) {
|
||||
$message = "Error loading Plugin Install Data! {$error}";
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
return;
|
||||
}
|
||||
|
||||
$data = json_decode($data);
|
||||
if (!$data) {
|
||||
$message = "Error loading Plugin Install Data! {$error}";
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
return;
|
||||
}
|
||||
|
||||
$pluginUpdateData = new PluginUpdateData($data);
|
||||
$this->installPlugin($pluginUpdateData, $player);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check given Plugin Class for Update
|
||||
*
|
||||
* @param string $pluginClass
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPluginUpdate($pluginClass) {
|
||||
$pluginClass = PluginManager::getPluginClass($pluginClass);
|
||||
/** @var Plugin $pluginClass */
|
||||
$pluginId = $pluginClass::getId();
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'plugins/' . $pluginId;
|
||||
$response = WebReader::getUrl($url);
|
||||
$dataJson = $response->getContent();
|
||||
$pluginVersion = json_decode($dataJson);
|
||||
if (!$pluginVersion) {
|
||||
return false;
|
||||
}
|
||||
$pluginUpdateData = new PluginUpdateData($pluginVersion);
|
||||
$version = $pluginClass::getVersion();
|
||||
if ($pluginUpdateData->isNewerThan($version)) {
|
||||
return $pluginUpdateData;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
49
core/Update/UpdateData.php
Normal file
49
core/Update/UpdateData.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Update;
|
||||
|
||||
/**
|
||||
* ManiaControl Update Data Model Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class UpdateData {
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
public $version = null;
|
||||
public $channel = null;
|
||||
public $url = null;
|
||||
public $releaseDate = null;
|
||||
public $minDedicatedBuild = null;
|
||||
|
||||
/**
|
||||
* Construct new update data instance
|
||||
*
|
||||
* @param object $updateData
|
||||
*/
|
||||
public function __construct($updateData) {
|
||||
$this->version = $updateData->version;
|
||||
$this->channel = $updateData->channel;
|
||||
$this->url = $updateData->url;
|
||||
$this->releaseDate = $updateData->release_date;
|
||||
$this->minDedicatedBuild = $updateData->min_dedicated_build;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the update data is newer than the given date
|
||||
*
|
||||
* @param string $compareDate
|
||||
* @return bool
|
||||
*/
|
||||
public function isNewerThan($compareDate) {
|
||||
if (!$compareDate) {
|
||||
return true;
|
||||
}
|
||||
$compareTime = strtotime($compareDate);
|
||||
$releaseTime = strtotime($this->releaseDate);
|
||||
return ($releaseTime > $compareTime);
|
||||
}
|
||||
}
|
515
core/Update/UpdateManager.php
Normal file
515
core/Update/UpdateManager.php
Normal file
@ -0,0 +1,515 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Update;
|
||||
|
||||
use ManiaControl\Admin\AuthenticationManager;
|
||||
use ManiaControl\Callbacks\CallbackListener;
|
||||
use ManiaControl\Callbacks\TimerListener;
|
||||
use ManiaControl\Commands\CommandListener;
|
||||
use ManiaControl\Files\BackupUtil;
|
||||
use ManiaControl\Files\FileUtil;
|
||||
use ManiaControl\Logger;
|
||||
use ManiaControl\ManiaControl;
|
||||
use ManiaControl\Players\Player;
|
||||
use ManiaControl\Players\PlayerManager;
|
||||
|
||||
/**
|
||||
* Manager checking for ManiaControl Core Updates
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class UpdateManager implements CallbackListener, CommandListener, TimerListener {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const CHANNEL_RELEASE = 'release';
|
||||
const CHANNEL_BETA = 'beta';
|
||||
const CHANNEL_NIGHTLY = 'nightly';
|
||||
const SETTING_ENABLE_UPDATECHECK = 'Enable Automatic Core Update Check';
|
||||
const SETTING_UPDATECHECK_INTERVAL = 'Core Update Check Interval (Hours)';
|
||||
const SETTING_UPDATECHECK_CHANNEL = 'Core Update Channel (release, beta, nightly)';
|
||||
const SETTING_PERFORM_BACKUPS = 'Perform Backup before Updating';
|
||||
const SETTING_AUTO_UPDATE = 'Perform update automatically';
|
||||
const SETTING_PERMISSION_UPDATE = 'Update Core';
|
||||
const SETTING_PERMISSION_UPDATECHECK = 'Check Core Update';
|
||||
const BUILD_DATE_FILE_NAME = 'build_date.txt';
|
||||
|
||||
/*
|
||||
* Public properties
|
||||
*/
|
||||
/** @var PluginUpdateManager $pluginUpdateManager
|
||||
* @deprecated see getPluginUpdateManager()
|
||||
*/
|
||||
public $pluginUpdateManager = null;
|
||||
|
||||
/*
|
||||
* Private properties
|
||||
*/
|
||||
/** @var ManiaControl $maniaControl */
|
||||
private $maniaControl = null;
|
||||
private $currentBuildDate = null;
|
||||
/** @var UpdateData $coreUpdateData */
|
||||
private $coreUpdateData = null;
|
||||
|
||||
/**
|
||||
* Construct a new update manager instance
|
||||
*
|
||||
* @param ManiaControl $maniaControl
|
||||
*/
|
||||
public function __construct(ManiaControl $maniaControl) {
|
||||
$this->maniaControl = $maniaControl;
|
||||
|
||||
// Settings
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_ENABLE_UPDATECHECK, true);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_AUTO_UPDATE, true);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_UPDATECHECK_INTERVAL, 1);
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_UPDATECHECK_CHANNEL, $this->getUpdateChannels());
|
||||
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_PERFORM_BACKUPS, true);
|
||||
|
||||
// Callbacks
|
||||
$updateInterval = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_UPDATECHECK_INTERVAL);
|
||||
$this->maniaControl->getTimerManager()->registerTimerListening($this, 'hourlyUpdateCheck', 1000 * 60 * 60 * $updateInterval);
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERCONNECT, $this, 'handlePlayerJoined');
|
||||
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERDISCONNECT, $this, 'handlePlayerDisconnect');
|
||||
|
||||
// Permissions
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_UPDATE, AuthenticationManager::AUTH_LEVEL_ADMIN);
|
||||
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_UPDATECHECK, AuthenticationManager::AUTH_LEVEL_MODERATOR);
|
||||
|
||||
// Chat commands
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('checkupdate', $this, 'handle_CheckUpdate', true, 'Checks if there is a core update.');
|
||||
$this->maniaControl->getCommandManager()->registerCommandListener('coreupdate', $this, 'handle_CoreUpdate', true, 'Performs the core update.');
|
||||
|
||||
// Children
|
||||
$this->pluginUpdateManager = new PluginUpdateManager($maniaControl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the possible update channels
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getUpdateChannels() {
|
||||
// TODO: change default channel on release
|
||||
return array(self::CHANNEL_BETA, self::CHANNEL_RELEASE, self::CHANNEL_NIGHTLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the plugin update manager
|
||||
*
|
||||
* @return PluginUpdateManager
|
||||
*/
|
||||
public function getPluginUpdateManager() {
|
||||
return $this->pluginUpdateManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform Hourly Update Check
|
||||
*/
|
||||
public function hourlyUpdateCheck() {
|
||||
$updateCheckEnabled = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ENABLE_UPDATECHECK);
|
||||
if (!$updateCheckEnabled) {
|
||||
$this->setCoreUpdateData();
|
||||
} else {
|
||||
$this->checkUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Core Update Data
|
||||
*
|
||||
* @param UpdateData $coreUpdateData
|
||||
*/
|
||||
public function setCoreUpdateData(UpdateData $coreUpdateData = null) {
|
||||
$this->coreUpdateData = $coreUpdateData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an Update Check
|
||||
*/
|
||||
public function checkUpdate() {
|
||||
$this->checkCoreUpdateAsync(array($this, 'handleUpdateCheck'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a Core Update asynchronously
|
||||
*
|
||||
* @param callable $function
|
||||
*/
|
||||
public function checkCoreUpdateAsync($function) {
|
||||
$updateChannel = $this->getCurrentUpdateChannelSetting();
|
||||
$url = ManiaControl::URL_WEBSERVICE . 'versions?current=1&channel=' . $updateChannel;
|
||||
|
||||
$this->maniaControl->getFileReader()->loadFile($url, function ($dataJson, $error) use (&$function) {
|
||||
if ($error) {
|
||||
Logger::logError('Error on UpdateCheck: ' . $error);
|
||||
return;
|
||||
}
|
||||
$versions = json_decode($dataJson);
|
||||
if (!$versions || !isset($versions[0])) {
|
||||
call_user_func($function);
|
||||
} else {
|
||||
$updateData = new UpdateData($versions[0]);
|
||||
call_user_func($function, $updateData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the Update Channel Setting
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCurrentUpdateChannelSetting() {
|
||||
$updateChannel = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_UPDATECHECK_CHANNEL);
|
||||
$updateChannel = strtolower($updateChannel);
|
||||
if (!in_array($updateChannel, $this->getUpdateChannels())) {
|
||||
$updateChannel = self::CHANNEL_RELEASE;
|
||||
}
|
||||
return $updateChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the fetched Update Data of the hourly Check
|
||||
*
|
||||
* @param UpdateData $updateData
|
||||
*/
|
||||
public function handleUpdateCheck(UpdateData $updateData = null) {
|
||||
if (!$this->checkUpdateData($updateData)) {
|
||||
// No new update available
|
||||
return;
|
||||
}
|
||||
if (!$this->checkUpdateDataBuildVersion($updateData)) {
|
||||
// Server incompatible
|
||||
Logger::logError("Please update Your Server to '{$updateData->minDedicatedBuild}' in order to receive further Updates!");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->coreUpdateData != $updateData) {
|
||||
if ($this->isNightlyUpdateChannel()) {
|
||||
Logger::log("New Nightly Build ({$updateData->releaseDate}) available!");
|
||||
} else {
|
||||
Logger::log("New ManiaControl Version {$updateData->version} available!");
|
||||
}
|
||||
$this->setCoreUpdateData($updateData);
|
||||
}
|
||||
|
||||
$this->checkAutoUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given Update Data has a new Version and fits for the Server
|
||||
*
|
||||
* @param UpdateData $updateData
|
||||
* @return bool
|
||||
*/
|
||||
public function checkUpdateData(UpdateData $updateData = null) {
|
||||
if (!$updateData || !$updateData->url) {
|
||||
// Data corrupted
|
||||
return false;
|
||||
}
|
||||
|
||||
$isNightly = $this->isNightlyUpdateChannel();
|
||||
$buildDate = $this->getBuildDate();
|
||||
|
||||
if ($isNightly || $buildDate) {
|
||||
return $updateData->isNewerThan($buildDate);
|
||||
}
|
||||
|
||||
return ($updateData->version > ManiaControl::VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if ManiaControl is running the Nightly Update Channel
|
||||
*
|
||||
* @param string $updateChannel
|
||||
* @return bool
|
||||
*/
|
||||
public function isNightlyUpdateChannel($updateChannel = null) {
|
||||
if (!$updateChannel) {
|
||||
$updateChannel = $this->getCurrentUpdateChannelSetting();
|
||||
}
|
||||
return ($updateChannel === self::CHANNEL_NIGHTLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the build date of the local version
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getBuildDate() {
|
||||
if (!$this->currentBuildDate) {
|
||||
$nightlyBuildDateFile = MANIACONTROL_PATH . 'core' . DIRECTORY_SEPARATOR . self::BUILD_DATE_FILE_NAME;
|
||||
if (file_exists($nightlyBuildDateFile)) {
|
||||
$this->currentBuildDate = file_get_contents($nightlyBuildDateFile);
|
||||
}
|
||||
}
|
||||
return $this->currentBuildDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the Update Data is compatible with the Server
|
||||
*
|
||||
* @param UpdateData $updateData
|
||||
* @return bool
|
||||
*/
|
||||
public function checkUpdateDataBuildVersion(UpdateData $updateData = null) {
|
||||
if (!$updateData) {
|
||||
// Data corrupted
|
||||
return false;
|
||||
}
|
||||
|
||||
$version = $this->maniaControl->getClient()->getVersion();
|
||||
if ($updateData->minDedicatedBuild > $version->build) {
|
||||
// Server not compatible
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an automatic Update should be performed
|
||||
*/
|
||||
public function checkAutoUpdate() {
|
||||
$autoUpdate = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_AUTO_UPDATE);
|
||||
if (!$autoUpdate) {
|
||||
// Auto update turned off
|
||||
return;
|
||||
}
|
||||
if (!$this->coreUpdateData) {
|
||||
// No update available
|
||||
return;
|
||||
}
|
||||
if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) > 0
|
||||
) {
|
||||
// Server not empty
|
||||
return;
|
||||
}
|
||||
|
||||
$this->performCoreUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a Core Update
|
||||
*
|
||||
* @param Player $player
|
||||
* @return bool
|
||||
*/
|
||||
public function performCoreUpdate(Player $player = null) {
|
||||
if (!$this->coreUpdateData) {
|
||||
$message = 'Update failed: No update Data available!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return false;
|
||||
}
|
||||
|
||||
Logger::log("Starting Update to Version v{$this->coreUpdateData->version}...");
|
||||
|
||||
$directories = array('core', 'plugins');
|
||||
if (!FileUtil::checkWritePermissions($directories)) {
|
||||
$message = 'Update not possible: Incorrect File System Permissions!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return false;
|
||||
}
|
||||
|
||||
$performBackup = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_PERFORM_BACKUPS);
|
||||
if ($performBackup && !BackupUtil::performFullBackup()) {
|
||||
$message = 'Creating Backup before Update failed!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
}
|
||||
|
||||
$updateData = $this->coreUpdateData;
|
||||
$this->maniaControl->getFileReader()->loadFile($updateData->url, function ($updateFileContent, $error) use (
|
||||
$updateData, &$player
|
||||
) {
|
||||
if (!$updateFileContent || $error) {
|
||||
$message = "Update failed: Couldn't load Update zip! {$error}";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return;
|
||||
}
|
||||
|
||||
$tempDir = FileUtil::getTempFolder();
|
||||
if (!$tempDir) {
|
||||
$message = "Update failed: Can't save Update zip!";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return;
|
||||
}
|
||||
$updateFileName = $tempDir . basename($updateData->url);
|
||||
|
||||
$bytes = file_put_contents($updateFileName, $updateFileContent);
|
||||
if (!$bytes || $bytes <= 0) {
|
||||
$message = "Update failed: Couldn't save Update zip!";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
return;
|
||||
}
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
$result = $zip->open($updateFileName);
|
||||
if ($result !== true) {
|
||||
$message = "Update failed: Couldn't open Update Zip. ({$result})";
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendError($message, $player);
|
||||
}
|
||||
Logger::logError($message);
|
||||
unlink($updateFileName);
|
||||
return;
|
||||
}
|
||||
|
||||
$zip->extractTo(MANIACONTROL_PATH);
|
||||
$zip->close();
|
||||
unlink($updateFileName);
|
||||
FileUtil::deleteTempFolder();
|
||||
|
||||
// Set the build date
|
||||
$this->setBuildDate($updateData->releaseDate);
|
||||
|
||||
$message = 'Update finished!';
|
||||
if ($player) {
|
||||
$this->maniaControl->getChat()->sendSuccess($message, $player);
|
||||
}
|
||||
Logger::log($message);
|
||||
|
||||
$this->maniaControl->restart();
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the build date version
|
||||
*
|
||||
* @param string $date
|
||||
* @return bool
|
||||
*/
|
||||
public function setBuildDate($date) {
|
||||
$nightlyBuildDateFile = MANIACONTROL_PATH . 'core' . DIRECTORY_SEPARATOR . self::BUILD_DATE_FILE_NAME;
|
||||
$success = (bool)file_put_contents($nightlyBuildDateFile, $date);
|
||||
$this->currentBuildDate = $date;
|
||||
return $success;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ManiaControl PlayerJoined callback
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handlePlayerJoined(Player $player) {
|
||||
if (!$this->coreUpdateData) {
|
||||
return;
|
||||
}
|
||||
// Announce available update
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_UPDATE)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->isNightlyUpdateChannel()) {
|
||||
$this->maniaControl->getChat()->sendSuccess('New Nightly Build (' . $this->coreUpdateData->releaseDate . ') available!', $player->login);
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendInformation('New ManiaControl Version ' . $this->coreUpdateData->version . ' available!', $player->login);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Player Disconnect Callback
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handlePlayerDisconnect(Player $player) {
|
||||
$this->checkAutoUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //checkupdate command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handle_CheckUpdate(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_UPDATECHECK)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->checkCoreUpdateAsync(function (UpdateData $updateData = null) use (&$player) {
|
||||
if (!$this->checkUpdateData($updateData)) {
|
||||
$this->maniaControl->getChat()->sendInformation('No Update available!', $player->login);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->checkUpdateDataBuildVersion($updateData)) {
|
||||
$this->maniaControl->getChat()->sendError("Please update Your Server to '{$updateData->minDedicatedBuild}' in order to receive further Updates!", $player->login);
|
||||
return;
|
||||
}
|
||||
|
||||
$isNightly = $this->isNightlyUpdateChannel();
|
||||
if ($isNightly) {
|
||||
$buildDate = $this->getBuildDate();
|
||||
if ($buildDate) {
|
||||
if ($updateData->isNewerThan($buildDate)) {
|
||||
$this->maniaControl->getChat()->sendInformation("No new Build available! (Current Build: '{$buildDate}')", $player->login);
|
||||
return;
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendSuccess("New Nightly Build ({$updateData->releaseDate}) available! (Current Build: '{$buildDate}')", $player->login);
|
||||
}
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendSuccess("New Nightly Build ('{$updateData->releaseDate}') available!", $player->login);
|
||||
}
|
||||
} else {
|
||||
$this->maniaControl->getChat()->sendSuccess('Update for Version ' . $updateData->version . ' available!', $player->login);
|
||||
}
|
||||
|
||||
$this->coreUpdateData = $updateData;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle //coreupdate command
|
||||
*
|
||||
* @param array $chatCallback
|
||||
* @param Player $player
|
||||
*/
|
||||
public function handle_CoreUpdate(array $chatCallback, Player $player) {
|
||||
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_UPDATE)
|
||||
) {
|
||||
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->checkCoreUpdateAsync(function (UpdateData $updateData = null) use (&$player) {
|
||||
if (!$updateData) {
|
||||
$this->maniaControl->getChat()->sendError('Update is currently not possible!', $player);
|
||||
return;
|
||||
}
|
||||
if (!$this->checkUpdateDataBuildVersion($updateData)) {
|
||||
$this->maniaControl->getChat()->sendError("The Next ManiaControl Update requires a newer Dedicated Server Version!", $player);
|
||||
return;
|
||||
}
|
||||
|
||||
$this->coreUpdateData = $updateData;
|
||||
|
||||
$this->performCoreUpdate($player);
|
||||
});
|
||||
}
|
||||
}
|
30
core/Utils/ClassUtil.php
Normal file
30
core/Utils/ClassUtil.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Utils;
|
||||
|
||||
/**
|
||||
* Utility Class offering Methods related to Classes
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class ClassUtil {
|
||||
|
||||
/**
|
||||
* Get the Class Name of the given Object
|
||||
*
|
||||
* @param mixed $object
|
||||
* @return string
|
||||
*/
|
||||
public static function getClass($object) {
|
||||
if (is_object($object)) {
|
||||
return get_class($object);
|
||||
}
|
||||
if (is_string($object)) {
|
||||
return $object;
|
||||
}
|
||||
trigger_error("Invalid class param: '" . print_r($object, true) . "'!");
|
||||
return (string)$object;
|
||||
}
|
||||
}
|
57
core/Utils/ColorUtil.php
Normal file
57
core/Utils/ColorUtil.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Utils;
|
||||
|
||||
/**
|
||||
* Utility Class offering Methods to convert and use ManiaPlanet Colors
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class ColorUtil {
|
||||
|
||||
/**
|
||||
* Convert the given float value to a color code from red to green
|
||||
*
|
||||
* @param float $value
|
||||
* @return string
|
||||
*/
|
||||
public static function floatToStatusColor($value) {
|
||||
$value = floatval($value);
|
||||
$red = 1.;
|
||||
$green = 1.;
|
||||
if ($value < 0.5) {
|
||||
$green = $value * 2.;
|
||||
}
|
||||
if ($value > 0.5) {
|
||||
$red = 2. * (1. - $value);
|
||||
}
|
||||
$red = ColorUtil::floatToCode($red);
|
||||
$green = ColorUtil::floatToCode($green);
|
||||
return $red . $green . '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hex color representation of the float
|
||||
*
|
||||
* @param float $value
|
||||
* @return string
|
||||
*/
|
||||
public static function floatToCode($value) {
|
||||
$value = floatval($value);
|
||||
if ($value < 0.) {
|
||||
$value = 0.;
|
||||
}
|
||||
if ($value > 1.) {
|
||||
$value = 1.;
|
||||
}
|
||||
$value *= 15.;
|
||||
$value = (int)round($value);
|
||||
if ($value < 10) {
|
||||
return (string)$value;
|
||||
}
|
||||
$codes = array(10 => 'a', 11 => 'b', 12 => 'c', 13 => 'd', 14 => 'e', 15 => 'f');
|
||||
return $codes[$value];
|
||||
}
|
||||
}
|
45
core/Utils/CommandLineHelper.php
Normal file
45
core/Utils/CommandLineHelper.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Utils;
|
||||
|
||||
/**
|
||||
* Command Line Helper Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class CommandLineHelper {
|
||||
|
||||
/**
|
||||
* Get the command line parameter value with the given name
|
||||
*
|
||||
* @param string $paramName
|
||||
* @return string
|
||||
*/
|
||||
public static function getParameter($paramName) {
|
||||
$paramName = (string)$paramName;
|
||||
$params = self::getAllParameters();
|
||||
foreach ($params as $param) {
|
||||
$parts = explode('=', $param, 2);
|
||||
if (count($parts) < 2) {
|
||||
continue;
|
||||
}
|
||||
if ($parts[0] !== $paramName) {
|
||||
continue;
|
||||
}
|
||||
return $parts[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all command line parameters
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getAllParameters() {
|
||||
global $argv;
|
||||
return (array)$argv;
|
||||
}
|
||||
}
|
196
core/Utils/Formatter.php
Normal file
196
core/Utils/Formatter.php
Normal file
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Utils;
|
||||
|
||||
use ManiaControl\Logger;
|
||||
|
||||
/**
|
||||
* Class offering Methods to format Texts and Values
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class Formatter {
|
||||
|
||||
/**
|
||||
* Return the given Text with Escaping around it
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function escapeText($text) {
|
||||
return '$<' . $text . '$>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given Time (in Milliseconds)
|
||||
*
|
||||
* @param int $time
|
||||
* @return string
|
||||
*/
|
||||
public static function formatTime($time) {
|
||||
// TODO: use gmdate()
|
||||
$time = (int)$time;
|
||||
$milliseconds = $time % 1000;
|
||||
$seconds = floor($time / 1000);
|
||||
$minutes = floor($seconds / 60);
|
||||
$hours = floor($minutes / 60);
|
||||
$minutes -= $hours * 60;
|
||||
$seconds -= $hours * 60 + $minutes * 60;
|
||||
$format = ($hours > 0 ? $hours . ':' : '');
|
||||
$format .= ($hours > 0 && $minutes < 10 ? '0' : '') . $minutes . ':';
|
||||
$format .= ($seconds < 10 ? '0' : '') . $seconds . ':';
|
||||
$format .= ($milliseconds < 100 ? '0' : '') . ($milliseconds < 10 ? '0' : '') . $milliseconds;
|
||||
return $format;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format an elapsed time String (2 days ago...) by a given timestamp
|
||||
*
|
||||
* @param int $ptime
|
||||
* @return string
|
||||
*/
|
||||
public static function time_elapsed_string($ptime) {
|
||||
// TODO: refactor code: camelCase!
|
||||
$etime = time() - $ptime;
|
||||
|
||||
if ($etime < 1) {
|
||||
return '0 seconds';
|
||||
}
|
||||
|
||||
$a = array(12 * 30 * 24 * 60 * 60 => 'year', 30 * 24 * 60 * 60 => 'month', 24 * 60 * 60 => 'day', 60 * 60 => 'hour', 60 => 'minute', 1 => 'second');
|
||||
|
||||
foreach ($a as $secs => $str) {
|
||||
$d = $etime / $secs;
|
||||
if ($d >= 1) {
|
||||
$r = round($d);
|
||||
return $r . ' ' . $str . ($r > 1 ? 's' : '') . ' ago';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the given Time (Seconds) to hh:mm:ss
|
||||
*
|
||||
* @param int $seconds
|
||||
* @return string
|
||||
*/
|
||||
public static function formatTimeH($seconds) {
|
||||
return gmdate('H:i:s', $seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given Time (Seconds) to MySQL Timestamp
|
||||
*
|
||||
* @param int $seconds
|
||||
* @return string
|
||||
*/
|
||||
public static function formatTimestamp($seconds) {
|
||||
return date('Y-m-d H:i:s', $seconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove possibly dangerous Codes
|
||||
* (Dangerous Codes are Links and Formats that might screw up the following Styling)
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function stripDirtyCodes($string) {
|
||||
$string = self::stripLinks($string);
|
||||
$string = preg_replace('/(?<!\$)((?:\$\$)*)\$[ow<>]/iu', '$1', $string);
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Links from the String
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function stripLinks($string) {
|
||||
return preg_replace('/(?<!\$)((?:\$\$)*)\$[hlp](?:\[.*?\])?(.*?)(?:\$[hlp]|(\$z)|$)/iu', '$1$2$3', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all Codes from the String
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function stripCodes($string) {
|
||||
$string = self::stripLinks($string);
|
||||
$string = self::stripColors($string);
|
||||
$string = preg_replace('/(?<!\$)((?:\$\$)*)\$[^$0-9a-hlp]/iu', '$1', $string);
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Colors from the String
|
||||
*
|
||||
* @param string $string
|
||||
* @return string
|
||||
*/
|
||||
public static function stripColors($string) {
|
||||
return preg_replace('/(?<!\$)((?:\$\$)*)\$(?:g|[0-9a-f][^\$]{0,2})/iu', '$1', $string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Map Country Names to 3-letter Nation Abbreviations
|
||||
* Created by Xymph
|
||||
* Based on http://en.wikipedia.org/wiki/List_of_IOC_country_codes
|
||||
* See also http://en.wikipedia.org/wiki/Comparison_of_IOC,_FIFA,_and_ISO_3166_country_codes
|
||||
*
|
||||
* @param string $country
|
||||
* @return string
|
||||
*/
|
||||
public static function mapCountry($country) {
|
||||
$nations = array('Afghanistan' => 'AFG', 'Albania' => 'ALB', 'Algeria' => 'ALG', 'Andorra' => 'AND', 'Angola' => 'ANG', 'Argentina' => 'ARG', 'Armenia' => 'ARM', 'Aruba' => 'ARU', 'Australia' => 'AUS', 'Austria' => 'AUT', 'Azerbaijan' => 'AZE', 'Bahamas' => 'BAH', 'Bahrain' => 'BRN', 'Bangladesh' => 'BAN', 'Barbados' => 'BAR', 'Belarus' => 'BLR', 'Belgium' => 'BEL', 'Belize' => 'BIZ', 'Benin' => 'BEN', 'Bermuda' => 'BER', 'Bhutan' => 'BHU', 'Bolivia' => 'BOL', 'Bosnia&Herzegovina' => 'BIH', 'Botswana' => 'BOT', 'Brazil' => 'BRA', 'Brunei' => 'BRU', 'Bulgaria' => 'BUL', 'Burkina Faso' => 'BUR', 'Burundi' => 'BDI', 'Cambodia' => 'CAM', 'Cameroon' => 'CAR', // actually CMR
|
||||
'Canada' => 'CAN', 'Cape Verde' => 'CPV', 'Central African Republic' => 'CAF', 'Chad' => 'CHA', 'Chile' => 'CHI', 'China' => 'CHN', 'Chinese Taipei' => 'TPE', 'Colombia' => 'COL', 'Congo' => 'CGO', 'Costa Rica' => 'CRC', 'Croatia' => 'CRO', 'Cuba' => 'CUB', 'Cyprus' => 'CYP', 'Czech Republic' => 'CZE', 'Czech republic' => 'CZE', 'DR Congo' => 'COD', 'Denmark' => 'DEN', 'Djibouti' => 'DJI', 'Dominica' => 'DMA', 'Dominican Republic' => 'DOM', 'Ecuador' => 'ECU', 'Egypt' => 'EGY', 'El Salvador' => 'ESA', 'Eritrea' => 'ERI', 'Estonia' => 'EST', 'Ethiopia' => 'ETH', 'Fiji' => 'FIJ', 'Finland' => 'FIN', 'France' => 'FRA', 'Gabon' => 'GAB', 'Gambia' => 'GAM', 'Georgia' => 'GEO', 'Germany' => 'GER', 'Ghana' => 'GHA', 'Greece' => 'GRE', 'Grenada' => 'GRN', 'Guam' => 'GUM', 'Guatemala' => 'GUA', 'Guinea' => 'GUI', 'Guinea-Bissau' => 'GBS', 'Guyana' => 'GUY', 'Haiti' => 'HAI', 'Honduras' => 'HON', 'Hong Kong' => 'HKG', 'Hungary' => 'HUN', 'Iceland' => 'ISL', 'India' => 'IND', 'Indonesia' => 'INA', 'Iran' => 'IRI', 'Iraq' => 'IRQ', 'Ireland' => 'IRL', 'Israel' => 'ISR', 'Italy' => 'ITA', 'Ivory Coast' => 'CIV', 'Jamaica' => 'JAM', 'Japan' => 'JPN', 'Jordan' => 'JOR', 'Kazakhstan' => 'KAZ', 'Kenya' => 'KEN', 'Kiribati' => 'KIR', 'Korea' => 'KOR', 'Kuwait' => 'KUW', 'Kyrgyzstan' => 'KGZ', 'Laos' => 'LAO', 'Latvia' => 'LAT', 'Lebanon' => 'LIB', 'Lesotho' => 'LES', 'Liberia' => 'LBR', 'Libya' => 'LBA', 'Liechtenstein' => 'LIE', 'Lithuania' => 'LTU', 'Luxembourg' => 'LUX', 'Macedonia' => 'MKD', 'Malawi' => 'MAW', 'Malaysia' => 'MAS', 'Mali' => 'MLI', 'Malta' => 'MLT', 'Mauritania' => 'MTN', 'Mauritius' => 'MRI', 'Mexico' => 'MEX', 'Moldova' => 'MDA', 'Monaco' => 'MON', 'Mongolia' => 'MGL', 'Montenegro' => 'MNE', 'Morocco' => 'MAR', 'Mozambique' => 'MOZ', 'Myanmar' => 'MYA', 'Namibia' => 'NAM', 'Nauru' => 'NRU', 'Nepal' => 'NEP', 'Netherlands' => 'NED', 'New Zealand' => 'NZL', 'Nicaragua' => 'NCA', 'Niger' => 'NIG', 'Nigeria' => 'NGR', 'Norway' => 'NOR', 'Oman' => 'OMA', 'Other Countries' => 'OTH', 'Pakistan' => 'PAK', 'Palau' => 'PLW', 'Palestine' => 'PLE', 'Panama' => 'PAN', 'Paraguay' => 'PAR', 'Peru' => 'PER', 'Philippines' => 'PHI', 'Poland' => 'POL', 'Portugal' => 'POR', 'Puerto Rico' => 'PUR', 'Qatar' => 'QAT', 'Romania' => 'ROM', // actually ROU
|
||||
'Russia' => 'RUS', 'Rwanda' => 'RWA', 'Samoa' => 'SAM', 'San Marino' => 'SMR', 'Saudi Arabia' => 'KSA', 'Senegal' => 'SEN', 'Serbia' => 'SCG', // actually SRB
|
||||
'Sierra Leone' => 'SLE', 'Singapore' => 'SIN', 'Slovakia' => 'SVK', 'Slovenia' => 'SLO', 'Somalia' => 'SOM', 'South Africa' => 'RSA', 'Spain' => 'ESP', 'Sri Lanka' => 'SRI', 'Sudan' => 'SUD', 'Suriname' => 'SUR', 'Swaziland' => 'SWZ', 'Sweden' => 'SWE', 'Switzerland' => 'SUI', 'Syria' => 'SYR', 'Taiwan' => 'TWN', 'Tajikistan' => 'TJK', 'Tanzania' => 'TAN', 'Thailand' => 'THA', 'Togo' => 'TOG', 'Tonga' => 'TGA', 'Trinidad and Tobago' => 'TRI', 'Tunisia' => 'TUN', 'Turkey' => 'TUR', 'Turkmenistan' => 'TKM', 'Tuvalu' => 'TUV', 'Uganda' => 'UGA', 'Ukraine' => 'UKR', 'United Arab Emirates' => 'UAE', 'United Kingdom' => 'GBR', 'United States of America' => 'USA', 'Uruguay' => 'URU', 'Uzbekistan' => 'UZB', 'Vanuatu' => 'VAN', 'Venezuela' => 'VEN', 'Vietnam' => 'VIE', 'Yemen' => 'YEM', 'Zambia' => 'ZAM', 'Zimbabwe' => 'ZIM');
|
||||
if (array_key_exists($country, $nations)) {
|
||||
return $nations[$country];
|
||||
}
|
||||
if ($country) {
|
||||
Logger::logWarning("Couldn't map Country: '{$country}'!");
|
||||
}
|
||||
return 'OTH';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given Value into a Bool
|
||||
*
|
||||
* @param mixed $value
|
||||
* @return bool
|
||||
*/
|
||||
public static function parseBoolean($value) {
|
||||
if (is_string($value)) {
|
||||
$value = strtolower($value);
|
||||
}
|
||||
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the given Text is encoded in UTF-8
|
||||
*
|
||||
* @param string $text
|
||||
* @return string
|
||||
*/
|
||||
public static function utf8($text) {
|
||||
if (is_array($text)) {
|
||||
$newArray = array();
|
||||
foreach ($text as $key => $value) {
|
||||
if (is_string($value)) {
|
||||
$newArray[$key] = self::utf8($value);
|
||||
} else {
|
||||
$newArray[$key] = $value;
|
||||
}
|
||||
}
|
||||
return $newArray;
|
||||
}
|
||||
return mb_convert_encoding($text, 'UTF-8', 'UTF-8');
|
||||
}
|
||||
}
|
188
core/Utils/SystemUtil.php
Normal file
188
core/Utils/SystemUtil.php
Normal file
@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Utils;
|
||||
|
||||
use ManiaControl\Logger;
|
||||
|
||||
/**
|
||||
* System Utility Class
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
class SystemUtil {
|
||||
/*
|
||||
* Constants
|
||||
*/
|
||||
const OS_UNIX = 'Unix';
|
||||
const OS_WIN = 'Windows';
|
||||
const MIN_PHP_VERSION = '5.4';
|
||||
|
||||
/**
|
||||
* Get whether ManiaControl is running on Windows
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isWindows() {
|
||||
return (self::getOS() === self::OS_WIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Operating System on which ManiaControl is running
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getOS() {
|
||||
if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
|
||||
return self::OS_WIN;
|
||||
}
|
||||
return self::OS_UNIX;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the requirements to run ManiaControl
|
||||
*/
|
||||
public static function checkRequirements() {
|
||||
$success = true;
|
||||
|
||||
// Check for min PHP version
|
||||
$phpVersion = phpversion();
|
||||
$message = 'Checking for minimum required PHP-Version ' . self::MIN_PHP_VERSION . ' ... ';
|
||||
if ($phpVersion < self::MIN_PHP_VERSION) {
|
||||
Logger::log($message . $phpVersion . ' TOO OLD VERSION!');
|
||||
Logger::log(' -- Make sure that you install at least PHP ' . self::MIN_PHP_VERSION . '!');
|
||||
$success = false;
|
||||
} else {
|
||||
Logger::log($message . self::MIN_PHP_VERSION . ' OK!');
|
||||
}
|
||||
|
||||
// Check for MySQLi
|
||||
$message = 'Checking for installed MySQLi ... ';
|
||||
if (!extension_loaded('mysqli')) {
|
||||
Logger::log($message . 'NOT FOUND!');
|
||||
Logger::log(" -- You don't have MySQLi installed! Check: http://www.php.net/manual/en/mysqli.installation.php");
|
||||
$success = false;
|
||||
} else {
|
||||
Logger::log($message . 'FOUND!');
|
||||
}
|
||||
|
||||
// Check for cURL
|
||||
$message = 'Checking for installed cURL ... ';
|
||||
if (!extension_loaded('curl')) {
|
||||
Logger::log($message . 'NOT FOUND!');
|
||||
Logger::log(" -- You don't have cURL installed! Check: http://www.php.net/manual/en/curl.installation.php");
|
||||
$success = false;
|
||||
} else {
|
||||
Logger::log($message . 'FOUND!');
|
||||
}
|
||||
|
||||
if (!$success) {
|
||||
// Missing requirements
|
||||
self::quit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop ManiaControl immediately
|
||||
*
|
||||
* @param string $message
|
||||
* @param bool $errorPrefix
|
||||
*/
|
||||
public static function quit($message = null, $errorPrefix = false) {
|
||||
if ($message) {
|
||||
if ($errorPrefix) {
|
||||
Logger::logError($message);
|
||||
} else {
|
||||
Logger::log($message);
|
||||
}
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart ManiaControl immediately
|
||||
*/
|
||||
public static function restart() {
|
||||
if (SystemUtil::isUnix()) {
|
||||
self::restartUnix();
|
||||
} else {
|
||||
self::restartWindows();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether ManiaControl is running on Unix
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function isUnix() {
|
||||
return (self::getOS() === self::OS_UNIX);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform restart on Unix
|
||||
*/
|
||||
private static function restartUnix() {
|
||||
if (!SystemUtil::checkFunctionAvailability('exec')) {
|
||||
Logger::log("Can't restart ManiaControl because the function 'exec' is disabled!");
|
||||
return;
|
||||
}
|
||||
$fileName = null;
|
||||
if ($scriptName = CommandLineHelper::getParameter('-sh')) {
|
||||
$fileName = $scriptName;
|
||||
} else {
|
||||
$fileName = 'ManiaControl.sh';
|
||||
}
|
||||
$filePath = MANIACONTROL_PATH . $fileName;
|
||||
if (!is_readable($filePath)) {
|
||||
Logger::log("Can't restart ManiaControl because the file '{$fileName}' doesn't exist or isn't readable!");
|
||||
return;
|
||||
}
|
||||
$command = 'sh ' . escapeshellarg($filePath) . ' > /dev/null &';
|
||||
exec($command);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given function is available
|
||||
*
|
||||
* @param string $functionName
|
||||
* @return bool
|
||||
*/
|
||||
public static function checkFunctionAvailability($functionName) {
|
||||
return (function_exists($functionName) && !in_array($functionName, self::getDisabledFunctions()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of disabled functions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function getDisabledFunctions() {
|
||||
$disabledText = ini_get('disable_functions');
|
||||
return explode(',', $disabledText);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform restart on Windows
|
||||
*/
|
||||
private static function restartWindows() {
|
||||
if (!SystemUtil::checkFunctionAvailability('system')) {
|
||||
Logger::log("Can't restart ManiaControl because the function 'system' is disabled!");
|
||||
return;
|
||||
}
|
||||
$fileName = null;
|
||||
if ($scriptName = CommandLineHelper::getParameter('-bat')) {
|
||||
$fileName = $scriptName;
|
||||
} else {
|
||||
$fileName = 'ManiaControl.bat';
|
||||
}
|
||||
$filePath = MANIACONTROL_PATH . $fileName;
|
||||
if (!is_readable($filePath)) {
|
||||
Logger::log("Can't restart ManiaControl because the file '{$fileName}' doesn't exist or isn't readable!");
|
||||
return;
|
||||
}
|
||||
$command = escapeshellarg($filePath);
|
||||
system($command); // TODO: windows stops here as long as controller is running
|
||||
}
|
||||
}
|
96
core/Utils/WebReader.php
Normal file
96
core/Utils/WebReader.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
namespace ManiaControl\Utils;
|
||||
|
||||
use cURL\Request;
|
||||
use cURL\Response;
|
||||
use ManiaControl\ManiaControl;
|
||||
|
||||
/**
|
||||
* Reader Utility Class for efficient Web Requests
|
||||
*
|
||||
* @author ManiaControl Team <mail@maniacontrol.com>
|
||||
* @copyright 2014 ManiaControl Team
|
||||
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||||
*/
|
||||
abstract class WebReader {
|
||||
|
||||
/**
|
||||
* Load a URL via GET
|
||||
*
|
||||
* @param string $url
|
||||
* @param callable $function
|
||||
* @return Response
|
||||
*/
|
||||
public static function getUrl($url, callable $function = null) {
|
||||
$request = static::newRequest($url);
|
||||
$response = $request->send();
|
||||
if ($function) {
|
||||
static::performCallback($response, $function);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @see WebReader::getUrl()
|
||||
*/
|
||||
public static function loadUrl($url, callable $function = null) {
|
||||
if ($function) {
|
||||
return static::getUrl($url, $function);
|
||||
}
|
||||
return static::getUrl($url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new cURL Request for the given URL
|
||||
*
|
||||
* @param string $url
|
||||
* @return Request
|
||||
*/
|
||||
protected static function newRequest($url) {
|
||||
$request = new Request($url);
|
||||
$options = $request->getOptions();
|
||||
$options->set(CURLOPT_TIMEOUT, 5) // timeout
|
||||
->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
|
||||
->set(CURLOPT_AUTOREFERER, true); // follow redirects
|
||||
return $request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the given callback function with the response
|
||||
*
|
||||
* @param Response $response
|
||||
* @param callable $function
|
||||
*/
|
||||
protected static function performCallback(Response $response, callable $function) {
|
||||
$content = $response->getContent();
|
||||
$error = $response->getError()->getMessage();
|
||||
call_user_func($function, $content, $error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a URL via POST
|
||||
*
|
||||
* @param string $url
|
||||
* @param string $content
|
||||
* @param callable $function
|
||||
* @return Response
|
||||
*/
|
||||
public static function postUrl($url, $content = null, callable $function = null) {
|
||||
$request = static::newRequest($url);
|
||||
$request->getOptions()->set(CURLOPT_POST, true); // post method
|
||||
if ($content) {
|
||||
$request->getOptions()->set(CURLOPT_POSTFIELDS, $content); // post content field
|
||||
}
|
||||
$response = $request->send();
|
||||
if ($function) {
|
||||
static::performCallback($response, $function);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user