381 lines
12 KiB
PHP
381 lines
12 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace MCTeam;
|
||
|
|
||
|
use ManiaControl\Admin\AuthenticationManager;
|
||
|
use ManiaControl\Callbacks\TimerListener;
|
||
|
use ManiaControl\Commands\CommandListener;
|
||
|
use ManiaControl\Files\FileUtil;
|
||
|
use ManiaControl\ManiaControl;
|
||
|
use ManiaControl\Players\Player;
|
||
|
use ManiaControl\Plugins\Plugin;
|
||
|
|
||
|
/**
|
||
|
* ManiaControl GameMode Presets Plugin
|
||
|
*
|
||
|
* @author ManiaControl Team <mail@maniacontrol.com>
|
||
|
* @copyright 2014-2020 ManiaControl Team
|
||
|
* @license http://www.gnu.org/licenses/ GNU General Public License, Version 3
|
||
|
*/
|
||
|
class GameModePresetsPlugin implements Plugin, CommandListener, TimerListener {
|
||
|
/*
|
||
|
* Constants
|
||
|
*/
|
||
|
const PLUGIN_ID = 9;
|
||
|
const PLUGIN_VERSION = 0.1;
|
||
|
const PLUGIN_NAME = 'GameMode Presets Plugin';
|
||
|
const PLUGIN_AUTHOR = 'MCTeam';
|
||
|
|
||
|
const PRESET_SETTING_MODE_NUMBER = 'Mode Number';
|
||
|
const PRESET_SETTING_SCRIPT_NAME = 'Script Name';
|
||
|
|
||
|
const SETTING_MAP_ACTION_ON_LOADMODE = 'Map Action on //loadmode';
|
||
|
const SETTING_MAP_ACTION_DELAY_ON_LOADMODE = 'Map Action Delay on //loadmode (in ms)';
|
||
|
const SETTING_PERMISSION_LOAD_GAMEMODE_PRESET = 'Permission load GameMode Preset';
|
||
|
const SETTING_PERMISSION_SAVE_GAMEMODE_PRESET = 'Permission save GameMode Preset';
|
||
|
|
||
|
const MAP_ACTION_ON_LOADMODE_NONE = 'None';
|
||
|
const MAP_ACTION_ON_LOADMODE_RESTART = 'Restart Map';
|
||
|
const MAP_ACTION_ON_LOADMODE_SKIP = 'Skip Map';
|
||
|
|
||
|
const TABLE_GAMEMODEPRESETS = 'mc_gamemodepresets';
|
||
|
|
||
|
/*
|
||
|
* Private properties
|
||
|
*/
|
||
|
/** @var ManiaControl $maniaControl * */
|
||
|
private $maniaControl = null;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::prepare()
|
||
|
*/
|
||
|
public static function prepare(ManiaControl $maniaControl) {
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::load()
|
||
|
*/
|
||
|
public function load(ManiaControl $maniaControl) {
|
||
|
$this->maniaControl = $maniaControl;
|
||
|
|
||
|
// Authentication Permission Level
|
||
|
$this->maniaControl->getAuthenticationManager()->definePluginPermissionLevel(
|
||
|
$this,
|
||
|
self::SETTING_PERMISSION_LOAD_GAMEMODE_PRESET,
|
||
|
AuthenticationManager::AUTH_LEVEL_ADMIN,
|
||
|
AuthenticationManager::AUTH_LEVEL_MODERATOR
|
||
|
);
|
||
|
$this->maniaControl->getAuthenticationManager()->definePluginPermissionLevel(
|
||
|
$this,
|
||
|
self::SETTING_PERMISSION_SAVE_GAMEMODE_PRESET,
|
||
|
AuthenticationManager::AUTH_LEVEL_SUPERADMIN,
|
||
|
AuthenticationManager::AUTH_LEVEL_MODERATOR
|
||
|
);
|
||
|
|
||
|
// Settings
|
||
|
$this->maniaControl->getSettingManager()->initSetting(
|
||
|
$this,
|
||
|
self::SETTING_MAP_ACTION_ON_LOADMODE,
|
||
|
array(
|
||
|
self::MAP_ACTION_ON_LOADMODE_NONE,
|
||
|
self::MAP_ACTION_ON_LOADMODE_RESTART,
|
||
|
self::MAP_ACTION_ON_LOADMODE_SKIP,
|
||
|
)
|
||
|
);
|
||
|
$this->maniaControl->getSettingManager()->initSetting(
|
||
|
$this,
|
||
|
self::SETTING_MAP_ACTION_DELAY_ON_LOADMODE,
|
||
|
1000
|
||
|
);
|
||
|
|
||
|
// Commands
|
||
|
$this->maniaControl->getCommandManager()->registerCommandListener(array('loadmode', 'modeload'), $this, 'commandLoadMode', true, 'Loads the mode settings from the given preset name.');
|
||
|
$this->maniaControl->getCommandManager()->registerCommandListener(array('savemode', 'modesave'), $this, 'commandSaveMode', true, 'Saves the mode settings under the given preset name.');
|
||
|
|
||
|
$this->initTables();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialize needed database tables
|
||
|
*/
|
||
|
private function initTables() {
|
||
|
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||
|
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_GAMEMODEPRESETS . "` (
|
||
|
`index` int(11) NOT NULL AUTO_INCREMENT,
|
||
|
`name` varchar(20) NOT NULL,
|
||
|
`settings` TEXT CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
|
||
|
PRIMARY KEY (`index`),
|
||
|
UNIQUE KEY (`name`)
|
||
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;";
|
||
|
$mysqli->query($query);
|
||
|
if ($mysqli->error) {
|
||
|
trigger_error($mysqli->error, E_USER_ERROR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Fetch preset from database
|
||
|
* @param string $name
|
||
|
* @return array|null
|
||
|
*/
|
||
|
private function fetchPreset($name) {
|
||
|
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||
|
$query = "SELECT `settings`
|
||
|
FROM `" . self::TABLE_GAMEMODEPRESETS . "`
|
||
|
WHERE `name` LIKE ?;";
|
||
|
|
||
|
$statement = $mysqli->prepare($query);
|
||
|
if ($mysqli->error || !$statement) {
|
||
|
trigger_error($mysqli->error, E_USER_ERROR);
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
$statement->bind_param('s', $name);
|
||
|
$statement->execute();
|
||
|
if ($statement->error) {
|
||
|
trigger_error($statement->error);
|
||
|
$statement->close();
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
$settings = null;
|
||
|
$statement->store_result();
|
||
|
$statement->bind_result($settings);
|
||
|
$statement->fetch();
|
||
|
$statement->free_result();
|
||
|
|
||
|
return json_decode($settings, true);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Fetch preset from database
|
||
|
* @param string $name
|
||
|
* @return array|null
|
||
|
*/
|
||
|
private function storePreset($name) {
|
||
|
$modeNumber = $this->maniaControl->getClient()->getGameMode();
|
||
|
$scriptName = $this->maniaControl->getClient()->getScriptName()['CurrentValue'];
|
||
|
$settings = null;
|
||
|
if ($modeNumber === 0) {
|
||
|
$settings = $this->maniaControl->getClient()->getModeScriptSettings();
|
||
|
} else {
|
||
|
$settings = $this->maniaControl->getClient()->execute('GetCurrentGameInfo');
|
||
|
}
|
||
|
|
||
|
$settings[self::PRESET_SETTING_MODE_NUMBER] = $modeNumber;
|
||
|
$settings[self::PRESET_SETTING_SCRIPT_NAME] = $scriptName;
|
||
|
$settings = json_encode($settings);
|
||
|
|
||
|
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
|
||
|
$query = "INSERT INTO `" . self::TABLE_GAMEMODEPRESETS . "`
|
||
|
(`name`, `settings`) VALUES (?, ?)
|
||
|
ON DUPLICATE KEY UPDATE `settings` = VALUES(`settings`);";
|
||
|
|
||
|
$statement = $mysqli->prepare($query);
|
||
|
if ($mysqli->error || !$statement) {
|
||
|
trigger_error($mysqli->error, E_USER_ERROR);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$statement->bind_param('ss', $name, $settings);
|
||
|
$statement->execute();
|
||
|
if ($statement->error) {
|
||
|
trigger_error($statement->error);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$statement->close();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Load Script
|
||
|
* @param string $scriptName
|
||
|
*/
|
||
|
private function loadScript($scriptName) {
|
||
|
static $scriptsDir = null;
|
||
|
if ($scriptsDir === null)
|
||
|
{
|
||
|
$scriptsDataDir = FileUtil::shortenPath($this->maniaControl->getServer()->getDirectory()->getScriptsFolder());
|
||
|
if ($this->maniaControl->getServer()->checkAccess($scriptsDataDir))
|
||
|
{
|
||
|
$gameShort = $this->maniaControl->getMapManager()->getCurrentMap()->getGame();
|
||
|
$game = '';
|
||
|
switch ($gameShort)
|
||
|
{
|
||
|
case 'qm': $game = 'QuestMania'; break;
|
||
|
case 'sm': $game = 'ShootMania'; break;
|
||
|
case 'tm': $game = 'TrackMania'; break;
|
||
|
}
|
||
|
|
||
|
if ($game != '')
|
||
|
{
|
||
|
$scriptsDir = $scriptsDataDir.DIRECTORY_SEPARATOR.'Modes'.DIRECTORY_SEPARATOR.$game.DIRECTORY_SEPARATOR;
|
||
|
if (!$this->maniaControl->getServer()->checkAccess($scriptsDir))
|
||
|
$scriptsDir = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ($scriptsDir === null)
|
||
|
throw new \Exception('Scripts directory not found, unable to load different scripts!');
|
||
|
}
|
||
|
|
||
|
$scriptPath = $scriptsDir.$scriptName;
|
||
|
if (!file_exists($scriptPath))
|
||
|
throw new \Exception('Script not found ('.$scriptPath.').');
|
||
|
|
||
|
$scriptText = file_get_contents($scriptPath);
|
||
|
|
||
|
$this->maniaControl->getClient()->setModeScriptText($scriptText);
|
||
|
$this->maniaControl->getClient()->setScriptName($scriptName);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handle //loadmode command
|
||
|
*
|
||
|
* @param array $chatCallback
|
||
|
* @param \ManiaControl\Players\Player $player
|
||
|
*/
|
||
|
public function commandLoadMode(array $chatCallback, Player $player) {
|
||
|
if (!$this->maniaControl->getAuthenticationManager()->checkPluginPermission($this, $player, self::SETTING_PERMISSION_LOAD_GAMEMODE_PRESET)) {
|
||
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Check for delayed shutdown
|
||
|
$params = explode(' ', $chatCallback[1][2]);
|
||
|
if (count($params) < 2) {
|
||
|
$this->maniaControl->getChat()->sendError('You must provide a gamemode preset name to load settings from!', $player);
|
||
|
return;
|
||
|
} elseif (count($params) > 2) {
|
||
|
$this->maniaControl->getChat()->sendError('You can only provide one gamemode preset name to load settings from!', $player);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$presetName = strtolower($params[1]);
|
||
|
$presetSettings = $this->fetchPreset($presetName);
|
||
|
if (!$presetSettings) {
|
||
|
$this->maniaControl->getChat()->sendError('The gamemode preset $<$fff' . $presetName . '$> does not exist!', $player);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$modeNumber = $presetSettings[self::PRESET_SETTING_MODE_NUMBER];
|
||
|
$scriptName = $presetSettings[self::PRESET_SETTING_SCRIPT_NAME];
|
||
|
unset($presetSettings[self::PRESET_SETTING_MODE_NUMBER]);
|
||
|
unset($presetSettings[self::PRESET_SETTING_SCRIPT_NAME]);
|
||
|
|
||
|
// this is a hack, because this setting always throws errors otherwise
|
||
|
$presetSettings['S_MatchmakingRematchRatio'] = floatval($presetSettings['S_MatchmakingRematchRatio']);
|
||
|
|
||
|
try {
|
||
|
$this->maniaControl->getClient()->setGameMode($modeNumber);
|
||
|
if ($modeNumber === 0) {
|
||
|
$this->loadScript($scriptName);
|
||
|
$this->maniaControl->getClient()->setModeScriptSettings($presetSettings);
|
||
|
} else {
|
||
|
$this->maniaControl->getClient()->setScriptName($scriptName);
|
||
|
$this->maniaControl->getClient()->execute('SetGameInfos', $presetSettings);
|
||
|
}
|
||
|
} catch (\Exception $e) {
|
||
|
$this->maniaControl->getChat()->sendException($e, $player);
|
||
|
$this->maniaControl->getChat()->sendError('Unable to load gamemode preset $<$fff' . $presetName . '$>!', $player);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$this->maniaControl->getChat()->sendSuccess($player->getEscapedNickname() . ' loaded gamemode preset $<$fff' . $presetName . '$>!');
|
||
|
$this->maniaControl->getTimerManager()->registerOneTimeListening(
|
||
|
$this,
|
||
|
function () {
|
||
|
$mapActionOnLoadmode = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MAP_ACTION_ON_LOADMODE);
|
||
|
switch ($mapActionOnLoadmode) {
|
||
|
case self::MAP_ACTION_ON_LOADMODE_NONE:
|
||
|
break;
|
||
|
case self::MAP_ACTION_ON_LOADMODE_RESTART:
|
||
|
$this->maniaControl->getMapManager()->getMapActions()->restartMap();
|
||
|
break;
|
||
|
case self::MAP_ACTION_ON_LOADMODE_SKIP:
|
||
|
$this->maniaControl->getMapManager()->getMapActions()->skipMap();
|
||
|
break;
|
||
|
}
|
||
|
},
|
||
|
$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_MAP_ACTION_DELAY_ON_LOADMODE)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handle //savemode command
|
||
|
*
|
||
|
* @param array $chatCallback
|
||
|
* @param \ManiaControl\Players\Player $player
|
||
|
*/
|
||
|
public function commandSaveMode(array $chatCallback, Player $player) {
|
||
|
if (!$this->maniaControl->getAuthenticationManager()->checkPluginPermission($this, $player, self::SETTING_PERMISSION_LOAD_GAMEMODE_PRESET)) {
|
||
|
$this->maniaControl->getAuthenticationManager()->sendNotAllowed($player);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// Check for delayed shutdown
|
||
|
$params = explode(' ', $chatCallback[1][2]);
|
||
|
if (count($params) < 2) {
|
||
|
$this->maniaControl->getChat()->sendError('You must provide a gamemode preset name to save settings into!', $player);
|
||
|
return;
|
||
|
} elseif (count($params) > 2) {
|
||
|
$this->maniaControl->getChat()->sendError('You can only provide one gamemode preset name to save settings into!', $player);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$presetName = strtolower($params[1]);
|
||
|
try {
|
||
|
$this->storePreset($presetName);
|
||
|
} catch (\Exception $e) {
|
||
|
$this->maniaControl->getChat()->sendException($e, $player);
|
||
|
$this->maniaControl->getChat()->sendError('Unable to save gamemode preset $<$fff' . $presetName . '$>!', $player);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$this->maniaControl->getChat()->sendSuccess($player->getEscapedNickname() . ' saved gamemode settings in preset $<$fff"' . $presetName . '"$>!');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::getId()
|
||
|
*/
|
||
|
public static function getId() {
|
||
|
return self::PLUGIN_ID;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::getName()
|
||
|
*/
|
||
|
public static function getName() {
|
||
|
return self::PLUGIN_NAME;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::getVersion()
|
||
|
*/
|
||
|
public static function getVersion() {
|
||
|
return self::PLUGIN_VERSION;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::getAuthor()
|
||
|
*/
|
||
|
public static function getAuthor() {
|
||
|
return self::PLUGIN_AUTHOR;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::getDescription()
|
||
|
*/
|
||
|
public static function getDescription() {
|
||
|
return "Plugin offers presets functionalites for GameModes";
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @see \ManiaControl\Plugins\Plugin::unload()
|
||
|
*/
|
||
|
public function unload() {
|
||
|
}
|
||
|
}
|