/** * Copyright (C) 2014-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any * component of this program must not be commercial, unless explicit * permission is granted from the original author. The use of this * program for non-profit purposes is permitted. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * In the event that this license restricts you from making desired use of this program, contact the original author. * Written by Justin James */ #include #include "Jupiter/Functions.h" #include "IRC_Bot.h" #include "RenX_Commands.h" #include "RenX_Core.h" #include "RenX_Server.h" #include "RenX_PlayerInfo.h" #include "RenX_Functions.h" #include "RenX_BanDatabase.h" #include "RenX_Tags.h" inline bool togglePhasing(RenX::Server *server, bool newState) { server->varData.set(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), newState ? STRING_LITERAL_AS_REFERENCE("true") : STRING_LITERAL_AS_REFERENCE("false")); return newState; } inline bool togglePhasing(RenX::Server *server) { return togglePhasing(server, !server->varData.getBool(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), false)); } inline void onDie(RenX::Server *server, const RenX::PlayerInfo *player) { if (player->isBot && server->varData.getBool(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), false)) server->kickPlayer(player); } bool RenX_CommandsPlugin::RenX_OnBan(RenX::Server *server, const RenX::PlayerInfo *player, Jupiter::StringType &data) { data = player->varData.get(this->getName(), STRING_LITERAL_AS_REFERENCE("banner")); return !data.isEmpty(); } void RenX_CommandsPlugin::RenX_OnSuicide(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &) { onDie(server, player); } void RenX_CommandsPlugin::RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &) { onDie(server, victim); } void RenX_CommandsPlugin::RenX_OnDie(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &) { onDie(server, player); } int RenX_CommandsPlugin::OnRehash() { RenX_CommandsPlugin::_defaultTempBanTime = Jupiter::IRC::Client::Config->getLongLong(RenX_CommandsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("TBanTime"), 86400); RenX_CommandsPlugin::playerInfoFormat = Jupiter::IRC::Client::Config->get(RenX_CommandsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("PlayerInfoFormat"), STRING_LITERAL_AS_REFERENCE(IRCCOLOR "03[Player Info]" IRCCOLOR "{TCOLOR} Name: " IRCBOLD "{RNAME}" IRCBOLD " - ID: {ID} - Team: " IRCBOLD "{TEAML}" IRCBOLD " - Vehicle Kills: {VEHICLEKILLS} - Building Kills {BUILDINGKILLS} - Kills {KILLS} - Deaths: {DEATHS} - KDR: {KDR} - Access: {ACCESS}")); RenX_CommandsPlugin::adminPlayerInfoFormat = Jupiter::IRC::Client::Config->get(RenX_CommandsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("AdminPlayerInfoFormat"), Jupiter::StringS::Format("%.*s - IP: " IRCBOLD "{IP}" IRCBOLD " - Steam ID: " IRCBOLD "{STEAM}", RenX_CommandsPlugin::playerInfoFormat.size(), RenX_CommandsPlugin::playerInfoFormat.ptr())); RenX::sanitizeTags(RenX_CommandsPlugin::playerInfoFormat); RenX::sanitizeTags(RenX_CommandsPlugin::adminPlayerInfoFormat); return 0; } time_t RenX_CommandsPlugin::getTBanTime() { return RenX_CommandsPlugin::_defaultTempBanTime; } const Jupiter::ReadableString &RenX_CommandsPlugin::getPlayerInfoFormat() const { return RenX_CommandsPlugin::playerInfoFormat; } const Jupiter::ReadableString &RenX_CommandsPlugin::getAdminPlayerInfoFormat() const { return RenX_CommandsPlugin::adminPlayerInfoFormat; } RenX_CommandsPlugin::RenX_CommandsPlugin() { this->OnRehash(); } // Plugin instantiation and entry point. RenX_CommandsPlugin pluginInstance; /** Console Commands */ // RawRCON Console Command RawRCONConsoleCommand::RawRCONConsoleCommand() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("rrcon")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("rawrcon")); } void RawRCONConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) { Jupiter::StringS msg = parameters; msg += '\n'; int i = RenX::getCore()->getServerCount(); if (i == 0) puts("Error: Not connected to any Renegade X servers."); else if (parameters.isEmpty() == false) while (--i >= 0) RenX::getCore()->getServer(i)->sendData(msg); else puts("Error: Too Few Parameters. Syntax: rcon "); } const Jupiter::ReadableString &RawRCONConsoleCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends data over the Renegade X server's rcon connection. Syntax: rrcon "); return defaultHelp; } CONSOLE_COMMAND_INIT(RawRCONConsoleCommand) // RCON Console Command RCONConsoleCommand::RCONConsoleCommand() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("rcon")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("renx")); } void RCONConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) { int i = RenX::getCore()->getServerCount(); if (i == 0) puts("Error: Not connected to any Renegade X servers."); else if (parameters != nullptr) while (--i >= 0) RenX::getCore()->getServer(i)->send(parameters); else puts("Error: Too Few Parameters. Syntax: rcon "); } const Jupiter::ReadableString &RCONConsoleCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Executes a command over the Renegade X server's rcon connection. Syntax: rcon "); return defaultHelp; } CONSOLE_COMMAND_INIT(RCONConsoleCommand) /** IRC Commands */ // Msg IRC Command void MsgIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("msg")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("say")); } void MsgIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { int type = source->getChannel(channel)->getType(); Jupiter::StringL msg; char prefix = source->getChannel(channel)->getUserPrefix(nick); if (prefix != '\0') msg += prefix; msg += nick; msg += "@IRC: "; msg += parameters; prefix = '\0'; // Reusing prefix to check if a match is ever found. for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { server->sendMessage(msg); prefix = 1; } } if (prefix == '\0') source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: Msg ")); } const Jupiter::ReadableString &MsgIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message in - game.Syntax: Msg "); return defaultHelp; } IRC_COMMAND_INIT(MsgIRCCommand) // PMsg IRC Command void PMsgIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("pmsg")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("psay")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("page")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("ppage")); this->setAccessLevel(1); } void PMsgIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.wordCount(WHITESPACE) >= 2) { int type = source->getChannel(channel)->getType(); Jupiter::ReferenceString name = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); RenX::PlayerInfo *player; Jupiter::StringL msg; char prefix = source->getChannel(channel)->getUserPrefix(nick); if (prefix != '\0') msg += prefix; msg += nick; msg += "@IRC: "; msg += Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE); if (parameters.size() != 0) { for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { player = server->getPlayerByPartName(name); if (player != nullptr) server->sendMessage(player, msg); else source->sendNotice(nick, Jupiter::StringS::Format("Error: Player \"%.*s\" not found.", name.size(), name.ptr())); } } } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: PMsg ")); } const Jupiter::ReadableString &PMsgIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message in - game.Syntax: PMsg "); return defaultHelp; } IRC_COMMAND_INIT(PMsgIRCCommand) // Host Msg IRC Command void HostMsgIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("hmsg")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("hsay")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("hostmessage")); this->setAccessLevel(4); } void HostMsgIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { int type = source->getChannel(channel)->getType(); bool success = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) success = server->sendMessage(parameters) > 0; } if (!success) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: hmsg ")); } const Jupiter::ReadableString &HostMsgIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message in-game. Syntax: hmsg "); return defaultHelp; } IRC_COMMAND_INIT(HostMsgIRCCommand) // Players IRC Command void PlayersIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("players")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("pl")); } const size_t STRING_LENGTH = 240; void PlayersIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &) { int type = source->getChannel(channel)->getType(); // Team colors const Jupiter::ReadableString &gTeamColor = RenX::getTeamColor(RenX::TeamType::GDI); const Jupiter::ReadableString &nTeamColor = RenX::getTeamColor(RenX::TeamType::Nod); const Jupiter::ReadableString &oTeamColor = RenX::getTeamColor(RenX::TeamType::Other); // Team names const Jupiter::ReadableString &gTeam = RenX::getTeamName(RenX::TeamType::GDI); const Jupiter::ReadableString &nTeam = RenX::getTeamName(RenX::TeamType::Nod); const Jupiter::ReadableString &oTeam = RenX::getTeamName(RenX::TeamType::Other); bool noServers = true; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { noServers = false; if (server->players.size() != 0) { // End string containers Jupiter::DLList gStrings; Jupiter::DLList nStrings; Jupiter::DLList oStrings; Jupiter::StringL *gCurrent = nullptr; Jupiter::StringL *nCurrent = nullptr; Jupiter::StringL *oCurrent = nullptr; // Team player counters unsigned int gTotal = 0; unsigned int nTotal = 0; unsigned int oTotal = 0; // Bot counters unsigned int gBots = 0; unsigned int nBots = 0; unsigned int oBots = 0; for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { if (node->data != nullptr) { Jupiter::String &name = RenX::getFormattedPlayerName(node->data); if (name.size() > STRING_LENGTH - 32) continue; // Name will be too long to send. switch (node->data->team) { case RenX::TeamType::Nod: if (nCurrent == nullptr || nCurrent->size() + name.size() > STRING_LENGTH) { nCurrent = new Jupiter::StringL(STRING_LENGTH); nCurrent->format(IRCCOLOR "%.*s[%.*s]: " IRCBOLD "%.*s" IRCBOLD, nTeamColor.size(), nTeamColor.ptr(), nTeam.size(), nTeam.ptr(), name.size(), name.ptr()); nStrings.add(nCurrent); } else nCurrent->aformat(IRCCOLOR ", " IRCBOLD "%.*s" IRCBOLD, name.size(), name.ptr()); nTotal++; if (node->data->isBot) nBots++; break; case RenX::TeamType::GDI: if (gCurrent == nullptr || gCurrent->size() + name.size() > STRING_LENGTH) { gCurrent = new Jupiter::StringL(STRING_LENGTH); gCurrent->format(IRCCOLOR "%.*s[%.*s]: " IRCBOLD "%.*s" IRCBOLD, gTeamColor.size(), gTeamColor.ptr(), gTeam.size(), gTeam.ptr(), name.size(), name.ptr()); gStrings.add(gCurrent); } else gCurrent->aformat(IRCCOLOR ", " IRCBOLD "%.*s" IRCBOLD, name.size(), name.ptr()); gTotal++; if (node->data->isBot) gBots++; break; default: if (oCurrent == nullptr || oCurrent->size() + name.size() > STRING_LENGTH) { oCurrent = new Jupiter::StringL(STRING_LENGTH); oCurrent->format(IRCCOLOR "%.*s[%.*s]: " IRCBOLD "%.*s" IRCBOLD, oTeamColor.size(), oTeamColor.ptr(), oTeam.size(), oTeam.ptr(), name.size(), name.ptr()); oStrings.add(oCurrent); } else oCurrent->aformat(IRCCOLOR ", " IRCBOLD "%.*s" IRCBOLD, name.size(), name.ptr()); oTotal++; if (node->data->isBot) oBots++; break; } } } Jupiter::StringL *outString; while (gStrings.size() != 0) { outString = gStrings.remove(0U); source->sendMessage(channel, *outString); delete outString; } while (nStrings.size() != 0) { outString = nStrings.remove(0U); source->sendMessage(channel, *outString); delete outString; } while (oStrings.size() != 0) { outString = oStrings.remove(0U); source->sendMessage(channel, *outString); delete outString; } Jupiter::StringL out; out.format(IRCCOLOR "03Total Players" IRCCOLOR ": %u", server->players.size()); if (gBots + nBots + oBots > 0) out.aformat(" (%u bots)", gBots + nBots + oBots); if (gTotal > 0) { out.aformat(IRCCOLOR "02 | " IRCCOLOR "%.*s%.*s" IRCCOLOR ": %u", gTeamColor.size(), gTeamColor.ptr(), gTeam.size(), gTeam.ptr(), gTotal); if (gBots > 0) out.aformat(" (%u bots)", gBots); } if (nTotal > 0) { out.aformat(IRCCOLOR "02 | " IRCCOLOR "%.*s%.*s" IRCCOLOR ": %u", nTeamColor.size(), nTeamColor.ptr(), nTeam.size(), nTeam.ptr(), nTotal); if (nBots > 0) out.aformat(" (%u bots)", nBots); } if (oTotal > 0) { out.aformat(IRCCOLOR "02 | " IRCCOLOR "%.*s%.*s" IRCCOLOR ": %u", oTeamColor.size(), oTeamColor.ptr(), oTeam.size(), oTeam.ptr(), oTotal); if (oBots > 0) out.aformat(" (%u bots)", oBots); } source->sendMessage(channel, out); } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("No players are in-game.")); } } if (noServers) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } const Jupiter::ReadableString &PlayersIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Lists the players currently in-game. Syntax: Players"); return defaultHelp; } IRC_COMMAND_INIT(PlayersIRCCommand) // PlayerInfo IRC Command void PlayerInfoIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("playerinfo")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("pi")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("player")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("pinfo")); this->setAccessLevel(2); } void PlayerInfoIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.size() != 0) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; Jupiter::StringL msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type) && server->players.size() != 0) { for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->name.findi(parameters) != Jupiter::INVALID_INDEX) { if (source->getAccessLevel(channel, nick) > 1) msg = pluginInstance.getAdminPlayerInfoFormat(); else msg = pluginInstance.getPlayerInfoFormat(); RenX::processTags(msg, server, player); source->sendMessage(channel, msg); } } } } if (msg.isEmpty()) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: PlayerInfo ")); } const Jupiter::ReadableString &PlayerInfoIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Gets information about a player. Syntax: PlayerInfo "); return defaultHelp; } IRC_COMMAND_INIT(PlayerInfoIRCCommand) // Steam IRC Command void SteamIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("steam")); this->setAccessLevel(1); } void SteamIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; if (parameters.size() != 0) { Jupiter::StringL msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type) && server->players.size() != 0) { for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->name.findi(parameters) != Jupiter::INVALID_INDEX) { Jupiter::String &playerName = RenX::getFormattedPlayerName(player); msg.format(IRCCOLOR "03[Steam] " IRCCOLOR "%.*s (ID: %d) ", playerName.size(), playerName.ptr(), player->id); if (player->steamid != 0) { msg += "is using steam ID " IRCBOLD; msg += server->formatSteamID(player); msg.aformat(IRCBOLD "; Steam Profile: " IRCBOLD "https://steamcommunity.com/profiles/%llu" IRCBOLD, player->steamid); } else msg += "is not using steam."; source->sendMessage(channel, msg); } } } } if (msg.isEmpty()) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } else { unsigned int total; unsigned int realPlayers; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type) && server->players.size() != 0) { total = 0; realPlayers = 0; for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->isBot == false) { realPlayers++; if (player->steamid != 0) total++; } } if (realPlayers != 0) source->sendMessage(channel, Jupiter::StringS::Format("%.2f%% (%u/%u) of players are using Steam.", ((double)total * 100) / ((double)realPlayers), total, realPlayers)); else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("No players are in-game.")); } } } } } const Jupiter::ReadableString &SteamIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Fetches steam usage information. Syntax: Steam [Player]"); return defaultHelp; } IRC_COMMAND_INIT(SteamIRCCommand) // Kill-Death Ratio IRC Command void KillDeathRatioIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("kills")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("deaths")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("kdr")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("killdeathraio")); } void KillDeathRatioIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.size() != 0) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; Jupiter::StringL msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type) && server->players.size() != 0) { for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->name.findi(parameters) != Jupiter::INVALID_INDEX) { Jupiter::String &playerName = RenX::getFormattedPlayerName(player); msg.format(IRCBOLD "%.*s" IRCBOLD IRCCOLOR ": Kills: %u - Deaths: %u - KDR: %.2f", playerName.size(), playerName.ptr(), player->kills, player->deaths, ((float)player->kills) / (player->deaths == 0 ? 1.0 : (float)player->deaths)); source->sendMessage(channel, msg); } } } } if (msg.isEmpty()) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: Kills ")); } const Jupiter::ReadableString &KillDeathRatioIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Gets a player's kills and deaths. Syntax: Kills "); return defaultHelp; } IRC_COMMAND_INIT(KillDeathRatioIRCCommand) // ShowMods IRC Command void ShowModsIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("showmods")); } extern ModsGameCommand ModsGameCommand_instance; void ShowModsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); bool sent = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { ModsGameCommand_instance.trigger(server, nullptr, Jupiter::ReferenceString::empty); sent = true; } } if (sent == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } const Jupiter::ReadableString &ShowModsIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message, displaying the in-game moderators. Syntax: showmods"); return defaultHelp; } IRC_COMMAND_INIT(ShowModsIRCCommand) // Mods IRC Command void ModsIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("mods")); } void ModsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.equalsi("show")) ShowModsIRCCommand_instance.trigger(source, channel, nick, parameters); else { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; Jupiter::StringL msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { msg = ""; if (server->players.size() != 0) { for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->isBot == false && (player->adminType.size() != 0 || (player->access != 0 && (player->gamePrefix.isEmpty() == false || player->formatNamePrefix.isEmpty() == false)))) { if (msg.size() != 0) msg += ", "; else msg += "Moderators in-game: "; msg += player->gamePrefix; msg += player->name; } } } if (msg.size() == 0) msg = "No moderators are in-game."; source->sendMessage(channel, msg); } } if (msg.size() == 0) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } } const Jupiter::ReadableString &ModsIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message, displaying the in-game moderators. Syntax: mods [show]"); return defaultHelp; } IRC_COMMAND_INIT(ModsIRCCommand) // BanSearch IRC Command void BanSearchIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("bansearch")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("bsearch")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("banfind")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("bfind")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("banlogs")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("blogs")); this->setAccessLevel(2); } void BanSearchIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { auto entries = RenX::banDatabase->getEntries(); if (parameters.isEmpty() == false) { if (entries.size() == 0) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("The ban database is empty!")); else { RenX::BanDatabase::Entry *entry; Jupiter::ReferenceString params = Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE); std::function isMatch = [&](unsigned int type_l) -> bool { switch (type_l) { default: case 0: // ANY return isMatch(1) || isMatch(2) || isMatch(3) || isMatch(4); case 1: // IP return entry->ip == params.asUnsignedInt(); case 2: // STEAM return entry->steamid == params.asUnsignedLongLong(); case 3: // NAME return entry->name.equalsi(params); case 4: // BANNER return entry->varData.get(pluginInstance.getName()).equalsi(params); case 5: // ACTIVE if (params.asBool()) // Got tired of seeing a compiler warning. return entry->active == 1; else return entry->active == 0; case 6: // ALL return true; } }; unsigned int type; Jupiter::ReferenceString type_str = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); if (type_str.equalsi(STRING_LITERAL_AS_REFERENCE("ip"))) type = 1; else if (type_str.equalsi(STRING_LITERAL_AS_REFERENCE("steam"))) type = 2; else if (type_str.equalsi(STRING_LITERAL_AS_REFERENCE("name"))) type = 3; else if (type_str.equalsi(STRING_LITERAL_AS_REFERENCE("banner"))) type = 4; else if (type_str.equalsi(STRING_LITERAL_AS_REFERENCE("active"))) type = 5; else if (type_str.equalsi(STRING_LITERAL_AS_REFERENCE("any"))) type = 0; else if (type_str.equalsi(STRING_LITERAL_AS_REFERENCE("all")) || type_str.equals('*')) type = 6; else { type = 0; params = parameters; } Jupiter::String out(256); char timeStr[256]; for (size_t i = 0; i != entries.size(); i++) { entry = entries.get(i); if (isMatch(type)) { Jupiter::StringS ip_str = Jupiter::Socket::ntop4(entry->ip); const Jupiter::ReadableString &banner = entry->varData.get(pluginInstance.getName()); strftime(timeStr, sizeof(timeStr), "%b %d %Y; Time: %H:%M:%S", localtime(&(entry->timestamp))); out.format("ID: %lu; Status: %sactive; Date: %s; IP: %.*s; Steam: %llu; Name: %.*s%s", i, entry->active ? "" : "in", timeStr, ip_str.size(), ip_str.ptr(), entry->steamid, entry->name.size(), entry->name.ptr(), banner.isEmpty() ? "" : "; Banner: "); out.concat(banner); source->sendNotice(nick, out); } } if (out.isEmpty()) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("No matches found.")); } } else source->sendNotice(nick, Jupiter::StringS::Format("There are a total of %u entries in the ban database.", entries.size())); } const Jupiter::ReadableString &BanSearchIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Searches the ban database for an entry. Syntax: bsearch [ip/steam/name/banner/active/any/all = any] "); return defaultHelp; } IRC_COMMAND_INIT(BanSearchIRCCommand) // ShowRules IRC Command void ShowRulesIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("showrules")); } void ShowRulesIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); Jupiter::StringL msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { msg = "Rules: "; msg += server->getRules(); server->sendMessage(msg); } } if (msg.size() == 0) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } const Jupiter::ReadableString &ShowRulesIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message, displaying the in-game rules. Syntax: showrules"); return defaultHelp; } IRC_COMMAND_INIT(ShowRulesIRCCommand) // Rules IRC Command void RulesIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("rules")); } void RulesIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.equalsi("show")) ShowRulesIRCCommand_instance.trigger(source, channel, nick, parameters); else { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); Jupiter::StringL msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { msg = IRCCOLOR "11[Rules]" IRCCOLOR " "; msg += server->getRules(); source->sendMessage(channel, msg); } } if (msg.size() == 0) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } } const Jupiter::ReadableString &RulesIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays the in-game rules. Syntax: rules [show]"); return defaultHelp; } IRC_COMMAND_INIT(RulesIRCCommand) // SetRules IRC Command void SetRulesIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("setrules")); this->setAccessLevel(4); } void SetRulesIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.size() != 0) { unsigned int r = 0; Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { server->setRules(parameters); r++; } } if (r == 0) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } } const Jupiter::ReadableString &SetRulesIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sets the in-game rules. Syntax: setrules [show]"); return defaultHelp; } IRC_COMMAND_INIT(SetRulesIRCCommand) // Reconnect IRC Command void ReconnectIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("reconnect")); this->setAccessLevel(3); } void ReconnectIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); Jupiter::StringS msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { if (server->reconnect()) msg.set("Connection established"); else msg.format("[RenX] ERROR: Failed to connect to %.*s on port %u." ENDL, server->getHostname().size(), server->getHostname().ptr(), server->getPort()); source->sendMessage(channel, msg); } } if (msg.isEmpty()) { // We didn't connect anywhere!! msg.set("ERROR: No servers found to connect to."); source->sendMessage(channel, msg); } } } const Jupiter::ReadableString &ReconnectIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Resets the RCON connection. Syntax: Reconnect"); return defaultHelp; } IRC_COMMAND_INIT(ReconnectIRCCommand) // GameOver IRC Command void GameOverIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("gameover")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("endmap")); this->setAccessLevel(3); } void GameOverIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; if (server->gameover() == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support gameover.")); } } if (match == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } const Jupiter::ReadableString &GameOverIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Ends the game immediately. Syntax: Gameover"); return defaultHelp; } IRC_COMMAND_INIT(GameOverIRCCommand) // SetMap IRC Command void SetMapIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("setmap")); this->setAccessLevel(4); } void SetMapIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; if (server->setMap(parameters) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support setmap.")); } } if (match == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: setmap ")); } const Jupiter::ReadableString &SetMapIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Ends the game immediately. Syntax: setmap "); return defaultHelp; } IRC_COMMAND_INIT(SetMapIRCCommand) // Mute IRC Command void MuteIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("mute")); this->setAccessLevel(2); } void MuteIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; player = server->getPlayerByPartName(parameters); if (player != nullptr) { if (server->mute(player) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support muting players.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } if (match == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: mute ")); } const Jupiter::ReadableString &MuteIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Mutes a player. Syntax: mute "); return defaultHelp; } IRC_COMMAND_INIT(MuteIRCCommand) // UnMute IRC Command void UnMuteIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("unmute")); this->setAccessLevel(2); } void UnMuteIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; player = server->getPlayerByPartName(parameters); if (player != nullptr) { if (server->unmute(player) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support muting players.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } if (match == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: unmute ")); } const Jupiter::ReadableString &UnMuteIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Unmutes a player. Syntax: unmute "); return defaultHelp; } IRC_COMMAND_INIT(UnMuteIRCCommand) // Kill IRC Command void KillIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("kill")); this->setAccessLevel(2); } void KillIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; player = server->getPlayerByPartName(parameters); if (player != nullptr) { if (server->kill(player) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support muting players.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } if (match == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: kill ")); } const Jupiter::ReadableString &KillIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kills a player. Syntax: kill "); return defaultHelp; } IRC_COMMAND_INIT(KillIRCCommand) // Disarm IRC Command void DisarmIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("disarm")); this->setAccessLevel(2); } void DisarmIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; player = server->getPlayerByPartName(parameters); if (player != nullptr) { if (server->disarm(player) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support muting players.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } if (match == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: disarm ")); } const Jupiter::ReadableString &DisarmIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Disarms all of a player's deployed objects. Syntax: disarm "); return defaultHelp; } IRC_COMMAND_INIT(DisarmIRCCommand) // DisarmC4 IRC Command void DisarmC4IRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("disarmc4")); this->setAccessLevel(2); } void DisarmC4IRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; player = server->getPlayerByPartName(parameters); if (player != nullptr) { if (server->disarmC4(player) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support muting players.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } if (match == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: disarmC4 ")); } const Jupiter::ReadableString &DisarmC4IRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Disarms all of a player's deployed C4s. Syntax: disarmc4 "); return defaultHelp; } IRC_COMMAND_INIT(DisarmC4IRCCommand) // DisarmBeacon IRC Command void DisarmBeaconIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("disarmb")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("disarmbeacon")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("disarmbeacons")); this->setAccessLevel(2); } void DisarmBeaconIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); RenX::PlayerInfo *player; bool match = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type)) { match = true; player = server->getPlayerByPartName(parameters); if (player != nullptr) { if (server->disarmBeacon(player) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support muting players.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } if (match == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: disarmb ")); } const Jupiter::ReadableString &DisarmBeaconIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Disarms all of a player's deployed beacons. Syntax: disarmb "); return defaultHelp; } IRC_COMMAND_INIT(DisarmBeaconIRCCommand) // Kick IRC Command void KickIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("kick")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("qkick")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("k")); this->setAccessLevel(2); } void KickIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.size() != 0) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); if (servers.size() != 0) { RenX::PlayerInfo *player; RenX::Server *server; unsigned int kicks = 0; for (size_t i = 0; i != servers.size(); i++) { server = servers.get(i); if (server != nullptr) { player = server->getPlayerByPartName(parameters); if (player != nullptr) { server->kickPlayer(player); kicks++; } } } source->sendMessage(channel, Jupiter::StringS::Format("%u players kicked.", kicks)); } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: Kick ")); } const Jupiter::ReadableString &KickIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks a player from the game. Syntax: Kick "); return defaultHelp; } IRC_COMMAND_INIT(KickIRCCommand) // TempBan IRC Command void TempBanIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("tban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("tb")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("tempban")); this->setAccessLevel(3); } void TempBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.size() != 0) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); if (servers.size() != 0) { RenX::PlayerInfo *player; RenX::Server *server; unsigned int kicks = 0; Jupiter::String banner(nick.size() + 4); banner += nick; banner += "@IRC"; for (size_t i = 0; i != servers.size(); i++) { server = servers.get(i); if (server != nullptr) { player = server->getPlayerByPartName(parameters); if (player != nullptr) { player->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), nick); server->banPlayer(player, pluginInstance.getTBanTime()); kicks++; } } } source->sendMessage(channel, Jupiter::StringS::Format("%u players kicked.", kicks)); } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: TempBan ")); } const Jupiter::ReadableString &TempBanIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and temporarily bans a player from the game. Syntax: TempBan "); return defaultHelp; } IRC_COMMAND_INIT(TempBanIRCCommand) // KickBan IRC Command void KickBanIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("kickban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("kb")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("ban")); this->setAccessLevel(4); } void KickBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.size() != 0) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); if (servers.size() != 0) { RenX::PlayerInfo *player; RenX::Server *server; unsigned int kicks = 0; Jupiter::String banner(nick.size() + 4); banner += nick; banner += "@IRC"; for (size_t i = 0; i != servers.size(); i++) { server = servers.get(i); if (server != nullptr) { player = server->getPlayerByPartName(parameters); if (player != nullptr) { player->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), nick); server->banPlayer(player); kicks++; } } } source->sendMessage(channel, Jupiter::StringS::Format("%u players kicked.", kicks)); } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: KickBan ")); } const Jupiter::ReadableString &KickBanIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and bans a player from the game. Syntax: KickBan "); return defaultHelp; } IRC_COMMAND_INIT(KickBanIRCCommand) // UnBan IRC Command void UnBanIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("unban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("deban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("uban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("dban")); this->setAccessLevel(4); } void UnBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.size() != 0) { size_t index = static_cast(parameters.asUnsignedLongLong()); if (index < RenX::banDatabase->getEntries().size()) { if (RenX::banDatabase->deactivate(index)) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Ban deactivated.")); else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Ban not active.")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Invalid ban ID; please find the ban ID using \"bansearch\".")); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: unban ")); } const Jupiter::ReadableString &UnBanIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Deactivates a ban. Syntax: unban "); return defaultHelp; } IRC_COMMAND_INIT(UnBanIRCCommand) // AddBots IRC Command void AddBotsIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("addbots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("addbot")); this->setAccessLevel(2); } void AddBotsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { Jupiter::ArrayList servers = RenX::getCore()->getServers(source->getChannel(channel)->getType()); if (servers.size() != 0) { int amount = 1; if (parameters.isEmpty() == false) amount = parameters.asInt(); if (amount != 0) { RenX::Server *server; Jupiter::StringL cmd; RenX::TeamType team = RenX::getTeam(Jupiter::ReferenceString::getWord(parameters, 1, WHITESPACE)); switch (team) { case RenX::TeamType::GDI: cmd = "addredbots "; break; case RenX::TeamType::Nod: cmd = "addbluebots "; break; case RenX::TeamType::None: case RenX::TeamType::Other: cmd = "addbots "; break; } for (size_t i = 0, extra; i != servers.size(); i++) { server = servers.get(i); if (server != nullptr) { extra = cmd.aformat("%u", amount); server->send(cmd); cmd -= extra; } server->sendMessage(Jupiter::StringS::Format("%u bots have been added to the server.", amount)); } } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Invalid amount entered. Amount must be a positive integer.")); } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } const Jupiter::ReadableString &AddBotsIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Adds bots to the game. Syntax: AddBots [Amount=1] [Team]"); return defaultHelp; } IRC_COMMAND_INIT(AddBotsIRCCommand) // KillBots IRC Command void KillBotsIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("killbots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("killbot")); this->setAccessLevel(2); } void KillBotsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); if (servers.size() != 0) { RenX::Server *server; for (size_t i = 0; i != servers.size(); i++) { server = servers.get(i); server->send(STRING_LITERAL_AS_REFERENCE("killbots")); server->sendMessage(STRING_LITERAL_AS_REFERENCE("All bots have been removed from the server.")); } } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } const Jupiter::ReadableString &KillBotsIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Removes all bots from the game. Syntax: KillBots"); return defaultHelp; } IRC_COMMAND_INIT(KillBotsIRCCommand) // PhaseBots IRC Command void PhaseBotsIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("phasebots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("phasebot")); this->setAccessLevel(2); } void PhaseBotsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); if (servers.size() != 0) { RenX::Server *server; for (size_t i = 0; i != servers.size(); i++) { server = servers.get(i); if (parameters.size() == 0) { if (togglePhasing(server)) server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been enabled.")); else server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been disabled.")); } else if (parameters.equalsi("true") || parameters.equalsi("on") || parameters.equalsi("start") || parameters.equalsi("1")) { togglePhasing(server, true); server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been enabled.")); } else { togglePhasing(server, false); server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been disabled.")); } } } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } const Jupiter::ReadableString &PhaseBotsIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Toggles the phasing of bots from the game by kicking them after death. Syntax: PhaseBots [on/off]"); return defaultHelp; } IRC_COMMAND_INIT(PhaseBotsIRCCommand) // RCON IRC Command void RCONIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("rcon")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("renx")); this->setAccessLevel(5); } void RCONIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters != nullptr) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { unsigned int r = RenX::getCore()->send(chan->getType(), parameters); if (r > 0) source->sendMessage(channel, Jupiter::StringS::Format("Command sent to %u servers.", r)); else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: rcon ")); } const Jupiter::ReadableString &RCONIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends data to the Renegade X server's rcon. Syntax: rcon "); return defaultHelp; } IRC_COMMAND_INIT(RCONIRCCommand) // Refund IRC Command void RefundIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("refund")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("givecredits")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("gc")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("money")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("credits")); this->setAccessLevel(3); } void RefundIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.wordCount(WHITESPACE) >= 2) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); Jupiter::ReferenceString playerName = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); double credits = Jupiter::ReferenceString::getWord(parameters, 1, WHITESPACE).asDouble(); RenX::PlayerInfo *player; Jupiter::StringL msg; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type) && server->players.size() != 0) { for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->name.findi(playerName) != Jupiter::INVALID_INDEX) { if (server->giveCredits(player, credits)) { msg.format("You have been refunded %.0f credits by %.*s.", credits, nick.size(), nick.ptr()); server->sendMessage(player, msg); msg.format("%.*s has been refunded %.0f credits.", player->name.size(), player->name.ptr(), credits); } else msg.set("Error: Server does not support refunds."); source->sendMessage(channel, msg); } } } } if (msg.isEmpty()) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: refund ")); } const Jupiter::ReadableString &RefundIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Refunds a player's credits. Syntax: refund "); return defaultHelp; } IRC_COMMAND_INIT(RefundIRCCommand) // Team-Change IRC Command void TeamChangeIRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("team")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("tc")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("ftc")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("forcetc")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("teamchange")); this->setAccessLevel(3); } void TeamChangeIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); Jupiter::ReferenceString playerName = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); RenX::PlayerInfo *player; bool playerFound = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type) && server->players.size() != 0) { for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->name.findi(playerName) != Jupiter::INVALID_INDEX) { playerFound = true; if (server->changeTeam(player) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support team changing.")); } } } } if (playerFound == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: team ")); } const Jupiter::ReadableString &TeamChangeIRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Changes a player's team. Syntax: team "); return defaultHelp; } IRC_COMMAND_INIT(TeamChangeIRCCommand) // TeamChange2 IRC Command void TeamChange2IRCCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("team2")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("tc2")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("ftc2")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("forcetc2")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("teamchange2")); this->setAccessLevel(3); } void TeamChange2IRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { int type = chan->getType(); Jupiter::ReferenceString playerName = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); RenX::PlayerInfo *player; bool playerFound = false; for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) { RenX::Server *server = RenX::getCore()->getServer(i); if (server->isLogChanType(type) && server->players.size() != 0) { for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->name.findi(playerName) != Jupiter::INVALID_INDEX) { playerFound = true; if (server->changeTeam(player, false) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Server does not support team changing.")); } } } } if (playerFound == false) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); } } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: team2 ")); } const Jupiter::ReadableString &TeamChange2IRCCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Changes a player's team, without resetting their credits. Syntax: team2 "); return defaultHelp; } IRC_COMMAND_INIT(TeamChange2IRCCommand) /** Game Commands */ // Help Game Command void HelpGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("help")); } void HelpGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { RenX::GameCommand *cmd; unsigned int cmdCount = 0; auto getAccessCommands = [&](int accessLevel) { Jupiter::String list; unsigned int i = 0; while (i != source->getCommandCount()) { cmd = source->getCommand(i++); if (cmd->getAccessLevel() == accessLevel) { cmdCount++; list.format("Access level %d commands: %.*s", accessLevel, cmd->getTrigger().size(), cmd->getTrigger().ptr()); break; } } while (i != source->getCommandCount()) { cmd = source->getCommand(i++); if (cmd->getAccessLevel() == accessLevel) { cmdCount++; list += ", "; list += cmd->getTrigger(); } } return list; }; if (parameters.wordCount(WHITESPACE) == 0) { for (int i = 0; i <= player->access; i++) { Jupiter::ReadableString &msg = getAccessCommands(i); if (msg.isEmpty() == false) source->sendMessage(player, getAccessCommands(i)); } if (cmdCount == 0) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("No listed commands available.")); } else { cmd = source->getCommand(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE)); if (cmd != nullptr) { if (player->access >= cmd->getAccessLevel()) source->sendMessage(player, cmd->getHelp(Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE))); else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Access Denied.")); } else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Command not found.")); } } const Jupiter::ReadableString &HelpGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Lists commands, or sends command-specific help. Syntax: help [command]"); return defaultHelp; } GAME_COMMAND_INIT(HelpGameCommand) // Mods Game Command void ModsGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("mods")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("showmods")); } void ModsGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *, const Jupiter::ReadableString &) { RenX::PlayerInfo *player; Jupiter::StringL msg; for (Jupiter::DLList::Node *node = source->players.getNode(0); node != nullptr; node = node->next) { player = node->data; if (player->isBot == false && (player->adminType.size() != 0 || (player->access != 0 && (player->gamePrefix.isEmpty() == false || player->formatNamePrefix.isEmpty() == false)))) { if (msg.size() != 4) msg += ", "; else msg += "Moderators in-game: "; msg += player->gamePrefix; msg += player->name; } } if (msg.size() == 4) { msg += "No moderators are in-game"; RenX::GameCommand *cmd = source->getCommand(STRING_LITERAL_AS_REFERENCE("modrequest")); if (cmd != nullptr) msg.aformat("; please use \"%.*s%.*s\" if you require assistance.", source->getCommandPrefix().size(), source->getCommandPrefix().ptr(), cmd->getTrigger().size(), cmd->getTrigger().ptr()); else msg += '.'; } source->sendMessage(msg); } const Jupiter::ReadableString &ModsGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays the in-game moderators. Syntax: mods"); return defaultHelp; } GAME_COMMAND_INIT(ModsGameCommand) // Rules Game Command void RulesGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("rules")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("rule")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("showrules")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("showrule")); } void RulesGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { source->sendMessage(Jupiter::StringS::Format("Rules: %.*s", source->getRules().size(), source->getRules().ptr())); } const Jupiter::ReadableString &RulesGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays the rules for this server. Syntax: rules"); return defaultHelp; } GAME_COMMAND_INIT(RulesGameCommand) // Mod Request Game Command void ModRequestGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("modrequest")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("requestmod")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("mod")); } void ModRequestGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { unsigned int serverCount = serverManager->size(); IRC_Bot *server; Jupiter::IRC::Client::Channel *channel; unsigned int channelCount; unsigned int messageCount = 0; int type; Jupiter::String &fmtName = RenX::getFormattedPlayerName(player); Jupiter::StringL msg = Jupiter::StringL::Format(IRCCOLOR "12[Moderator Request] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR "07 has requested assistance in-game; please look in ", fmtName.size(), fmtName.ptr()); Jupiter::StringS msg2 = Jupiter::StringS::Format(IRCCOLOR "12[Moderator Request] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR "07 has requested assistance in-game!" IRCCOLOR, fmtName.size(), fmtName.ptr()); for (unsigned int a = 0; a < serverCount; a++) { server = serverManager->getServer(a); if (server != nullptr) { channelCount = server->getChannelCount(); for (unsigned int b = 0; b < channelCount; b++) { channel = server->getChannel(b); if (channel != nullptr) { type = channel->getType(); if (source->isLogChanType(type)) { server->sendMessage(channel->getName(), msg2); msg += channel->getName(); for (unsigned int c = 0; c < channel->getUserCount(); c++) { if (channel->getUserPrefix(c) != 0 && channel->getUser(c)->getNickname().equals(server->getNickname()) == false) { server->sendMessage(channel->getUser(c)->getUser()->getNickname(), msg); messageCount++; } } msg -= channel->getName().size(); } } } } } source->sendMessage(player, Jupiter::StringS::Format("A total of %u moderators have been notified of your assistance request.", messageCount)); } const Jupiter::ReadableString &ModRequestGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Notifies the moderators on IRC that assistance is required. Syntax: modRequest"); return defaultHelp; } GAME_COMMAND_INIT(ModRequestGameCommand) // Kick Game Command void KickGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("kick")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("qkick")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("k")); this->setAccessLevel(1); } void KickGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (player == target) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not kick yourself.")); else if (target->access >= player->access) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not kick higher level moderators.")); else { source->kickPlayer(target); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been kicked from the game.")); } } else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: kick ")); } const Jupiter::ReadableString &KickGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks a player from the game. Syntax: kick "); return defaultHelp; } GAME_COMMAND_INIT(KickGameCommand) // TempBan Game Command void TempBanGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("tban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("tempbank")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("tb")); this->setAccessLevel(1); } void TempBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (player == target) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not ban yourself.")); else if (target->access >= player->access) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not ban higher level moderators.")); else { target->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), player->name); source->banPlayer(target, pluginInstance.getTBanTime()); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been temporarily banned and kicked from the game.")); } } else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: tban ")); } const Jupiter::ReadableString &TempBanGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and temporarily bans a player from the game. Syntax: tban "); return defaultHelp; } GAME_COMMAND_INIT(TempBanGameCommand) // KickBan Game Command void KickBanGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("ban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("kickban")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("kb")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("b")); this->setAccessLevel(2); } void KickBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { if (parameters.isEmpty() == false) { RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (player == target) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not ban yourself.")); else if (target->access >= player->access) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not ban higher level moderators.")); else { target->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), player->name); source->banPlayer(target); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been banned and kicked from the game.")); } } else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: ban ")); } const Jupiter::ReadableString &KickBanGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and bans a player from the game. Syntax: ban "); return defaultHelp; } GAME_COMMAND_INIT(KickBanGameCommand) // AddBots Game Command void AddBotsGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("addbots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("abots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("addbot")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("abot")); this->setAccessLevel(1); } void AddBotsGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { RenX::TeamType team = RenX::getTeam(Jupiter::ReferenceString::getWord(parameters, 1, WHITESPACE)); Jupiter::StringS cmd; switch (team) { case RenX::TeamType::GDI: cmd = "addredbots "; break; case RenX::TeamType::Nod: cmd = "addbluebots "; break; default: case RenX::TeamType::None: case RenX::TeamType::Other: cmd = "addbots "; break; } unsigned int amount; if (parameters.isEmpty()) amount = 1; else amount = parameters.asUnsignedInt(); cmd += Jupiter::StringS::Format("%u", amount); source->send(cmd); source->sendMessage(player, Jupiter::StringS::Format("%u bots have been added to the server.", amount)); } const Jupiter::ReadableString &AddBotsGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Adds bots to the game. Syntax: addbots [amount=1] [team]"); return defaultHelp; } GAME_COMMAND_INIT(AddBotsGameCommand) // KillBots Game Command void KillBotsGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("killbots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("kbots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("rembots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("rbots")); this->setAccessLevel(2); } void KillBotsGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { source->send(STRING_LITERAL_AS_REFERENCE("killbots")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("All bots have been removed from the server.")); } const Jupiter::ReadableString &KillBotsGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Removes all bots from the game. Syntax: killbots"); return defaultHelp; } GAME_COMMAND_INIT(KillBotsGameCommand) // PhaseBots Game Command void PhaseBotsGameCommand::create() { this->addTrigger(STRING_LITERAL_AS_REFERENCE("phasebots")); this->addTrigger(STRING_LITERAL_AS_REFERENCE("pbots")); this->setAccessLevel(1); } void PhaseBotsGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) { if (parameters.size() == 0) { if (togglePhasing(source)) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Bot phasing has been enabled.")); else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Bot phasing has been disabled.")); } else if (parameters.equalsi("true") || parameters.equalsi("on") || parameters.equalsi("start") || parameters.equalsi("1")) { togglePhasing(source, true); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Bot phasing has been enabled.")); } else { togglePhasing(source, false); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Bot phasing has been disabled.")); } } const Jupiter::ReadableString &PhaseBotsGameCommand::getHelp(const Jupiter::ReadableString &) { static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Removes all bots from the game. Syntax: phasebots"); return defaultHelp; } GAME_COMMAND_INIT(PhaseBotsGameCommand) extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() { return &pluginInstance; }