From 50e96e6ebeacbc5a7a9cb6a586b7f120a2021e82 Mon Sep 17 00:00:00 2001 From: JustinAJ Date: Thu, 28 May 2015 03:25:40 -0400 Subject: [PATCH] Added reasons to kicks and bans. RenX::BanDataBase: * Added "reason" parameter to add() * Added reason to Entry * Added write() functions * Version number incremented RenX::Server: * Added "reason" parameter to kickPlayer() and banPlayer() functions. * Added forceKickPlayer() function Adjusted plugins to above changes. --- Release/Plugins/RenX.Core.lib | Bin 122554 -> 125108 bytes RenX.Commands/RenX_Commands.cpp | 61 ++++++---- RenX.Core/RenX_BanDatabase.cpp | 108 +++++++++++++----- RenX.Core/RenX_BanDatabase.h | 18 ++- RenX.Core/RenX_Server.cpp | 81 ++++++++----- RenX.Core/RenX_Server.h | 22 +++- .../ExcessiveHeadshots.cpp | 2 +- RenX.ModSystem/RenX_ModSystem.cpp | 2 +- RenX.Warn/RenX_Warn.cpp | 8 +- 9 files changed, 211 insertions(+), 91 deletions(-) diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index e59c6e7001a6c0de6fd212d4595f8bb19292b177..b97b55e8fde412f138abf47782ba48e315142b4d 100644 GIT binary patch delta 14206 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 G`TqdA?A{On delta 13445 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 && server->varData.getBool(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), false)) server->kickPlayer(player); + if (player->isBot && server->varData.getBool(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), false)) + server->kickPlayer(player, Jupiter::StringS::empty); } bool RenX_CommandsPlugin::RenX_OnBan(RenX::Server *server, const RenX::PlayerInfo *player, Jupiter::StringType &data) @@ -1517,16 +1518,18 @@ void KickIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &cha RenX::PlayerInfo *player; RenX::Server *server; unsigned int kicks = 0; + Jupiter::StringS name = Jupiter::StringS::getWord(parameters, 0, WHITESPACE); + Jupiter::StringS reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::StringS::gotoWord(parameters, 1, WHITESPACE) : STRING_LITERAL_AS_REFERENCE("No reason"); for (size_t i = 0; i != servers.size(); i++) { server = servers.get(i); if (server != nullptr) { - player = server->getPlayerByPartName(parameters); + player = server->getPlayerByPartName(name); if (player != nullptr) { - server->kickPlayer(player); - kicks++; + server->kickPlayer(player, reason); + ++kicks; } } } @@ -1535,12 +1538,12 @@ void KickIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &cha 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 ")); + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: Kick [Reason]")); } const Jupiter::ReadableString &KickIRCCommand::getHelp(const Jupiter::ReadableString &) { - static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks a player from the game. Syntax: Kick "); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks a player from the game. Syntax: Kick [Reason]"); return defaultHelp; } @@ -1569,6 +1572,8 @@ void TempBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & RenX::PlayerInfo *player; RenX::Server *server; unsigned int kicks = 0; + Jupiter::StringS name = Jupiter::StringS::getWord(parameters, 0, WHITESPACE); + Jupiter::StringS reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::StringS::gotoWord(parameters, 1, WHITESPACE) : STRING_LITERAL_AS_REFERENCE("No reason"); Jupiter::String banner(nick.size() + 4); banner += nick; banner += "@IRC"; @@ -1577,11 +1582,11 @@ void TempBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & server = servers.get(i); if (server != nullptr) { - player = server->getPlayerByPartName(parameters); + player = server->getPlayerByPartName(name); if (player != nullptr) { player->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), nick); - server->banPlayer(player, pluginInstance.getTBanTime()); + server->banPlayer(player, reason, pluginInstance.getTBanTime()); kicks++; } } @@ -1591,12 +1596,12 @@ void TempBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & 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 ")); + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: TempBan [Reason]")); } 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 "); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and temporarily bans a player from the game. Syntax: TempBan [Reason]"); return defaultHelp; } @@ -1625,6 +1630,8 @@ void KickBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & RenX::PlayerInfo *player; RenX::Server *server; unsigned int kicks = 0; + Jupiter::StringS name = Jupiter::StringS::getWord(parameters, 0, WHITESPACE); + Jupiter::StringS reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::StringS::gotoWord(parameters, 1, WHITESPACE) : STRING_LITERAL_AS_REFERENCE("No reason"); Jupiter::String banner(nick.size() + 4); banner += nick; banner += "@IRC"; @@ -1637,7 +1644,7 @@ void KickBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & if (player != nullptr) { player->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), nick); - server->banPlayer(player); + server->banPlayer(player, reason); kicks++; } } @@ -1647,12 +1654,12 @@ void KickBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & 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 ")); + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: KickBan [Reason]")); } 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 "); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and bans a player from the game. Syntax: KickBan [Reason]"); return defaultHelp; } @@ -2412,7 +2419,9 @@ void KickGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, co { if (parameters.isEmpty() == false) { - RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); + Jupiter::StringS name = Jupiter::StringS::getWord(parameters, 0, WHITESPACE); + Jupiter::StringS reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::StringS::gotoWord(parameters, 1, WHITESPACE) : STRING_LITERAL_AS_REFERENCE("No reason"); + RenX::PlayerInfo *target = source->getPlayerByPartName(name); if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (player == target) @@ -2421,17 +2430,17 @@ void KickGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, co source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not kick higher level moderators.")); else { - source->kickPlayer(target); + source->kickPlayer(target, reason); 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 ")); + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: kick [Reason]")); } const Jupiter::ReadableString &KickGameCommand::getHelp(const Jupiter::ReadableString &) { - static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks a player from the game. Syntax: kick "); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks a player from the game. Syntax: kick [Reason]"); return defaultHelp; } @@ -2451,7 +2460,9 @@ void TempBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, { if (parameters.isEmpty() == false) { - RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); + Jupiter::StringS name = Jupiter::StringS::getWord(parameters, 0, WHITESPACE); + Jupiter::StringS reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::StringS::gotoWord(parameters, 1, WHITESPACE) : STRING_LITERAL_AS_REFERENCE("No reason"); + RenX::PlayerInfo *target = source->getPlayerByPartName(name); if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (player == target) @@ -2461,17 +2472,17 @@ void TempBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, else { target->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), player->name); - source->banPlayer(target, pluginInstance.getTBanTime()); + source->banPlayer(target, reason, 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 ")); + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: tban [Reason]")); } 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 "); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and temporarily bans a player from the game. Syntax: tban [Reason]"); return defaultHelp; } @@ -2492,6 +2503,8 @@ void KickBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, { if (parameters.isEmpty() == false) { + Jupiter::StringS name = Jupiter::StringS::getWord(parameters, 0, WHITESPACE); + Jupiter::StringS reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::StringS::gotoWord(parameters, 1, WHITESPACE) : STRING_LITERAL_AS_REFERENCE("No reason"); RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); @@ -2502,17 +2515,17 @@ void KickBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, else { target->varData.set(pluginInstance.getName(), STRING_LITERAL_AS_REFERENCE("banner"), player->name); - source->banPlayer(target); + source->banPlayer(target, reason); 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 ")); + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: ban [reason]")); } 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 "); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and bans a player from the game. Syntax: ban [reason]"); return defaultHelp; } diff --git a/RenX.Core/RenX_BanDatabase.cpp b/RenX.Core/RenX_BanDatabase.cpp index 92710d4..d1b435a 100644 --- a/RenX.Core/RenX_BanDatabase.cpp +++ b/RenX.Core/RenX_BanDatabase.cpp @@ -27,6 +27,9 @@ RenX::BanDatabase _banDatabase; RenX::BanDatabase *RenX::banDatabase = &_banDatabase; RenX::BanDatabase &RenX::defaultBanDatabase = _banDatabase; +const Jupiter::ReferenceString DEFAULT_REASON = "(No reason information provided)"; +const uint8_t write_version = 1; + bool RenX::BanDatabase::load(const Jupiter::ReadableString &fname) { RenX::BanDatabase::filename = fname; @@ -40,6 +43,9 @@ bool RenX::BanDatabase::load(const Jupiter::ReadableString &fname) Jupiter::String playerName(16); Jupiter::String key(32); Jupiter::String value(32); + Jupiter::String reason(128); + if (RenX::BanDatabase::version < 1) + reason = DEFAULT_REASON; Entry *entry; int c; while (!feof(file)) @@ -72,6 +78,24 @@ bool RenX::BanDatabase::load(const Jupiter::ReadableString &fname) } entry->name = playerName; + // load reason + if (RenX::BanDatabase::version >= 1) + { + reason.truncate(reason.size()); + c = fgetc(file); + while (c != '\n' && c != '\0') + { + if (c == EOF) + { + fprintf(stderr, "ERROR: Unexpected EOF in %s at %lu", RenX::BanDatabase::filename.c_str(), ftell(file)); + break; + } + reason += c; + c = fgetc(file); + } + } + entry->reason = reason; + // load variable data while (c == '\0') { @@ -109,11 +133,23 @@ bool RenX::BanDatabase::load(const Jupiter::ReadableString &fname) entries.add(entry); } fclose(file); + if (RenX::BanDatabase::version != write_version) + { + file = fopen(RenX::BanDatabase::filename.c_str(), "wb"); + if (file != nullptr) + { + size_t index = 0; + while (index != RenX::BanDatabase::entries.size()) + RenX::BanDatabase::write(RenX::BanDatabase::entries.get(++index), file); + } + fprintf(stdout, "Updated BanDatabase file \"%s\" from version %d to %d.", RenX::BanDatabase::filename.c_str(), RenX::BanDatabase::version, write_version); + RenX::BanDatabase::version = write_version; + } return true; } else { - RenX::BanDatabase::version = 0; + RenX::BanDatabase::version = write_version; file = fopen(RenX::BanDatabase::filename.c_str(), "ab"); if (file != nullptr) { @@ -126,7 +162,39 @@ bool RenX::BanDatabase::load(const Jupiter::ReadableString &fname) } } -void RenX::BanDatabase::add(RenX::Server *server, const RenX::PlayerInfo *player, time_t length) +void RenX::BanDatabase::write(RenX::BanDatabase::Entry *entry) +{ + FILE *file = fopen(RenX::BanDatabase::filename.c_str(), "ab"); + if (file != nullptr) + { + RenX::BanDatabase::write(entry, file); + fclose(file); + } +} + +void RenX::BanDatabase::write(RenX::BanDatabase::Entry *entry, FILE *file) +{ + fgetpos(file, &entry->pos); + fwrite(&entry->active, 1, 1, file); + fwrite(&entry->timestamp, sizeof(time_t), 1, file); + fwrite(&entry->length, sizeof(time_t), 1, file); + fwrite(&entry->steamid, sizeof(uint64_t), 1, file); + fwrite(&entry->ip, sizeof(uint32_t), 1, file); + fwrite(entry->name.ptr(), sizeof(char), entry->name.size(), file); + + for (size_t index = 0; index != entry->varData.size(); ++index) + { + const Jupiter::INIFile::Section::KeyValuePair *pair = entry->varData.getPair(index); + fputc('\0', file); + fwrite(pair->getKey().ptr(), sizeof(char), pair->getKey().size(), file); + fputc('\0', file); + fwrite(pair->getValue().ptr(), sizeof(char), pair->getValue().size(), file); + } + + fputc('\n', file); +} + +void RenX::BanDatabase::add(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason, time_t length) { Entry *entry = new Entry(); entry->active = 1; @@ -135,36 +203,16 @@ void RenX::BanDatabase::add(RenX::Server *server, const RenX::PlayerInfo *player entry->steamid = player->steamid; entry->ip = player->ip32; entry->name = player->name; - entries.add(entry); - FILE *file = fopen(RenX::BanDatabase::filename.c_str(), "ab"); - if (file != nullptr) - { - fgetpos(file, &entry->pos); - fwrite(&entry->active, 1, 1, file); - fwrite(&entry->timestamp, sizeof(time_t), 1, file); - fwrite(&entry->length, sizeof(time_t), 1, file); - fwrite(&entry->steamid, sizeof(uint64_t), 1, file); - fwrite(&entry->ip, sizeof(uint32_t), 1, file); - fwrite(entry->name.ptr(), sizeof(char), entry->name.size(), file); - // add plugin data - Jupiter::String pluginData; - Jupiter::ArrayList &xPlugins = *RenX::getCore()->getPlugins(); - for (size_t i = 0; i < xPlugins.size(); i++) - if (xPlugins.get(i)->RenX_OnBan(server, player, pluginData)) - { - const Jupiter::ReadableString &pluginName = xPlugins.get(i)->getName(); - fputc('\0', file); - fwrite(pluginName.ptr(), sizeof(char), pluginName.size(), file); - fputc('\0', file); - fwrite(pluginData.ptr(), sizeof(char), pluginData.size(), file); - entry->varData.set(pluginName, pluginData); - } + // add plugin data + Jupiter::String pluginData; + Jupiter::ArrayList &xPlugins = *RenX::getCore()->getPlugins(); + for (size_t i = 0; i < xPlugins.size(); i++) + if (xPlugins.get(i)->RenX_OnBan(server, player, pluginData)) + entry->varData.set(xPlugins.get(i)->getName(), pluginData); - - fputc('\n', file); - fclose(file); - } + entries.add(entry); + RenX::BanDatabase::write(entry); } bool RenX::BanDatabase::deactivate(size_t index) diff --git a/RenX.Core/RenX_BanDatabase.h b/RenX.Core/RenX_BanDatabase.h index a8eb205..b2599d9 100644 --- a/RenX.Core/RenX_BanDatabase.h +++ b/RenX.Core/RenX_BanDatabase.h @@ -53,6 +53,7 @@ namespace RenX uint64_t steamid /** SteamID of the banned player */; uint32_t ip /** IPv4 address of the banned player */; Jupiter::StringS name /** Name of the banned player */; + Jupiter::StringS reason /** Reason the player was banned */; Jupiter::INIFile::Section varData; /** Variable entry data */ }; @@ -72,7 +73,22 @@ namespace RenX * @param player Data of the player to be banned * @param length Duration of the ban */ - void add(RenX::Server *server, const RenX::PlayerInfo *player, time_t length); + void add(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason, time_t length); + + /** + * @brief Writes a ban file to the database. + * + * @param entry Entry to write to the database. + */ + void write(Entry *entry); + + /** + * @brief Writes a ban file to the database. + * + * @param entry Entry to write to the database. + * @param file FILE stream to write to. + */ + static void write(Entry *entry, FILE *file); /** * @brief Deactivates a ban entry. diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index b45e07d..68cfa46 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -278,37 +278,58 @@ Jupiter::StringS RenX::Server::formatSteamID(uint64_t id) const } } -void RenX::Server::kickPlayer(int id) +void RenX::Server::kickPlayer(int id, const Jupiter::ReadableString &reason) { - RenX::Server::sock.send(Jupiter::StringS::Format("ckick pid%d\n", id)); + if (reason.isEmpty()) + RenX::Server::sock.send(Jupiter::StringS::Format("ckick pid%d\n", id)); + else + RenX::Server::sock.send(Jupiter::StringS::Format("ckick pid%d %.*s\n", id, reason.size(), reason.ptr())); +} + +void RenX::Server::kickPlayer(const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason) +{ + RenX::Server::kickPlayer(player->id, reason); +} + +void RenX::Server::forceKickPlayer(int id, const Jupiter::ReadableString &reason) +{ + if (reason.isEmpty()) + RenX::Server::sock.send(Jupiter::StringS::Format("cfkick pid%d You were kicked from the server.\n", id)); + else + RenX::Server::sock.send(Jupiter::StringS::Format("cfkick pid%d %.*s\n", id, reason.size(), reason.ptr())); } -void RenX::Server::kickPlayer(const RenX::PlayerInfo *player) +void RenX::Server::forceKickPlayer(const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason) { - RenX::Server::kickPlayer(player->id); + RenX::Server::forceKickPlayer(player->id, reason); } -void RenX::Server::banPlayer(int id) +void RenX::Server::banPlayer(int id, const Jupiter::ReadableString &reason) { if (RenX::Server::rconBan) - RenX::Server::sock.send(Jupiter::StringS::Format("ckickban pid%d\n", id)); + RenX::Server::sock.send(Jupiter::StringS::Format("ckickban pid%d %.*s\n", id, reason.size(), reason.ptr())); else { RenX::PlayerInfo *player = RenX::Server::getPlayer(id); if (player != nullptr) - RenX::Server::banPlayer(player); + RenX::Server::banPlayer(player, reason); } } -void RenX::Server::banPlayer(const RenX::PlayerInfo *player, time_t length) +void RenX::Server::banPlayer(const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason, time_t length) { - if (RenX::Server::rconBan && length == 0) - RenX::Server::sock.send(Jupiter::StringS::Format("cadminkickban pid%d\n", player->id)); - else - RenX::Server::kickPlayer(player); - if (RenX::Server::localBan) - RenX::banDatabase->add(this, player, length); + RenX::banDatabase->add(this, player, reason, length); + + if (length == 0) + { + if (RenX::Server::rconBan) + RenX::Server::sock.send(Jupiter::StringS::Format("ckickban pid%d %.*s\n", player->id, reason.size(), reason.ptr())); + else + RenX::Server::forceKickPlayer(player, Jupiter::StringS::Format("You are permanently banned from the server for: %.*s", reason.size(), reason.ptr())); + } + else + RenX::Server::forceKickPlayer(player, Jupiter::StringS::Format("You are banned from the server for the next %d days, %d:%d:%d for: %.*s", length/3600, length%3600, length/60, length%60, reason.size(), reason.ptr())); } bool RenX::Server::removePlayer(int id) @@ -906,7 +927,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) auto banCheck = [this](const RenX::PlayerInfo *player) { const Jupiter::ArrayList &entries = RenX::banDatabase->getEntries(); - RenX::BanDatabase::Entry *entry; + RenX::BanDatabase::Entry *entry = nullptr; for (size_t i = 0; i != entries.size(); i++) { entry = entries.get(i); @@ -914,15 +935,25 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) { if (entry->length != 0 && entry->timestamp + entry->length < time(0)) banDatabase->deactivate(i); - else if (this->localSteamBan && entry->steamid != 0 && entry->steamid == player->steamid) - return true; - else if (this->localIPBan && entry->ip != 0 && entry->ip == player->ip32) - return true; - else if (this->localNameBan && entry->name.isEmpty() == false && entry->name.equalsi(player->name)) - return true; + else if ((this->localSteamBan && entry->steamid != 0 && entry->steamid == player->steamid) + || (this->localIPBan && entry->ip != 0 && entry->ip == player->ip32) + || (this->localNameBan && entry->name.isEmpty() == false && entry->name.equalsi(player->name))) + { + char timeStr[256]; + if (entry->length == 0) + { + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(&(entry->timestamp))); + this->forceKickPlayer(player, Jupiter::StringS::Format("You are were permanently banned from the server on %s for: %.*s", timeStr, entry->reason.size(), entry->reason.ptr())); + } + else + { + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(entry->timestamp + entry->length))); + this->forceKickPlayer(player, Jupiter::StringS::Format("You are banned from the server until %s for: %.*s", timeStr, entry->reason.size(), entry->reason.ptr())); + } + return; + } } } - return false; }; auto getPlayerOrAdd = [&](const Jupiter::ReadableString &name, int id, RenX::TeamType team, bool isBot, uint64_t steamid, const Jupiter::ReadableString &ip) { @@ -971,8 +1002,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) if (recalcUUID) { this->setUUIDIfDifferent(r, calc_uuid(r)); - if (banCheck(r)) - this->kickPlayer(r); + banCheck(r); } } return r; @@ -1868,8 +1898,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) if (player != nullptr) { player->id = buff.getToken(3, RenX::DelimC).asInt(); - if (banCheck(player)) - this->kickPlayer(player); + banCheck(player); for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnIDChange(this, player, oldID); } diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index 1635d11..812d3ec 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -244,21 +244,35 @@ namespace RenX * * @param id Player ID of the player to kick. */ - void kickPlayer(int id); + void kickPlayer(int id, const Jupiter::ReadableString &reason); /** * @brief Kicks a player from the server. * * @param player Data of the player to kick. */ - void kickPlayer(const RenX::PlayerInfo *player); + void kickPlayer(const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason); + + /** + * @brief Kicks a player from the server. + * + * @param id Player ID of the player to kick. + */ + void forceKickPlayer(int id, const Jupiter::ReadableString &reason); + + /** + * @brief Kicks a player from the server. + * + * @param player Data of the player to kick. + */ + void forceKickPlayer(const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason); /** * @brief Bans a player from the server. * * @param id Player ID of the player to ban. */ - void banPlayer(int id); + void banPlayer(int id, const Jupiter::ReadableString &reason); /** * @brief Bans a player from the server. @@ -266,7 +280,7 @@ namespace RenX * @param player Data of the player to ban. * @param length Duration of the ban (0 for permanent). */ - void banPlayer(const RenX::PlayerInfo *player, time_t length = 0); + void banPlayer(const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason, time_t length = 0); /** * @brief Removes a player's data based on their ID number. diff --git a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp index f8be8b4..e766023 100644 --- a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp +++ b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp @@ -53,7 +53,7 @@ void RenX_ExcessiveHeadshotsPlugin::RenX_OnKill(RenX::Server *server, const RenX if (flags >= RenX_ExcessiveHeadshotsPlugin::minFlags) { - server->kickPlayer(player); + server->banPlayer(player, STRING_LITERAL_AS_REFERENCE("Aimbot detected")); server->sendPubChan(IRCCOLOR "13[Aimbot]" IRCCOLOR " %.*s was banned from the server! Kills: %u - Deaths: %u - Headshots: %u", player->name.size(), player->name.ptr(), player->kills, player->deaths, player->headshots); const Jupiter::ReadableString &steamid = server->formatSteamID(player); server->sendAdmChan(IRCCOLOR "13[Aimbot]" IRCCOLOR " %.*s was banned from the server! Kills: %u - Deaths: %u - Headshots: %u - IP: " IRCBOLD "%.*s" IRCBOLD " - Steam ID: " IRCBOLD "%.*s" IRCBOLD, player->name.size(), player->name.ptr(), player->kills, player->deaths, player->headshots, player->ip.size(), player->ip.ptr(), steamid.size(), steamid.ptr()); diff --git a/RenX.ModSystem/RenX_ModSystem.cpp b/RenX.ModSystem/RenX_ModSystem.cpp index b68ecf6..40d0e80 100644 --- a/RenX.ModSystem/RenX_ModSystem.cpp +++ b/RenX.ModSystem/RenX_ModSystem.cpp @@ -197,7 +197,7 @@ int RenX_ModSystemPlugin::auth(RenX::Server *server, const RenX::PlayerInfo *pla } else if (kickLockMismatch_l) { - server->kickPlayer(player); + server->kickPlayer(player, STRING_LITERAL_AS_REFERENCE("Moderator entry lock mismatch")); return -1; } } diff --git a/RenX.Warn/RenX_Warn.cpp b/RenX.Warn/RenX_Warn.cpp index 3c96713..22d0765 100644 --- a/RenX.Warn/RenX_Warn.cpp +++ b/RenX.Warn/RenX_Warn.cpp @@ -72,11 +72,11 @@ void WarnIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &cha switch (pluginInstance.warnAction) { case -1: - server->kickPlayer(player); + server->kickPlayer(player, Jupiter::StringS::Format("Warning limit reached (%d warnings)", warns)); source->sendNotice(nick, Jupiter::StringS::Format("%.*s has been kicked from the server for exceeding the warning limit (%d warnings).", player->name.size(), player->name.ptr(), warns)); break; default: - server->banPlayer(player, pluginInstance.warnAction); + server->banPlayer(player, Jupiter::StringS::Format("Warning limit reached (%d warnings)", warns), pluginInstance.warnAction); source->sendNotice(nick, Jupiter::StringS::Format("%.*s has been banned from the server for exceeding the warning limit (%d warnings).", player->name.size(), player->name.ptr(), warns)); break; } @@ -182,11 +182,11 @@ void WarnGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, co switch (pluginInstance.warnAction) { case -1: - source->kickPlayer(target); + source->kickPlayer(target, Jupiter::StringS::Format("Warning limit reached (%d warnings)", warns)); source->sendMessage(player, Jupiter::StringS::Format("%.*s has been kicked from the server for exceeding the warning limit (%d warnings).", target->name.size(), target->name.ptr(), warns)); break; default: - source->banPlayer(target, pluginInstance.warnAction); + source->banPlayer(target, Jupiter::StringS::Format("Warning limit reached (%d warnings)", warns), pluginInstance.warnAction); source->sendMessage(player, Jupiter::StringS::Format("%.*s has been banned from the server for exceeding the warning limit (%d warnings).", target->name.size(), target->name.ptr(), warns)); break; }