Compare commits

..

70 Commits

Author SHA1 Message Date
beu
6913609475 add php version in the /version 2025-06-22 22:45:23 +02:00
beu
a42c12ace8 remove map from the playlist when erasing map file 2025-06-22 11:47:22 +02:00
beu
a769fec577 improve logging 2025-06-22 11:45:44 +02:00
beu
271395edfa improve logging 2025-06-22 11:45:37 +02:00
beu
aefff423f7 check permission to prevent CustomEvent injection 2025-06-22 11:45:02 +02:00
beu
827e59ff93 fix error if admin is null 2025-06-22 11:10:12 +02:00
beu
f15fc201d2 Add logging when an admin change a setting 2025-06-22 10:41:45 +02:00
beu
7a8d9f2b0b fix many PHP 8.4 compatibility issues 2025-05-26 22:50:03 +02:00
beu
03a991cd50 sort plugins by natural order 2025-03-27 15:33:03 +01:00
beu
84e7e5fb17 fix small bug when disabling linked setting 2025-03-21 21:29:50 +01:00
beu
d8f93a3a31 increase default column size 2025-03-21 21:28:09 +01:00
beu
7ded2c6ffc fix php doc 2025-03-13 16:36:33 +01:00
beu
356cab4869 fix typo 2025-02-17 21:50:43 +01:00
beu
04a35dc47f disable auto update 2025-02-17 21:40:15 +01:00
beu
cfa42acd24 fix symbols in map name 2025-02-07 20:43:08 +01:00
beu
43cc088fa6 fix api url 2025-01-24 09:45:52 +01:00
beu
e6444a5a47 merge Maniacontrol official repository changes 2025-01-23 19:33:22 +01:00
beu
a6875cabc8 trim command before explode 2025-01-10 15:44:37 +01:00
beu
bfa3fdce60 fix add admin command 2024-11-13 16:21:39 +01:00
beu
9331e22a54 fix error with the setServerOptions method 2024-09-07 20:37:28 +02:00
beu
9c114cd13b allow to add admin without having them in the database 2024-08-28 18:26:55 +02:00
beu
c8bbb3d7c6 cherry pick maniaplanet lib 6.1 2024-08-25 22:30:06 +02:00
beu
3044e466b9 Add PUT method 2024-08-03 11:56:21 +02:00
beu
fb36146cf6 fix position on default widget size 2024-07-23 18:16:30 +02:00
beu
601e3d7431 improve button positions 2024-07-14 19:09:57 +02:00
beu
39db992394 Add support of Zip archive + Create folder button 2024-07-14 16:02:48 +02:00
beu
40c33de0c8 improve style of plugin menu 2024-07-14 15:25:20 +02:00
beu
52945ac7f7 fix tooltip function 2024-07-13 23:06:49 +02:00
beu
8e6fce3e2b Fix different interfaces elements positions when changing size settings 2024-07-13 14:47:11 +02:00
beu
4d1489ed34 fix discord link content-disposition header 2024-07-11 17:48:25 +02:00
beu
268e7454a9 Add Patchdata function 2024-05-27 14:06:59 +02:00
Beu
a8ad7492cf Add ServerPlugin Methods 2024-04-08 16:37:56 +02:00
Beu
f7b3fb5f71 fix error when pcntl extension is not loaded 2023-12-23 21:10:31 +01:00
Beu
996dde826d add getAccountId function 2023-12-23 12:15:00 +01:00
Beu
e44dfa0ef2 prevent to send admin messages to everyone when no admin is connected 2023-12-22 18:42:20 +01:00
Beu
93423e36af add support of process signals 2023-12-01 19:05:24 +01:00
Beu
251988b19b add default permission check for admin commands 2023-11-25 16:07:35 +01:00
Beu
afe617b642 add callbacks for PlayerActions 2023-11-01 17:20:05 +01:00
Beu
4b9ea37217 convert value from database to int 2023-11-01 11:17:40 +01:00
Beu
c2ff687e29 add new property 2023-10-16 14:06:26 +02:00
Beu
c1dea96f27 add a permission to show the map list 2023-10-09 10:18:33 +02:00
Beu
6de16109f3 fix entry name 2023-10-02 15:25:05 +02:00
Beu
69bbcfbc40 fix profile variable 2023-09-27 17:55:40 +02:00
Beu
4bcbda64d6 fix clearstorage at start 2023-09-08 21:23:47 +02:00
Beu
8b3e624d1c fix other paging sizes 2023-09-08 16:00:30 +02:00
Beu
478e842230 add message when plugins update are available 2023-09-08 15:08:49 +02:00
Beu
405d6027f7 fix plugin warning 2023-09-08 14:55:38 +02:00
Beu
02b7b279af fix download button position 2023-09-08 13:06:15 +02:00
Beu
2440de9b92 Fix various interfaces to adapt with different sizes 2023-09-08 12:19:12 +02:00
Beu
d6745370b2 add a setting to disable the cache 2023-09-07 18:16:25 +02:00
Beu
e0859dfc21 add a setting to disable update check when opening plugin menu 2023-08-14 22:32:48 +02:00
Beu
bf9d80ea9c Add Czechia 2023-08-14 18:25:32 +02:00
Beu
bad5ecd70f ensure to have right to perform actions on the map list 2023-08-14 18:18:10 +02:00
Beu
bff16f6441 allow to remove rights to themself 2023-08-14 18:16:58 +02:00
Beu
0f55bff6c2 ensure to a map file name allowed by the server 2023-08-14 17:35:02 +02:00
Beu
d947337c9c fix strict requirement argument 2023-08-14 17:32:13 +02:00
Beu
0ad0d06f85 Add a setting to disable ManiaExchange 2023-08-14 17:11:09 +02:00
Beu
129053e951 Add TeamId from OnScoresStructure 2023-07-12 17:26:49 +02:00
Beu
13965aef03 add and use new attribute for the length of the Entries 2023-07-10 17:12:57 +02:00
Beu
8c478084a2 Replace Entry by TextEdit for string settings to workaround the limit of 255 characters 2023-07-06 21:28:55 +02:00
Beu
2b14b6bf7a add missing property 2023-07-06 21:28:14 +02:00
Beu
7967779492 Add new properties 2023-06-30 18:22:20 +02:00
Beu
9edb5de5c6 fix compatibility for php < 8 2023-05-25 13:35:18 +02:00
Beu
32e00a8051 Hide server password in server options 2023-05-25 13:03:31 +02:00
Beu
cc46f63155 Add the possibility to have custom library 2023-04-13 17:27:44 +02:00
Beu
e0028a7f47 Merge branch 'master' of https://git.virtit.fr/beu/TrackManiaControl 2023-04-11 15:49:48 +02:00
Beu
195e942bd3 Fix implicit conversion 2023-04-11 15:49:32 +02:00
Beu
4c78ee9d1d do not send the script to the players when hiding Manialink 2023-04-01 10:22:58 +02:00
Beu
9a6d7a9284 floor to prevent implicit conversion 2023-01-17 12:32:10 +01:00
Beu
fab4b98787 fix property 2023-01-17 12:31:50 +01:00
116 changed files with 3111 additions and 2173 deletions

10
.gitignore vendored
View File

@ -8,6 +8,12 @@
/logs/ /logs/
/ManiaControl.log /ManiaControl.log
/ManiaControl.pid /ManiaControl.pid
!/plugins/ /plugins/
/plugins/*
!/plugins/MCTeam/ !/plugins/MCTeam/
/libs/
!/libs/curl-easy
!/libs/Evenement
!/libs/FML
!/libs/Maniaplanet
!/libs/React
!/libs/Symfony

View File

@ -28,6 +28,11 @@ if (!ini_get('date.timezone') && function_exists('date_default_timezone_set')) {
// Make sure garbage collection is enabled // Make sure garbage collection is enabled
gc_enable(); gc_enable();
// Listen process signals
if (extension_loaded('pcntl')) {
pcntl_async_signals(true);
}
// Register AutoLoader // Register AutoLoader
require_once MANIACONTROL_PATH . 'core' . DIRECTORY_SEPARATOR . 'AutoLoader.php'; require_once MANIACONTROL_PATH . 'core' . DIRECTORY_SEPARATOR . 'AutoLoader.php';
\ManiaControl\AutoLoader::register(); \ManiaControl\AutoLoader::register();

View File

@ -1,3 +1,10 @@
###v0.258###
#Changes
- MC compatibility with MX v2 api
###v0.257###
#Changes
- MC now supports php 8.0 and 8.1
###v0.255### ###v0.255###
#Additions #Additions
- added optional descriptions to Settings (but no MC-settings have descriptions yet) - added optional descriptions to Settings (but no MC-settings have descriptions yet)

View File

@ -37,7 +37,6 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
*/ */
const ACTION_OPEN_ADMIN_LIST = 'AdminList.OpenAdminList'; const ACTION_OPEN_ADMIN_LIST = 'AdminList.OpenAdminList';
const ACTION_REVOKE_RIGHTS = 'AdminList.RevokeRights'; const ACTION_REVOKE_RIGHTS = 'AdminList.RevokeRights';
const MAX_PLAYERS_PER_PAGE = 15;
/* /*
* Private Properties * Private Properties
@ -129,9 +128,10 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
$index = 1; $index = 1;
$posY -= 10; $posY -= 10;
$pageFrame = null; $pageFrame = null;
$pageMaxCount = $this->getPlayersPerPage();
foreach ($admins as $admin) { foreach ($admins as $admin) {
if ($index % self::MAX_PLAYERS_PER_PAGE === 1) { if ($index % $pageMaxCount === 1) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $frame->addChild($pageFrame);
@ -236,6 +236,16 @@ class AdminLists implements ManialinkPageAnswerListener, CallbackListener, Usage
} }
} }
/**
* Get number of players per page
*
* @return int
*/
public function getPlayersPerPage() {
$pageheight = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
return floor(($pageheight - 16) / 4);
}
/** /**
* Reopen the widget on Map Begin, MapListChanged, etc. * Reopen the widget on Map Begin, MapListChanged, etc.
* *

View File

@ -56,7 +56,7 @@ class AuthCommands implements CommandListener, UsageInformationAble {
$text = $chatCallback[1][2]; $text = $chatCallback[1][2];
$commandParts = explode(' ', $text); $commandParts = explode(' ', $text);
if (!array_key_exists(1, $commandParts)) { if (!array_key_exists(1, $commandParts) || $commandParts[1] === "") {
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
'Usage Example: %s %s', 'Usage Example: %s %s',
$commandParts[0], $commandParts[0],
@ -68,12 +68,10 @@ class AuthCommands implements CommandListener, UsageInformationAble {
$target = $this->maniaControl->getPlayerManager()->getPlayer($commandParts[1]); $target = $this->maniaControl->getPlayerManager()->getPlayer($commandParts[1]);
if (!$target) { if (!$target) {
$message = $this->maniaControl->getChat()->formatMessage( // It's not needed to save the player, it will be done by the grantAuthLevel function
'Player %s not found!', $target = new Player($this->maniaControl, false);
$commandParts[1] $target->login = $commandParts[1];
); $target->nickname = $commandParts[1];
$this->maniaControl->getChat()->sendError($message, $player);
return;
} }
$success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, $targetAuthLevel); $success = $this->maniaControl->getAuthenticationManager()->grantAuthLevel($target, $targetAuthLevel);
@ -154,7 +152,7 @@ class AuthCommands implements CommandListener, UsageInformationAble {
return; return;
} }
if ($target->authLevel >= AuthenticationManager::AUTH_LEVEL_MASTERADMIN) { if ($player !== $target && $target->authLevel >= AuthenticationManager::AUTH_LEVEL_MASTERADMIN) {
$this->maniaControl->getChat()->sendError('You cannot remove rights of a MasterAdmin!', $player); $this->maniaControl->getChat()->sendError('You cannot remove rights of a MasterAdmin!', $player);
return; return;
} }
@ -164,7 +162,7 @@ class AuthCommands implements CommandListener, UsageInformationAble {
return; return;
} }
if ($player->authLevel <= $target->authLevel) { if ($player !== $target && $player->authLevel <= $target->authLevel) {
$this->maniaControl->getChat()->sendError('You cannot remove rights of a higher privileged player!', $player); $this->maniaControl->getChat()->sendError('You cannot remove rights of a higher privileged player!', $player);
return; return;
} }

View File

@ -15,7 +15,7 @@ abstract class AutoLoader {
* Register the Auto Loader * Register the Auto Loader
*/ */
public static function register() { public static function register() {
spl_autoload_register(array(get_class(), 'autoload')); spl_autoload_register(array(get_called_class(), 'autoload'));
} }
/** /**

View File

@ -176,7 +176,7 @@ class CallbackManager implements UsageInformationAble {
/** /**
* Remove the Callback Listener from the given Listeners Array * Remove the Callback Listener from the given Listeners Array
* *
* @param Listening[] $listeningsArray * @param Listening[][] $listeningsArray
* @param CallbackListener $listener * @param CallbackListener $listener
* @return bool * @return bool
*/ */

View File

@ -17,6 +17,7 @@ use ManiaControl\ManiaControl;
*/ */
class StartEndStructure extends BaseTimeStructure { class StartEndStructure extends BaseTimeStructure {
private $count; private $count;
private $valid;
/** /**
* StartEndStructure constructor. * StartEndStructure constructor.
@ -28,6 +29,7 @@ class StartEndStructure extends BaseTimeStructure {
parent::__construct($maniaControl, $data); parent::__construct($maniaControl, $data);
$this->count = $this->getPlainJsonObject()->count; $this->count = $this->getPlainJsonObject()->count;
$this->valid = $this->getPlainJsonObject()->valid;
} }
/** /**
@ -39,4 +41,14 @@ class StartEndStructure extends BaseTimeStructure {
public function getCount() { public function getCount() {
return $this->count; return $this->count;
} }
/**
* Get the Valid Round Count of this Section
*
* @api
* @return int
*/
public function getValidRoundCount() {
return $this->valid;
}
} }

View File

@ -16,6 +16,7 @@ use ManiaControl\Callbacks\Structures\Common\Models\CommonPlayerScore;
*/ */
class PlayerScore extends CommonPlayerScore { class PlayerScore extends CommonPlayerScore {
private $teamid;
private $bestRaceTime; private $bestRaceTime;
private $bestLapTime; private $bestLapTime;
private $stuntScore; private $stuntScore;
@ -28,6 +29,26 @@ class PlayerScore extends CommonPlayerScore {
private $prevRaceCheckpoints; private $prevRaceCheckpoints;
private $prevStuntsScore; private $prevStuntsScore;
/**
* Returns the TeamId
*
* @api
* @return int
*/
public function getTeamId() {
return $this->teamid;
}
/**
* Sets the TeamId
*
* @api
* @param int $teamid
*/
public function setTeamId($teamid) {
$this->teamid = $teamid;
}
/** /**
* Returns the Rank * Returns the Rank
* *

View File

@ -70,6 +70,13 @@ class OnScoresStructure extends CommonScoresStructure {
$playerScore->setPrevStuntsScore($jsonPlayer->prevstuntsscore); $playerScore->setPrevStuntsScore($jsonPlayer->prevstuntsscore);
} }
// New attribute added in TM2020
if (property_exists($jsonPlayer, 'team')) {
// player->teamid can be wrong if the mode forced the team, so this is the best value
$player->teamId = $jsonPlayer->team;
$playerScore->setTeamId($jsonPlayer->team);
}
$this->playerScores[$jsonPlayer->login] = $playerScore; $this->playerScores[$jsonPlayer->login] = $playerScore;
} }
} }

View File

@ -21,6 +21,10 @@ class OnWayPointEventStructure extends BasePlayerTimeStructure {
private $stuntsScore; private $stuntsScore;
private $checkPointInRace; private $checkPointInRace;
private $checkPointInLap; private $checkPointInLap;
private $curRaceCheckpoints;
private $curLapCheckpoints;
private $isInfiniteLaps;
private $isIndependentLaps;
private $isEndRace; private $isEndRace;
private $isEndLap; private $isEndLap;
private $blockId; private $blockId;
@ -42,6 +46,10 @@ class OnWayPointEventStructure extends BasePlayerTimeStructure {
$this->stuntsScore = isset($this->getPlainJsonObject()->stuntsscore) ? $this->getPlainJsonObject()->stuntsscore : null; $this->stuntsScore = isset($this->getPlainJsonObject()->stuntsscore) ? $this->getPlainJsonObject()->stuntsscore : null;
$this->checkPointInRace = (int) $this->getPlainJsonObject()->checkpointinrace; $this->checkPointInRace = (int) $this->getPlainJsonObject()->checkpointinrace;
$this->checkPointInLap = (int) $this->getPlainJsonObject()->checkpointinlap; $this->checkPointInLap = (int) $this->getPlainJsonObject()->checkpointinlap;
$this->curRaceCheckpoints = isset($this->getPlainJsonObject()->curracecheckpoints) ? $this->getPlainJsonObject()->curracecheckpoints : null;
$this->curLapCheckpoints = isset($this->getPlainJsonObject()->curlapcheckpoints) ? $this->getPlainJsonObject()->curlapcheckpoints : null;
$this->isInfiniteLaps = isset($this->getPlainJsonObject()->isinfinitelaps) ? Formatter::parseBoolean($this->getPlainJsonObject()->isinfinitelaps) : null;
$this->isIndependentLaps = isset($this->getPlainJsonObject()->isindependentlaps) ? Formatter::parseBoolean($this->getPlainJsonObject()->isindependentlaps) : null;
$this->isEndRace = Formatter::parseBoolean($this->getPlainJsonObject()->isendrace); $this->isEndRace = Formatter::parseBoolean($this->getPlainJsonObject()->isendrace);
$this->isEndLap = Formatter::parseBoolean($this->getPlainJsonObject()->isendlap); $this->isEndLap = Formatter::parseBoolean($this->getPlainJsonObject()->isendlap);
$this->blockId = $this->getPlainJsonObject()->blockid; $this->blockId = $this->getPlainJsonObject()->blockid;
@ -94,6 +102,38 @@ class OnWayPointEventStructure extends BasePlayerTimeStructure {
return $this->checkPointInLap; return $this->checkPointInLap;
} }
/**
* @api
* @return array|null
*/
public function getCurRaceCheckpoints() {
return $this->curRaceCheckpoints;
}
/**
* @api
* @return array|null
*/
public function getCurLapCheckpoints() {
return $this->curLapCheckpoints;
}
/**
* @api
* @return bool|null
*/
public function getIsInfiniteLaps() {
return $this->isInfiniteLaps;
}
/**
* @api
* @return bool|null
*/
public function getIsIndependentLaps() {
return $this->isIndependentLaps;
}
/** /**
* @api * @api
* @return mixed * @return mixed

View File

@ -351,6 +351,7 @@ class Chat implements CallbackListener, CommunicationListener, UsageInformationA
*/ */
public function sendMessageToAdmins($message, $minLevel = AuthenticationManager::AUTH_LEVEL_MODERATOR, $prefix = true) { public function sendMessageToAdmins($message, $minLevel = AuthenticationManager::AUTH_LEVEL_MODERATOR, $prefix = true) {
$admins = $this->maniaControl->getAuthenticationManager()->getConnectedAdmins($minLevel); $admins = $this->maniaControl->getAuthenticationManager()->getConnectedAdmins($minLevel);
if (count($admins) === 0) return false;
return $this->sendChat($message, $admins, $prefix); return $this->sendChat($message, $admins, $prefix);
} }

View File

@ -2,8 +2,10 @@
namespace ManiaControl\Commands; namespace ManiaControl\Commands;
use ManiaControl\Admin\AuthenticationManager;
use ManiaControl\Callbacks\CallbackListener; use ManiaControl\Callbacks\CallbackListener;
use ManiaControl\Callbacks\CallbackManager; use ManiaControl\Callbacks\CallbackManager;
use ManiaControl\Callbacks\Callbacks;
use ManiaControl\Callbacks\Listening; use ManiaControl\Callbacks\Listening;
use ManiaControl\General\UsageInformationAble; use ManiaControl\General\UsageInformationAble;
use ManiaControl\General\UsageInformationTrait; use ManiaControl\General\UsageInformationTrait;
@ -18,6 +20,10 @@ use ManiaControl\ManiaControl;
*/ */
class CommandManager implements CallbackListener, UsageInformationAble { class CommandManager implements CallbackListener, UsageInformationAble {
use UsageInformationTrait; use UsageInformationTrait;
/*
* Constants
*/
const SETTING_PERMISSION_ADMIN_COMMANDS = "Minimum permissions level to use admin commands";
/* /*
* Private properties * Private properties
@ -48,6 +54,12 @@ class CommandManager implements CallbackListener, UsageInformationAble {
// Callbacks // Callbacks
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERCHAT, $this, 'handleChatCallback'); $this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERCHAT, $this, 'handleChatCallback');
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
}
public function handleAfterInit() {
// Permissions
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_ADMIN_COMMANDS, AuthenticationManager::AUTH_LEVEL_MODERATOR, AuthenticationManager::AUTH_LEVEL_PLAYER);
} }
/** /**
@ -327,6 +339,11 @@ class CommandManager implements CallbackListener, UsageInformationAble {
$isAdminCommand = true; $isAdminCommand = true;
$commandListenings = $this->adminCommandListenings; $commandListenings = $this->adminCommandListenings;
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_ADMIN_COMMANDS)) {
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
return;
}
if ($command === 'admin') { if ($command === 'admin') {
// Strip 'admin' keyword // Strip 'admin' keyword
if (isset($commandArray[1])) { if (isset($commandArray[1])) {

View File

@ -161,7 +161,7 @@ class HelpManager implements CommandListener, CallbackListener, ManialinkPageAns
* @param Player $player * @param Player $player
* @return string * @return string
*/ */
private function parseHelpList(array $commands, $isHelpAll = false, Player $player = null) { private function parseHelpList(array $commands, $isHelpAll = false, ?Player $player = null) {
$showCommands = array(); $showCommands = array();
$registeredMethods = array(); $registeredMethods = array();
$message = ''; $message = '';
@ -238,9 +238,10 @@ class HelpManager implements CommandListener, CallbackListener, ManialinkPageAns
$index = 1; $index = 1;
$posY -= 10; $posY -= 10;
$pageFrame = null; $pageFrame = null;
$pageMaxCount = floor($height * 0.80 / 4);
foreach ($commands as $command) { foreach ($commands as $command) {
if ($index % 15 === 1) { if ($index % $pageMaxCount === 1) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $frame->addChild($pageFrame);
$posY = $height / 2 - 10; $posY = $height / 2 - 10;

View File

@ -188,7 +188,7 @@ class Configurator implements CallbackListener, CommandListener, ManialinkPageAn
* @param Player $player * @param Player $player
* @return \FML\ManiaLink * @return \FML\ManiaLink
*/ */
private function buildManialink($menuIdShown = 0, Player $player = null) { private function buildManialink($menuIdShown = 0, ?Player $player = null) {
$menuPosX = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSX); $menuPosX = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSX);
$menuPosY = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSY); $menuPosY = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_POSY);
$menuWidth = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_WIDTH); $menuWidth = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MENU_WIDTH);

View File

@ -139,6 +139,20 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
} }
$statement->close(); $statement->close();
$query = "ALTER TABLE `" . self::TABLE_GAMEMODE_SETTINGS . "` MODIFY `settingValue` VARCHAR(1000);";
// Grow the size limit for plugins settings
$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 true;
} }
@ -319,20 +333,24 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
} }
// Config // Config
$innerWidth = $width - 3;
$innerHeight = $height - 10;
$pagerSize = 9.; $pagerSize = 9.;
$settingHeight = 5.; $settingHeight = 5.;
$valueWidth = $innerWidth * 0.3;
$labelTextSize = 2; $labelTextSize = 2;
$pageMaxCount = floor($innerHeight / $settingHeight);
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize); $pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize); $pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
@ -342,7 +360,7 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.35, $height * -0.44, 1); $pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1); $pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2); $pageCountLabel->setTextSize(2);
@ -352,17 +370,24 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
$descriptionLabel = new Label(); $descriptionLabel = new Label();
$frame->addChild($descriptionLabel); $frame->addChild($descriptionLabel);
$descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT); $descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT);
$descriptionLabel->setPosition($width * -0.45, $height * -0.44); $descriptionLabel->setPosition($width * -0.5 + 3, $height * -0.5 + 5);
$descriptionLabel->setSize($width * 0.7, $settingHeight); $descriptionLabel->setSize($width - 30, $settingHeight);
$descriptionLabel->setText('Changes only apply with map skip/restart'); $descriptionLabel->setText('Changes only apply with map skip/restart');
$descriptionLabel->setTextColor('ff0'); $descriptionLabel->setTextColor('ff0');
$descriptionLabel->setTextSize($labelTextSize); $descriptionLabel->setTextSize(1);
$descriptionLabel->setTranslate(true); $descriptionLabel->setTranslate(true);
} }
$repositionnedFrame = new Frame();
$frame->addChild($repositionnedFrame);
$repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
$pagesFrame = new Frame();
$repositionnedFrame->addChild($pagesFrame);
$pagesFrame->setPosition(2, -1);
// Setting pages // Setting pages
$pageFrame = null; $pageFrame = null;
$posY = 0.;
$index = 0; $index = 0;
foreach ($scriptParams as $key => $scriptParam) { foreach ($scriptParams as $key => $scriptParam) {
@ -385,25 +410,28 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
); );
} }
if ($index % 13 === 0) { if ($index % $pageMaxCount === 0) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $pagesFrame->addChild($pageFrame);
$posY = 0.41 * $height;
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$index = 1;
} }
$settingFrame = new Frame(); $settingFrame = new Frame();
$pageFrame->addChild($settingFrame); $pageFrame->addChild($settingFrame);
$settingFrame->setY($posY); $settingFrame->setY($settingHeight * $index * -1);
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$settingFrame->addChild($nameLabel); $settingFrame->addChild($nameLabel);
$nameLabel->setHorizontalAlign($nameLabel::LEFT); $nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setSize(0.4 * $width, $settingHeight); $nameLabel->setSize($innerWidth * 0.6, $settingHeight);
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall); $nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
$nameLabel->setText($settingName); $nameLabel->setText($settingName);
$nameLabel->setTextSize($labelTextSize); $nameLabel->setTextSize($labelTextSize);
$nameLabel->setX(-0.46 * $width); $nameLabel->setX(1);
if ($scriptParam->desc === self::DESCRIPTION_HIDDEN) {
$nameLabel->setTextColor("AAAAAA");
}
if (!$isScriptMode) { if (!$isScriptMode) {
if (is_bool($settingValue[0])) { if (is_bool($settingValue[0])) {
@ -415,18 +443,18 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
} else { } else {
$activeQuad->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_LvlRed); $activeQuad->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_LvlRed);
} }
$activeQuad->setX(0.1 * $width); $activeQuad->setX($innerWidth - $valueWidth - 2.5);
} else { } else {
$currentLabel = new Label_Text(); $currentLabel = new Label_Text();
$settingFrame->addChild($currentLabel); $settingFrame->addChild($currentLabel);
$currentLabel->setHorizontalAlign(Label_Text::RIGHT); $currentLabel->setHorizontalAlign(Label_Text::RIGHT);
$currentLabel->setSize(0.2 * $width, 0.9 * $settingHeight); $currentLabel->setSize($innerWidth * 0.2, 0.9 * $settingHeight);
$currentLabel->setStyle(Label_Text::STYLE_TextValueSmall); $currentLabel->setStyle(Label_Text::STYLE_TextValueSmall);
$currentLabel->setText($settingValue[0]); $currentLabel->setText($settingValue[0]);
$currentLabel->setTextColor('aaa'); $currentLabel->setTextColor('aaa');
$currentLabel->setTextPrefix('$i'); $currentLabel->setTextPrefix('$i');
$currentLabel->setTextSize(1); $currentLabel->setTextSize(0.5);
$currentLabel->setX(0.11 * $width); $currentLabel->setX($innerWidth - $valueWidth);
} }
$settingValue = $settingValue[1]; $settingValue = $settingValue[1];
@ -436,7 +464,7 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
// Boolean checkbox // Boolean checkbox
$quad = new Quad(); $quad = new Quad();
$quad->setSize(4, 4); $quad->setSize(4, 4);
$quad->setX(0.27 * $width); $quad->setPosition($innerWidth - $valueWidth / 2, 0);
$checkBox = new CheckBox(self::ACTION_PREFIX_SETTING . $settingName, $settingValue, $quad); $checkBox = new CheckBox(self::ACTION_PREFIX_SETTING . $settingName, $settingValue, $quad);
$settingFrame->addChild($checkBox); $settingFrame->addChild($checkBox);
} else { } else {
@ -445,24 +473,24 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
$settingFrame->addChild($entry); $settingFrame->addChild($entry);
$entry->setDefault($settingValue); $entry->setDefault($settingValue);
$entry->setName(self::ACTION_PREFIX_SETTING . $settingName); $entry->setName(self::ACTION_PREFIX_SETTING . $settingName);
$entry->setSize(0.3 * $width, 0.9 * $settingHeight);
$entry->setStyle(Label_Text::STYLE_TextValueSmall); $entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setTextSize(1); $entry->setTextSize(1);
$entry->setX(0.275 * $width); $entry->setMaxLength(1000);
$entry->setPosition($innerWidth - $valueWidth / 2, 0);
$entry->setSize($valueWidth, $settingHeight * 0.9);
} }
if ($isScriptMode) { if ($isScriptMode) {
$descriptionLabel = new Label(); $descriptionLabel = new Label();
$pageFrame->addChild($descriptionLabel); $pageFrame->addChild($descriptionLabel);
$descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT); $descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT);
$descriptionLabel->setPosition(-0.45 * $width, -0.44 * $height); $descriptionLabel->setPosition(3, $height * -1 + 5);
$descriptionLabel->setSize(0.7 * $width, $settingHeight); $descriptionLabel->setSize($width - 30, $settingHeight);
$descriptionLabel->setTextSize($labelTextSize); $descriptionLabel->setTextSize(1);
$descriptionLabel->setTranslate(true); $descriptionLabel->setTranslate(true);
$nameLabel->addTooltipLabelFeature($descriptionLabel, $scriptParam->desc); $nameLabel->addTooltipLabelFeature($descriptionLabel, $scriptParam->desc);
} }
$posY -= $settingHeight;
$index++; $index++;
} }
@ -590,6 +618,7 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
// Trigger own callback // Trigger own callback
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_GAMEMODESETTING_CHANGED, $settingName, $settingValue); $this->maniaControl->getCallbackManager()->triggerCallback(self::CB_GAMEMODESETTING_CHANGED, $settingName, $settingValue);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') changed the gamemode setting "'. $settingName .'" to "'. $settingValue .'"');
$settingIndex++; $settingIndex++;
} }
@ -599,7 +628,6 @@ class GameModeSettings implements ConfiguratorMenu, CallbackListener, Communicat
$chatMessage .= '!'; $chatMessage .= '!';
$this->maniaControl->getChat()->sendInformation($chatMessage); $this->maniaControl->getChat()->sendInformation($chatMessage);
Logger::logInfo($chatMessage, true);
return true; return true;
} }

View File

@ -15,6 +15,7 @@ use FML\Script\Script;
use ManiaControl\Admin\AuthenticationManager; use ManiaControl\Admin\AuthenticationManager;
use ManiaControl\Callbacks\CallbackListener; use ManiaControl\Callbacks\CallbackListener;
use ManiaControl\Callbacks\CallbackManager; use ManiaControl\Callbacks\CallbackManager;
use ManiaControl\Logger;
use ManiaControl\ManiaControl; use ManiaControl\ManiaControl;
use ManiaControl\Players\Player; use ManiaControl\Players\Player;
use ManiaControl\Settings\Setting; use ManiaControl\Settings\Setting;
@ -108,18 +109,18 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$pagerSize = 9.; $pagerSize = 9.;
$settingHeight = 5.; $settingHeight = 5.;
$labelTextSize = 2; $labelTextSize = 2;
$pageMaxCount = 10; $pageMaxCount = floor(($height * 0.78) / $settingHeight);
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize); $pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize); $pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
@ -129,7 +130,7 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.35, $height * -0.44); $pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1); $pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2); $pageCountLabel->setTextSize(2);
@ -226,6 +227,7 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$entry->setSize($width * 0.3, $settingHeight * 0.9); $entry->setSize($width * 0.3, $settingHeight * 0.9);
$entry->setStyle(Label_Text::STYLE_TextValueSmall); $entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setTextSize(1); $entry->setTextSize(1);
$entry->setMaxLength(1000);
$entry->setName($settingName); $entry->setName($settingName);
$entry->setDefault($setting->value); $entry->setDefault($setting->value);
} }
@ -242,7 +244,7 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
self::ACTION_PREFIX_SETTINGLINKS . $settingClass self::ACTION_PREFIX_SETTINGLINKS . $settingClass
); );
$frame->addChild($mapNameButton); $frame->addChild($mapNameButton);
$mapNameButton->setPosition(-$width / 2 + 60, -35); $mapNameButton->setPosition(-$width / 2 + 60, $height * -0.45);
} }
return $frame; return $frame;
@ -269,18 +271,18 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$pagerSize = 9.; $pagerSize = 9.;
$settingHeight = 5.; $settingHeight = 5.;
$labelTextSize = 2; $labelTextSize = 2;
$pageMaxCount = 10; $pageMaxCount = floor(($height * 0.78) / $settingHeight);
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize); $pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize); $pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
@ -290,7 +292,7 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.35, $height * -0.44); $pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1); $pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2); $pageCountLabel->setTextSize(2);
@ -386,19 +388,18 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
// Config // Config
$pagerSize = 9.; $pagerSize = 9.;
$settingHeight = 5.; $settingHeight = 5.;
$pageMaxCount = 13; $pageMaxCount = floor(($height - 10) / $settingHeight);
$posY = 0;
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize); $pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize); $pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
@ -408,20 +409,24 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.35, $height * -0.44, 1); $pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1); $pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2); $pageCountLabel->setTextSize(2);
$paging->setLabel($pageCountLabel); $paging->setLabel($pageCountLabel);
$repositionnedFrame = new Frame();
$frame->addChild($repositionnedFrame);
$repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
$pageFrame = null; $pageFrame = null;
$index = 0; $index = 0;
foreach ($settingClasses as $settingClass) { foreach ($settingClasses as $settingClass) {
if ($index % $pageMaxCount === 0) { if ($index % $pageMaxCount === 0) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $repositionnedFrame->addChild($pageFrame);
$posY = $height * 0.41;
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$index = 1;
} }
$classLabel = new Label_Text(); $classLabel = new Label_Text();
@ -435,15 +440,14 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$pageFrame->addChild($classLabel); $pageFrame->addChild($classLabel);
$classLabel->setHorizontalAlign($classLabel::LEFT); $classLabel->setHorizontalAlign($classLabel::LEFT);
$classLabel->setPosition($width * -0.45, $posY); $classLabel->setPosition(2, $settingHeight * $index * -1);
$classLabel->setSize($width * 0.9, $settingHeight * 0.9); $classLabel->setSize($width - 6, $settingHeight * 0.9);
$classLabel->setStyle($classLabel::STYLE_TextCardSmall); $classLabel->setStyle($classLabel::STYLE_TextCardSmall);
$classLabel->setTextSize(2); $classLabel->setTextSize(2);
$classLabel->setText($className); $classLabel->setText($className);
$classLabel->setTextColor('fff'); $classLabel->setTextColor('fff');
$classLabel->setAction(self::ACTION_PREFIX_SETTINGCLASS . $settingClass); $classLabel->setAction(self::ACTION_PREFIX_SETTINGCLASS . $settingClass);
$posY -= $settingHeight;
$index++; $index++;
} }
@ -525,6 +529,7 @@ class ManiaControlSettings implements ConfiguratorMenu, CallbackListener {
$setting->value = $settingData['Value']; $setting->value = $settingData['Value'];
} }
$this->maniaControl->getSettingManager()->saveSetting($setting); $this->maniaControl->getSettingManager()->saveSetting($setting);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') changed the setting "'. $setting->class . '\\\\' . $setting->setting .'" to "'. $setting->value .'"');
} }
$this->maniaControl->getChat()->sendSuccess('Settings saved!', $player); $this->maniaControl->getChat()->sendSuccess('Settings saved!', $player);

View File

@ -44,6 +44,9 @@ class Database implements TimerListener {
// Enable mysqli Reconnect // Enable mysqli Reconnect
ini_set('mysqli.reconnect', 'on'); ini_set('mysqli.reconnect', 'on');
// Change error report mechanism -> used to set compatibility to php < 8.1
mysqli_report(MYSQLI_REPORT_OFF);
// Open database connection // Open database connection
$this->loadConfig(); $this->loadConfig();
$this->mysqli = @new \mysqli($this->config->host, $this->config->user, $this->config->pass, null, $this->config->port); $this->mysqli = @new \mysqli($this->config->host, $this->config->user, $this->config->pass, null, $this->config->port);
@ -220,7 +223,7 @@ class Database implements TimerListener {
* Check whether the Database Connection is still open * Check whether the Database Connection is still open
*/ */
public function checkConnection() { public function checkConnection() {
if (!$this->getMysqli() || !@$this->getMysqli()->ping()) { if (!$this->getMysqli() || !$this->getMysqli()->query('DO 1')) {
$this->maniaControl->quit('The MySQL Server has gone away!', true); $this->maniaControl->quit('The MySQL Server has gone away!', true);
} }
} }

View File

@ -109,6 +109,59 @@ class AsyncHttpRequest implements UsageInformationAble {
$this->processRequest($request); $this->processRequest($request);
} }
/**
* Carry out a PatchData Request
*/
public function patchData() {
array_push($this->headers, 'Content-Type: ' . $this->contentType);
array_push($this->headers, 'Keep-Alive: timeout=600, max=2000');
array_push($this->headers, 'Connection: Keep-Alive');
array_push($this->headers, 'Expect:');
array_push($this->headers, 'Accept-Charset: utf-8');
$content = $this->content;
if ($this->compression) {
$content = gzencode($this->content);
array_push($this->headers, 'Content-Encoding: gzip');
}
$request = $this->newRequest($this->url, $this->timeout);
$request->getOptions()->set(CURLOPT_CUSTOMREQUEST, 'PATCH')// patch method
->set(CURLOPT_POSTFIELDS, $content)// post content field
->set(CURLOPT_HTTPHEADER, $this->headers) // headers
;
$this->processRequest($request);
}
/**
* Carry out a PutData Request
*/
public function putData() {
array_push($this->headers, 'Content-Type: ' . $this->contentType);
array_push($this->headers, 'Keep-Alive: timeout=600, max=2000');
array_push($this->headers, 'Connection: Keep-Alive');
array_push($this->headers, 'Expect:');
array_push($this->headers, 'Accept-Charset: utf-8');
$content = $this->content;
if ($this->compression) {
$content = gzencode($this->content);
array_push($this->headers, 'Content-Encoding: gzip');
}
$request = $this->newRequest($this->url, $this->timeout);
$request->getOptions()->set(CURLOPT_CUSTOMREQUEST, 'PUT')// patch method
->set(CURLOPT_POSTFIELDS, $content)// put content field
->set(CURLOPT_HTTPHEADER, $this->headers) // headers
;
$this->processRequest($request);
}
/** /**
* Processes the Request * Processes the Request
* *

View File

@ -57,8 +57,9 @@ abstract class FileUtil {
public static function getClearedFileName($fileName) { public static function getClearedFileName($fileName) {
$fileName = Formatter::stripCodes($fileName); $fileName = Formatter::stripCodes($fileName);
$fileName = Formatter::utf8($fileName); $fileName = Formatter::utf8($fileName);
$fileName = preg_replace('/[^0-9A-Za-z\-\+\.\_\ ]/', null, $fileName); $fileName = preg_replace('/[^0-9A-Za-z\-\+\.\_\ ]/', '', $fileName);
$fileName = preg_replace('/ /', '_', $fileName); $fileName = preg_replace('/ /', '_', $fileName);
$fileName = str_replace(["'", "+"], '', $fileName);
return $fileName; return $fileName;
} }

View File

@ -56,7 +56,7 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener,
/* /*
* Constants * Constants
*/ */
const VERSION = '0.256'; const VERSION = '0.258';
const ISTRACKMANIACONTROL = True; const ISTRACKMANIACONTROL = True;
const API_VERSION = '2038-01-19'; const API_VERSION = '2038-01-19';
const MIN_DEDIVERSION = '2020-07-01_00_00'; const MIN_DEDIVERSION = '2020-07-01_00_00';
@ -299,7 +299,6 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener,
} }
// Delete client // Delete client
Connection::delete($this->getClient());
$this->client = null; $this->client = null;
} }
@ -548,7 +547,7 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener,
* @param Player $player * @param Player $player
*/ */
public function commandVersion(array $chatCallback, Player $player) { public function commandVersion(array $chatCallback, Player $player) {
$message = 'This server is using TrackManiaControl v' . ManiaControl::VERSION . '!'; $message = 'This server is using TrackManiaControl v' . ManiaControl::VERSION . ' with PHP '. phpversion() .'!';
$this->getChat()->sendInformation($message, $player); $this->getChat()->sendInformation($message, $player);
} }
@ -652,6 +651,13 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener,
Logger::log('Starting ManiaControl v' . self::VERSION . '!'); Logger::log('Starting ManiaControl v' . self::VERSION . '!');
try { try {
// Manage SIGTERM signal
if (extension_loaded('pcntl')) {
pcntl_signal(SIGTERM, function() {
$this->quit("Stop signal received from the OS.", false);
});
}
// Connect to server // Connect to server
$this->connect(); $this->connect();
@ -715,7 +721,7 @@ class ManiaControl implements CallbackListener, CommandListener, TimerListener,
Logger::log("Connecting to Server at {$serverConfig->host}:{$serverConfig->port}..."); Logger::log("Connecting to Server at {$serverConfig->host}:{$serverConfig->port}...");
try { try {
$this->client = Connection::factory($serverConfig->host, $serverConfig->port, self::SCRIPT_TIMEOUT, $serverConfig->user, $serverConfig->pass, self::API_VERSION); $this->client = new Connection($serverConfig->host, $serverConfig->port, self::SCRIPT_TIMEOUT, $serverConfig->user, $serverConfig->pass, self::API_VERSION);
} catch (TransportException $exception) { } catch (TransportException $exception) {
$message = "Couldn't connect to the server: '{$exception->getMessage()}'"; $message = "Couldn't connect to the server: '{$exception->getMessage()}'";
$this->quit($message, true); $this->quit($message, true);

View File

@ -44,7 +44,7 @@ class MXMapInfo {
} else { } else {
$this->dir = 'maps'; $this->dir = 'maps';
$this->id = $mx->MapID; $this->id = $mx->MapID;
$this->uid = isset($mx->MapUID) ? $mx->MapUID : ''; $this->uid = isset($mx->TrackUID) ? $mx->TrackUID : ''; // TODO: fix when migrating to new api; TrackUID is equal to MapUID
} }
if (!isset($mx->GbxMapName) || $mx->GbxMapName === '?') { if (!isset($mx->GbxMapName) || $mx->GbxMapName === '?') {

View File

@ -71,6 +71,7 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
* @param array $callback * @param array $callback
*/ */
public function handleManialinkPageAnswer(array $callback) { public function handleManialinkPageAnswer(array $callback) {
if (!$this->maniaControl->getMapManager()->getMXManager()->getStatus()) return;
$actionId = $callback[1][2]; $actionId = $callback[1][2];
$actionArray = explode('.', $actionId); $actionArray = explode('.', $actionId);
if (count($actionArray) <= 2) { if (count($actionArray) <= 2) {
@ -101,6 +102,7 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
* @param Player $player * @param Player $player
*/ */
public function showListCommand(array $chatCallback, Player $player) { public function showListCommand(array $chatCallback, Player $player) {
if (!$this->maniaControl->getMapManager()->getMXManager()->getStatus()) return;
$this->mapListShown[$player->login] = true; $this->mapListShown[$player->login] = true;
$params = explode(' ', $chatCallback[1][2]); $params = explode(' ', $chatCallback[1][2]);
$searchString = ''; $searchString = '';
@ -141,6 +143,7 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
* @param string $searchString * @param string $searchString
*/ */
private function getMXMapsAndShowList(Player $player, $author = '', $environment = '', $searchString = '') { private function getMXMapsAndShowList(Player $player, $author = '', $environment = '', $searchString = '') {
if (!$this->maniaControl->getMapManager()->getMXManager()->getStatus()) return;
//TODO do more clean solution //TODO do more clean solution
if($environment == ""){ if($environment == ""){
$titleId = $this->maniaControl->getServer()->titleId; $titleId = $this->maniaControl->getServer()->titleId;
@ -191,6 +194,7 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
* @internal param array $chatCallback * @internal param array $chatCallback
*/ */
private function showManiaExchangeList(array $maps, Player $player) { private function showManiaExchangeList(array $maps, Player $player) {
if (!$this->maniaControl->getMapManager()->getMXManager()->getStatus()) return;
// Start offsets // Start offsets
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth(); $width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight(); $height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
@ -340,6 +344,7 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
* @param $openedWidget * @param $openedWidget
*/ */
public function handleWidgetOpened(Player $player, $openedWidget) { public function handleWidgetOpened(Player $player, $openedWidget) {
if (!$this->maniaControl->getMapManager()->getMXManager()->getStatus()) return;
//unset when another main widget got opened //unset when another main widget got opened
if ($openedWidget !== 'ManiaExchangeList') { if ($openedWidget !== 'ManiaExchangeList') {
unset($this->mapListShown[$player->login]); unset($this->mapListShown[$player->login]);
@ -355,5 +360,4 @@ class ManiaExchangeList implements CallbackListener, ManialinkPageAnswerListener
public function closeWidget(Player $player) { public function closeWidget(Player $player) {
unset($this->mapListShown[$player->login]); unset($this->mapListShown[$player->login]);
} }
} }

View File

@ -23,7 +23,7 @@ class ManiaExchangeManager implements UsageInformationAble {
* Constants * Constants
* @deprecated SEARCH Constants * @deprecated SEARCH Constants
*/ */
//Search orders (prior parameter) https://api.mania-exchange.com/documents/enums#orderings //Search orders (prior parameter) https://api2.mania.exchange/documents/enums#orderings
const SEARCH_ORDER_NONE = -1; const SEARCH_ORDER_NONE = -1;
const SEARCH_ORDER_TRACK_NAME = 0; const SEARCH_ORDER_TRACK_NAME = 0;
const SEARCH_ORDER_AUTHOR = 1; const SEARCH_ORDER_AUTHOR = 1;
@ -54,6 +54,7 @@ class ManiaExchangeManager implements UsageInformationAble {
*/ */
/** @var ManiaControl $maniaControl */ /** @var ManiaControl $maniaControl */
private $maniaControl = null; private $maniaControl = null;
private $enabled = true;
private $mxIdUidVector = array(); private $mxIdUidVector = array();
/** /**
@ -67,6 +68,22 @@ class ManiaExchangeManager implements UsageInformationAble {
//$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MX_KEY, ""); //$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MX_KEY, "");
} }
/**
* Set the status of the plugin
*
* @param bool $status
*/
public function setStatus(bool $status) {
$this->enabled = $status;
}
/**
* Get the status of the plugin
*/
public function getStatus() {
return $this->enabled;
}
/** /**
* Unset Map by Mx Id * Unset Map by Mx Id
* *
@ -84,6 +101,7 @@ class ManiaExchangeManager implements UsageInformationAble {
* @param mixed $maps * @param mixed $maps
*/ */
public function fetchManiaExchangeMapInformation($maps = null) { public function fetchManiaExchangeMapInformation($maps = null) {
if (!$this->enabled) return;
if ($maps) { if ($maps) {
// Fetch Information for a single map // Fetch Information for a single map
$maps = array($maps); $maps = array($maps);
@ -160,7 +178,7 @@ class ManiaExchangeManager implements UsageInformationAble {
* @param string $string * @param string $string
*/ */
public function fetchMaplistByMixedUidIdString($string) { public function fetchMaplistByMixedUidIdString($string) {
if (!$this->enabled) return;
// For TM2020 // For TM2020
if ($this->maniaControl->getServer()->titleId == "Trackmania") { if ($this->maniaControl->getServer()->titleId == "Trackmania") {
// Get Title Prefix // Get Title Prefix
@ -172,7 +190,7 @@ class ManiaExchangeManager implements UsageInformationAble {
} }
// compile search URL // compile search URL
$url = "https://{$titlePrefix}/api/maps/get_map_info/multi/{$string}"; $url = 'https://' . $titlePrefix . "/api/maps/get_map_info/multi/{$string}";
/*if ($key = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MX_KEY)) { /*if ($key = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MX_KEY)) {
$url .= "&key=" . $key; $url .= "&key=" . $key;
@ -217,6 +235,7 @@ class ManiaExchangeManager implements UsageInformationAble {
* @param array $mxMapInfos * @param array $mxMapInfos
*/ */
public function updateMapObjectsWithManiaExchangeIds(array $mxMapInfos) { public function updateMapObjectsWithManiaExchangeIds(array $mxMapInfos) {
if (!$this->enabled) return;
$mysqli = $this->maniaControl->getDatabase()->getMysqli(); $mysqli = $this->maniaControl->getDatabase()->getMysqli();
// Save map data // Save map data
$saveMapQuery = "UPDATE `" . MapManager::TABLE_MAPS . "` $saveMapQuery = "UPDATE `" . MapManager::TABLE_MAPS . "`
@ -269,6 +288,7 @@ class ManiaExchangeManager implements UsageInformationAble {
* @param callable $function * @param callable $function
*/ */
public function fetchMapInfo($mapId, callable $function) { public function fetchMapInfo($mapId, callable $function) {
if (!$this->enabled) return;
// For TM2020 // For TM2020
if ($this->maniaControl->getServer()->titleId == "Trackmania") { if ($this->maniaControl->getServer()->titleId == "Trackmania") {
// Get Title Prefix // Get Title Prefix
@ -280,7 +300,7 @@ class ManiaExchangeManager implements UsageInformationAble {
} }
// compile search URL // compile search URL
$url = "https://{$titlePrefix}/api/maps/get_map_info/multi/{$mapId}"; $url = 'https://' . $titlePrefix . '/api/maps/get_map_info/multi/' . $mapId;
/*if ($key = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MX_KEY)) { /*if ($key = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MX_KEY)) {
$url .= "&key=" . $key; $url .= "&key=" . $key;
@ -335,6 +355,7 @@ class ManiaExchangeManager implements UsageInformationAble {
* @see \ManiaControl\ManiaExchange\ManiaExchangeMapSearch * @see \ManiaControl\ManiaExchange\ManiaExchangeMapSearch
*/ */
public function fetchMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $sortOrder = ManiaExchangeMapSearch::SEARCH_ORDER_UPDATED_NEWEST) { public function fetchMapsAsync(callable $function, $name = '', $author = '', $env = '', $maxMapsReturned = 100, $sortOrder = ManiaExchangeMapSearch::SEARCH_ORDER_UPDATED_NEWEST) {
if (!$this->enabled) return;
$mapSearch = new ManiaExchangeMapSearch($this->maniaControl); $mapSearch = new ManiaExchangeMapSearch($this->maniaControl);
$mapSearch->setMapName($name); $mapSearch->setMapName($name);
$mapSearch->setAuthorName($author); $mapSearch->setAuthorName($author);

View File

@ -18,7 +18,7 @@ use Maniaplanet\DedicatedServer\Xmlrpc\GameModeException;
class ManiaExchangeMapSearch implements UsageInformationAble { class ManiaExchangeMapSearch implements UsageInformationAble {
use UsageInformationTrait; use UsageInformationTrait;
//Search orders (prior parameter) https://api.mania-exchange.com/documents/enums#orderings //Search orders (prior parameter) https://api2.mania.exchange/documents/enums#orderings
const SEARCH_ORDER_NONE = -1; const SEARCH_ORDER_NONE = -1;
const SEARCH_ORDER_TRACK_NAME = 0; const SEARCH_ORDER_TRACK_NAME = 0;
const SEARCH_ORDER_AUTHOR = 1; const SEARCH_ORDER_AUTHOR = 1;
@ -41,7 +41,7 @@ class ManiaExchangeMapSearch implements UsageInformationAble {
const SEARCH_ORDER_ONLINE_RATING_LTH = 26; const SEARCH_ORDER_ONLINE_RATING_LTH = 26;
const SEARCH_ORDER_ONLINE_RATING_HTL = 27; const SEARCH_ORDER_ONLINE_RATING_HTL = 27;
//Special Search Orders (mode parameter): https://api.mania-exchange.com/documents/enums#modes //Special Search Orders (mode parameter): https://api2.mania.exchange/documents/enums#modes
const SEARCH_ORDER_SPECIAL_DEFAULT = 0; const SEARCH_ORDER_SPECIAL_DEFAULT = 0;
const SEARCH_ORDER_SPECIAL_USER_TRACKS = 1; const SEARCH_ORDER_SPECIAL_USER_TRACKS = 1;
const SEARCH_ORDER_SPECIAL_LATEST_TRACKS = 2; const SEARCH_ORDER_SPECIAL_LATEST_TRACKS = 2;
@ -140,6 +140,8 @@ class ManiaExchangeMapSearch implements UsageInformationAble {
* @param callable $function * @param callable $function
*/ */
public function fetchMapsAsync(callable $function) { public function fetchMapsAsync(callable $function) {
if (!$this->maniaControl->getMapManager()->getMXManager()->getStatus()) return;
// compile search URL // compile search URL
$parameters = ""; $parameters = "";

View File

@ -75,7 +75,7 @@ class CustomUIManager implements CallbackListener, TimerListener, UsageInformati
* *
* @param Player $player * @param Player $player
*/ */
public function updateManialink(Player $player = null) { public function updateManialink(?Player $player = null) {
$this->maniaControl->getManialinkManager()->sendManialink($this->customUI, $player); $this->maniaControl->getManialinkManager()->sendManialink($this->customUI, $player);
} }

View File

@ -336,7 +336,7 @@ class ManialinkManager implements ManialinkPageAnswerListener, CallbackListener,
} }
} else { } else {
$emptyManialink = new ManiaLink($manialinkId); $emptyManialink = new ManiaLink($manialinkId);
$this->sendManialink($emptyManialink, $logins); $this->sendManialink($emptyManialink, $logins, 0, false, false);
} }
} }

View File

@ -106,7 +106,7 @@ class StyleManager implements UsageInformationAble {
// Predefine Description Label // Predefine Description Label
$descriptionLabel = new Label(); $descriptionLabel = new Label();
$descriptionLabel->setAlign($descriptionLabel::LEFT, $descriptionLabel::TOP)->setPosition($width * -0.5 + 10, $height * -0.5 + 5)->setZ(1)->setSize($width * 0.7, 4)->setTextSize(2)->setVisible(false); $descriptionLabel->setAlign($descriptionLabel::LEFT, $descriptionLabel::TOP)->setPosition($width * -0.5 + 10, $height * -0.5 + 5)->setZ(1)->setSize($width * 0.7, 4)->setTextSize(1)->setVisible(false);
return $descriptionLabel; return $descriptionLabel;
} }
@ -125,30 +125,36 @@ class StyleManager implements UsageInformationAble {
$frame = new Frame(); $frame = new Frame();
$posX = -$width / 2 + 5;
$label = new Label_Text(); $label = new Label_Text();
$frame->addChild($label); $frame->addChild($label);
$label->setPosition(-$width / 2 + 5, 0); $label->setPosition($posX, 0);
$label->setHorizontalAlign($label::LEFT); $label->setHorizontalAlign($label::LEFT);
$label->setTextSize(1); $label->setTextSize(1);
$label->setText('Search: '); $label->setText('Search: ');
$posX += 10;
$entry = new Entry(); $entry = new Entry();
$frame->addChild($entry); $frame->addChild($entry);
$entry->setStyle(Label_Text::STYLE_TextValueSmall); $entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setHorizontalAlign($entry::LEFT); $entry->setHorizontalAlign($entry::LEFT);
$entry->setPosition(-$width / 2 + 15, 0); $entry->setPosition($posX, 0);
$entry->setTextSize(1); $entry->setTextSize(1);
$entry->setSize($width * 0.28, 4); $entry->setSize($width * 0.28, 4);
$entry->setName('SearchString'); $entry->setName('SearchString');
$entry->setDefault($entryvalue); $entry->setDefault($entryvalue);
$posX += $width * 0.28 + 10;
if ($actionReset) { if ($actionReset) {
$quad = new Quad_Icons64x64_1(); $quad = new Quad_Icons64x64_1();
$frame->addChild($quad); $frame->addChild($quad);
$quad->setSubStyle($quad::SUBSTYLE_QuitRace); $quad->setSubStyle($quad::SUBSTYLE_QuitRace);
$quad->setColorize('aaa'); $quad->setColorize('aaa');
$quad->setSize(5, 5); $quad->setSize(5, 5);
$quad->setPosition(-$width / 2 + 20 + $width * 0.25 - 2, 0); $quad->setPosition($posX - 12, 0);
$quad->setZ(1); $quad->setZ(1);
$quad->setAction($actionReset); $quad->setAction($actionReset);
} }
@ -161,7 +167,9 @@ class StyleManager implements UsageInformationAble {
$actionMapNameSearch $actionMapNameSearch
); );
$frame->addChild($mapNameButton); $frame->addChild($mapNameButton);
$mapNameButton->setX(-$width / 2 + 68); $mapNameButton->setX($posX);
$posX += 20;
//Search for Author //Search for Author
$authorButton = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildRoundTextButton( $authorButton = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildRoundTextButton(
@ -171,7 +179,7 @@ class StyleManager implements UsageInformationAble {
$actionAuthorSearch $actionAuthorSearch
); );
$frame->addChild($authorButton); $frame->addChild($authorButton);
$authorButton->setX(-$width / 2 + 87); $authorButton->setX($posX);
return $frame; return $frame;
} }
@ -237,18 +245,27 @@ class StyleManager implements UsageInformationAble {
$pagerSize = 6.; $pagerSize = 6.;
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.42, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT)->setPosition($width * 0.40, $height * -0.44, 1)->setStyle($pageCountLabel::STYLE_TextTitle1)->setTextSize(1); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(1);
if ($paging) { if ($paging) {
$paging->addButtonControl($pagerNext)->addButtonControl($pagerPrev)->setLabel($pageCountLabel); $paging->addButtonControl($pagerNext);
$paging->addButtonControl($pagerPrev);
$paging->setLabel($pageCountLabel);
} }
} }

View File

@ -2,9 +2,12 @@
namespace ManiaControl\Maps; namespace ManiaControl\Maps;
use finfo;
use ZipArchive;
use FML\Controls\Frame; use FML\Controls\Frame;
use FML\Controls\Label; use FML\Controls\Label;
use FML\Controls\Entry; use FML\Controls\Entry;
use FML\Controls\Labels\Label_Button;
use FML\Controls\Labels\Label_Text; use FML\Controls\Labels\Label_Text;
use FML\Controls\Quads\Quad_BgsPlayerCard; use FML\Controls\Quads\Quad_BgsPlayerCard;
use FML\Controls\Quads\Quad_Icons64x64_1; use FML\Controls\Quads\Quad_Icons64x64_1;
@ -12,6 +15,7 @@ use FML\Controls\Quads\Quad_UIConstruction_Buttons;
use FML\Controls\Quads\Quad_UIConstructionBullet_Buttons; use FML\Controls\Quads\Quad_UIConstructionBullet_Buttons;
use FML\ManiaLink; use FML\ManiaLink;
use FML\Script\Features\Paging; use FML\Script\Features\Paging;
use ManiaControl\Admin\AuthenticationManager;
use ManiaControl\Files\AsyncHttpRequest; use ManiaControl\Files\AsyncHttpRequest;
use ManiaControl\Files\FileUtil; use ManiaControl\Files\FileUtil;
use ManiaControl\Logger; use ManiaControl\Logger;
@ -41,6 +45,7 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
const ACTION_INSPECT_FILE = 'MapsDirBrowser.InspectFile.'; const ACTION_INSPECT_FILE = 'MapsDirBrowser.InspectFile.';
const ACTION_ADD_FILE = 'MapsDirBrowser.AddFile.'; const ACTION_ADD_FILE = 'MapsDirBrowser.AddFile.';
const ACTION_ERASE_FILE = 'MapsDirBrowser.EraseFile.'; const ACTION_ERASE_FILE = 'MapsDirBrowser.EraseFile.';
const ACTION_CREATE_FOLDER = 'MapsDirBrowser.CreateFolder';
const ACTION_DOWNLOAD_FILE = 'MapsDirBrowser.DownloadFile'; const ACTION_DOWNLOAD_FILE = 'MapsDirBrowser.DownloadFile';
const WIDGET_NAME = 'MapsDirBrowser.Widget'; const WIDGET_NAME = 'MapsDirBrowser.Widget';
const CACHE_FOLDER_PATH = 'FolderPath'; const CACHE_FOLDER_PATH = 'FolderPath';
@ -67,6 +72,7 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_INSPECT_FILE), $this, 'handleInspectFile'); $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_ADD_FILE), $this, 'handleAddFile');
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_ERASE_FILE), $this, 'handleEraseFile'); $this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_ERASE_FILE), $this, 'handleEraseFile');
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_CREATE_FOLDER), $this, 'handleCreateFolder');
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_DOWNLOAD_FILE), $this, 'handleDownloadFile'); $this->maniaControl->getManialinkManager()->registerManialinkPageAnswerRegexListener($this->buildActionRegex(self::ACTION_DOWNLOAD_FILE), $this, 'handleDownloadFile');
} }
@ -137,17 +143,31 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth(); $width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight(); $height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
$innerWidth = $width - 2;
$innerHeigth = $height - 27;
$lineHeight = 4.;
$index = 0; $index = 0;
$posY = $height / 2 - 10;
$pageFrame = null; $pageFrame = null;
$pageMaxCount = floor($innerHeigth / 4);
$repositionnedFrame = new Frame();
$frame->addChild($repositionnedFrame);
$repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
$navigateRootQuad = new Quad_Icons64x64_1(); $navigateRootQuad = new Quad_Icons64x64_1();
$frame->addChild($navigateRootQuad); $repositionnedFrame->addChild($navigateRootQuad);
$navigateRootQuad->setPosition($width * -0.47, $height * 0.45)->setSize(4, 4)->setSubStyle($navigateRootQuad::SUBSTYLE_ToolRoot); $navigateRootQuad->setPosition(5, -5);
$navigateRootQuad->setSize(4, 4);
$navigateRootQuad->setSubStyle($navigateRootQuad::SUBSTYLE_ToolRoot);
$navigateUpQuad = new Quad_Icons64x64_1(); $navigateUpQuad = new Quad_Icons64x64_1();
$frame->addChild($navigateUpQuad); $repositionnedFrame->addChild($navigateUpQuad);
$navigateUpQuad->setPosition($width * -0.44, $height * 0.45)->setSize(4, 4)->setSubStyle($navigateUpQuad::SUBSTYLE_ToolUp); $navigateUpQuad->setPosition(9, -5);
$navigateUpQuad->setSize(4, 4);
$navigateUpQuad->setSubStyle($navigateUpQuad::SUBSTYLE_ToolUp);
if (!$isInMapsFolder) { if (!$isInMapsFolder) {
$navigateRootQuad->setAction(self::ACTION_NAVIGATE_ROOT); $navigateRootQuad->setAction(self::ACTION_NAVIGATE_ROOT);
@ -155,111 +175,189 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
} }
$directoryLabel = new Label_Text(); $directoryLabel = new Label_Text();
$frame->addChild($directoryLabel); $repositionnedFrame->addChild($directoryLabel);
$dataFolder = $this->maniaControl->getServer()->getDirectory()->getUserDataFolder(); $dataFolder = $this->maniaControl->getServer()->getDirectory()->getUserDataFolder();
$directoryText = substr($folderPath, strlen($dataFolder)); $directoryText = substr($folderPath, strlen($dataFolder));
$directoryLabel->setPosition($width * -0.41, $height * 0.45)->setSize($width * 0.85, 4)->setHorizontalAlign($directoryLabel::LEFT)->setText($directoryText)->setTextSize(2); $directoryLabel->setPosition(12, -5);
$directoryLabel->setSize($width * 0.85, 4);
$directoryLabel->setHorizontalAlign($directoryLabel::LEFT);
$directoryLabel->setText($directoryText);
$directoryLabel->setTextSize(2);
$tooltipLabel = new Label(); $tooltipLabel = new Label();
$frame->addChild($tooltipLabel); $repositionnedFrame->addChild($tooltipLabel);
$tooltipLabel->setPosition($width * -0.48, $height * -0.44)->setSize($width * 0.8, 5)->setHorizontalAlign($tooltipLabel::LEFT)->setTextSize(1); $tooltipLabel->setPosition(3, $height * -1 + 15);
$tooltipLabel->setSize($width * 0.8, 5);
$tooltipLabel->setHorizontalAlign($tooltipLabel::LEFT);
$tooltipLabel->setTextSize(1);
// Back button
$backButton = new Label_Button();
$repositionnedFrame->addChild($backButton);
$backButton->setStyle($backButton::STYLE_CardMain_Quit);
$backButton->setHorizontalAlign($backButton::LEFT);
$backButton->setScale(0.5);
$backButton->setText('Back');
$backButton->setPosition(3, $height * -1 + 5);
$backButton->setSize(5, 10);
$backButton->setAction(MapCommands::ACTION_OPEN_MAPLIST);
// Create folder button
$label = new Label_Text();
$repositionnedFrame->addChild($label);
$label->setPosition($width - 113, $height * -1 + 10);
$label->setSize(25, 5);
$label->setHorizontalAlign($label::LEFT);
$label->setTextSize(1);
$label->setText('Create folder: ');
$label->setAreaFocusColor("00000000");
$label->setAreaColor("00000000");
$entry = new Entry();
$repositionnedFrame->addChild($entry);
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setHorizontalAlign($entry::LEFT);
$entry->setPosition($width - 95, $height * -1 + 10);
$entry->setTextSize(1);
$entry->setSize(50, 4);
$entry->setName("Name");
//Search for Map-Name
$createFolderButton = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildRoundTextButton(
'Create',
18,
5,
self::ACTION_CREATE_FOLDER
);
$repositionnedFrame->addChild($createFolderButton);
$createFolderButton->setPosition($width - 27 - 18/2, $height * -1 + 10);
// Download button
$label = new Label_Text();
$repositionnedFrame->addChild($label);
$label->setPosition($width - 122, $height * -1 + 5);
$label->setSize(27, 5);
$label->setHorizontalAlign($label::LEFT);
$label->setTextSize(1);
$label->setText('Download from URL: ');
$label->setAreaFocusColor("00000000");
$label->setAreaColor("00000000");
$label->addTooltipLabelFeature($tooltipLabel, 'Support Map.Gbx and Zip files');
$entry = new Entry();
$repositionnedFrame->addChild($entry);
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setHorizontalAlign($entry::LEFT);
$entry->setPosition($width - 95, $height * -1 + 5);
$entry->setTextSize(1);
$entry->setSize(50, 4);
$entry->setName("URL");
//Search for Map-Name
$downloadButton = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildRoundTextButton(
'Download',
18,
5,
self::ACTION_DOWNLOAD_FILE
);
$repositionnedFrame->addChild($downloadButton);
$downloadButton->setPosition($width - 27 - 18/2, $height * -1 + 5);
$mapFiles = $this->scanMapFiles($folderPath); $mapFiles = $this->scanMapFiles($folderPath);
if (is_array($mapFiles)) { if (is_array($mapFiles)) {
if (empty($mapFiles)) { if (empty($mapFiles)) {
$emptyLabel = new Label(); $emptyLabel = new Label();
$frame->addChild($emptyLabel); $repositionnedFrame->addChild($emptyLabel);
$emptyLabel->setY(20)->setTextColor('aaa')->setText('No files found.')->setTranslate(true); $emptyLabel->setPosition($innerWidth * 0.5, $innerHeigth * -0.5);
$emptyLabel->setTextColor('aaa');
$emptyLabel->setText('No files found.');
$emptyLabel->setTranslate(true);
} else { } else {
$canAddMaps = $this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP); $canAddMaps = $this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP);
$canEraseMaps = $this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ERASE_MAP); $canEraseMaps = $this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ERASE_MAP);
$pagesFrame = new Frame();
$repositionnedFrame->addChild($pagesFrame);
$pagesFrame->setPosition(1, -10);
foreach ($mapFiles as $filePath => $fileName) { foreach ($mapFiles as $filePath => $fileName) {
$shortFilePath = substr($filePath, strlen($folderPath)); $shortFilePath = substr($filePath, strlen($folderPath));
if ($index % 15 === 0) { if ($index % $pageMaxCount === 0) {
// New Page // New Page
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $pagesFrame->addChild($pageFrame);
$posY = $height / 2 - 10;
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$index = 1;
} }
// Map Frame // Map Frame
$mapFrame = new Frame(); $mapFrame = new Frame();
$pageFrame->addChild($mapFrame); $pageFrame->addChild($mapFrame);
$mapFrame->setY($posY); $mapFrame->setY($lineHeight * $index * -1);
if ($index % 2 === 0) { if ($index % 2 === 0) {
// Striped background line // Striped background line
$lineQuad = new Quad_BgsPlayerCard(); $lineQuad = new Quad_BgsPlayerCard();
$mapFrame->addChild($lineQuad); $mapFrame->addChild($lineQuad);
$lineQuad->setZ(-1)->setSize($width, 4)->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig); $lineQuad->setX($innerWidth / 2);
$lineQuad->setZ(-1);
$lineQuad->setSize($width, $lineHeight);
$lineQuad->setSubStyle($lineQuad::SUBSTYLE_BgPlayerCardBig);
} }
// File name Label // File name Label
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$mapFrame->addChild($nameLabel); $mapFrame->addChild($nameLabel);
$nameLabel->setX($width * -0.48)->setSize($width * 0.79, 4)->setHorizontalAlign($nameLabel::LEFT)->setStyle($nameLabel::STYLE_TextCardRaceRank)->setTextSize(1)->setText($fileName); $nameLabel->setX(2);
$nameLabel->setSize($innerWidth - 20, $lineHeight);
$nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setStyle($nameLabel::STYLE_TextCardRaceRank);
$nameLabel->setTextSize(1);
$nameLabel->setText($fileName);
if (substr($fileName, -1) === DIRECTORY_SEPARATOR) $nameLabel->setTextPrefix(' ');
if (is_dir($filePath)) { if (is_dir($filePath)) {
// Folder // Folder
$nameLabel->setAction(self::ACTION_OPEN_FOLDER . substr($shortFilePath, 0, -1))->addTooltipLabelFeature($tooltipLabel, 'Open folder ' . $fileName); $nameLabel->setAction(self::ACTION_OPEN_FOLDER . substr($shortFilePath, 0, -1))->addTooltipLabelFeature($tooltipLabel, 'Open folder ' . $fileName);
} else { } else {
// File // File
$nameLabel->setAction(self::ACTION_INSPECT_FILE . $fileName)->addTooltipLabelFeature($tooltipLabel, 'Inspect file ' . $fileName); $nameLabel->setAction(self::ACTION_INSPECT_FILE . base64_encode($fileName))->addTooltipLabelFeature($tooltipLabel, 'Inspect file ' . $fileName);
if ($canAddMaps) { if ($canAddMaps) {
// 'Add' button // 'Add' button
$addButton = new Quad_UIConstructionBullet_Buttons(); $addButton = new Quad_UIConstructionBullet_Buttons();
$mapFrame->addChild($addButton); $mapFrame->addChild($addButton);
$addButton->setX($width * 0.42)->setSize(4, 4)->setSubStyle($addButton::SUBSTYLE_NewBullet)->setAction(self::ACTION_ADD_FILE . $fileName)->addTooltipLabelFeature($tooltipLabel, 'Add map ' . $fileName); $addButton->setX($width - 5);
$addButton->setSize(4, 4);
$addButton->setSubStyle($addButton::SUBSTYLE_NewBullet);
$addButton->setAction(self::ACTION_ADD_FILE . base64_encode($fileName));
$addButton->addTooltipLabelFeature($tooltipLabel, 'Add map ' . $fileName);
} }
if ($canEraseMaps) { if ($canEraseMaps) {
// 'Erase' button // 'Erase' button
$eraseButton = new Quad_UIConstruction_Buttons(); $eraseButton = new Quad_UIConstruction_Buttons();
$mapFrame->addChild($eraseButton); $mapFrame->addChild($eraseButton);
$eraseButton->setX($width * 0.46)->setSize(4, 4)->setSubStyle($eraseButton::SUBSTYLE_Erase)->setAction(self::ACTION_ERASE_FILE . $fileName)->addTooltipLabelFeature($tooltipLabel, 'Erase file ' . $fileName); $eraseButton->setX($width - 10);
$eraseButton->setSize(4, 4);
$eraseButton->setSubStyle($eraseButton::SUBSTYLE_Erase);
$eraseButton->setAction(self::ACTION_ERASE_FILE . base64_encode($fileName));
$eraseButton->addTooltipLabelFeature($tooltipLabel, 'Erase file ' . $fileName);
} }
} }
$posY -= 4;
$index++; $index++;
} }
} }
$label = new Label_Text();
$frame->addChild($label);
$label->setPosition(-$width / 2 + 5, -$height / 2 + 8.5);
$label->setHorizontalAlign($label::LEFT);
$label->setTextSize(1);
$label->setText('Download from URL: ');
$entry = new Entry();
$frame->addChild($entry);
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setHorizontalAlign($entry::LEFT);
$entry->setPosition(-$width / 2 + 35, -$height / 2 + 8.5);
$entry->setTextSize(1);
$entry->setSize($width * 0.35, 4);
$entry->setName('SearchString');
//Search for Map-Name
$mapNameButton = $this->maniaControl->getManialinkManager()->getElementBuilder()->buildRoundTextButton(
'Download',
18,
5,
self::ACTION_DOWNLOAD_FILE
);
$frame->addChild($mapNameButton);
$mapNameButton->setPosition(-$width / 2 + 100, -$height / 2 + 8.5);
} else { } else {
$errorLabel = new Label(); $errorLabel = new Label();
$frame->addChild($errorLabel); $repositionnedFrame->addChild($errorLabel);
$errorLabel->setY(20)->setTextColor('f30')->setText('No access to the directory.')->setTranslate(true); $errorLabel->setPosition($innerWidth * 0.5, $innerHeigth * -0.5);
$errorLabel->setTextColor('f30');
$errorLabel->setText('No access to the directory.');
$errorLabel->setTranslate(true);
} }
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, self::WIDGET_NAME); $this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, self::WIDGET_NAME);
@ -295,6 +393,15 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
} }
} }
} }
uasort($mapFiles, function ($a, $b) {
$aIsDir = (substr($a, -1) === DIRECTORY_SEPARATOR);
$bIsDir = (substr($b, -1) === DIRECTORY_SEPARATOR);
if ($aIsDir && !$bIsDir) return -1;
else if (!$aIsDir && $bIsDir) return 1;
return 0;
});
return $mapFiles; return $mapFiles;
} }
@ -351,9 +458,23 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
*/ */
public function handleInspectFile(array $actionCallback, Player $player) { public function handleInspectFile(array $actionCallback, Player $player) {
$actionName = $actionCallback[1][2]; $actionName = $actionCallback[1][2];
$fileName = substr($actionName, strlen(self::ACTION_INSPECT_FILE)); $fileName = base64_decode(substr($actionName, strlen(self::ACTION_INSPECT_FILE)));
// TODO: show inspect file view $folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
var_dump($fileName); $filePath = $folderPath . $fileName;
$mapsFolder = $this->maniaControl->getServer()->getDirectory()->getMapsFolder();
$relativeFilePath = substr($filePath, strlen($mapsFolder));
try {
$message = '';
$infos = $this->maniaControl->getClient()->getMapInfo($relativeFilePath);
foreach ($infos as $key => $value) {
$message .= '$<$0c0' . $key .':$> '. $value . PHP_EOL;
}
$this->maniaControl->getChat()->sendChat($message, $player->login, false);
} catch (\Throwable $th) {
$this->maniaControl->getChat()->sendError("can't fetch map info: ". $th->getMessage(), $player->login);
}
} }
/** /**
@ -363,8 +484,13 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
* @param Player $player * @param Player $player
*/ */
public function handleAddFile(array $actionCallback, Player $player) { public function handleAddFile(array $actionCallback, Player $player) {
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)) {
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
return;
}
$actionName = $actionCallback[1][2]; $actionName = $actionCallback[1][2];
$fileName = substr($actionName, strlen(self::ACTION_ADD_FILE)); $fileName = base64_decode(substr($actionName, strlen(self::ACTION_ADD_FILE)));
$folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH); $folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
$filePath = $folderPath . $fileName; $filePath = $folderPath . $fileName;
@ -409,7 +535,7 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
$map $map
); );
$this->maniaControl->getChat()->sendSuccess($message); $this->maniaControl->getChat()->sendSuccess($message);
Logger::logInfo($message, true); Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') added the map file "'. $filePath .'"');
// Queue requested Map // Queue requested Map
$this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($player, $map); $this->maniaControl->getMapManager()->getMapQueue()->addMapToMapQueue($player, $map);
@ -422,16 +548,33 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
* @param Player $player * @param Player $player
*/ */
public function handleEraseFile(array $actionCallback, Player $player) { public function handleEraseFile(array $actionCallback, Player $player) {
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ERASE_MAP)) {
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
return;
}
$actionName = $actionCallback[1][2]; $actionName = $actionCallback[1][2];
$fileName = substr($actionName, strlen(self::ACTION_ERASE_FILE)); $fileName = base64_decode(substr($actionName, strlen(self::ACTION_ERASE_FILE)));
$folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH); $folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
$filePath = $folderPath . $fileName; $filePath = $folderPath . $fileName;
$maps = $this->maniaControl->getMapManager()->getMaps();
$mapsFolder = $this->maniaControl->getServer()->getDirectory()->getMapsFolder();
$filteredMaps = array_filter($maps, function ($item) use ($mapsFolder, $filePath) {
return ($mapsFolder . $item->fileName === $filePath);
});
foreach ($filteredMaps as $map) {
Logger::log('Map "'. $filePath .'" loaded by the server, removing it from the playlist before erasing the file');
$this->maniaControl->getMapManager()->removeMap($player, $map->uid);
}
if (@unlink($filePath)) { if (@unlink($filePath)) {
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
'Erased %s!', 'Erased %s!',
$fileName $fileName
); );
$this->maniaControl->getChat()->sendSuccess($message, $player); $this->maniaControl->getChat()->sendSuccess($message, $player);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') erased the map file "'. $filePath .'"');
$this->showManiaLink($player); $this->showManiaLink($player);
} else { } else {
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
@ -442,7 +585,38 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
} }
} }
/**
* Handle 'CreateFolder' page action
*
* @param array $actionCallback
* @param Player $player
*/
public function handleCreateFolder(array $actionCallback, Player $player) {
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)) {
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
return;
}
$name = trim($actionCallback[1][3][0]["Value"]);
var_dump($actionCallback);
if ($name === "") return;
$folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
if (mkdir($folderPath . $name, 755, true)) {
$message = "Successfully created directory ". $name;
$this->maniaControl->getChat()->sendSuccess($message, $player);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') created the folder "'. $folderPath .'"');
$this->showManiaLink($player, $name);
} else {
$message = "Failed to create directory ". $name;
$this->maniaControl->getChat()->sendError($message, $player);
Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error when creating the folder "'. $folderPath .'".');
$this->showManiaLink($player);
}
}
/** /**
* Handle 'handleDownloadFile' page action * Handle 'handleDownloadFile' page action
@ -451,7 +625,8 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
* @param Player $player * @param Player $player
*/ */
public function handleDownloadFile(array $actionCallback, Player $player) { public function handleDownloadFile(array $actionCallback, Player $player) {
$url = trim($actionCallback[1][3][0]["Value"]); $url = trim($actionCallback[1][3][1]["Value"]);
if ($url === "") return;
$folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH); $folderPath = $player->getCache($this, self::CACHE_FOLDER_PATH);
if (filter_var($url, FILTER_VALIDATE_URL)) { if (filter_var($url, FILTER_VALIDATE_URL)) {
@ -460,11 +635,37 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
if (!$file || $error) { if (!$file || $error) {
$message = "Impossible to download the file: " . $error; $message = "Impossible to download the file: " . $error;
$this->maniaControl->getChat()->sendError($message, $player); $this->maniaControl->getChat()->sendError($message, $player);
Logger::logError($message); Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error during the download of the zip file "'. $url .'": '. $error);
return; return;
} }
$filePath = ""; $filePath = "";
$finfo = new finfo(FILEINFO_MIME_TYPE);
if ($finfo->buffer($file) === "application/zip") {
$zip = new ZipArchive();
// Create a temporary file
$tempFile = tempnam(sys_get_temp_dir(), 'zip');
file_put_contents($tempFile, $file);
$open = $zip->open($tempFile);
if ($open === true) {
$zip->extractTo($folderPath);
$zip->close();
$message = "Successfully extracted zip archive from ". $url;
$this->maniaControl->getChat()->sendSuccess($message, $player);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') downloaded the zip file "'. $url .'"');
} else {
$message = "Cannot extract archive from ". $url;
$this->maniaControl->getChat()->sendError($message, $player);
Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error when downloading the zip file "'. $url .'": Cannot extract the archive');
}
// Clean up the temporary file
unlink($tempFile);
} else {
$fileName = "";
$contentdispositionheader = ""; $contentdispositionheader = "";
foreach ($headers as $key => $value) { foreach ($headers as $key => $value) {
if (strtolower($key) === "content-disposition") { if (strtolower($key) === "content-disposition") {
@ -493,44 +694,44 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
$attributes[trim($key)] = trim($value); $attributes[trim($key)] = trim($value);
} }
$attrNames = ['filename*' => true, 'filename' => false]; $fileName = null;
$filename = null;
$isUtf8 = false; if (array_key_exists('filename*', $attributes)) {
foreach ($attrNames as $attrName => $utf8) { $fileName = trim($attributes['filename*']);
if (!empty($attributes[$attrName])) {
$filename = trim($attributes[$attrName]); // remove prefix if needed
$isUtf8 = $utf8; if (strpos(strtolower($fileName), "utf-8''") === 0) {
break; $fileName = substr($fileName, strlen("utf-8''"));
} }
} else if (array_key_exists('filename', $attributes)) {
$fileName = trim($attributes['filename']);
} }
if ($filename !== null) { if ($fileName !== null) {
if ($isUtf8 && strpos($filename, "utf-8''") === 0 && $filename = substr($filename, strlen("utf-8''"))) { if (substr($fileName, 0, 1) === '"' && substr($fileName, -1, 1) === '"') {
$filePath = $folderPath . rawurldecode($filename); $fileName = substr($fileName, 1, -1);
}
if (substr($filename, 0, 1) === '"' && substr($filename, -1, 1) === '"') {
$filePath = $folderPath . substr($filename, 1, -1);
} else {
$filePath = $folderPath . $filename;
} }
$filePath = $folderPath . FileUtil::getClearedFileName($fileName);
} }
} }
if (!$this->isMapFileName($filePath)) { if (!$this->isMapFileName($filePath)) {
$message = "File is not a map: " . $filename; $message = "File is not a map: " . $fileName;
$this->maniaControl->getChat()->sendError($message, $player); $this->maniaControl->getChat()->sendError($message, $player);
Logger::logError($message); Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error when downloadeding the map file "'. $fileName .'": File is not a map');
return; return;
} }
} else { } else {
$path = parse_url($url, PHP_URL_PATH); $path = parse_url($url, PHP_URL_PATH);
// extracted basename // extracted basename
$filePath = $folderPath . basename($path); $fileName = basename($path);
if (!$this->isMapFileName($filePath)) { if (!$this->isMapFileName($fileName)) {
$filePath .= ".Map.Gbx"; $fileName .= ".Map.Gbx";
} }
$filePath = $folderPath . $fileName;
} }
if ($filePath != "") { if ($filePath != "") {
@ -543,13 +744,19 @@ class DirectoryBrowser implements ManialinkPageAnswerListener {
} }
$bytes = file_put_contents($filePath, $file); $bytes = file_put_contents($filePath, $file);
if (!$bytes || $bytes <= 0) { if (!$bytes || $bytes <= 0) {
$message = "Impossible to determine filename"; $message = "Failed to write file " . $filePath;
$this->maniaControl->getChat()->sendError($message, $player); $this->maniaControl->getChat()->sendError($message, $player);
Logger::logError($message); Logger::logError(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') encountered an error when downloadeding the map file "'. $fileName .'": Failed to write the file');
return; return;
} }
$message = "Successfully downloaded the map ". $fileName;
$this->maniaControl->getChat()->sendSuccess($message, $player);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') downloaded the map file "'. $filePath .'"');
} }
$this->showManiaLink($player, $folderPath); }
$this->showManiaLink($player);
}); });
$asyncHttpRequest->getData(); $asyncHttpRequest->getData();

View File

@ -8,6 +8,7 @@ use FML\Controls\Quads\Quad_UIConstruction_Buttons;
use ManiaControl\Admin\AuthenticationManager; use ManiaControl\Admin\AuthenticationManager;
use ManiaControl\Callbacks\CallbackListener; use ManiaControl\Callbacks\CallbackListener;
use ManiaControl\Callbacks\CallbackManager; use ManiaControl\Callbacks\CallbackManager;
use ManiaControl\Callbacks\Callbacks;
use ManiaControl\Commands\CommandListener; use ManiaControl\Commands\CommandListener;
use ManiaControl\Logger; use ManiaControl\Logger;
use ManiaControl\ManiaControl; use ManiaControl\ManiaControl;
@ -49,7 +50,6 @@ class MapCommands implements CommandListener, ManialinkPageAnswerListener, Callb
*/ */
public function __construct(ManiaControl $maniaControl) { public function __construct(ManiaControl $maniaControl) {
$this->maniaControl = $maniaControl; $this->maniaControl = $maniaControl;
$this->initActionsMenuButtons();
// Admin commands // Admin commands
$this->maniaControl->getCommandManager()->registerCommandListener(array('nextmap', 'next', 'skip'), $this, 'command_NextMap', true, 'Skips to the next map.'); $this->maniaControl->getCommandManager()->registerCommandListener(array('nextmap', 'next', 'skip'), $this, 'command_NextMap', true, 'Skips to the next map.');
@ -68,6 +68,7 @@ class MapCommands implements CommandListener, ManialinkPageAnswerListener, Callb
$this->maniaControl->getCommandManager()->registerCommandListener(array('xmaps', 'xlist'), $this, 'command_xList', false, 'Shows maps from ManiaExchange.'); $this->maniaControl->getCommandManager()->registerCommandListener(array('xmaps', 'xlist'), $this, 'command_xList', false, 'Shows maps from ManiaExchange.');
// Callbacks // Callbacks
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer'); $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_XLIST, $this, 'command_xList');
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_OPEN_MAPLIST, $this, 'command_List'); $this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_OPEN_MAPLIST, $this, 'command_List');
@ -75,16 +76,22 @@ class MapCommands implements CommandListener, ManialinkPageAnswerListener, Callb
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SKIP_MAP, $this, 'command_NextMap'); $this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_SKIP_MAP, $this, 'command_NextMap');
} }
public function handleAfterInit() {
$this->initActionsMenuButtons();
}
/** /**
* Add all Actions Menu Buttons * Add all Actions Menu Buttons
*/ */
private function initActionsMenuButtons() { private function initActionsMenuButtons() {
// Menu Open xList // Menu Open xList
if ($this->maniaControl->getMapManager()->getMXManager()->getStatus()) {
$itemQuad = new Quad(); $itemQuad = new Quad();
$itemQuad->setImageUrl($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON)); $itemQuad->setImageUrl($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON));
$itemQuad->setImageFocusUrl($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_MOVER)); $itemQuad->setImageFocusUrl($this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_MOVER));
$itemQuad->setAction(self::ACTION_OPEN_XLIST); $itemQuad->setAction(self::ACTION_OPEN_XLIST);
$this->maniaControl->getActionsMenu()->addPlayerMenuItem($itemQuad, 5, 'Open MX List'); $this->maniaControl->getActionsMenu()->addPlayerMenuItem($itemQuad, 5, 'Open MX List');
}
// Menu Open List // Menu Open List
$itemQuad = new Quad_Icons64x64_1(); $itemQuad = new Quad_Icons64x64_1();
@ -207,7 +214,7 @@ class MapCommands implements CommandListener, ManialinkPageAnswerListener, Callb
return; return;
} }
$params = explode(' ', $chatCallback[1][2], 2); $params = explode(' ', trim($chatCallback[1][2]), 2);
if (count($params) < 2) { if (count($params) < 2) {
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
'Usage example: %s', 'Usage example: %s',

View File

@ -13,6 +13,7 @@ use FML\Controls\Quads\Quad_Icons64x64_1;
use FML\Controls\Quads\Quad_UIConstruction_Buttons; use FML\Controls\Quads\Quad_UIConstruction_Buttons;
use FML\ManiaLink; use FML\ManiaLink;
use FML\Script\Features\Paging; use FML\Script\Features\Paging;
use ManiaControl\Admin\AuthenticationManager;
use ManiaControl\Callbacks\CallbackListener; use ManiaControl\Callbacks\CallbackListener;
use ManiaControl\Callbacks\CallbackManager; use ManiaControl\Callbacks\CallbackManager;
use ManiaControl\Callbacks\Callbacks; use ManiaControl\Callbacks\Callbacks;
@ -55,11 +56,11 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
const ACTION_SEARCH_MAP_NAME = 'MapList.SearchMapName'; const ACTION_SEARCH_MAP_NAME = 'MapList.SearchMapName';
const ACTION_SEARCH_AUTHOR = 'MapList.SearchAuthor'; const ACTION_SEARCH_AUTHOR = 'MapList.SearchAuthor';
const ACTION_RESET = 'MapList.ResetMapList'; const ACTION_RESET = 'MapList.ResetMapList';
const MAX_MAPS_PER_PAGE = 13;
const MAX_PAGES_PER_CHUNK = 2; const MAX_PAGES_PER_CHUNK = 2;
const DEFAULT_CUSTOM_VOTE_PLUGIN = 'MCTeam\CustomVotesPlugin'; const DEFAULT_CUSTOM_VOTE_PLUGIN = 'MCTeam\CustomVotesPlugin';
const CACHE_CURRENT_PAGE = 'CurrentPage'; const CACHE_CURRENT_PAGE = 'CurrentPage';
const WIDGET_NAME = 'MapList'; const WIDGET_NAME = 'MapList';
const SETTING_PERMISSION_MAPLIST = 'Show the Map List';
/* /*
* Private properties * Private properties
@ -75,6 +76,9 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
public function __construct(ManiaControl $maniaControl) { public function __construct(ManiaControl $maniaControl) {
$this->maniaControl = $maniaControl; $this->maniaControl = $maniaControl;
// Permissions
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_MAPLIST, AuthenticationManager::AUTH_LEVEL_PLAYER, AuthenticationManager::AUTH_LEVEL_PLAYER);
// Callbacks // Callbacks
$this->maniaControl->getCallbackManager()->registerCallbackListener(ManialinkManager::CB_MAIN_WINDOW_CLOSED, $this, 'closeWidget'); $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(ManialinkManager::CB_MAIN_WINDOW_OPENED, $this, 'handleWidgetOpened');
@ -111,6 +115,8 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
*/ */
public function checkUpdates(array $chatCallback, Player $player) { public function checkUpdates(array $chatCallback, Player $player) {
// Update Mx Infos // Update Mx Infos
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_CHECK_UPDATE)) return;
$this->maniaControl->getMapManager()->getMXManager()->fetchManiaExchangeMapInformation(); $this->maniaControl->getMapManager()->getMXManager()->fetchManiaExchangeMapInformation();
// Reshow the Maplist // Reshow the Maplist
@ -125,9 +131,11 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
* @param int $pageIndex * @param int $pageIndex
*/ */
public function showMapList(Player $player, $mapList = null, $pageIndex = -1, $entryvalue = "") { public function showMapList(Player $player, $mapList = null, $pageIndex = -1, $entryvalue = "") {
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_MAPLIST)) return;
$width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth(); $width = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsWidth();
$height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight(); $height = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
$buttonY = -$height / 2 + 9; $buttonY = $height * -0.5 + 5;
if ($pageIndex < 0) { if ($pageIndex < 0) {
$pageIndex = (int) $player->getCache($this, self::CACHE_CURRENT_PAGE); $pageIndex = (int) $player->getCache($this, self::CACHE_CURRENT_PAGE);
@ -137,15 +145,16 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$chunkIndex = $this->getChunkIndexFromPageNumber($pageIndex); $chunkIndex = $this->getChunkIndexFromPageNumber($pageIndex);
$mapsBeginIndex = $this->getChunkMapsBeginIndex($chunkIndex); $mapsBeginIndex = $this->getChunkMapsBeginIndex($chunkIndex);
$pageMaxCount = $this->getMapPerPage();
// Get Maps // Get Maps
if (!is_array($mapList)) { if (!is_array($mapList)) {
$mapList = $this->maniaControl->getMapManager()->getMaps(); $mapList = $this->maniaControl->getMapManager()->getMaps();
} }
$mapList = array_slice($mapList, $mapsBeginIndex, self::MAX_PAGES_PER_CHUNK * self::MAX_MAPS_PER_PAGE); $mapList = array_slice($mapList, $mapsBeginIndex, self::MAX_PAGES_PER_CHUNK * $pageMaxCount);
$totalMapsCount = $this->maniaControl->getMapManager()->getMapsCount(); $totalMapsCount = $this->maniaControl->getMapManager()->getMapsCount();
$pagesCount = ceil($totalMapsCount / self::MAX_MAPS_PER_PAGE); $pagesCount = ceil($totalMapsCount / $pageMaxCount);
// Create ManiaLink // Create ManiaLink
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID); $maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
@ -169,7 +178,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
self::ACTION_CLEAR_MAPQUEUE self::ACTION_CLEAR_MAPQUEUE
); );
$frame->addChild($clearMapQueueButton); $frame->addChild($clearMapQueueButton);
$clearMapQueueButton->setPosition($width/2 - 5 - 30/2, $buttonY); $clearMapQueueButton->setPosition($width * 0.5 - 30/2 - 27, $buttonY);
} }
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_CHECK_UPDATE)) { if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_CHECK_UPDATE)) {
@ -181,7 +190,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_GREEN) $this->maniaControl->getManialinkManager()->getIconManager()->getIcon(IconManager::MX_ICON_GREEN)
); );
$frame->addChild($mxCheckForUpdatesButton); $frame->addChild($mxCheckForUpdatesButton);
$mxCheckForUpdatesButton->setPosition($width/2 - 5 - 30 - 5 - 36/2, $buttonY); $mxCheckForUpdatesButton->setPosition($width * 0.5 - 36/2 - 57, $buttonY);
} }
if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)) { if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_ADD_MAP)) {
@ -192,7 +201,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
DirectoryBrowser::ACTION_SHOW DirectoryBrowser::ACTION_SHOW
); );
$frame->addChild($browserButton); $frame->addChild($browserButton);
$browserButton->setPosition(-$width/2 + 5 + 36/2, $buttonY); $browserButton->setPosition($width * -0.5 + 36 / 2 + 5, $buttonY);
} }
// Headline // Headline
@ -205,7 +214,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$labelLine->addLabelEntryText('Id', $posX + 5); $labelLine->addLabelEntryText('Id', $posX + 5);
$labelLine->addLabelEntryText('Mx Id', $posX + 10); $labelLine->addLabelEntryText('Mx Id', $posX + 10);
$labelLine->addLabelEntryText('Map Name', $posX + 20); $labelLine->addLabelEntryText('Map Name', $posX + 20);
$labelLine->addLabelEntryText('Author', $posX + 68); $labelLine->addLabelEntryText('Author', $width / 2 - 56);
$labelLine->addLabelEntryText('Actions', $width / 2 - 16); $labelLine->addLabelEntryText('Actions', $width / 2 - 16);
$labelLine->setY(-7); $labelLine->setY(-7);
$labelLine->render(); $labelLine->render();
@ -215,6 +224,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
// Predefine description Label // Predefine description Label
$descriptionLabel = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultDescriptionLabel(); $descriptionLabel = $this->maniaControl->getManialinkManager()->getStyleManager()->getDefaultDescriptionLabel();
$descriptionLabel->setY($height * -0.5 + 12);
$frame->addChild($descriptionLabel); $frame->addChild($descriptionLabel);
$queuedMaps = $this->maniaControl->getMapManager()->getMapQueue()->getQueuedMapsRanking(); $queuedMaps = $this->maniaControl->getMapManager()->getMapQueue()->getQueuedMapsRanking();
@ -235,7 +245,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
foreach ($mapList as $map) { foreach ($mapList as $map) {
/** @var Map $map */ /** @var Map $map */
if ($index % self::MAX_MAPS_PER_PAGE === 0) { if ($index % $pageMaxCount === 0) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $frame->addChild($pageFrame);
$posY = $height / 2 - 16; $posY = $height / 2 - 16;
@ -275,7 +285,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$mxQuad->setSize(3, 3); $mxQuad->setSize(3, 3);
$mxQuad->setImageUrl($mxIcon); $mxQuad->setImageUrl($mxIcon);
$mxQuad->setImageFocusUrl($mxIconHover); $mxQuad->setImageFocusUrl($mxIconHover);
$mxQuad->setX($posX + 65); $mxQuad->setX($width / 2 - 63);
$mxQuad->setUrl($map->mx->pageurl); $mxQuad->setUrl($map->mx->pageurl);
$mxQuad->setZ(0.01); $mxQuad->setZ(0.01);
$description = 'View ' . $map->getEscapedName() . ' on Mania-Exchange'; $description = 'View ' . $map->getEscapedName() . ' on Mania-Exchange';
@ -287,7 +297,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$mxQuad->setSize(3, 3); $mxQuad->setSize(3, 3);
$mxQuad->setImageUrl($mxIconGreen); $mxQuad->setImageUrl($mxIconGreen);
$mxQuad->setImageFocusUrl($mxIconGreenHover); $mxQuad->setImageFocusUrl($mxIconGreenHover);
$mxQuad->setX($posX + 62); $mxQuad->setX($width / 2 - 60);
$mxQuad->setUrl($map->mx->pageurl); $mxQuad->setUrl($map->mx->pageurl);
$mxQuad->setZ(0.01); $mxQuad->setZ(0.01);
$description = 'Update for ' . $map->getEscapedName() . ' available on Mania-Exchange!'; $description = 'Update for ' . $map->getEscapedName() . ' available on Mania-Exchange!';
@ -304,12 +314,12 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$labelLine = new LabelLine($mapFrame); $labelLine = new LabelLine($mapFrame);
$labelLine->addLabelEntryText($mapListId, $posX + 5, 5); $labelLine->addLabelEntryText($mapListId, $posX + 5, 5);
$labelLine->addLabelEntryText($mxId, $posX + 10, 10); $labelLine->addLabelEntryText($mxId, $posX + 10, 10);
$labelLine->addLabelEntryText(Formatter::stripDirtyCodes($map->name), $posX + 20, 42); $labelLine->addLabelEntryText(Formatter::stripDirtyCodes($map->name), $posX + 20, $width - 20 - 56 - 5);
$label = new Label_Text(); $label = new Label_Text();
$mapFrame->addChild($label); $mapFrame->addChild($label);
$label->setText($map->authorNick); $label->setText($map->authorNick);
$label->setX($posX + 68); $label->setX($width / 2 - 56);
$label->setSize(47, 0); $label->setSize(47, 0);
$label->setAction(MapCommands::ACTION_SHOW_AUTHOR . $map->authorLogin); $label->setAction(MapCommands::ACTION_SHOW_AUTHOR . $map->authorLogin);
$description = 'Click to checkout all maps by $<' . $map->authorLogin . '$>!'; $description = 'Click to checkout all maps by $<' . $map->authorLogin . '$>!';
@ -340,7 +350,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$description = $map->getEscapedName() . ' is on Map-Queue Position: ' . $queuedMaps[$map->uid]; $description = $map->getEscapedName() . ' is on Map-Queue Position: ' . $queuedMaps[$map->uid];
$label->addTooltipLabelFeature($descriptionLabel, $description); $label->addTooltipLabelFeature($descriptionLabel, $description);
} }
} else { } else if ($this->maniaControl->getAuthenticationManager()->checkPermission($player, MapQueue::SETTING_PERMISSION_ADD_TO_QUEUE)) {
// Map-Queue-Map-Button // Map-Queue-Map-Button
$queueLabel = new Label_Button(); $queueLabel = new Label_Button();
$mapFrame->addChild($queueLabel); $mapFrame->addChild($queueLabel);
@ -445,6 +455,16 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, self::WIDGET_NAME); $this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, self::WIDGET_NAME);
} }
/**
* Get number of maps per page
*
* @return int
*/
public function getMapPerPage() {
$pageheight = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
return floor(($pageheight - 26) / 4);
}
/** /**
* Get the Chunk Index with the given Page Index * Get the Chunk Index with the given Page Index
* *
@ -453,7 +473,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
*/ */
private function getChunkIndexFromPageNumber($pageIndex) { private function getChunkIndexFromPageNumber($pageIndex) {
$mapsCount = $this->maniaControl->getMapManager()->getMapsCount(); $mapsCount = $this->maniaControl->getMapManager()->getMapsCount();
$pagesCount = ceil($mapsCount / self::MAX_MAPS_PER_PAGE); $pagesCount = ceil($mapsCount / $this->getMapPerPage());
if ($pageIndex > $pagesCount - 1) { if ($pageIndex > $pagesCount - 1) {
$pageIndex = $pagesCount - 1; $pageIndex = $pagesCount - 1;
} }
@ -467,7 +487,7 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
* @return int * @return int
*/ */
private function getChunkMapsBeginIndex($chunkIndex) { private function getChunkMapsBeginIndex($chunkIndex) {
return $chunkIndex * self::MAX_PAGES_PER_CHUNK * self::MAX_MAPS_PER_PAGE; return $chunkIndex * self::MAX_PAGES_PER_CHUNK * $this->getMapPerPage();
} }
/** /**
@ -584,6 +604,8 @@ class MapList implements ManialinkPageAnswerListener, CallbackListener {
} }
break; break;
case self::ACTION_SWITCH_MAP: case self::ACTION_SWITCH_MAP:
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, MapManager::SETTING_PERMISSION_SKIP_MAP)) return;
// Don't queue on Map-Change // Don't queue on Map-Change
$this->maniaControl->getMapManager()->getMapQueue()->dontQueueNextMapChange(); $this->maniaControl->getMapManager()->getMapQueue()->dontQueueNextMapChange();
try { try {

View File

@ -19,6 +19,8 @@ use ManiaControl\ManiaExchange\ManiaExchangeList;
use ManiaControl\ManiaExchange\ManiaExchangeManager; use ManiaControl\ManiaExchange\ManiaExchangeManager;
use ManiaControl\ManiaExchange\MXMapInfo; use ManiaControl\ManiaExchange\MXMapInfo;
use ManiaControl\Players\Player; use ManiaControl\Players\Player;
use ManiaControl\Settings\Setting;
use ManiaControl\Settings\SettingManager;
use ManiaControl\Utils\Formatter; use ManiaControl\Utils\Formatter;
use Maniaplanet\DedicatedServer\InvalidArgumentException; use Maniaplanet\DedicatedServer\InvalidArgumentException;
use Maniaplanet\DedicatedServer\Xmlrpc\AlreadyInListException; use Maniaplanet\DedicatedServer\Xmlrpc\AlreadyInListException;
@ -56,6 +58,7 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
const SETTING_AUTOSAVE_MAPLIST = 'Autosave Maplist file'; const SETTING_AUTOSAVE_MAPLIST = 'Autosave Maplist file';
const SETTING_MAPLIST_FILE = 'File to write Maplist in'; 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'; const SETTING_WRITE_OWN_MAPLIST_FILE = 'Write a own Maplist File for every Server called serverlogin.txt';
const SETTING_ENABLE_MX = 'Enable MX features';
const SEARCH_BY_AUTHOR = 'Author'; const SEARCH_BY_AUTHOR = 'Author';
const SEARCH_BY_MAP_NAME = 'Mapname'; const SEARCH_BY_MAP_NAME = 'Mapname';
@ -116,6 +119,7 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
// Callbacks // Callbacks
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit'); $this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::ONINIT, $this, 'handleOnInit');
$this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit'); $this->maniaControl->getCallbackManager()->registerCallbackListener(Callbacks::AFTERINIT, $this, 'handleAfterInit');
$this->maniaControl->getCallbackManager()->registerCallbackListener(SettingManager::CB_SETTING_CHANGED, $this, 'updateSettings');
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_MAPLISTMODIFIED, $this, 'mapsModified'); $this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_MAPLISTMODIFIED, $this, 'mapsModified');
// Permissions // Permissions
@ -131,6 +135,9 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_AUTOSAVE_MAPLIST, true); $this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_AUTOSAVE_MAPLIST, true);
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAPLIST_FILE, "MatchSettings/tracklist.txt"); $this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_MAPLIST_FILE, "MatchSettings/tracklist.txt");
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_WRITE_OWN_MAPLIST_FILE, false); $this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_WRITE_OWN_MAPLIST_FILE, false);
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_ENABLE_MX, true);
$this->mxManager->setStatus($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ENABLE_MX, true));
//Initlaize Communication Listenings //Initlaize Communication Listenings
$this->initalizeCommunicationListenings(); $this->initalizeCommunicationListenings();
@ -188,6 +195,8 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
* @param string $uid * @param string $uid
*/ */
public function updateMap($admin, $uid) { public function updateMap($admin, $uid) {
if ($admin !== null && !$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_ADD_MAP)) return;
$this->updateMapTimestamp($uid); $this->updateMapTimestamp($uid);
if (!isset($uid) || !isset($this->maps[$uid])) { if (!isset($uid) || !isset($this->maps[$uid])) {
@ -213,6 +222,19 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
} }
} }
/**
* Update Settings
*
* @param ?Setting $setting
*/
public function updateSettings(?Setting $setting = null) {
if (!isset($setting) || !$setting->belongsToClass($this)) return;
if ($setting->setting === self::SETTING_ENABLE_MX) {
$this->mxManager->setStatus($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ENABLE_MX, true));
}
}
/** /**
* Update the Timestamp of a Map * Update the Timestamp of a Map
* *
@ -252,6 +274,8 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
* @return bool * @return bool
*/ */
public function removeMap($admin, $uid, $eraseFile = false, $message = true) { public function removeMap($admin, $uid, $eraseFile = false, $message = true) {
if ($admin !== null && !$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_REMOVE_MAP)) return;
if (!isset($this->maps[$uid])) { if (!isset($this->maps[$uid])) {
if ($admin) { if ($admin) {
$this->maniaControl->getChat()->sendError('Map does not exist!', $admin); $this->maniaControl->getChat()->sendError('Map does not exist!', $admin);
@ -354,7 +378,7 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
public function addMapFromMx($mapId, $login, $update = false) { public function addMapFromMx($mapId, $login, $update = false) {
if (is_numeric($mapId)) { if (is_numeric($mapId)) {
// Check if map exists // Check if map exists
$this->maniaControl->getMapManager()->getMXManager()->fetchMapInfo($mapId, function (MXMapInfo $mapInfo = null) use ( $this->maniaControl->getMapManager()->getMXManager()->fetchMapInfo($mapId, function (?MXMapInfo $mapInfo = null) use (
&$login, &$update &$login, &$update
) { ) {
if (!$mapInfo || !isset($mapInfo->uploaded)) { if (!$mapInfo || !isset($mapInfo->uploaded)) {
@ -733,7 +757,7 @@ class MapManager implements CallbackListener, CommunicationListener, UsageInform
$currentIndex = $this->getMapIndex($this->getCurrentMap()); $currentIndex = $this->getMapIndex($this->getCurrentMap());
// No RestructureNeeded // No RestructureNeeded
if ($currentIndex < Maplist::MAX_MAPS_PER_PAGE - 1) { if ($currentIndex < $this->mapList->getMapPerPage() - 1) {
return true; return true;
} }

View File

@ -36,6 +36,7 @@ class MapQueue implements CallbackListener, CommandListener, UsageInformationAbl
const SETTING_MAPLIMIT_ADMIN = 'Maximum maps per admin (Admin+) in the Map-Queue (-1 = unlimited)'; const SETTING_MAPLIMIT_ADMIN = 'Maximum maps per admin (Admin+) in the Map-Queue (-1 = unlimited)';
const SETTING_MESSAGE_FORMAT = 'Message Format'; const SETTING_MESSAGE_FORMAT = 'Message Format';
const SETTING_BUFFERSIZE = 'Size of the Map-Queue buffer (recently played maps)'; const SETTING_BUFFERSIZE = 'Size of the Map-Queue buffer (recently played maps)';
const SETTING_PERMISSION_ADD_TO_QUEUE = 'Add map to queue';
const SETTING_PERMISSION_CLEAR_MAPQUEUE = 'Clear MapQueue'; const SETTING_PERMISSION_CLEAR_MAPQUEUE = 'Clear MapQueue';
const SETTING_PERMISSION_QUEUE_BUFFER = 'Queue maps in buffer'; const SETTING_PERMISSION_QUEUE_BUFFER = 'Queue maps in buffer';
@ -74,6 +75,7 @@ class MapQueue implements CallbackListener, CommandListener, UsageInformationAbl
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_BUFFERSIZE, 10); $this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_BUFFERSIZE, 10);
// Permissions // Permissions
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_ADD_TO_QUEUE, AuthenticationManager::AUTH_LEVEL_PLAYER, AuthenticationManager::AUTH_LEVEL_PLAYER);
$this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_CLEAR_MAPQUEUE, AuthenticationManager::AUTH_LEVEL_MODERATOR); $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); $this->maniaControl->getAuthenticationManager()->definePermissionLevel(self::SETTING_PERMISSION_QUEUE_BUFFER, AuthenticationManager::AUTH_LEVEL_ADMIN);
@ -113,7 +115,7 @@ class MapQueue implements CallbackListener, CommandListener, UsageInformationAbl
* *
* @param Player $admin |null * @param Player $admin |null
*/ */
public function clearMapQueue(Player $admin = null) { public function clearMapQueue(?Player $admin = null) {
if ($admin && !$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)) { if ($admin && !$this->maniaControl->getAuthenticationManager()->checkPermission($admin, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)) {
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin); $this->maniaControl->getAuthenticationManager()->sendNotAllowed($admin);
return; return;
@ -283,6 +285,8 @@ class MapQueue implements CallbackListener, CommandListener, UsageInformationAbl
return; return;
} }
if (!$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_ADD_TO_QUEUE)) return;
// Check if the Player is muted // Check if the Player is muted
if ($player->isMuted()) { if ($player->isMuted()) {
$this->maniaControl->getChat()->sendError('Muted Players are not allowed to queue a map.', $player); $this->maniaControl->getChat()->sendError('Muted Players are not allowed to queue a map.', $player);
@ -369,6 +373,10 @@ class MapQueue implements CallbackListener, CommandListener, UsageInformationAbl
if (!isset($this->queuedMaps[$uid])) { if (!isset($this->queuedMaps[$uid])) {
return; return;
} }
$queuer = $this->maniaControl->getMapManager()->getMapQueue()->getQueuer($uid);
if (($queuer === null || $queuer->login !== $player->login) && !$this->maniaControl->getAuthenticationManager()->checkPermission($player, self::SETTING_PERMISSION_CLEAR_MAPQUEUE)) return;
/** @var Map $map */ /** @var Map $map */
$map = $this->queuedMaps[$uid][1]; $map = $this->queuedMaps[$uid][1];
unset($this->queuedMaps[$uid]); unset($this->queuedMaps[$uid]);

View File

@ -196,6 +196,23 @@ class Player implements Dumpable, UsageInformationAble {
return ($this->pid <= 0 || substr($this->login, 0, 1) === '*'); return ($this->pid <= 0 || substr($this->login, 0, 1) === '*');
} }
/**
* Get AccountId from Login
*
* @api
* @return string
*/
public function getAccountId() {
if (strlen($this->login) !== 22) return $this->login;
$login = str_pad($this->login, 24, "=", STR_PAD_RIGHT);
$login = str_replace("_","/", str_replace("-","+", $login));
$login = base64_decode($login);
return vsprintf("%s%s-%s-%s-%s-%s%s%s", str_split(bin2hex($login), 4));
}
/** /**
* Get province * Get province
* *

View File

@ -47,6 +47,17 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
const SPECTATOR_BUT_KEEP_SELECTABLE = 3; const SPECTATOR_BUT_KEEP_SELECTABLE = 3;
const ECHO_WARN_PLAYER = 'ManiaControl.PlayerManager.WarnPlayer'; const ECHO_WARN_PLAYER = 'ManiaControl.PlayerManager.WarnPlayer';
/*
* Callback Constants
*/
const CB_PLAYER_FORCED_TO_PLAY = 'PlayerActions.PlayerForcedToPlay';
const CB_PLAYER_FORCED_TO_TEAM = 'PlayerActions.PlayerForcedToTeam';
const CB_PLAYER_FORCED_TO_SPEC = 'PlayerActions.PlayerForcedToSpec';
const CB_PLAYER_MUTED = 'PlayerActions.PlayerMuted';
const CB_PLAYER_WARNED = 'PlayerActions.PlayerWarned';
const CB_PLAYER_KICKED = 'PlayerActions.PlayerKicked';
const CB_PLAYER_BANNED = 'PlayerActions.PlayerBanned';
/* /*
* Permission Setting Constants * Permission Setting Constants
*/ */
@ -201,6 +212,8 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
return false; return false;
} }
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYER_FORCED_TO_TEAM, $target, $teamId);
$message = false; $message = false;
$teamName = ''; $teamName = '';
if ($teamId === self::TEAM_BLUE) { if ($teamId === self::TEAM_BLUE) {
@ -229,7 +242,7 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
if ($message) { if ($message) {
$this->maniaControl->getChat()->sendInformation($message); $this->maniaControl->getChat()->sendInformation($message);
Logger::logInfo($chatMessage, true); Logger::logInfo($message, true);
} }
return true; return true;
@ -281,6 +294,8 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
} }
} }
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYER_FORCED_TO_PLAY, $target);
// Announce force // Announce force
if ($displayAnnouncement) { if ($displayAnnouncement) {
if ($calledByAdmin) { if ($calledByAdmin) {
@ -340,6 +355,8 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
return false; return false;
} }
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYER_FORCED_TO_SPEC, $target);
if ($calledByAdmin) { if ($calledByAdmin) {
$title = $admin->getAuthLevelName(); $title = $admin->getAuthLevelName();
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
@ -460,6 +477,8 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
return false; return false;
} }
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYER_MUTED, $target);
if ($calledByAdmin) { if ($calledByAdmin) {
$title = $admin->getAuthLevelName(); $title = $admin->getAuthLevelName();
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
@ -561,6 +580,8 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
// Display manialink // Display manialink
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $target); $this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $target);
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYER_WARNED, $target);
if ($calledByAdmin) { if ($calledByAdmin) {
$title = $admin->getAuthLevelName(); $title = $admin->getAuthLevelName();
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
@ -625,6 +646,8 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
} }
} }
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYER_KICKED, $target);
if ($calledByAdmin) { if ($calledByAdmin) {
$title = $admin->getAuthLevelName(); $title = $admin->getAuthLevelName();
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
@ -679,6 +702,8 @@ class PlayerActions implements EchoListener, CommunicationListener, UsageInforma
return; return;
} }
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_PLAYER_BANNED, $target);
$title = $admin->getAuthLevelName(); $title = $admin->getAuthLevelName();
$message = $this->maniaControl->getChat()->formatMessage( $message = $this->maniaControl->getChat()->formatMessage(
"{$title} %s banned %s!", "{$title} %s banned %s!",

View File

@ -62,7 +62,6 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
const CACHE_CURRENT_PAGE = 'PlayerList.CurrentPage'; const CACHE_CURRENT_PAGE = 'PlayerList.CurrentPage';
const DEFAULT_CUSTOM_VOTE_PLUGIN = 'MCTeam\CustomVotesPlugin'; const DEFAULT_CUSTOM_VOTE_PLUGIN = 'MCTeam\CustomVotesPlugin';
const SHOWN_MAIN_WINDOW = -1; const SHOWN_MAIN_WINDOW = -1;
const MAX_PLAYERS_PER_PAGE = 15;
const MAX_PAGES_PER_CHUNK = 2; const MAX_PAGES_PER_CHUNK = 2;
/* /*
@ -157,8 +156,8 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
$totalPlayersCount = count($players); $totalPlayersCount = count($players);
$chunkIndex = $this->getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount); $chunkIndex = $this->getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount);
$playerBeginIndex = $this->getChunkStatsBeginIndex($chunkIndex); $playerBeginIndex = $this->getChunkStatsBeginIndex($chunkIndex);
$pageMaxCount = $this->getPlayersPerPage();
$pagesCount = ceil($totalPlayersCount / self::MAX_PLAYERS_PER_PAGE); $pagesCount = ceil($totalPlayersCount / $pageMaxCount);
//create manialink //create manialink
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID); $maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
@ -207,11 +206,11 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
$playerIndex = 1 + $playerBeginIndex; $playerIndex = 1 + $playerBeginIndex;
//Slice Array to chunk length //Slice Array to chunk length
$players = array_slice($players, $playerBeginIndex, self::MAX_PAGES_PER_CHUNK * self::MAX_PLAYERS_PER_PAGE, true); $players = array_slice($players, $playerBeginIndex, self::MAX_PAGES_PER_CHUNK * $pageMaxCount , true);
$pageNumber = 1 + $chunkIndex * self::MAX_PAGES_PER_CHUNK; $pageNumber = 1 + $chunkIndex * self::MAX_PAGES_PER_CHUNK;
foreach ($players as $listPlayer) { foreach ($players as $listPlayer) {
if ($index % self::MAX_PLAYERS_PER_PAGE === 1) { if ($index % $pageMaxCount === 1) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $frame->addChild($pageFrame);
@ -628,7 +627,7 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
* @return int * @return int
*/ */
private function getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount) { private function getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount) {
$pagesCount = ceil($totalPlayersCount / self::MAX_PLAYERS_PER_PAGE); $pagesCount = ceil($totalPlayersCount / $this->getPlayersPerPage());
if ($pageIndex > $pagesCount - 1) { if ($pageIndex > $pagesCount - 1) {
$pageIndex = $pagesCount - 1; $pageIndex = $pagesCount - 1;
} }
@ -642,7 +641,18 @@ class PlayerList implements ManialinkPageAnswerListener, CallbackListener, Timer
* @return int * @return int
*/ */
private function getChunkStatsBeginIndex($chunkIndex) { private function getChunkStatsBeginIndex($chunkIndex) {
return $chunkIndex * self::MAX_PAGES_PER_CHUNK * self::MAX_PLAYERS_PER_PAGE; return $chunkIndex * self::MAX_PAGES_PER_CHUNK * $this->getPlayersPerPage();
}
/**
* Get number of players per page
*
* @return int
*/
public function getPlayersPerPage() {
$pageheight = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
return floor($pageheight * 0.82 / 4);
} }
/** /**

View File

@ -600,12 +600,12 @@ class PlayerManager implements CallbackListener, TimerListener, CommunicationLis
} }
$player = new Player($this->maniaControl, false); $player = new Player($this->maniaControl, false);
$player->index = $row->index; $player->index = intval($row->index);
$player->login = $row->login; $player->login = $row->login;
$player->rawNickname = $row->nickname; $player->rawNickname = $row->nickname;
$player->nickname = Formatter::stripDirtyCodes($player->rawNickname); $player->nickname = Formatter::stripDirtyCodes($player->rawNickname);
$player->path = $row->path; $player->path = $row->path;
$player->authLevel = $row->authLevel; $player->authLevel = intval($row->authLevel);
return $player; return $player;
} }
@ -715,12 +715,12 @@ class PlayerManager implements CallbackListener, TimerListener, CommunicationLis
} }
$player = new Player($this->maniaControl, false); $player = new Player($this->maniaControl, false);
$player->index = $playerIndex; $player->index = intval($playerIndex);
$player->login = $row->login; $player->login = $row->login;
$player->rawNickname = $row->nickname; $player->rawNickname = $row->nickname;
$player->nickname = Formatter::stripDirtyCodes($player->rawNickname); $player->nickname = Formatter::stripDirtyCodes($player->rawNickname);
$player->path = $row->path; $player->path = $row->path;
$player->authLevel = $row->authLevel; $player->authLevel = intval($row->authLevel);
return $player; return $player;
} }

View File

@ -79,7 +79,9 @@ class InstallMenu implements ConfiguratorMenu, ManialinkPageAnswerListener {
// Config // Config
$pagerSize = 9.; $pagerSize = 9.;
$entryHeight = 5.; $entryHeight = 5.;
$posY = 0.; $innerWidth = $width - 4;
$innerHeight = $height - 16;
$pageMaxCount = floor($innerHeight / $entryHeight);
$pageFrame = null; $pageFrame = null;
$url = ManiaControl::URL_WEBSERVICE . 'plugins'; $url = ManiaControl::URL_WEBSERVICE . 'plugins';
@ -105,23 +107,41 @@ class InstallMenu implements ConfiguratorMenu, ManialinkPageAnswerListener {
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = clone $pagerPrev; $pagerNext = clone $pagerPrev;
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setX($width * 0.45); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSubStyle($pagerPrev::SUBSTYLE_ArrowNext); $pagerNext->setSubStyle($pagerPrev::SUBSTYLE_ArrowNext);
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT)->setPosition($width * 0.35, $height * -0.44, 1)->setStyle($pageCountLabel::STYLE_TextTitle1)->setTextSize(2); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2);
$paging->addButtonControl($pagerNext)->addButtonControl($pagerPrev)->setLabel($pageCountLabel); $paging->addButtonControl($pagerNext);
$paging->addButtonControl($pagerPrev);
$paging->setLabel($pageCountLabel);
$repositionnedFrame = new Frame();
$frame->addChild($repositionnedFrame);
$repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
// Info tooltip // Info tooltip
$infoTooltipLabel = new Label(); $infoTooltipLabel = new Label();
$frame->addChild($infoTooltipLabel); $repositionnedFrame->addChild($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); $infoTooltipLabel->setAlign($infoTooltipLabel::LEFT, $infoTooltipLabel::TOP);
$infoTooltipLabel->setPosition(3, $height * -1 + 16);
$infoTooltipLabel->setSize($width - 30, 20);
$infoTooltipLabel->setTextSize(1);
$infoTooltipLabel->setTranslate(true);
$infoTooltipLabel->setVisible(false);
$infoTooltipLabel->setAutoNewLine(true);
$infoTooltipLabel->setMaxLines(5);
// List plugins // List plugins
foreach ($pluginList as $plugin) { foreach ($pluginList as $plugin) {
@ -135,21 +155,26 @@ class InstallMenu implements ConfiguratorMenu, ManialinkPageAnswerListener {
continue; continue;
} }
if ($index % 10 === 0) { if ($index % $pageMaxCount === 0) {
// New page // New page
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $repositionnedFrame->addChild($pageFrame);
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$posY = $height * 0.41; $index = 1;
} }
$pluginFrame = new Frame(); $pluginFrame = new Frame();
$pageFrame->addChild($pluginFrame); $pageFrame->addChild($pluginFrame);
$pluginFrame->setY($posY); $pluginFrame->setY($entryHeight * $index * -1);
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$pluginFrame->addChild($nameLabel); $pluginFrame->addChild($nameLabel);
$nameLabel->setHorizontalAlign($nameLabel::LEFT)->setX($width * -0.46)->setSize($width * 0.62, $entryHeight)->setStyle($nameLabel::STYLE_TextCardSmall)->setTextSize(2)->setText($plugin->name); $nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setX(2);
$nameLabel->setSize($innerWidth * 0.6, $entryHeight);
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
$nameLabel->setTextSize(2);
$nameLabel->setText($plugin->name);
$description = "Author: {$plugin->author}\nVersion: {$plugin->currentVersion->version}\nDesc: {$plugin->description}"; $description = "Author: {$plugin->author}\nVersion: {$plugin->currentVersion->version}\nDesc: {$plugin->description}";
$infoTooltipLabel->setLineSpacing(1); $infoTooltipLabel->setLineSpacing(1);
@ -159,7 +184,7 @@ class InstallMenu implements ConfiguratorMenu, ManialinkPageAnswerListener {
// Incompatibility label // Incompatibility label
$infoLabel = new Label_Text(); $infoLabel = new Label_Text();
$pluginFrame->addChild($infoLabel); $pluginFrame->addChild($infoLabel);
$infoLabel->setHorizontalAlign($infoLabel::RIGHT)->setX($width * 0.47)->setSize($width * 0.33, $entryHeight)->setTextSize(1)->setTextColor('f30'); $infoLabel->setHorizontalAlign($infoLabel::RIGHT)->setX($innerWidth * 0.47)->setSize($innerWidth * 0.33, $entryHeight)->setTextSize(1)->setTextColor('f30');
if ($plugin->currentVersion->min_mc_version > ManiaControl::VERSION) { if ($plugin->currentVersion->min_mc_version > ManiaControl::VERSION) {
$infoLabel->setText("Needs at least MC-Version '{$plugin->currentVersion->min_mc_version}'"); $infoLabel->setText("Needs at least MC-Version '{$plugin->currentVersion->min_mc_version}'");
} else { } else {
@ -169,17 +194,24 @@ class InstallMenu implements ConfiguratorMenu, ManialinkPageAnswerListener {
// Install button // Install button
$installButton = new Label_Button(); $installButton = new Label_Button();
$pluginFrame->addChild($installButton); $pluginFrame->addChild($installButton);
$installButton->setHorizontalAlign($installButton::RIGHT)->setX($width * 0.47)->setStyle($installButton::STYLE_CardButtonSmall)->setText('Install')->setTranslate(true)->setAction(self::ACTION_PREFIX_INSTALL_PLUGIN . $plugin->id); $installButton->setHorizontalAlign($installButton::RIGHT);
$installButton->setSize($innerWidth * 0.3, $entryHeight);
$installButton->setX($innerWidth - 4);
$installButton->setStyle($installButton::STYLE_CardButtonSmall);
$installButton->setText('Install');
$installButton->setTranslate(true);
$installButton->setAction(self::ACTION_PREFIX_INSTALL_PLUGIN . $plugin->id);
if ($plugin->currentVersion->verified > 0) { if ($plugin->currentVersion->verified > 0) {
// Suggested quad // Suggested quad
$suggestedQuad = new Quad_Icons64x64_1(); $suggestedQuad = new Quad_Icons64x64_1();
$pluginFrame->addChild($suggestedQuad); $pluginFrame->addChild($suggestedQuad);
$suggestedQuad->setPosition($width * 0.45, $entryHeight * 0.12, 2)->setSize(4, 4)->setSubStyle($suggestedQuad::SUBSTYLE_StateSuggested); $suggestedQuad->setPosition($innerWidth - 2, $entryHeight * 0.12, 2);
$suggestedQuad->setSize(4, 4);
$suggestedQuad->setSubStyle($suggestedQuad::SUBSTYLE_StateSuggested);
} }
} }
$posY -= $entryHeight;
$index++; $index++;
} }
} }

View File

@ -400,7 +400,7 @@ class PluginManager {
return false; return false;
} }
array_push($this->pluginClasses, $pluginClass); array_push($this->pluginClasses, $pluginClass);
sort($this->pluginClasses); natcasesort($this->pluginClasses);
return true; return true;
} }

View File

@ -48,6 +48,7 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
const ACTION_PREFIX_UPDATEPLUGIN = 'PluginMenu.Update.'; const ACTION_PREFIX_UPDATEPLUGIN = 'PluginMenu.Update.';
const ACTION_UPDATEPLUGINS = 'PluginMenu.Update.All'; const ACTION_UPDATEPLUGINS = 'PluginMenu.Update.All';
const SETTING_PERMISSION_CHANGE_PLUGIN_SETTINGS = 'Change Plugin Settings'; const SETTING_PERMISSION_CHANGE_PLUGIN_SETTINGS = 'Change Plugin Settings';
const SETTING_CHECK_UPDATE_WHEN_OPENING = 'Check update when opening the menu';
const CACHE_SETTING_CLASS = 'PluginMenuCache.SettingClass'; const CACHE_SETTING_CLASS = 'PluginMenuCache.SettingClass';
/* /*
@ -64,6 +65,9 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
public function __construct(ManiaControl $maniaControl) { public function __construct(ManiaControl $maniaControl) {
$this->maniaControl = $maniaControl; $this->maniaControl = $maniaControl;
// Settings
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_CHECK_UPDATE_WHEN_OPENING, true);
// Callbacks // Callbacks
$this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer'); $this->maniaControl->getCallbackManager()->registerCallbackListener(CallbackManager::CB_MP_PLAYERMANIALINKPAGEANSWER, $this, 'handleManialinkPageAnswer');
$this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_BACK_TO_PLUGINS, $this, 'backToPlugins'); $this->maniaControl->getManialinkManager()->registerManialinkPageAnswerListener(self::ACTION_BACK_TO_PLUGINS, $this, 'backToPlugins');
@ -103,18 +107,18 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
// Config // Config
$pagerSize = 9.; $pagerSize = 9.;
$entryHeight = 5.; $entryHeight = 5.;
$pageMaxCount = 10; $pageMaxCount = floor(($height - 16) / $entryHeight);
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize); $pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_ArrowPrev); $pagerPrev->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize); $pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_ArrowNext); $pagerNext->setSubStyle(Quad_Icons64x64_1::SUBSTYLE_ArrowNext);
@ -124,7 +128,7 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.35, $height * -0.44, 1); $pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1); $pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2); $pageCountLabel->setTextSize(2);
@ -145,33 +149,66 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
// Display normal Plugin List // Display normal Plugin List
// Plugin pages // Plugin pages
$posY = 0.; $posY = 0.;
$pluginUpdates = null;
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_CHECK_UPDATE_WHEN_OPENING)) {
$pluginUpdates = $this->maniaControl->getUpdateManager()->getPluginUpdateManager()->getPluginsUpdates(); $pluginUpdates = $this->maniaControl->getUpdateManager()->getPluginUpdateManager()->getPluginsUpdates();
}
usort($pluginClasses, function ($pluginClassA, $pluginClassB) { usort($pluginClasses, function ($pluginClassA, $pluginClassB) {
/** @var Plugin $pluginClassA */ /** @var Plugin $pluginClassA */
/** @var Plugin $pluginClassB */ /** @var Plugin $pluginClassB */
return strcmp($pluginClassA::getName(), $pluginClassB::getName()); return strcasecmp($pluginClassA::getName(), $pluginClassB::getName());
}); });
$repositionnedFrame = new Frame();
$frame->addChild($repositionnedFrame);
$repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
$pagesFrame = new Frame();
$repositionnedFrame->addChild($pagesFrame);
$pagesFrame->setY(-1);
$descriptionLabel = new Label();
$repositionnedFrame->addChild($descriptionLabel);
$descriptionLabel->setAlign($descriptionLabel::LEFT, $descriptionLabel::TOP);
$descriptionLabel->setPosition(3, $height * -1 + 16);
$descriptionLabel->setSize($width - 30, 20);
$descriptionLabel->setTextSize(1);
$descriptionLabel->setTranslate(true);
$descriptionLabel->setVisible(false);
$descriptionLabel->setMaxLines(5);
$descriptionLabel->setLineSpacing(1);
$tooltip = new Label();
$repositionnedFrame->addChild($tooltip);
$tooltip->setAlign($descriptionLabel::LEFT, $descriptionLabel::TOP);
$tooltip->setPosition(3, $height * -1 + 5);
$tooltip->setSize($width - 30, 5);
$tooltip->setTextSize(1);
$tooltip->setTranslate(true);
$tooltip->setVisible(false);
$index = 0;
$pageFrame = null; $pageFrame = null;
foreach ($pluginClasses as $index => $pluginClass) { foreach ($pluginClasses as $pluginClass) {
/** @var Plugin $pluginClass */ /** @var Plugin $pluginClass */
if ($index % $pageMaxCount === 0) { if ($index % $pageMaxCount === 0) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $pagesFrame->addChild($pageFrame);
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$posY = $height * 0.41; $index = 1;
} }
$active = $this->maniaControl->getPluginManager()->isPluginActive($pluginClass); $active = $this->maniaControl->getPluginManager()->isPluginActive($pluginClass);
$pluginFrame = new Frame(); $pluginFrame = new Frame();
$pageFrame->addChild($pluginFrame); $pageFrame->addChild($pluginFrame);
$pluginFrame->setY($posY); $pluginFrame->setY($entryHeight * $index * -1);
$activeQuad = new Quad_Icons64x64_1(); $activeQuad = new Quad_Icons64x64_1();
$pluginFrame->addChild($activeQuad); $pluginFrame->addChild($activeQuad);
$activeQuad->setPosition($width * -0.45, -0.1, 1); $activeQuad->setPosition(5, 0, 1);
$activeQuad->setSize($entryHeight * 0.9, $entryHeight * 0.9); $activeQuad->setSize($entryHeight * 0.9, $entryHeight * 0.9);
if ($active) { if ($active) {
$activeQuad->setSubStyle($activeQuad::SUBSTYLE_LvlGreen); $activeQuad->setSubStyle($activeQuad::SUBSTYLE_LvlGreen);
@ -182,66 +219,58 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$pluginFrame->addChild($nameLabel); $pluginFrame->addChild($nameLabel);
$nameLabel->setHorizontalAlign($nameLabel::LEFT); $nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setX($width * -0.4); $nameLabel->setX(7.5);
$nameLabel->setSize($width * 0.5, $entryHeight); $nameLabel->setSize($width - 50, $entryHeight);
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall); $nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
$nameLabel->setTextSize(2); $nameLabel->setTextSize(2);
$nameLabel->setText($pluginClass::getName()); $nameLabel->setText($pluginClass::getName());
$descriptionLabel = new Label();
$pageFrame->addChild($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->setMaxLines(5);
$descriptionLabel->setLineSpacing(1);
$description = "Author: {$pluginClass::getAuthor()}\nVersion: {$pluginClass::getVersion()}\nDesc: {$pluginClass::getDescription()}"; $description = "Author: {$pluginClass::getAuthor()}\nVersion: {$pluginClass::getVersion()}\nDesc: {$pluginClass::getDescription()}";
$nameLabel->addTooltipLabelFeature($descriptionLabel, $description); $nameLabel->addTooltipLabelFeature($descriptionLabel, $description);
$quad = new Quad_Icons128x32_1(); $quad = new Quad_Icons128x32_1();
$pluginFrame->addChild($quad); $pluginFrame->addChild($quad);
$quad->setSubStyle($quad::SUBSTYLE_Settings); $quad->setSubStyle($quad::SUBSTYLE_Settings);
$quad->setX(15); $quad->setX($width - 37);
$quad->setZ(1); $quad->setZ(1);
$quad->setSize(5, 5); $quad->setSize(5, 5);
$quad->setAction(self::ACTION_PREFIX_SETTINGS . $pluginClass); $quad->setAction(self::ACTION_PREFIX_SETTINGS . $pluginClass);
$quad->addTooltipLabelFeature($tooltip, "Open settings of ". $pluginClass::getName());
$statusChangeButton = new Label_Button(); $statusChangeButton = new Label_Button();
$pluginFrame->addChild($statusChangeButton); $pluginFrame->addChild($statusChangeButton);
$statusChangeButton->setHorizontalAlign($statusChangeButton::RIGHT); $statusChangeButton->setHorizontalAlign($statusChangeButton::RIGHT);
$statusChangeButton->setX($width * 0.45); $statusChangeButton->setX($width - 6);
$statusChangeButton->setStyle($statusChangeButton::STYLE_CardButtonSmall); $statusChangeButton->setStyle($statusChangeButton::STYLE_CardButtonSmallS);
if ($active) { if ($active) {
$statusChangeButton->setTextPrefix('$f00');
$statusChangeButton->setText('Deactivate'); $statusChangeButton->setText('Deactivate');
$statusChangeButton->setAction(self::ACTION_PREFIX_DISABLEPLUGIN . $pluginClass); $statusChangeButton->setAction(self::ACTION_PREFIX_DISABLEPLUGIN . $pluginClass);
$statusChangeButton->addTooltipLabelFeature($tooltip, "Deactivate plugin ". $pluginClass::getName());
} else { } else {
$statusChangeButton->setTextPrefix('a');
$statusChangeButton->setText('Activate'); $statusChangeButton->setText('Activate');
$statusChangeButton->setAction(self::ACTION_PREFIX_ENABLEPLUGIN . $pluginClass); $statusChangeButton->setAction(self::ACTION_PREFIX_ENABLEPLUGIN . $pluginClass);
$statusChangeButton->addTooltipLabelFeature($tooltip, "Activate plugin ". $pluginClass::getName());
} }
if ($pluginUpdates && array_key_exists($pluginClass::getId(), $pluginUpdates)) { if ($pluginUpdates && array_key_exists($pluginClass::getId(), $pluginUpdates)) {
$quadUpdate = new Quad_Icons128x128_1(); $quadUpdate = new Quad_Icons128x128_1();
$pluginFrame->addChild($quadUpdate); $pluginFrame->addChild($quadUpdate);
$quadUpdate->setSubStyle($quadUpdate::SUBSTYLE_ProfileVehicle); $quadUpdate->setSubStyle($quadUpdate::SUBSTYLE_ProfileVehicle);
$quadUpdate->setX(56); $quadUpdate->setX($width - 3.5);
$quadUpdate->setZ(2); $quadUpdate->setZ(2);
$quadUpdate->setSize(5, 5); $quadUpdate->setSize(5, 5);
$quadUpdate->setAction(self::ACTION_PREFIX_UPDATEPLUGIN . $pluginClass); $quadUpdate->setAction(self::ACTION_PREFIX_UPDATEPLUGIN . $pluginClass);
} }
$posY -= $entryHeight; $index++;
} }
if ($pluginUpdates) { if ($pluginUpdates) {
$updatePluginsButton = new Label_Button(); $updatePluginsButton = new Label_Button();
$frame->addChild($updatePluginsButton); $frame->addChild($updatePluginsButton);
$updatePluginsButton->setHorizontalAlign($updatePluginsButton::RIGHT); $updatePluginsButton->setHorizontalAlign($updatePluginsButton::RIGHT);
$updatePluginsButton->setPosition($width * 0.5, -29, 2); $updatePluginsButton->setPosition($width * 0.5, $height * -0.37, 2);
$updatePluginsButton->setWidth(10); $updatePluginsButton->setWidth(10);
$updatePluginsButton->setStyle($updatePluginsButton::STYLE_CardButtonSmallS); $updatePluginsButton->setStyle($updatePluginsButton::STYLE_CardButtonSmallS);
$updatePluginsButton->setText(count($pluginUpdates) . ' update(s)'); $updatePluginsButton->setText(count($pluginUpdates) . ' update(s)');
@ -267,18 +296,36 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
$settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass); $settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass);
$isunlinkable = $this->maniaControl->getSettingManager()->getSettingValue($this->maniaControl->getSettingManager(), SettingManager::SETTING_ALLOW_UNLINK_SERVER); $isunlinkable = $this->maniaControl->getSettingManager()->getSettingValue($this->maniaControl->getSettingManager(), SettingManager::SETTING_ALLOW_UNLINK_SERVER);
$pageSettingsMaxCount = 10; $repositionnedFrame = new Frame();
$posY = 0; $frame->addChild($repositionnedFrame);
$index = 0; $repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
$pagesFrame = new Frame();
$repositionnedFrame->addChild($pagesFrame);
$pagesFrame->setY(-8.);
if ($isunlinkable) {
$pagesFrame->setX(5.); // move a bit the settings to diplay the padlocks
$innerWidth = $width - 6;
} else {
$pagesFrame->setX(2.);
$innerWidth = $width - 3;
}
$innerHeight = $height - 8 - 10;
$settingHeight = 5.; $settingHeight = 5.;
$valueWidth = $innerWidth * 0.3;
$pageSettingsMaxCount = floor($innerHeight / $settingHeight);
$index = 0;
$pageFrame = null; $pageFrame = null;
//Headline Label //Headline Label
$headLabel = new Label_Text(); $headLabel = new Label_Text();
$frame->addChild($headLabel); $repositionnedFrame->addChild($headLabel);
$headLabel->setHorizontalAlign($headLabel::LEFT); $headLabel->setHorizontalAlign($headLabel::LEFT);
$headLabel->setPosition($width * -0.46, $height * 0.41); $headLabel->setPosition(3, -6);
$headLabel->setSize($width * 0.6, $settingHeight); $headLabel->setSize($width - 6, $settingHeight);
$headLabel->setStyle($headLabel::STYLE_TextCardSmall); $headLabel->setStyle($headLabel::STYLE_TextCardSmall);
$headLabel->setTextSize(3); $headLabel->setTextSize(3);
$headLabel->setText($settingClass); $headLabel->setText($settingClass);
@ -292,38 +339,37 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
foreach ($settings as $setting) { foreach ($settings as $setting) {
if ($index % $pageSettingsMaxCount === 0) { if ($index % $pageSettingsMaxCount === 0) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $pagesFrame->addChild($pageFrame);
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$posY = $height * 0.41 - $settingHeight * 1.5; $index = 1;
} }
$settingFrame = new Frame(); $settingFrame = new Frame();
$pageFrame->addChild($settingFrame); $pageFrame->addChild($settingFrame);
$settingFrame->setY($posY); $settingFrame->setY($settingHeight * $index * -1);
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$settingFrame->addChild($nameLabel); $settingFrame->addChild($nameLabel);
$nameLabel->setHorizontalAlign($nameLabel::LEFT); $nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setX($width * -0.46); $nameLabel->setSize($innerWidth * 0.6, $settingHeight);
$nameLabel->setSize($width * 0.6, $settingHeight);
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall); $nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
$nameLabel->setTextSize(2); $nameLabel->setTextSize(2);
$nameLabel->setText($setting->setting); $nameLabel->setText($setting->setting);
$nameLabel->setTextColor('fff'); $nameLabel->setTextColor('fff');
$descriptionLabel = new Label_Text(); $descriptionLabel = new Label_Text();
$pageFrame->addChild($descriptionLabel); $repositionnedFrame->addChild($descriptionLabel);
$descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT); $descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT);
$descriptionLabel->setPosition(-0.45 * $width, -0.35 * $height); $descriptionLabel->setPosition(3, $height * -1 + 10);
$descriptionLabel->setSize(0.9 * $width, $settingHeight); $descriptionLabel->setSize($innerWidth - 6, $settingHeight);
$descriptionLabel->setTextSize(2); $descriptionLabel->setTextSize(1);
$descriptionLabel->setTranslate(true); $descriptionLabel->setTranslate(true);
$nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description); $nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description);
if ($isunlinkable) { if ($isunlinkable) {
$quadlink = new Quad(); $quadlink = new Quad();
$settingFrame->addChild($quadlink); $settingFrame->addChild($quadlink);
$quadlink->setPosition(-0.48 * $width, 0.2, -0.01); $quadlink->setPosition(-2, 0.2);
$quadlink->setSize(4, 4); $quadlink->setSize(4, 4);
$quadlink->setColorize("ccccccaa"); $quadlink->setColorize("ccccccaa");
$quadlink->setStyle("UICommon64_1"); $quadlink->setStyle("UICommon64_1");
@ -334,15 +380,15 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
if ($setting->type === Setting::TYPE_BOOL) { if ($setting->type === Setting::TYPE_BOOL) {
// Boolean checkbox // Boolean checkbox
$quad = new Quad(); $quad = new Quad();
$quad->setPosition($width * 0.33, 0, -0.01); $quad->setPosition($innerWidth - $valueWidth / 2, 0);
$quad->setSize(4, 4); $quad->setSize(4, 4);
$checkBox = new CheckBox(self::ACTION_PREFIX_SETTING . $setting->index, $setting->value, $quad); $checkBox = new CheckBox(self::ACTION_PREFIX_SETTING . $setting->index, $setting->value, $quad);
$settingFrame->addChild($checkBox); $settingFrame->addChild($checkBox);
} else if ($setting->type === Setting::TYPE_SET) { } else if ($setting->type === Setting::TYPE_SET) {
// SET value picker // SET value picker
$label = new Label_Text(); $label = new Label_Text();
$label->setX($width * 0.33); $label->setPosition($innerWidth - $valueWidth / 2, 0);
$label->setSize($width * 0.3, $settingHeight * 0.9); $label->setSize($valueWidth, $settingHeight * 0.9);
$label->setStyle($label::STYLE_TextValueSmall); $label->setStyle($label::STYLE_TextValueSmall);
$label->setTextSize(1); $label->setTextSize(1);
$valuePicker = new ValuePicker(self::ACTION_PREFIX_SETTING . $setting->index, $setting->set, $setting->value, $label); $valuePicker = new ValuePicker(self::ACTION_PREFIX_SETTING . $setting->index, $setting->set, $setting->value, $label);
@ -351,26 +397,25 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
// Value entry // Value entry
$entry = new Entry(); $entry = new Entry();
$settingFrame->addChild($entry); $settingFrame->addChild($entry);
$entry->setX($width * 0.33); $entry->setPosition($innerWidth - $valueWidth / 2, 0);
$entry->setSize($width * 0.3, $settingHeight * 0.9); $entry->setSize($valueWidth, $settingHeight * 0.9);
$entry->setTextSize(1); $entry->setTextSize(1);
$entry->setMaxLength(1000); // Actions are limited to 1024 chars per field
$entry->setStyle(Label_Text::STYLE_TextValueSmall); $entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setName(self::ACTION_PREFIX_SETTING . $setting->index); $entry->setName(self::ACTION_PREFIX_SETTING . $setting->index);
$entry->setDefault($setting->value); $entry->setDefault($setting->value);
} }
$posY -= $settingHeight;
$index++; $index++;
} }
$backButton = new Label_Button(); $backButton = new Label_Button();
$frame->addChild($backButton); $repositionnedFrame->addChild($backButton);
$backButton->setStyle($backButton::STYLE_CardMain_Quit); $backButton->setStyle($backButton::STYLE_CardMain_Quit);
$backButton->setHorizontalAlign($backButton::LEFT); $backButton->setHorizontalAlign($backButton::LEFT);
$backButton->setScale(0.5); $backButton->setScale(0.5);
$backButton->setText('Back'); $backButton->setText('Back');
$backButton->setPosition(-$width / 2 + 5, -$height / 2 + 5); $backButton->setPosition(5 , $height * -1 + 5);
$backButton->setAction(self::ACTION_BACK_TO_PLUGINS); $backButton->setAction(self::ACTION_BACK_TO_PLUGINS);
if ($isunlinkable) { if ($isunlinkable) {
@ -380,8 +425,8 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
5, 5,
self::ACTION_PREFIX_MANAGE_SETTING_LINK . $settingClass self::ACTION_PREFIX_MANAGE_SETTING_LINK . $settingClass
); );
$frame->addChild($mapNameButton); $repositionnedFrame->addChild($mapNameButton);
$mapNameButton->setPosition(-$width / 2 + 60, -35); $mapNameButton->setPosition(60, $height * -1 + 5);
} }
return $frame; return $frame;
@ -401,10 +446,21 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
public function getManageSettingsLink(Frame $frame, $width, $height, Paging $paging, Player $player, $settingClass) { public function getManageSettingsLink(Frame $frame, $width, $height, Paging $paging, Player $player, $settingClass) {
$settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass); $settings = $this->maniaControl->getSettingManager()->getSettingsByClass($settingClass);
$pageSettingsMaxCount = 10; $repositionnedFrame = new Frame();
$posY = 0; $frame->addChild($repositionnedFrame);
$index = 0; $repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
$pagesFrame = new Frame();
$repositionnedFrame->addChild($pagesFrame);
$pagesFrame->setY(-8.);
$pagesFrame->setX(5.);
$innerWidth = $width - 6;
$innerHeight = $height - 8 - 10;
$settingHeight = 5.; $settingHeight = 5.;
$pageSettingsMaxCount = floor($innerHeight / $settingHeight);
$index = 0;
$pageFrame = null; $pageFrame = null;
if (count($settings) > 64) { if (count($settings) > 64) {
@ -414,10 +470,10 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
//Headline Label //Headline Label
$headLabel = new Label_Text(); $headLabel = new Label_Text();
$frame->addChild($headLabel); $repositionnedFrame->addChild($headLabel);
$headLabel->setHorizontalAlign($headLabel::LEFT); $headLabel->setHorizontalAlign($headLabel::LEFT);
$headLabel->setPosition($width * -0.46, $height * 0.41); $headLabel->setPosition(3, -6);
$headLabel->setSize($width * 0.6, $settingHeight); $headLabel->setSize($width - 6, $settingHeight);
$headLabel->setStyle($headLabel::STYLE_TextCardSmall); $headLabel->setStyle($headLabel::STYLE_TextCardSmall);
$headLabel->setTextSize(3); $headLabel->setTextSize(3);
$headLabel->setText($settingClass); $headLabel->setText($settingClass);
@ -426,54 +482,51 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
foreach ($settings as $setting) { foreach ($settings as $setting) {
if ($index % $pageSettingsMaxCount === 0) { if ($index % $pageSettingsMaxCount === 0) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $pagesFrame->addChild($pageFrame);
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$posY = $height * 0.41 - $settingHeight * 1.5; $index = 1;
} }
$settingFrame = new Frame(); $settingFrame = new Frame();
$pageFrame->addChild($settingFrame); $pageFrame->addChild($settingFrame);
$settingFrame->setY($posY); $settingFrame->setY($settingHeight * $index * -1);
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$settingFrame->addChild($nameLabel); $settingFrame->addChild($nameLabel);
$nameLabel->setHorizontalAlign($nameLabel::LEFT); $nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setX($width * -0.46); $nameLabel->setSize($innerWidth * 0.6, $settingHeight);
$nameLabel->setSize($width * 0.6, $settingHeight);
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall); $nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
$nameLabel->setTextSize(2); $nameLabel->setTextSize(2);
$nameLabel->setText($setting->setting); $nameLabel->setText($setting->setting);
$nameLabel->setTextColor('fff'); $nameLabel->setTextColor('fff');
$descriptionLabel = new Label_Text(); $descriptionLabel = new Label_Text();
$pageFrame->addChild($descriptionLabel); $repositionnedFrame->addChild($descriptionLabel);
$descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT); $descriptionLabel->setHorizontalAlign($descriptionLabel::LEFT);
$descriptionLabel->setPosition(-0.45 * $width, -0.35 * $height); $descriptionLabel->setPosition(3, $height * -1 + 10);
$descriptionLabel->setSize(0.9 * $width, $settingHeight); $descriptionLabel->setSize($innerWidth - 6, $settingHeight);
$descriptionLabel->setTextSize(2); $descriptionLabel->setTextSize(1);
$descriptionLabel->setTranslate(true); $descriptionLabel->setTranslate(true);
$nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description); $nameLabel->addTooltipLabelFeature($descriptionLabel, $setting->description);
$quad = new Quad(); $quad = new Quad();
$quad->setPosition($width * 0.33, 0.2, -0.01); $quad->setPosition($innerWidth - $innerWidth * 0.3 / 2, 0.2);
$quad->setSize(4, 4); $quad->setSize(4, 4);
$checkBox = new CheckBox(self::ACTION_PREFIX_SETTING_LINK . $setting->index, $setting->linked, $quad); $checkBox = new CheckBox(self::ACTION_PREFIX_SETTING_LINK . $setting->index, $setting->linked, $quad);
$checkBox->setEnabledDesign("UICommon64_1", "Padlock_light"); $checkBox->setEnabledDesign("UICommon64_1", "Padlock_light");
$checkBox->setDisabledDesign("UICommon64_1", "Padlock_light"); $checkBox->setDisabledDesign("UICommon64_1", "Padlock_light");
$settingFrame->addChild($checkBox); $settingFrame->addChild($checkBox);
$posY -= $settingHeight;
$index++; $index++;
} }
$backButton = new Label_Button(); $backButton = new Label_Button();
$frame->addChild($backButton); $repositionnedFrame->addChild($backButton);
$backButton->setStyle($backButton::STYLE_CardMain_Quit); $backButton->setStyle($backButton::STYLE_CardMain_Quit);
$backButton->setHorizontalAlign($backButton::LEFT); $backButton->setHorizontalAlign($backButton::LEFT);
$backButton->setScale(0.5); $backButton->setScale(0.5);
$backButton->setText('Back'); $backButton->setText('Back');
$backButton->setPosition(-$width / 2 + 5, -$height / 2 + 5); $backButton->setPosition(5 , $height * -1 + 5);
$backButton->setAction(self::ACTION_PREFIX_SETTINGS . $settingClass); $backButton->setAction(self::ACTION_PREFIX_SETTINGS . $settingClass);
return $frame; return $frame;
@ -583,6 +636,8 @@ class PluginMenu implements CallbackListener, ConfiguratorMenu, ManialinkPageAns
$setting->value = $settingData['Value']; $setting->value = $settingData['Value'];
} }
$this->maniaControl->getSettingManager()->saveSetting($setting); $this->maniaControl->getSettingManager()->saveSetting($setting);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') changed the setting "'. $setting->class . '\\\\' . $setting->setting .'" to "'. $setting->value .'"');
} }
$this->maniaControl->getChat()->sendSuccess('Plugin Settings saved!', $player); $this->maniaControl->getChat()->sendSuccess('Plugin Settings saved!', $player);

View File

@ -275,35 +275,50 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT)->setPosition($width * 0.35, $height * -0.44, 1)->setStyle($pageCountLabel::STYLE_TextTitle1)->setTextSize(2); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2);
$paging->addButtonControl($pagerNext)->addButtonControl($pagerPrev)->setLabel($pageCountLabel); $paging->addButtonControl($pagerNext);
$paging->addButtonControl($pagerPrev);
$paging->setLabel($pageCountLabel);
$repositionnedFrame = new Frame();
$frame->addChild($repositionnedFrame);
$repositionnedFrame->setPosition($width * -0.5, $height * 0.5);
$pagesFrame = new Frame();
$repositionnedFrame->addChild($pagesFrame);
$pagesFrame->setY(-8.);
// Pages // Pages
$posY = 0.; $posY = 0.;
$index = 0; $index = 0;
$pageFrame = null; $pageFrame = null;
$pageMaxCount = floor(($height - 16) / $optionHeight);
foreach ($serverOptionsArray as $name => $value) { foreach ($serverOptionsArray as $name => $value) {
// Continue on CurrentMaxPlayers... // Continue on CurrentMaxPlayers...
$pos = strpos($name, 'Current'); // TODO: display 'Current...' somewhere if (strpos($name, 'Current') !== false) continue; // TODO: display 'Current...' somewhere
if ($pos !== false) {
continue;
}
if ($index % 13 === 0) { if ($index % $pageMaxCount === 0) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $pagesFrame->addChild($pageFrame);
$posY = $height * 0.41;
$paging->addPageControl($pageFrame); $paging->addPageControl($pageFrame);
$posY = 0.;
} }
$optionsFrame = new Frame(); $optionsFrame = new Frame();
@ -312,25 +327,59 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$optionsFrame->addChild($nameLabel); $optionsFrame->addChild($nameLabel);
$nameLabel->setHorizontalAlign($nameLabel::LEFT)->setX($width * -0.46)->setSize($width * 0.4, $optionHeight)->setStyle($nameLabel::STYLE_TextCardSmall)->setTextSize($labelTextSize)->setText($name)->setTextColor('fff'); $nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setX(2);
$nameLabel->setSize($width * 0.6, $optionHeight);
$nameLabel->setStyle($nameLabel::STYLE_TextCardSmall);
$nameLabel->setTextSize($labelTextSize)->setText($name);
$nameLabel->setTextColor('fff');
if (is_bool($value)) { if (is_bool($value)) {
// Boolean checkbox // Boolean checkbox
$quad = new Quad(); $quad = new Quad();
$quad->setPosition($width * 0.23, 0, -0.01)->setSize(4, 4); $quad->setPosition($width - $width * 0.3 / 2 - 2, 0, -0.01);
$quad->setSize(4, 4);
$checkBox = new CheckBox(self::ACTION_PREFIX_OPTION . $name, $value, $quad); $checkBox = new CheckBox(self::ACTION_PREFIX_OPTION . $name, $value, $quad);
$optionsFrame->addChild($checkBox); $optionsFrame->addChild($checkBox);
} else { } else {
// Other // Other
$entry = new Entry(); $entry = new Entry();
$optionsFrame->addChild($entry); $optionsFrame->addChild($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); $entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setX($width - $width * 0.3 / 2 - 2);
$entry->setTextSize(1);
$entry->setSize($width * 0.3, $optionHeight * 0.9);
$entry->setName(self::ACTION_PREFIX_OPTION . $name);
$entry->setDefault($value);
if ($name === 'Comment') { if ($name === 'Comment') {
$entry->setSize($width * 0.48, $optionHeight * 3. + $optionHeight * 0.9)->setAutoNewLine(true)->setVerticalAlign($entry::TOP)->setY($optionHeight * 1.5 + 2.5); $entry->setSize($width * 0.3, $optionHeight * 3. + $optionHeight * 0.9);
$entry->setAutoNewLine(true);
$entry->setVerticalAlign($entry::TOP);
$entry->setY($optionHeight * 1.5 + 2.5);
$optionsFrame->setY($posY - $optionHeight * 1.5); $optionsFrame->setY($posY - $optionHeight * 1.5);
$posY -= $optionHeight * 3.; $posY -= $optionHeight * 3.;
$index += 3; $index += 3;
} else if (strpos($name, 'Password') !== false) {
$entry->setTextFormat("Password");
$entry->setId($name);
$quad = new Quad();
$quad->setPosition($width - $width * 0.3 - 4, 0, -0.01);
$quad->setSize(4, 4);
$checkBox = new CheckBox(null, false, $quad);
$checkBox->setEnabledDesign("UICommon64_1", "Eye_light");
$checkBox->setDisabledDesign("UICommon64_1", "Eye_light");
$checkBox->setCustomScript("
declare CMlEntry Entry <=> (Quad_CheckBox.Parent.Parent.GetFirstChild(\"$name\") as CMlEntry);
if (Entry != Null) {
if (Quad_CheckBox.StyleSelected) {
Entry.TextFormat = CMlEntry::ETextFormat::Basic;
} else {
Entry.TextFormat = CMlEntry::ETextFormat::Password;
}
}");
$optionsFrame->addChild($checkBox);
} }
} }
@ -369,6 +418,7 @@ class ServerOptionsMenu implements CallbackListener, ConfiguratorMenu, TimerList
$success = $this->applyNewServerOptions($newServerOptions, $player); $success = $this->applyNewServerOptions($newServerOptions, $player);
if ($success) { if ($success) {
$this->maniaControl->getChat()->sendSuccess('Server Options saved!', $player); $this->maniaControl->getChat()->sendSuccess('Server Options saved!', $player);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') changed Server Options');
} else { } else {
$this->maniaControl->getChat()->sendError('Server Options saving failed!', $player); $this->maniaControl->getChat()->sendError('Server Options saving failed!', $player);
} }

View File

@ -166,13 +166,13 @@ class ServerUIPropertiesMenu implements ConfiguratorMenu, CallbackListener, Time
// Pagers // Pagers
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.39, $height * -0.44, 2); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize); $pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize); $pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
@ -182,7 +182,7 @@ class ServerUIPropertiesMenu implements ConfiguratorMenu, CallbackListener, Time
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.35, $height * -0.44, 1); $pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1); $pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(2); $pageCountLabel->setTextSize(2);

View File

@ -10,6 +10,7 @@ use ManiaControl\Admin\AuthenticationManager;
use ManiaControl\Callbacks\CallbackListener; use ManiaControl\Callbacks\CallbackListener;
use ManiaControl\Callbacks\TimerListener; use ManiaControl\Callbacks\TimerListener;
use ManiaControl\Configurator\ConfiguratorMenu; use ManiaControl\Configurator\ConfiguratorMenu;
use ManiaControl\Logger;
use ManiaControl\ManiaControl; use ManiaControl\ManiaControl;
use ManiaControl\Players\Player; use ManiaControl\Players\Player;
use Maniaplanet\DedicatedServer\Structures\VoteRatio; use Maniaplanet\DedicatedServer\Structures\VoteRatio;
@ -71,11 +72,20 @@ class VoteRatiosMenu implements CallbackListener, ConfiguratorMenu, TimerListene
$nameLabel = new Label_Text(); $nameLabel = new Label_Text();
$voteRatioFrame->addChild($nameLabel); $voteRatioFrame->addChild($nameLabel);
$nameLabel->setHorizontalAlign($nameLabel::LEFT)->setX($width * -0.46)->setSize($width * 0.7, $lineHeight)->setTextSize(2)->setTranslate(true)->setText($voteRatioDescription); $nameLabel->setHorizontalAlign($nameLabel::LEFT);
$nameLabel->setX($width * -0.5 + 4);
$nameLabel->setSize($width * 0.7, $lineHeight);
$nameLabel->setTextSize(2);
$nameLabel->setTranslate(true);
$nameLabel->setText($voteRatioDescription);
$entry = new Entry(); $entry = new Entry();
$voteRatioFrame->addChild($entry); $voteRatioFrame->addChild($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); $entry->setX($width * 0.5 - $width * 0.14 / 2 - 4);
$entry->setSize($width * 0.14, $lineHeight * 0.9);
$entry->setStyle(Label_Text::STYLE_TextValueSmall);
$entry->setTextSize($index === 0 ? 2 : 1);
$entry->setName(self::ACTION_PREFIX_VOTE_RATIO . $voteRatioCommand);
$voteRatio = $this->getVoteRatioForCommand($voteRatios, $voteRatioCommand); $voteRatio = $this->getVoteRatioForCommand($voteRatios, $voteRatioCommand);
if ($voteRatio) { if ($voteRatio) {
@ -157,6 +167,7 @@ class VoteRatiosMenu implements CallbackListener, ConfiguratorMenu, TimerListene
$success = $this->maniaControl->getClient()->setCallVoteRatios($newVoteRatios); $success = $this->maniaControl->getClient()->setCallVoteRatios($newVoteRatios);
if ($success) { if ($success) {
$this->maniaControl->getChat()->sendSuccess('Vote Ratios saved!', $player); $this->maniaControl->getChat()->sendSuccess('Vote Ratios saved!', $player);
Logger::log(AuthenticationManager::getAuthLevelName($player->authLevel) .' "'. $player->nickname . '" ('. $player->login .') changed the Vote Ratios');
} else { } else {
$this->maniaControl->getChat()->sendError('Vote Ratios saving failed!', $player); $this->maniaControl->getChat()->sendError('Vote Ratios saving failed!', $player);
} }

View File

@ -28,6 +28,7 @@ class SettingManager implements CallbackListener, UsageInformationAble {
const SETTING_ALLOW_UNLINK_SERVER = 'Allow to unlink settings with multiple servers'; const SETTING_ALLOW_UNLINK_SERVER = 'Allow to unlink settings with multiple servers';
const SETTING_DELETE_UNUSED_SETTING_AT_START = 'Delete unused settings at ManiaControl start'; const SETTING_DELETE_UNUSED_SETTING_AT_START = 'Delete unused settings at ManiaControl start';
const SETTING_DISABLE_SETTING_CACHE = 'Disable settings cache';
/* /*
* Private properties * Private properties
@ -36,6 +37,8 @@ class SettingManager implements CallbackListener, UsageInformationAble {
private $maniaControl = null; private $maniaControl = null;
/** @var Setting[] $storedSettings */ /** @var Setting[] $storedSettings */
private $storedSettings = array(); private $storedSettings = array();
/** @var bool $disableCache */
private $disableCache = false;
/** /**
* Construct a new setting manager instance * Construct a new setting manager instance
@ -51,6 +54,7 @@ class SettingManager implements CallbackListener, UsageInformationAble {
$this->initSetting($this, self::SETTING_ALLOW_UNLINK_SERVER, false); $this->initSetting($this, self::SETTING_ALLOW_UNLINK_SERVER, false);
$this->initSetting($this, self::SETTING_DELETE_UNUSED_SETTING_AT_START, true); $this->initSetting($this, self::SETTING_DELETE_UNUSED_SETTING_AT_START, true);
$this->initSetting($this, self::SETTING_DISABLE_SETTING_CACHE, false, "only for not linked settings");
} }
/** /**
@ -114,6 +118,15 @@ class SettingManager implements CallbackListener, UsageInformationAble {
trigger_error($mysqli->error, E_USER_ERROR); trigger_error($mysqli->error, E_USER_ERROR);
} }
} }
// Grow the default value
$mysqli->query("ALTER TABLE `" . self::TABLE_SETTINGS . "` MODIFY `default` VARCHAR(1000);");
if ($mysqli->error) {
// If not Duplicate
if ($mysqli->errno !== 1060) {
trigger_error($mysqli->error, E_USER_ERROR);
}
}
return $result; return $result;
} }
@ -121,6 +134,8 @@ class SettingManager implements CallbackListener, UsageInformationAble {
* Handle After Init Callback * Handle After Init Callback
*/ */
public function handleAfterInit() { public function handleAfterInit() {
$this->disableCache = boolval($this->getSettingValue($this, self::SETTING_DISABLE_SETTING_CACHE));
if ($this->disableCache) $this->clearStorage();
$this->deleteUnusedSettings(); $this->deleteUnusedSettings();
} }
@ -225,6 +240,7 @@ class SettingManager implements CallbackListener, UsageInformationAble {
* @param Setting $setting * @param Setting $setting
*/ */
private function storeSetting(Setting $setting) { private function storeSetting(Setting $setting) {
if ($this->disableCache && $setting->linked) return;
$this->storedSettings[$setting->class . $setting->setting] = $setting; $this->storedSettings[$setting->class . $setting->setting] = $setting;
} }
@ -433,7 +449,20 @@ class SettingManager implements CallbackListener, UsageInformationAble {
// Trigger Settings Changed Callback // Trigger Settings Changed Callback
if (!$init) { if (!$init) {
$this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SETTING_CHANGED, $setting); $this->maniaControl->getCallbackManager()->triggerCallback(self::CB_SETTING_CHANGED, $setting);
// during the init, value = default
if ($setting->setting === self::SETTING_DISABLE_SETTING_CACHE) {
$this->disableCache = boolval($setting->value);
if ($this->disableCache) {
$this->clearStorage();
} }
}
if ($this->disableCache && $setting->linked && isset($this->storedSettings[$setting->class . $setting->setting])) {
unset($this->storedSettings[$setting->class . $setting->setting]);
}
}
return true; return true;
} }

View File

@ -38,7 +38,6 @@ class SimpleStatsList implements ManialinkPageAnswerListener, CallbackListener,
const ACTION_OPEN_STATSLIST = 'SimpleStatsList.OpenStatsList'; const ACTION_OPEN_STATSLIST = 'SimpleStatsList.OpenStatsList';
const ACTION_SORT_STATS = 'SimpleStatsList.SortStats'; const ACTION_SORT_STATS = 'SimpleStatsList.SortStats';
const ACTION_PAGING_CHUNKS = 'SimpleStatsList.PagingChunk'; const ACTION_PAGING_CHUNKS = 'SimpleStatsList.PagingChunk';
const MAX_PLAYERS_PER_PAGE = 15;
const MAX_PAGES_PER_CHUNK = 10; const MAX_PAGES_PER_CHUNK = 10;
const CACHE_CURRENT_PAGE = 'SimpleStatsList.CurrentPage'; const CACHE_CURRENT_PAGE = 'SimpleStatsList.CurrentPage';
@ -146,7 +145,7 @@ class SimpleStatsList implements ManialinkPageAnswerListener, CallbackListener,
$chunkIndex = $this->getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount); $chunkIndex = $this->getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount);
$playerBeginIndex = $this->getChunkStatsBeginIndex($chunkIndex); $playerBeginIndex = $this->getChunkStatsBeginIndex($chunkIndex);
$pagesCount = ceil($totalPlayersCount / self::MAX_PLAYERS_PER_PAGE); $pagesCount = ceil($totalPlayersCount / $this->getPlayersPerPage());
$maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID); $maniaLink = new ManiaLink(ManialinkManager::MAIN_MLID);
$width = $this->statsWidth + 60; $width = $this->statsWidth + 60;
@ -231,16 +230,17 @@ class SimpleStatsList implements ManialinkPageAnswerListener, CallbackListener,
$posY -= 10; $posY -= 10;
$pageFrame = null; $pageFrame = null;
$playerIndex = 1 + $playerBeginIndex; $playerIndex = 1 + $playerBeginIndex;
$pageMaxCount = $this->getPlayersPerPage();
if (!isset($statRankings[$order])) { if (!isset($statRankings[$order])) {
return; return;
} }
//Slice Array to chunk length //Slice Array to chunk length
$statRankings[$order] = array_slice($statRankings[$order], $playerBeginIndex, self::MAX_PAGES_PER_CHUNK * self::MAX_PLAYERS_PER_PAGE, true); $statRankings[$order] = array_slice($statRankings[$order], $playerBeginIndex, self::MAX_PAGES_PER_CHUNK * $pageMaxCount, true);
$pageNumber = 1 + $chunkIndex * self::MAX_PAGES_PER_CHUNK; $pageNumber = 1 + $chunkIndex * self::MAX_PAGES_PER_CHUNK;
foreach ($statRankings[$order] as $playerId => $value) { foreach ($statRankings[$order] as $playerId => $value) {
if ($index % self::MAX_PLAYERS_PER_PAGE === 1) { if ($index % $pageMaxCount === 1) {
$pageFrame = new Frame(); $pageFrame = new Frame();
$frame->addChild($pageFrame); $frame->addChild($pageFrame);
$pageFrame->setZ(1); $pageFrame->setZ(1);
@ -314,17 +314,26 @@ class SimpleStatsList implements ManialinkPageAnswerListener, CallbackListener,
$pagerSize = 6.; $pagerSize = 6.;
$pagerPrev = new Quad_Icons64x64_1(); $pagerPrev = new Quad_Icons64x64_1();
$frame->addChild($pagerPrev); $frame->addChild($pagerPrev);
$pagerPrev->setPosition($width * 0.42, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev); $pagerPrev->setPosition($width * 0.5 - 12, $height * -0.5 + 5, 2);
$pagerPrev->setSize($pagerSize, $pagerSize);
$pagerPrev->setSubStyle($pagerPrev::SUBSTYLE_ArrowPrev);
$pagerNext = new Quad_Icons64x64_1(); $pagerNext = new Quad_Icons64x64_1();
$frame->addChild($pagerNext); $frame->addChild($pagerNext);
$pagerNext->setPosition($width * 0.45, $height * -0.44, 2)->setSize($pagerSize, $pagerSize)->setSubStyle($pagerNext::SUBSTYLE_ArrowNext); $pagerNext->setPosition($width * 0.5 - 5, $height * -0.5 + 5, 2);
$pagerNext->setSize($pagerSize, $pagerSize);
$pagerNext->setSubStyle($pagerNext::SUBSTYLE_ArrowNext);
$pageCountLabel = new Label_Text(); $pageCountLabel = new Label_Text();
$frame->addChild($pageCountLabel); $frame->addChild($pageCountLabel);
$pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT)->setPosition($width * 0.40, $height * -0.44, 1)->setStyle($pageCountLabel::STYLE_TextTitle1)->setTextSize(1); $pageCountLabel->setHorizontalAlign($pageCountLabel::RIGHT);
$pageCountLabel->setPosition($width * 0.5 - 16, $height * -0.5 + 5, 1);
$pageCountLabel->setStyle($pageCountLabel::STYLE_TextTitle1);
$pageCountLabel->setTextSize(1);
$paging->addButtonControl($pagerNext)->addButtonControl($pagerPrev)->setLabel($pageCountLabel); $paging->addButtonControl($pagerNext);
$paging->addButtonControl($pagerPrev);
$paging->setLabel($pageCountLabel);
$this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'SimpleStatsList'); $this->maniaControl->getManialinkManager()->displayWidget($maniaLink, $player, 'SimpleStatsList');
} }
@ -337,7 +346,7 @@ class SimpleStatsList implements ManialinkPageAnswerListener, CallbackListener,
* @return int * @return int
*/ */
private function getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount) { private function getChunkIndexFromPageNumber($pageIndex, $totalPlayersCount) {
$pagesCount = ceil($totalPlayersCount / self::MAX_PLAYERS_PER_PAGE); $pagesCount = ceil($totalPlayersCount / $this->getPlayersPerPage());
if ($pageIndex > $pagesCount - 1) { if ($pageIndex > $pagesCount - 1) {
$pageIndex = $pagesCount - 1; $pageIndex = $pagesCount - 1;
} }
@ -351,9 +360,20 @@ class SimpleStatsList implements ManialinkPageAnswerListener, CallbackListener,
* @return int * @return int
*/ */
private function getChunkStatsBeginIndex($chunkIndex) { private function getChunkStatsBeginIndex($chunkIndex) {
return $chunkIndex * self::MAX_PAGES_PER_CHUNK * self::MAX_PLAYERS_PER_PAGE; return $chunkIndex * self::MAX_PAGES_PER_CHUNK * $this->getPlayersPerPage();
} }
/**
* Get number of players per page
*
* @return int
*/
public function getPlayersPerPage() {
$pageheight = $this->maniaControl->getManialinkManager()->getStyleManager()->getListWidgetsHeight();
return floor($pageheight * 0.82 / 4);
}
/** /**
* Called on ManialinkPageAnswer * Called on ManialinkPageAnswer
* *

View File

@ -68,7 +68,7 @@ class PluginUpdateManager implements CallbackListener, CommandListener, TimerLis
* *
* @param Player $player * @param Player $player
*/ */
public function checkPluginsUpdate(Player $player = null) { public function checkPluginsUpdate(?Player $player = null) {
$message = 'Checking Plugins for newer Versions...'; $message = 'Checking Plugins for newer Versions...';
if ($player) { if ($player) {
$this->maniaControl->getChat()->sendInformation($message, $player); $this->maniaControl->getChat()->sendInformation($message, $player);
@ -119,6 +119,8 @@ class PluginUpdateManager implements CallbackListener, CommandListener, TimerLis
$message = "Plugins Update Check completed: There are {$updatesCount} Updates available!"; $message = "Plugins Update Check completed: There are {$updatesCount} Updates available!";
if ($player) { if ($player) {
$this->maniaControl->getChat()->sendSuccess($message, $player); $this->maniaControl->getChat()->sendSuccess($message, $player);
} else {
$this->maniaControl->getChat()->sendSuccessToAdmins($message . " (you can use //pluginsupdate)");
} }
Logger::log($message); Logger::log($message);
} }
@ -163,7 +165,7 @@ class PluginUpdateManager implements CallbackListener, CommandListener, TimerLis
* *
* @param Player $player * @param Player $player
*/ */
public function performPluginsUpdate(Player $player = null) { public function performPluginsUpdate(?Player $player = null) {
$pluginsUpdates = $this->getPluginsUpdates(); $pluginsUpdates = $this->getPluginsUpdates();
if (empty($pluginsUpdates)) { if (empty($pluginsUpdates)) {
$message = 'There are no Plugin Updates available!'; $message = 'There are no Plugin Updates available!';
@ -239,7 +241,7 @@ class PluginUpdateManager implements CallbackListener, CommandListener, TimerLis
* @param Player $player * @param Player $player
* @param bool $update * @param bool $update
*/ */
private function installPlugin(PluginUpdateData $pluginUpdateData, Player $player = null, $update = false) { private function installPlugin(PluginUpdateData $pluginUpdateData, ?Player $player = null, $update = false) {
if ($player && !$this->maniaControl->getAuthenticationManager()->checkPermission($player, InstallMenu::SETTING_PERMISSION_INSTALL_PLUGINS)) if ($player && !$this->maniaControl->getAuthenticationManager()->checkPermission($player, InstallMenu::SETTING_PERMISSION_INSTALL_PLUGINS))
{ {
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player); $this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);

View File

@ -64,7 +64,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
// Settings // Settings
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_ENABLE_UPDATECHECK, true); $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_AUTO_UPDATE, false);
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_UPDATECHECK_INTERVAL, 1); $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_UPDATECHECK_CHANNEL, $this->getUpdateChannels());
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_PERFORM_BACKUPS, true); $this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_PERFORM_BACKUPS, true);
@ -130,7 +130,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
* *
* @param UpdateData $coreUpdateData * @param UpdateData $coreUpdateData
*/ */
public function setCoreUpdateData(UpdateData $coreUpdateData = null) { public function setCoreUpdateData(?UpdateData $coreUpdateData = null) {
$this->coreUpdateData = $coreUpdateData; $this->coreUpdateData = $coreUpdateData;
} }
@ -189,7 +189,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
* *
* @param UpdateData $updateData * @param UpdateData $updateData
*/ */
public function handleUpdateCheck(UpdateData $updateData = null) { public function handleUpdateCheck(?UpdateData $updateData = null) {
if (!$this->checkUpdateData($updateData)) { if (!$this->checkUpdateData($updateData)) {
// No new update available // No new update available
return; return;
@ -218,7 +218,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
* @param UpdateData $updateData * @param UpdateData $updateData
* @return bool * @return bool
*/ */
public function checkUpdateData(UpdateData $updateData = null) { public function checkUpdateData(?UpdateData $updateData = null) {
if (!$updateData || !$updateData->url) { if (!$updateData || !$updateData->url) {
// Data corrupted // Data corrupted
return false; return false;
@ -268,7 +268,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
* @param UpdateData $updateData * @param UpdateData $updateData
* @return bool * @return bool
*/ */
public function checkUpdateDataBuildVersion(UpdateData $updateData = null) { public function checkUpdateDataBuildVersion(?UpdateData $updateData = null) {
if (!$updateData) { if (!$updateData) {
// Data corrupted // Data corrupted
return false; return false;
@ -310,7 +310,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
* @param Player $player * @param Player $player
* @return bool * @return bool
*/ */
public function performCoreUpdate(Player $player = null) { public function performCoreUpdate(?Player $player = null) {
if (!$this->coreUpdateData) { if (!$this->coreUpdateData) {
$message = 'Update failed: No update Data available!'; $message = 'Update failed: No update Data available!';
if ($player) { if ($player) {
@ -490,7 +490,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
return; return;
} }
$this->checkCoreUpdateAsync(function (UpdateData $updateData = null) use (&$player) { $this->checkCoreUpdateAsync(function (?UpdateData $updateData = null) use (&$player) {
if (!$this->checkUpdateData($updateData)) { if (!$this->checkUpdateData($updateData)) {
$this->maniaControl->getChat()->sendInformation('No Update available!', $player); $this->maniaControl->getChat()->sendInformation('No Update available!', $player);
return; return;
@ -516,7 +516,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
); );
$this->maniaControl->getChat()->sendInformation($message, $player); $this->maniaControl->getChat()->sendInformation($message, $player);
} else { } else {
$message = $this->maniaControl->getChat()->formatMesssage( $message = $this->maniaControl->getChat()->formatMessage(
'New Nightly Build (%s) available! (Current Build: %s)', 'New Nightly Build (%s) available! (Current Build: %s)',
$updateData->releaseDate, $updateData->releaseDate,
$buildDate $buildDate
@ -524,14 +524,14 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
$this->maniaControl->getChat()->sendSuccess($message, $player); $this->maniaControl->getChat()->sendSuccess($message, $player);
} }
} else { } else {
$message = $this->maniaControl->getChat()->formatMesssage( $message = $this->maniaControl->getChat()->formatMessage(
'New Nightly Build (%s) available!', 'New Nightly Build (%s) available!',
$updateData->releaseDate $updateData->releaseDate
); );
$this->maniaControl->getChat()->sendSuccess($message, $player); $this->maniaControl->getChat()->sendSuccess($message, $player);
} }
} else { } else {
$message = $this->maniaControl->getChat()->formatMesssage( $message = $this->maniaControl->getChat()->formatMessage(
'Update for Version %s available!', 'Update for Version %s available!',
$updateData->version $updateData->version
); );
@ -563,7 +563,7 @@ class UpdateManager implements CallbackListener, CommandListener, TimerListener,
* @param null $player * @param null $player
*/ */
private function checkAndHandleCoreUpdate($player = null) { private function checkAndHandleCoreUpdate($player = null) {
$this->checkCoreUpdateAsync(function (UpdateData $updateData = null) use (&$player) { $this->checkCoreUpdateAsync(function (?UpdateData $updateData = null) use (&$player) {
if (!$updateData) { if (!$updateData) {
if ($player) { if ($player) {
$this->maniaControl->getChat()->sendError('Update is currently not possible!', $player); $this->maniaControl->getChat()->sendError('Update is currently not possible!', $player);

View File

@ -89,7 +89,7 @@ abstract class Formatter implements UsageInformationAble {
*/ */
public static function formatTimeH($seconds) { public static function formatTimeH($seconds) {
$hrs = floor($seconds / 3600); $hrs = floor($seconds / 3600);
$mins = intval(($seconds / 60) % 60); $mins = intval(floor($seconds / 60) % 60);
$sec = intval($seconds % 60); $sec = intval($seconds % 60);
$hrs = str_pad($hrs, 2, '0', STR_PAD_LEFT); $hrs = str_pad($hrs, 2, '0', STR_PAD_LEFT);
@ -177,7 +177,7 @@ abstract class Formatter implements UsageInformationAble {
'Cambodia' => 'CAM', 'Cameroon' => 'CAR', // actually CMR 'Cambodia' => 'CAM', 'Cameroon' => 'CAR', // actually CMR
'Canada' => 'CAN', 'Cape Verde' => 'CPV', 'Central African Republic' => 'CAF', 'Chad' => 'CHA', 'Chile' => 'CHI', 'China' => 'CHN', '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', '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', 'Czech Republic' => 'CZE', 'Czech republic' => 'CZE', 'Czechia' => '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', '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', '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', 'Greece' => 'GRE', 'Grenada' => 'GRN', 'Guam' => 'GUM', 'Guatemala' => 'GUA', 'Guinea' => 'GUI', 'Guinea-Bissau' => 'GBS', 'Guyana' => 'GUY',

View File

@ -107,6 +107,16 @@ class SystemUtil {
Logger::log($message . 'FOUND!'); Logger::log($message . 'FOUND!');
} }
// Check for Xml
$message = 'Checking for installed xml ... ';
if (!extension_loaded('SimpleXML')) {
Logger::log($message . 'NOT FOUND!');
Logger::log(" -- You don't have xml installed! Check: https://www.php.net/manual/en/xml.setup.php");
$success = false;
} else {
Logger::log($message . 'FOUND!');
}
if (!$success) { if (!$success) {
// Missing requirements // Missing requirements
self::quit(); self::quit();

View File

@ -22,7 +22,7 @@ abstract class WebReader {
* @param callable $function * @param callable $function
* @return Response * @return Response
*/ */
public static function getUrl($url, callable $function = null) { public static function getUrl($url, ?callable $function = null) {
$request = static::newRequest($url); $request = static::newRequest($url);
$response = $request->send(); $response = $request->send();
if ($function) { if ($function) {
@ -73,7 +73,7 @@ abstract class WebReader {
* @param callable $function * @param callable $function
* @return Response * @return Response
*/ */
public static function postUrl($url, $content = null, callable $function = null) { public static function postUrl($url, $content = null, ?callable $function = null) {
$request = static::newRequest($url); $request = static::newRequest($url);
$request->getOptions()->set(CURLOPT_POST, true); // post method $request->getOptions()->set(CURLOPT_POST, true); // post method
if ($content) { if ($content) {

View File

@ -38,7 +38,7 @@ class CheckBox implements Renderable, ScriptFeatureable
* @param bool $default (optional) Default value * @param bool $default (optional) Default value
* @param Quad $quad (optional) CheckBox quad * @param Quad $quad (optional) CheckBox quad
*/ */
public function __construct($name = null, $default = null, Quad $quad = null) public function __construct($name = null, $default = null, ?Quad $quad = null)
{ {
$this->feature = new CheckBoxFeature(); $this->feature = new CheckBoxFeature();
if ($name) { if ($name) {
@ -143,6 +143,30 @@ class CheckBox implements Renderable, ScriptFeatureable
return $this->feature->getDisabledDesign(); return $this->feature->getDisabledDesign();
} }
/**
* Set script launched when clicking on the checkbox
*
* @api
* @param string $customScript script
* @return static
*/
public function setCustomScript(string $customScript)
{
$this->feature->setCustomScript($customScript);
return $this;
}
/**
* Get script launched when clicking on the checkbox
*
* @api
* @return string
*/
public function getCustomScript()
{
return $this->feature->getCustomScript();
}
/** /**
* Set the disabled design * Set the disabled design
* *

View File

@ -73,7 +73,7 @@ class CheckBoxDesign implements Imageable, Styleable, SubStyleable
public function setStyle($style) public function setStyle($style)
{ {
$this->style = (string)$style; $this->style = (string)$style;
$this->url = null; $this->imageUrl = null;
return $this; return $this;
} }
@ -91,7 +91,7 @@ class CheckBoxDesign implements Imageable, Styleable, SubStyleable
public function setSubStyle($subStyle) public function setSubStyle($subStyle)
{ {
$this->subStyle = (string)$subStyle; $this->subStyle = (string)$subStyle;
$this->url = null; $this->imageUrl = null;
return $this; return $this;
} }

View File

@ -39,7 +39,7 @@ class ValuePicker implements Renderable, ScriptFeatureable
* @param string $default (optional) Default value * @param string $default (optional) Default value
* @param Label $label (optional) ValuePicker label * @param Label $label (optional) ValuePicker label
*/ */
public function __construct($name = null, array $values = null, $default = null, Label $label = null) public function __construct($name = null, ?array $values = null, $default = null, ?Label $label = null)
{ {
$this->feature = new ValuePickerFeature(); $this->feature = new ValuePickerFeature();
if ($name) { if ($name) {

View File

@ -191,7 +191,7 @@ class Audio extends Control implements Playable, Scriptable
/** /**
* @see Scriptable::setScriptAction() * @see Scriptable::setScriptAction()
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null) public function setScriptAction($scriptAction, ?array $scriptActionParameters = null)
{ {
$this->scriptAction = (string)$scriptAction; $this->scriptAction = (string)$scriptAction;
$this->setScriptActionParameters($scriptActionParameters); $this->setScriptActionParameters($scriptActionParameters);
@ -209,7 +209,7 @@ class Audio extends Control implements Playable, Scriptable
/** /**
* @see Scriptable::setScriptActionParameters() * @see Scriptable::setScriptActionParameters()
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null) public function setScriptActionParameters(?array $scriptActionParameters = null)
{ {
$this->scriptActionParameters = $scriptActionParameters; $this->scriptActionParameters = $scriptActionParameters;
return $this; return $this;

View File

@ -48,6 +48,11 @@ class Entry extends Control implements NewLineable, Scriptable, Styleable, TextF
*/ */
protected $autoNewLine = null; protected $autoNewLine = null;
/**
* @var string $maxLength Text format
*/
protected $maxLength = null;
/** /**
* @var string $textFormat Text format * @var string $textFormat Text format
*/ */
@ -192,6 +197,30 @@ class Entry extends Control implements NewLineable, Scriptable, Styleable, TextF
return $this; return $this;
} }
/**
* Get text format
*
* @api
* @return int
*/
public function getMaxLength()
{
return $this->maxLength;
}
/**
* Set text format
*
* @api
* @param int $maxLength Max Length
* @return static
*/
public function setMaxLength($maxLength)
{
$this->maxLength = $maxLength;
return $this;
}
/** /**
* Get text format * Get text format
* *
@ -244,7 +273,7 @@ class Entry extends Control implements NewLineable, Scriptable, Styleable, TextF
/** /**
* @see Scriptable::setScriptAction() * @see Scriptable::setScriptAction()
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null) public function setScriptAction($scriptAction, ?array $scriptActionParameters = null)
{ {
$this->scriptAction = (string)$scriptAction; $this->scriptAction = (string)$scriptAction;
$this->setScriptActionParameters($scriptActionParameters); $this->setScriptActionParameters($scriptActionParameters);
@ -262,7 +291,7 @@ class Entry extends Control implements NewLineable, Scriptable, Styleable, TextF
/** /**
* @see Scriptable::setScriptActionParameters() * @see Scriptable::setScriptActionParameters()
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null) public function setScriptActionParameters(?array $scriptActionParameters = null)
{ {
$this->scriptActionParameters = $scriptActionParameters; $this->scriptActionParameters = $scriptActionParameters;
return $this; return $this;
@ -443,6 +472,9 @@ class Entry extends Control implements NewLineable, Scriptable, Styleable, TextF
if ($this->selectText) { if ($this->selectText) {
$domElement->setAttribute("selecttext", 1); $domElement->setAttribute("selecttext", 1);
} }
if ($this->maxLength) {
$domElement->setAttribute("maxlen", $this->maxLength);
}
if ($this->autoNewLine) { if ($this->autoNewLine) {
$domElement->setAttribute("autonewline", 1); $domElement->setAttribute("autonewline", 1);
} }

View File

@ -103,7 +103,7 @@ class Frame extends Control implements Container
* @deprecated Use Style * @deprecated Use Style
* @see Style * @see Style
*/ */
public function setFormat(Format $format = null) public function setFormat(?Format $format = null)
{ {
$this->format = $format; $this->format = $format;
return $this; return $this;

View File

@ -138,7 +138,7 @@ class Frame3d extends Frame implements Scriptable
/** /**
* @see Scriptable::setScriptAction() * @see Scriptable::setScriptAction()
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null) public function setScriptAction($scriptAction, ?array $scriptActionParameters = null)
{ {
$this->scriptAction = (string)$scriptAction; $this->scriptAction = (string)$scriptAction;
$this->setScriptActionParameters($scriptActionParameters); $this->setScriptActionParameters($scriptActionParameters);
@ -156,7 +156,7 @@ class Frame3d extends Frame implements Scriptable
/** /**
* @see Scriptable::setScriptActionParameters() * @see Scriptable::setScriptActionParameters()
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null) public function setScriptActionParameters(?array $scriptActionParameters = null)
{ {
$this->scriptActionParameters = $scriptActionParameters; $this->scriptActionParameters = $scriptActionParameters;
return $this; return $this;

View File

@ -467,7 +467,7 @@ class Label extends Control implements Actionable, Linkable, NewLineable, MultiL
/** /**
* @see Scriptable::setScriptAction() * @see Scriptable::setScriptAction()
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null) public function setScriptAction($scriptAction, ?array $scriptActionParameters = null)
{ {
$this->scriptAction = (string)$scriptAction; $this->scriptAction = (string)$scriptAction;
$this->setScriptActionParameters($scriptActionParameters); $this->setScriptActionParameters($scriptActionParameters);
@ -485,7 +485,7 @@ class Label extends Control implements Actionable, Linkable, NewLineable, MultiL
/** /**
* @see Scriptable::setScriptActionParameters() * @see Scriptable::setScriptActionParameters()
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null) public function setScriptActionParameters(?array $scriptActionParameters = null)
{ {
$this->scriptActionParameters = $scriptActionParameters; $this->scriptActionParameters = $scriptActionParameters;
return $this; return $this;

View File

@ -579,7 +579,7 @@ class Quad extends Control implements Actionable, BackgroundColorable, BgColorab
/** /**
* @see Scriptable::setScriptAction() * @see Scriptable::setScriptAction()
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null) public function setScriptAction($scriptAction, ?array $scriptActionParameters = null)
{ {
$this->scriptAction = (string)$scriptAction; $this->scriptAction = (string)$scriptAction;
$this->setScriptActionParameters($scriptActionParameters); $this->setScriptActionParameters($scriptActionParameters);
@ -597,7 +597,7 @@ class Quad extends Control implements Actionable, BackgroundColorable, BgColorab
/** /**
* @see Scriptable::setScriptActionParameters() * @see Scriptable::setScriptActionParameters()
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null) public function setScriptActionParameters(?array $scriptActionParameters = null)
{ {
$this->scriptActionParameters = $scriptActionParameters; $this->scriptActionParameters = $scriptActionParameters;
return $this; return $this;

View File

@ -26,6 +26,11 @@ class TextEdit extends Control implements MultiLineable, Scriptable, Styleable,
const FORMAT_Password = "Password"; const FORMAT_Password = "Password";
const FORMAT_NewPassword = "NewPassword"; const FORMAT_NewPassword = "NewPassword";
/**
* @var string $name TextEdit name
*/
protected $name = null;
/** /**
* @var string $default Default value * @var string $default Default value
*/ */
@ -276,7 +281,7 @@ class TextEdit extends Control implements MultiLineable, Scriptable, Styleable,
/** /**
* @see Scriptable::setScriptAction() * @see Scriptable::setScriptAction()
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null) public function setScriptAction($scriptAction, ?array $scriptActionParameters = null)
{ {
$this->scriptAction = (string)$scriptAction; $this->scriptAction = (string)$scriptAction;
$this->setScriptActionParameters($scriptActionParameters); $this->setScriptActionParameters($scriptActionParameters);
@ -294,7 +299,7 @@ class TextEdit extends Control implements MultiLineable, Scriptable, Styleable,
/** /**
* @see Scriptable::setScriptActionParameters() * @see Scriptable::setScriptActionParameters()
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null) public function setScriptActionParameters(?array $scriptActionParameters = null)
{ {
$this->scriptActionParameters = $scriptActionParameters; $this->scriptActionParameters = $scriptActionParameters;
return $this; return $this;

View File

@ -191,7 +191,7 @@ class Video extends Control implements Playable, Scriptable
/** /**
* @see Scriptable::setScriptAction() * @see Scriptable::setScriptAction()
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null) public function setScriptAction($scriptAction, ?array $scriptActionParameters = null)
{ {
$this->scriptAction = (string)$scriptAction; $this->scriptAction = (string)$scriptAction;
$this->setScriptActionParameters($scriptActionParameters); $this->setScriptActionParameters($scriptActionParameters);
@ -209,7 +209,7 @@ class Video extends Control implements Playable, Scriptable
/** /**
* @see Scriptable::setScriptActionParameters() * @see Scriptable::setScriptActionParameters()
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null) public function setScriptActionParameters(?array $scriptActionParameters = null)
{ {
$this->scriptActionParameters = $scriptActionParameters; $this->scriptActionParameters = $scriptActionParameters;
return $this; return $this;

View File

@ -41,7 +41,7 @@ class FrameModel implements Container, Identifiable, Renderable
* @param Renderable[] $children Children * @param Renderable[] $children Children
* @return static * @return static
*/ */
public static function create($modelId = null, array $children = null) public static function create($modelId = null, ?array $children = null)
{ {
return new static($modelId, $children); return new static($modelId, $children);
} }
@ -53,7 +53,7 @@ class FrameModel implements Container, Identifiable, Renderable
* @param string $modelId Model id * @param string $modelId Model id
* @param Renderable[] $children Children * @param Renderable[] $children Children
*/ */
public function __construct($modelId = null, array $children = null) public function __construct($modelId = null, ?array $children = null)
{ {
if ($modelId) { if ($modelId) {
$this->setId($modelId); $this->setId($modelId);
@ -176,7 +176,7 @@ class FrameModel implements Container, Identifiable, Renderable
* @deprecated Use Style * @deprecated Use Style
* @see Style * @see Style
*/ */
public function setFormat(Format $format = null) public function setFormat(?Format $format = null)
{ {
$this->format = $format; $this->format = $format;
return $this; return $this;

View File

@ -96,7 +96,7 @@ class ManiaLink
* @param Renderable[] $children (optional) Children * @param Renderable[] $children (optional) Children
* @return static * @return static
*/ */
public static function create($maniaLinkId = null, $version = null, $name = null, array $children = null) public static function create($maniaLinkId = null, $version = null, $name = null, ?array $children = null)
{ {
return new static($maniaLinkId, $version, $name, $children); return new static($maniaLinkId, $version, $name, $children);
} }
@ -110,7 +110,7 @@ class ManiaLink
* @param string $name (optional) Name * @param string $name (optional) Name
* @param Renderable[] $children (optional) Children * @param Renderable[] $children (optional) Children
*/ */
public function __construct($maniaLinkId = null, $version = null, $name = null, array $children = null) public function __construct($maniaLinkId = null, $version = null, $name = null, ?array $children = null)
{ {
if (is_string($version) && (!$name || is_array($name)) && !$children) { if (is_string($version) && (!$name || is_array($name)) && !$children) {
// backwards-compatibility (version has been introduced later, if it's a string it's supposed to be the name) // backwards-compatibility (version has been introduced later, if it's a string it's supposed to be the name)
@ -418,7 +418,7 @@ class ManiaLink
* @param Dico $dico Dictionary * @param Dico $dico Dictionary
* @return static * @return static
*/ */
public function setDico(Dico $dico = null) public function setDico(?Dico $dico = null)
{ {
$this->dico = $dico; $this->dico = $dico;
return $this; return $this;
@ -445,7 +445,7 @@ class ManiaLink
* @param Stylesheet $stylesheet Stylesheet * @param Stylesheet $stylesheet Stylesheet
* @return static * @return static
*/ */
public function setStylesheet(Stylesheet $stylesheet = null) public function setStylesheet(?Stylesheet $stylesheet = null)
{ {
$this->stylesheet = $stylesheet; $this->stylesheet = $stylesheet;
return $this; return $this;
@ -489,7 +489,7 @@ class ManiaLink
* @param Script $script Script * @param Script $script Script
* @return static * @return static
*/ */
public function setScript(Script $script = null) public function setScript(?Script $script = null)
{ {
$this->script = $script; $this->script = $script;
return $this; return $this;

View File

@ -29,7 +29,7 @@ class ManiaLinks
* @param ManiaLink[] $children ManiaLink children * @param ManiaLink[] $children ManiaLink children
* @return static * @return static
*/ */
public static function create(array $children = null) public static function create(?array $children = null)
{ {
return new static($children); return new static($children);
} }
@ -40,7 +40,7 @@ class ManiaLinks
* @api * @api
* @param ManiaLink[] $children ManiaLink children * @param ManiaLink[] $children ManiaLink children
*/ */
public function __construct(array $children = null) public function __construct(?array $children = null)
{ {
if ($children) { if ($children) {
$this->setChildren($children); $this->setChildren($children);
@ -162,7 +162,7 @@ class ManiaLinks
* @param CustomUI $customUI CustomUI object * @param CustomUI $customUI CustomUI object
* @return static * @return static
*/ */
public function setCustomUI(CustomUI $customUI = null) public function setCustomUI(?CustomUI $customUI = null)
{ {
$this->customUI = $customUI; $this->customUI = $customUI;
return $this; return $this;

View File

@ -41,7 +41,7 @@ class ActionTrigger extends ScriptFeature
* @param Control $control (optional) Action Control * @param Control $control (optional) Action Control
* @param string $labelName (optional) Script label name * @param string $labelName (optional) Script label name
*/ */
public function __construct($actionName = null, Control $control = null, $labelName = ScriptLabel::MOUSECLICK) public function __construct($actionName = null, ?Control $control = null, $labelName = ScriptLabel::MOUSECLICK)
{ {
if ($actionName) { if ($actionName) {
$this->setActionName($actionName); $this->setActionName($actionName);
@ -96,7 +96,7 @@ class ActionTrigger extends ScriptFeature
* @param Control $control Action Control * @param Control $control Action Control
* @return static * @return static
*/ */
public function setControl(Control $control = null) public function setControl(?Control $control = null)
{ {
if ($control) { if ($control) {
$control->checkId(); $control->checkId();

View File

@ -53,6 +53,11 @@ class CheckBoxFeature extends ScriptFeature
*/ */
protected $disabledDesign = null; protected $disabledDesign = null;
/**
* @var string $customScript Script executed when clicking on the checkbox
*/
protected $customScript = "";
/** /**
* Construct a new CheckBox Feature * Construct a new CheckBox Feature
* *
@ -61,7 +66,7 @@ class CheckBoxFeature extends ScriptFeature
* @param Entry $entry (optional) Hidden Entry * @param Entry $entry (optional) Hidden Entry
* @param bool $default (optional) Default value * @param bool $default (optional) Default value
*/ */
public function __construct(Quad $quad = null, Entry $entry = null, $default = null) public function __construct(?Quad $quad = null, ?Entry $entry = null, $default = null)
{ {
if ($quad) { if ($quad) {
$this->setQuad($quad); $this->setQuad($quad);
@ -199,6 +204,30 @@ class CheckBoxFeature extends ScriptFeature
return $this; return $this;
} }
/**
* Get script launched when clicking on the checkbox
*
* @api
* @return string
*/
public function getCustomScript()
{
return $this->customScript;
}
/**
* Set script launched when clicking on the checkbox
*
* @api
* @param string $customScript script
* @return static
*/
public function setCustomScript(string $customScript)
{
$this->customScript = $customScript;
return $this;
}
/** /**
* @see ScriptFeature::prepare() * @see ScriptFeature::prepare()
*/ */
@ -290,6 +319,7 @@ EntryId = \"{$entryId}\";
if (Event.ControlId == \"{$quadId}\") { if (Event.ControlId == \"{$quadId}\") {
declare Quad_CheckBox <=> (Event.Control as CMlQuad); declare Quad_CheckBox <=> (Event.Control as CMlQuad);
" . self::FUNCTION_UPDATE_QUAD_DESIGN . "(Quad_CheckBox); " . self::FUNCTION_UPDATE_QUAD_DESIGN . "(Quad_CheckBox);
" . $this->customScript . "
}"; }";
} }

View File

@ -41,7 +41,7 @@ class Clock extends ScriptFeature
* @param bool $showSeconds (optional) Show the seconds * @param bool $showSeconds (optional) Show the seconds
* @param bool $showFullDate (optional) Show the date * @param bool $showFullDate (optional) Show the date
*/ */
public function __construct(Label $label = null, $showSeconds = true, $showFullDate = false) public function __construct(?Label $label = null, $showSeconds = true, $showFullDate = false)
{ {
if ($label) { if ($label) {
$this->setLabel($label); $this->setLabel($label);

View File

@ -41,7 +41,7 @@ class ControlScript extends ScriptFeature
* @param string $scriptText (optional) Script text * @param string $scriptText (optional) Script text
* @param string $labelName (optional) Script Label name * @param string $labelName (optional) Script Label name
*/ */
public function __construct(Control $control = null, $scriptText = null, $labelName = ScriptLabel::MOUSECLICK) public function __construct(?Control $control = null, $scriptText = null, $labelName = ScriptLabel::MOUSECLICK)
{ {
if ($control) { if ($control) {
$this->setControl($control); $this->setControl($control);

View File

@ -35,7 +35,7 @@ class EntrySubmit extends ScriptFeature
* @param Entry $entry (optional) Entry Control * @param Entry $entry (optional) Entry Control
* @param string $url (optional) Submit url * @param string $url (optional) Submit url
*/ */
public function __construct(Entry $entry = null, $url = null) public function __construct(?Entry $entry = null, $url = null)
{ {
if ($entry) { if ($entry) {
$this->setEntry($entry); $this->setEntry($entry);

View File

@ -54,7 +54,7 @@ class GraphCurve extends ScriptFeature
* @param Graph $graph (optional) Graph * @param Graph $graph (optional) Graph
* @param array[] $points (optional) Points * @param array[] $points (optional) Points
*/ */
public function __construct(Graph $graph = null, array $points = null) public function __construct(?Graph $graph = null, ?array $points = null)
{ {
if ($graph) { if ($graph) {
$this->setGraph($graph); $this->setGraph($graph);
@ -200,7 +200,7 @@ class GraphCurve extends ScriptFeature
* @param float[] $color (optional) Color * @param float[] $color (optional) Color
* @return static * @return static
*/ */
public function setColor(array $color = null) public function setColor(?array $color = null)
{ {
$this->color = $color; $this->color = $color;
return $this; return $this;

View File

@ -38,7 +38,7 @@ class GraphSettings extends ScriptFeature
* @api * @api
* @param Graph $graph (optional) Graph * @param Graph $graph (optional) Graph
*/ */
public function __construct(Graph $graph = null) public function __construct(?Graph $graph = null)
{ {
if ($graph) { if ($graph) {
$this->setGraph($graph); $this->setGraph($graph);

View File

@ -35,7 +35,7 @@ class MapInfo extends ScriptFeature
* @param Control $control (optional) Map Info Control * @param Control $control (optional) Map Info Control
* @param string $labelName (optional) Script Label name * @param string $labelName (optional) Script Label name
*/ */
public function __construct(Control $control = null, $labelName = ScriptLabel::MOUSECLICK) public function __construct(?Control $control = null, $labelName = ScriptLabel::MOUSECLICK)
{ {
if ($control) { if ($control) {
$this->setControl($control); $this->setControl($control);

View File

@ -40,7 +40,7 @@ class Menu extends ScriptFeature
* @param Control $control (optional) Toggled Menu Control * @param Control $control (optional) Toggled Menu Control
* @param bool $isStartElement (optional) Whether the Menu should start with the given Element * @param bool $isStartElement (optional) Whether the Menu should start with the given Element
*/ */
public function __construct(Control $item = null, Control $control = null, $isStartElement = true) public function __construct(?Control $item = null, ?Control $control = null, $isStartElement = true)
{ {
if ($item && $control) { if ($item && $control) {
$this->addItem($item, $control, $isStartElement); $this->addItem($item, $control, $isStartElement);
@ -116,7 +116,7 @@ class Menu extends ScriptFeature
* @param MenuElement $startElement Start Element * @param MenuElement $startElement Start Element
* @return static * @return static
*/ */
public function setStartElement(MenuElement $startElement = null) public function setStartElement(?MenuElement $startElement = null)
{ {
$this->startElement = $startElement; $this->startElement = $startElement;
if ($startElement && !in_array($startElement, $this->elements, true)) { if ($startElement && !in_array($startElement, $this->elements, true)) {

View File

@ -32,7 +32,7 @@ class MenuElement
* @param Control $item (optional) Item Control in the Menu bar * @param Control $item (optional) Item Control in the Menu bar
* @param Control $control (optional) Toggled Menu Control * @param Control $control (optional) Toggled Menu Control
*/ */
public function __construct(Control $item = null, Control $control = null) public function __construct(?Control $item = null, ?Control $control = null)
{ {
if ($item) { if ($item) {
$this->setItem($item); $this->setItem($item);

View File

@ -73,7 +73,7 @@ class Paging extends ScriptFeature
* @param PagingPage[] $pages (optional) Pages * @param PagingPage[] $pages (optional) Pages
* @param PagingButton[] $buttons (optional) Pageing Buttons * @param PagingButton[] $buttons (optional) Pageing Buttons
*/ */
public function __construct(Label $label = null, array $pages = null, array $buttons = null) public function __construct(?Label $label = null, ?array $pages = null, ?array $buttons = null)
{ {
if ($label) { if ($label) {
$this->setLabel($label); $this->setLabel($label);

View File

@ -32,7 +32,7 @@ class PagingButton
* @param Control $control (optional) Paging Control * @param Control $control (optional) Paging Control
* @param int $pagingCount (optional) Number of browsed pages per click * @param int $pagingCount (optional) Number of browsed pages per click
*/ */
public function __construct(Control $control = null, $pagingCount = 1) public function __construct(?Control $control = null, $pagingCount = 1)
{ {
if ($control) { if ($control) {
$this->setControl($control); $this->setControl($control);

View File

@ -31,7 +31,7 @@ class PagingPage
* @param Control $control (optional) Page Control * @param Control $control (optional) Page Control
* @param int $pageNumber (optional) Number of the Page * @param int $pageNumber (optional) Number of the Page
*/ */
public function __construct(Control $control = null, $pageNumber = null) public function __construct(?Control $control = null, $pageNumber = null)
{ {
if ($control) { if ($control) {
$this->setControl($control); $this->setControl($control);

View File

@ -46,7 +46,7 @@ class PlayerProfile extends ScriptFeature
* @param Control $control (optional) Profile Control * @param Control $control (optional) Profile Control
* @param string $labelName (optional) Script Label name * @param string $labelName (optional) Script Label name
*/ */
public function __construct($login = null, Control $control = null, $labelName = ScriptLabel::MOUSECLICK, $titleId = "Trackmania") public function __construct($login = null, ?Control $control = null, $labelName = ScriptLabel::MOUSECLICK, $titleId = "Trackmania")
{ {
if ($login) { if ($login) {
$this->setLogin($login); $this->setLogin($login);
@ -181,8 +181,8 @@ class PlayerProfile extends ScriptFeature
$login = Builder::escapeText($this->login); $login = Builder::escapeText($this->login);
if ($this->titleId == "Trackmania") { if ($this->titleId == "Trackmania") {
$apicall = "declare Text LibTMxSMRaceScoresTable_OpenProfileLogin for ClientUI = \"\"; $apicall = "declare Text TMGame_ScoresTable_OpenProfileUserId for ClientUI = \"\";
LibTMxSMRaceScoresTable_OpenProfileLogin = {$login};"; TMGame_ScoresTable_OpenProfileUserId = {$login};";
} else { } else {
$apicall = "ShowProfile({$login});"; $apicall = "ShowProfile({$login});";
} }

View File

@ -27,7 +27,7 @@ class Preload extends ScriptFeature
* @api * @api
* @param string[] $imageUrls (optional) Image urls * @param string[] $imageUrls (optional) Image urls
*/ */
public function __construct(array $imageUrls = null) public function __construct(?array $imageUrls = null)
{ {
if ($imageUrls) { if ($imageUrls) {
$this->setImageUrls($imageUrls); $this->setImageUrls($imageUrls);

View File

@ -40,7 +40,7 @@ class RadioButtonGroupFeature extends ScriptFeature
* @api * @api
* @param Entry $entry (optional) Hidden Entry * @param Entry $entry (optional) Hidden Entry
*/ */
public function __construct(Entry $entry = null) public function __construct(?Entry $entry = null)
{ {
if ($entry) { if ($entry) {
$this->setEntry($entry); $this->setEntry($entry);

View File

@ -54,8 +54,8 @@ class Toggle extends ScriptFeature
* @param bool $onlyHide (optional) If it should only hide the Control but not toggle * @param bool $onlyHide (optional) If it should only hide the Control but not toggle
*/ */
public function __construct( public function __construct(
Control $togglingControl = null, ?Control $togglingControl = null,
Control $toggledControl = null, ?Control $toggledControl = null,
$labelName = ScriptLabel::MOUSECLICK, $labelName = ScriptLabel::MOUSECLICK,
$onlyShow = false, $onlyShow = false,
$onlyHide = false $onlyHide = false

View File

@ -54,7 +54,7 @@ class Tooltip extends ScriptFeature
* @param bool $invert (optional) If the visibility toggling should be inverted * @param bool $invert (optional) If the visibility toggling should be inverted
* @param string $text (optional) Text to display if the TooltipControl is a Label * @param string $text (optional) Text to display if the TooltipControl is a Label
*/ */
public function __construct(Control $hoverControl = null, Control $tooltipControl = null, $stayOnClick = null, $invert = null, $text = null) public function __construct(?Control $hoverControl = null, ?Control $tooltipControl = null, $stayOnClick = null, $invert = null, $text = null)
{ {
if ($hoverControl) { if ($hoverControl) {
$this->setHoverControl($hoverControl); $this->setHoverControl($hoverControl);

View File

@ -85,7 +85,7 @@ class UISound extends ScriptFeature
* @param int $variant (optional) Sound variant * @param int $variant (optional) Sound variant
* @param string $labelName (optional) Script Label name * @param string $labelName (optional) Script Label name
*/ */
public function __construct($soundName = null, Control $control = null, $variant = 0, $labelName = ScriptLabel::MOUSECLICK) public function __construct($soundName = null, ?Control $control = null, $variant = 0, $labelName = ScriptLabel::MOUSECLICK)
{ {
if ($soundName) { if ($soundName) {
$this->setSoundName($soundName); $this->setSoundName($soundName);
@ -143,7 +143,7 @@ class UISound extends ScriptFeature
* @param Control $control (optional) Sound Control * @param Control $control (optional) Sound Control
* @return static * @return static
*/ */
public function setControl(Control $control = null) public function setControl(?Control $control = null)
{ {
if ($control) { if ($control) {
$control->checkId(); $control->checkId();

View File

@ -56,7 +56,7 @@ class ValuePickerFeature extends ScriptFeature
* @param string[] $values (optional) Possible values * @param string[] $values (optional) Possible values
* @param string $default (optional) Default value * @param string $default (optional) Default value
*/ */
public function __construct(Label $label = null, Entry $entry = null, array $values = null, $default = null) public function __construct(?Label $label = null, ?Entry $entry = null, ?array $values = null, $default = null)
{ {
if ($label) { if ($label) {
$this->setLabel($label); $this->setLabel($label);

View File

@ -150,7 +150,7 @@ class Stylesheet
* @param Mood $mood Mood * @param Mood $mood Mood
* @return static * @return static
*/ */
public function setMood(Mood $mood = null) public function setMood(?Mood $mood = null)
{ {
$this->mood = $mood; $this->mood = $mood;
return $this; return $this;

View File

@ -90,6 +90,6 @@ interface Container
* @deprecated Use Style * @deprecated Use Style
* @see Style * @see Style
*/ */
public function setFormat(Format $format = null); public function setFormat(?Format $format = null);
} }

View File

@ -45,7 +45,7 @@ interface Scriptable
* @param string[] $scriptActionParameters (optional) Script action parameters * @param string[] $scriptActionParameters (optional) Script action parameters
* @return static * @return static
*/ */
public function setScriptAction($scriptAction, array $scriptActionParameters = null); public function setScriptAction($scriptAction, ?array $scriptActionParameters = null);
/** /**
* Get script action parameters * Get script action parameters
@ -62,6 +62,6 @@ interface Scriptable
* @param string[] $scriptActionParameters (optional) Script action parameters * @param string[] $scriptActionParameters (optional) Script action parameters
* @return static * @return static
*/ */
public function setScriptActionParameters(array $scriptActionParameters = null); public function setScriptActionParameters(?array $scriptActionParameters = null);
} }

2333
libs/Maniaplanet/DedicatedServer/Connection.php Executable file → Normal file

File diff suppressed because it is too large Load Diff

View File

@ -9,46 +9,52 @@ namespace Maniaplanet\DedicatedServer\Structures;
abstract class AbstractStructure abstract class AbstractStructure
{ {
static public function fromArray($array) public static function fromArrayOfArray($array)
{ {
if(!is_array($array)) if (!is_array($array)) {
return $array; return $array;
$object = new static;
foreach($array as $key => $value)
$object->{lcfirst($key)} = $value;
return $object;
} }
static public function fromArrayOfArray($array) $result = [];
{ foreach ($array as $key => $value) {
if(!is_array($array))
return $array;
$result = array();
foreach($array as $key => $value)
$result[$key] = static::fromArray($value); $result[$key] = static::fromArray($value);
}
return $result; return $result;
} }
static public function getPropertyFromArray($array, $property) public static function fromArray($array)
{
if (!is_array($array)) {
return $array;
}
$object = new static;
foreach ($array as $key => $value) {
$object->{lcfirst($key)} = $value;
}
return $object;
}
public static function getPropertyFromArray($array, $property)
{ {
return array_map(get_called_class() . '::extractProperty', $array, array_fill(0, count($array), $property)); return array_map(get_called_class() . '::extractProperty', $array, array_fill(0, count($array), $property));
} }
static protected function extractProperty($element, $property) protected static function extractProperty($element, $property)
{ {
if(!is_a($element, get_called_class()) || !property_exists($element, $property)) if (!is_a($element, get_called_class()) || !property_exists($element, $property)) {
throw new \InvalidArgumentException('property ' . $property . ' does not exists in class: ' . get_called_class()); throw new \InvalidArgumentException('property ' . $property . ' does not exists in class: ' . get_called_class());
}
return $element->$property; return $element->$property;
} }
function toArray() function toArray()
{ {
$out = array(); $out = [];
foreach(get_object_vars($this) as $key => $value) foreach (get_object_vars($this) as $key => $value) {
$out[ucfirst($key)] = $value; $out[ucfirst($key)] = $value;
}
return $out; return $out;
} }
} }

View File

@ -28,7 +28,7 @@ class NetworkStats extends AbstractStructure
/** @var PlayerNetInfo[] */ /** @var PlayerNetInfo[] */
public $playerNetInfos; public $playerNetInfos;
static public function fromArray($array) public static function fromArray($array)
{ {
$object = parent::fromArray($array); $object = parent::fromArray($array);
$object->playerNetInfos = PlayerNetInfo::fromArrayOfArray($object->playerNetInfos); $object->playerNetInfos = PlayerNetInfo::fromArrayOfArray($object->playerNetInfos);

1
libs/Maniaplanet/DedicatedServer/Structures/Player.php Executable file → Normal file
View File

@ -4,6 +4,7 @@
* *
* @license http://www.gnu.org/licenses/lgpl.html LGPL License 3 * @license http://www.gnu.org/licenses/lgpl.html LGPL License 3
*/ */
namespace Maniaplanet\DedicatedServer\Structures; namespace Maniaplanet\DedicatedServer\Structures;
class Player extends AbstractStructure class Player extends AbstractStructure

View File

@ -46,10 +46,22 @@ class PlayerDetailedInfo extends Player
/** @var string */ /** @var string */
public $broadcasterLogin; public $broadcasterLogin;
/** @var string[] */ /** @var string[] */
public $allies = array(); public $allies = [];
/** @var string */ /** @var string */
public $clubLink; public $clubLink;
/**
* @return PlayerDetailedInfo
*/
public static function fromArray($array)
{
$object = parent::fromArray($array);
$object->avatar = FileDesc::fromArray($object->avatar);
$object->skins = Skin::fromArrayOfArray($object->skins);
$object->ladderStats = LadderStats::fromArray($object->ladderStats);
return $object;
}
/** /**
* @return string[] * @return string[]
*/ */
@ -57,16 +69,4 @@ class PlayerDetailedInfo extends Player
{ {
return explode('|', $this->path); return explode('|', $this->path);
} }
/**
* @return PlayerDetailedInfo
*/
static public function fromArray($array)
{
$object = parent::fromArray($array);
$object->avatar = FileDesc::fromArray($object->avatar);
$object->skins = Skin::fromArrayOfArray($object->skins);
$object->ladderStats = LadderStats::fromArray($object->ladderStats);
return $object;
}
} }

View File

@ -20,7 +20,7 @@ class PlayerInfo extends Player
/** @var bool */ /** @var bool */
public $isInOfficialMode; public $isInOfficialMode;
/** @var int */ /** @var int */
public $ladderScore; public $ladderScore; // TODO CHECK IF EXISTS
/** @var int */ /** @var int */
public $ladderRanking; public $ladderRanking;
/** @var int */ /** @var int */
@ -63,7 +63,7 @@ class PlayerInfo extends Player
/** /**
* @return PlayerInfo * @return PlayerInfo
*/ */
static public function fromArray($array) public static function fromArray($array)
{ {
$object = parent::fromArray($array); $object = parent::fromArray($array);

View File

@ -18,9 +18,9 @@ class ScriptInfo extends AbstractStructure
/** @var string */ /** @var string */
public $version; public $version;
/** @var ScriptSettings[] */ /** @var ScriptSettings[] */
public $paramDescs = array(); public $paramDescs = [];
/** @var Command[] */ /** @var Command[] */
public $commandDescs = array(); public $commandDescs = [];
/** /**
* @return ScriptInfo * @return ScriptInfo

View File

@ -27,7 +27,7 @@ class ServerOptions extends AbstractStructure
* @internal * @internal
* @return bool * @return bool
*/ */
function isValid() public function isValid(): bool
{ {
return is_string($this->name) return is_string($this->name)
&& is_string($this->comment) && is_string($this->comment)
@ -41,15 +41,16 @@ class ServerOptions extends AbstractStructure
* @internal * @internal
* @return mixed[] * @return mixed[]
*/ */
function toSetterArray() public function toSetterArray()
{ {
$out = array(); $out = [];
foreach(get_object_vars($this) as $key => $value) foreach (get_object_vars($this) as $key => $value) {
{ if (str_starts_with($key, 'current') || $value === null) {
if(substr($key, 0, 7) == 'current' || $value === null)
continue; continue;
if($key == 'nextUseChangingValidationSeed') }
if ($key === 'nextUseChangingValidationSeed') {
$key = 'useChangingValidationSeed'; $key = 'useChangingValidationSeed';
}
$out[ucfirst($key)] = $value; $out[ucfirst($key)] = $value;
} }
return $out; return $out;

View File

@ -0,0 +1,28 @@
<?php
/**
* ManiaPlanet dedicated server Xml-RPC client
*
* @license http://www.gnu.org/licenses/lgpl.html LGPL License 3
*/
namespace Maniaplanet\DedicatedServer\Structures;
class ServerPlugin extends AbstractStructure
{
/** @var string */
public $name;
/** @var string[] */
public $settingsValues;
/** @var ScriptSettings[] */
public $settingsDesc = array();
/**
* @return ScriptInfo
*/
public static function fromArray($array)
{
$object = parent::fromArray($array);
$object->settingsDesc = ScriptSettings::fromArrayOfArray($object->paramDescs);
return $object;
}
}

View File

@ -27,7 +27,7 @@ class Vote extends AbstractStructure
* @param string $cmdName * @param string $cmdName
* @param mixed[] $cmdParam * @param mixed[] $cmdParam
*/ */
function __construct($cmdName='', $cmdParam=array()) function __construct($cmdName = '', $cmdParam = [])
{ {
$this->cmdName = $cmdName; $this->cmdName = $cmdName;
$this->cmdParam = $cmdParam; $this->cmdParam = $cmdParam;

View File

@ -7,4 +7,6 @@
namespace Maniaplanet\DedicatedServer\Xmlrpc; namespace Maniaplanet\DedicatedServer\Xmlrpc;
class Exception extends \Exception {} class Exception extends \Exception
{
}

View File

@ -7,8 +7,10 @@
namespace Maniaplanet\DedicatedServer\Xmlrpc; namespace Maniaplanet\DedicatedServer\Xmlrpc;
class FaultException extends Exception { class FaultException extends Exception
static function create($faultString, $faultCode) { {
static function create($faultString, $faultCode)
{
switch ($faultString) { switch ($faultString) {
case 'Password incorrect.': case 'Password incorrect.':
case 'Permission denied.': case 'Permission denied.':
@ -31,6 +33,7 @@ class FaultException extends Exception {
case 'Already waiting for a vote.': case 'Already waiting for a vote.':
case 'You must stop server first.': case 'You must stop server first.':
return new LockedFeatureException($faultString, $faultCode); return new LockedFeatureException($faultString, $faultCode);
case 'Can\'t kick server.':
case 'Login or Uid unknown.': case 'Login or Uid unknown.':
case 'Login unknown.': case 'Login unknown.':
case 'Payer login unknown.': case 'Payer login unknown.':
@ -110,44 +113,58 @@ class FaultException extends Exception {
} }
} }
class AuthenticationException extends FaultException { class AuthenticationException extends FaultException
{
} }
class UnavailableFeatureException extends FaultException { class UnavailableFeatureException extends FaultException
{
} }
class LockedFeatureException extends FaultException { class LockedFeatureException extends FaultException
{
} }
class UnknownPlayerException extends FaultException { class UnknownPlayerException extends FaultException
{
} }
class PlayerStateException extends FaultException { class PlayerStateException extends FaultException
{
} }
class AlreadyInListException extends FaultException { class AlreadyInListException extends FaultException
{
} }
class NotInListException extends FaultException { class NotInListException extends FaultException
{
} }
class IndexOutOfBoundException extends FaultException { class IndexOutOfBoundException extends FaultException
{
} }
class NextMapException extends FaultException { class NextMapException extends FaultException
{
} }
class ChangeInProgressException extends FaultException { class ChangeInProgressException extends FaultException
{
} }
class InvalidMapException extends FaultException { class InvalidMapException extends FaultException
{
} }
class GameModeException extends FaultException { class GameModeException extends FaultException
{
} }
class ServerOptionsException extends FaultException { class ServerOptionsException extends FaultException
{
} }
class FileException extends FaultException { class FileException extends FaultException
{
} }

View File

@ -9,18 +9,18 @@ namespace Maniaplanet\DedicatedServer\Xmlrpc;
class GbxRemote class GbxRemote
{ {
const MAX_REQUEST_SIZE = 0x200000; // 2MB const MAX_REQUEST_SIZE = 0x400000; // 4MB
const MAX_RESPONSE_SIZE = 0x400000; // 4MB const MAX_RESPONSE_SIZE = 0x400000; // 4MB
public static $received; public static $received;
public static $sent; public static $sent;
private $socket; private $socket;
private $readTimeout = array('sec' => 30, 'usec' => 0); private $readTimeout = ['sec' => 5, 'usec' => 0];
private $writeTimeout = array('sec' => 30, 'usec' => 0); private $writeTimeout = ['sec' => 5, 'usec' => 0];
private $requestHandle; private $requestHandle;
private $callbacksBuffer = array(); private $callbacksBuffer = [];
private $multicallBuffer = array(); private $multicallBuffer = [];
private $lastNetworkActivity = 0; private $lastNetworkActivity = 0;
/** /**
@ -34,25 +34,99 @@ class GbxRemote
$this->connect($host, $port, $timeout); $this->connect($host, $port, $timeout);
} }
/**
* @param string $host
* @param int $port
* @param int $timeout
* @throws TransportException
*/
private function connect($host, $port, $timeout)
{
$this->socket = @fsockopen($host, $port, $errno, $errstr, $timeout);
if (!$this->socket) {
throw new TransportException('Cannot open socket', TransportException::NOT_INITIALIZED);
}
stream_set_read_buffer($this->socket, 0);
stream_set_write_buffer($this->socket, 0);
// handshake
$header = $this->read(15);
if ($header === false) {
if (!is_resource($this->socket)) {
$this->onIoFailure('socket closed during handshake');
}
$this->onIoFailure(sprintf('during handshake (%s)', socket_strerror(socket_last_error())));
}
extract(unpack('Vsize/a*protocol', $header));
/** @var $size int */
/** @var $protocol string */
if ($size != 11 || $protocol != 'GBXRemote 2') {
throw new TransportException('Wrong protocol header', TransportException::WRONG_PROTOCOL);
}
$this->lastNetworkActivity = time();
}
/**
* @param int $size
* @return boolean|string
*/
private function read($size)
{
@stream_set_timeout($this->socket, $this->readTimeout['sec'], $this->readTimeout['usec']);
$data = '';
while (strlen($data) < $size) {
$buf = @fread($this->socket, $size - strlen($data));
if ($buf === '' || $buf === false) {
return false;
}
$data .= $buf;
}
self::$received += $size;
return $data;
}
/**
* @param string $when
* @throws TransportException
*/
private function onIoFailure($when)
{
$meta = stream_get_meta_data($this->socket);
if ($meta['timed_out']) {
throw new TransportException('Connection timed out ' . $when, TransportException::TIMED_OUT);
}
throw new TransportException('Connection interrupted ' . $when, TransportException::INTERRUPTED);
}
function __destruct() function __destruct()
{ {
$this->terminate(); $this->terminate();
} }
public function terminate()
{
if ($this->socket) {
fclose($this->socket);
$this->socket = null;
}
}
/** /**
* Change timeouts * Change timeouts
* @param int $read read timeout (in ms), 0 to leave unchanged * @param int $read read timeout (in ms), 0 to leave unchanged
* @param int $write write timeout (in ms), 0 to leave unchanged * @param int $write write timeout (in ms), 0 to leave unchanged
*/ */
function setTimeouts($read=0, $write=0) public function setTimeouts($read = 0, $write = 0)
{
if($read)
{ {
if ($read) {
$this->readTimeout['sec'] = (int)($read / 1000); $this->readTimeout['sec'] = (int)($read / 1000);
$this->readTimeout['usec'] = ($read % 1000) * 1000; $this->readTimeout['usec'] = ($read % 1000) * 1000;
} }
if($write) if ($write) {
{
$this->writeTimeout['sec'] = (int)($write / 1000); $this->writeTimeout['sec'] = (int)($write / 1000);
$this->writeTimeout['usec'] = ($write % 1000) * 1000; $this->writeTimeout['usec'] = ($write % 1000) * 1000;
} }
@ -68,39 +142,49 @@ class GbxRemote
} }
/** /**
* @param string $host
* @param int $port
* @param int $timeout
* @throws TransportException * @throws TransportException
*/ */
private function connect($host, $port, $timeout) private function assertConnected()
{ {
$this->socket = @fsockopen($host, $port, $errno, $errstr, $timeout); if (!$this->socket) {
if(!$this->socket) throw new TransportException('Connection not initialized', TransportException::NOT_INITIALIZED);
throw new TransportException('Cannot open socket', TransportException::NOT_INITIALIZED); }
stream_set_read_buffer($this->socket, 0);
stream_set_write_buffer($this->socket, 0);
// handshake
$header = $this->read(15);
if($header === false)
$this->onIoFailure(sprintf('during handshake (%s)', socket_strerror(socket_last_error($this->socket))));
extract(unpack('Vsize/a*protocol', $header));
/** @var $size int */
/** @var $protocol string */
if($size != 11 || $protocol != 'GBXRemote 2')
throw new TransportException('Wrong protocol header', TransportException::WRONG_PROTOCOL);
$this->lastNetworkActivity = time();
} }
function terminate() /**
* @param string $method
* @param mixed[] $args
*/
function addCall($method, $args)
{ {
if($this->socket) $this->multicallBuffer[] = [
'methodName' => $method,
'params' => $args
];
}
/**
* @return mixed
*/
function multiquery()
{ {
fclose($this->socket); switch (count($this->multicallBuffer)) {
$this->socket = null; case 0:
return [];
case 1:
$call = array_shift($this->multicallBuffer);
return [$this->query($call['methodName'], $call['params'])];
default:
$result = $this->query('system.multicall', [$this->multicallBuffer]);
foreach ($result as &$value) {
if (isset($value['faultCode'])) {
$value = FaultException::create($value['faultString'], $value['faultCode']);
} else {
$value = $value[0];
}
}
$this->multicallBuffer = [];
return $result;
} }
} }
@ -110,19 +194,19 @@ class GbxRemote
* @return mixed * @return mixed
* @throws MessageException * @throws MessageException
*/ */
function query($method, $args=array()) function query($method, $args = [])
{ {
$this->assertConnected(); $this->assertConnected();
$xml = Request::encode($method, $args); $xml = Request::encode($method, $args);
if(strlen($xml) > self::MAX_REQUEST_SIZE-8) if (strlen($xml) > self::MAX_REQUEST_SIZE - 8) {
{ if ($method != 'system.multicall' || count($args[0]) < 2) {
if($method != 'system.multicall' || count($args[0]) < 2)
throw new MessageException('Request too large', MessageException::REQUEST_TOO_LARGE); throw new MessageException('Request too large', MessageException::REQUEST_TOO_LARGE);
}
$mid = count($args[0]) >> 1; $mid = count($args[0]) >> 1;
$res1 = $this->query('system.multicall', array(array_slice($args[0], 0, $mid))); $res1 = $this->query('system.multicall', [array_slice($args[0], 0, $mid)]);
$res2 = $this->query('system.multicall', array(array_slice($args[0], $mid))); $res2 = $this->query('system.multicall', [array_slice($args[0], $mid)]);
return array_merge($res1, $res2); return array_merge($res1, $res2);
} }
@ -131,60 +215,40 @@ class GbxRemote
} }
/** /**
* @param string $method * @param string $xml
* @param mixed[] $args
*/
function addCall($method, $args)
{
$this->multicallBuffer[] = array(
'methodName' => $method,
'params' => $args
);
}
/**
* @return mixed
*/
function multiquery()
{
switch(count($this->multicallBuffer))
{
case 0:
return array();
case 1:
$call = array_shift($this->multicallBuffer);
return array($this->query($call['methodName'], $call['params']));
default:
$result = $this->query('system.multicall', array($this->multicallBuffer));
foreach($result as &$value)
if(isset($value['faultCode']))
$value = FaultException::create($value['faultString'], $value['faultCode']);
else
$value = $value[0];
$this->multicallBuffer = array();
return $result;
}
}
/**
* @return mixed[]
*/
function getCallbacks()
{
$this->assertConnected();
$this->flush();
$cb = $this->callbacksBuffer;
$this->callbacksBuffer = array();
return $cb;
}
/**
* @throws TransportException * @throws TransportException
*/ */
private function assertConnected() private function writeMessage($xml)
{ {
if(!$this->socket) if ($this->requestHandle == (int)0xffffffff) {
throw new TransportException('Connection not initialized', TransportException::NOT_INITIALIZED); $this->requestHandle = (int)0x80000000;
}
$data = pack('V2', strlen($xml), ++$this->requestHandle) . $xml;
if (!$this->write($data)) {
$this->onIoFailure('while writing');
}
$this->lastNetworkActivity = time();
}
/**
* @param string $data
* @return boolean
*/
private function write($data)
{
@stream_set_timeout($this->socket, $this->writeTimeout['sec'], $this->writeTimeout['usec']);
self::$sent += strlen($data);
while (strlen($data) > 0) {
$written = @fwrite($this->socket, $data);
if ($written === 0 || $written === false) {
return false;
}
$data = substr($data, $written);
}
return true;
} }
/** /**
@ -194,18 +258,17 @@ class GbxRemote
*/ */
private function flush($waitResponse = false) private function flush($waitResponse = false)
{ {
$r = array($this->socket); $r = [$this->socket];
while($waitResponse || @stream_select($r, $w, $e, 0) > 0) while ($waitResponse || @stream_select($r, $w, $e, 0) > 0) {
{
list($handle, $xml) = $this->readMessage(); list($handle, $xml) = $this->readMessage();
list($type, $value) = Request::decode($xml); list($type, $value) = Request::decode($xml);
switch($type) switch ($type) {
{
case 'fault': case 'fault':
throw FaultException::create($value['faultString'], $value['faultCode']); throw FaultException::create($value['faultString'], $value['faultCode']);
case 'response': case 'response':
if($handle == $this->requestHandle) if ($handle == $this->requestHandle) {
return $value; return $value;
}
break; break;
case 'call': case 'call':
$this->callbacksBuffer[] = $value; $this->callbacksBuffer[] = $value;
@ -221,92 +284,40 @@ class GbxRemote
private function readMessage() private function readMessage()
{ {
$header = $this->read(8); $header = $this->read(8);
if($header === false) if ($header === false) {
$this->onIoFailure('while reading header'); $this->onIoFailure('while reading header');
}
extract(unpack('Vsize/Vhandle', $header)); extract(unpack('Vsize/Vhandle', $header));
/** @var $size int */ /** @var $size int */
/** @var $handle int */ /** @var $handle int */
if($size == 0 || $handle == 0) if ($size == 0 || $handle == 0) {
throw new TransportException('Incorrect header', TransportException::PROTOCOL_ERROR); throw new TransportException('Incorrect header', TransportException::PROTOCOL_ERROR);
}
if($size > self::MAX_RESPONSE_SIZE) if ($size > self::MAX_RESPONSE_SIZE) {
throw new MessageException('Response too large', MessageException::RESPONSE_TOO_LARGE); throw new MessageException('Response too large', MessageException::RESPONSE_TOO_LARGE);
}
$data = $this->read($size); $data = $this->read($size);
if($data === false) if ($data === false) {
$this->onIoFailure('while reading data'); $this->onIoFailure('while reading data');
}
$this->lastNetworkActivity = time(); $this->lastNetworkActivity = time();
return array($handle, $data); return [$handle, $data];
} }
/** /**
* @param string $xml * @return mixed[]
* @throws TransportException
*/ */
private function writeMessage($xml) function getCallbacks()
{ {
if($this->requestHandle == (int) 0xffffffff) $this->assertConnected();
$this->requestHandle = (int) 0x80000000; $this->flush();
$data = pack('V2', strlen($xml), ++$this->requestHandle).$xml; $cb = $this->callbacksBuffer;
if(!$this->write($data)) $this->callbacksBuffer = [];
$this->onIoFailure('while writing'); return $cb;
$this->lastNetworkActivity = time();
}
/**
* @param int $size
* @return boolean|string
*/
private function read($size)
{
@stream_set_timeout($this->socket, $this->readTimeout['sec'], $this->readTimeout['usec']);
$data = '';
while(strlen($data) < $size)
{
$buf = @fread($this->socket, $size - strlen($data));
if($buf === '' || $buf === false)
return false;
$data .= $buf;
}
self::$received += $size;
return $data;
}
/**
* @param string $data
* @return boolean
*/
private function write($data)
{
@stream_set_timeout($this->socket, $this->writeTimeout['sec'], $this->writeTimeout['usec']);
self::$sent += strlen($data);
while(strlen($data) > 0)
{
$written = @fwrite($this->socket, $data);
if($written === 0 || $written === false)
return false;
$data = substr($data, $written);
}
return true;
}
/**
* @param string $when
* @throws TransportException
*/
private function onIoFailure($when)
{
$meta = stream_get_meta_data($this->socket);
if($meta['timed_out'])
throw new TransportException('Connection timed out '.$when, TransportException::TIMED_OUT);
throw new TransportException('Connection interrupted '.$when, TransportException::INTERRUPTED);
} }
} }

Some files were not shown because too many files have changed in this diff Show More