Browse Source

Bot:

* Added "Error: Command disabled." error message
CoreCommands:
* Added "Error: Command disabled." error message
RenX.Core:
* Fixed all known crashing/corruption issues related to the new BanDatabase.
* Replaced 'banCheck' processLine lambda function
* bIsCompetitive is now tracked as 'competitive'
* Added checks for commands disabled when 'competitive' is true
RenX.Commands:
* Combined Date and Time fields in BanSearch IRC Command results.
* Added error message for when certain commands are disabled/not supported by a server
* Global ban checks are now run after a "ban" or "addban" command is executed
pull/3/head
JustinAJ 9 years ago
parent
commit
c724eea309
  1. 29
      Bot/IRC_Bot.cpp
  2. 17
      CoreCommands/CoreCommands.cpp
  3. 2
      Jupiter
  4. BIN
      Release/Bot.lib
  5. BIN
      Release/Plugins/RenX.Core.lib
  6. 70
      RenX.Commands/RenX_Commands.cpp
  7. 15
      RenX.Core/RenX_BanDatabase.cpp
  8. 3
      RenX.Core/RenX_BanDatabase.h
  9. 20
      RenX.Core/RenX_Core.cpp
  10. 15
      RenX.Core/RenX_Core.h
  11. 366
      RenX.Core/RenX_Server.cpp
  12. 21
      RenX.Core/RenX_Server.h
  13. 14
      RenX.ModSystem/RenX_ModSystem.cpp
  14. 4
      RenX.ModSystem/RenX_ModSystem.h

29
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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -16,19 +16,6 @@
* Written by Jessica James <jessica.aj@outlook.com> * Written by Jessica James <jessica.aj@outlook.com>
*/ */
/**
* 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 <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <cctype> #include <cctype>
@ -38,9 +25,11 @@
#include "IRC_Bot.h" #include "IRC_Bot.h"
#include "IRC_Command.h" #include "IRC_Command.h"
using namespace Jupiter::literals;
IRC_Bot::IRC_Bot(const Jupiter::ReadableString &configSection) : Client(configSection) 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++) for (size_t i = 0; i != IRCMasterCommandList->size(); i++)
IRC_Bot::addCommand(IRCMasterCommandList->get(i)->copy()); IRC_Bot::addCommand(IRCMasterCommandList->get(i)->copy());
IRC_Bot::setCommandAccessLevels(); IRC_Bot::setCommandAccessLevels();
@ -200,11 +189,13 @@ void IRC_Bot::OnChat(const Jupiter::ReadableString &channel, const Jupiter::Read
if (cmd != nullptr) if (cmd != nullptr)
{ {
IRCCommand::active_server = this; IRCCommand::active_server = this;
int cAccess = cmd->getAccessLevel(chan); int command_access = cmd->getAccessLevel(chan);
if (cAccess >= 0 && Jupiter::IRC::Client::getAccessLevel(channel, nick) >= cAccess) if (command_access < 0)
cmd->trigger(this, channel, nick, parameters); this->sendNotice(nick, "Error: Command disabled."_jrs);
else if (Jupiter::IRC::Client::getAccessLevel(channel, nick) < command_access)
this->sendNotice(nick, "Access Denied."_jrs);
else else
this->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Access Denied.")); cmd->trigger(this, channel, nick, parameters);
IRCCommand::active_server = IRCCommand::selected_server; IRCCommand::active_server = IRCCommand::selected_server;
} }
} }

17
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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -68,7 +68,7 @@ CONSOLE_COMMAND_INIT(HelpConsoleCommand)
void HelpIRCCommand::create() 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 &parameters) void HelpIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &parameters)
@ -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, 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 <command>")); source->sendNotice(nick, "For command-specific help, use: help <command>"_jrs);
} }
else else
{ {
IRCCommand *cmd = source->getCommand(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE)); IRCCommand *cmd = source->getCommand(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE));
if (cmd) 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))); 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);
} }
} }
} }

2
Jupiter

@ -1 +1 @@
Subproject commit 5b83899a03642d18deb6a85dabfb1afd8d76422e Subproject commit 5eca27adc30fef1d51156d94de85a34f4e5793d0

BIN
Release/Bot.lib

Binary file not shown.

BIN
Release/Plugins/RenX.Core.lib

Binary file not shown.

70
RenX.Commands/RenX_Commands.cpp

@ -1164,8 +1164,7 @@ void BanSearchIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString
if (isMatch(type)) if (isMatch(type))
{ {
Jupiter::StringS &ip_str = Jupiter::Socket::ntop4(entry->ip); 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, %H:%M:%S", localtime(&(entry->timestamp)));
strftime(timeStr, sizeof(timeStr), "%b %d %Y; Time: %H:%M:%S", localtime(&(entry->timestamp)));
if ((entry->flags & 0x7FFF) == 0) if ((entry->flags & 0x7FFF) == 0)
types = " NULL;"_jrs; 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", 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(), 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()) if (entry->rdns.isNotEmpty())
{ {
@ -1639,8 +1638,10 @@ void DisarmIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &c
player = server->getPlayerByPartName(parameters); player = server->getPlayerByPartName(parameters);
if (player != nullptr) if (player != nullptr)
{ {
server->disarm(player); 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.")); 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 else
source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); 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); player = server->getPlayerByPartName(parameters);
if (player != nullptr) if (player != nullptr)
{ {
server->disarmC4(player); 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.")); 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 else
source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); 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); player = server->getPlayerByPartName(parameters);
if (player != nullptr) if (player != nullptr)
{ {
server->disarmBeacon(player); 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.")); 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 else
source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); 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.")); 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 <player>")); else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: mineban <player>"));
} }
const Jupiter::ReadableString &MineBanIRCCommand::getHelp(const Jupiter::ReadableString &) 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::PlayerInfo *player;
RenX::Server *server; RenX::Server *server;
unsigned int kicks = 0; unsigned int kicks = 0;
Jupiter::StringS name = Jupiter::StringS::getWord(parameters, 0, WHITESPACE); Jupiter::ReferenceString name = Jupiter::ReferenceString::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 reason = parameters.wordCount(WHITESPACE) > 1 ? Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE) : "No reason"_jrs;
Jupiter::String banner(nick.size() + 4); Jupiter::String banner(nick.size() + 4);
banner += nick; banner += nick;
banner += "@IRC"; banner += "@IRC";
@ -1965,7 +1970,10 @@ void KickBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &
if (kicks == 0) if (kicks == 0)
source->sendMessage(channel, "Player \""_jrs + name + "\" not found."_jrs); source->sendMessage(channel, "Player \""_jrs + name + "\" not found."_jrs);
else else
{
source->sendMessage(channel, Jupiter::StringS::Format("%u players kicked.", kicks)); 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.")); 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; flags |= RenX::BanDatabase::Entry::FLAG_USE_RDNS;
RenX::banDatabase->add(name, ip, prefix_length, steamid, rdns, banner, reason, duration); 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); RenX::Server *server = RenX::getCore()->getServer(i);
if (server->isLogChanType(type) && server->players.size() != 0) if (server->isLogChanType(type) && server->players.size() != 0)
{ {
for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = server->players.getNode(0); node != nullptr; node = node->next) player = server->getPlayerByPartName(playerName);
if (player != nullptr)
{ {
player = node->data; if (server->giveCredits(player, credits))
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("You have been refunded %.0f credits by %.*s.", credits, nick.size(), nick.ptr()); msg.format("%.*s has been refunded %.0f credits.", player->name.size(), player->name.ptr(), credits);
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);
} }
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.")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found."));
else if (target->access >= player->access) else if (target->access >= player->access)
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not disarm higher level moderators.")); 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 else
{
source->disarm(target);
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed.")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed."));
}
} }
else else
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarm <player>")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarm <player>"));
@ -2819,11 +2824,10 @@ void DisarmC4GameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found."));
else if (target->access >= player->access) else if (target->access >= player->access)
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not disarm higher level moderators.")); 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 else
{
source->disarmC4(target);
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed.")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed."));
}
} }
else else
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarmc4 <player>")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarmc4 <player>"));
@ -2856,11 +2860,10 @@ void DisarmBeaconGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *pl
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found."));
else if (target->access >= player->access) else if (target->access >= player->access)
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You can not disarm higher level moderators.")); 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 else
{
source->disarmBeacon(target);
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed.")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been disarmed."));
}
} }
else else
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarmb <player>")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Too few parameters. Syntax: disarmb <player>"));
@ -3019,6 +3022,7 @@ void KickBanGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player,
{ {
source->banPlayer(target, player->name, reason); source->banPlayer(target, player->name, reason);
source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been banned and kicked from the game.")); source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Player has been banned and kicked from the game."));
RenX::getCore()->banCheck();
} }
} }
else else

15
RenX.Core/RenX_BanDatabase.cpp

@ -44,7 +44,7 @@ void RenX::BanDatabase::process_data(Jupiter::DataBuffer &buffer, FILE *file, fp
entry->length = buffer.pop<time_t>(); entry->length = buffer.pop<time_t>();
entry->steamid = buffer.pop<uint64_t>(); entry->steamid = buffer.pop<uint64_t>();
entry->ip = buffer.pop<uint32_t>(); entry->ip = buffer.pop<uint32_t>();
entry->prefix_length = buffer.pop<uint32_t>(); entry->prefix_length = buffer.pop<uint8_t>();
entry->rdns = buffer.pop<Jupiter::String_Strict, char>(); entry->rdns = buffer.pop<Jupiter::String_Strict, char>();
entry->name = buffer.pop<Jupiter::String_Strict, char>(); entry->name = buffer.pop<Jupiter::String_Strict, char>();
entry->banner = buffer.pop<Jupiter::String_Strict, char>(); entry->banner = buffer.pop<Jupiter::String_Strict, char>();
@ -53,6 +53,8 @@ void RenX::BanDatabase::process_data(Jupiter::DataBuffer &buffer, FILE *file, fp
// Read varData from buffer to entry // Read varData from buffer to entry
for (size_t varData_entries = buffer.pop<size_t>(); varData_entries != 0; --varData_entries) for (size_t varData_entries = buffer.pop<size_t>(); varData_entries != 0; --varData_entries)
entry->varData.set(buffer.pop<Jupiter::String_Strict, char>(), buffer.pop<Jupiter::String_Strict, char>()); entry->varData.set(buffer.pop<Jupiter::String_Strict, char>(), buffer.pop<Jupiter::String_Strict, char>());
RenX::BanDatabase::entries.add(entry);
} }
void RenX::BanDatabase::process_header(FILE *file) 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."); puts("Warning: Unsupported ban database file version. The database will be removed and rewritten.");
this->create_header(file); this->create_header(file);
fgetpos(file, std::addressof(RenX::BanDatabase::eof));
RenX::BanDatabase::read_version = RenX::BanDatabase::write_version; RenX::BanDatabase::read_version = RenX::BanDatabase::write_version;
} }
return;
} }
fgetpos(file, std::addressof(RenX::BanDatabase::eof));
} }
void RenX::BanDatabase::upgrade_database() void RenX::BanDatabase::upgrade_database()
@ -97,7 +103,8 @@ void RenX::BanDatabase::upgrade_database()
void RenX::BanDatabase::write(RenX::BanDatabase::Entry *entry) 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) if (file != nullptr)
{ {
RenX::BanDatabase::write(entry, file); RenX::BanDatabase::write(entry, file);
@ -136,6 +143,7 @@ void RenX::BanDatabase::write(RenX::BanDatabase::Entry *entry, FILE *file)
// push buffer to file // push buffer to file
buffer.push_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) 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) if (file != nullptr)
{ {
fsetpos(file, &entry->pos); 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); fclose(file);
} }
return true; return true;

3
RenX.Core/RenX_BanDatabase.h

@ -176,7 +176,7 @@ namespace RenX
* @param entry Entry to write to the database. * @param entry Entry to write to the database.
* @param file FILE stream to write to. * @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. * @brief Deactivates a ban entry.
@ -214,6 +214,7 @@ namespace RenX
/** Database version */ /** Database version */
const uint8_t write_version = 3U; const uint8_t write_version = 3U;
uint8_t read_version = write_version; uint8_t read_version = write_version;
fpos_t eof;
Jupiter::CStringS filename; Jupiter::CStringS filename;
Jupiter::ArrayList<RenX::BanDatabase::Entry> entries; Jupiter::ArrayList<RenX::BanDatabase::Entry> entries;

20
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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * 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); return RenX::Core::servers.get(index);
} }
Jupiter::ArrayList<RenX::Server> RenX::Core::getServers()
{
return RenX::Core::servers;
}
Jupiter::ArrayList<RenX::Server> RenX::Core::getServers(int type) Jupiter::ArrayList<RenX::Server> RenX::Core::getServers(int type)
{ {
Jupiter::ArrayList<RenX::Server> r; Jupiter::ArrayList<RenX::Server> r;
@ -150,14 +155,17 @@ Jupiter::INIFile &RenX::Core::getCommandsFile()
int RenX::Core::addCommand(RenX::GameCommand *command) int RenX::Core::addCommand(RenX::GameCommand *command)
{ {
for (size_t i = 0; i != RenX::Core::servers.size(); i++) for (size_t i = 0; i != RenX::Core::servers.size(); ++i)
{ RenX::Core::servers.get(i)->addCommand(command->copy());
RenX::Server *server = RenX::Core::servers.get(i);
server->addCommand(command->copy());
}
return RenX::Core::servers.size(); 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() int RenX::Core::think()
{ {
size_t index = 0; size_t index = 0;

15
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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -98,6 +98,14 @@ namespace RenX
*/ */
RenX::Server *getServer(unsigned int index); 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<RenX::Server> getServers();
/** /**
* @brief Constructs a list of servers based on their type. * @brief Constructs a list of servers based on their type.
* *
@ -165,6 +173,11 @@ namespace RenX
*/ */
int addCommand(GameCommand *command); 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. * @brief Initializes the Core.
*/ */

366
RenX.Core/RenX_Server.cpp

@ -169,6 +169,11 @@ bool RenX::Server::isSeamless() const
return RenX::Server::seamless; return RenX::Server::seamless;
} }
bool RenX::Server::isCompetitive() const
{
return RenX::Server::competitive;
}
bool RenX::Server::isPublicLogChanType(int type) const bool RenX::Server::isPublicLogChanType(int type) const
{ {
return RenX::Server::logChanType == type; return RenX::Server::logChanType == type;
@ -295,7 +300,8 @@ RenX::PlayerInfo *RenX::Server::getPlayerByName(const Jupiter::ReadableString &n
idToken.shiftRight(6); idToken.shiftRight(6);
else if (name.matchi("pid?*")) else if (name.matchi("pid?*"))
idToken.shiftRight(3); idToken.shiftRight(3);
else return nullptr; else
return nullptr;
int id = idToken.asInt(10); int id = idToken.asInt(10);
for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) for (Jupiter::DLList<RenX::PlayerInfo>::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); RenX::Server::forceKickPlayer(player->id, reason);
} }
void RenX::Server::banCheck()
{
for (Jupiter::DLList<RenX::PlayerInfo>::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<RenX::BanDatabase::Entry> &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<const time_t>(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<const time_t>(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<const time_t>(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<const time_t>(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<const time_t>(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<const time_t>(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) void RenX::Server::banPlayer(int id, const Jupiter::ReadableString &banner, const Jupiter::ReadableString &reason)
{ {
if (RenX::Server::rconBan) 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())); RenX::Server::forceKickPlayer(player, Jupiter::StringS::Format("You are permanently banned from the server for: %.*s", reason.size(), reason.ptr()));
} }
else if (banner.isNotEmpty()) 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<long long>(length / 86400), static_cast<int>(length % 3600), static_cast<int>((length % 3600) / 60), static_cast<int>(length % 60), reason.size(), reason.ptr()));
else 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<long long>(length/86400), static_cast<int>(length%3600), static_cast<int>((length%3600)/60), static_cast<int>(length%60), reason.size(), reason.ptr()));
} }
bool RenX::Server::removePlayer(int id) 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) 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) 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) 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) bool RenX::Server::kill(RenX::PlayerInfo *player)
@ -541,7 +705,7 @@ bool RenX::Server::kill(RenX::PlayerInfo *player)
bool RenX::Server::disarm(int id) 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) bool RenX::Server::disarm(RenX::PlayerInfo *player)
@ -551,7 +715,7 @@ bool RenX::Server::disarm(RenX::PlayerInfo *player)
bool RenX::Server::disarmC4(int id) 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) bool RenX::Server::disarmC4(RenX::PlayerInfo *player)
@ -561,7 +725,7 @@ bool RenX::Server::disarmC4(RenX::PlayerInfo *player)
bool RenX::Server::disarmBeacon(int id) 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) bool RenX::Server::disarmBeacon(RenX::PlayerInfo *player)
@ -1033,156 +1197,6 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line)
isBot = false; isBot = false;
id = idToken.asInt(10); id = idToken.asInt(10);
}; };
auto banCheck = [this](RenX::PlayerInfo *player)
{
const Jupiter::ArrayList<RenX::BanDatabase::Entry> &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<const time_t>(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<const time_t>(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<const time_t>(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<const time_t>(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<const time_t>(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<const time_t>(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) 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); RenX::PlayerInfo *r = this->getPlayer(id);
@ -1204,7 +1218,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line)
this->players.add(r); this->players.add(r);
r->uuid = calc_uuid(r); r->uuid = calc_uuid(r);
banCheck(r); this->banCheck(r);
for (size_t i = 0; i < xPlugins.size(); i++) for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnPlayerCreate(this, r); xPlugins.get(i)->RenX_OnPlayerCreate(this, r);
@ -1233,7 +1247,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line)
if (recalcUUID) if (recalcUUID)
{ {
this->setUUIDIfDifferent(r, calc_uuid(r)); this->setUUIDIfDifferent(r, calc_uuid(r));
banCheck(r); this->banCheck(r);
} }
} }
return r; return r;
@ -1598,18 +1612,23 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line)
} }
else if (this->lastCommand.equalsi("gameinfo"_jrs)) 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 if (this->lastCommandParams.isEmpty())
this->playerLimit = tokens.getToken(1).asInt(); {
this->vehicleLimit = tokens.getToken(3).asInt(); // "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->mineLimit = tokens.getToken(5).asInt(); this->playerLimit = tokens.getToken(1).asInt();
this->timeLimit = tokens.getToken(7).asInt(); this->vehicleLimit = tokens.getToken(3).asInt();
this->passworded = tokens.getToken(9).asBool(); this->mineLimit = tokens.getToken(5).asInt();
this->steamRequired = tokens.getToken(11).asBool(); this->timeLimit = tokens.getToken(7).asInt();
this->privateMessageTeamOnly = tokens.getToken(13).asBool(); this->passworded = tokens.getToken(9).asBool();
this->allowPrivateMessaging = tokens.getToken(15).asBool(); this->steamRequired = tokens.getToken(11).asBool();
this->autoBalanceTeams = tokens.getToken(17).asBool(); this->privateMessageTeamOnly = tokens.getToken(13).asBool();
this->spawnCrates = tokens.getToken(19).asBool(); this->allowPrivateMessaging = tokens.getToken(15).asBool();
this->crateRespawnAfterPickup = tokens.getToken(21).asDouble(); 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)) else if (this->lastCommand.equalsi("mutatorlist"_jrs))
{ {
@ -2233,7 +2252,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line)
if (player != nullptr) if (player != nullptr)
{ {
player->id = tokens.getToken(3).asInt(); player->id = tokens.getToken(3).asInt();
banCheck(player); this->banCheck(player);
for (size_t i = 0; i < xPlugins.size(); i++) for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnIDChange(this, player, oldID); 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::sock.send("s\n"_jrs);
RenX::Server::send("serverinfo"_jrs); RenX::Server::send("serverinfo"_jrs);
RenX::Server::send("gameinfo"_jrs); RenX::Server::send("gameinfo"_jrs);
RenX::Server::send("gameinfo bIsCompetitive"_jrs);
RenX::Server::send("mutatorlist"_jrs); RenX::Server::send("mutatorlist"_jrs);
RenX::Server::send("rotation"_jrs); RenX::Server::send("rotation"_jrs);
RenX::Server::fetchClientList(); RenX::Server::fetchClientList();

21
RenX.Core/RenX_Server.h

@ -138,6 +138,13 @@ namespace RenX
*/ */
bool isSeamless() const; 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. * @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); 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. * @brief Bans a player from the server.
* *
@ -911,6 +931,7 @@ namespace RenX
bool allowPrivateMessaging = true; bool allowPrivateMessaging = true;
bool autoBalanceTeams = true; bool autoBalanceTeams = true;
bool spawnCrates = true; bool spawnCrates = true;
bool competitive = false;
int attempts = 0; int attempts = 0;
int playerLimit = 0; int playerLimit = 0;
int vehicleLimit = 0; int vehicleLimit = 0;

14
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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * 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->gamePrefix = section->get(STRING_LITERAL_AS_REFERENCE("GamePrefix"), group->gamePrefix);
player->access = section->getInt(STRING_LITERAL_AS_REFERENCE("Access"), group->access); player->access = section->getInt(STRING_LITERAL_AS_REFERENCE("Access"), group->access);
if (player->access != 0) 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())); 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)) if (server->getRCONUsername().equals("DevBot"_jrs))
server->sendData(Jupiter::StringS::Format("d%d\n", player->id)); server->sendData(Jupiter::StringS::Format("d%d\n", player->id));
}
Jupiter::String playerName = RenX::getFormattedPlayerName(player); 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()); 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; 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) void RenX_ModSystemPlugin::RenX_OnAdminLogin(RenX::Server *server, const RenX::PlayerInfo *player)
{ {
ModGroup *group = nullptr; ModGroup *group = nullptr;

4
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 * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * 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_OnPlayerCreate(RenX::Server *server, const RenX::PlayerInfo *player) override;
void RenX_OnPlayerDelete(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_OnAdminLogin(RenX::Server *server, const RenX::PlayerInfo *player) override;
void RenX_OnAdminGrant(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; void RenX_OnAdminLogout(RenX::Server *server, const RenX::PlayerInfo *player) override;

Loading…
Cancel
Save