Big refactoring of the plugin:

- Add better command aliases
- Add setting to automatically add admins
- Add setting to automatically kick non-guestlisted players
This commit is contained in:
Beu 2025-02-18 09:41:55 +01:00
parent 1532b6e04a
commit 293d5cf88f

View File

@ -2,35 +2,43 @@
namespace Beu;
use ManiaControl\Commands\CommandListener;
use ManiaControl\ManiaControl;
use ManiaControl\Logger;
use ManiaControl\Admin\AuthenticationManager;
use ManiaControl\Callbacks\CallbackListener;
use ManiaControl\Callbacks\TimerListener;
use ManiaControl\Commands\CommandListener;
use ManiaControl\Players\Player;
use ManiaControl\Players\PlayerManager;
use ManiaControl\Plugins\Plugin;
use ManiaControl\ManiaControl;
use ManiaControl\Settings\SettingManager;
/**
* Plugin Description
*
* @author Beu
* @version 1.1
*/
class GuestlistManager implements CommandListener, Plugin {
class GuestlistManager implements CommandListener, CallbackListener, TimerListener, Plugin {
/*
* Constants
*/
const PLUGIN_ID = 154;
const PLUGIN_VERSION = 1.3;
const PLUGIN_VERSION = 2.0;
const PLUGIN_NAME = 'Guestlist Manager';
const PLUGIN_AUTHOR = 'Beu';
const SETTING_GUESTLIST_FILE = 'Guestlist file';
const SETTING_LOAD_AT_START = 'Load Guestlist at Maniacontrol start';
const SETTING_ADD_ADMINS = 'Automatically add admins to the guestlist';
const SETTING_ADMIN_LEVEL = 'Minimum Admin level to automatically add admin to the guestlist';
const SETTING_ENFORCE_GUESTLIST = 'Kick all non-guestlisted players';
/**
* Private Properties
*/
/** @var ManiaControl $maniaControl */
private $maniaControl = null;
private $checkNonGuestlistedPlayers = true;
/**
* @see \ManiaControl\Plugins\Plugin::prepare()
@ -79,17 +87,40 @@ class GuestlistManager implements CommandListener, Plugin {
public function load(ManiaControl $maniaControl) {
$this->maniaControl = $maniaControl;
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_GUESTLIST_FILE, "guestlist.txt", 'guestlist file');
$this->maniaControl->getCommandManager()->registerCommandListener('addalltogl', $this, 'doaddalltogl', true, 'Add all connected players to the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener('addtogl', $this, 'doaddtogl', true, 'Add someone to the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener('savegl', $this, 'dosavegl', true, 'Save the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener('loadgl', $this, 'doloadgl', true, 'Load the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener('cleangl', $this, 'docleangl', true, 'Clean the guestlist');
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_GUESTLIST_FILE, "guestlist.txt", 'guestlist file', 10);
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_LOAD_AT_START, false, 'Load guestlist file at maniacontrol start', 20);
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_ADD_ADMINS, false, 'Due to a bug, player can join a server without being guestlisted. This setting is to prevent this.', 90);
$this->maniaControl->getAuthenticationManager()->definePluginPermissionLevel($this, self::SETTING_ADMIN_LEVEL, AuthenticationManager::AUTH_LEVEL_MODERATOR);
$this->maniaControl->getSettingManager()->initSetting($this, self::SETTING_ENFORCE_GUESTLIST, false, 'Due to a bug, player can join a server without being guestlisted. This setting is to prevent this.', 110);
$this->maniaControl->getCommandManager()->registerCommandListener(['gladdall', 'addalltogl'], $this, 'handleAddAll', true, 'Add all connected players to the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener(['gladd', 'addtogl'], $this, 'handleAdd', true, 'Add player to the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener(['glremove', 'gldelete', 'removefromgl', 'deletefromgl'], $this, 'handleRemove', true, 'Remove player to the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener(['glsave', 'savegl'], $this, 'handleSave', true, 'Save the guestlist file');
$this->maniaControl->getCommandManager()->registerCommandListener(['glload', 'loadgl'], $this, 'handleLoad', true, 'Load the guestlist file');
$this->maniaControl->getCommandManager()->registerCommandListener(['glclear', 'glclean', 'cleangl'], $this, 'handleClear', true, 'Clear the guestlist');
$this->maniaControl->getCommandManager()->registerCommandListener(['glkickall'], $this, 'handleKickAll', true, 'Kick non-guestlisted players');
$guestlist = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_GUESTLIST_FILE);
if ($guestlist === "" || is_file($this->maniaControl->getServer()->getDirectory()->getUserDataFolder() . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $guestlist)) {
$this->maniaControl->getClient()->loadGuestList($guestlist);
$this->maniaControl->getCallbackManager()->registerCallbackListener(AuthenticationManager::CB_AUTH_LEVEL_CHANGED, $this, 'handleAuthLevelChanged');
$this->maniaControl->getCallbackManager()->registerCallbackListener(PlayerManager::CB_PLAYERCONNECT, $this, 'handlePlayerConnect');
$this->maniaControl->getCallbackManager()->registerCallbackListener(SettingManager::CB_SETTING_CHANGED, $this, 'handleSettingChanged');
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_LOAD_AT_START)) {
$guestlist = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_GUESTLIST_FILE);
if ($guestlist === "" || is_file($this->maniaControl->getServer()->getDirectory()->getUserDataFolder() . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $guestlist)) {
$this->maniaControl->getClient()->loadGuestList($guestlist);
}
}
$this->addAdminsToGuestlist();
$this->maniaControl->getTimerManager()->registerTimerListening($this, function () {
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ENFORCE_GUESTLIST)) return;
if (!$this->checkNonGuestlistedPlayers) return;
$this->checkNonGuestlistedPlayers = false;
$this->kickNonGuestlistedPlayers();
}, 1000);
}
/**
@ -99,12 +130,12 @@ class GuestlistManager implements CommandListener, Plugin {
}
/**
* Add all connected players to the guestlist
* handle Add All to GL command
*
* @param array $chat
* @param \ManiaControl\Players\Player $player
*/
public function doaddalltogl(Array $chat, Player $player) {
*/
public function handleAddAll(Array $chat, Player $player) {
$players = $this->maniaControl->getPlayerManager()->getPlayers();
$guestlist = $this->maniaControl->getClient()->getGuestList();
$i = 0;
@ -113,44 +144,48 @@ class GuestlistManager implements CommandListener, Plugin {
$i++;
}
}
$this->maniaControl->getChat()->sendSuccess( "All connected players have been added to the Guestlist");
Logger::log('Adding all connected players to the guestlist by '. $player->nickname);
$this->maniaControl->getChat()->sendSuccess("All connected players have been added to the Guestlist");
$this->maniaControl->getChat()->sendSuccess( "Added: " . $i . "/" . count($players), $player);
}
/**
* Add players to the guestlist
* handle Add GL command
*
* @param array $chat
* @param \ManiaControl\Players\Player $player
*/
public function doaddtogl(Array $chat, Player $player) {
*/
public function handleAdd(Array $chat, Player $player) {
$command = explode(" ", $chat[1][2]);
$peopletoadd = $command[1];
$playerToAdd = $command[1];
if (empty($peopletoadd)) {
$this->maniaControl->getChat()->sendError("You must set the nickname as argument", $player);
if (empty($playerToAdd)) {
$this->maniaControl->getChat()->sendError("You must set the login or the nickname as argument", $player);
} else {
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
$query = 'SELECT login FROM `' . PlayerManager::TABLE_PLAYERS . '` WHERE nickname LIKE "' . $peopletoadd . '"';
$result = $mysqli->query($query);
$stmt = $mysqli->prepare('SELECT `login` FROM `' . PlayerManager::TABLE_PLAYERS . '` WHERE nickname LIKE ? LIMIT 1;');
$stmt->bind_param('s', $playerToAdd);
$stmt->execute();
$result = $stmt->get_result();
$array = mysqli_fetch_array($result);
if (isset($array[0])) {
$login = $array[0];
} elseif (strlen($peopletoadd) == 22) {
$login = $peopletoadd ;
} elseif (strlen($playerToAdd) == 22) {
$login = $playerToAdd;
}
if ($mysqli->error) {
trigger_error($mysqli->error, E_USER_ERROR);
}
if (!isset($login)) {
$this->maniaControl->getChat()->sendError( "Login not found. FYI The player must be connected" , $player);
$this->maniaControl->getChat()->sendError("Player not found. Use the nickname of already connected player or just their login", $player);
} else {
if ($this->addLoginToGL($login)) {
$this->maniaControl->getChat()->sendSuccess( "Player " . $peopletoadd . " added to the Guestlist" , $player);
Logger::log('Player "'. $playerToAdd .'" added to the guestlist by '. $player->nickname);
$this->maniaControl->getChat()->sendSuccess('Player "' . $playerToAdd . '" added to the Guestlist', $player);
} else {
$this->maniaControl->getChat()->sendSuccess( "Player " . $peopletoadd . " already in the Guestlist" , $player);
$this->maniaControl->getChat()->sendSuccess('Player "' . $playerToAdd . '" already in the Guestlist', $player);
}
}
}
@ -161,15 +196,16 @@ class GuestlistManager implements CommandListener, Plugin {
*
* @param string $login
* @param array $guestlist
*/
public function addLoginToGL(String $login, array $guestlist = []) {
if (empty($guestlist)) {
*/
public function addLoginToGL(String $login, ?array $guestlist = null) {
if ($guestlist === null) {
$guestlist = $this->maniaControl->getClient()->getGuestList();
}
$logintoadd = "";
$logintoadd = array_search($login ,array_column($guestlist, 'login'));
if (strlen($logintoadd) == 0) {
if (!in_array($login, array_column($guestlist, 'login'))) {
Logger::log('Player "'. $login .'" added to the guestlist');
$this->maniaControl->getClient()->addGuest($login);
$this->checkNonGuestlistedPlayers = true;
return true;
} else {
return false;
@ -177,12 +213,78 @@ class GuestlistManager implements CommandListener, Plugin {
}
/**
* load from the guestlist file
* handle Remove from GL command
*
* @param array $chat
* @param Player $player
* @return void
*/
public function handleRemove(Array $chat, Player $player) {
$command = explode(" ", $chat[1][2]);
$playerToRemove = $command[1];
if (empty($playerToRemove)) {
$this->maniaControl->getChat()->sendError("You must set the login or the nickname as argument", $player);
} else {
$mysqli = $this->maniaControl->getDatabase()->getMysqli();
$stmt = $mysqli->prepare('SELECT `login` FROM `' . PlayerManager::TABLE_PLAYERS . '` WHERE nickname LIKE ? LIMIT 1;');
$stmt->bind_param('s', $playerToRemove);
$stmt->execute();
$result = $stmt->get_result();
$array = mysqli_fetch_array($result);
if (isset($array[0])) {
$login = $array[0];
} elseif (strlen($playerToRemove) == 22) {
$login = $playerToRemove;
}
if ($mysqli->error) {
trigger_error($mysqli->error, E_USER_ERROR);
}
if (!isset($login)) {
$this->maniaControl->getChat()->sendError('Player not found. Use the nickname of already connected player or just their login', $player);
} else {
if ($this->removeLoginFromGL($login)) {
Logger::log('Player "'. $playerToRemove .'" removed from the guestlist by '. $player->nickname);
$this->maniaControl->getChat()->sendSuccess('Player "' . $playerToRemove . '" removed to the Guestlist', $player);
} else {
$this->maniaControl->getChat()->sendSuccess('Player "' . $playerToRemove . '" not in the Guestlist', $player);
}
}
}
}
/**
* Remove login from the guestlist
*
* @param string $login
* @param array $guestlist
*/
public function removeLoginFromGL(String $login, ?array $guestlist = null) {
if ($guestlist === null) {
$guestlist = $this->maniaControl->getClient()->getGuestList();
}
if (in_array($login, array_column($guestlist, 'login'))) {
Logger::log('Player "'. $login .'" removed from the guestlist');
$this->maniaControl->getClient()->removeGuest($login);
$this->checkNonGuestlistedPlayers = true;
return true;
} else {
return false;
}
}
/**
* hangle Load GL command
*
* @param array $chat
* @param \ManiaControl\Players\Player $player
*/
public function doloadgl(Array $chat, Player $player) {
*/
public function handleLoad(Array $chat, Player $player) {
$guestlist = '';
$text = explode(" ",$chat[1][2]);
if (count($text) > 1 && $text[1] != "") {
$guestlist = $text[1];
@ -193,30 +295,69 @@ class GuestlistManager implements CommandListener, Plugin {
} else {
$guestlist = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_GUESTLIST_FILE);
}
if ($guestlist === "" || is_file($this->maniaControl->getServer()->getDirectory()->getUserDataFolder() . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $guestlist)) {
$this->maniaControl->getClient()->loadGuestList($guestlist);
$this->maniaControl->getChat()->sendSuccess( "Guestlist loaded!" , $player);
} else {
$this->maniaControl->getChat()->sendError("Impossible to load the guestlist file" , $player);
try {
if ($guestlist === "") {
Logger::log('Player "'. $player->nickname .'" loaded default guestlist');
$this->maniaControl->getClient()->loadGuestList();
$this->checkNonGuestlistedPlayers = true;
} else {
$filepath = $this->maniaControl->getServer()->getDirectory()->getUserDataFolder() . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $guestlist;
if (is_file($filepath)) {
Logger::log('Player "'. $player->nickname .'" loaded guestlist file: '. $guestlist);
$this->maniaControl->getClient()->loadGuestList($guestlist);
$this->checkNonGuestlistedPlayers = true;
} else {
$this->maniaControl->getChat()->sendError("No guestlist file: ". $filepath, $player);
Logger::logError("Can't load guestlist, no file: ". $filepath);
}
}
$this->maniaControl->getChat()->sendSuccess("Guestlist loaded!", $player);
} catch (\Throwable $th) {
$this->maniaControl->getChat()->sendError("Can't load guestlist: ". $th->getMessage(), $player);
Logger::logError("Can't load guestlist: ". $th->getMessage());
}
}
/**
* save to the guestlist file
* handle Save GL command
*
* @param array $chat
* @param \ManiaControl\Players\Player $player
*/
public function dosavegl(Array $chat, Player $player) {
try {
$guestlist = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_GUESTLIST_FILE);
if ($guestlist !== "") {
$filepath = $this->maniaControl->getServer()->getDirectory()->getUserDataFolder() . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $guestlist;
*/
public function handleSave(Array $chat, Player $player) {
$guestlist = '';
$text = explode(" ",$chat[1][2]);
if (count($text) > 1 && $text[1] != "") {
$guestlist = $text[1];
if (!is_file($filepath)) {
file_put_contents($filepath, '<?xml version="1.0" encoding="utf-8" ?><guestlist></guestlist>');
}
if (substr($guestlist , -4) != ".txt" && substr($guestlist , -4) != ".xml") {
$guestlist .= ".txt";
}
} else {
$guestlist = $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_GUESTLIST_FILE);
}
if ($guestlist === "") {
$this->maniaControl->getChat()->sendError('No guestlist file provided');
return;
}
try {
$filepath = $this->maniaControl->getServer()->getDirectory()->getUserDataFolder() . DIRECTORY_SEPARATOR . "Config" . DIRECTORY_SEPARATOR . $guestlist;
$directory = dirname($filepath);
/**
* The server can't save a file if it was not loaded before: https://forum.nadeo.com/viewtopic.php?p=11976
* this is a workaround
*/
if (!is_dir($directory)) {
mkdir($directory, 0755, true);
}
if (!is_file($filepath)) {
file_put_contents($filepath, '<?xml version="1.0" encoding="utf-8" ?><guestlist></guestlist>');
}
// Workaround when the file was never loaded by the server
@ -228,9 +369,11 @@ class GuestlistManager implements CommandListener, Plugin {
$this->maniaControl->getClient()->addGuest($guest->login);
}
Logger::log('Player "'. $player->nickname .'" saved guestlist file: '. $guestlist);
$this->maniaControl->getClient()->saveGuestList($guestlist);
$this->checkNonGuestlistedPlayers = true;
$this->maniaControl->getChat()->sendSuccess("Guestlist saved!" , $player);
$this->maniaControl->getChat()->sendSuccess("Guestlist saved!", $player);
} catch (\Exception $e) {
Logger::logError("Impossible to save guestlist: " . $e->getMessage());
$this->maniaControl->getChat()->sendError("Impossible to save guestlist: " . $e->getMessage(), $player);
@ -238,13 +381,107 @@ class GuestlistManager implements CommandListener, Plugin {
}
/**
* clean the guestlist
* handle Clear GL command
*
* @param array $chat
* @param \ManiaControl\Players\Player $player
*/
public function docleangl(Array $chat, Player $player) {
*/
public function handleClear(Array $chat, Player $player) {
Logger::log('Guestlist cleared by '. $player->nickname);
$this->maniaControl->getClient()->cleanGuestList();
$this->maniaControl->getChat()->sendSuccess( "Guestlist cleaned!" , $player);
$this->checkNonGuestlistedPlayers = true;
$this->maniaControl->getChat()->sendSuccess("Guestlist cleaned!", $player);
if ($this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ADD_ADMINS)) {
$this->maniaControl->getChat()->sendSuccess("Re-adding admins to the guestlist", $player);
$this->addAdminsToGuestlist();
}
}
/**
* handle Kick non-guestlisted players command
*
* @param array $chat
* @param \ManiaControl\Players\Player $player
*/
public function handleKickAll(Array $chat, Player $player) {
Logger::log('All non-guestlisted players kicked by '. $player->nickname);
$kicked = $this->kickNonGuestlistedPlayers();
$this->maniaControl->getChat()->sendSuccess($kicked . ' players kicked', $player);
}
/**
* Kick non-guestlist players from the server
*
* @return int
*/
private function kickNonGuestlistedPlayers() {
$kicked = 0;
$guests = array_column($this->maniaControl->getClient()->getGuestList(), 'login');
foreach ($this->maniaControl->getPlayerManager()->getPlayers() as $player) {
if (!in_array($player->login, $guests)) {
try {
Logger::log('Player "'. $player->nickname .'" kicked from the server as not guestlisted');
$this->maniaControl->getClient()->kick($player->nickname, "You are not guestlisted on the server");
$kicked++;
} catch (\Throwable $th) {
Logger::logError("Can't kick ". $player->nickname .": ". $th->getMessage());
}
}
}
return $kicked;
}
/**
* add Admins to GL
*
* @param \ManiaControl\Players\Player $player
*/
private function addAdminsToGuestlist() {
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ADD_ADMINS)) return;
$guestlist = $this->maniaControl->getClient()->getGuestList();
foreach ($this->maniaControl->getAuthenticationManager()->getAdmins() as $admin) {
if ($this->maniaControl->getAuthenticationManager()->checkRight($admin, $this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ADMIN_LEVEL))) continue;
$this->addLoginToGL($admin->login, $guestlist);
}
}
/**
* handle Auth Level changed callback
*
* @param \ManiaControl\Players\Player $player
*/
public function handleAuthLevelChanged(Player $player) {
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ADD_ADMINS)) return;
$guestlist = $this->maniaControl->getClient()->getGuestList();
$isGuestlisted = in_array($player->login, array_column($guestlist, 'login'));
$isAdmin = $this->maniaControl->getAuthenticationManager()->checkRight($player,$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ADMIN_LEVEL));
if (!$isGuestlisted && $isAdmin) {
$this->addLoginToGL($player->login, $guestlist);
$this->maniaControl->getChat()->sendSuccessToAdmins('New admin "'. $player->nickname . '" automatically added to the guestlist');
Logger::log('New admin "'. $player->nickname . '" automatically added to the guestlist');
} else if ($isGuestlisted && !$isAdmin) {
$this->maniaControl->getChat()->sendErrorToAdmins('Non-admin "'. $player->nickname . '" is still in the guestlist. Remove them manually if needed');
}
}
/**
* handle Player connect callback
*/
public function handlePlayerConnect() {
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ENFORCE_GUESTLIST)) return;
$this->checkNonGuestlistedPlayers = true;
}
/**
* handle Setting changed callback
*/
public function handleSettingChanged() {
if (!$this->maniaControl->getSettingManager()->getSettingValue($this, self::SETTING_ENFORCE_GUESTLIST)) return;
$this->checkNonGuestlistedPlayers = true;
}
}