diff --git a/Bot/IRC_Bot.cpp b/Bot/IRC_Bot.cpp index d919e1f..615ffe6 100644 --- a/Bot/IRC_Bot.cpp +++ b/Bot/IRC_Bot.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2013-2015 Jessica James. + * Copyright (C) 2013-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,19 +16,6 @@ * Written by Jessica James */ -/** - * Long term plan: - * Eventually, this file and its header will no longer be a part of this project. - * The features made available by this core will slowly be transferred away in pieces - * to other locations, such as the internal Jupiter library, or various plugins. - * - * There is a relatively thin line between what will go in Jupiter, and what will be - * pushed to plugins. - * Example: The "Command" and "Plugin" classes ended up in Jupiter; they're abstract concepts - * that doesn't put a specific behavior on any mechanisms. The "IRCCommand" class, however, - * alters the behavior of the IRC Client, and thus should be contained within a plugin. - */ - #include #include #include @@ -38,9 +25,11 @@ #include "IRC_Bot.h" #include "IRC_Command.h" +using namespace Jupiter::literals; + IRC_Bot::IRC_Bot(const Jupiter::ReadableString &configSection) : Client(configSection) { - IRC_Bot::commandPrefix = this->readConfigValue(STRING_LITERAL_AS_REFERENCE("Prefix")); + IRC_Bot::commandPrefix = this->readConfigValue("Prefix"_jrs); for (size_t i = 0; i != IRCMasterCommandList->size(); i++) IRC_Bot::addCommand(IRCMasterCommandList->get(i)->copy()); IRC_Bot::setCommandAccessLevels(); @@ -200,11 +189,13 @@ void IRC_Bot::OnChat(const Jupiter::ReadableString &channel, const Jupiter::Read if (cmd != nullptr) { IRCCommand::active_server = this; - int cAccess = cmd->getAccessLevel(chan); - if (cAccess >= 0 && Jupiter::IRC::Client::getAccessLevel(channel, nick) >= cAccess) - cmd->trigger(this, channel, nick, parameters); + int command_access = cmd->getAccessLevel(chan); + if (command_access < 0) + this->sendNotice(nick, "Error: Command disabled."_jrs); + else if (Jupiter::IRC::Client::getAccessLevel(channel, nick) < command_access) + this->sendNotice(nick, "Access Denied."_jrs); else - this->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Access Denied.")); + cmd->trigger(this, channel, nick, parameters); IRCCommand::active_server = IRCCommand::selected_server; } } diff --git a/CoreCommands/CoreCommands.cpp b/CoreCommands/CoreCommands.cpp index 72a1b12..b5af7c5 100644 --- a/CoreCommands/CoreCommands.cpp +++ b/CoreCommands/CoreCommands.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014-2015 Jessica James. + * Copyright (C) 2014-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -68,7 +68,7 @@ CONSOLE_COMMAND_INIT(HelpConsoleCommand) void HelpIRCCommand::create() { - this->addTrigger(STRING_LITERAL_AS_REFERENCE("help")); + this->addTrigger("help"_jrs); } void HelpIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) @@ -90,18 +90,23 @@ void HelpIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &cha source->sendNotice(nick, Jupiter::StringS::Format("Access level %d commands: %.*s", i, triggers.size(), triggers.ptr())); } } - source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("For command-specific help, use: help ")); + source->sendNotice(nick, "For command-specific help, use: help "_jrs); } else { IRCCommand *cmd = source->getCommand(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE)); if (cmd) { - if (access >= cmd->getAccessLevel(chan)) + int command_access = cmd->getAccessLevel(chan); + + if (command_access < 0) + source->sendNotice(nick, "Error: Command disabled."_jrs); + else if (access < command_access) + source->sendNotice(nick, "Access Denied."_jrs); + else source->sendNotice(nick, cmd->getHelp(Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE))); - else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Access Denied.")); } - else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Command not found.")); + else source->sendNotice(nick, "Error: Command not found."_jrs); } } } diff --git a/Jupiter b/Jupiter index 5b83899..5eca27a 160000 --- a/Jupiter +++ b/Jupiter @@ -1 +1 @@ -Subproject commit 5b83899a03642d18deb6a85dabfb1afd8d76422e +Subproject commit 5eca27adc30fef1d51156d94de85a34f4e5793d0 diff --git a/Release/Bot.lib b/Release/Bot.lib index 9b08312..8ecbe06 100644 Binary files a/Release/Bot.lib and b/Release/Bot.lib differ diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index bb9c23f..1d8d80e 100644 Binary files a/Release/Plugins/RenX.Core.lib and b/Release/Plugins/RenX.Core.lib differ diff --git a/RenX.Commands/RenX_Commands.cpp b/RenX.Commands/RenX_Commands.cpp index 563c5ea..bce56cf 100644 --- a/RenX.Commands/RenX_Commands.cpp +++ b/RenX.Commands/RenX_Commands.cpp @@ -1164,8 +1164,7 @@ void BanSearchIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString 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))); + strftime(timeStr, sizeof(timeStr), "%b %d %Y, %H:%M:%S", localtime(&(entry->timestamp))); if ((entry->flags & 0x7FFF) == 0) types = " NULL;"_jrs; @@ -1193,7 +1192,7 @@ void BanSearchIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString out.format("ID: %lu (%sactive); Date: %s; IP: %.*s/%u; Steam: %llu; Types:%.*s Name: %.*s; Banner: %.*s", i, entry->is_active() ? "" : "in", timeStr, ip_str.size(), ip_str.ptr(), entry->prefix_length, entry->steamid, types.size(), types.ptr(), - entry->name.size(), entry->name.ptr(), banner.size(), banner.ptr()); + entry->name.size(), entry->name.ptr(), entry->banner.size(), entry->banner.ptr()); if (entry->rdns.isNotEmpty()) { @@ -1639,8 +1638,10 @@ void DisarmIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &c player = server->getPlayerByPartName(parameters); if (player != nullptr) { - server->disarm(player); - source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("All deployables (c4, beacons, etc) belonging to ") + RenX::getFormattedPlayerName(player) + STRING_LITERAL_AS_REFERENCE(IRCCOLOR " have been disarmed.")); + if (server->disarm(player)) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("All deployables (c4, beacons, etc) belonging to ") + RenX::getFormattedPlayerName(player) + STRING_LITERAL_AS_REFERENCE(IRCCOLOR " have been disarmed.")); + else + source->sendMessage(channel, "Error: Server does not support disarms."_jrs); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); @@ -1688,8 +1689,10 @@ void DisarmC4IRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString player = server->getPlayerByPartName(parameters); if (player != nullptr) { - server->disarmC4(player); - source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("All C4 belonging to ") + RenX::getFormattedPlayerName(player) + STRING_LITERAL_AS_REFERENCE(IRCCOLOR " have been disarmed.")); + if (server->disarmC4(player)) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("All C4 belonging to ") + RenX::getFormattedPlayerName(player) + STRING_LITERAL_AS_REFERENCE(IRCCOLOR " have been disarmed.")); + else + source->sendMessage(channel, "Error: Server does not support disarms."_jrs); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); @@ -1739,8 +1742,10 @@ void DisarmBeaconIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableStr player = server->getPlayerByPartName(parameters); if (player != nullptr) { - server->disarmBeacon(player); - source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("All beacons belonging to ") + RenX::getFormattedPlayerName(player) + STRING_LITERAL_AS_REFERENCE(IRCCOLOR " have been disarmed.")); + if (server->disarmBeacon(player)) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("All beacons belonging to ") + RenX::getFormattedPlayerName(player) + STRING_LITERAL_AS_REFERENCE(IRCCOLOR " have been disarmed.")); + else + source->sendMessage(channel, "Error: Server does not support disarms."_jrs); } else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); @@ -1799,7 +1804,7 @@ void MineBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & 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 ")); + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: mineban ")); } const Jupiter::ReadableString &MineBanIRCCommand::getHelp(const Jupiter::ReadableString &) @@ -1887,8 +1892,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::ReferenceString name = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); + Jupiter::ReferenceString reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE) : "No reason"_jrs; Jupiter::String banner(nick.size() + 4); banner += nick; banner += "@IRC"; @@ -1965,7 +1970,10 @@ void KickBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString & if (kicks == 0) source->sendMessage(channel, "Player \""_jrs + name + "\" not found."_jrs); else + { source->sendMessage(channel, Jupiter::StringS::Format("%u players kicked.", kicks)); + RenX::getCore()->banCheck(); + } } else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); } @@ -2125,6 +2133,7 @@ void AddBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &c flags |= RenX::BanDatabase::Entry::FLAG_USE_RDNS; RenX::banDatabase->add(name, ip, prefix_length, steamid, rdns, banner, reason, duration); + RenX::getCore()->banCheck(); } } } @@ -2397,21 +2406,18 @@ void RefundIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &c 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 = server->getPlayerByPartName(playerName); + if (player != nullptr) { - player = node->data; - if (player->name.findi(playerName) != Jupiter::INVALID_INDEX) + if (server->giveCredits(player, credits)) { - 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); + 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); } } } @@ -2784,11 +2790,10 @@ void DisarmGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (target->access >= player->access) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not disarm higher level moderators.")); + else if (source->disarm(target) == false) + source->sendMessage(player, "Error: Server does not support disarms."_jrs); else - { - source->disarm(target); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed.")); - } } else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarm ")); @@ -2819,11 +2824,10 @@ void DisarmC4GameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (target->access >= player->access) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not disarm higher level moderators.")); + else if (source->disarmC4(target) == false) + source->sendMessage(player, "Error: Server does not support disarms."_jrs); else - { - source->disarmC4(target); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed.")); - } } else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarmc4 ")); @@ -2856,11 +2860,10 @@ void DisarmBeaconGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *pl source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); else if (target->access >= player->access) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not disarm higher level moderators.")); + else if (source->disarmBeacon(target) == false) + source->sendMessage(player, "Error: Server does not support disarms."_jrs); else - { - source->disarmBeacon(target); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed.")); - } } else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarmb ")); @@ -3019,6 +3022,7 @@ void KickBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, { source->banPlayer(target, player->name, reason); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been banned and kicked from the game.")); + RenX::getCore()->banCheck(); } } else diff --git a/RenX.Core/RenX_BanDatabase.cpp b/RenX.Core/RenX_BanDatabase.cpp index 3c71f20..414f12a 100644 --- a/RenX.Core/RenX_BanDatabase.cpp +++ b/RenX.Core/RenX_BanDatabase.cpp @@ -44,7 +44,7 @@ void RenX::BanDatabase::process_data(Jupiter::DataBuffer &buffer, FILE *file, fp entry->length = buffer.pop(); entry->steamid = buffer.pop(); entry->ip = buffer.pop(); - entry->prefix_length = buffer.pop(); + entry->prefix_length = buffer.pop(); entry->rdns = buffer.pop(); entry->name = buffer.pop(); entry->banner = buffer.pop(); @@ -53,6 +53,8 @@ void RenX::BanDatabase::process_data(Jupiter::DataBuffer &buffer, FILE *file, fp // Read varData from buffer to entry for (size_t varData_entries = buffer.pop(); varData_entries != 0; --varData_entries) entry->varData.set(buffer.pop(), buffer.pop()); + + RenX::BanDatabase::entries.add(entry); } void RenX::BanDatabase::process_header(FILE *file) @@ -77,9 +79,13 @@ void RenX::BanDatabase::process_file_finish(FILE *file) { puts("Warning: Unsupported ban database file version. The database will be removed and rewritten."); this->create_header(file); + fgetpos(file, std::addressof(RenX::BanDatabase::eof)); RenX::BanDatabase::read_version = RenX::BanDatabase::write_version; } + return; } + + fgetpos(file, std::addressof(RenX::BanDatabase::eof)); } void RenX::BanDatabase::upgrade_database() @@ -97,7 +103,8 @@ void RenX::BanDatabase::upgrade_database() void RenX::BanDatabase::write(RenX::BanDatabase::Entry *entry) { - FILE *file = fopen(filename.c_str(), "ab"); + FILE *file = fopen(filename.c_str(), "r+b"); + fsetpos(file, std::addressof(RenX::BanDatabase::eof)); if (file != nullptr) { RenX::BanDatabase::write(entry, file); @@ -136,6 +143,7 @@ void RenX::BanDatabase::write(RenX::BanDatabase::Entry *entry, FILE *file) // push buffer to file buffer.push_to(file); + fgetpos(file, std::addressof(RenX::BanDatabase::eof)); } void RenX::BanDatabase::add(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &banner, const Jupiter::ReadableString &reason, time_t length, uint16_t flags) @@ -193,7 +201,8 @@ bool RenX::BanDatabase::deactivate(size_t index) if (file != nullptr) { fsetpos(file, &entry->pos); - fputc(entry->flags, file); + fseek(file, sizeof(size_t), SEEK_CUR); + fwrite(std::addressof(entry->flags), sizeof(entry->flags), 1, file); fclose(file); } return true; diff --git a/RenX.Core/RenX_BanDatabase.h b/RenX.Core/RenX_BanDatabase.h index 744262e..048bc33 100644 --- a/RenX.Core/RenX_BanDatabase.h +++ b/RenX.Core/RenX_BanDatabase.h @@ -176,7 +176,7 @@ namespace RenX * @param entry Entry to write to the database. * @param file FILE stream to write to. */ - static void write(Entry *entry, FILE *file); + void write(Entry *entry, FILE *file); /** * @brief Deactivates a ban entry. @@ -214,6 +214,7 @@ namespace RenX /** Database version */ const uint8_t write_version = 3U; uint8_t read_version = write_version; + fpos_t eof; Jupiter::CStringS filename; Jupiter::ArrayList entries; diff --git a/RenX.Core/RenX_Core.cpp b/RenX.Core/RenX_Core.cpp index 82f9596..6ab3069 100644 --- a/RenX.Core/RenX_Core.cpp +++ b/RenX.Core/RenX_Core.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014-2015 Jessica James. + * Copyright (C) 2014-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -94,6 +94,11 @@ RenX::Server *RenX::Core::getServer(unsigned int index) return RenX::Core::servers.get(index); } +Jupiter::ArrayList RenX::Core::getServers() +{ + return RenX::Core::servers; +} + Jupiter::ArrayList RenX::Core::getServers(int type) { Jupiter::ArrayList r; @@ -150,14 +155,17 @@ Jupiter::INIFile &RenX::Core::getCommandsFile() int RenX::Core::addCommand(RenX::GameCommand *command) { - for (size_t i = 0; i != RenX::Core::servers.size(); i++) - { - RenX::Server *server = RenX::Core::servers.get(i); - server->addCommand(command->copy()); - } + for (size_t i = 0; i != RenX::Core::servers.size(); ++i) + RenX::Core::servers.get(i)->addCommand(command->copy()); return RenX::Core::servers.size(); } +void RenX::Core::banCheck() +{ + for (size_t index = 0; index != RenX::Core::servers.size(); ++index) + RenX::Core::servers.get(index)->banCheck(); +} + int RenX::Core::think() { size_t index = 0; diff --git a/RenX.Core/RenX_Core.h b/RenX.Core/RenX_Core.h index 1c952b9..90199c7 100644 --- a/RenX.Core/RenX_Core.h +++ b/RenX.Core/RenX_Core.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014-2015 Jessica James. + * Copyright (C) 2014-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -98,6 +98,14 @@ namespace RenX */ RenX::Server *getServer(unsigned int index); + /** + * @brief Fetches the list of servers + * Note: This copies the array of pointers, not the objects themselves. + * + * @return Copy of the list of servers. + */ + Jupiter::ArrayList getServers(); + /** * @brief Constructs a list of servers based on their type. * @@ -165,6 +173,11 @@ namespace RenX */ int addCommand(GameCommand *command); + /** + * @brief Performs a ban check on every player on each server, and kicks as appropriate. + */ + void banCheck(); + /** * @brief Initializes the Core. */ diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index 19b93e8..ae074e7 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -169,6 +169,11 @@ bool RenX::Server::isSeamless() const return RenX::Server::seamless; } +bool RenX::Server::isCompetitive() const +{ + return RenX::Server::competitive; +} + bool RenX::Server::isPublicLogChanType(int type) const { return RenX::Server::logChanType == type; @@ -295,7 +300,8 @@ RenX::PlayerInfo *RenX::Server::getPlayerByName(const Jupiter::ReadableString &n idToken.shiftRight(6); else if (name.matchi("pid?*")) idToken.shiftRight(3); - else return nullptr; + else + return nullptr; int id = idToken.asInt(10); for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) @@ -379,6 +385,164 @@ void RenX::Server::forceKickPlayer(const RenX::PlayerInfo *player, const Jupiter RenX::Server::forceKickPlayer(player->id, reason); } +void RenX::Server::banCheck() +{ + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) + this->banCheck(node->data); +} + +void RenX::Server::banCheck(RenX::PlayerInfo *player) +{ + const Jupiter::ArrayList &entries = RenX::banDatabase->getEntries(); + RenX::BanDatabase::Entry *entry = nullptr; + uint32_t netmask; + + RenX::BanDatabase::Entry *last_to_expire[7]; + for (size_t index = 0; index != sizeof(last_to_expire); ++index) + last_to_expire[index] = nullptr; + + auto handle_type = [&entry, &last_to_expire](size_t index) + { + if (last_to_expire[index] == nullptr) + last_to_expire[index] = entry; + else if (last_to_expire[index]->length == 0) + { + // favor older bans if they're also permanent + if (entry->length == 0 && entry->timestamp < last_to_expire[index]->timestamp) + last_to_expire[index] = entry; + } + else if (entry->length == 0 || entry->timestamp + entry->length > last_to_expire[index]->timestamp + last_to_expire[index]->length) + last_to_expire[index] = entry; + }; + + for (size_t i = 0; i != entries.size(); i++) + { + entry = entries.get(i); + if (entry->is_active()) + { + if (entry->length != 0 && entry->timestamp + entry->length < time(0)) + banDatabase->deactivate(i); + else + { + if (entry->prefix_length >= 32) + netmask = 0xFFFFFFFF; + else + netmask = Jupiter_prefix_length_to_netmask(entry->prefix_length); + + printf("%d vs %d" ENDL, (entry->ip & netmask), (player->ip32 & netmask)); + if ((this->localSteamBan && entry->steamid != 0 && entry->steamid == player->steamid) + || (this->localIPBan && entry->ip != 0 && (entry->ip & netmask) == (player->ip32 & netmask)) + || (this->localRDNSBan && entry->rdns.isNotEmpty() && entry->is_rdns_ban() && player->rdns.match(entry->rdns)) + || (this->localNameBan && entry->name.isNotEmpty() && entry->name.equalsi(player->name))) + { + player->ban_flags |= entry->flags; + if (entry->is_type_game()) + handle_type(0); + if (entry->is_type_chat()) + handle_type(1); + if (entry->is_type_bot()) + handle_type(2); + if (entry->is_type_vote()) + handle_type(3); + if (entry->is_type_mine()) + handle_type(4); + if (entry->is_type_ladder()) + handle_type(5); + if (entry->is_type_alert()) + handle_type(6); + } + } + } + } + + char timeStr[256]; + if (last_to_expire[0] != nullptr) // Game ban + { + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[0]->timestamp + last_to_expire[0]->length))); + if (last_to_expire[0]->length == 0) + this->forceKickPlayer(player, Jupiter::StringS::Format("You were permanently banned from the server on %s for: %.*s", timeStr, last_to_expire[0]->reason.size(), last_to_expire[0]->reason.ptr())); + else + this->forceKickPlayer(player, Jupiter::StringS::Format("You are banned from the server until %s for: %.*s", timeStr, last_to_expire[0]->reason.size(), last_to_expire[0]->reason.ptr())); + + player->ban_flags |= RenX::BanDatabase::Entry::FLAG_TYPE_BOT; // implies FLAG_TYPE_BOT + } + else + { + if (last_to_expire[1] != nullptr) // Chat ban + { + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[1]->timestamp + last_to_expire[1]->length))); + this->mute(player); + if (last_to_expire[1]->length == 0) + this->sendMessage(player, Jupiter::StringS::Format("You were permanently muted on this server on %s for: %.*s", timeStr, last_to_expire[1]->reason.size(), last_to_expire[1]->reason.ptr())); + else + this->sendMessage(player, Jupiter::StringS::Format("You are muted on this server until %s for: %.*s", timeStr, last_to_expire[1]->reason.size(), last_to_expire[1]->reason.ptr())); + + player->ban_flags |= RenX::BanDatabase::Entry::FLAG_TYPE_BOT; // implies FLAG_TYPE_BOT + } + else if (last_to_expire[2] != nullptr) // Bot ban + { + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[2]->timestamp + last_to_expire[2]->length))); + if (last_to_expire[2]->length == 0) + this->sendMessage(player, Jupiter::StringS::Format("You were permanently bot-muted on this server on %s for: %.*s", timeStr, last_to_expire[2]->reason.size(), last_to_expire[2]->reason.ptr())); + else + this->sendMessage(player, Jupiter::StringS::Format("You are bot-muted on this server until %s for: %.*s", timeStr, last_to_expire[2]->reason.size(), last_to_expire[2]->reason.ptr())); + } + if (last_to_expire[3] != nullptr) // Vote ban + { + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[3]->timestamp + last_to_expire[3]->length))); + if (last_to_expire[3]->length == 0) + this->sendMessage(player, Jupiter::StringS::Format("You were permanently vote-muted on this server on %s for: %.*s", timeStr, last_to_expire[3]->reason.size(), last_to_expire[3]->reason.ptr())); + else + this->sendMessage(player, Jupiter::StringS::Format("You are vote-muted on this server until %s for: %.*s", timeStr, last_to_expire[3]->reason.size(), last_to_expire[3]->reason.ptr())); + } + if (last_to_expire[4] != nullptr) // Mine ban + { + this->mineBan(player); + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[4]->timestamp + last_to_expire[4]->length))); + if (last_to_expire[4]->length == 0) + this->sendMessage(player, Jupiter::StringS::Format("You were permanently mine-banned on this server on %s for: %.*s", timeStr, last_to_expire[4]->reason.size(), last_to_expire[4]->reason.ptr())); + else + this->sendMessage(player, Jupiter::StringS::Format("You are mine-banned on this server until %s for: %.*s", timeStr, last_to_expire[4]->reason.size(), last_to_expire[4]->reason.ptr())); + } + if (last_to_expire[5] != nullptr) // Ladder ban + { + strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[5]->timestamp + last_to_expire[5]->length))); + if (last_to_expire[5]->length == 0) + this->sendMessage(player, Jupiter::StringS::Format("You were permanently ladder-banned on this server on %s for: %.*s", timeStr, last_to_expire[5]->reason.size(), last_to_expire[5]->reason.ptr())); + else + this->sendMessage(player, Jupiter::StringS::Format("You are ladder-banned on this server until %s for: %.*s", timeStr, last_to_expire[5]->reason.size(), last_to_expire[5]->reason.ptr())); + } + if (last_to_expire[6] != nullptr) // Alert + { + unsigned int serverCount = serverManager->size(); + IRC_Bot *server; + Jupiter::IRC::Client::Channel *channel; + unsigned int channelCount; + Jupiter::String &fmtName = RenX::getFormattedPlayerName(player); + Jupiter::StringL msg = Jupiter::StringL::Format(IRCCOLOR "04[Alert] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR " is marked for monitoring by %.*s for: \"%.*s\". Please keep an eye on them in ", fmtName.size(), fmtName.ptr(), last_to_expire[6]->banner.size(), last_to_expire[6]->banner.ptr(), last_to_expire[6]->reason.size(), last_to_expire[6]->reason.ptr()); + Jupiter::StringS msg2 = Jupiter::StringS::Format(IRCCOLOR "04[Alert] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR " is marked for monitoring by %.*s for: \"%.*s\"." IRCCOLOR, fmtName.size(), fmtName.ptr(), last_to_expire[6]->banner.size(), last_to_expire[6]->banner.ptr(), last_to_expire[6]->reason.size(), last_to_expire[6]->reason.ptr()); + for (unsigned int a = 0; a < serverCount; a++) + { + server = serverManager->getServer(a); + channelCount = server->getChannelCount(); + for (unsigned int b = 0; b < channelCount; b++) + { + channel = server->getChannel(b); + if (this->isAdminLogChanType(channel->getType())) + { + 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); + msg -= channel->getName().size(); + } + } + } + } + } +}; + void RenX::Server::banPlayer(int id, const Jupiter::ReadableString &banner, const Jupiter::ReadableString &reason) { if (RenX::Server::rconBan) @@ -406,9 +570,9 @@ void RenX::Server::banPlayer(const RenX::PlayerInfo *player, const Jupiter::Read RenX::Server::forceKickPlayer(player, Jupiter::StringS::Format("You are permanently banned from the server for: %.*s", reason.size(), reason.ptr())); } else if (banner.isNotEmpty()) - RenX::Server::forceKickPlayer(player, Jupiter::StringS::Format("You are banned from the server by %.*s for the next %d days, %d:%d:%d for: %.*s", banner.size(), banner.ptr(), length / 86400, length % 3600, (length % 3600) / 60, length % 60, reason.size(), reason.ptr())); + RenX::Server::forceKickPlayer(player, Jupiter::StringS::Format("You are banned from the server by %.*s for the next %lld days, %.2d:%.2d:%.2d for: %.*s", banner.size(), banner.ptr(), static_cast(length / 86400), static_cast(length % 3600), static_cast((length % 3600) / 60), static_cast(length % 60), 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/86400, length%3600, (length%3600)/60, length%60, reason.size(), reason.ptr())); + RenX::Server::forceKickPlayer(player, Jupiter::StringS::Format("You are banned from the server for the next %lld days, %.2d:%.2d:%.2d for: %.*s", static_cast(length/86400), static_cast(length%3600), static_cast((length%3600)/60), static_cast(length%60), reason.size(), reason.ptr())); } bool RenX::Server::removePlayer(int id) @@ -521,7 +685,7 @@ bool RenX::Server::unmute(const RenX::PlayerInfo *player) bool RenX::Server::giveCredits(int id, double credits) { - return RenX::Server::send(Jupiter::StringS::Format("givecredits pid%d %f", id, credits)) > 0; + return RenX::Server::competitive == false && RenX::Server::send(Jupiter::StringS::Format("givecredits pid%d %f", id, credits)) > 0; } bool RenX::Server::giveCredits(RenX::PlayerInfo *player, double credits) @@ -531,7 +695,7 @@ bool RenX::Server::giveCredits(RenX::PlayerInfo *player, double credits) bool RenX::Server::kill(int id) { - return RenX::Server::send(Jupiter::StringS::Format("kill pid%d", id)) > 0; + return RenX::Server::competitive == false && RenX::Server::send(Jupiter::StringS::Format("kill pid%d", id)) > 0; } bool RenX::Server::kill(RenX::PlayerInfo *player) @@ -541,7 +705,7 @@ bool RenX::Server::kill(RenX::PlayerInfo *player) bool RenX::Server::disarm(int id) { - return RenX::Server::send(Jupiter::StringS::Format("disarm pid%d", id)) > 0; + return RenX::Server::competitive == false && RenX::Server::send(Jupiter::StringS::Format("disarm pid%d", id)) > 0; } bool RenX::Server::disarm(RenX::PlayerInfo *player) @@ -551,7 +715,7 @@ bool RenX::Server::disarm(RenX::PlayerInfo *player) bool RenX::Server::disarmC4(int id) { - return RenX::Server::send(Jupiter::StringS::Format("disarmc4 pid%d", id)) > 0; + return RenX::Server::competitive == false && RenX::Server::send(Jupiter::StringS::Format("disarmc4 pid%d", id)) > 0; } bool RenX::Server::disarmC4(RenX::PlayerInfo *player) @@ -561,7 +725,7 @@ bool RenX::Server::disarmC4(RenX::PlayerInfo *player) bool RenX::Server::disarmBeacon(int id) { - return RenX::Server::send(Jupiter::StringS::Format("disarmb pid%d", id)) > 0; + return RenX::Server::competitive == false && RenX::Server::send(Jupiter::StringS::Format("disarmb pid%d", id)) > 0; } bool RenX::Server::disarmBeacon(RenX::PlayerInfo *player) @@ -1033,156 +1197,6 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) isBot = false; id = idToken.asInt(10); }; - auto banCheck = [this](RenX::PlayerInfo *player) - { - const Jupiter::ArrayList &entries = RenX::banDatabase->getEntries(); - RenX::BanDatabase::Entry *entry = nullptr; - uint32_t netmask; - - RenX::BanDatabase::Entry *last_to_expire[7]; - for (size_t index = 0; index != sizeof(last_to_expire); ++index) - last_to_expire[index] = nullptr; - - auto handle_type = [entry](RenX::BanDatabase::Entry *&last_to_expire) - { - if (last_to_expire == nullptr) - last_to_expire = entry; - else if (last_to_expire->length == 0) - { - // favor older bans if they're also permanent - if (entry->length == 0 && entry->timestamp < last_to_expire->timestamp) - last_to_expire = entry; - } - else if (entry->length == 0 || entry->timestamp + entry->length > last_to_expire->timestamp + last_to_expire->length) - last_to_expire = entry; - }; - - for (size_t i = 0; i != entries.size(); i++) - { - entry = entries.get(i); - if (entry->is_active()) - { - if (entry->length != 0 && entry->timestamp + entry->length < time(0)) - banDatabase->deactivate(i); - else - { - if (entry->prefix_length >= 32) - netmask = 0xFFFFFFFF; - else - netmask = Jupiter_prefix_length_to_netmask(entry->prefix_length); - - if ((this->localSteamBan && entry->steamid != 0 && entry->steamid == player->steamid) - || (this->localIPBan && entry->ip != 0 && (entry->ip & netmask) == (player->ip32 & netmask)) - || (this->localRDNSBan && entry->rdns.isNotEmpty() && entry->is_rdns_ban() && player->rdns.match(entry->rdns)) - || (this->localNameBan && entry->name.isNotEmpty() && entry->name.equalsi(player->name))) - { - player->ban_flags |= entry->flags; - if (entry->is_type_game()) - handle_type(last_to_expire[0]); - if (entry->is_type_chat()) - handle_type(last_to_expire[1]); - if (entry->is_type_bot()) - handle_type(last_to_expire[2]); - if (entry->is_type_vote()) - handle_type(last_to_expire[3]); - if (entry->is_type_mine()) - handle_type(last_to_expire[4]); - if (entry->is_type_ladder()) - handle_type(last_to_expire[5]); - if (entry->is_type_alert()) - handle_type(last_to_expire[6]); - } - } - } - } - - char timeStr[256]; - if (last_to_expire[0] != nullptr) // Game ban - { - strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[0]->timestamp + last_to_expire[0]->length))); - if (last_to_expire[0]->length == 0) - this->forceKickPlayer(player, Jupiter::StringS::Format("You were permanently banned from the server on %s for: %.*s", timeStr, last_to_expire[0]->reason.size(), last_to_expire[0]->reason.ptr())); - else - this->forceKickPlayer(player, Jupiter::StringS::Format("You are banned from the server until %s for: %.*s", timeStr, last_to_expire[0]->reason.size(), last_to_expire[0]->reason.ptr())); - - player->ban_flags |= RenX::BanDatabase::Entry::FLAG_TYPE_BOT; // implies FLAG_TYPE_BOT - } - else - { - if (last_to_expire[1] != nullptr) // Chat ban - { - strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[1]->timestamp + last_to_expire[1]->length))); - this->mute(player); - if (last_to_expire[1]->length == 0) - this->sendMessage(player, Jupiter::StringS::Format("You were permanently muted on this server on %s for: %.*s", timeStr, last_to_expire[1]->reason.size(), last_to_expire[1]->reason.ptr())); - else - this->sendMessage(player, Jupiter::StringS::Format("You are muted on this server until %s for: %.*s", timeStr, last_to_expire[1]->reason.size(), last_to_expire[1]->reason.ptr())); - - player->ban_flags |= RenX::BanDatabase::Entry::FLAG_TYPE_BOT; // implies FLAG_TYPE_BOT - } - else if (last_to_expire[2] != nullptr) // Bot ban - { - strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[2]->timestamp + last_to_expire[2]->length))); - if (last_to_expire[2]->length == 0) - this->sendMessage(player, Jupiter::StringS::Format("You were permanently bot-muted on this server on %s for: %.*s", timeStr, last_to_expire[2]->reason.size(), last_to_expire[2]->reason.ptr())); - else - this->sendMessage(player, Jupiter::StringS::Format("You are bot-muted on this server until %s for: %.*s", timeStr, last_to_expire[2]->reason.size(), last_to_expire[2]->reason.ptr())); - } - if (last_to_expire[3] != nullptr) // Vote ban - { - strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[3]->timestamp + last_to_expire[3]->length))); - if (last_to_expire[3]->length == 0) - this->sendMessage(player, Jupiter::StringS::Format("You were permanently vote-muted on this server on %s for: %.*s", timeStr, last_to_expire[3]->reason.size(), last_to_expire[3]->reason.ptr())); - else - this->sendMessage(player, Jupiter::StringS::Format("You are vote-muted on this server until %s for: %.*s", timeStr, last_to_expire[3]->reason.size(), last_to_expire[3]->reason.ptr())); - } - if (last_to_expire[4] != nullptr) // Mine ban - { - this->mineBan(player); - strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[4]->timestamp + last_to_expire[4]->length))); - if (last_to_expire[4]->length == 0) - this->sendMessage(player, Jupiter::StringS::Format("You were permanently mine-banned on this server on %s for: %.*s", timeStr, last_to_expire[4]->reason.size(), last_to_expire[4]->reason.ptr())); - else - this->sendMessage(player, Jupiter::StringS::Format("You are mine-banned on this server until %s for: %.*s", timeStr, last_to_expire[4]->reason.size(), last_to_expire[4]->reason.ptr())); - } - if (last_to_expire[5] != nullptr) // Ladder ban - { - strftime(timeStr, sizeof(timeStr), "%b %d %Y at %H:%M:%S", localtime(std::addressof(last_to_expire[5]->timestamp + last_to_expire[5]->length))); - if (last_to_expire[5]->length == 0) - this->sendMessage(player, Jupiter::StringS::Format("You were permanently ladder-banned on this server on %s for: %.*s", timeStr, last_to_expire[5]->reason.size(), last_to_expire[5]->reason.ptr())); - else - this->sendMessage(player, Jupiter::StringS::Format("You are ladder-banned on this server until %s for: %.*s", timeStr, last_to_expire[5]->reason.size(), last_to_expire[5]->reason.ptr())); - } - if (last_to_expire[6] != nullptr) // Alert - { - unsigned int serverCount = serverManager->size(); - IRC_Bot *server; - Jupiter::IRC::Client::Channel *channel; - unsigned int channelCount; - Jupiter::String &fmtName = RenX::getFormattedPlayerName(player); - Jupiter::StringL msg = Jupiter::StringL::Format(IRCCOLOR "04[Alert] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR " is marked for monitoring by %.*s for: \"%.*s\". Please keep an eye on them in ", fmtName.size(), fmtName.ptr(), last_to_expire[6]->banner.size(), last_to_expire[6]->banner.ptr(), last_to_expire[6]->reason.size(), last_to_expire[6]->reason.ptr()); - Jupiter::StringS msg2 = Jupiter::StringS::Format(IRCCOLOR "04[Alert] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR " is marked for monitoring by %.*s for: \"%.*s\"." IRCCOLOR, fmtName.size(), fmtName.ptr(), last_to_expire[6]->banner.size(), last_to_expire[6]->banner.ptr(), last_to_expire[6]->reason.size(), last_to_expire[6]->reason.ptr()); - for (unsigned int a = 0; a < serverCount; a++) - { - server = serverManager->getServer(a); - channelCount = server->getChannelCount(); - for (unsigned int b = 0; b < channelCount; b++) - { - channel = server->getChannel(b); - if (this->isAdminLogChanType(channel->getType())) - { - 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); - msg -= channel->getName().size(); - } - } - } - } - } - }; auto getPlayerOrAdd = [&](const Jupiter::ReadableString &name, int id, RenX::TeamType team, bool isBot, uint64_t steamid, const Jupiter::ReadableString &ip) { RenX::PlayerInfo *r = this->getPlayer(id); @@ -1204,7 +1218,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) this->players.add(r); r->uuid = calc_uuid(r); - banCheck(r); + this->banCheck(r); for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnPlayerCreate(this, r); @@ -1233,7 +1247,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) if (recalcUUID) { this->setUUIDIfDifferent(r, calc_uuid(r)); - banCheck(r); + this->banCheck(r); } } return r; @@ -1598,18 +1612,23 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) } else if (this->lastCommand.equalsi("gameinfo"_jrs)) { - // "PlayerLimit" | PlayerLimit | "VehicleLimit" | VehicleLimit | "MineLimit" | MineLimit | "TimeLimit" | TimeLimit | "bPassworded" | bPassworded | "bSteamRequired" | bSteamRequired | "bPrivateMessageTeamOnly" | bPrivateMessageTeamOnly | "bAllowPrivateMessaging" | bAllowPrivateMessaging | "bAutoBalanceTeams" | bAutoBalanceTeams | "bSpawnCrates" | bSpawnCrates | "CrateRespawnAfterPickup" | CrateRespawnAfterPickup - this->playerLimit = tokens.getToken(1).asInt(); - this->vehicleLimit = tokens.getToken(3).asInt(); - this->mineLimit = tokens.getToken(5).asInt(); - this->timeLimit = tokens.getToken(7).asInt(); - this->passworded = tokens.getToken(9).asBool(); - this->steamRequired = tokens.getToken(11).asBool(); - this->privateMessageTeamOnly = tokens.getToken(13).asBool(); - this->allowPrivateMessaging = tokens.getToken(15).asBool(); - this->autoBalanceTeams = tokens.getToken(17).asBool(); - this->spawnCrates = tokens.getToken(19).asBool(); - this->crateRespawnAfterPickup = tokens.getToken(21).asDouble(); + if (this->lastCommandParams.isEmpty()) + { + // "PlayerLimit" | PlayerLimit | "VehicleLimit" | VehicleLimit | "MineLimit" | MineLimit | "TimeLimit" | TimeLimit | "bPassworded" | bPassworded | "bSteamRequired" | bSteamRequired | "bPrivateMessageTeamOnly" | bPrivateMessageTeamOnly | "bAllowPrivateMessaging" | bAllowPrivateMessaging | "bAutoBalanceTeams" | bAutoBalanceTeams | "bSpawnCrates" | bSpawnCrates | "CrateRespawnAfterPickup" | CrateRespawnAfterPickup | bIsCompetitive | "bIsCompetitive" + this->playerLimit = tokens.getToken(1).asInt(); + this->vehicleLimit = tokens.getToken(3).asInt(); + this->mineLimit = tokens.getToken(5).asInt(); + this->timeLimit = tokens.getToken(7).asInt(); + this->passworded = tokens.getToken(9).asBool(); + this->steamRequired = tokens.getToken(11).asBool(); + this->privateMessageTeamOnly = tokens.getToken(13).asBool(); + this->allowPrivateMessaging = tokens.getToken(15).asBool(); + this->autoBalanceTeams = tokens.getToken(17).asBool(); + this->spawnCrates = tokens.getToken(19).asBool(); + this->crateRespawnAfterPickup = tokens.getToken(21).asDouble(); + } + else if (this->lastCommandParams.equalsi("bIsCompetitive")) + this->competitive = tokens.getToken(0).asBool(); } else if (this->lastCommand.equalsi("mutatorlist"_jrs)) { @@ -2233,7 +2252,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) if (player != nullptr) { player->id = tokens.getToken(3).asInt(); - banCheck(player); + this->banCheck(player); for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnIDChange(this, player, oldID); } @@ -2638,6 +2657,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) RenX::Server::sock.send("s\n"_jrs); RenX::Server::send("serverinfo"_jrs); RenX::Server::send("gameinfo"_jrs); + RenX::Server::send("gameinfo bIsCompetitive"_jrs); RenX::Server::send("mutatorlist"_jrs); RenX::Server::send("rotation"_jrs); RenX::Server::fetchClientList(); diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index f96ebb2..4fa2ebc 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -138,6 +138,13 @@ namespace RenX */ bool isSeamless() const; + /** + * @brief Checks if the server is marked as competitive. + * + * @return True if the server is a competitive server, false otherwise. + */ + bool isCompetitive() const; + /** * @brief Checks if a channel type is a public channel type. * @@ -334,6 +341,19 @@ namespace RenX */ void forceKickPlayer(const RenX::PlayerInfo *player, const Jupiter::ReadableString &reason); + /** + * @brief Checks if any players are in the ban list, and kicks any players listed. + */ + void banCheck(); + + /** + * @brief Checks if a player is in the ban list, and kicks them if they are. + * Note: Check a player's ban_flags to see what ban types are active on them. + * + * @param player Data of the player to check. + */ + void banCheck(RenX::PlayerInfo *player); + /** * @brief Bans a player from the server. * @@ -911,6 +931,7 @@ namespace RenX bool allowPrivateMessaging = true; bool autoBalanceTeams = true; bool spawnCrates = true; + bool competitive = false; int attempts = 0; int playerLimit = 0; int vehicleLimit = 0; diff --git a/RenX.ModSystem/RenX_ModSystem.cpp b/RenX.ModSystem/RenX_ModSystem.cpp index f555cef..4c4f1c1 100644 --- a/RenX.ModSystem/RenX_ModSystem.cpp +++ b/RenX.ModSystem/RenX_ModSystem.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014-2015 Jessica James. + * Copyright (C) 2014-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -173,9 +173,11 @@ int RenX_ModSystemPlugin::auth(RenX::Server *server, const RenX::PlayerInfo *pla player->gamePrefix = section->get(STRING_LITERAL_AS_REFERENCE("GamePrefix"), group->gamePrefix); player->access = section->getInt(STRING_LITERAL_AS_REFERENCE("Access"), group->access); if (player->access != 0) + { server->sendMessage(player, Jupiter::StringS::Format("You are now authenticated with access level %d; group: %.*s.", player->access, group->name.size(), group->name.ptr())); - if (server->getRCONUsername().equals("DevBot"_jrs)) - server->sendData(Jupiter::StringS::Format("d%d\n", player->id)); + if (server->getRCONUsername().equals("DevBot"_jrs)) + server->sendData(Jupiter::StringS::Format("d%d\n", player->id)); + } Jupiter::String playerName = RenX::getFormattedPlayerName(player); server->sendLogChan(IRCCOLOR "03[Authentication] " IRCBOLD "%.*s" IRCBOLD IRCCOLOR " is now authenticated with access level %d; group: %.*s.", playerName.size(), playerName.ptr(), player->access, group->name.size(), group->name.ptr()); return player->access; @@ -354,6 +356,12 @@ void RenX_ModSystemPlugin::RenX_OnPlayerDelete(RenX::Server *server, const RenX: } } +void RenX_ModSystemPlugin::RenX_OnIDChange(RenX::Server *server, const RenX::PlayerInfo *player, int oldID) +{ + if (player->access != 0 && server->getRCONUsername().equals("DevBot"_jrs)) + server->sendData(Jupiter::StringS::Format("d%d\n", player->id)); +} + void RenX_ModSystemPlugin::RenX_OnAdminLogin(RenX::Server *server, const RenX::PlayerInfo *player) { ModGroup *group = nullptr; diff --git a/RenX.ModSystem/RenX_ModSystem.h b/RenX.ModSystem/RenX_ModSystem.h index db069ec..a01ccff 100644 --- a/RenX.ModSystem/RenX_ModSystem.h +++ b/RenX.ModSystem/RenX_ModSystem.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014-2015 Jessica James. + * Copyright (C) 2014-2016 Jessica James. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -95,6 +95,8 @@ public: // RenX::Plugin void RenX_OnPlayerCreate(RenX::Server *server, const RenX::PlayerInfo *player) override; void RenX_OnPlayerDelete(RenX::Server *server, const RenX::PlayerInfo *player) override; + void RenX_OnIDChange(RenX::Server *server, const RenX::PlayerInfo *player, int oldID) override; + void RenX_OnAdminLogin(RenX::Server *server, const RenX::PlayerInfo *player) override; void RenX_OnAdminGrant(RenX::Server *server, const RenX::PlayerInfo *player) override; void RenX_OnAdminLogout(RenX::Server *server, const RenX::PlayerInfo *player) override;