From 627d007d590cc5cc3c1dec59873fe16c7886606d Mon Sep 17 00:00:00 2001 From: JustinAJ Date: Wed, 2 Jul 2014 23:08:20 -0400 Subject: [PATCH] Initial Commit --- Bot/Bot.vcxproj | 109 ++ Bot/Bot.vcxproj.filters | 56 + Bot/Console_Command.cpp | 49 + Bot/Console_Command.h | 107 ++ Bot/IRC_Bot.cpp | 204 +++ Bot/IRC_Bot.h | 128 ++ Bot/IRC_Command.cpp | 119 ++ Bot/IRC_Command.h | 197 +++ Bot/Jupiter_Bot.h | 38 + Bot/Main.cpp | 154 ++ Bot/ServerManager.cpp | 154 ++ Bot/ServerManager.h | 157 ++ CoreCommands/CoreCommands.cpp | 228 +++ CoreCommands/CoreCommands.h | 41 + CoreCommands/CoreCommands.vcxproj | 85 ++ CoreCommands/CoreCommands.vcxproj.filters | 35 + ExtraCommands/ExtraCommands.cpp | 287 ++++ ExtraCommands/ExtraCommands.h | 43 + ExtraCommands/ExtraCommands.vcxproj | 84 + ExtraCommands/ExtraCommands.vcxproj.filters | 35 + FunCommands/FunCommands.cpp | 169 ++ FunCommands/FunCommands.h | 36 + FunCommands/FunCommands.vcxproj | 84 + FunCommands/FunCommands.vcxproj.filters | 35 + Jupiter Bot.sln | 176 +++ MakeRelease.bat | 66 + Plugin.Example/Example.cpp | 44 + Plugin.Example/Example.h | 28 + Plugin.Example/Plugin.Example.vcxproj | 84 + Plugin.Example/Plugin.Example.vcxproj.filters | 35 + Plugin.Template - Copy/Example.cpp | 11 + Plugin.Template - Copy/Example.h | 11 + .../Plugin.Template.vcxproj | 83 + .../Plugin.Template.vcxproj.filters | 35 + Plugin.Template/Example.cpp | 19 + Plugin.Template/Example.h | 24 + Plugin.Template/Plugin.Template.vcxproj | 84 + .../Plugin.Template.vcxproj.filters | 35 + PluginManager/PluginManager.cpp | 172 +++ PluginManager/PluginManager.h | 39 + PluginManager/PluginManager.vcxproj | 85 ++ PluginManager/PluginManager.vcxproj.filters | 35 + Release/Bot.lib | Bin 0 -> 19582 bytes Release/Plugins/RenX.Core.lib | Bin 0 -> 51654 bytes RenX.Announcements/RenX.Announcements.vcxproj | 85 ++ .../RenX.Announcements.vcxproj.filters | 38 + RenX.Announcements/RenX_Announcements.cpp | 73 + RenX.Announcements/RenX_Announcements.h | 43 + RenX.Commands/RenX.Commands.vcxproj | 87 ++ RenX.Commands/RenX.Commands.vcxproj.filters | 38 + RenX.Commands/RenX_Commands.cpp | 1357 +++++++++++++++++ RenX.Commands/RenX_Commands.h | 71 + RenX.Core/RenX.Core.vcxproj | 95 ++ RenX.Core/RenX.Core.vcxproj.filters | 65 + RenX.Core/RenX.h | 70 + RenX.Core/RenX_Core.cpp | 619 ++++++++ RenX.Core/RenX_Core.h | 188 +++ RenX.Core/RenX_Functions.cpp | 592 +++++++ RenX.Core/RenX_Functions.h | 169 ++ RenX.Core/RenX_GameCommand.cpp | 51 + RenX.Core/RenX_GameCommand.h | 110 ++ RenX.Core/RenX_PlayerInfo.h | 73 + RenX.Core/RenX_Plugin.cpp | 161 ++ RenX.Core/RenX_Plugin.h | 102 ++ RenX.Core/RenX_Server.cpp | 443 ++++++ RenX.Core/RenX_Server.h | 431 ++++++ .../ExcessiveHeadshots.cpp | 70 + RenX.ExcessiveHeadshots/ExcessiveHeadshots.h | 44 + .../RenX.ExcessiveHeadshots.vcxproj | 85 ++ .../RenX.ExcessiveHeadshots.vcxproj.filters | 38 + RenX.ExtraLogging/RenX.ExtraLogging.vcxproj | 85 ++ .../RenX.ExtraLogging.vcxproj.filters | 38 + RenX.ExtraLogging/RenX_ExtraLogging.cpp | 61 + RenX.ExtraLogging/RenX_ExtraLogging.h | 40 + RenX.Logging/RenX.Logging.vcxproj | 85 ++ RenX.Logging/RenX.Logging.vcxproj.filters | 38 + RenX.Logging/RenX_Logging.cpp | 318 ++++ RenX.Logging/RenX_Logging.h | 90 ++ RenX.Medals/RenX.Medals.vcxproj | 86 ++ RenX.Medals/RenX.Medals.vcxproj.filters | 38 + RenX.Medals/RenX_Medals.cpp | 355 +++++ RenX.Medals/RenX_Medals.h | 63 + RenX.Plugin.Template - Copy/Example.cpp | 11 + RenX.Plugin.Template - Copy/Example.h | 12 + .../RenX.Plugin.Template.vcxproj | 84 + .../RenX.Plugin.Template.vcxproj.filters | 38 + RenX.Plugin.Template/Example.cpp | 19 + RenX.Plugin.Template/Example.h | 24 + .../RenX.Plugin.Template.vcxproj | 85 ++ .../RenX.Plugin.Template.vcxproj.filters | 38 + RenX.SetJoin/RenX.SetJoin.vcxproj | 85 ++ RenX.SetJoin/RenX.SetJoin.vcxproj.filters | 38 + RenX.SetJoin/RenX_SetJoin.cpp | 130 ++ RenX.SetJoin/RenX_SetJoin.h | 41 + SetJoin/SetJoin.cpp | 118 ++ SetJoin/SetJoin.h | 38 + SetJoin/SetJoin.vcxproj | 84 + SetJoin/SetJoin.vcxproj.filters | 35 + 98 files changed, 11075 insertions(+) create mode 100644 Bot/Bot.vcxproj create mode 100644 Bot/Bot.vcxproj.filters create mode 100644 Bot/Console_Command.cpp create mode 100644 Bot/Console_Command.h create mode 100644 Bot/IRC_Bot.cpp create mode 100644 Bot/IRC_Bot.h create mode 100644 Bot/IRC_Command.cpp create mode 100644 Bot/IRC_Command.h create mode 100644 Bot/Jupiter_Bot.h create mode 100644 Bot/Main.cpp create mode 100644 Bot/ServerManager.cpp create mode 100644 Bot/ServerManager.h create mode 100644 CoreCommands/CoreCommands.cpp create mode 100644 CoreCommands/CoreCommands.h create mode 100644 CoreCommands/CoreCommands.vcxproj create mode 100644 CoreCommands/CoreCommands.vcxproj.filters create mode 100644 ExtraCommands/ExtraCommands.cpp create mode 100644 ExtraCommands/ExtraCommands.h create mode 100644 ExtraCommands/ExtraCommands.vcxproj create mode 100644 ExtraCommands/ExtraCommands.vcxproj.filters create mode 100644 FunCommands/FunCommands.cpp create mode 100644 FunCommands/FunCommands.h create mode 100644 FunCommands/FunCommands.vcxproj create mode 100644 FunCommands/FunCommands.vcxproj.filters create mode 100644 Jupiter Bot.sln create mode 100644 MakeRelease.bat create mode 100644 Plugin.Example/Example.cpp create mode 100644 Plugin.Example/Example.h create mode 100644 Plugin.Example/Plugin.Example.vcxproj create mode 100644 Plugin.Example/Plugin.Example.vcxproj.filters create mode 100644 Plugin.Template - Copy/Example.cpp create mode 100644 Plugin.Template - Copy/Example.h create mode 100644 Plugin.Template - Copy/Plugin.Template.vcxproj create mode 100644 Plugin.Template - Copy/Plugin.Template.vcxproj.filters create mode 100644 Plugin.Template/Example.cpp create mode 100644 Plugin.Template/Example.h create mode 100644 Plugin.Template/Plugin.Template.vcxproj create mode 100644 Plugin.Template/Plugin.Template.vcxproj.filters create mode 100644 PluginManager/PluginManager.cpp create mode 100644 PluginManager/PluginManager.h create mode 100644 PluginManager/PluginManager.vcxproj create mode 100644 PluginManager/PluginManager.vcxproj.filters create mode 100644 Release/Bot.lib create mode 100644 Release/Plugins/RenX.Core.lib create mode 100644 RenX.Announcements/RenX.Announcements.vcxproj create mode 100644 RenX.Announcements/RenX.Announcements.vcxproj.filters create mode 100644 RenX.Announcements/RenX_Announcements.cpp create mode 100644 RenX.Announcements/RenX_Announcements.h create mode 100644 RenX.Commands/RenX.Commands.vcxproj create mode 100644 RenX.Commands/RenX.Commands.vcxproj.filters create mode 100644 RenX.Commands/RenX_Commands.cpp create mode 100644 RenX.Commands/RenX_Commands.h create mode 100644 RenX.Core/RenX.Core.vcxproj create mode 100644 RenX.Core/RenX.Core.vcxproj.filters create mode 100644 RenX.Core/RenX.h create mode 100644 RenX.Core/RenX_Core.cpp create mode 100644 RenX.Core/RenX_Core.h create mode 100644 RenX.Core/RenX_Functions.cpp create mode 100644 RenX.Core/RenX_Functions.h create mode 100644 RenX.Core/RenX_GameCommand.cpp create mode 100644 RenX.Core/RenX_GameCommand.h create mode 100644 RenX.Core/RenX_PlayerInfo.h create mode 100644 RenX.Core/RenX_Plugin.cpp create mode 100644 RenX.Core/RenX_Plugin.h create mode 100644 RenX.Core/RenX_Server.cpp create mode 100644 RenX.Core/RenX_Server.h create mode 100644 RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp create mode 100644 RenX.ExcessiveHeadshots/ExcessiveHeadshots.h create mode 100644 RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj create mode 100644 RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj.filters create mode 100644 RenX.ExtraLogging/RenX.ExtraLogging.vcxproj create mode 100644 RenX.ExtraLogging/RenX.ExtraLogging.vcxproj.filters create mode 100644 RenX.ExtraLogging/RenX_ExtraLogging.cpp create mode 100644 RenX.ExtraLogging/RenX_ExtraLogging.h create mode 100644 RenX.Logging/RenX.Logging.vcxproj create mode 100644 RenX.Logging/RenX.Logging.vcxproj.filters create mode 100644 RenX.Logging/RenX_Logging.cpp create mode 100644 RenX.Logging/RenX_Logging.h create mode 100644 RenX.Medals/RenX.Medals.vcxproj create mode 100644 RenX.Medals/RenX.Medals.vcxproj.filters create mode 100644 RenX.Medals/RenX_Medals.cpp create mode 100644 RenX.Medals/RenX_Medals.h create mode 100644 RenX.Plugin.Template - Copy/Example.cpp create mode 100644 RenX.Plugin.Template - Copy/Example.h create mode 100644 RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj create mode 100644 RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj.filters create mode 100644 RenX.Plugin.Template/Example.cpp create mode 100644 RenX.Plugin.Template/Example.h create mode 100644 RenX.Plugin.Template/RenX.Plugin.Template.vcxproj create mode 100644 RenX.Plugin.Template/RenX.Plugin.Template.vcxproj.filters create mode 100644 RenX.SetJoin/RenX.SetJoin.vcxproj create mode 100644 RenX.SetJoin/RenX.SetJoin.vcxproj.filters create mode 100644 RenX.SetJoin/RenX_SetJoin.cpp create mode 100644 RenX.SetJoin/RenX_SetJoin.h create mode 100644 SetJoin/SetJoin.cpp create mode 100644 SetJoin/SetJoin.h create mode 100644 SetJoin/SetJoin.vcxproj create mode 100644 SetJoin/SetJoin.vcxproj.filters diff --git a/Bot/Bot.vcxproj b/Bot/Bot.vcxproj new file mode 100644 index 0000000..3ddd9a2 --- /dev/null +++ b/Bot/Bot.vcxproj @@ -0,0 +1,109 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C188871B-5F32-4946-B301-24CA2EBB275D} + Win32Proj + IRCBotImp + Bot + + + + Application + true + v120 + Unicode + + + Application + false + v120 + true + Unicode + + + + + + + + + + + + + true + + + false + AllRules.ruleset + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;JUPITER_BOT_EXPORTS;%(PreprocessorDefinitions) + true + ..\Jupiter;%(AdditionalIncludeDirectories) + + + Console + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;JUPITER_BOT_EXPORTS;%(PreprocessorDefinitions) + true + Speed + + ../Jupiter + + + Console + true + true + true + + + true + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Bot/Bot.vcxproj.filters b/Bot/Bot.vcxproj.filters new file mode 100644 index 0000000..ceeff80 --- /dev/null +++ b/Bot/Bot.vcxproj.filters @@ -0,0 +1,56 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Resource Files + + + \ No newline at end of file diff --git a/Bot/Console_Command.cpp b/Bot/Console_Command.cpp new file mode 100644 index 0000000..0cd70db --- /dev/null +++ b/Bot/Console_Command.cpp @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Console_Command.h" + +Jupiter::ArrayList _consoleCommands; +Jupiter::ArrayList *consoleCommands = &_consoleCommands; + +ConsoleCommand::ConsoleCommand() +{ + consoleCommands->add(this); +} + +ConsoleCommand::~ConsoleCommand() +{ + for (size_t i = 0; i != consoleCommands->size(); i++) + { + if (consoleCommands->get(i) == this) + { + consoleCommands->remove(i); + break; + } + } +} + +ConsoleCommand *getConsoleCommand(const Jupiter::ReadableString &trigger) +{ + for (size_t i = 0; i != consoleCommands->size(); i++) + { + ConsoleCommand *cmd = consoleCommands->get(i); + if (cmd->matches(trigger)) + return cmd; + } + return nullptr; +} \ No newline at end of file diff --git a/Bot/Console_Command.h b/Bot/Console_Command.h new file mode 100644 index 0000000..94a5b00 --- /dev/null +++ b/Bot/Console_Command.h @@ -0,0 +1,107 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _CONSOLE_COMMAND_H_HEADER +#define _CONSOLE_COMMAND_H_HEADER + +/** +* @file Console_Command.h +* @brief Provides an extendable command system specialized for console-based commands. +*/ + +#include "Jupiter_Bot.h" +#include "Jupiter/Command.h" +#include "Jupiter/ArrayList.h" + +class Command; +class ConsoleCommand; + +/* +* Initial access level is always 0. Change this using setAccessLevel() +* There are no default triggers. Add triggers using addTrigger(trigger) +* When your command is triggered, trigger(parameters) will be called. +* You must provide command-specific help for your command, through getHelp(). +* The first trigger added is the trigger which is displayed to the user in the help command. +*/ + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +/** Console command list */ +JUPITER_BOT_API extern Jupiter::ArrayList *consoleCommands; + +/** +* @brief Provides the basis for console commands. +* Note: This will likely be moved to a separate file in the future. +*/ +class JUPITER_BOT_API ConsoleCommand : public Jupiter::Command +{ +public: + /** + * @brief Called when the command is to be executed. + * + * @param input Parameters passed to the command by the user. + */ + virtual void trigger(const Jupiter::ReadableString &input) = 0; + + /** + * @brief Default constructor for the console command class. + */ + ConsoleCommand(); + + /** + * @brief Destructor for the console command class. + */ + ~ConsoleCommand(); +}; + +/** +* @brief Fetches a console command based on its trigger. +* +* @param trigger Trigger of the command to fetch. +* @return A console command if it exists, nullptr otherwise. +*/ +JUPITER_BOT_API extern ConsoleCommand *getConsoleCommand(const Jupiter::ReadableString &trigger); + +/** Console Command Macros */ + +/** Defines the core of a console command's declaration. This should be included in every console command. */ +#define BASE_CONSOLE_COMMAND(CLASS) \ + public: \ + CLASS(); \ + void trigger(const Jupiter::ReadableString ¶meters); \ + const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters); + +/** Expands to become the entire declaration for a console command. In most cases, this will be sufficient. */ +#define GENERIC_CONSOLE_COMMAND(CLASS) \ +class CLASS : public ConsoleCommand { \ + BASE_CONSOLE_COMMAND(CLASS) \ +}; + +/** Instantiates a console command. */ +#define CONSOLE_COMMAND_INIT(CLASS) \ + CLASS CLASS ## _instance; + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _CONSOLE_COMMAND_H_HEADER \ No newline at end of file diff --git a/Bot/IRC_Bot.cpp b/Bot/IRC_Bot.cpp new file mode 100644 index 0000000..5575979 --- /dev/null +++ b/Bot/IRC_Bot.cpp @@ -0,0 +1,204 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +/** + * 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 +#include "Jupiter/INIFile.h" +#include "Jupiter/Plugin.h" +#include "Jupiter/Functions.h" +#include "IRC_Bot.h" +#include "IRC_Command.h" + +IRC_Bot::IRC_Bot(const Jupiter::ReadableString &configSection) : Client(configSection) +{ + IRC_Bot::commandPrefix = this->readConfigValue(STRING_LITERAL_AS_REFERENCE("Prefix")); + for (size_t i = 0; i != IRCMasterCommandList->size(); i++) + IRC_Bot::addCommand(IRCMasterCommandList->get(i)->copy()); + IRC_Bot::setCommandAccessLevels(); +} + +IRC_Bot::~IRC_Bot() +{ + while (IRC_Bot::commands.size()) delete IRC_Bot::commands.remove(0); +} + +void IRC_Bot::addCommand(IRCCommand *cmd) +{ + IRC_Bot::commands.add(cmd); +} + +bool IRC_Bot::freeCommand(const Jupiter::ReadableString &trigger) +{ + for (size_t i = 0; i != IRC_Bot::commands.size(); i++) + { + if (IRC_Bot::commands.get(i)->matches(trigger)) + { + delete IRC_Bot::commands.remove(i); + return true; + } + } + return false; +} + +int IRC_Bot::getCommandIndex(const Jupiter::ReadableString &trigger) const +{ + for (size_t i = 0; i != IRC_Bot::commands.size(); i++) + if (IRC_Bot::commands.get(i)->matches(trigger)) + return i; + return -1; +} + +IRCCommand *IRC_Bot::getCommand(const Jupiter::ReadableString &trigger) const +{ + int i = IRC_Bot::getCommandIndex(trigger); + if (i < 0) return nullptr; + return IRC_Bot::commands.get(i); +} + +Jupiter::ArrayList IRC_Bot::getAccessCommands(Jupiter::IRC::Client::Channel *chan, int access) +{ + Jupiter::ArrayList r; + for (size_t i = 0; i != IRC_Bot::commands.size(); i++) + { + IRCCommand *cmd = IRC_Bot::commands.get(i); + if (cmd->getAccessLevel(chan) == access) + r.add(cmd); + } + return r; +} + +Jupiter::StringL IRC_Bot::getTriggers(Jupiter::ArrayList cmds) +{ + Jupiter::StringL r; + for (size_t i = 0; i < cmds.size(); i++) + { + r += cmds[i]->getTrigger(); + r += ' '; + } + return r; +} + +void IRC_Bot::setCommandAccessLevels() +{ + // Rewrite this later + // Note: Prepare for abstraction of configuration file type. + Jupiter::StringS commandSection = "DefaultCommands"; + + checkForCommands: + int sIndex = Config->getSectionIndex(commandSection); + if (sIndex >= 0) + { + int sLen = Config->getSectionLength(sIndex); + for (int i = 0; i < sLen; i++) + { + const Jupiter::ReadableString &key = Config->getKey(commandSection, i); + int pos = key.find('.'); + if (pos != Jupiter::INVALID_INDEX) + { + Jupiter::ReferenceString command = Jupiter::ReferenceString(key.ptr(), pos); + if (command != nullptr) + { + IRCCommand *cmd = IRC_Bot::getCommand(command); + if (cmd != nullptr) + { + Jupiter::ReferenceString channelType(key.ptr() + pos + 1, key.size() - pos - 1); + if (isdigit(key[pos + 1])) + cmd->setAccessLevel(channelType.asInt(10), Config->getInt(commandSection, key)); + else cmd->setAccessLevel(channelType.asInt(10), Config->getInt(commandSection, key)); + } + else if (this->getPrintOutput()) printf("Unable to find command \"%.*s\"" ENDL, key.size(), key.ptr()); + } + } + else + { + IRCCommand *cmd = IRC_Bot::getCommand(key); + if (cmd != nullptr) cmd->setAccessLevel(Config->getInt(commandSection, key)); + else if (this->getPrintOutput()) printf("Unable to find command \"%.*s\"" ENDL, key.size(), key.ptr()); + } + } + } + if (commandSection.equals("DefaultCommands")) + { + commandSection = this->getConfigSection(); + commandSection += "Commands"; + if (commandSection.equals("DefaultCommands") == false) goto checkForCommands; + } +} + +int IRC_Bot::OnRehash() +{ + if (Config->reload() == Jupiter::ERROR_INDICATOR) return 1; + IRC_Bot::setCommandAccessLevels(); + return 0; +} + +void IRC_Bot::OnChat(const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &message) +{ + int chanIndex = this->getChannelIndex(channel); + if (chanIndex >= 0) + { + Channel *chan = this->getChannel(chanIndex); + if (chan->getType() >= 0) + { + Jupiter::ReferenceString msg = message; + while (msg.isEmpty() == false && isspace(msg[0])) + msg.shiftRight(1); + + if (IRC_Bot::commandPrefix.size() <= msg.size()) + { + bool matchesPrefix = true; + size_t i; + for (i = 0; i != IRC_Bot::commandPrefix.size(); i++) + { + if (toupper(msg.get(0)) != toupper(IRC_Bot::commandPrefix[i])) + { + matchesPrefix = false; + break; + } + msg.shiftRight(1); + } + + if (matchesPrefix) + { + Jupiter::ReferenceString command = Jupiter::ReferenceString::getWord(msg, 0, WHITESPACE);; + Jupiter::ReferenceString parameters = Jupiter::ReferenceString::gotoWord(msg, 1, WHITESPACE); + IRCCommand *cmd = IRC_Bot::getCommand(command); + if (cmd != nullptr) + { + int cAccess = cmd->getAccessLevel(chan); + if (cAccess >= 0 && Jupiter::IRC::Client::getAccessLevel(channel, nick) >= cAccess) cmd->trigger(this, channel, nick, parameters); + else this->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Access Denied.")); + } + } + } + } + } +} \ No newline at end of file diff --git a/Bot/IRC_Bot.h b/Bot/IRC_Bot.h new file mode 100644 index 0000000..6e07ea6 --- /dev/null +++ b/Bot/IRC_Bot.h @@ -0,0 +1,128 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _IRC_BOT_H_HEADER +#define _IRC_BOT_H_HEADER + +/** + * @file IRC_Bot.h + * @brief Provides extendable bot-like interfacing with the IRC client. + */ + +#include "Jupiter_Bot.h" +#include "Jupiter/IRC_Client.h" +#include "Jupiter/ArrayList.h" +#include "Jupiter/Rehash.h" +#include "Jupiter/String.h" + +/** Forward Declaration */ +class IRCCommand; + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +/** +* @brief Provies extendable bot-like interfacing with the IRC client. +*/ +class JUPITER_BOT_API IRC_Bot : public Jupiter::IRC::Client, public Jupiter::Rehashable +{ +public: + + /** + * @brief Pulls the configured access levels from the config and applies them. + */ + void setCommandAccessLevels(); + + /** + * @brief Adds a command to the command list. + */ + void addCommand(IRCCommand *cmd); + + /** + * @brief Removes a command from the command list. + * + * @param trigger Trigger of the command to remove + * @return True if a command is removed, false otherwise. + */ + bool freeCommand(const Jupiter::ReadableString &trigger); + + /** + * @brief Gets the index of a command. + * + * @param trigger Trigger of the command to find. + * @return Index of the first match for the trigger if found, -1 otherwise. + */ + int getCommandIndex(const Jupiter::ReadableString &trigger) const; + + /** + * @return Gets a command. + * + * @param trigger Trigger of the command to find. + * @return First command using the specified trigger, nullptr otherwise. + */ + IRCCommand *getCommand(const Jupiter::ReadableString &trigger) const; + + /** + * @brief Creates and returns an ArrayList of IRC Commands with a specified access level. + * + * @param chan Channel which access levels are set. + * @param access Access level to match. + * @return An ArrayList containing pointers to all of the matching commands. + */ + Jupiter::ArrayList getAccessCommands(Jupiter::IRC::Client::Channel *chan, int access); + + /** + * @brief Gets the triggers of all the commands in an ArrayList, and adds them to a space-deliminated string. + * + * @param cmds Commands to construct the string with. + * @return A string containing the triggers of the commands in a space-deliminated list. + */ + static Jupiter::StringL getTriggers(Jupiter::ArrayList cmds); + + /** + * @brief Reloads some settings. + * + * @return 0 on success, 1 otherwise. + */ + int OnRehash(); + + /** Constructor for IRC_Bot */ + IRC_Bot(const Jupiter::ReadableString &configSection); + + /** Destructor for IRC_Bot */ + ~IRC_Bot(); + + /** Overloaded events from Jupiter::IRC::Client */ +protected: + + void OnChat(const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &message); + + /** Private members for internal usage */ +private: + Jupiter::ArrayList commands; + Jupiter::StringS commandPrefix; +}; + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _IRC_BOT_H_HEADER \ No newline at end of file diff --git a/Bot/IRC_Command.cpp b/Bot/IRC_Command.cpp new file mode 100644 index 0000000..09ad1ba --- /dev/null +++ b/Bot/IRC_Command.cpp @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "IRC_Command.h" + +Jupiter::ArrayList _IRCMasterCommandList; +Jupiter::ArrayList *IRCMasterCommandList = &_IRCMasterCommandList; + +IRCCommand::IRCCommand() +{ + IRCCommand::access = 0; + IRCMasterCommandList->add(this); +} + +IRCCommand::IRCCommand(const IRCCommand &command) +{ + IRCCommand::access = command.access; + size_t i; + + for (i = 0; i < command.channels.size(); i++) + IRCCommand::channels.add(new IRCCommand::ChannelAccessPair(*command.channels.get(i))); + + for (i = 0; i < command.types.size(); i++) + IRCCommand::types.add(new IRCCommand::TypeAccessPair(*command.types.get(i))); +} + +IRCCommand::~IRCCommand() +{ + for (size_t i = 0; i != IRCMasterCommandList->size(); i++) + { + if (IRCMasterCommandList->get(i) == this) + { + serverManager->removeCommand(this); + IRCMasterCommandList->remove(i); + break; + } + } + IRCCommand::channels.emptyAndDelete(); + IRCCommand::types.emptyAndDelete(); +} + +// IRC Command Functions + +int IRCCommand::getAccessLevel() +{ + return IRCCommand::access; +} + +int IRCCommand::getAccessLevel(int type) +{ + for (size_t i = 0; i != IRCCommand::types.size(); i++) + if (IRCCommand::types.get(i)->type == type) + return IRCCommand::types.get(i)->access; + return IRCCommand::access; +} + +int IRCCommand::getAccessLevel(const Jupiter::ReadableString &channel) +{ + IRCCommand::ChannelAccessPair *pair; + for (size_t i = 0; i != IRCCommand::channels.size(); i++) + { + pair = IRCCommand::channels.get(i); + if (pair->channel.equalsi(channel)) + return pair->access; + } + return IRCCommand::access; +} + +int IRCCommand::getAccessLevel(Jupiter::IRC::Client::Channel *channel) +{ + IRCCommand::ChannelAccessPair *pair; + for (size_t i = 0; i != IRCCommand::channels.size(); i++) + { + pair = IRCCommand::channels.get(i); + if (pair->channel.equalsi(channel->getName())) + return pair->access; + } + + for (size_t i = 0; i != IRCCommand::types.size(); i++) + if (IRCCommand::types.get(i)->type == channel->getType()) + return IRCCommand::types.get(i)->access; + + return IRCCommand::access; +} + +void IRCCommand::setAccessLevel(int accessLevel) +{ + IRCCommand::access = accessLevel; +} + +void IRCCommand::setAccessLevel(int type, int accessLevel) +{ + IRCCommand::TypeAccessPair *pair = new IRCCommand::TypeAccessPair(); + pair->type = type; + pair->access = accessLevel; + IRCCommand::types.add(pair); +} + +void IRCCommand::setAccessLevel(const Jupiter::ReadableString &channel, int accessLevel) +{ + IRCCommand::ChannelAccessPair *pair = new IRCCommand::ChannelAccessPair(); + pair->channel = channel; + pair->access = accessLevel; + IRCCommand::channels.add(pair); +} \ No newline at end of file diff --git a/Bot/IRC_Command.h b/Bot/IRC_Command.h new file mode 100644 index 0000000..209d1af --- /dev/null +++ b/Bot/IRC_Command.h @@ -0,0 +1,197 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _IRC_COMMAND_H_HEADER +#define _IRC_COMMAND_H_HEADER + +/** +* @file IRC_Command.h +* @brief Provides an extendable command system specialized for IRC chat-based commands. +*/ + +#include "Jupiter/Command.h" +#include "Jupiter/IRC_Client.h" +#include "Jupiter/ArrayList.h" +#include "Jupiter/String.h" +#include "ServerManager.h" +#include "Jupiter_Bot.h" + +class IRC_Bot; +class IRCCommand; + +/* +* Initial access level is always 0. Change this using setAccessLevel() +* There are no default triggers. Add triggers using addTrigger(trigger) +* When your command is triggered, trigger(channel, nick, parameters) will be called. +* You must provide command-specific help for your command, through getHelp(). +* The first trigger added is the trigger which is displayed to the user in the help command. +*/ + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +/** IRC Master Command List */ +JUPITER_BOT_API extern Jupiter::ArrayList *IRCMasterCommandList; + +/** +* @brief Provides the basis for IRC commands. +* Note: This will likely be moved to a separate file in the future. +*/ +class JUPITER_BOT_API IRCCommand : public Jupiter::Command +{ +public: + /** + * @brief Fetches a command's default access level. + * + * @return Default access level. + */ + int getAccessLevel(); + + /** + * @brief Fetches a command's access level for a channel type. + * + * @return Access level. + */ + int getAccessLevel(int type); + + /** + * @brief Fetches a command's access level for a specific channel by name. + * + * @return Access level. + */ + int getAccessLevel(const Jupiter::ReadableString &channel); + + /** + * @brief Fetches a command's access level for a specific channel. + * + * @return Access level. + */ + int getAccessLevel(Jupiter::IRC::Client::Channel *channel); + + /** + * @brief Sets a command's default access level. + * + * @param accessLevel Access level. + */ + void setAccessLevel(int accessLevel); + + /** + * @brief Sets a command's access level for a channel type. + * + * @param type Type of channel for which to set access. + * @param accessLevel Access level. + */ + void setAccessLevel(int type, int accessLevel); + + /** + * @brief Sets a command's access level for a specific channel by name. + * + * @param channel Specific channel name for which to set access. + * @param accessLevel Access level. + */ + void setAccessLevel(const Jupiter::ReadableString &channel, int accessLevel); + + /** + * @brief Called when the command is to be executed. + * + * @param source IRC Server from which the command is being executed. + * @param channel Name of the channel from which the message originated. + * @param nick Nickname of the user who executed the command. + * @param parameters Parameters specified with the command. + */ + virtual void trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) = 0; + + /** + * @brief Called when the command is intially created. Define triggers and access levels here. + */ + virtual void create() = 0; + + /** + * @brief Creates a copy of a command. + * Note: This is primarily for internal usage. + * + * @return Copy of the command. + */ + virtual IRCCommand *copy() = 0; + + /** + * @brief Default constructor for the IRC command class. + * Generally, this is called only for master commands. + */ + IRCCommand(); + + /** + * @brief Copy constructor for the IRC command class. + * Generally, this is called only for slave commands. + */ + IRCCommand(const IRCCommand &command); + + /** + * @brief Destructor for the IRC command class. + */ + virtual ~IRCCommand(); + + /** Private members */ +private: + int access; /** Default access level */ + + struct TypeAccessPair + { + int type; + int access; + }; + Jupiter::ArrayList types; /** Access levels for channel types */ + + struct ChannelAccessPair + { + Jupiter::StringS channel; + int access; + }; + Jupiter::ArrayList channels; /** Access levels for specific channels */ +}; + +/** IRC Command Macros */ + +/** Defines the core of an IRC command's declaration. This should be included in every IRC command. */ +#define BASE_IRC_COMMAND(CLASS) \ + public: \ + void trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters); \ + const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters); \ + CLASS *copy(); \ + void create(); \ + CLASS() { this->create(); if (serverManager != nullptr) serverManager->addCommand(this); } + +/** Expands to become the entire declaration for an IRC command. In most cases, this will be sufficient. */ +#define GENERIC_IRC_COMMAND(CLASS) \ +class CLASS : public IRCCommand { \ + BASE_IRC_COMMAND(CLASS) \ + CLASS(CLASS &c) : IRCCommand(c) { this->create(); } }; + +/** Instantiates an IRC command, and also defines neccessary core functions for compatibility. */ +#define IRC_COMMAND_INIT(CLASS) \ + CLASS CLASS ## _instance; \ + CLASS *CLASS::copy() { return new CLASS(*this); } + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _IRC_COMMAND_H_HEADER \ No newline at end of file diff --git a/Bot/Jupiter_Bot.h b/Bot/Jupiter_Bot.h new file mode 100644 index 0000000..4e360de --- /dev/null +++ b/Bot/Jupiter_Bot.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined JUPITER_BOT_API + +/** +* @file Jupiter_Bot.h +* @brief Defines JUPITER_BOT_API. +* On anything other than Windows, JUPITER_BOT_API is defined as nothing, to prevent compiler errors. +*/ + +#if defined _WIN32 + +#if defined JUPITER_BOT_EXPORTS +#define JUPITER_BOT_API __declspec(dllexport) +#else // JUPITER_BOT_EXPORTS +#define JUPITER_BOT_API __declspec(dllimport) +#endif // JUPITER_BOT_EXPORTS + +#else // _WIN32 +#define JUPITER_BOT_API +#endif // _WIN32 + +#endif // JUPITER_BOT_API \ No newline at end of file diff --git a/Bot/Main.cpp b/Bot/Main.cpp new file mode 100644 index 0000000..a9c9991 --- /dev/null +++ b/Bot/Main.cpp @@ -0,0 +1,154 @@ +/** + * Copyright (C) 2013-2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include +#include +#include +#include +#include +#include "Jupiter/Functions.h" +#include "Jupiter/INIFile.h" +#include "Jupiter/Queue.h" +#include "Jupiter/Socket.h" +#include "Jupiter/Plugin.h" +#include "Jupiter/Timer.h" +#include "IRC_Bot.h" +#include "ServerManager.h" +#include "Console_Command.h" +#include "IRC_Command.h" + +Jupiter::Queue inputQueue; + +void onTerminate() +{ + puts("Terminate signal received..."); +} + +void onExit() +{ + puts("Exit signal received; Cleaning up..."); + Jupiter::Socket::cleanup(); + puts("Clean-up complete. Closing..."); +} + +void inputLoop() +{ + const size_t inputSize = 1024; + char *input = new char[inputSize]; + while (ftell(stdin) != -1) // This can be expanded later to check for EBADF specifically. + { + fgets(input, inputSize, stdin); + input[strcspn(input, "\r\n")] = 0; + inputQueue.enqueue(input); + } + delete[] input; +} + +int main(int argc, const char **args) +{ + atexit(onExit); + std::set_terminate(onTerminate); + std::thread inputThread(inputLoop); + srand((unsigned int) time(0)); + puts(Jupiter::copyright); + const char *configFileName = CONFIG_INI; + + for (int i = 1; i < argc; i++) + { + if (streqli(args[i], "-help")) + { + puts("Help coming soon, to a theatre near you!"); + return 0; + } + else if (streqli(args[i], "-config") && ++i < argc) configFileName = args[i]; + else if (streqli(args[i], "-pluginsdir") && ++i < argc) Jupiter::setPluginDirectory(Jupiter::ReferenceString(args[i])); + else if (streqli(args[i], "-configFormat") && ++i < argc) puts("Feature not yet supported!"); + else printf("Warning: Unknown command line argument \"%s\" specified. Ignoring...", args[i]); + } + + puts("Loading config file..."); + if (!Jupiter::IRC::Client::Config->readFile(configFileName)) + { + puts("Unable to read config file. Closing..."); + exit(0); + } + + fputs("Config loaded. ", stdout); + const Jupiter::ReadableString &pDir = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("Config"), STRING_LITERAL_AS_REFERENCE("PluginsDirectory")); + if (pDir.isEmpty() == false) + { + Jupiter::setPluginDirectory(pDir); + printf("Plugins will be loaded from \"%.*s\"." ENDL, pDir.size(), pDir.ptr()); + } + + puts("Loading plugins..."); + const Jupiter::ReadableString &pluginList = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("Config"), STRING_LITERAL_AS_REFERENCE("Plugins")); + if (pluginList.isEmpty()) + puts("No plugins to load!"); + else + { + unsigned int nPlugins = pluginList.wordCount(WHITESPACE); + printf("Attempting to load %u plugins..." ENDL, nPlugins); + for (unsigned int i = 0; i < nPlugins; i++) + { + Jupiter::ReferenceString plugin = Jupiter::ReferenceString::getWord(pluginList, i, WHITESPACE); + if (Jupiter::loadPlugin(plugin) == nullptr) fprintf(stderr, "WARNING: Failed to load plugin \"%.*s\"!" ENDL, plugin.size(), plugin.ptr()); + else printf("\"%.*s\" loaded successfully." ENDL, plugin.size(), plugin.ptr()); + } + } + + if (consoleCommands->size() > 0) + printf("%u Console Commands have been initialized%s" ENDL, consoleCommands->size(), getConsoleCommand(STRING_LITERAL_AS_REFERENCE("help")) == nullptr ? "." : "; type \"help\" for more information."); + if (IRCMasterCommandList->size() > 0) + printf("%u IRC Commands have been loaded into the master list." ENDL, IRCMasterCommandList->size()); + + puts("Retreiving network list..."); + const Jupiter::ReadableString &serverList = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("Config"), STRING_LITERAL_AS_REFERENCE("Servers")); + if (serverList == nullptr) + puts("Unable to find network list."); + else + { + unsigned int nServers = serverList.wordCount(WHITESPACE); + printf("Attempting to connect to %u servers..." ENDL, nServers); + for (unsigned int i = 0; i < nServers; i++) + serverManager->addServer(Jupiter::ReferenceString::getWord(serverList, i, WHITESPACE)); + } + + puts("Sockets established."); + while (1) + { + for (size_t i = 0; i < Jupiter::plugins->size(); i++) + if (Jupiter::plugins->get(i)->think() != 0) + Jupiter::freePlugin(i); + Jupiter_checkTimers(); + serverManager->think(); + Jupiter::ReferenceString input = (const char *)inputQueue.dequeue(); + if (input != nullptr) + { + Jupiter::ReferenceString command = input.getWord(0, WHITESPACE); + + ConsoleCommand *cmd = getConsoleCommand(command); + if (cmd != nullptr) + cmd->trigger(input.gotoWord(1, WHITESPACE)); + else + printf("Error: Command \"%.*s\" not found." ENDL, command.size(), command.ptr()); + } + std::this_thread::sleep_for((std::chrono::milliseconds(1))); + } + return 0; +} \ No newline at end of file diff --git a/Bot/ServerManager.cpp b/Bot/ServerManager.cpp new file mode 100644 index 0000000..7bdb44b --- /dev/null +++ b/Bot/ServerManager.cpp @@ -0,0 +1,154 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Jupiter/Functions.h" +#include "ServerManager.h" +#include "IRC_Bot.h" +#include "IRC_Command.h" + +ServerManager _serverManager; +ServerManager *serverManager = &_serverManager; + +int ServerManager::think() +{ + for (size_t i = 0; i < ServerManager::servers.size(); i++) + { + IRC_Bot *server = ServerManager::servers.get(i); + if (server->think() != 0) delete ServerManager::servers.remove(i); + } + return ServerManager::servers.size() != 0; +} + +size_t ServerManager::addCommand(IRCCommand *command) +{ + for (size_t i = 0; i != ServerManager::servers.size(); i++) + { + IRC_Bot *server = ServerManager::servers.get(i); + server->addCommand(command->copy()); + } + return ServerManager::servers.size(); +} + +size_t ServerManager::removeCommand(IRCCommand *command) +{ + size_t r = 0; + for (size_t i = 0; i != ServerManager::servers.size(); i++) + { + IRC_Bot *server = ServerManager::servers.get(i); + if (server->freeCommand(command->getTrigger())) r++; + } + return r; +} + +size_t ServerManager::removeCommand(const Jupiter::ReadableString &command) +{ + size_t r = 0; + for (size_t i = 0; i != ServerManager::servers.size(); i++) + { + IRC_Bot *server = ServerManager::servers.get(i); + if (server->freeCommand(command)) r++; + } + return r; +} + +size_t ServerManager::syncCommands() +{ + for (size_t i = 0; i != ServerManager::servers.size(); i++) + { + IRC_Bot *server = ServerManager::servers.get(i); + server->setCommandAccessLevels(); + } + return ServerManager::servers.size(); +} + +IRC_Bot *ServerManager::getServer(const Jupiter::ReadableString &serverConfig) +{ + for (size_t i = 0; i != ServerManager::servers.size(); i++) + { + IRC_Bot *server = ServerManager::servers.get(i); + if (server->getConfigSection().equalsi(serverConfig)) return server; + } + return nullptr; +} + +IRC_Bot *ServerManager::getServer(size_t serverIndex) +{ + if (serverIndex < ServerManager::servers.size()) return ServerManager::servers.get(serverIndex); + return nullptr; +} + +bool ServerManager::addServer(const Jupiter::ReadableString &serverConfig) +{ + IRC_Bot *server = new IRC_Bot(serverConfig); + if (server->connect() == true) + { + ServerManager::servers.add(server); + return true; + } + else + { + delete server; + return false; + } +} + +bool ServerManager::freeServer(size_t serverIndex) +{ + if (serverIndex < ServerManager::servers.size()) + { + delete ServerManager::servers.remove(serverIndex); + return true; + } + return false; +} + +bool ServerManager::freeServer(IRC_Bot *server) +{ + for (size_t i = 0; i != ServerManager::servers.size(); i++) + { + if (ServerManager::servers.get(i) == server) + { + delete ServerManager::servers.remove(i); + return true; + } + } + return false; +} + +bool ServerManager::freeServer(const Jupiter::ReadableString &serverConfig) +{ + for (size_t i = 0; i != ServerManager::servers.size(); i++) + { + IRC_Bot *server = ServerManager::servers.get(i); + if (server->getConfigSection().equalsi(serverConfig)) + { + delete ServerManager::servers.remove(i); + return true; + } + } + return false; +} + +size_t ServerManager::size() +{ + return ServerManager::servers.size(); +} + +ServerManager::~ServerManager() +{ + ServerManager::servers.emptyAndDelete(); +} \ No newline at end of file diff --git a/Bot/ServerManager.h b/Bot/ServerManager.h new file mode 100644 index 0000000..8644383 --- /dev/null +++ b/Bot/ServerManager.h @@ -0,0 +1,157 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _SERVERMANAGER_H_HEADER +#define _SERVERMANAGER_H_HEADER + +/** + * @file ServerManager.h + * @brief Provides a system for controlling and affecting multiple IRC connections simultaneously. + */ + +#include "Jupiter_Bot.h" +#include "Jupiter/Thinker.h" +#include "Jupiter/ArrayList.h" +#include "Jupiter/Readable_String.h" + +/** Forward declarations */ +class IRC_Bot; +class IRCCommand; + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +/** +* @brief Provides a system for controlling and affecting multiple IRC connections simultaneously. +*/ +class JUPITER_BOT_API ServerManager : public Jupiter::Thinker +{ +public: + /** + * @brief Calls think() on all of the managed connections. + * + * @return false if there are still active connections, true otherwise. + */ + int think(); + + /** + * @brief Adds a copy of a command to each managed server. + * + * @param command Command to copy to each server. + * @return Number of servers copied to. + */ + size_t addCommand(IRCCommand *command); + + /** + * @brief Removes any command which matches an input command's primary trigger. + * + * @param command Command to get the trigger of. + * @return Number of servers which had a command removed. + */ + size_t removeCommand(IRCCommand *command); + + /** + * @brief Removes any command which matches a trigger. + * + * @param command Trigger to match against. + * @return Number of servers which had a command removed. + */ + size_t removeCommand(const Jupiter::ReadableString &command); + + /** + * @brief Syncs command access levels from the configuration file. + * + * @return Number of servers sync'd. + */ + size_t syncCommands(); + + /** + * @brief Fetches a server based on its configuration section + * + * @param serverConfig Configuration section to match against. + * @return Pointer to a matching server instance on success, nullptr otherwise. + */ + IRC_Bot *getServer(const Jupiter::ReadableString &serverConfig); + + /** + * @brief Fetches a server based on its index. + * + * @param index Index of the server to fetch. + * @return Pointer to a server on success, nullptr otherwise. + */ + IRC_Bot *getServer(size_t index); + + /** + * @brief Adds a server based on its configuration section to the list. + * + * @return True if a socket connection was successfully established, false otherwise. + */ + bool addServer(const Jupiter::ReadableString &serverConfig); + + /** + * @brief Removes a server from the manager, based on its index. + * + * @param index Index of the server to remove. + * @return True if a server was removed, false otherwise. + */ + bool freeServer(size_t index); + + /** + * @brief Removes a server from the manager, based on its data. + * + * @param server Data of the server to remove. + * @return True if a server was removed, false otherwise. + */ + bool freeServer(IRC_Bot *server); + + /** + * @brief Removes a server from the manager, based on its configuration section. + * + * @param serverConfig Configuration section of the server to remove. + * @return True if a server was removed, false otherwise. + */ + bool freeServer(const Jupiter::ReadableString &serverConfig); + + /** + * @brief Returns the number of servers in the list. + * + * @return Number of servers in the list. + */ + size_t size(); + + /** + * Destructor for the ServerManager class. + */ + virtual ~ServerManager(); + +private: + /** Underlying ArrayList of servers */ + Jupiter::ArrayList servers; +}; + +/** Pointer to an instance of the server manager. Note: DO NOT DELETE OR FREE THIS POINTER. */ +JUPITER_BOT_API extern ServerManager *serverManager; + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _SERVERMANAGER_H_HEADER \ No newline at end of file diff --git a/CoreCommands/CoreCommands.cpp b/CoreCommands/CoreCommands.cpp new file mode 100644 index 0000000..1441c53 --- /dev/null +++ b/CoreCommands/CoreCommands.cpp @@ -0,0 +1,228 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/INIFile.h" +#include "Jupiter/Functions.h" +#include "Jupiter/ArrayList.h" +#include "CoreCommands.h" +#include "IRC_Bot.h" + +// Help Console Command + +HelpConsoleCommand::HelpConsoleCommand() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("help")); +} + +void HelpConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) +{ + if (parameters.isEmpty()) + { + fputs("Supported commands:", stdout); + for (size_t i = 0; i != consoleCommands->size(); i++) + { + fputc(' ', stdout); + consoleCommands->get(i)->getTrigger().print(stdout); + } + printf(ENDL "%s - %s" ENDL, Jupiter::version, Jupiter::copyright); + puts("For command-specific help, use: help "); + } + else + { + Jupiter::ReferenceString command = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); + ConsoleCommand *cmd = getConsoleCommand(command); + if (cmd != nullptr) + cmd->getHelp(Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE)).println(stdout); + else + printf("Error: Command \"%.*s\" not found." ENDL, command.size(), command.ptr()); + } +} + +const Jupiter::ReadableString &HelpConsoleCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Lists commands, or sends command-specific help. Syntax: help [command]"); + return defaultHelp; +} + +CONSOLE_COMMAND_INIT(HelpConsoleCommand) + +// Version Console Command + +VersionConsoleCommand::VersionConsoleCommand() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("version")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("versioninfo")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("copyright")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("copyrightinfo")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("client")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("clientinfo")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("info")); +} + +void VersionConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) +{ + printf("Version: %s" ENDL "%s" ENDL, Jupiter::version, Jupiter::copyright); +} + +const Jupiter::ReadableString &VersionConsoleCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays version and copyright information"); + return defaultHelp; +} + +CONSOLE_COMMAND_INIT(VersionConsoleCommand) + +// Help Command. + +void HelpIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("help")); +} + +void HelpIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + int cIndex = source->getChannelIndex(channel); + if (cIndex >= 0) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(cIndex); + int access = source->getAccessLevel(channel, nick); + if (parameters == nullptr) + { + for (int i = 0; i <= access; i++) + { + Jupiter::ArrayList cmds = source->getAccessCommands(chan, i); + if (cmds.size() != 0) + { + Jupiter::StringL &triggers = source->getTriggers(cmds); + if (triggers.size() >= 0) + 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 ")); + } + else + { + IRCCommand *cmd = source->getCommand(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE)); + if (cmd) + { + if (access >= cmd->getAccessLevel(chan)) + 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.")); + } + } +} + +const Jupiter::ReadableString &HelpIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Syntax: help [command]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(HelpIRCCommand) + +// Version IRC Command + +void VersionIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("version")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("versioninfo")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("copyright")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("copyrightinfo")); +} + +void VersionIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + source->sendMessage(channel, Jupiter::StringS::Format("Version: %s", Jupiter::version)); + source->sendMessage(channel, Jupiter::ReferenceString(Jupiter::copyright)); +} + +const Jupiter::ReadableString &VersionIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays version and copyright information. Syntax: version"); + return defaultHelp; +} + +IRC_COMMAND_INIT(VersionIRCCommand) + +// Sync Command + +void SyncIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("sync")); + this->setAccessLevel(4); +} + +void SyncIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (source->Config == nullptr) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Unable to find Config data.")); + else + { + bool r; + if (parameters.size() != 0) + r = source->Config->sync(parameters); + else r = source->Config->sync(); + if (r) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Config data synced to file successfully.")); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Unable to sync Config data.")); + } +} + +const Jupiter::ReadableString &SyncIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Syncs the configuration data to a file. Syntax: sync [file]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(SyncIRCCommand) + +// Rehash Command + +void RehashIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rehash")); + this->setAccessLevel(4); +} + +void RehashIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (source->Config == nullptr) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Unable to find Config data.")); + else + { + unsigned int r = Jupiter::rehash(); + if (r == 0) + source->sendMessage(channel, Jupiter::StringS::Format("All %u objects were successfully rehashed.", Jupiter::getRehashableCount())); + else source->sendMessage(channel, Jupiter::StringS::Format("%u of %u objects failed to successfully rehash.", r, Jupiter::getRehashableCount())); + } +} + +const Jupiter::ReadableString &RehashIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Rehashes configuration data from a file. Syntax: rehash [file]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(RehashIRCCommand) + +// Plugin instantiation and entry point. +CoreCommandsPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/CoreCommands/CoreCommands.h b/CoreCommands/CoreCommands.h new file mode 100644 index 0000000..b847192 --- /dev/null +++ b/CoreCommands/CoreCommands.h @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _CORECOMMANDS_H_HEADER +#define _CORECOMMANDS_H_HEADER + +#include "Jupiter/Plugin.h" +#include "Console_Command.h" +#include "IRC_Command.h" + +class CoreCommandsPlugin : public Jupiter::Plugin +{ +public: + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "CoreCommands"); +}; + +GENERIC_CONSOLE_COMMAND(HelpConsoleCommand) +GENERIC_CONSOLE_COMMAND(VersionConsoleCommand) +GENERIC_IRC_COMMAND(HelpIRCCommand) +GENERIC_IRC_COMMAND(VersionIRCCommand) +GENERIC_IRC_COMMAND(SyncIRCCommand) +GENERIC_IRC_COMMAND(RehashIRCCommand) + +#endif // _CORECOMMANDS_H_HEADER \ No newline at end of file diff --git a/CoreCommands/CoreCommands.vcxproj b/CoreCommands/CoreCommands.vcxproj new file mode 100644 index 0000000..9412988 --- /dev/null +++ b/CoreCommands/CoreCommands.vcxproj @@ -0,0 +1,85 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {55F71101-B302-4345-9F9F-3055E805422A} + PluginExample + CoreCommands + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CoreCommands/CoreCommands.vcxproj.filters b/CoreCommands/CoreCommands.vcxproj.filters new file mode 100644 index 0000000..200b773 --- /dev/null +++ b/CoreCommands/CoreCommands.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/ExtraCommands/ExtraCommands.cpp b/ExtraCommands/ExtraCommands.cpp new file mode 100644 index 0000000..04d8750 --- /dev/null +++ b/ExtraCommands/ExtraCommands.cpp @@ -0,0 +1,287 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/Functions.h" +#include "ExtraCommands.h" +#include "IRC_Bot.h" + +// Raw Console Command + +RawConsoleCommand::RawConsoleCommand() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("raw")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("sendraw")); +} + +void RawConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) +{ + if (parameters.wordCount(WHITESPACE) < 2) + puts("Error: Too few parameters."); + else + { + Jupiter::ReferenceString network = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); + Jupiter::ReferenceString message = Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE); + size_t total = 0; + for (size_t i = 0; i < serverManager->size(); i++) + { + IRC_Bot *server = serverManager->getServer(i); + if (server->getConfigSection().matchi(network)) + { + server->send(message); + total++; + } + } + printf("%u packets sent." ENDL, total); + } +} + +const Jupiter::ReadableString &RawConsoleCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Syntax: raw "); + return defaultHelp; +} + +CONSOLE_COMMAND_INIT(RawConsoleCommand) + +// Message Console Command + +MessageConsoleCommand::MessageConsoleCommand() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("ircmsg")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("message")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("privmsg")); +} + +void MessageConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) +{ + if (parameters.wordCount(WHITESPACE) < 3) + puts("Error: Too few parameters."); + else + { + Jupiter::ReferenceString network = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); + Jupiter::ReferenceString channel = Jupiter::ReferenceString::getWord(parameters, 1, WHITESPACE); + Jupiter::ReferenceString message = Jupiter::ReferenceString::gotoWord(parameters, 2, WHITESPACE); + + size_t total = 0; + for (size_t i = 0; i < serverManager->size(); i++) + { + IRC_Bot *server = serverManager->getServer(i); + if (server->getConfigSection().matchi(network)) + { + server->sendMessage(channel, message); + total++; + } + } + printf("%u messages sent." ENDL, total); + } +} + +const Jupiter::ReadableString &MessageConsoleCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message to an IRC user/channel, on a specified network (accepts wildcards). Syntax: msg "); + return defaultHelp; +} + +CONSOLE_COMMAND_INIT(MessageConsoleCommand) + +// Join Command + +void JoinIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("Join")); + this->setAccessLevel(3); +} + +void JoinIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + if (parameters.wordCount(WHITESPACE) == 1) + source->joinChannel(parameters); + else source->joinChannel(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE), Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE)); + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: join [password]")); +} + +const Jupiter::ReadableString &JoinIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Joins a channel. Syntax: join "); + return defaultHelp; +} + +IRC_COMMAND_INIT(JoinIRCCommand) + +// Part Command + +void PartIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("Part")); + this->setAccessLevel(3); +} + +void PartIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + if (parameters.wordCount(WHITESPACE) == 1) + source->partChannel(parameters); + else source->partChannel(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE), Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE)); + } + else source->partChannel(channel); +} + +const Jupiter::ReadableString &PartIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Parts from a channel. Syntax: part [channel=here] [message=empty]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(PartIRCCommand) + +// Info Command + +void InfoIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("info")); + this->setAccessLevel(4); +} + +void InfoIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + Jupiter::String msg; + msg.format("Outputing data for %u channels...", source->getChannelCount()); + source->sendMessage(channel, msg); + for (unsigned int a = 0; a < source->getChannelCount(); a++) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(a); + if (chan != nullptr) + { + msg.format("Channel %.*s - Type: %d", chan->getName().size(), chan->getName().ptr(), chan->getType()); + source->sendMessage(channel, msg); + for (unsigned int b = 0; b < chan->getUserCount(); b++) + { + Jupiter::IRC::Client::Channel::User *chanUser = chan->getUser(b); + Jupiter::IRC::Client::User *user = chanUser->getUser(); + msg.format("PRIVMSG %.*s :User %.*s!%.*s@%.*s (prefix: %c) of channel %.*s (of %u shared)" ENDL, channel.size(), channel.ptr(), user->getNickname().size(), user->getNickname().ptr(), user->getUsername().size(), user->getUsername().ptr(), user->getHostname().size(), user->getHostname().ptr(), chan->getUserPrefix(b) ? chan->getUserPrefix(b) : ' ', chan->getName().size(), chan->getName().ptr(), user->getChannelCount()); + source->send(msg); + } + } + } +} + +const Jupiter::ReadableString &InfoIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "TEMPORARY COMMAND - Spits out some info about channels. Syntax: info"); + return defaultHelp; +} + +IRC_COMMAND_INIT(InfoIRCCommand) + +// Exit command + +void ExitIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("exit")); + this->setAccessLevel(5); +} + +void ExitIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Bye!")); + exit(0); +} + +const Jupiter::ReadableString &ExitIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Closes the bot's application process. Syntax: exit"); + return defaultHelp; +} + +IRC_COMMAND_INIT(ExitIRCCommand) + +// IRC Connect command + +void IRCConnectIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("IRCConnect")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("IRCReconnect")); + this->setAccessLevel(5); +} + +void IRCConnectIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters == nullptr) + source->disconnect(STRING_LITERAL_AS_REFERENCE("Connect command used; reconnecting..."), false); + else + { + IRC_Bot *server = serverManager->getServer(parameters); + if (server != nullptr) + { + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Warning: Server already exists. Severing connection...")); + server->disconnect(true); + } + if (serverManager->addServer(parameters)) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Connection successfully established; server added to server list.")); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Unable to find configuration settings for server, or connection refused.")); + } +} + +const Jupiter::ReadableString &IRCConnectIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Connects/reconnects to an IRC server, based on config entry. Syntax: IRCConnect [server=here]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(IRCConnectIRCCommand) + +// IRC Disconnect command + +void IRCDisconnectIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("IRCDisconnect")); + this->setAccessLevel(5); +} + +void IRCDisconnectIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.isEmpty()) + source->disconnect(STRING_LITERAL_AS_REFERENCE("Disconnect command used"), true); + else + { + IRC_Bot *server = serverManager->getServer(parameters); + if (server == nullptr) + source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Server not found.")); + else server->disconnect(STRING_LITERAL_AS_REFERENCE("Disconnect command used remotely"), true); + } +} + +const Jupiter::ReadableString &IRCDisconnectIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Disconnects from an IRC server, based on config entry. Syntax: IRCDisconnect [server=here]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(IRCDisconnectIRCCommand) + +// Plugin instantiation and entry point. +FunCommandsPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/ExtraCommands/ExtraCommands.h b/ExtraCommands/ExtraCommands.h new file mode 100644 index 0000000..08a80d2 --- /dev/null +++ b/ExtraCommands/ExtraCommands.h @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _FUNCOMMANDS_H_HEADER +#define _FUNCOMMANDS_H_HEADER + +#include "Jupiter/Plugin.h" +#include "Console_Command.h" +#include "IRC_Command.h" + +class FunCommandsPlugin : public Jupiter::Plugin +{ +public: + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "ExtraCommands"); +}; + +GENERIC_CONSOLE_COMMAND(RawConsoleCommand) +GENERIC_CONSOLE_COMMAND(MessageConsoleCommand) +GENERIC_IRC_COMMAND(JoinIRCCommand) +GENERIC_IRC_COMMAND(PartIRCCommand) +GENERIC_IRC_COMMAND(InfoIRCCommand) +GENERIC_IRC_COMMAND(ExitIRCCommand) +GENERIC_IRC_COMMAND(IRCConnectIRCCommand) +GENERIC_IRC_COMMAND(IRCDisconnectIRCCommand) + +#endif // _EXTRACOMMANDS_H_HEADER \ No newline at end of file diff --git a/ExtraCommands/ExtraCommands.vcxproj b/ExtraCommands/ExtraCommands.vcxproj new file mode 100644 index 0000000..7456408 --- /dev/null +++ b/ExtraCommands/ExtraCommands.vcxproj @@ -0,0 +1,84 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {85874531-681D-4F44-8A84-C8E939DA3FCB} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExtraCommands/ExtraCommands.vcxproj.filters b/ExtraCommands/ExtraCommands.vcxproj.filters new file mode 100644 index 0000000..c81bd10 --- /dev/null +++ b/ExtraCommands/ExtraCommands.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/FunCommands/FunCommands.cpp b/FunCommands/FunCommands.cpp new file mode 100644 index 0000000..21acab8 --- /dev/null +++ b/FunCommands/FunCommands.cpp @@ -0,0 +1,169 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/Functions.h" +#include "Jupiter/Socket.h" +#include "Jupiter/CString.h" +#include "FunCommands.h" +#include "IRC_Bot.h" + +// 8ball + +void EightBallIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("8ball")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("8balls")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("eightBall")); +} + +void EightBallIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + Jupiter::StringS msg; + unsigned short r = rand() % 20; + switch (r) + { + case 0: + msg.set("No."); + break; + case 1: + msg.set("Yes."); + break; + case 2: + msg.set("Maybe."); + break; + case 3: + msg.set("Seven."); + break; + case 4: + msg.set("Consider counseling."); + break; + case 5: + msg.set("Look into a realationship. A real one."); + break; + case 6: + msg.set("Quit asking me these deep questions, before I get deeply into you."); + break; + case 7: + msg.set("Fuck you."); + break; + case 8: + msg.set("Fuck me."); + break; + case 9: + msg.set("I'm sorry, I don't bend that way."); + break; + case 10: + msg.format("Hai %.*s ;)", nick.size(), nick.ptr()); + break; + case 11: + msg.format("Let's ban %.*s!", nick.size(), nick.ptr()); + break; + case 12: + msg.format("Sorry %.*s, but your IQ must be at least %d for me to care.", nick.size(), nick.ptr(), rand() % 50); + break; + case 13: + msg.set("Ask me those kind of questions in #Faggots"); + break; + case 14: + msg.set("I don't talk to slut-mongers."); + break; + case 15: + msg.set("I only talk to slut-mongers."); + break; + case 16: + msg.set("Nuclear launch detected."); + break; + case 17: + msg.set("404 - Not found."); + break; + case 18: + msg.set("I hurr u liek mudkipz?"); + break; + case 19: + msg.set("Walk this way, babycakes ;)"); + break; + default: + msg.set("Nothingness. You suck. Go rot."); + break; + } + source->sendMessage(channel, msg); +} + +const Jupiter::ReadableString &EightBallIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Accurately answers your question 60% of the time, EVERY time. Syntax: 8ball [question]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(EightBallIRCCommand) + +// Resolve Command + +void ResolveIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("resolve")); +} + +void ResolveIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + unsigned int count = parameters.wordCount(WHITESPACE); + if (count > 1) + { + Jupiter::ReferenceString command = Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE); + if (command.equalsi("hostname") || command.equalsi("host")) + { + Jupiter::ReferenceString resolved = Jupiter::Socket::resolveHostname(Jupiter::CStringS::gotoWord(parameters, 1, WHITESPACE).c_str(), 0); + if (resolved.isEmpty() == false) + source->sendMessage(channel, resolved); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Unable to resolve.")); + } + else if (command.equalsi("ip")) + { + Jupiter::ReferenceString resolved = Jupiter::Socket::resolveAddress(Jupiter::CStringS::gotoWord(parameters, 1, WHITESPACE).c_str(), 0); + if (resolved.isEmpty() == false) + source->sendMessage(channel, resolved); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Unable to resolve.")); + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Invalid type. You can only resolve hostnames and IP addresses.")); + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Too few parameters. Syntax: resolve
")); +} + +const Jupiter::ReadableString &ResolveIRCCommand::getHelp(const Jupiter::ReadableString ¶meters) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Resolves an IP address or hostname. Syntax: resolve
"); + static STRING_LITERAL_AS_NAMED_REFERENCE(hostHelp, "Resolves a hostname to an IP address. Syntax: resolve hostname
"); + static STRING_LITERAL_AS_NAMED_REFERENCE(ipHelp, "Reverse-resolves an IP address to a hostname. Syntax: resolve ip
"); + + if (parameters.equalsi(STRING_LITERAL_AS_REFERENCE("hostname")) || parameters.equalsi(STRING_LITERAL_AS_REFERENCE("host"))) + return hostHelp; + if (parameters.equalsi(STRING_LITERAL_AS_REFERENCE("ip"))) + return ipHelp; + + return defaultHelp; +} + +IRC_COMMAND_INIT(ResolveIRCCommand) + +// Plugin instantiation and entry point. +ExtraCommandsPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/FunCommands/FunCommands.h b/FunCommands/FunCommands.h new file mode 100644 index 0000000..10afa1b --- /dev/null +++ b/FunCommands/FunCommands.h @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _FUNCOMMANDS_H_HEADER +#define _FUNCOMMANDS_H_HEADER + +#include "Jupiter/Plugin.h" +#include "IRC_Command.h" + +class ExtraCommandsPlugin : public Jupiter::Plugin +{ +public: + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "FunCommands"); +}; + +GENERIC_IRC_COMMAND(EightBallIRCCommand) +GENERIC_IRC_COMMAND(ResolveIRCCommand) + +#endif // _FUNCOMMANDS_H_HEADER \ No newline at end of file diff --git a/FunCommands/FunCommands.vcxproj b/FunCommands/FunCommands.vcxproj new file mode 100644 index 0000000..e24bb0f --- /dev/null +++ b/FunCommands/FunCommands.vcxproj @@ -0,0 +1,84 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {80E38D71-CEC5-457F-88EC-24D3097C3470} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/FunCommands/FunCommands.vcxproj.filters b/FunCommands/FunCommands.vcxproj.filters new file mode 100644 index 0000000..d37fcc3 --- /dev/null +++ b/FunCommands/FunCommands.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/Jupiter Bot.sln b/Jupiter Bot.sln new file mode 100644 index 0000000..de02f01 --- /dev/null +++ b/Jupiter Bot.sln @@ -0,0 +1,176 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30110.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Bot", "Bot\Bot.vcxproj", "{C188871B-5F32-4946-B301-24CA2EBB275D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin.Example", "Plugin.Example\Plugin.Example.vcxproj", "{EA2C0100-5CC5-4416-8216-059833CAACE2}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Plugin.Template", "Plugin.Template\Plugin.Template.vcxproj", "{1DD04156-F096-4C41-9E1C-5BFD3234E9FD}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PluginManager", "PluginManager\PluginManager.vcxproj", "{9D82C7EE-4167-4F5A-9764-B2C6B0EB9712}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetJoin", "SetJoin\SetJoin.vcxproj", "{FDBEC4F9-AC8D-4197-BA6C-D042DF218A93}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FunCommands", "FunCommands\FunCommands.vcxproj", "{80E38D71-CEC5-457F-88EC-24D3097C3470}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExtraCommands", "ExtraCommands\ExtraCommands.vcxproj", "{85874531-681D-4F44-8A84-C8E939DA3FCB}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CoreCommands", "CoreCommands\CoreCommands.vcxproj", "{55F71101-B302-4345-9F9F-3055E805422A}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.Core", "RenX.Core\RenX.Core.vcxproj", "{9103DF3D-8B4A-48E5-A6B3-CBE2554630E2}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.Commands", "RenX.Commands\RenX.Commands.vcxproj", "{72B6B5A6-4267-4FED-9F96-917C7974CE25}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.Plugin.Template", "RenX.Plugin.Template\RenX.Plugin.Template.vcxproj", "{6F575493-CF43-43CB-8062-9F3D0722A624}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.Logging", "RenX.Logging\RenX.Logging.vcxproj", "{069D6053-F39A-4418-BAA3-FA8D260C83D1}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.ExcessiveHeadshots", "RenX.ExcessiveHeadshots\RenX.ExcessiveHeadshots.vcxproj", "{0F71052A-A773-4AB5-AE2A-50DBDFB9CF9E}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.ExtraLogging", "RenX.ExtraLogging\RenX.ExtraLogging.vcxproj", "{CEFD949E-BCF2-4EDB-8168-0920924FE2D8}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.Announcements", "RenX.Announcements\RenX.Announcements.vcxproj", "{EF55A6DC-1861-4037-868A-9557ECAEBC27}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{844CF9EF-70F3-449D-ACF3-A70D3501A775}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.Medals", "RenX.Medals\RenX.Medals.vcxproj", "{C295FFC2-8CE5-4387-B237-E4E1B1AB9987}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RenX.SetJoin", "RenX.SetJoin\RenX.SetJoin.vcxproj", "{0489F164-DC8F-433C-8CFA-F7EB2A3356F1}" + ProjectSection(ProjectDependencies) = postProject + {C188871B-5F32-4946-B301-24CA2EBB275D} = {C188871B-5F32-4946-B301-24CA2EBB275D} + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} = {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C188871B-5F32-4946-B301-24CA2EBB275D}.Debug|Win32.ActiveCfg = Release|Win32 + {C188871B-5F32-4946-B301-24CA2EBB275D}.Debug|Win32.Build.0 = Release|Win32 + {C188871B-5F32-4946-B301-24CA2EBB275D}.Release|Win32.ActiveCfg = Release|Win32 + {C188871B-5F32-4946-B301-24CA2EBB275D}.Release|Win32.Build.0 = Release|Win32 + {EA2C0100-5CC5-4416-8216-059833CAACE2}.Debug|Win32.ActiveCfg = Debug|Win32 + {EA2C0100-5CC5-4416-8216-059833CAACE2}.Debug|Win32.Build.0 = Debug|Win32 + {EA2C0100-5CC5-4416-8216-059833CAACE2}.Release|Win32.ActiveCfg = Release|Win32 + {EA2C0100-5CC5-4416-8216-059833CAACE2}.Release|Win32.Build.0 = Release|Win32 + {1DD04156-F096-4C41-9E1C-5BFD3234E9FD}.Debug|Win32.ActiveCfg = Debug|Win32 + {1DD04156-F096-4C41-9E1C-5BFD3234E9FD}.Debug|Win32.Build.0 = Debug|Win32 + {1DD04156-F096-4C41-9E1C-5BFD3234E9FD}.Release|Win32.ActiveCfg = Release|Win32 + {1DD04156-F096-4C41-9E1C-5BFD3234E9FD}.Release|Win32.Build.0 = Release|Win32 + {9D82C7EE-4167-4F5A-9764-B2C6B0EB9712}.Debug|Win32.ActiveCfg = Debug|Win32 + {9D82C7EE-4167-4F5A-9764-B2C6B0EB9712}.Debug|Win32.Build.0 = Debug|Win32 + {9D82C7EE-4167-4F5A-9764-B2C6B0EB9712}.Release|Win32.ActiveCfg = Release|Win32 + {9D82C7EE-4167-4F5A-9764-B2C6B0EB9712}.Release|Win32.Build.0 = Release|Win32 + {FDBEC4F9-AC8D-4197-BA6C-D042DF218A93}.Debug|Win32.ActiveCfg = Debug|Win32 + {FDBEC4F9-AC8D-4197-BA6C-D042DF218A93}.Debug|Win32.Build.0 = Debug|Win32 + {FDBEC4F9-AC8D-4197-BA6C-D042DF218A93}.Release|Win32.ActiveCfg = Release|Win32 + {FDBEC4F9-AC8D-4197-BA6C-D042DF218A93}.Release|Win32.Build.0 = Release|Win32 + {80E38D71-CEC5-457F-88EC-24D3097C3470}.Debug|Win32.ActiveCfg = Debug|Win32 + {80E38D71-CEC5-457F-88EC-24D3097C3470}.Debug|Win32.Build.0 = Debug|Win32 + {80E38D71-CEC5-457F-88EC-24D3097C3470}.Release|Win32.ActiveCfg = Release|Win32 + {80E38D71-CEC5-457F-88EC-24D3097C3470}.Release|Win32.Build.0 = Release|Win32 + {85874531-681D-4F44-8A84-C8E939DA3FCB}.Debug|Win32.ActiveCfg = Debug|Win32 + {85874531-681D-4F44-8A84-C8E939DA3FCB}.Debug|Win32.Build.0 = Debug|Win32 + {85874531-681D-4F44-8A84-C8E939DA3FCB}.Release|Win32.ActiveCfg = Release|Win32 + {85874531-681D-4F44-8A84-C8E939DA3FCB}.Release|Win32.Build.0 = Release|Win32 + {55F71101-B302-4345-9F9F-3055E805422A}.Debug|Win32.ActiveCfg = Debug|Win32 + {55F71101-B302-4345-9F9F-3055E805422A}.Debug|Win32.Build.0 = Debug|Win32 + {55F71101-B302-4345-9F9F-3055E805422A}.Release|Win32.ActiveCfg = Release|Win32 + {55F71101-B302-4345-9F9F-3055E805422A}.Release|Win32.Build.0 = Release|Win32 + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2}.Debug|Win32.ActiveCfg = Debug|Win32 + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2}.Debug|Win32.Build.0 = Debug|Win32 + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2}.Release|Win32.ActiveCfg = Release|Win32 + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2}.Release|Win32.Build.0 = Release|Win32 + {72B6B5A6-4267-4FED-9F96-917C7974CE25}.Debug|Win32.ActiveCfg = Debug|Win32 + {72B6B5A6-4267-4FED-9F96-917C7974CE25}.Debug|Win32.Build.0 = Debug|Win32 + {72B6B5A6-4267-4FED-9F96-917C7974CE25}.Release|Win32.ActiveCfg = Release|Win32 + {72B6B5A6-4267-4FED-9F96-917C7974CE25}.Release|Win32.Build.0 = Release|Win32 + {6F575493-CF43-43CB-8062-9F3D0722A624}.Debug|Win32.ActiveCfg = Debug|Win32 + {6F575493-CF43-43CB-8062-9F3D0722A624}.Debug|Win32.Build.0 = Debug|Win32 + {6F575493-CF43-43CB-8062-9F3D0722A624}.Release|Win32.ActiveCfg = Release|Win32 + {6F575493-CF43-43CB-8062-9F3D0722A624}.Release|Win32.Build.0 = Release|Win32 + {069D6053-F39A-4418-BAA3-FA8D260C83D1}.Debug|Win32.ActiveCfg = Debug|Win32 + {069D6053-F39A-4418-BAA3-FA8D260C83D1}.Debug|Win32.Build.0 = Debug|Win32 + {069D6053-F39A-4418-BAA3-FA8D260C83D1}.Release|Win32.ActiveCfg = Release|Win32 + {069D6053-F39A-4418-BAA3-FA8D260C83D1}.Release|Win32.Build.0 = Release|Win32 + {0F71052A-A773-4AB5-AE2A-50DBDFB9CF9E}.Debug|Win32.ActiveCfg = Debug|Win32 + {0F71052A-A773-4AB5-AE2A-50DBDFB9CF9E}.Debug|Win32.Build.0 = Debug|Win32 + {0F71052A-A773-4AB5-AE2A-50DBDFB9CF9E}.Release|Win32.ActiveCfg = Release|Win32 + {0F71052A-A773-4AB5-AE2A-50DBDFB9CF9E}.Release|Win32.Build.0 = Release|Win32 + {CEFD949E-BCF2-4EDB-8168-0920924FE2D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {CEFD949E-BCF2-4EDB-8168-0920924FE2D8}.Debug|Win32.Build.0 = Debug|Win32 + {CEFD949E-BCF2-4EDB-8168-0920924FE2D8}.Release|Win32.ActiveCfg = Release|Win32 + {CEFD949E-BCF2-4EDB-8168-0920924FE2D8}.Release|Win32.Build.0 = Release|Win32 + {EF55A6DC-1861-4037-868A-9557ECAEBC27}.Debug|Win32.ActiveCfg = Debug|Win32 + {EF55A6DC-1861-4037-868A-9557ECAEBC27}.Debug|Win32.Build.0 = Debug|Win32 + {EF55A6DC-1861-4037-868A-9557ECAEBC27}.Release|Win32.ActiveCfg = Release|Win32 + {EF55A6DC-1861-4037-868A-9557ECAEBC27}.Release|Win32.Build.0 = Release|Win32 + {C295FFC2-8CE5-4387-B237-E4E1B1AB9987}.Debug|Win32.ActiveCfg = Debug|Win32 + {C295FFC2-8CE5-4387-B237-E4E1B1AB9987}.Debug|Win32.Build.0 = Debug|Win32 + {C295FFC2-8CE5-4387-B237-E4E1B1AB9987}.Release|Win32.ActiveCfg = Release|Win32 + {C295FFC2-8CE5-4387-B237-E4E1B1AB9987}.Release|Win32.Build.0 = Release|Win32 + {0489F164-DC8F-433C-8CFA-F7EB2A3356F1}.Debug|Win32.ActiveCfg = Debug|Win32 + {0489F164-DC8F-433C-8CFA-F7EB2A3356F1}.Debug|Win32.Build.0 = Debug|Win32 + {0489F164-DC8F-433C-8CFA-F7EB2A3356F1}.Release|Win32.ActiveCfg = Release|Win32 + {0489F164-DC8F-433C-8CFA-F7EB2A3356F1}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/MakeRelease.bat b/MakeRelease.bat new file mode 100644 index 0000000..8741cea --- /dev/null +++ b/MakeRelease.bat @@ -0,0 +1,66 @@ +@ECHO OFF +if NOT "%2" == "-scr" ECHO Copyright (C) 2014 Justin James. All rights reserved. +ECHO. + +if "%1" == "/?" GOTO Help +if "%1" == "-help" GOTO Help +if "%1" == "--help" GOTO Help +if "%1" == "-clean" GOTO CleanUp +if "%1" == "-binary" GOTO BinaryCopy +if "%1" == "-source" GOTO SourceCopy +CALL %0 -clean -scr +CALL %0 -binary -scr +CALL %0 -source -scr +if "%1" == "" GOTO Done +GOTO EOF + +:Help: +ECHO This is a convenience script to assist in build release. +ECHO Usage: %0 [-clean/-binary/-source] +ECHO. +ECHO Clean: Deletes any contents from previous builds. +ECHO Binary: Copies and ZIPS the essential binaries to run the applicaiton. +ECHO Source: Copies and ZIPS the source code to run the application. +ECHO. +ECHO If no parameters are given, then all functions will be executed. +ECHO. +ECHO If a parameter other than "-clean", "-binary", or "-source" is given, +ECHO then the program will execute all functions without pausing at the end. +ECHO. +ECHO Program execution order: +ECHO Clean +ECHO Binary +ECHO Source +ECHO. +ECHO Dependencies: +ECHO COPY, ROBOCOPY, DEL, RMDIR, PAUSE, ECHO, GOTO, IF, CALL +GOTO EOF + +:CleanUp: +RMDIR /S /Q "..\Jupiter Bot Binaries" +RMDIR /S /Q "..\Jupiter Bot Source" +DEL /F /Q "..\Jupiter Bot Binaries.zip" +DEL /F /Q "..\Jupiter Bot.zip" +GOTO EOF + +:BinaryCopy: +ROBOCOPY "Release\\" "..\Jupiter Bot Binaries\\" *.dll *.exe ReadMe.txt /S +COPY /Y "Release\Example Config.ini" "..\Jupiter Bot Binaries\Config.ini" +COPY /Y "Release\Translations.ini" "..\Jupiter Bot Binaries\Translations.ini" +"C:\Program Files\WinRAR\WinRAR.exe" a -r "..\Jupiter Bot Binaries.zip" "..\Jupiter Bot Binaries" +GOTO EOF + +:SourceCopy: +ROBOCOPY ".\\" "..\Jupiter Bot Source\\" *.* /S /XD Release +ROBOCOPY "Release\\" "..\Jupiter Bot Source\Release\\" *.dll *.exe ReadMe.txt /S +COPY /Y "Release\Example Config.ini" "..\Jupiter Bot Source\Release\Config.ini" +COPY /Y "Release\Translations.ini" "..\Jupiter Bot Source\Release\Translations.ini" +"C:\Program Files\WinRAR\WinRAR.exe" a -r "..\Jupiter Bot.zip" "..\Jupiter Bot Source" +GOTO EOF + +:Done: +ECHO Operations complete. +PAUSE +GOTO EOF + +:EOF: \ No newline at end of file diff --git a/Plugin.Example/Example.cpp b/Plugin.Example/Example.cpp new file mode 100644 index 0000000..fa66aef --- /dev/null +++ b/Plugin.Example/Example.cpp @@ -0,0 +1,44 @@ +/** + * This file is in the public domain, furnished "as is", without technical + * support, and with no warranty, express or implied, as to its usefulness for + * any purpose. + * + * Written by Justin James + */ + +#include "Example.h" +#include "IRC_Bot.h" + +void ExamplePlugin::OnConnect(Jupiter::IRC::Client *server) +{ + server->sendNotice(STRING_LITERAL_AS_REFERENCE("Agent"), STRING_LITERAL_AS_REFERENCE("Honey, I'm home!")); +} + +// Example IRC Command Implementation + +void ExampleIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("example")); +} + +void ExampleIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("This is an example command!")); +} + +const Jupiter::ReadableString &ExampleIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(helpmsg, "This is just an example command. It takes no parameters!"); + return helpmsg; +} + +IRC_COMMAND_INIT(ExampleIRCCommand) + + +// Plugin instantiation and entry point. +ExamplePlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/Plugin.Example/Example.h b/Plugin.Example/Example.h new file mode 100644 index 0000000..4c81968 --- /dev/null +++ b/Plugin.Example/Example.h @@ -0,0 +1,28 @@ +/** + * This file is in the public domain, furnished "as is", without technical + * support, and with no warranty, express or implied, as to its usefulness for + * any purpose. + * + * Written by Justin James + */ + +#if !defined _EXAMPLE_H_HEADER +#define _EXAMPLE_H_HEADER + +#include "Jupiter/Plugin.h" +#include "IRC_Command.h" + +class ExamplePlugin : public Jupiter::Plugin +{ +public: + void OnConnect(Jupiter::IRC::Client *server); + const Jupiter::ReadableString &getName() override { return this->name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "ExamplePlugin"); +}; + +// Example IRC Command Declaration +GENERIC_IRC_COMMAND(ExampleIRCCommand) + +#endif // _EXAMPLE_H_HEADER \ No newline at end of file diff --git a/Plugin.Example/Plugin.Example.vcxproj b/Plugin.Example/Plugin.Example.vcxproj new file mode 100644 index 0000000..0715b2c --- /dev/null +++ b/Plugin.Example/Plugin.Example.vcxproj @@ -0,0 +1,84 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {EA2C0100-5CC5-4416-8216-059833CAACE2} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugin.Example/Plugin.Example.vcxproj.filters b/Plugin.Example/Plugin.Example.vcxproj.filters new file mode 100644 index 0000000..ab9ee24 --- /dev/null +++ b/Plugin.Example/Plugin.Example.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/Plugin.Template - Copy/Example.cpp b/Plugin.Template - Copy/Example.cpp new file mode 100644 index 0000000..c0d7700 --- /dev/null +++ b/Plugin.Template - Copy/Example.cpp @@ -0,0 +1,11 @@ +#include "Example.h" + + + +// Plugin instantiation and entry point. +TPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/Plugin.Template - Copy/Example.h b/Plugin.Template - Copy/Example.h new file mode 100644 index 0000000..6d2625b --- /dev/null +++ b/Plugin.Template - Copy/Example.h @@ -0,0 +1,11 @@ +#if !defined _EXAMPLE_H_HEADER +#define _EXAMPLE_H_HEADER + +#include "Plugin.h" + +class TPlugin : public Jupiter::Plugin +{ + const char *getName() { return "TemplatePlugin"; } +}; + +#endif // _EXAMPLE_H_HEADER \ No newline at end of file diff --git a/Plugin.Template - Copy/Plugin.Template.vcxproj b/Plugin.Template - Copy/Plugin.Template.vcxproj new file mode 100644 index 0000000..955a247 --- /dev/null +++ b/Plugin.Template - Copy/Plugin.Template.vcxproj @@ -0,0 +1,83 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {1DD04156-F096-4C41-9E1C-5BFD3234E9FD} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugin.Template - Copy/Plugin.Template.vcxproj.filters b/Plugin.Template - Copy/Plugin.Template.vcxproj.filters new file mode 100644 index 0000000..ed05baa --- /dev/null +++ b/Plugin.Template - Copy/Plugin.Template.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/Plugin.Template/Example.cpp b/Plugin.Template/Example.cpp new file mode 100644 index 0000000..63c184b --- /dev/null +++ b/Plugin.Template/Example.cpp @@ -0,0 +1,19 @@ +/** + * This file is in the public domain, furnished "as is", without technical + * support, and with no warranty, express or implied, as to its usefulness for + * any purpose. + * + * Written by Justin James + */ + +#include "Example.h" + + + +// Plugin instantiation and entry point. +TPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/Plugin.Template/Example.h b/Plugin.Template/Example.h new file mode 100644 index 0000000..be72a54 --- /dev/null +++ b/Plugin.Template/Example.h @@ -0,0 +1,24 @@ +/** + * This file is in the public domain, furnished "as is", without technical + * support, and with no warranty, express or implied, as to its usefulness for + * any purpose. + * + * Written by Justin James + */ + +#if !defined _EXAMPLE_H_HEADER +#define _EXAMPLE_H_HEADER + +#include "Jupiter/Plugin.h" +#include "Jupiter/Reference_String.h" + +class TPlugin : public Jupiter::Plugin +{ +public: + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "TemplatePlugin"); +}; + +#endif // _EXAMPLE_H_HEADER \ No newline at end of file diff --git a/Plugin.Template/Plugin.Template.vcxproj b/Plugin.Template/Plugin.Template.vcxproj new file mode 100644 index 0000000..17971d7 --- /dev/null +++ b/Plugin.Template/Plugin.Template.vcxproj @@ -0,0 +1,84 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {1DD04156-F096-4C41-9E1C-5BFD3234E9FD} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Plugin.Template/Plugin.Template.vcxproj.filters b/Plugin.Template/Plugin.Template.vcxproj.filters new file mode 100644 index 0000000..ab9ee24 --- /dev/null +++ b/Plugin.Template/Plugin.Template.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/PluginManager/PluginManager.cpp b/PluginManager/PluginManager.cpp new file mode 100644 index 0000000..4595882 --- /dev/null +++ b/PluginManager/PluginManager.cpp @@ -0,0 +1,172 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/Functions.h" +#include "PluginManager.h" +#include "IRC_Bot.h" + +// Plugin Console Command +PluginConsoleCommand::PluginConsoleCommand() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("plugin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("plugins")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("module")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("modules")); +} + +void PluginConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) +{ + if (parameters.isEmpty() || parameters.matchi("list*")) + { + printf("There are %u plugins loaded." ENDL, Jupiter::plugins->size()); + for (size_t i = 0; i != Jupiter::plugins->size(); i++) Jupiter::plugins->get(i)->getName().println(stdout); + } + else + { + if (parameters.matchi("load *")) + { + if (Jupiter::loadPlugin(Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE)) == nullptr) + puts("Error: Failed to load plugin."); + else + puts("Plugin successfully loaded."); + } + else if (parameters.matchi("unload *")) + { + Jupiter::ReferenceString pluginName = Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE); + if (Jupiter::getPlugin(pluginName) == nullptr) + puts("Error: Plugin does not exist."); + else if (Jupiter::freePlugin(pluginName) == false) + puts("Error: Failed to unload plugin."); + else + puts("Plugin successfully unloaded."); + } + else + puts("Error: Invalid Syntax. Syntax: plugin {[list], , }"); + } +} + +const Jupiter::ReadableString &PluginConsoleCommand::getHelp(const Jupiter::ReadableString ¶meters) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(loadHelp, "Loads a plugin by file name. Do not include a file extension. Syntax: plugin load "); + static STRING_LITERAL_AS_NAMED_REFERENCE(unloadHelp, "Unloads a plugin by name. Syntax: plugin unload "); + static STRING_LITERAL_AS_NAMED_REFERENCE(listHelp, "Lists all of the plugins currently loaded. Syntax: plugin [list]"); + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Manages plugins. Syntax: plugin {[list], , }"); + + if (parameters.equalsi(STRING_LITERAL_AS_REFERENCE("load"))) + return loadHelp; + if (parameters.equalsi(STRING_LITERAL_AS_REFERENCE("unload"))) + return unloadHelp; + if (parameters.equalsi(STRING_LITERAL_AS_REFERENCE("list"))) + return listHelp; + + return defaultHelp; +} + +CONSOLE_COMMAND_INIT(PluginConsoleCommand) + +// Load Plugin + +void LoadPluginIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("loadplugin")); + this->setAccessLevel(5); +} + +void LoadPluginIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters != nullptr) + { + if (Jupiter::getPlugin(parameters) != nullptr) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Plugin already exists. You must first unload the plugin.")); + else + { + if (Jupiter::loadPlugin(parameters) == nullptr) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Failed to load plugin.")); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Plugin successfully loaded.")); + } + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: loadPlugin ")); +} + +const Jupiter::ReadableString &LoadPluginIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Dynamically loads a plugin. Syntax: loadPlugin "); + return defaultHelp; +} + +IRC_COMMAND_INIT(LoadPluginIRCCommand) + +// Free Plugin + +void FreePluginIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("freeplugin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("unloadplugin")); + this->setAccessLevel(5); +} + +void FreePluginIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters != nullptr) + { + if (Jupiter::getPlugin(parameters) == nullptr) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Plugin does not exist.")); + else if (Jupiter::freePlugin(parameters) == false) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Failed to unload plugin.")); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Plugin successfully unloaded.")); + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: freePlugin ")); +} + +const Jupiter::ReadableString &FreePluginIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Dynamically unloads a plugin. Syntax: freePlugin "); + return defaultHelp; +} + +IRC_COMMAND_INIT(FreePluginIRCCommand) + +// List Plugins + +void ListPluginIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("listplugin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("listplugins")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("pluginlist")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("pluginslist")); + this->setAccessLevel(4); +} + +void ListPluginIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + source->sendMessage(channel, Jupiter::StringS::Format("%u plugins loaded:", Jupiter::plugins->size())); + for (size_t i = 0; i != Jupiter::plugins->size(); i++) + source->sendMessage(channel, Jupiter::plugins->get(i)->getName()); +} + +const Jupiter::ReadableString &ListPluginIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Lists the currently loaded plugins. Syntax: pluginlist"); + return defaultHelp; +} + +IRC_COMMAND_INIT(ListPluginIRCCommand) + +// Plugin instantiation and entry point. +PluginManager pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/PluginManager/PluginManager.h b/PluginManager/PluginManager.h new file mode 100644 index 0000000..44ec003 --- /dev/null +++ b/PluginManager/PluginManager.h @@ -0,0 +1,39 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _PLUGINMANAGER_H_HEADER +#define _PLUGINMANAGER_H_HEADER + +#include "Jupiter/Plugin.h" +#include "Console_Command.h" +#include "IRC_Command.h" + +class PluginManager : public Jupiter::Plugin +{ +public: + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "PluginManager"); +}; + +GENERIC_CONSOLE_COMMAND(PluginConsoleCommand) +GENERIC_IRC_COMMAND(LoadPluginIRCCommand) +GENERIC_IRC_COMMAND(FreePluginIRCCommand) +GENERIC_IRC_COMMAND(ListPluginIRCCommand) + +#endif // _PLUGINMANAGER_H_HEADER \ No newline at end of file diff --git a/PluginManager/PluginManager.vcxproj b/PluginManager/PluginManager.vcxproj new file mode 100644 index 0000000..eb4d059 --- /dev/null +++ b/PluginManager/PluginManager.vcxproj @@ -0,0 +1,85 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {9D82C7EE-4167-4F5A-9764-B2C6B0EB9712} + PluginExample + PluginManager + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/PluginManager/PluginManager.vcxproj.filters b/PluginManager/PluginManager.vcxproj.filters new file mode 100644 index 0000000..1e0686a --- /dev/null +++ b/PluginManager/PluginManager.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/Release/Bot.lib b/Release/Bot.lib new file mode 100644 index 0000000000000000000000000000000000000000..5ba44af9ab051abf116f7e496e850b4617df3129 GIT binary patch literal 19582 zcmcIsO>7)R7JhNUCYS`m&q7EDIA9V8i8Hq6$IjpM_$Szj6TmSMi&#wtdq@Tn8+j%X z>;WW{BL@x~I3boZ*X4jXM2G`>Sc&BhCytyrAf%OGzt>gOUHwyC)jgAuUfR?B>V2EXImnKW)$*F2NdcP#UR>~6<@#p1XB6^GH@E=4+_YjSp zB|7yBQT1n{xt|10&Ji({b_%Kt5iuS6SkTnhMAJuzYAZyGxX*NUub{O zh-qfGpxJ{&Op{*UX%0#uAtg&qN&s1IU}g@ z8`^=!FAJLf7P^9tUlMfo6X*##^MxSqD+~Isyt2}4z8JMS1hOHKOQeADWufvS9*E;R>9$V8ef%=nU)5JDvVYe+^au8(G zMH?~;n2U|W$Y2o$Mg$k#o#TNefCgrkz&1UOHZ)5dZtK03Y zcX|_v*|!)DloKyPTTK7-u$IM?)G8L1I4oo-W?+YI$tUURS@>Y-Bu8?fGI-J@=);xL zSbN;8!GgTrbC6D*>nd<#Rn}OS+gDrNtGvK!VIkcQgmjy&1KEmEctFrN-M)IO2#4_D zpmoxwdduKx{e^YJJwMusrso|Nj#4S~?ZWMWEKJHXM_^-?FN7mye9kL_Tq?Ct+zsWh zK|?u?+#Cy6Hal0ad~2dEHtL+tiIl3jw6W1`>xoq~(?dtXC45p#M(%{@Fm_8!O=}py zS6j7@n!I|Rf1P*w{(;iZ{*sHW@eu$swyYhdy;%@)_!+V5x%HZ#9a zM4@70>Thhe)eDBELu0;q!Ci^IWYk-0YsoRfEQ<|N7#7?ch?PDF0Fn2Hz#ruLpAzF7 z-+TN;JQ5ro8+N04J-^+>)|Un+E3td=d?o#Hz1#Um+lxKJ++Eaymzl$N3(+`5Mqc0O zPmoO);U~iWp_8yrX5hve*)X)c#v+(G*`+hE-6vMxayZNwHPLOLbudp8XZh}Zc7=D4 zSns~Oz8Wko!VbY(bZjozIqRG4>l-(NV3{J$K_$743__G$A2GlxxN13r6+YQg57Q}K zPd1P})q=HCvwH7pXZ@{s(1~VmSu6#rt(9?AZ9PFme;g*-a};&QF`{2i5&c{x`Uy3~ zxk;j(C8D7U(Z|P#zMdjFGEKBn!@WhKy{OH8itC3nM7;*lZd?z}5`Bqw@1fnVpzn_3 zZ?yjgKyO0sYp6Z`0J;qsry=hQ?*E48m&b{|h3re<{{(WsK)v)UkLYvA<9g>U)KKS6 z5{;ILz6bBE1)`7e_nvdmqmEiDc)!GT8TubY+YjcU7oNTPJkjr<@6dL~l3!Y;VcJ0t z(17Ko8RW^bkEm z&(dG0N)lnCEv(%;sT%fDYMERav2Npg@dq)?*kkt%UmYCLBa)-2 z4)PvLVB2(#m^vm&>09;+$KN^#Orh-tM>iGv-hT-3VrpxU=<)zIpbIB?Qbl7qUp{x* zB+K9pM%B;eOpGxraek+jRoqiRDPL=ll)RYC9K&XUJ!R3$Q@C4=94#q$_@uAOuLw>#rqD+f-@=$$Bp(fd zrMzNUsV-(PxoIfTI9YWsb9Zu>&Pk%??PxOaY*qHpnr^yx%qq$l5xWlCEK*-fnrhQl zn==+kIXI)N(vLHfU)34&{*L0XSG^@?R>}4Kv?GkexH;B-ryU%AwViq`*J|?o>*e94 zEn8{N?awZ5-GVwLYO?rj8Cz?=e&fpMMe!A9H1P+HV@5t6s;*<5wN|e+imIykJcP@? zK|jjxTXFTMbX)SF3M)R0^FNT{+#bU9UQ|Q*vt4%T5IwkiJHE3l{_F(pT7KYs zXLWOqFgBu}FCA`D;ALD=Ihh^bluKdQAAwm@z%R$cf zp22v=M7gSY#*ptB|MHb$)zUp<&3_dBqj?7E@#4dt@lW+dUfDASKH@H8xgQD`4+-a; zOA|G9mOPwG{{?^;*mR3!%%#8+*!_4e=^t$_mDPRb`;Yn}uLHBJi!~nwXsYw&wPa;l zy50z%#pj8*w1p$nA-`AKZ2JsqHs_9pmEgAlQQRkiy9GhRyn&%0bN5vK=3pe&)2Dzq zBoJdS!9n>zLFVtJa?=>*UJZlHpKb+nK5s6_=u*xGG*Gl zqg=`G;kyN*K5t|Nswi4nB}uUvvkw*>4$y=T$Ds1tGGp}a5m+&w=@+qTKzt6p+vy`( zD|X7T`Fm@atsLoh32c2F1t%X|pI+)v$u%FbU2|h`s?!45jIO zxB}1Zzgg%HCehQ6oEJt{XK3Qt!xQNHLlQmaQo5;g_jcOgM>q(B^DD454Bby*S{XuK zooCjRVK&b|uZMYN6)trb)hH{Id_-tuI4fTiv1+gZ4piYJ5p3X8jxUU!v4%WqLJz{L zU$IxvxxKP#SVM3`3+JcOdLEk-YR{ms1~qw>Ej|zVrFS1|pzSIIv4~NV)wAL{7;+RG zXhWGHszb8>DLWg5HJLVKgIvtmFEtSw6x}RQs>!Q!oR~I@)AP{magJa8ZNDhBa(nQ! zA)Cb^LY&XT*!8ueqtwc6EyK#n^|cYD)nEoPx5dI=@kig(k3hEr4!Ut6zNlSl2D{)m zDb91s(aNxkzQv%ak=q92>OU-q<**&-@f7P3Y+A|k^`L)Gqzsr_^J#+x*|SC?nit+~ zE38|VXFctp8*dyaaCvo)PZ^Q(paV8M%W^KQsAgI3h=&|B>!-RfUQ%gibgtvSjKC>q z;pfuBwI5Rz*|;ofooPe%vj`2JjcQnID^w|#d!~(-luJczw*t)$2bv9LcU37Vug+ed zrQ>r_M`JkEgQ;z!u#cHpGmJ17>5t^mQD1oSkLI{iBRZOYhZaYr76ac@R>PWG+i62a zdLG)2v9{LDUIw`N9{?Xe4d4?GBdr1W*aHB+-6QCgzXK5cYPX=T{u6-c=^jB(yaGV< z!^Z@@_!I!qPcIVm6#h;0LzGYS)R}_5b}9hT&tCQELi|L!?L|R{e+NMH=xRZCAts_* z`vu*3F96Y9Ckwg-(-PhOxS(5}$7iIk9uV}gHJC4?ul!BWohX;+@T{Q6{|rF%$@`Jk z0(|EWg1&tc0MU0!f*yMffas@)ljxiG33_G_fao`;2>Nvsfaq6$6!cBBIniS%hv>&Q z3;NNY06f}(pGbEfi)HaJ=Al>6k)r?}VVWaIU#biGBIb+eQ^-s7m5qY#TM0n)=@SHf z;Wz-IyMG|)9xOYLcH<|~11|}B5N$(r-xGp9cMSm1{fL?9Glv9yb`t>6=Vt^x_zI>& z`ZU^t=*xErx_1_U=nKyXdH~Cv=>8uIx&v)YbSvT_y5m7Xw;>PFxAqHq`dO@JNUxxN zqUZi9=wVDl^!4)u{o-5zqNA8sqL=<5==lWzq8Bg^L=W8~=r_N{azc9KH9=p09OWQA zvP;l+Q5Vsp$WQb*+JflG>jZuK5v&(TFCP{3gWCXzetB5XHx>biUOq$6lYhZf}X=NA$s;zK~G>g5`7`B}H#C-(D)o6a@#UC!W^~6Tm8GhD+gB=eq`4(3BI0e$O1-sMY1bO{ z*2Wr|MnQ_oMn`u{PEUF-I>ixyPo17L3tP1`g_ybG+RTmmG?wda4bddiW#%h3t4oa=s)9+AL*?ebP>akVg-QCZ$)FY(M0#vNes${? zHS7C$MavAVzbVkwFPK2b#x}M2XZIt^VI_ycT9P7gxjQ{RvKB@yHx0b zwQSjot!k*RbamaM22{7@eLO+pbhcwb{5OA|0D>0B9{VJYBOi zakEt8mQLnoyjp25B&aD*2i<_5AM0eKhx(#zH7sRmukxivgW2&HTNP}fwL?{Zpp?RK zXdVynnwbdQ#zu3g(r#DhMG1POG18ms?lgw)#2EfhdiYgsVh<^@*P9&ikiO% znRiZCZ2QZF>dsny+rj-+v`J?*cExB?yWH9DCo8EYz7QTDW=RZ&G+` zdC_UE$4NF@;fH6U!HP!RBMS2kj+Fpsg5ekXQX!TD=O*EII8##Q{|1iO)L5W=ZXBbf z!&fBRl(*DpD>s(dG5~YJmXb+TC1^r9N|flfv=?wY&WLZ^8DLIACC1U^_ClkHqyD@Z zs58zS1xu_us?8SeyX6ctFR2pcM6-!~m9f;FjhT;3iBRr@=8G{esS@Q>V_(iz%tN9? zH#)zB6S;gXn2$_`5VPD^ZkuuPdAGXP>i3Bru9T8=G)YFY29rXN#4@{K%e2`f&J8pd zkrLn5<-M)BW^HdZXOQ{Hl}INJROgo48F3augK%zQB~F^OVF!*hj;ANF4(T!JI?PlYk8Jym5lbTT9&i*ZXudB|r{XB#!!Rw{9 zlgnB{6>-gBI7eO3AkouKnp*)Cl1eCqzdJf)4z@1W=4$iZE`x4qk+~SJ?qAHise}rm zOG;!OyjAi-#c|r;T%Ee6M&@Hf_w&#d6%s$~455PhzHT>)E-I3FnW;1#>r<%KrxGFc zU)o49Ve}8&_(N(c5uWEwIfA2awdgAd+DY*|Zb}+`gN3E>U!oq}+of*GM7~5lp)~fb zI9+1eKcl&cTy=8*V{WdhjDiSD91ebp#l%&-v9`ZDUTIgtzRkd|X5_(hD(L>I<6I~t zqC6eQNZ=~k$T0F0=WDGvhFt-U1TODP1g;jT=hE^sHo6O4f>(BqU(vCP1Wr#HE!Tf>6GcDKRjSj45>bjH0i6X}{j}k4axqN?Azo{XDjr8;L_)BV;g9#?luf9Pl&AG!FK8ZOw0B9Eq)XXLI#t{uRJK zzY5UvG)9d+ff2Vq#HiyJ0WSKfh(>;MA`Hy!tbM3z1&D4d8c&0ajxq<^!mx z|5l7(y%XSM{QJUNF#7X$j3mX+11NV5>iXMPkQd+2Vwyi=`eG_01BVkYZ4M6kP0DnY$tMI!LzP}kGV*m6bfE`H3-i`UeJoTckqet*P zQvFM)^NaZXrvNsh&XxB8obYLYi!-e1Fa7Q2zY@hdu+a z>9YVcpGQ03yB9ItU0+7b7&ZC~rau$Y{22Mx-hr|(zYpT)nP`Xo-@+(SwA~@J9!3qKEi7r#e4UW0bI?n#WO zMSC2586$f!V)yVb0T#aja0WjA1>f~xxjck&&OjZHVtMRFeXl-?dBk$t^?fWmjA&hh zbT8_iLcQNZ4DFu-{Qf7X7i~I=ywmtMMYMka*1$#ZAvg_s;61Ptu7G#Jg>X9TfL*W_ zPKEcvDR2gi!$z2ZBFw@V%)k_EhEbS=OW`uu4%4s!w!+1*4K9HX!zS1QmqQ8O5ATDw zLKRMi18^f;17%o%8tj86yc@2E^{@{5;XJq!&V@RB5YB-`I1{de!|+kK8E%5(VF}u> zA5MZ3;O+1>7=l3z7Iwo5SZSH-H^CcV1dfF_!r5>Z4F6kM;VtlHAUcNp5do2S{^Nt|KGAgS1j4PGKBRc)y$I?%^fue{yR{wAiQBOBarP$WqBUh#=F+ zj9ib-<`EDgjg`>-vc*c@9FKrMSl2SVdlkne_RExSd0BC@V8DoS@MC3F-{U z^LRVEt*!5@NZN8Xy^q-THlOE6I;%lDeR7EBW=rQac9JI@wLXA&H@G4-gCoStYUe^E z?OF;_k>G{3itr>kxdtJVyu4yIsg@^4gi{uXQ?_EgUL?&PX@!C!+ymn?IfPLojonTW z@|3{xUIEIHm2chKgI78jT%1`NEX#QXf+v<|p`Ah9i{m-0I_zTy^LH8qPM<_DNv0t; zpn^4Tca@M$>s9@pB^(o2I4v8>f=F7wt{YEFWb3lh9}qyh`At`;jyT?7*8K1LO0o+U zU&P(hMP?ElR<}2GxOJmC+=E3bX`W&Vi3Kx{tQT)9BtJja0-*zZ9}b>|zU zjO%IX2$=gV6!zYYWRC)JBzrQD$=ZjJ=$tk&L`{E^j=LtES+wbal4L|qAZ<=KB=G26 zH}!@hNo2!j7l9@4iaBw@H7%aQj&~kRhmGwbWLRCfmfqXwrL;NWo6U3Vw+nrUlV_JR zdu`1E^r~T76iH{5b2(Lp(6gMpqU2G-p55WT*sDRa-W3z1m)Gssj}|h87%V#1&E#?2 zPgf2;Cq*lyy0cbZOdIPSietcGu=7e?sSEovS5X3=Dk;jH5x9*yf+E?t9PaQ4{8ow# zjYUoG_vI`zmKRb+IhCYRiwj(mvKHxP>c|h_Rx;JkM-9!xBSly_o;u7?Xf^kf!pjXF z2SCq544-zDvgsCMw|kevwV7_;k=ZB@v1P~LSdwCmJ^sq)&^3F$O7Hu~i}?s?zLyVC zg~!WzJg-{jU2z}3Dl?t4FIrF! zdXIoAD$bP|@E9DL0h5(mGholtxv5Ca!^IhhqxnIyqm%Q?-h($Us~EdLkeky}Nta7R zt&;;ZQ10Lc4H6|fLj%@yF3});7RRU}#S3}Uw`)T|Zb~Q#b~IwoAwMUn4kuq%X}t7q z#P?-$n<`l2Ld_MH971TLc9b1kcjQp2j--5G5bSYI)gX6*&&IW?r^(=84MZimSvhAm zXDgSL$>pkuO67PB(#Q4u$_*UOSNi+X-2=^RL%fpRvK-Lj-&1ki>Jy0u3!g}WPkAp&Q)4>Vm}V*!8tXxMrDF zdn-psvU2jOKzu87+#rr&zzGgtMN?|GuOcJC`KxfoMgqH8H&#pvN3en}!5!S;lq;^t zm5ZHUHjtHzkf`C@2}s;eMEW>8K3bxme>`eyL{tyni--MhSR?N;#!7?Fz6wDQ6KEWzrrb+viC(r;~_ ze04JZ@gGS4<9~4sewLv3sLwa(e~nS7B3f4R(f1|jIl2-*PsTV(`gc6b)LHQM)o;RY zNh19_4(a&WlQ!4pnvGWD+IG*`v*+|oO-^6tz199BW=co`0E1BJuhsbf8@<1n9w^N< zmi8mw<7fXH{`D`ZkkZgU0=N=nwo4dOOy4ZXZ@dhWreowc{ltS`1Uv)5H}w4(^q>Ea zWB~>b2me-L;4om-NOj=AP+?ZFOk32LzJWfa#;o*e42Dd52EmWW8Z#f{!~09AG3(_k zsxjY^5B?|B7&1i{YJyGaz86);{_wD~-G)`WiI(J9aS5uqpMX1W%q^s7kJHdY6bOS=Xg1MgDD1^sRHMAFwpsJ zd#?HYsCfmJN@R$4MxBGhe$&%(+lx9^3Z1m$CwGNOn-)RN0k9{Fwm&GVu%`c9)PIag zKc0wTy7-fg=Ar1EUx1q5AT&oEiwTY~arMrnZK`K)H0Tdy++Fkf=$wBLbAGJU%n$hl z2d^^bdLYK?A3)u7hl6*efTlZpj)zC0b3B1s-z>E1Yb45X(owOjwlK8!w|J-`E;h)h z)70Kp37z5g?%#sIRkJ6X_Gai;-zqdmwzur1Z>n?0NzF=~i_ETbD>G?5UT6)~x$Joz z9E`5%>#(Mu;Au6VA7rKK+@}u3^ei;BI8kU1*RJqI7951L<%eR%6q>lK7AT@>ns(rk zgJ4fKwcRkTzD;6K>Rgf$^3;El(684%?SLlJm}^aVJ1&kwXE~$KUvd!cH9=ghg-wFb zsAy4naukY)W1SoVd$OqqF$m5^1n=+>gqy_RSczMlKUwG!Z?rXM5#f6y5T-e6%^|WUi?&cG$O%6$?+PM3O+}dB8EyvAy~ir_MI*i*5udIg z?#kittk?^(>*3bE2C?_3*mF8{&f&5ro4U~_mt`F75~6*dg0@Si*%{mv^`u`;wK;mc zFcUXkgP!d5x;Kkwhdo)9MRabi!`!@I%}p1M-!rT!#=hu2kVcfX3i5o8^=HK@r)9j( zlo9I(RIGW03vjsZ<4Zv<+Bx2<5bv1^UYcHHjzh?dRZg`zR+CyTZ= zA}fJ5A0_|N*$UEBffEc&ie9ZxE?l`47ZKYz3byVBr8KQG=HRj+vB?mc$res8GYH{Z)Xj8?!WW-i5^s(y{ zY`Fx}WX2lb$6laf%^^yMLuF4^eL?hmW)IfSUIl4>(LW4fiXI`_vUS8;V0gRp8@*Z4 zN6!-)h`vuj-?eBZ4nIY27Qb#(9ANmQcO?VYk z>OM~}?eq^sV$ipny)%^=Q4Gge;=^c(K|`i@`wC5arm<{c)p)FtRik4zmI2`8@%GBo(K)Y$BeKgM7YUE=oU-NY{WZq z3yY1&4K=OgrV-Di#FHULIU73DICrU!&MEep!*L$xOtZDi6g-x9OJ_u58g-|9G>OsL z88M7V_l8z~HevnQ>|;n52F`)8r;PP_+Q*e8yqw{2Zgr-5v_+z`4_oJ8oNINVAUgrx zYwpD|oMCA4i-+fs*^@=-7W!nhWd6GIQC@GQcS*u9X__Gh|1SvE@WC0?DVlk?f~gGFEFFH&t6SYCc7ApxGNnv z0QO{2M#FM*U8_GAVg0#+>9@Hmf@yc}qYSI)D;XBOr90g5&mlUux1kt&(Ye{He2htV zTW|>M$)dyxy>c4Qd-83FV7G!G+npHq|x?gE2@bLa|CnO!vgl z9V!|1cfyM`OI(cluT9dQ=sIEGEZVH8$Jj?`67IiY`nYKl z9WdEj)sWl@&|1}nh-fiD6ge$tcL;@`FiTm~7*qeUlz=1;@BLs**^s}aPWsJPEwSvn zuSrZTy5VWB*5^yyG0yDY^%gxMx7xLuatYdJe+)vayP+~#&NQd|NC%hR1=?IX#euOW zi~4L@wKOHJgv+d$PUqgnv`^8J2vT2?l?|K8I&Fz9;qt9)2u5VMhgP4rV0~Ve2x4#J za&B(UGrvMXc1V29NvHE~NW`a)6y3*bD$yGy-h^w&vX!W5m3}}V$l-dkY#2vk=0%&a zR1f+XBabWCU3tdAIoCN;k8#LH7qxqs1{{NG(Vq^)wAZuHayJpSxO?81BKMKm + + + + Debug + Win32 + + + Release + Win32 + + + + {EF55A6DC-1861-4037-868A-9557ECAEBC27} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.Announcements/RenX.Announcements.vcxproj.filters b/RenX.Announcements/RenX.Announcements.vcxproj.filters new file mode 100644 index 0000000..9ff9780 --- /dev/null +++ b/RenX.Announcements/RenX.Announcements.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/RenX.Announcements/RenX_Announcements.cpp b/RenX.Announcements/RenX_Announcements.cpp new file mode 100644 index 0000000..b6723c8 --- /dev/null +++ b/RenX.Announcements/RenX_Announcements.cpp @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Jupiter/IRC_Client.h" +#include "Jupiter/INIFile.h" +#include "RenX_Announcements.h" +#include "RenX_Core.h" +#include "RenX_Server.h" + +RenX_AnnouncementsPlugin pluginInstance; + +void announce(unsigned int) +{ + if (pluginInstance.random == false) + { + pluginInstance.lastLine++; + if (pluginInstance.lastLine == pluginInstance.announcementsFile.getLineCount()) pluginInstance.lastLine = 0; + } + else + { + unsigned int trand; + do trand = rand() % pluginInstance.announcementsFile.getLineCount(); + while (trand == pluginInstance.lastLine); + pluginInstance.lastLine = trand; + } + const Jupiter::ReadableString &announcement = pluginInstance.announcementsFile.getLine(pluginInstance.lastLine); + RenX::Core *core = RenX::getCore(); + RenX::Server *server; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + server = core->getServer(i); + if (server->players.size() != 0) + server->sendMessage(announcement); + } +} + +RenX_AnnouncementsPlugin::RenX_AnnouncementsPlugin() +{ + RenX_AnnouncementsPlugin::announcementsFile.load(Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX.Announcements"), STRING_LITERAL_AS_REFERENCE("File"), STRING_LITERAL_AS_REFERENCE("Announcements.txt"))); + if (RenX_AnnouncementsPlugin::announcementsFile.getLineCount() != 0) + { + RenX_AnnouncementsPlugin::random = Jupiter::IRC::Client::Config->getBool(STRING_LITERAL_AS_REFERENCE("RenX.Announcements"), STRING_LITERAL_AS_REFERENCE("Random")); + time_t delay = Jupiter::IRC::Client::Config->getInt(STRING_LITERAL_AS_REFERENCE("RenX.Announcements"), STRING_LITERAL_AS_REFERENCE("Delay"), 60); + RenX_AnnouncementsPlugin::timer = new Jupiter::Timer(0, delay, announce); + if (RenX_AnnouncementsPlugin::random == false) RenX_AnnouncementsPlugin::lastLine = RenX_AnnouncementsPlugin::announcementsFile.getLineCount() - 1; + } + else fputs("[RenX.Announcements] ERROR: No announcements loaded." ENDL, stderr); +} + +RenX_AnnouncementsPlugin::~RenX_AnnouncementsPlugin() +{ + RenX_AnnouncementsPlugin::timer->kill(); + RenX_AnnouncementsPlugin::announcementsFile.unload(); +} + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.Announcements/RenX_Announcements.h b/RenX.Announcements/RenX_Announcements.h new file mode 100644 index 0000000..5a43a00 --- /dev/null +++ b/RenX.Announcements/RenX_Announcements.h @@ -0,0 +1,43 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_ANNOUNCEMENTS_H_HEADER +#define _RENX_ANNOUNCEMENTS_H_HEADER + +#include "Jupiter/Plugin.h" +#include "Jupiter/Timer.h" +#include "Jupiter/File.h" +#include "RenX_Plugin.h" + +class RenX_AnnouncementsPlugin : public RenX::Plugin +{ +public: + const Jupiter::ReadableString &getName() override { return name; } + RenX_AnnouncementsPlugin(); + ~RenX_AnnouncementsPlugin(); + +public: + Jupiter::File announcementsFile; + bool random; + unsigned int lastLine; + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.Announcements"); + Jupiter::Timer *timer; +}; + +#endif // _RENX_ANNOUNCEMENTS_H_HEADER \ No newline at end of file diff --git a/RenX.Commands/RenX.Commands.vcxproj b/RenX.Commands/RenX.Commands.vcxproj new file mode 100644 index 0000000..b7ad2b8 --- /dev/null +++ b/RenX.Commands/RenX.Commands.vcxproj @@ -0,0 +1,87 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {72B6B5A6-4267-4FED-9F96-917C7974CE25} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + Document + + + + + + \ No newline at end of file diff --git a/RenX.Commands/RenX.Commands.vcxproj.filters b/RenX.Commands/RenX.Commands.vcxproj.filters new file mode 100644 index 0000000..fc45530 --- /dev/null +++ b/RenX.Commands/RenX.Commands.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/RenX.Commands/RenX_Commands.cpp b/RenX.Commands/RenX_Commands.cpp new file mode 100644 index 0000000..f14c92c --- /dev/null +++ b/RenX.Commands/RenX_Commands.cpp @@ -0,0 +1,1357 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Jupiter/Functions.h" +#include "IRC_Bot.h" +#include "RenX_Commands.h" +#include "RenX_Core.h" +#include "RenX_Server.h" +#include "RenX_PlayerInfo.h" +#include "RenX_Functions.h" + +inline bool togglePhasing(RenX::Server *server, bool newState) +{ + server->varData.set(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), newState ? STRING_LITERAL_AS_REFERENCE("true") : STRING_LITERAL_AS_REFERENCE("false")); + return newState; +} + +inline bool togglePhasing(RenX::Server *server) +{ + return togglePhasing(server, !server->varData.getBool(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), false)); +} + +inline void onDie(RenX::Server *server, const RenX::PlayerInfo *player) +{ + if (player->isBot && server->varData.getBool(STRING_LITERAL_AS_REFERENCE("RenX.Commands"), STRING_LITERAL_AS_REFERENCE("phasing"), false)) server->kickPlayer(player); +} + +void RenX_CommandsPlugin::RenX_OnSuicide(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &) +{ + onDie(server, player); +} + +void RenX_CommandsPlugin::RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &) +{ + onDie(server, victim); +} + +void RenX_CommandsPlugin::RenX_OnDie(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &) +{ + onDie(server, player); +} + +/** Console Commands */ + +// RCON Console Command + +RCONConsoleCommand::RCONConsoleCommand() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rcon")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("renx")); +} + +void RCONConsoleCommand::trigger(const Jupiter::ReadableString ¶meters) +{ + int i = RenX::getCore()->getServerCount(); + if (i == 0) + puts("Error: Not connected to any Renegade X servers."); + else if (parameters != nullptr) + { + RenX::Server *server; + while (--i >= 0) + { + server = RenX::getCore()->getServer(i); + RenX::getCore()->send(server, parameters); + } + } + else + puts("Error: Too Few Parameters. Syntax: rcon "); +} + +const Jupiter::ReadableString &RCONConsoleCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends data to the Renegade X server's rcon. Syntax: rcon "); + return defaultHelp; +} + +CONSOLE_COMMAND_INIT(RCONConsoleCommand) + +/** IRC Commands */ + +// Msg IRC Command + +void MsgIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("msg")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("say")); +} + +void MsgIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.isEmpty() == false) + { + Jupiter::StringL msg = "say "; + msg += source->getChannel(channel)->getUserPrefix(nick); + msg += nick; + msg += "@IRC: "; + msg += parameters; + if (RenX::getCore()->send(source->getChannel(channel)->getType(), msg) == 0) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: Msg ")); +} + +const Jupiter::ReadableString &MsgIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message in - game.Syntax: Msg "); + return defaultHelp; +} + +IRC_COMMAND_INIT(MsgIRCCommand) + +// Host Msg IRC Command + +void HostMsgIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("hmsg")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("hsay")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("hostmessage")); + this->setAccessLevel(4); +} + +void HostMsgIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.isEmpty() == false) + { + if (RenX::getCore()->send(source->getChannel(channel)->getType(), Jupiter::StringS::Format("say %.*s", parameters.size(), parameters.ptr())) == 0) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: hmsg ")); +} + +const Jupiter::ReadableString &HostMsgIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message in-game. Syntax: hmsg "); + return defaultHelp; +} + +IRC_COMMAND_INIT(HostMsgIRCCommand) + +// Players IRC Command + +void PlayersIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("players")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("pl")); +} + +const size_t STRING_LENGTH = 240; + +void PlayersIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &) +{ + int type = source->getChannel(channel)->getType(); + + // Team colors + const Jupiter::ReadableString &gTeamColor = RenX::getTeamColor(RenX::TeamType::GDI); + const Jupiter::ReadableString &nTeamColor = RenX::getTeamColor(RenX::TeamType::Nod); + const Jupiter::ReadableString &oTeamColor = RenX::getTeamColor(RenX::TeamType::Other); + + // Team names + const Jupiter::ReadableString &gTeam = RenX::getTeamName(RenX::TeamType::GDI); + const Jupiter::ReadableString &nTeam = RenX::getTeamName(RenX::TeamType::Nod); + const Jupiter::ReadableString &oTeam = RenX::getTeamName(RenX::TeamType::Other); + + bool noServers = true; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type)) + { + noServers = false; + if (server->players.size() != 0) + { + // End string containers + Jupiter::DLList gStrings; + Jupiter::DLList nStrings; + Jupiter::DLList oStrings; + + Jupiter::StringL *gCurrent = nullptr; + Jupiter::StringL *nCurrent = nullptr; + Jupiter::StringL *oCurrent = nullptr; + + // Team player counters + unsigned int gTotal = 0; + unsigned int nTotal = 0; + unsigned int oTotal = 0; + + // Bot counters + unsigned int gBots = 0; + unsigned int nBots = 0; + unsigned int oBots = 0; + + for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) + { + if (node->data != nullptr) + { + Jupiter::String &name = RenX::getFormattedPlayerName(node->data); + if (name.size() > STRING_LENGTH - 32) continue; // Name will be too long to send. + + switch (node->data->team) + { + case RenX::TeamType::Nod: + if (nCurrent == nullptr || nCurrent->size() + name.size() > STRING_LENGTH) + { + nCurrent = new Jupiter::StringL(STRING_LENGTH); + nCurrent->format(IRCCOLOR "%.*s[%.*s]: " IRCBOLD "%.*s" IRCBOLD, nTeamColor.size(), nTeamColor.ptr(), nTeam.size(), nTeam.ptr(), name.size(), name.ptr()); + nStrings.add(nCurrent); + } + else nCurrent->aformat(IRCCOLOR ", " IRCBOLD "%.*s" IRCBOLD, name.size(), name.ptr()); + nTotal++; + if (node->data->isBot) + nBots++; + break; + case RenX::TeamType::GDI: + if (gCurrent == nullptr || gCurrent->size() + name.size() > STRING_LENGTH) + { + gCurrent = new Jupiter::StringL(STRING_LENGTH); + gCurrent->format(IRCCOLOR "%.*s[%.*s]: " IRCBOLD "%.*s" IRCBOLD, gTeamColor.size(), gTeamColor.ptr(), gTeam.size(), gTeam.ptr(), name.size(), name.ptr()); + gStrings.add(gCurrent); + } + else gCurrent->aformat(IRCCOLOR ", " IRCBOLD "%.*s" IRCBOLD, name.size(), name.ptr()); + gTotal++; + if (node->data->isBot) + gBots++; + break; + default: + if (oCurrent == nullptr || oCurrent->size() + name.size() > STRING_LENGTH) + { + oCurrent = new Jupiter::StringL(STRING_LENGTH); + oCurrent->format(IRCCOLOR "%.*s[%.*s]: " IRCBOLD "%.*s" IRCBOLD, oTeamColor.size(), oTeamColor.ptr(), oTeam.size(), oTeam.ptr(), name.size(), name.ptr()); + oStrings.add(oCurrent); + } + else oCurrent->aformat(IRCCOLOR ", " IRCBOLD "%.*s" IRCBOLD, name.size(), name.ptr()); + oTotal++; + if (node->data->isBot) + oBots++; + break; + } + } + } + Jupiter::StringL *outString; + while (gStrings.size() != 0) + { + outString = gStrings.remove(0U); + source->sendMessage(channel, *outString); + delete outString; + } + while (nStrings.size() != 0) + { + outString = nStrings.remove(0U); + source->sendMessage(channel, *outString); + delete outString; + } + while (oStrings.size() != 0) + { + outString = oStrings.remove(0U); + source->sendMessage(channel, *outString); + delete outString; + } + + Jupiter::StringL out; + out.format(IRCCOLOR "03Total Players" IRCCOLOR ": %u", server->players.size()); + if (gBots + nBots + oBots > 0) + out.aformat(" (%u bots)", gBots + nBots + oBots); + if (gTotal > 0) + { + out.aformat(IRCCOLOR "02 | " IRCCOLOR "%.*s%.*s" IRCCOLOR ": %u", gTeamColor.size(), gTeamColor.ptr(), gTeam.size(), gTeam.ptr(), gTotal); + if (gBots > 0) + out.aformat(" (%u bots)", gBots); + } + if (nTotal > 0) + { + out.aformat(IRCCOLOR "02 | " IRCCOLOR "%.*s%.*s" IRCCOLOR ": %u", nTeamColor.size(), nTeamColor.ptr(), nTeam.size(), nTeam.ptr(), nTotal); + if (nBots > 0) + out.aformat(" (%u bots)", nBots); + } + if (oTotal > 0) + { + out.aformat(IRCCOLOR "02 | " IRCCOLOR "%.*s%.*s" IRCCOLOR ": %u", oTeamColor.size(), oTeamColor.ptr(), oTeam.size(), oTeam.ptr(), oTotal); + if (oBots > 0) + out.aformat(" (%u bots)", oBots); + } + source->sendMessage(channel, out); + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("No players are in-game.")); + } + } + if (noServers) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); +} + +const Jupiter::ReadableString &PlayersIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Lists the players currently in-game. Syntax: Players"); + return defaultHelp; +} + +IRC_COMMAND_INIT(PlayersIRCCommand) + +// PlayerInfo IRC Command + +void PlayerInfoIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("playerinfo")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("pi")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("player")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("pinfo")); + this->setAccessLevel(2); +} + +void PlayerInfoIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + RenX::PlayerInfo *player; + Jupiter::StringL msg; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type) && server->players.size() != 0) + { + for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) + { + player = node->data; + if (player->name.findi(parameters) != Jupiter::INVALID_INDEX) + { + const Jupiter::ReadableString &teamColor = RenX::getTeamColor(player->team); + const Jupiter::ReadableString &teamName = RenX::getFullTeamName(player->team); + msg.format(IRCCOLOR "03[Player Info]" IRCCOLOR "%.*s Name: " IRCBOLD "%.*s" IRCBOLD " - ID: %d - Team: " IRCBOLD "%.*s" IRCBOLD " - Vehicle Kills: %u - Defence Kills: %u - Building Kills: %u - Kills: %u (%u headshots) - Deaths: %u (%u suicides) - KDR: %.2f", teamColor.size(), teamColor.ptr(), player->name.size(), player->name.ptr(), player->id, teamName.size(), teamName.ptr(), player->vehicleKills, player->defenceKills, player->buildingKills, player->kills, player->headshots, player->deaths, player->suicides, ((float)player->kills) / (player->deaths == 0 ? 1.0 : (float)player->deaths)); + if (source->getAccessLevel(channel, nick) > 1) + { + msg += " - IP: " IRCBOLD; + if (player->ip.size() != 0) + { + msg += player->ip; + msg += IRCBOLD; + } + else msg += "IP Not Found" IRCBOLD; + } + if (player->steamid.size() != 0) + { + msg += " - Steam ID: " IRCBOLD; + msg += player->steamid; + msg += IRCBOLD; + } + if (player->adminType.size() != 0) + { + msg += " - Admin Type: " IRCBOLD; + msg += player->adminType; + msg += IRCBOLD; + } + source->sendMessage(channel, msg); + } + } + } + } + if (msg.isEmpty()) source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); + } + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: PlayerInfo ")); +} + +const Jupiter::ReadableString &PlayerInfoIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Gets information about a player. Syntax: PlayerInfo "); + return defaultHelp; +} + +IRC_COMMAND_INIT(PlayerInfoIRCCommand) + +// Steam IRC Command + +void SteamIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("steam")); + this->setAccessLevel(1); +} + +void SteamIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + RenX::PlayerInfo *player; + if (parameters.size() != 0) + { + Jupiter::StringL msg; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type) && server->players.size() != 0) + { + for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) + { + player = node->data; + if (player->name.findi(parameters) != Jupiter::INVALID_INDEX) + { + Jupiter::String &playerName = RenX::getFormattedPlayerName(player); + msg.format(IRCCOLOR "03[Steam] " IRCCOLOR "%.*s (ID: %d) ", playerName.size(), playerName.ptr(), player->id); + if (player->steamid.size() != 0) + { + msg += "is using steam ID " IRCBOLD; + msg += player->steamid; + msg += IRCBOLD; + } + else msg += "is not using steam."; + source->sendMessage(channel, msg); + } + } + } + } + if (msg.isEmpty()) + source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); + } + else + { + unsigned int total = 0; + unsigned int realPlayers = 0; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type) && server->players.size() != 0) + { + for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) + { + player = node->data; + if (player->isBot == false) + { + realPlayers++; + if (player->steamid.size() != 0) total++; + } + } + } + if (realPlayers != 0) + source->sendMessage(channel, Jupiter::StringS::Format("%.2f%% (%u/%u) of players are using Steam.", ((double)total * 100) / ((double)realPlayers), total, realPlayers)); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("No players are in-game.")); + } + } + } +} + +const Jupiter::ReadableString &SteamIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Fetches steam usage information. Syntax: Steam [Player]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(SteamIRCCommand) + +// Kill-Death Ratio IRC Command + +void KillDeathRatioIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("kills")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("deaths")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("kdr")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("killdeathraio")); +} + +void KillDeathRatioIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + RenX::PlayerInfo *player; + Jupiter::StringL msg; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type) && server->players.size() != 0) + { + for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) + { + player = node->data; + if (player->name.findi(parameters) != Jupiter::INVALID_INDEX) + { + Jupiter::String &playerName = RenX::getFormattedPlayerName(player); + msg.format(IRCBOLD "%.*s" IRCBOLD IRCCOLOR ": Kills: %u - Deaths: %u - KDR: %.2f", playerName.size(), playerName.ptr(), player->kills, player->deaths, ((float)player->kills) / (player->deaths == 0 ? 1.0 : (float)player->deaths)); + source->sendMessage(channel, msg); + } + } + } + } + if (msg.isEmpty()) + source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Player not found.")); + } + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: Kills ")); +} + +const Jupiter::ReadableString &KillDeathRatioIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Gets a player's kills and deaths. Syntax: Kills "); + return defaultHelp; +} + +IRC_COMMAND_INIT(KillDeathRatioIRCCommand) + +// ShowMods IRC Command + +void ShowModsIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("showmods")); +} + +extern ModsGameCommand ModsGameCommand_instance; + +void ShowModsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + bool sent = false; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type)) + { + ModsGameCommand_instance.trigger(server, nullptr, Jupiter::ReferenceString::empty); + sent = true; + } + } + if (sent == false) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } +} + +const Jupiter::ReadableString &ShowModsIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message, displaying the in-game moderators. Syntax: showmods"); + return defaultHelp; +} + +IRC_COMMAND_INIT(ShowModsIRCCommand) + +// Mods IRC Command + +void ModsIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("mods")); +} + +void ModsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.equalsi("show")) ShowModsIRCCommand_instance.trigger(source, channel, nick, parameters); + else + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + RenX::PlayerInfo *player; + Jupiter::StringL msg; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type)) + { + msg = ""; + if (server->players.size() != 0) + { + for (Jupiter::DLList::Node *node = server->players.getNode(0); node != nullptr; node = node->next) + { + player = node->data; + if (player->adminType.size() != 0) + { + if (msg.size() != 0) msg += ", "; + else msg += "Moderators in-game: "; + msg += player->name; + } + } + } + if (msg.size() == 0) msg = "No moderators are in-game."; + source->sendMessage(channel, msg); + } + } + if (msg.size() == 0) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + } +} + +const Jupiter::ReadableString &ModsIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message, displaying the in-game moderators. Syntax: mods [show]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(ModsIRCCommand) + +// ShowRules IRC Command + +void ShowRulesIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("showrules")); +} + +void ShowRulesIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + Jupiter::StringL msg; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type)) + { + msg = "Rules: "; + msg += server->getRules(); + server->sendMessage(msg); + } + } + if (msg.size() == 0) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } +} + +const Jupiter::ReadableString &ShowRulesIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends a message, displaying the in-game rules. Syntax: showrules"); + return defaultHelp; +} + +IRC_COMMAND_INIT(ShowRulesIRCCommand) + +// Rules IRC Command + +void RulesIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rules")); +} + +void RulesIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.equalsi("show")) ShowRulesIRCCommand_instance.trigger(source, channel, nick, parameters); + else + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + Jupiter::StringL msg; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type)) + { + msg = IRCCOLOR "11[Rules]" IRCCOLOR " "; + msg += server->getRules(); + source->sendMessage(channel, msg); + } + } + if (msg.size() == 0) source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + } +} + +const Jupiter::ReadableString &RulesIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays the in-game rules. Syntax: rules [show]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(RulesIRCCommand) + +// SetRules IRC Command + +void SetRulesIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("setrules")); + this->setAccessLevel(4); +} + +void SetRulesIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + unsigned int r = 0; + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type)) + { + server->setRules(parameters); + r++; + } + } + if (r == 0) + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + } +} + +const Jupiter::ReadableString &SetRulesIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sets the in-game rules. Syntax: setrules [show]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(SetRulesIRCCommand) + +// Reconnect IRC Command + +void ReconnectIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("reconnect")); + this->setAccessLevel(4); +} + +void ReconnectIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString &) +{ + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + int type = chan->getType(); + Jupiter::StringS msg; + for (unsigned int i = 0; i != RenX::getCore()->getServerCount(); i++) + { + RenX::Server *server = RenX::getCore()->getServer(i); + if (server->isLogChanType(type)) + { + if (server->reconnect()) msg.format("Connection established"); + else msg.format("[RenX] ERROR: Failed to connect to %.*s on port %u." ENDL, server->getHostname().size(), server->getHostname().ptr(), server->getPort()); + source->sendMessage(channel, msg); + } + } + if (msg.isEmpty()) + { + // We didn't connect anywhere!! + msg.format("ERROR: No servers found to connect to."); + source->sendMessage(channel, msg); + } + } +} + +const Jupiter::ReadableString &ReconnectIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Gets information about a player. Syntax: Reconnect"); + return defaultHelp; +} + +IRC_COMMAND_INIT(ReconnectIRCCommand) + +// RestartMap IRC Command + +/*void RestartMapIRCCommand::create() +{ + this->addTrigger("restartmap"); + this->setAccessLevel(2); +} + +void RestartMapIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + int r = RenX::getCore()->send(source->getChannel(channel.c_str())->getType(), "adminrestartmap"); + if (r > 0) + { + char t[256]; + sprintf(t, "Command sent to %d servers.", r); + source->sendMessage(channel.c_str(), t); + } + else source->sendMessage(channel.c_str(), "Error: Channel not attached to any connected Renegade X servers."); +} + +const char *RestartMapIRCCommand::getHelp() +{ + return "Restarts the current map. Syntax: RestartMap"; +} + +IRC_COMMAND_INIT(RestartMapIRCCommand) + +// SetMap IRC Command + +void SetMapIRCCommand::create() +{ + this->addTrigger("setmap"); + this->setAccessLevel(3); +} + +void SetMapIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters != nullptr) + { + Jupiter::StringL cmd = "adminrestartmap "; + cmd += parameters; + int r = RenX::getCore()->send(source->getChannel(channel.c_str())->getType(), cmd.c_str()); + if (r > 0) + { + char t[256]; + sprintf(t, "Command sent to %d servers.", r); + source->sendMessage(channel.c_str(), t); + } + else source->sendMessage(channel.c_str(), "Error: Channel not attached to any connected Renegade X servers."); + } + else source->sendNotice(nick.c_str(), "Error: Too Few Parameters. Syntax: SetMap "); +} + +const char *SetMapIRCCommand::getHelp() +{ + return "Sets the next map, and ends the current map. Syntax: SetMap "; +} + +IRC_COMMAND_INIT(SetMapIRCCommand)*/ + +// Mute IRC Command + +/*void MuteIRCCommand::create() +{ + this->addTrigger("mute"); + this->addTrigger("silence"); + this->setAccessLevel(2); +} + +void MuteIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters != nullptr) + { + Jupiter::StringL cmd = "AdminForceTextMute "; + cmd += parameters; + int r = RenX::getCore()->send(source->getChannel(channel.c_str())->getType(), cmd.c_str()); + if (r > 0) + { + char t[256]; + sprintf(t, "Command sent to %d servers.", r); + source->sendMessage(channel.c_str(), t); + } + else source->sendMessage(channel.c_str(), "Error: Channel not attached to any connected Renegade X servers."); + } + else source->sendNotice(nick.c_str(), "Error: Too Few Parameters. Syntax: Mute "); +} + +const char *MuteIRCCommand::getHelp() +{ + return "Mutes a player from the game chat. Syntax: Mute "; +} + +IRC_COMMAND_INIT(MuteIRCCommand) + +// UnMute IRC Command + +void UnMuteIRCCommand::create() +{ + this->addTrigger("unmute"); + this->setAccessLevel(2); +} + +void UnMuteIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters != nullptr) + { + Jupiter::StringL cmd = "AdminForceTextUnMute "; + cmd += parameters; + int r = RenX::getCore()->send(source->getChannel(channel.c_str())->getType(), cmd.c_str()); + if (r > 0) + { + char t[256]; + sprintf(t, "Command sent to %d servers.", r); + source->sendMessage(channel.c_str(), t); + } + else source->sendMessage(channel.c_str(), "Error: Channel not attached to any connected Renegade X servers."); + } + else source->sendNotice(nick.c_str(), "Error: Too Few Parameters. Syntax: UnMute "); +} + +const char *UnMuteIRCCommand::getHelp() +{ + return "UnMutes a player from the game chat. Syntax: UnMute "; +} + +IRC_COMMAND_INIT(UnMuteIRCCommand)*/ + +// Kick IRC Command + +void KickIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("kick")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("qkick")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("k")); + this->setAccessLevel(3); +} + +void KickIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); + if (servers.size() != 0) + { + RenX::PlayerInfo *player; + RenX::Server *server; + unsigned int kicks = 0; + for (size_t i = 0; i != servers.size(); i++) + { + server = servers.get(i); + if (server != nullptr) + { + player = server->getPlayerByPartName(parameters); + if (player != nullptr) + { + server->kickPlayer(player); + kicks++; + } + } + } + source->sendMessage(channel, Jupiter::StringS::Format("%u players kicked.", kicks)); + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: Kick ")); +} + +const Jupiter::ReadableString &KickIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks a player from the game. Syntax: Kick "); + return defaultHelp; +} + +IRC_COMMAND_INIT(KickIRCCommand) + +// KickBan IRC Command + +void KickBanIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("kickban")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("kb")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("ban")); + this->setAccessLevel(4); +} + +void KickBanIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); + if (servers.size() != 0) + { + RenX::PlayerInfo *player; + RenX::Server *server; + unsigned int kicks = 0; + for (size_t i = 0; i != servers.size(); i++) + { + server = servers.get(i); + if (server != nullptr) + { + player = server->getPlayerByPartName(parameters); + if (player != nullptr) + { + server->banPlayer(player); + kicks++; + } + } + } + source->sendMessage(channel, Jupiter::StringS::Format("%u players kicked.", kicks)); + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: KickBan ")); +} + +const Jupiter::ReadableString &KickBanIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Kicks and bans a player from the game. Syntax: KickBan "); + return defaultHelp; +} + +IRC_COMMAND_INIT(KickBanIRCCommand) + +// AddBots IRC Command + +void AddBotsIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("addbots")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("addbot")); + this->setAccessLevel(2); +} + +void AddBotsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + Jupiter::ArrayList servers = RenX::getCore()->getServers(source->getChannel(channel)->getType()); + if (servers.size() != 0) + { + int amount = parameters.asInt(); + if (amount != 0) + { + RenX::Server *server; + Jupiter::StringL cmd; + Jupiter::ReferenceString targetTeam = Jupiter::ReferenceString::getWord(parameters, 1, WHITESPACE); + RenX::TeamType team = targetTeam.isEmpty() ? RenX::TeamType::Other : RenX::getTeam(targetTeam[0]); + + switch (team) + { + case RenX::TeamType::GDI: + cmd = "addredbots "; + break; + case RenX::TeamType::Nod: + cmd = "addbluebots "; + break; + case RenX::TeamType::Other: + cmd = "addbots "; + break; + } + + for (size_t i = 0, extra; i != servers.size(); i++) + { + server = servers.get(i); + if (server != nullptr) + { + extra = cmd.aformat("%u", amount); + server->send(cmd); + cmd -= extra; + } + server->sendMessage(Jupiter::StringS::Format("%u bots have been added to the server.", amount)); + } + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Invalid amount entered. Amount must be a positive integer.")); + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: AddBots [Team]")); +} + +const Jupiter::ReadableString &AddBotsIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Adds bots to the game. Syntax: AddBots [Team]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(AddBotsIRCCommand) + +// KillBots IRC Command + +void KillBotsIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("killbots")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("killbot")); + this->setAccessLevel(2); +} + +void KillBotsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); + if (servers.size() != 0) + { + RenX::Server *server; + + for (size_t i = 0; i != servers.size(); i++) + { + server = servers.get(i); + server->send(STRING_LITERAL_AS_REFERENCE("killbots")); + server->sendMessage(STRING_LITERAL_AS_REFERENCE("All bots have been removed from the server.")); + } + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } +} + +const Jupiter::ReadableString &KillBotsIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Removes all bots from the game. Syntax: KillBots"); + return defaultHelp; +} + +IRC_COMMAND_INIT(KillBotsIRCCommand) + +// PhaseBots IRC Command + +void PhaseBotsIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("phasebots")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("phasebot")); + this->setAccessLevel(2); +} + +void PhaseBotsIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + Jupiter::ArrayList servers = RenX::getCore()->getServers(chan->getType()); + if (servers.size() != 0) + { + RenX::Server *server; + + for (size_t i = 0; i != servers.size(); i++) + { + server = servers.get(i); + if (parameters.size() == 0) + { + if (togglePhasing(server)) + server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been enabled.")); + else server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been disabled.")); + } + else if (parameters.equalsi("true") || parameters.equalsi("on") || parameters.equalsi("start") || parameters.equalsi("1")) + { + togglePhasing(server, true); + server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been enabled.")); + } + else + { + togglePhasing(server, false); + server->sendMessage(STRING_LITERAL_AS_REFERENCE("Bot phasing has been disabled.")); + } + } + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } +} + +const Jupiter::ReadableString &PhaseBotsIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Toggles the phasing of bots from the game by kicking them after death. Syntax: PhaseBots [on/off]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(PhaseBotsIRCCommand) + +// RCON IRC Command + +void RCONIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rcon")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("renx")); + this->setAccessLevel(5); +} + +void RCONIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters != nullptr) + { + Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); + if (chan != nullptr) + { + unsigned int r = RenX::getCore()->send(chan->getType(), parameters); + if (r > 0) + source->sendMessage(channel, Jupiter::StringS::Format("Command sent to %u servers.", r)); + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Error: Channel not attached to any connected Renegade X servers.")); + } + } + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Error: Too Few Parameters. Syntax: rcon ")); +} + +const Jupiter::ReadableString &RCONIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sends data to the Renegade X server's rcon. Syntax: rcon "); + return defaultHelp; +} + +IRC_COMMAND_INIT(RCONIRCCommand) + +/** Game Commands */ + +// Help Game Command + +void HelpGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("help")); +} + +void HelpGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + Jupiter::StringL output = "say Available Commands: "; + parameters.println(stdout); + if (parameters.wordCount(WHITESPACE) == 0) + { + // We know there's at least one command, because of this command! + output += source->getCommand(0)->getTrigger(); + for (unsigned int i = 1; i != source->getCommandCount(); i++) + { + output += ", "; + output += source->getCommand(i)->getTrigger(); + } + } + else + { + RenX::GameCommand *cmd = source->getCommand(Jupiter::ReferenceString::getWord(parameters, 0, WHITESPACE)); + if (cmd != nullptr) + output += cmd->getHelp(Jupiter::ReferenceString::gotoWord(parameters, 1, WHITESPACE)); + else output += "Error: Command not found."; + } + source->send(output); +} + +const Jupiter::ReadableString &HelpGameCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Lists commands, or sends command-specific help. Syntax: help [command]"); + return defaultHelp; +} + +GAME_COMMAND_INIT(HelpGameCommand) + +// Mods Game Command + +void ModsGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("mods")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("showmods")); +} + +void ModsGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *, const Jupiter::ReadableString &) +{ + RenX::PlayerInfo *player; + Jupiter::StringL msg = "say "; + for (Jupiter::DLList::Node *node = source->players.getNode(0); node != nullptr; node = node->next) + { + player = node->data; + if (player->adminType.size() != 0) + { + if (msg.size() != 4) msg += ", "; + else msg += "Moderators in-game: "; + msg += player->name; + } + } + if (msg.size() == 4) + { + msg += "No moderators are in-game"; + RenX::GameCommand *cmd = source->getCommand(STRING_LITERAL_AS_REFERENCE("modrequest")); + if (cmd != nullptr) + msg.aformat("; please use \"%.*s%.*s\" if you require assistance.", source->getCommandPrefix().size(), source->getCommandPrefix().ptr(), cmd->getTrigger().size(), cmd->getTrigger().ptr()); + else msg += '.'; + } + source->send(msg); +} + +const Jupiter::ReadableString &ModsGameCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays the in-game moderators. Syntax: mods"); + return defaultHelp; +} + +GAME_COMMAND_INIT(ModsGameCommand) + +// Rules Game Command + +void RulesGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rules")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rule")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("showrules")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("showrule")); +} + +void RulesGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + source->sendMessage(Jupiter::StringS::Format("Rules: %.*s", source->getRules().size(), source->getRules().ptr())); +} + +const Jupiter::ReadableString &RulesGameCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays the rules for this server. Syntax: rules"); + return defaultHelp; +} + +GAME_COMMAND_INIT(RulesGameCommand) + +// Mod Request Game Command + +void ModRequestGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("modrequest")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("requestmod")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("mod")); +} + +void ModRequestGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + unsigned int serverCount = serverManager->size(); + IRC_Bot *server; + Jupiter::IRC::Client::Channel *channel; + unsigned int channelCount; + int type; + Jupiter::String &fmtName = RenX::getFormattedPlayerName(player); + Jupiter::StringL msg = Jupiter::StringL::Format(IRCCOLOR "12[Moderator Request] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR "07 has requested assistance in-game; please look in ", fmtName.size(), fmtName.ptr()); + Jupiter::StringS msg2 = Jupiter::StringS::Format(IRCCOLOR "12[Moderator Request] " IRCCOLOR IRCBOLD "%.*s" IRCBOLD IRCCOLOR "07 has requested assistance in-game!" IRCCOLOR, fmtName.size(), fmtName.ptr()); + for (unsigned int a = 0; a < serverCount; a++) + { + server = serverManager->getServer(a); + if (server != nullptr) + { + channelCount = server->getChannelCount(); + for (unsigned int b = 0; b < channelCount; b++) + { + channel = server->getChannel(b); + if (channel != nullptr) + { + type = channel->getType(); + server->sendMessage(channel->getName(), msg2); + if (source->isLogChanType(type)) + { + msg += channel->getName(); + for (unsigned int c = 0; c < channel->getUserCount(); c++) + if (channel->getUserPrefix(c) != 0) + server->sendMessage(channel->getUser(c)->getUser()->getNickname(), msg); + msg -= channel->getName().size(); + } + } + } + } + } +} + +const Jupiter::ReadableString &ModRequestGameCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Notifies the moderators on IRC that assistance is required. Syntax: modRequest"); + return defaultHelp; +} + +GAME_COMMAND_INIT(ModRequestGameCommand) + +// Plugin instantiation and entry point. +RenX_CommandsPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.Commands/RenX_Commands.h b/RenX.Commands/RenX_Commands.h new file mode 100644 index 0000000..b181273 --- /dev/null +++ b/RenX.Commands/RenX_Commands.h @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_COMMANDS_H_HEADER +#define _RENX_COMMANDS_H_HEADER + +#include "Console_Command.h" +#include "IRC_Command.h" +#include "RenX_GameCommand.h" +#include "RenX_Plugin.h" + +class RenX_CommandsPlugin : public RenX::Plugin +{ +public: // RenX::Plugin + void RenX_OnSuicide(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) override; + void RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType) override; + void RenX_OnDie(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) override; + +public: // Jupiter::Plugin + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.Commands"); +}; + +GENERIC_CONSOLE_COMMAND(RCONConsoleCommand) +//GENERIC_CONSOLE_COMMAND(RCONSelectConsoleCommand) + +GENERIC_IRC_COMMAND(MsgIRCCommand) +GENERIC_IRC_COMMAND(HostMsgIRCCommand) +GENERIC_IRC_COMMAND(PlayersIRCCommand) +GENERIC_IRC_COMMAND(PlayerInfoIRCCommand) +GENERIC_IRC_COMMAND(SteamIRCCommand) +GENERIC_IRC_COMMAND(KillDeathRatioIRCCommand) +GENERIC_IRC_COMMAND(ShowModsIRCCommand) +GENERIC_IRC_COMMAND(ModsIRCCommand) +GENERIC_IRC_COMMAND(ShowRulesIRCCommand) +GENERIC_IRC_COMMAND(RulesIRCCommand) +GENERIC_IRC_COMMAND(SetRulesIRCCommand) +GENERIC_IRC_COMMAND(ReconnectIRCCommand) +GENERIC_IRC_COMMAND(RestartMapIRCCommand) +GENERIC_IRC_COMMAND(SetMapIRCCommand) +GENERIC_IRC_COMMAND(MuteIRCCommand) +GENERIC_IRC_COMMAND(UnMuteIRCCommand) +GENERIC_IRC_COMMAND(KickIRCCommand) +GENERIC_IRC_COMMAND(KickBanIRCCommand) +GENERIC_IRC_COMMAND(AddBotsIRCCommand) +GENERIC_IRC_COMMAND(KillBotsIRCCommand) +GENERIC_IRC_COMMAND(PhaseBotsIRCCommand) +GENERIC_IRC_COMMAND(RCONIRCCommand) + +GENERIC_GAME_COMMAND(HelpGameCommand) +GENERIC_GAME_COMMAND(ModsGameCommand) +GENERIC_GAME_COMMAND(RulesGameCommand) +GENERIC_GAME_COMMAND(ModRequestGameCommand) + +#endif // _RENX_COMMANDS_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX.Core.vcxproj b/RenX.Core/RenX.Core.vcxproj new file mode 100644 index 0000000..e5c0f20 --- /dev/null +++ b/RenX.Core/RenX.Core.vcxproj @@ -0,0 +1,95 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {9103DF3D-8B4A-48E5-A6B3-CBE2554630E2} + PluginExample + RenX.Core + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;RENX_EXPORTS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.Core/RenX.Core.vcxproj.filters b/RenX.Core/RenX.Core.vcxproj.filters new file mode 100644 index 0000000..0e497aa --- /dev/null +++ b/RenX.Core/RenX.Core.vcxproj.filters @@ -0,0 +1,65 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + \ No newline at end of file diff --git a/RenX.Core/RenX.h b/RenX.Core/RenX.h new file mode 100644 index 0000000..f175343 --- /dev/null +++ b/RenX.Core/RenX.h @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined RENX_API + +/** + * @file RenX.h + * @brief Defines RENX_API and some global enums for RenX. + * On anything other than Windows, RENX_API is defined as nothing, to prevent compiler errors. + */ + +#if defined _WIN32 + +#if defined RENX_EXPORTS +#define RENX_API __declspec(dllexport) +#else // RENX_EXPORTS +#define RENX_API __declspec(dllimport) +#endif // RENX_EXPORTS + +#else // _WIN32 +#define RENX_API +#endif // _WIN32 + +#if defined __cplusplus + +namespace RenX +{ + enum WinType + { + Score, + Base, + Beacon, + Tie, + Shutdown, + Unknown + }; + + enum TeamType + { + GDI, + Nod, + Other + }; + + enum ObjectType + { + Player, + Vehicle, + Building, + Defence + }; +} + +#endif // __cplusplus + +#endif // RENX_API \ No newline at end of file diff --git a/RenX.Core/RenX_Core.cpp b/RenX.Core/RenX_Core.cpp new file mode 100644 index 0000000..94bb701 --- /dev/null +++ b/RenX.Core/RenX_Core.cpp @@ -0,0 +1,619 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/INIFile.h" +#include "Jupiter/Functions.h" +#include "IRC_Bot.h" +#include "RenX_Core.h" +#include "RenX_Server.h" +#include "RenX_PlayerInfo.h" +#include "RenX_Functions.h" +#include "RenX_GameCommand.h" +#include "RenX_Plugin.h" + +RenX::Core pluginInstance; +RenX::Core *RenXInstance = &pluginInstance; + +RenX::Core *RenX::getCore() +{ + return &pluginInstance; +} + +RenX::Core::Core() +{ + const Jupiter::ReadableString &serverList = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX"), STRING_LITERAL_AS_REFERENCE("Servers")); + RenX::Core::translationsFile.readFile(Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX"), STRING_LITERAL_AS_REFERENCE("TranslationsFile"), STRING_LITERAL_AS_REFERENCE("Translations.ini"))); + + RenX::initTranslations(RenX::Core::translationsFile); + unsigned int wc = serverList.wordCount(WHITESPACE); + + RenX::Server *server; + for (unsigned int i = 0; i != wc; i++) + { + server = new RenX::Server(Jupiter::ReferenceString::getWord(serverList, i, WHITESPACE)); + + if (server->connect() == false) + { + fprintf(stderr, "[RenX] ERROR: Failed to connect to %.*s on port %u. Error code: %d" ENDL, server->getHostname().size(), server->getHostname().ptr(), server->getPort(), Jupiter::Socket::getLastError()); + delete server; + } + else RenX::Core::addServer(server); + } +} + +RenX::Core::~Core() +{ + RenX::Core::servers.emptyAndDelete(); +} + +int RenX::Core::send(RenX::Server *server, const Jupiter::ReadableString &msg) +{ + return server->send(msg); +} + +unsigned int RenX::Core::send(int type, const Jupiter::ReadableString &msg) +{ + unsigned int r = 0; + RenX::Server *server; + for (size_t i = 0; i != RenX::Core::servers.size(); i++) + { + server = RenX::Core::getServer(i); + if (server->isLogChanType(type) && RenX::Core::send(server, msg) > 0) r++; + } + return r; +} + +void RenX::Core::addServer(RenX::Server *server) +{ + RenX::Core::servers.add(server); +} + +int RenX::Core::getServerIndex(RenX::Server *server) +{ + for (size_t i = 0; i != RenX::Core::servers.size(); i++) + if (server == RenX::Core::servers.get(i)) + return i; + return -1; +} + +RenX::Server *RenX::Core::getServer(unsigned int index) +{ + return RenX::Core::servers.get(index); +} + +Jupiter::ArrayList RenX::Core::getServers(int type) +{ + Jupiter::ArrayList r; + RenX::Server *server; + for (size_t i = 0; i != RenX::Core::servers.size(); i++) + { + server = RenX::Core::servers.get(i); + if (server != nullptr && server->isLogChanType(type)) + r.add(server); + } + return r; +} + +void RenX::Core::removeServer(unsigned int index) +{ + delete RenX::Core::servers.remove(index); +} + +int RenX::Core::removeServer(RenX::Server *server) +{ + int i = RenX::Core::getServerIndex(server); + if (i >= 0) delete RenX::Core::servers.remove(i); + return i; +} + +unsigned int RenX::Core::getServerCount() +{ + return RenX::Core::servers.size(); +} + +Jupiter::ArrayList *RenX::Core::getPlugins() +{ + return &(RenX::Core::plugins); +} + +Jupiter::INIFile &RenX::Core::getTranslationsFile() +{ + return RenX::Core::translationsFile; +} + +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()); + } + return RenX::Core::servers.size(); +} + +// This shouldn't be needed later. +/*#define PARSE_PLAYER_DATA(STRING, OFFSET) \ + char *name = nullptr; int id; char team; \ + const char *p = strstr(buff, STRING); \ + if (p - buff - OFFSET < 12) { } \ + team = *(p - 3); \ + if (*(p - 9) == '<') id = atoi(p - 8); \ + else id = atoi(p - 9); \ + name = charToChar(buff + OFFSET + 1, 0, (int)(p - 10 - (buff + OFFSET + 1)));*/ + +#define PARSE_PLAYER_DATA() \ + Jupiter::ReferenceString name; \ + TeamType team; \ + int id; \ + bool isBot = false; { \ + Jupiter::ReferenceString idToken; \ + if (playerData[0] == ',') { \ + name = playerData.gotoWord(1, ","); \ + idToken = playerData.getWord(0, ","); \ + team = Other; \ + } else { \ + name = playerData.gotoWord(2, ","); \ + idToken = playerData.getWord(1, ","); \ + team = RenX::getTeam(playerData[0]); \ + } \ + if (idToken[0] == 'b') { idToken.shiftRight(1); isBot = true; } \ + id = idToken.asInt(10); } \ + RenX::PlayerInfo *player = getPlayerOrAdd(server, name, id, team, isBot); + +inline RenX::PlayerInfo *getPlayerOrAdd(RenX::Server *server, const Jupiter::ReadableString &name, int id, RenX::TeamType team, bool isBot) +{ + RenX::PlayerInfo *r = server->getPlayer(id); + if (r == nullptr) + { + r = new RenX::PlayerInfo(); + r->id = id; + r->name = name; + r->isBot = isBot; + r->joinTime = time(nullptr); + if (id != 0) server->players.add(r); + } + else if (r->name.size() == 0) r->name = name; + r->team = team; + return r; +} + +inline void onPreGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) +{ + RenX::PlayerInfo *player; + + if (server->players.size() != 0) + { + for (Jupiter::DLList::Node *n = server->players.getNode(0); n != nullptr; n = n->next) + { + player = n->data; + if (player != nullptr) + { + if (player->team == team) + player->wins++; + else player->loses++; + } + } + } +} + +inline void onPostGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) +{ + RenX::PlayerInfo *player; + + if (server->players.size() != 0) + { + for (Jupiter::DLList::Node *n = server->players.getNode(0); n != nullptr; n = n->next) + { + player = n->data; + if (player != nullptr) + { + player->kills = 0; + player->deaths = 0; + player->suicides = 0; + player->headshots = 0; + player->vehicleKills = 0; + player->buildingKills = 0; + player->defenceKills = 0; + } + } + } +} + +inline void onChat(RenX::Server *server, RenX::PlayerInfo *player, const Jupiter::ReadableString &message, bool isPublic) +{ + const Jupiter::ReadableString &prefix = server->getCommandPrefix(); + if (message.find(prefix) == 0 && message.size() != prefix.size()) + { + Jupiter::ReferenceString command; + Jupiter::ReferenceString parameters; + if (containsSymbol(WHITESPACE, message.get(prefix.size()))) + { + command = Jupiter::ReferenceString::getWord(message, 1, WHITESPACE); + parameters = Jupiter::ReferenceString::gotoWord(message, 2, WHITESPACE); + } + else + { + command = Jupiter::ReferenceString::getWord(message, 0, WHITESPACE); + command.shiftRight(prefix.size()); + parameters = Jupiter::ReferenceString::gotoWord(message, 1, WHITESPACE); + } + server->triggerCommand(command, player, parameters); + } +} + +int RenX::Core::think() +{ + // Change this later to just call server->think(). + RenX::Server *server; + for (size_t a = 0; a < RenX::Core::servers.size(); a++) + { + server = RenX::Core::servers.get(a); + if (server->isConnected() == false) + { + if (time(0) >= server->getLastAttempt() + server->getDelay()) + { + if (server->connect()) server->sendLogChan(IRCCOLOR "03[RenX]" IRCCOLOR " Socket successfully reconnected to Renegade-X server."); + else server->sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Failed to reconnect to Renegade-X server."); + } + } + else + { + if (server->sock.recv() > 0) + { + Jupiter::ReferenceString buffer = server->sock.getBuffer(); + unsigned int totalLines = buffer.wordCount(ENDL); + for (unsigned int currentLine = 0; currentLine != totalLines; currentLine++) + { + Jupiter::ReferenceString buff = buffer.getWord(currentLine, ENDL); + Jupiter::ReferenceString header = buff.getWord(0, RenX::DelimS); + Jupiter::ReferenceString playerData = buff.getWord(1, RenX::DelimS); + Jupiter::ReferenceString action = buff.getWord(2, RenX::DelimS); + + //printf("[RenX Dump] %.*s - %.*s - %.*s" ENDL, header.size(), header.ptr(), playerData.size(), playerData.ptr(), action.size(), action.ptr()); + + if (buff.size() != 0) + { + switch (header[0]) + { + case 'l': + if (header.equals("lGAME:")) + { + if (action.equals("deployed")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString objectType = buff.getWord(3, RenX::DelimS); + if (objectType.match("*Beacon")) player->beaconPlacements++; + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnDeploy(server, player, objectType); + } + else if (action.equals("suicided by")) + { + PARSE_PLAYER_DATA(); + player->deaths++; + player->suicides++; + Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnSuicide(server, player, damageType); + } + else if (action.equals("killed")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString victimData = buff.getWord(3, RenX::DelimS); + Jupiter::ReferenceString vname = victimData.getWord(2, ","); + Jupiter::ReferenceString vidToken = victimData.getWord(1, ","); + int vid; + bool visBot = false; + if (vidToken[0] == 'b') + { + vidToken.shiftRight(1); + visBot = true; + } + vid = vidToken.asInt(10); + TeamType vteam = RenX::getTeam(victimData.getWord(0, ",")[0]); + Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS); + RenX::PlayerInfo *victim = getPlayerOrAdd(server, vname, vid, vteam, visBot); + player->kills++; + if (damageType.equals("Rx_DmgType_Headshot")) player->headshots++; + victim->deaths++; + + if (server->needsCList) + { + server->sendData(STRING_LITERAL_AS_REFERENCE("clogclientlist\n")); + server->needsCList = false; + } + + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnKill(server, player, victim, damageType); + } + else if (action.match("died by")) + { + PARSE_PLAYER_DATA(); + player->deaths++; + Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnDie(server, player, damageType); + } + else if (action.match("destroyed*")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString victim = buff.getWord(3, RenX::DelimS); + Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS); + ObjectType type; + if (action.equals("destroyed building")) + { + type = Building; + player->buildingKills++; + } + else if (victim.match("Rx_Defence_*")) + { + type = Defence; + player->defenceKills++; + } + else + { + type = Vehicle; + player->vehicleKills++; + } + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnDestroy(server, player, victim, damageType, type); + } + else if (playerData.match("??? wins (*)")) + { + TeamType team = RenX::getTeam(playerData[0]); + int gScore = buff.getWord(2, RenX::DelimS).gotoWord(1, "=").asInt(10); + int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10); + Jupiter::ReferenceString winType = Jupiter::ReferenceString::substring(playerData, 10); + winType.truncate(1); + WinType iWinType = Unknown; + if (gScore == nScore) + iWinType = Tie; + else if (winType.equals("TimeLimit")) + iWinType = Score; + else if (winType.equals("Buildings")) + iWinType = Base; + + server->needsCList = true; + onPreGameOver(server, iWinType, team, gScore, nScore); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnGameOver(server, iWinType, team, gScore, nScore); + onPostGameOver(server, iWinType, team, gScore, nScore); + } + else if (playerData.equals("Tie")) + { + int gScore = action.gotoWord(1, "=").asInt(10); + int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10); + + server->needsCList = true; + if (gScore == nScore) + { + onPreGameOver(server, Tie, Other, gScore, nScore); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnGameOver(server, Tie, Other, gScore, nScore); + onPostGameOver(server, Tie, Other, gScore, nScore); + } + else + { + TeamType winTeam = gScore > nScore ? RenX::getTeam('G') : RenX::getTeam('N'); + onPreGameOver(server, Shutdown, winTeam, gScore, nScore); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnGameOver(server, Shutdown, winTeam, gScore, nScore); + onPostGameOver(server, Shutdown, winTeam, gScore, nScore); + } + } + else for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnGame(server, buff.gotoWord(1, RenX::DelimS)); + } + else if (header.equals("lCHAT:")) + { + if (action.equals("teamsay:")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS); + onChat(server, player, message, false); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnTeamChat(server, player, message); + } + else if (action.equals("say:")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS); + onChat(server, player, message, true); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnChat(server, player, message); + } + } + else if (header.equals("lPLAYER:")) + { + PARSE_PLAYER_DATA(); + if (action.equals("disconnected")) + { + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnPart(server, player); + server->removePlayer(player); + player = nullptr; + } + else if (action.equals("entered from")) + { + player->ip = buff.getWord(3, RenX::DelimS); + if (buff.getWord(4, RenX::DelimS).equals("steamid")) player->steamid = buff.getWord(5, RenX::DelimS); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnJoin(server, player); + } + else if (action.equals("changed name to:")) + { + Jupiter::ReferenceString newName = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnNameChange(server, player, newName); + player->name = newName; + } + } + else if (header.equals("lRCON:")) + { + if (action.equals("executed:")) + { + Jupiter::ReferenceString command = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnExecute(server, playerData, command); + } + else if (action.equals("subscribed")) for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnSubscribe(server, playerData); + else for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnRCON(server, buff.gotoWord(1, RenX::DelimS)); + } + else if (header.equals("lADMIN:")) + { + PARSE_PLAYER_DATA(); + if (action.equals("logged in as")) + { + player->adminType = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnAdminLogin(server, player); + } + else if (action.equals("logged out of")) + { + Jupiter::ReferenceString type = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnAdminLogout(server, player); + player->adminType = ""; + } + else for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnAdmin(server, buff.gotoWord(1, RenX::DelimS)); + } + else if (header.equals("lC-LIST:")) + { + // ID IP SteamID Team Name + + int id; + bool isBot = false; + if (playerData.get(0) == 'b') + { + isBot = true; + playerData.shiftRight(1); + id = playerData.asInt(10); + playerData.shiftLeft(1); + } + else id = playerData.asInt(10); + Jupiter::ReferenceString ip = playerData.getWord(1, WHITESPACE); + Jupiter::ReferenceString steamid = playerData.getWord(2, WHITESPACE); + RenX::TeamType team; + Jupiter::ReferenceString name; + if (steamid.equals("-----NO")) // RCONv2-2a + { + steamid = ""; + Jupiter::ReferenceString &teamToken = playerData.getWord(4, WHITESPACE); + if (teamToken.isEmpty()) + break; + team = getTeam(teamToken.get(0)); + name = playerData.gotoWord(5, WHITESPACE); + } + else + { + if (steamid.equals("-----NO-STEAM-----")) // RCONv2-2.5a + steamid = ""; + Jupiter::ReferenceString &teamToken = playerData.getWord(3, WHITESPACE); + if (teamToken.isEmpty()) + break; + team = getTeam(teamToken.get(0)); + name = playerData.gotoWord(4, WHITESPACE); + } + + RenX::PlayerInfo *player = getPlayerOrAdd(server, name, id, team, isBot); + if (player->ip.size() == 0) + { + player->ip = ip; + player->steamid = steamid; + } + } + else + { + buff.shiftRight(1); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnLog(server, buff); + buff.shiftLeft(1); + } + break; + + case 'c': + buff.shiftRight(1); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnCommand(server, buff); + buff.shiftLeft(1); + break; + + case 'e': + buff.shiftRight(1); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnError(server, buff); + buff.shiftLeft(1); + break; + + case 'v': + buff.shiftRight(1); + server->rconVersion = buff.asInt(10); + server->gameVersion = buff.substring(3); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnVersion(server, buff); + buff.shiftLeft(1); + break; + + case 'a': + buff.shiftRight(1); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnAuthorized(server, buff); + buff.shiftLeft(1); + break; + + default: + buff.shiftRight(1); + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnOther(server, header[0], buff); + buff.shiftLeft(1); + break; + } + for (size_t i = 0; i < RenX::Core::plugins.size(); i++) + RenX::Core::plugins.get(i)->RenX_OnRaw(server, buff); + } + } + } + else if (Jupiter::Socket::getLastError() != 10035) // This is a serious error + { + if (server->reconnect()) server->sendLogChan(IRCCOLOR "07[Warning]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt in progress."); + else + { + server->wipeData(); + server->sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt failed."); + } + } + } + } + return Jupiter::Plugin::think(); +} + +// Entry point + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} + +// Unload + +extern "C" __declspec(dllexport) void unload(void) +{ + while (pluginInstance.getPlugins()->size() > 0) freePlugin(pluginInstance.getPlugins()->remove(0)); +} diff --git a/RenX.Core/RenX_Core.h b/RenX.Core/RenX_Core.h new file mode 100644 index 0000000..67f481d --- /dev/null +++ b/RenX.Core/RenX_Core.h @@ -0,0 +1,188 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_CORE_H_HEADER +#define _RENX_CORE_H_HEADER + +/** + * @file RenX_Core.h + * @brief Provides Renegade-X RCON interaction. + */ + +#include "Jupiter/Plugin.h" +#include "Jupiter/INIFile.h" +#include "RenX.h" + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace RenX +{ + /** Forward delcarations */ + struct PlayerInfo; + class Server; + class Plugin; + class GameCommand; + + /** + * @brief Provides an interface for the Renegade-X RCON protocol. + * The core manages the servers its connected to. Otherwise, it's + * the same as any other Jupiter plugin. + */ + class RENX_API Core : public Jupiter::Plugin + { + public: + + /** + * @brief Loops through the Renegade-X servers and parses data. + * This should only be called by main(). + * + * @return Result of Jupiter::Plugin::Think(). + */ + virtual int think(); + + /** + * @brief Returns the name of the plugin. + * @see Jupiter::Plugin::getName(). + * + * @return Name of the plugin in a string. + */ + const Jupiter::ReadableString &getName() override { return name; } + + /** + * @brief Sends a command to a specific server. + * + * @param server Server to send the command to. + * @param data Command to send. + * @return Number of bytes sent on success, less than or equal to 0 otherwise. + */ + int send(Server *server, const Jupiter::ReadableString &data); + + /** + * @brief Sends a command to all servers of a specific type. + * + * @param type Server type to send the command to. + * @param data Command to send. + * @return Number of servers sent to on success, less than or equal to 0 otherwise. + */ + unsigned int send(int type, const Jupiter::ReadableString &data); + + /** + * @brief Adds a server to the server list. + * + * @param server Server to add to the list. + */ + void addServer(RenX::Server *server); + + /** + * @brief Fetches a server's index. + * + * @return Index of the server if it exists, -1 otherwise. + */ + int getServerIndex(RenX::Server *server); + + /** + * @brief Fetches a server based on its index. + * + * @param index Index of the server + * @return Server located at the specified index. + */ + RenX::Server *getServer(unsigned int index); + + /** + * @brief Constructs a list of servers based on their type. + * + * @param type Type of servers to fetch. + * @return ArrayList of servers with the same type. + */ + Jupiter::ArrayList getServers(int type); + + /** + * @brief Removes a server based on its index. + * + * @param index Index of the server + */ + void removeServer(unsigned int index); + + /** + * @brief Removes a server based on its data. + * + * @param server Server to be removed. + * @return Index of the server removed. + */ + int removeServer(RenX::Server *server); + + /** + * @brief Fetches the number of servers. + * + * @return Number of servers. + */ + unsigned int getServerCount(); + + /** + * @brief Fetches the Renegade-X plugins currently loaded. + * + * @return ArrayList containing pointers to the plugins. + */ + Jupiter::ArrayList *getPlugins(); + + /** + * @brief Fetches the translations override file. + * + * @return INIFile containing translations overrides. + */ + Jupiter::INIFile &getTranslationsFile(); + + /** + * @brief Copys a command, and passes it to each server. + * + * @param command Command to copy. + * @return Number of commands added. + */ + int addCommand(GameCommand *command); + + /** + * @brief Default constructor for the Core class. + */ + Core(); + + /** + * Destructor for the Core class. + */ + ~Core(); + + private: + /** Inaccessible private members */ + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.Core"); + Jupiter::ArrayList servers; + Jupiter::ArrayList plugins; + Jupiter::INIFile translationsFile; + }; + + RENX_API Core *getCore(); + +} + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _RENX_CORE_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_Functions.cpp b/RenX.Core/RenX_Functions.cpp new file mode 100644 index 0000000..0c73432 --- /dev/null +++ b/RenX.Core/RenX_Functions.cpp @@ -0,0 +1,592 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/Functions.h" +#include "Jupiter/INIFile.h" +#include "IRC_Bot.h" +#include "ServerManager.h" +#include "RenX_Functions.h" +#include "RenX_Core.h" +#include "RenX_Server.h" +#include "RenX_PlayerInfo.h" + +/** Team color translations */ +Jupiter::ReferenceString NodColor = "04"; +Jupiter::ReferenceString GDIColor = "08"; +Jupiter::ReferenceString OtherColor = "14"; + +/** Short team name translations */ +Jupiter::ReferenceString NodShortName = "Nod"; +Jupiter::ReferenceString GDIShortName = "GDI"; +Jupiter::ReferenceString OtherShortName = "N/A"; + +/** Long team name translations */ +Jupiter::ReferenceString NodLongName = "Brotherhood of Nod"; +Jupiter::ReferenceString GDILongName = "Global Defense Initiative"; +Jupiter::ReferenceString OtherLongName = "Unknown"; + +/** RenegadeX RCON protocol message deliminator */ +const char *RenX::DelimS = "\xA0"; +const char RenX::DelimC = *RenX::DelimS; + +/** WinType translations */ + +Jupiter::ReferenceString scoreWinTypeTranslation = "Domination (High Score)"; +Jupiter::ReferenceString baseWinTypeTranslation = "Conquest (Base Destruction)"; +Jupiter::ReferenceString beaconWinTypeTranslation = "Espionage (Beacon)"; +Jupiter::ReferenceString tieWinTypeTranslation = "Draw (Tie)"; +Jupiter::ReferenceString shutdownWinTypeTranslation = "Ceasefire (Shutdown)"; +Jupiter::ReferenceString unknownWinTypeTranslation = "Aliens (Unknown)"; + +/** WinType plain translations */ + +Jupiter::ReferenceString scoreWinTypePlainTranslation = "High Score"; +Jupiter::ReferenceString baseWinTypePlainTranslation = "Base Destruction"; +Jupiter::ReferenceString beaconWinTypePlainTranslation = "Beacon"; +Jupiter::ReferenceString tieWinTypePlainTranslation = "Tie"; +Jupiter::ReferenceString shutdownWinTypePlainTranslation = "Shutdown"; +Jupiter::ReferenceString unknownWinTypePlainTranslation = "Unknown"; + +/** Object / damage type translations */ + +/** Nod Vehicles */ +Jupiter::ReferenceString translated_Vehicle_Harvester_Nod = STRING_LITERAL_AS_REFERENCE("Nod Harvester"); +// Buggy -> Buggy +Jupiter::ReferenceString translated_Vehicle_Artillery = STRING_LITERAL_AS_REFERENCE("Mobile Artillery"); +Jupiter::ReferenceString translated_Vehicle_APC_Nod = STRING_LITERAL_AS_REFERENCE("Nod APC"); +Jupiter::ReferenceString translated_Vehicle_LightTank = STRING_LITERAL_AS_REFERENCE("Light Tank"); +Jupiter::ReferenceString translated_Vehicle_FlameTank = STRING_LITERAL_AS_REFERENCE("Flame Tank"); +Jupiter::ReferenceString translated_Vehicle_StealthTank = STRING_LITERAL_AS_REFERENCE("Stealth Tank"); +Jupiter::ReferenceString translated_Vehicle_Chinook_Nod = STRING_LITERAL_AS_REFERENCE("Nod Chinook"); +// Apache -> Apache + +/** GDI Vehicles */ +Jupiter::ReferenceString translated_Vehicle_Harvester_GDI = STRING_LITERAL_AS_REFERENCE("GDI Harvester"); +// Humvee -> Humvee +Jupiter::ReferenceString translated_Vehicle_MRLS = STRING_LITERAL_AS_REFERENCE("Mobile Rocket Launcher System"); +Jupiter::ReferenceString translated_Vehicle_APC_GDI = STRING_LITERAL_AS_REFERENCE("GDI APC"); +Jupiter::ReferenceString translated_Vehicle_MediumTank = STRING_LITERAL_AS_REFERENCE("Medium Tank"); +Jupiter::ReferenceString translated_Vehicle_MammothTank = STRING_LITERAL_AS_REFERENCE("Mammoth Tank"); +Jupiter::ReferenceString translated_Vehicle_Chinook_GDI = STRING_LITERAL_AS_REFERENCE("GDI Chinook"); +// Orca -> Orca + +/** Other Vehicles */ +Jupiter::ReferenceString translated_Vehicle_A10_DmgType_GattlingGun = STRING_LITERAL_AS_REFERENCE("A10 Thunderbolt Gattling Gun"); +Jupiter::ReferenceString translated_Vehicle_A10_DmgType_Bomb = STRING_LITERAL_AS_REFERENCE("A10 Thunderbolt Bomb"); +Jupiter::ReferenceString translated_Vehicle_AC130_DmgType_HeavyCannon = STRING_LITERAL_AS_REFERENCE("AC130 Heavy Cannon"); +Jupiter::ReferenceString translated_Vehicle_AC130_DmgType_AutoCannon = STRING_LITERAL_AS_REFERENCE("AC130 Auto Cannon"); + +/** Non-weapon damage types */ +Jupiter::ReferenceString translated_DmgType_Suicided = STRING_LITERAL_AS_REFERENCE("Suicide"); +Jupiter::ReferenceString translated_DmgType_Tiberium = STRING_LITERAL_AS_REFERENCE("Tiberium"); +Jupiter::ReferenceString translated_DmgType_TiberiumBleed = STRING_LITERAL_AS_REFERENCE("Tiberium Decay"); +Jupiter::ReferenceString translated_DmgType_RanOver = STRING_LITERAL_AS_REFERENCE("Crushed"); + +/** Infantry weapons */ +// Pistol -> Pistol +Jupiter::ReferenceString translated_DmgType_SMG = STRING_LITERAL_AS_REFERENCE("Machine Pistol"); +Jupiter::ReferenceString translated_DmgType_HeavyPistol = STRING_LITERAL_AS_REFERENCE("Heavy Pistol"); +// Carbine -> Carbine +Jupiter::ReferenceString translated_DmgType_TiberiumFlechetteRifle = STRING_LITERAL_AS_REFERENCE("Tiberium Flechette Gun"); // Not a rifle. +Jupiter::ReferenceString translated_DmgType_TiberiumAutoRifle = STRING_LITERAL_AS_REFERENCE("Tiberium Automatic Rifle"); + +// Grenade -> Grenade +Jupiter::ReferenceString translated_DmgType_TimedC4 = STRING_LITERAL_AS_REFERENCE("Timed C4"); +Jupiter::ReferenceString translated_DmgType_RemoteC4 = STRING_LITERAL_AS_REFERENCE("Remote C4"); +Jupiter::ReferenceString translated_DmgType_ProxyC4 = STRING_LITERAL_AS_REFERENCE("Proximity C4"); +Jupiter::ReferenceString translated_DmgType_BurnC4 = STRING_LITERAL_AS_REFERENCE("C4 Burn"); +Jupiter::ReferenceString translated_DmgType_FireBleed = STRING_LITERAL_AS_REFERENCE("Fire Burn"); // Caused by C4 or flame weapons + +Jupiter::ReferenceString translated_DmgType_AutoRifle = STRING_LITERAL_AS_REFERENCE("Automatic Rifle"); +// Shotgun -> Shotgun +Jupiter::ReferenceString translated_DmgType_FlameThrower = STRING_LITERAL_AS_REFERENCE("Flamethrower"); +Jupiter::ReferenceString translated_DmgType_GrenadeLauncher = STRING_LITERAL_AS_REFERENCE("Grenade Launcher"); +Jupiter::ReferenceString translated_DmgType_MarksmanRifle = STRING_LITERAL_AS_REFERENCE("Marksman's Rifle"); + +Jupiter::ReferenceString translated_DmgType_ChainGun = STRING_LITERAL_AS_REFERENCE("Chain Gun"); +Jupiter::ReferenceString translated_DmgType_MissileLauncher = STRING_LITERAL_AS_REFERENCE("Missile Launcher"); +Jupiter::ReferenceString translated_DmgType_MissileLauncher_Alt = STRING_LITERAL_AS_REFERENCE("Missile Launcher"); +Jupiter::ReferenceString translated_DmgType_ChemicalThrower = STRING_LITERAL_AS_REFERENCE("Chemical Spray Gun"); +Jupiter::ReferenceString translated_DmgType_LaserRifle = STRING_LITERAL_AS_REFERENCE("Laser Rifle"); +Jupiter::ReferenceString translated_DmgType_TacticalRifle = STRING_LITERAL_AS_REFERENCE("Tactical Rifle"); +Jupiter::ReferenceString translated_DmgType_RocketLauncher = STRING_LITERAL_AS_REFERENCE("Rocket Launcher"); +Jupiter::ReferenceString translated_DmgType_LaserChainGun = STRING_LITERAL_AS_REFERENCE("Laser Chain Gun"); +Jupiter::ReferenceString translated_DmgType_FlakCannon = STRING_LITERAL_AS_REFERENCE("Flak"); +Jupiter::ReferenceString translated_DmgType_FlakCannon_Alt = STRING_LITERAL_AS_REFERENCE("Concentrated Flak"); +Jupiter::ReferenceString translated_DmgType_SniperRifle = STRING_LITERAL_AS_REFERENCE("Sniper Rifle"); +Jupiter::ReferenceString translated_DmgType_RamjetRifle = STRING_LITERAL_AS_REFERENCE("Ramjet"); +// Railgun -> Railgun +Jupiter::ReferenceString translated_DmgType_PersonalIonCannon = STRING_LITERAL_AS_REFERENCE("Personal Ion Cannon"); +Jupiter::ReferenceString translated_DmgType_VoltRifle = STRING_LITERAL_AS_REFERENCE("Volt Rifle"); +Jupiter::ReferenceString translated_DmgType_VoltRifle_Alt = STRING_LITERAL_AS_REFERENCE("Volt Rifle Burst"); +Jupiter::ReferenceString translated_DmgType_VoltAutoRifle = STRING_LITERAL_AS_REFERENCE("Volt Automatic Rifle"); +Jupiter::ReferenceString translated_DmgType_VoltAutoRifle_Alt = STRING_LITERAL_AS_REFERENCE("Volt Automatic Rifle Burst"); + +/** Vehicle weapons */ +Jupiter::ReferenceString translated_DmgType_MammothTank_Missile = STRING_LITERAL_AS_REFERENCE("Mammoth Tank Missile"); +Jupiter::ReferenceString translated_DmgType_MammothTank_Cannon = STRING_LITERAL_AS_REFERENCE("Mammoth Tank Cannon"); +Jupiter::ReferenceString translated_DmgType_Orca_Missile = STRING_LITERAL_AS_REFERENCE("Orca Missle"); +Jupiter::ReferenceString translated_DmgType_Orca_Gun = STRING_LITERAL_AS_REFERENCE("Orca Gun"); +Jupiter::ReferenceString translated_DmgType_Apache_Rocket = STRING_LITERAL_AS_REFERENCE("Apache Rocket"); +Jupiter::ReferenceString translated_DmgType_Apache_Gun = STRING_LITERAL_AS_REFERENCE("Apache Gun"); + +/** Other weapons */ +Jupiter::ReferenceString translated_DmgType_Nuke = STRING_LITERAL_AS_REFERENCE("Nuclear Missile Strike"); +Jupiter::ReferenceString translated_DmgType_IonCannon = STRING_LITERAL_AS_REFERENCE("Ion Cannon Strike"); +Jupiter::ReferenceString translated_DmgType_GunEmpl = STRING_LITERAL_AS_REFERENCE("Gun Emplacement Gattling Gun"); +Jupiter::ReferenceString translated_DmgType_GunEmpl_Alt = STRING_LITERAL_AS_REFERENCE("Gun Emplacement Automatic Cannon"); +Jupiter::ReferenceString translated_DmgType_RocketEmpl_Swarm = STRING_LITERAL_AS_REFERENCE("Rocket Emplacement Swarm Missile"); +Jupiter::ReferenceString translated_DmgType_RocketEmpl_Missile = STRING_LITERAL_AS_REFERENCE("Rocket Emplacement Hellfire Missile"); + +// Vehicles copied from above. + +/** Nod Vehicles */ +Jupiter::ReferenceString translated_DmgType_Harvester_Nod = STRING_LITERAL_AS_REFERENCE("Nod Harvester"); +// Buggy -> Buggy +Jupiter::ReferenceString translated_DmgType_Artillery = STRING_LITERAL_AS_REFERENCE("Mobile Artillery"); +Jupiter::ReferenceString translated_DmgType_APC_Nod = STRING_LITERAL_AS_REFERENCE("Nod APC"); +Jupiter::ReferenceString translated_DmgType_LightTank = STRING_LITERAL_AS_REFERENCE("Light Tank"); +Jupiter::ReferenceString translated_DmgType_FlameTank = STRING_LITERAL_AS_REFERENCE("Flame Tank"); +Jupiter::ReferenceString translated_DmgType_StealthTank = STRING_LITERAL_AS_REFERENCE("Stealth Tank"); +Jupiter::ReferenceString translated_DmgType_Chinook_Nod = STRING_LITERAL_AS_REFERENCE("Nod Chinook"); +// Apache -> Apache + +/** GDI Vehicles */ +Jupiter::ReferenceString translated_DmgType_Harvester_GDI = STRING_LITERAL_AS_REFERENCE("GDI Harvester"); +// Humvee -> Humvee +Jupiter::ReferenceString translated_DmgType_MRLS = STRING_LITERAL_AS_REFERENCE("Mobile Rocket Launcher System"); +Jupiter::ReferenceString translated_DmgType_APC_GDI = STRING_LITERAL_AS_REFERENCE("GDI APC"); +Jupiter::ReferenceString translated_DmgType_MediumTank = STRING_LITERAL_AS_REFERENCE("Medium Tank"); +Jupiter::ReferenceString translated_DmgType_MammothTank = STRING_LITERAL_AS_REFERENCE("Mammoth Tank"); +Jupiter::ReferenceString translated_DmgType_Chinook_GDI = STRING_LITERAL_AS_REFERENCE("GDI Chinook"); +// Orca -> Orca + +/** Other Vehicles */ +Jupiter::ReferenceString translated_DmgType_A10_DmgType_GattlingGun = STRING_LITERAL_AS_REFERENCE("A10 Thunderbolt Gattling Gun"); +Jupiter::ReferenceString translated_DmgType_A10_DmgType_Bomb = STRING_LITERAL_AS_REFERENCE("A10 Thunderbolt Bomb"); +Jupiter::ReferenceString translated_DmgType_AC130_DmgType_HeavyCannon = STRING_LITERAL_AS_REFERENCE("AC130 Heavy Cannon"); +Jupiter::ReferenceString translated_DmgType_AC130_DmgType_AutoCannon = STRING_LITERAL_AS_REFERENCE("AC130 Auto Cannon"); + +/** Nod structures */ +Jupiter::ReferenceString translated_Building_HandOfNod_Internals = STRING_LITERAL_AS_REFERENCE("Hand of Nod"); +Jupiter::ReferenceString translated_Building_AirTower_Internals = STRING_LITERAL_AS_REFERENCE("Airstrip"); +Jupiter::ReferenceString translated_Building_Refinery_Nod_Internals = STRING_LITERAL_AS_REFERENCE("Nod Refinery"); +Jupiter::ReferenceString translated_Building_PowerPlant_Nod_Internals = STRING_LITERAL_AS_REFERENCE("Nod Power Plant"); + +/** GDI structures */ +Jupiter::ReferenceString translated_Building_Barracks_Internals = STRING_LITERAL_AS_REFERENCE("Barracks"); +Jupiter::ReferenceString translated_Building_WeaponsFactory_Internals = STRING_LITERAL_AS_REFERENCE("Weapons Factory"); +Jupiter::ReferenceString translated_Building_Refinery_GDI_Internals = STRING_LITERAL_AS_REFERENCE("GDI Refinery"); +Jupiter::ReferenceString translated_Building_PowerPlant_GDI_Internals = STRING_LITERAL_AS_REFERENCE("GDI Power Plant"); + +/** Defense structures */ +Jupiter::ReferenceString translated_Building_AdvancedGuardTower_Internals = STRING_LITERAL_AS_REFERENCE("Advanced Guard Tower"); +Jupiter::ReferenceString translated_Building_Obelisk_Internals = STRING_LITERAL_AS_REFERENCE("Obelisk of Light"); + +/** Defences */ +Jupiter::ReferenceString translated_Defence_GuardTower = STRING_LITERAL_AS_REFERENCE("Guard Tower"); +Jupiter::ReferenceString translated_Defence_Turret = STRING_LITERAL_AS_REFERENCE("Turret"); +Jupiter::ReferenceString translated_Defence_SAMSite = STRING_LITERAL_AS_REFERENCE("SAM Site"); +Jupiter::ReferenceString translated_Defence_AATower = STRING_LITERAL_AS_REFERENCE("Anti-Air Guard Tower"); +Jupiter::ReferenceString translated_Defence_GunEmplacement = STRING_LITERAL_AS_REFERENCE("Gun Emplacement"); +Jupiter::ReferenceString translated_Defence_RocketEmplacement = STRING_LITERAL_AS_REFERENCE("Rocket Emplacement"); + +/** UT damage types */ +Jupiter::ReferenceString translated_UTDmgType_VehicleExplosion = STRING_LITERAL_AS_REFERENCE("Vehicle Explosion"); + +/** Beacons */ +Jupiter::ReferenceString translated_IonCannonBeacon = STRING_LITERAL_AS_REFERENCE("Ion Cannon Strike"); +Jupiter::ReferenceString translated_NukeBeacon = STRING_LITERAL_AS_REFERENCE("Nuclear Strike Beacon"); +Jupiter::ReferenceString translated_KillZDamageType = STRING_LITERAL_AS_REFERENCE("Kill Zone"); + +RenX::TeamType RenX::getTeam(char team) +{ + switch (team) + { + case 'g': + case 'G': + return GDI; + case 'n': + case 'N': + return Nod; + default: + return Other; + } +} + +const Jupiter::ReadableString &RenX::getTeamColor(TeamType team) +{ + switch (team) + { + case GDI: + return GDIColor; + case Nod: + return NodColor; + default: + return OtherColor; + } +} + +const Jupiter::ReadableString &RenX::getTeamName(TeamType team) +{ + switch (team) + { + case GDI: + return GDIShortName; + case Nod: + return NodShortName; + default: + return OtherShortName; + } +} + +const Jupiter::ReadableString &RenX::getFullTeamName(TeamType team) +{ + switch (team) + { + case GDI: + return GDILongName; + case Nod: + return NodLongName; + default: + return OtherLongName; + } +} + +RenX::TeamType RenX::getEnemy(TeamType team) +{ + switch (team) + { + case GDI: + return Nod; + case Nod: + return GDI; + default: + return Other; + } +} + +inline const Jupiter::ReadableString &checkINIForValue(const Jupiter::ReadableString §ion, const Jupiter::ReadableString &key) +{ + return RenX::getCore()->getTranslationsFile().get(section, key); +} + +const Jupiter::ReadableString &RenX::translateName(const Jupiter::ReadableString &obj) +{ + if (obj.isEmpty()) + return Jupiter::ReferenceString::empty; + + Jupiter::ReferenceString iniTranslation = checkINIForValue(STRING_LITERAL_AS_REFERENCE("Name"), obj); + if (iniTranslation.isEmpty() == false) + return iniTranslation; + + static Jupiter::ReferenceString object; + object = obj; + + if (object.find(STRING_LITERAL_AS_REFERENCE("Rx_")) == 0) + object.shiftRight(3); + + if (object.find(STRING_LITERAL_AS_REFERENCE("Vehicle_")) == 0) + { + object.shiftRight(8); + + /** Nod Vehicles */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("Harvester_Nod"))) return translated_Vehicle_Harvester_Nod; + // Buggy -> Buggy + if (object.equals(STRING_LITERAL_AS_REFERENCE("Artillery"))) return translated_Vehicle_Artillery; + if (object.equals(STRING_LITERAL_AS_REFERENCE("APC_Nod"))) return translated_Vehicle_APC_Nod; + if (object.equals(STRING_LITERAL_AS_REFERENCE("LightTank"))) return translated_Vehicle_LightTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("FlameTank"))) return translated_Vehicle_FlameTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("StealthTank"))) return translated_Vehicle_StealthTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Chinook_Nod"))) return translated_Vehicle_Chinook_Nod; + // Apache -> Apache + + /** GDI Vehicles */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("Harvester_GDI"))) return translated_Vehicle_Harvester_GDI; + // Humvee -> Humvee + if (object.equals(STRING_LITERAL_AS_REFERENCE("MRLS"))) return translated_Vehicle_MRLS; + if (object.equals(STRING_LITERAL_AS_REFERENCE("APC_GDI"))) return translated_Vehicle_APC_GDI; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MediumTank"))) return translated_Vehicle_MediumTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MammothTank"))) return translated_Vehicle_MammothTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Chinook_GDI"))) return translated_Vehicle_Chinook_GDI; + // Orca -> Orca + + /** Other Vehicles */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("A10_DmgType_GattlingGun"))) return translated_Vehicle_A10_DmgType_GattlingGun; + if (object.equals(STRING_LITERAL_AS_REFERENCE("A10_DmgType_Bomb"))) return translated_Vehicle_A10_DmgType_Bomb; + if (object.equals(STRING_LITERAL_AS_REFERENCE("AC130_DmgType_HeavyCannon"))) return translated_Vehicle_AC130_DmgType_HeavyCannon; + if (object.equals(STRING_LITERAL_AS_REFERENCE("AC130_DmgType_AutoCannon"))) return translated_Vehicle_AC130_DmgType_AutoCannon; + } + else if (object.find(STRING_LITERAL_AS_REFERENCE("DmgType_")) == 0) + { + object.shiftRight(8); + + /** Non-weapon damage types */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("Suicided"))) return translated_DmgType_Suicided; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Tiberium"))) return translated_DmgType_Tiberium; + if (object.equals(STRING_LITERAL_AS_REFERENCE("TiberiumBleed"))) return translated_DmgType_TiberiumBleed; + if (object.equals(STRING_LITERAL_AS_REFERENCE("RanOver"))) return translated_DmgType_RanOver; + + /** Infantry weapons */ + // Pistol -> Pistol + if (object.equals(STRING_LITERAL_AS_REFERENCE("SMG"))) return translated_DmgType_SMG; + if (object.equals(STRING_LITERAL_AS_REFERENCE("HeavyPistol"))) return translated_DmgType_HeavyPistol; + // Carbine -> Carbine + if (object.equals(STRING_LITERAL_AS_REFERENCE("TiberiumFlechetteRifle"))) return translated_DmgType_TiberiumFlechetteRifle; // Not a rifle. + if (object.equals(STRING_LITERAL_AS_REFERENCE("TiberiumAutoRifle"))) return translated_DmgType_TiberiumAutoRifle; + + // Grenade -> Grenade + if (object.equals(STRING_LITERAL_AS_REFERENCE("TimedC4"))) return translated_DmgType_TimedC4; + if (object.equals(STRING_LITERAL_AS_REFERENCE("RemoteC4"))) return translated_DmgType_RemoteC4; + if (object.equals(STRING_LITERAL_AS_REFERENCE("ProxyC4"))) return translated_DmgType_ProxyC4; + if (object.equals(STRING_LITERAL_AS_REFERENCE("BurnC4"))) return translated_DmgType_BurnC4; + if (object.equals(STRING_LITERAL_AS_REFERENCE("FireBleed"))) return translated_DmgType_FireBleed; // Caused by C4 or flame weapons + + if (object.equals(STRING_LITERAL_AS_REFERENCE("AutoRifle"))) return translated_DmgType_AutoRifle; + // Shotgun -> Shotgun + if (object.equals(STRING_LITERAL_AS_REFERENCE("FlameThrower"))) return translated_DmgType_FlameThrower; + if (object.equals(STRING_LITERAL_AS_REFERENCE("GrenadeLauncher"))) return translated_DmgType_GrenadeLauncher; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MarksmanRifle"))) return translated_DmgType_MarksmanRifle; + + if (object.equals(STRING_LITERAL_AS_REFERENCE("ChainGun"))) return translated_DmgType_ChainGun; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MissileLauncher"))) return translated_DmgType_MissileLauncher; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MissileLauncher_Alt"))) return translated_DmgType_MissileLauncher_Alt; + if (object.equals(STRING_LITERAL_AS_REFERENCE("ChemicalThrower"))) return translated_DmgType_ChemicalThrower; + if (object.equals(STRING_LITERAL_AS_REFERENCE("LaserRifle"))) return translated_DmgType_LaserRifle; + if (object.equals(STRING_LITERAL_AS_REFERENCE("TacticalRifle"))) return translated_DmgType_TacticalRifle; + if (object.equals(STRING_LITERAL_AS_REFERENCE("RocketLauncher"))) return translated_DmgType_RocketLauncher; + if (object.equals(STRING_LITERAL_AS_REFERENCE("LaserChainGun"))) return translated_DmgType_LaserChainGun; + if (object.equals(STRING_LITERAL_AS_REFERENCE("FlakCannon"))) return translated_DmgType_FlakCannon; + if (object.equals(STRING_LITERAL_AS_REFERENCE("FlakCannon_Alt"))) return translated_DmgType_FlakCannon_Alt; + if (object.equals(STRING_LITERAL_AS_REFERENCE("SniperRifle"))) return translated_DmgType_SniperRifle; + if (object.equals(STRING_LITERAL_AS_REFERENCE("RamjetRifle"))) return translated_DmgType_RamjetRifle; + // Railgun -> Railgun + if (object.equals(STRING_LITERAL_AS_REFERENCE("PersonalIonCannon"))) return translated_DmgType_PersonalIonCannon; + if (object.equals(STRING_LITERAL_AS_REFERENCE("VoltRifle"))) return translated_DmgType_VoltRifle; + if (object.equals(STRING_LITERAL_AS_REFERENCE("VoltRifle_Alt"))) return translated_DmgType_VoltRifle_Alt; + if (object.equals(STRING_LITERAL_AS_REFERENCE("VoltAutoRifle"))) return translated_DmgType_VoltAutoRifle; + if (object.equals(STRING_LITERAL_AS_REFERENCE("VoltAutoRifle_Alt"))) return translated_DmgType_VoltAutoRifle_Alt; + + /** Vehicle weapons */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("MammothTank_Missile"))) return translated_DmgType_MammothTank_Missile; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MammothTank_Cannon"))) return translated_DmgType_MammothTank_Cannon; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Orca_Missile"))) return translated_DmgType_Orca_Missile; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Orca_Gun"))) return translated_DmgType_Orca_Gun; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Apache_Rocket"))) return translated_DmgType_Apache_Rocket; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Apache_Gun"))) return translated_DmgType_Apache_Gun; + + /** Other weapons */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("Nuke"))) return translated_DmgType_Nuke; + if (object.equals(STRING_LITERAL_AS_REFERENCE("IonCannon"))) return translated_DmgType_IonCannon; + if (object.equals(STRING_LITERAL_AS_REFERENCE("GunEmpl"))) return translated_DmgType_GunEmpl; + if (object.equals(STRING_LITERAL_AS_REFERENCE("GunEmpl_Alt"))) return translated_DmgType_GunEmpl_Alt; + if (object.equals(STRING_LITERAL_AS_REFERENCE("RocketEmpl_Swarm"))) return translated_DmgType_RocketEmpl_Swarm; + if (object.equals(STRING_LITERAL_AS_REFERENCE("RocketEmpl_Missile"))) return translated_DmgType_RocketEmpl_Missile; + + // Vehicles copied from above. + + /** Nod Vehicles */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("Harvester_Nod"))) return translated_DmgType_Harvester_Nod; + // Buggy -> Buggy + if (object.equals(STRING_LITERAL_AS_REFERENCE("Artillery"))) return translated_DmgType_Artillery; + if (object.equals(STRING_LITERAL_AS_REFERENCE("APC_Nod"))) return translated_DmgType_APC_Nod; + if (object.equals(STRING_LITERAL_AS_REFERENCE("LightTank"))) return translated_DmgType_LightTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("FlameTank"))) return translated_DmgType_FlameTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("StealthTank"))) return translated_DmgType_StealthTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Chinook_Nod"))) return translated_DmgType_Chinook_Nod; + // Apache -> Apache + + /** GDI Vehicles */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("Harvester_GDI"))) return translated_DmgType_Harvester_GDI; + // Humvee -> Humvee + if (object.equals(STRING_LITERAL_AS_REFERENCE("MRLS"))) return translated_DmgType_MRLS; + if (object.equals(STRING_LITERAL_AS_REFERENCE("APC_GDI"))) return translated_DmgType_APC_GDI; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MediumTank"))) return translated_DmgType_MediumTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("MammothTank"))) return translated_DmgType_MammothTank; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Chinook_GDI"))) return translated_DmgType_Chinook_GDI; + // Orca -> Orca + + /** Other Vehicles */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("A10_DmgType_GattlingGun"))) return translated_DmgType_A10_DmgType_GattlingGun; + if (object.equals(STRING_LITERAL_AS_REFERENCE("A10_DmgType_Bomb"))) return translated_DmgType_A10_DmgType_Bomb; + if (object.equals(STRING_LITERAL_AS_REFERENCE("AC130_DmgType_HeavyCannon"))) return translated_DmgType_AC130_DmgType_HeavyCannon; + if (object.equals(STRING_LITERAL_AS_REFERENCE("AC130_DmgType_AutoCannon"))) return translated_DmgType_AC130_DmgType_AutoCannon; + } + else if (object.find(STRING_LITERAL_AS_REFERENCE("Building_")) == 0) + { + object.shiftRight(9); + /** Nod structures */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("HandOfNod_Internals"))) return translated_Building_HandOfNod_Internals; + if (object.equals(STRING_LITERAL_AS_REFERENCE("AirTower_Internals"))) return translated_Building_AirTower_Internals; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Refinery_Nod_Internals"))) return translated_Building_Refinery_Nod_Internals; + if (object.equals(STRING_LITERAL_AS_REFERENCE("PowerPlant_Nod_Internals"))) return translated_Building_PowerPlant_Nod_Internals; + + /** GDI structures */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("Barracks_Internals"))) return translated_Building_Barracks_Internals; + if (object.equals(STRING_LITERAL_AS_REFERENCE("WeaponsFactory_Internals"))) return translated_Building_WeaponsFactory_Internals; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Refinery_GDI_Internals"))) return translated_Building_Refinery_GDI_Internals; + if (object.equals(STRING_LITERAL_AS_REFERENCE("PowerPlant_GDI_Internals"))) return translated_Building_PowerPlant_GDI_Internals; + + /** Defense structures */ + if (object.equals(STRING_LITERAL_AS_REFERENCE("AdvancedGuardTower_Internals"))) return translated_Building_AdvancedGuardTower_Internals; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Obelisk_Internals"))) return translated_Building_Obelisk_Internals; + } + else if (object.find(STRING_LITERAL_AS_REFERENCE("Defence_")) == 0) + { + object.shiftRight(8); + if (object.equals(STRING_LITERAL_AS_REFERENCE("GuardTower"))) return translated_Defence_GuardTower; + if (object.equals(STRING_LITERAL_AS_REFERENCE("Turret"))) return translated_Defence_Turret; + if (object.equals(STRING_LITERAL_AS_REFERENCE("SAMSite"))) return translated_Defence_SAMSite; + if (object.equals(STRING_LITERAL_AS_REFERENCE("AATower"))) return translated_Defence_AATower; + if (object.equals(STRING_LITERAL_AS_REFERENCE("GunEmplacement"))) return translated_Defence_GunEmplacement; + if (object.equals(STRING_LITERAL_AS_REFERENCE("RocketEmplacement"))) return translated_Defence_RocketEmplacement; + } + else if (object.find(STRING_LITERAL_AS_REFERENCE("UTDmgType_")) == 0) + { + object.shiftRight(10); + if (object.equals(STRING_LITERAL_AS_REFERENCE("VehicleExplosion"))) return translated_UTDmgType_VehicleExplosion; + // Drowned -> Drowned + } + else if (object.equals(STRING_LITERAL_AS_REFERENCE("IonCannonBeacon"))) return translated_IonCannonBeacon; + else if (object.equals(STRING_LITERAL_AS_REFERENCE("NukeBeacon"))) return translated_NukeBeacon; + else if (object.equals(STRING_LITERAL_AS_REFERENCE("KillZDamageType"))) return translated_KillZDamageType; + return object; +} + +const Jupiter::ReadableString &RenX::translateWinType(RenX::WinType winType) +{ + switch (winType) + { + case Score: + return scoreWinTypeTranslation; + case Base: + return baseWinTypeTranslation; + case Beacon: + return beaconWinTypeTranslation; + case Tie: + return tieWinTypeTranslation; + case Shutdown: + return shutdownWinTypeTranslation; + case Unknown: + default: + return unknownWinTypeTranslation; + } +} + +const Jupiter::ReadableString &RenX::translateWinTypePlain(RenX::WinType winType) +{ + switch (winType) + { + case Score: + return scoreWinTypePlainTranslation; + case Base: + return baseWinTypePlainTranslation; + case Beacon: + return beaconWinTypePlainTranslation; + case Tie: + return tieWinTypePlainTranslation; + case Shutdown: + return shutdownWinTypePlainTranslation; + case Unknown: + default: + return unknownWinTypePlainTranslation; + } +} + +void RenX::initTranslations(Jupiter::INIFile &translationsFile) +{ + NodColor = translationsFile.get(STRING_LITERAL_AS_REFERENCE("TeamColor"), STRING_LITERAL_AS_REFERENCE("Nod"), STRING_LITERAL_AS_REFERENCE("04")); + GDIColor = translationsFile.get(STRING_LITERAL_AS_REFERENCE("TeamColor"), STRING_LITERAL_AS_REFERENCE("GDI"), STRING_LITERAL_AS_REFERENCE("08")); + OtherColor = translationsFile.get(STRING_LITERAL_AS_REFERENCE("TeamColor"), STRING_LITERAL_AS_REFERENCE("Other"), STRING_LITERAL_AS_REFERENCE("14")); + + NodShortName = translationsFile.get(STRING_LITERAL_AS_REFERENCE("ShortTeamName"), STRING_LITERAL_AS_REFERENCE("Nod"), STRING_LITERAL_AS_REFERENCE("Nod")); + GDIShortName = translationsFile.get(STRING_LITERAL_AS_REFERENCE("ShortTeamName"), STRING_LITERAL_AS_REFERENCE("GDI"), STRING_LITERAL_AS_REFERENCE("GDI")); + OtherShortName = translationsFile.get(STRING_LITERAL_AS_REFERENCE("ShortTeamName"), STRING_LITERAL_AS_REFERENCE("Other"), STRING_LITERAL_AS_REFERENCE("N/A")); + NodLongName = translationsFile.get(STRING_LITERAL_AS_REFERENCE("LongTeamName"), STRING_LITERAL_AS_REFERENCE("Nod"), STRING_LITERAL_AS_REFERENCE("Brotherhood of Nod")); + GDILongName = translationsFile.get(STRING_LITERAL_AS_REFERENCE("LongTeamName"), STRING_LITERAL_AS_REFERENCE("GDI"), STRING_LITERAL_AS_REFERENCE("Global Defense Initiative")); + OtherLongName = translationsFile.get(STRING_LITERAL_AS_REFERENCE("LongTeamName"), STRING_LITERAL_AS_REFERENCE("Other"), STRING_LITERAL_AS_REFERENCE("Unknown")); + + scoreWinTypeTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinType"), STRING_LITERAL_AS_REFERENCE("Score"), STRING_LITERAL_AS_REFERENCE("Domination (High Score)")); + baseWinTypeTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinType"), STRING_LITERAL_AS_REFERENCE("Base"), STRING_LITERAL_AS_REFERENCE("Conquest (Base Destruction)")); + beaconWinTypeTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinType"), STRING_LITERAL_AS_REFERENCE("Beacon"), STRING_LITERAL_AS_REFERENCE("Espionage (Beacon)")); + tieWinTypeTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinType"), STRING_LITERAL_AS_REFERENCE("Tie"), STRING_LITERAL_AS_REFERENCE("Draw (Tie)")); + shutdownWinTypeTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinType"), STRING_LITERAL_AS_REFERENCE("Shutdown"), STRING_LITERAL_AS_REFERENCE("Ceasefire (Shutdown)")); + unknownWinTypeTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinType"), STRING_LITERAL_AS_REFERENCE("Unknown"), STRING_LITERAL_AS_REFERENCE("Aliens (Unknown)")); + + scoreWinTypePlainTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinTypePlain"), STRING_LITERAL_AS_REFERENCE("Score"), STRING_LITERAL_AS_REFERENCE("High Score")); + baseWinTypePlainTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinTypePlain"), STRING_LITERAL_AS_REFERENCE("Base"), STRING_LITERAL_AS_REFERENCE("Base Destruction")); + beaconWinTypePlainTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinTypePlain"), STRING_LITERAL_AS_REFERENCE("Beacon"), STRING_LITERAL_AS_REFERENCE("Beacon")); + tieWinTypePlainTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinTypePlain"), STRING_LITERAL_AS_REFERENCE("Tie"), STRING_LITERAL_AS_REFERENCE("Tie")); + shutdownWinTypePlainTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinTypePlain"), STRING_LITERAL_AS_REFERENCE("Shutdown"), STRING_LITERAL_AS_REFERENCE("Shutdown")); + unknownWinTypePlainTranslation = translationsFile.get(STRING_LITERAL_AS_REFERENCE("WinTypePlain"), STRING_LITERAL_AS_REFERENCE("Unknown"), STRING_LITERAL_AS_REFERENCE("Unknown")); +} + +Jupiter::String RenX::getFormattedPlayerName(const RenX::PlayerInfo *player) +{ + Jupiter::String r; + if (player->isBot) r += IRCCOLOR "05[B]"; + r += IRCCOLOR; + r += RenX::getTeamColor(player->team); + r += player->name; + return r; +} + +void RenX::sanitizeString(char *str) +{ + while (*str != 0) + { + switch (*str) + { + case '|': + *str = '/'; + break; + case '\\': + if (*(str + 1) == 0) *str = '/'; // So users get something at least. + break; + default: + break; + } + str++; + } +} + +time_t RenX::getGameTime(const RenX::PlayerInfo *player) +{ + time_t currentTime = time(0); + if (player->joinTime == currentTime) currentTime++; + return currentTime - player->joinTime; +} + +double RenX::getKillDeathRatio(const RenX::PlayerInfo *player, bool includeSuicides) +{ + double deaths = player->deaths; + if (includeSuicides == false) deaths -= player->suicides; + if (deaths == 0) deaths = 1; + return ((double)player->kills) / deaths; +} + +double RenX::getHeadshotKillRatio(const RenX::PlayerInfo *player) +{ + if (player->kills == 0) return 0; + return ((double)player->headshots) / ((double)player->kills); +} + +double RenX::getKillsPerSecond(const RenX::PlayerInfo *player) +{ + return ((double)player->kills) / ((double)RenX::getGameTime(player)); +} diff --git a/RenX.Core/RenX_Functions.h b/RenX.Core/RenX_Functions.h new file mode 100644 index 0000000..69b7238 --- /dev/null +++ b/RenX.Core/RenX_Functions.h @@ -0,0 +1,169 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_FUNCTIONS_H_HEADER +#define _RENX_FUNCTIONS_H_HEADER + +/** + * @file RenX_Functions.h + * @brief Provides some functions to be used at your convenience. + */ + +#include "Jupiter/INIFile.h" +#include "Jupiter/String.h" +#include "RenX.h" + +namespace RenX +{ + /** Forward declarations */ + struct PlayerInfo; + class Server; + + /** + * @brief Translates the first character of a team's name into a TeamType. + * + * @param First character of the team name. + * @return A corresponding TeamType. + */ + RENX_API TeamType getTeam(char team); + + /** + * @brief Fetches the corresponding IRC color code for a team. + * + * @param team Team to get IRC color code for + * @return A team's corresponding IRC color-code. + */ + RENX_API const Jupiter::ReadableString &getTeamColor(TeamType team); + + /** + * @brief Fetches a team's name. + * Example: GDI + * + * @param team Team to translate into a name. + * @return The team's corresponding name. + */ + RENX_API const Jupiter::ReadableString &getTeamName(TeamType team); + + /** + * @brief Fetches a team's full name. + * Example: Global Defense Initiative + * + * @param team Team to translate into a name. + * @return The team's corresponding name. + */ + RENX_API const Jupiter::ReadableString &getFullTeamName(TeamType team); + + /** + * @brief Fetches a team's enemy. + * + * @param team TeamType to return enemy for. + * @return Enemy TeamType of the input team. + */ + RENX_API TeamType getEnemy(TeamType team); + + /** + * @brief Translates a preset's name into a real name. + * + * @param object Preset to translate. + * @return Translated name of the preset. + */ + RENX_API const Jupiter::ReadableString &translateName(const Jupiter::ReadableString &object); + + /** + * @brief Translates a WinType into a human-readable string. + * Example: + * + * @param winType WinType to translate. + * @return String containing the human-readable translation of the WinType. + */ + RENX_API const Jupiter::ReadableString &translateWinType(WinType winType); + + /** + * @brief Translates a WinType into a human-readable string. + * Example: Base Destruction + * + * @param winType WinType to translate. + * @return String containing the human-readable translation of the WinType. + */ + RENX_API const Jupiter::ReadableString &translateWinTypePlain(WinType winType); + + /** + * @brief Initializes translation definitions. + * + * @param filename Optional parameter to specify which file to load. + */ + RENX_API void initTranslations(Jupiter::INIFile &settings); + + /** + * @brief Creates a String containing an IRC-ready version of the player's name. + * Note: This includes a bot indicator. + * + * @param player Data of the player + * @return IRC-ready version of the player's name. + */ + RENX_API Jupiter::String getFormattedPlayerName(const RenX::PlayerInfo *player); + + /** + * @brief Sanitizes a string into a RCON-ready state. + * Note: This resolves the pipe character ('|') exploit. + * + * @brief str String to sanitize. + */ + RENX_API void sanitizeString(char *str); + + /** + * @brief Calculates for how many seconds a player has been in-game. + * Note: This will always be at least 1. + * + * @param player A player's data. + * @return Number of seconds a player has been in-game. + */ + RENX_API time_t getGameTime(const RenX::PlayerInfo *player); + + /** + * @brief Calculates a player's Kill-Death ratio, based on their data. + * Note: If the player has not died, this function will use 1 for their death count. + * + * @param player A player's data. + * @param includeSuicides True if suicides should be included in the death count, false otherwise. + * @return Player's Kill-Death ratio. + */ + RENX_API double getKillDeathRatio(const RenX::PlayerInfo *player, bool includeSuicides = true); + + /** + * @brief Calculates a player's Headshot-Kill ratio, based on their data. + * Note: If the player has no kills, this function returns 0. + * + * @param player A player's data. + * @return Player's Headshot-Kill ratio. + */ + RENX_API double getHeadshotKillRatio(const RenX::PlayerInfo *player); + + /** + * @brief Calculates a player's kills-per-second since joining. + * + * @param player A player's data. + * @return Player's Kill-Death ratio. + */ + RENX_API double getKillsPerSecond(const RenX::PlayerInfo *player); + + /** Constant variables */ + RENX_API extern const char *DelimS; /** RCON message deliminator in a C-Style string */ + RENX_API extern const char DelimC; /** RCON message deliminator as a character */ +} + +#endif // _RENX_FUNCTIONS_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_GameCommand.cpp b/RenX.Core/RenX_GameCommand.cpp new file mode 100644 index 0000000..836071d --- /dev/null +++ b/RenX.Core/RenX_GameCommand.cpp @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "RenX_GameCommand.h" +#include "RenX_Server.h" + +Jupiter::ArrayList _GameMasterCommandList; +Jupiter::ArrayList *RenX::GameMasterCommandList = &_GameMasterCommandList; + +RenX::GameCommand::GameCommand(const RenX::GameCommand &command) +{ + RenX::GameMasterCommandList->add(this); +} + +RenX::GameCommand::GameCommand() +{ + RenX::GameMasterCommandList->add(this); +} + +RenX::GameCommand::~GameCommand() +{ + RenX::Core *core = RenX::getCore(); + for (int a = RenX::GameMasterCommandList->size() - 1; a >= 0; a--) + { + if (RenX::GameMasterCommandList->get(a) == this) + { + RenX::Server *server; + for (int b = core->getServerCount() - 1; b >= 0; b--) + { + server = core->getServer(b); + if (server != nullptr) server->removeCommand(this->getTrigger()); + } + RenX::GameMasterCommandList->remove(a); + break; + } + } +} \ No newline at end of file diff --git a/RenX.Core/RenX_GameCommand.h b/RenX.Core/RenX_GameCommand.h new file mode 100644 index 0000000..6c04632 --- /dev/null +++ b/RenX.Core/RenX_GameCommand.h @@ -0,0 +1,110 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_GAMECOMMAND_H_HEADER +#define _RENX_GAMECOMMAND_H_HEADER + +/** + * @file RenX_GameCommand.h + * @brief Provides the basis of the in-game Renegade-X chat command system. + */ + +#include "Jupiter/Command.h" +#include "RenX.h" +#include "RenX_Core.h" // getCore(). + +namespace RenX +{ + /** Forward delcarations */ + class Server; + struct PlayerInfo; + class GameCommand; + + /** Master command list */ + RENX_API extern Jupiter::ArrayList *GameMasterCommandList; + + /** + * @brief Provides an extendable interface from which in-game commands can be created. + * TODO: Add access levels + */ + class RENX_API GameCommand : public Jupiter::Command + { + public: + + /** + * @brief Called when a player with the proper access privledges executes this command. + * + * @param source Renegade-X server where the player is located. + * @param player Player who executed the command. + * @param parameters Parameters following the command. + */ + virtual void trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) = 0; + + /** + * @brief Called when the command is intially created. Define triggers and access levels here. + */ + virtual void create() = 0; + + /** + * @brief Used internally to provide per-server configurable commands. + * Note: This is automatically generated by the GAME_COMMAND_INIT macro. + */ + virtual GameCommand *copy() = 0; + + /** + * @brief Copy constructor for a Game Command. + * Note: This is automatically generated by the GENERIC_GAME_COMMAND macro. + */ + GameCommand(const GameCommand &command); + + /** + * @brief Default constructor for a Game Command. + * Note: This is automatically generated by the BASE_GAME_COMMAND macro. + */ + GameCommand(); + + /** + * @brief Destructor for a Game Command. + * Note: This is not automatically generated by any macro, and is available for use. + */ + virtual ~GameCommand(); + }; +} + +/** Game Command Macros */ + +/** Defines the core of a game command's declaration. This should be included in every game command. */ +#define BASE_GAME_COMMAND(CLASS) \ + public: \ + void trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters); \ + const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters); \ + CLASS *copy(); \ + void create(); \ + CLASS() { this->create(); RenX::getCore()->addCommand(this); } + +/** Expands to become the entire declaration for a game command. In most cases, this will be sufficient. */ +#define GENERIC_GAME_COMMAND(CLASS) \ +class CLASS : public RenX::GameCommand { \ + BASE_GAME_COMMAND(CLASS) \ + CLASS(CLASS &c) : RenX::GameCommand(c) { this->create(); } }; + +/** Instantiates a game command, and also defines neccessary core functions for compatibility. */ +#define GAME_COMMAND_INIT(CLASS) \ + CLASS CLASS ## _instance; \ + CLASS *CLASS::copy() { return new CLASS(*this); } + +#endif // _RENX_GAMECOMMAND_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_PlayerInfo.h b/RenX.Core/RenX_PlayerInfo.h new file mode 100644 index 0000000..4f93974 --- /dev/null +++ b/RenX.Core/RenX_PlayerInfo.h @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_PLAYERINFO_H_HEADER +#define _RENX_PLAYERINFO_H_HEADER + +/** + * @file RenX_PlayerInfo.h + * @brief Defines the PlayerInfo structure. + */ + +#include "Jupiter/String.h" +#include "Jupiter/INIFile.h" +#include "RenX.h" + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace RenX +{ + + /** + * @brief Includes all of the tracked information about a player. + */ + struct RENX_API PlayerInfo + { + Jupiter::StringS name; + Jupiter::StringS ip; + Jupiter::StringS adminType; + Jupiter::StringS steamid; + TeamType team = Other; + int id = 0; + bool isBot = false; + time_t joinTime = 0; + unsigned int kills = 0; + unsigned int deaths = 0; + unsigned int suicides = 0; + unsigned int headshots = 0; + unsigned int vehicleKills = 0; + unsigned int buildingKills = 0; + unsigned int defenceKills = 0; + unsigned int wins = 0; + unsigned int loses = 0; + unsigned int beaconPlacements = 0; + + Jupiter::INIFile varData; // This will be replaced later with a more dedicated type. + }; + +} + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _RENX_PLAYERINFO_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_Plugin.cpp b/RenX.Core/RenX_Plugin.cpp new file mode 100644 index 0000000..e6f2274 --- /dev/null +++ b/RenX.Core/RenX_Plugin.cpp @@ -0,0 +1,161 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "RenX_Plugin.h" +#include "RenX_Core.h" + +RenX::Plugin::Plugin() +{ + RenX::getCore()->getPlugins()->add(this); +} + +RenX::Plugin::~Plugin() +{ + for (size_t i = 0; i != RenX::getCore()->getPlugins()->size(); i++) + { + if (RenX::getCore()->getPlugins()->get(i) == this) + { + RenX::getCore()->getPlugins()->remove(i); + break; + } + } +} + +void RenX::Plugin::RenX_OnJoin(Server *, const RenX::PlayerInfo *) +{ + return; +} + +void RenX::Plugin::RenX_OnPart(Server *, const RenX::PlayerInfo *) +{ + return; +} + +void RenX::Plugin::RenX_OnNameChange(Server *, const PlayerInfo *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnChat(Server *, const RenX::PlayerInfo *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnTeamChat(Server *, const RenX::PlayerInfo *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnDeploy(Server *, const RenX::PlayerInfo *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnSuicide(Server *, const RenX::PlayerInfo *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnKill(Server *, const RenX::PlayerInfo *, const RenX::PlayerInfo *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnDie(Server *, const RenX::PlayerInfo *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnDestroy(Server *, const RenX::PlayerInfo *, const Jupiter::ReadableString &, const Jupiter::ReadableString &, ObjectType) +{ + return; +} + +void RenX::Plugin::RenX_OnGameOver(Server *, RenX::WinType, TeamType, int, int) +{ + return; +} + +void RenX::Plugin::RenX_OnGame(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnExecute(Server *, const Jupiter::ReadableString &, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnSubscribe(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnRCON(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnAdminLogin(Server *, const RenX::PlayerInfo *) +{ + return; +} + +void RenX::Plugin::RenX_OnAdminLogout(Server *, const RenX::PlayerInfo *) +{ + return; +} + +void RenX::Plugin::RenX_OnAdmin(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnLog(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnCommand(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnError(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnVersion(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnAuthorized(Server *, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnOther(Server *, char, const Jupiter::ReadableString &) +{ + return; +} + +void RenX::Plugin::RenX_OnRaw(Server *, const Jupiter::ReadableString &) +{ + return; +} \ No newline at end of file diff --git a/RenX.Core/RenX_Plugin.h b/RenX.Core/RenX_Plugin.h new file mode 100644 index 0000000..de1e174 --- /dev/null +++ b/RenX.Core/RenX_Plugin.h @@ -0,0 +1,102 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_PLUGIN_H_HEADER +#define _RENX_PLUGIN_H_HEADER + +/** + * @file RenX_Plugin.h + * @brief Provides an plugin interface that interacts with the Renegade-X Core. + */ + +#include "Jupiter/Plugin.h" +#include "RenX.h" + +namespace RenX +{ + + /** Forward declarations */ + struct PlayerInfo; + class Plugin; + class Server; + + class RENX_API Plugin : public Jupiter::Plugin + { + public: + /** Player type logs */ + virtual void RenX_OnJoin(Server *server, const PlayerInfo *player); + virtual void RenX_OnPart(Server *server, const PlayerInfo *player); + virtual void RenX_OnNameChange(Server *server, const PlayerInfo *player, const Jupiter::ReadableString &newPlayerName); + + /** Chat type logs */ + virtual void RenX_OnChat(Server *server, const PlayerInfo *player, const Jupiter::ReadableString &message); + virtual void RenX_OnTeamChat(Server *server, const PlayerInfo *player, const Jupiter::ReadableString &message); + + /** Game type logs */ + virtual void RenX_OnDeploy(Server *server, const PlayerInfo *player, const Jupiter::ReadableString &object); + virtual void RenX_OnSuicide(Server *server, const PlayerInfo *player, const Jupiter::ReadableString &damageType); + virtual void RenX_OnKill(Server *server, const PlayerInfo *player, const PlayerInfo *victim, const Jupiter::ReadableString &damageType); + virtual void RenX_OnDie(Server *server, const PlayerInfo *player, const Jupiter::ReadableString &damageType); + virtual void RenX_OnDestroy(Server *server, const PlayerInfo *player, const Jupiter::ReadableString &objectName, const Jupiter::ReadableString &damageType, ObjectType type); + virtual void RenX_OnGameOver(Server *server, WinType winType, TeamType team, int gScore, int nScore); + virtual void RenX_OnGame(Server *server, const Jupiter::ReadableString &raw); + + /** RCON type logs */ + virtual void RenX_OnExecute(Server *server, const Jupiter::ReadableString &user, const Jupiter::ReadableString &command); + virtual void RenX_OnSubscribe(Server *server, const Jupiter::ReadableString &user); + virtual void RenX_OnRCON(Server *server, const Jupiter::ReadableString &raw); + + /** Admin Type Logs */ + virtual void RenX_OnAdminLogin(Server *server, const PlayerInfo *player); + virtual void RenX_OnAdminLogout(Server *server, const PlayerInfo *player); + virtual void RenX_OnAdmin(Server *server, const Jupiter::ReadableString &raw); + + /** Other Logs */ + virtual void RenX_OnLog(Server *server, const Jupiter::ReadableString &raw); + + /** Command type */ + virtual void RenX_OnCommand(Server *server, const Jupiter::ReadableString &raw); + + /** Error type */ + virtual void RenX_OnError(Server *server, const Jupiter::ReadableString &raw); + + /** Version type */ + virtual void RenX_OnVersion(Server *server, const Jupiter::ReadableString &raw); + + /** Authorized type */ + virtual void RenX_OnAuthorized(Server *server, const Jupiter::ReadableString &raw); + + /** Other type - executed if none of the above matched */ + virtual void RenX_OnOther(Server *server, const char token, const Jupiter::ReadableString &raw); + + /** Catch-all - always executes for every line from RCON */ + virtual void RenX_OnRaw(Server *server, const Jupiter::ReadableString &raw); + + /** + * @brief Default constructor for the Plugin class. + */ + Plugin(); + + /** + * @brief Destructor for the Plugin class. + */ + virtual ~Plugin(); + }; + +} + +#endif // _RENX_PLUGIN_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp new file mode 100644 index 0000000..4ed362f --- /dev/null +++ b/RenX.Core/RenX_Server.cpp @@ -0,0 +1,443 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/INIFile.h" +#include "Jupiter/String.h" +#include "ServerManager.h" +#include "IRC_Bot.h" +#include "RenX_Server.h" +#include "RenX_PlayerInfo.h" +#include "RenX_GameCommand.h" +#include "RenX_Functions.h" + +bool RenX::Server::isConnected() const +{ + return RenX::Server::connected; +} + +bool RenX::Server::isPublicLogChanType(int type) const +{ + return RenX::Server::logChanType == type; +} + +bool RenX::Server::isAdminLogChanType(int type) const +{ + return RenX::Server::adminLogChanType == type; +} + +bool RenX::Server::isLogChanType(int type) const +{ + return RenX::Server::isPublicLogChanType(type) || RenX::Server::isAdminLogChanType(type); +} + +int RenX::Server::send(const Jupiter::ReadableString &command) +{ + char *t = new char[command.size() + 2]; + *t = 'c'; + for (size_t i = 0; i != command.size(); i++) t[i + 1] = command.get(i); + t[command.size() + 1] = '\n'; + int r; + RenX::sanitizeString(t); + r = RenX::Server::sock.send(t, command.size() + 2); + delete[] t; + return r; +} + +int RenX::Server::sendMessage(const Jupiter::ReadableString &message) +{ + char *t = new char[message.size() + 6]; + strcpy(t, "csay "); + for (size_t i = 0; i != message.size(); i++) t[i + 5] = message.get(i); + t[message.size() + 5] = '\n'; + RenX::sanitizeString(t); + int r = RenX::Server::sock.send(t, message.size() + 6); + delete[] t; + return r; +} + +int RenX::Server::sendMessage(RenX::PlayerInfo *player, const Jupiter::ReadableString &message) +{ + // We'll have a real implementation when Kil adds one to RCON! :D + return RenX::Server::sendMessage(message); +} + +int RenX::Server::sendData(const Jupiter::ReadableString &data) +{ + return RenX::Server::sock.send(data); +} + +RenX::PlayerInfo *RenX::Server::getPlayer(int id) const +{ + if (RenX::Server::players.size() == 0) return nullptr; + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) if (node->data->id == id) return node->data; + return nullptr; +} + +RenX::PlayerInfo *RenX::Server::getPlayerByName(const Jupiter::ReadableString &name) const +{ + if (RenX::Server::players.size() == 0) return nullptr; + + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) + if (node->data->name == name) + return node->data; + + Jupiter::ReferenceString idToken = name; + if (name.matchi("Player?*")) + idToken.shiftRight(6); + else if (name.matchi("pid?*")) + idToken.shiftRight(3); + else return nullptr; + int id = name.asInt(10); + + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) + if (node->data->id == id) + return node->data; + + return nullptr; +} + +RenX::PlayerInfo *RenX::Server::getPlayerByPartName(const Jupiter::ReadableString &partName) const +{ + if (RenX::Server::players.size() == 0) return nullptr; + RenX::PlayerInfo *r = RenX::Server::getPlayerByName(partName); + if (r != nullptr) return r; + return RenX::Server::getPlayerByPartNameFast(partName); +} + +RenX::PlayerInfo *RenX::Server::getPlayerByPartNameFast(const Jupiter::ReadableString &partName) const +{ + if (RenX::Server::players.size() == 0) return nullptr; + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) + if (node->data->name.find(partName) != Jupiter::INVALID_INDEX) + return node->data; + return nullptr; +} + +void RenX::Server::kickPlayer(int id) +{ + RenX::Server::sock.send(Jupiter::StringS::Format("cadminkick pid%d\n", id)); +} + +void RenX::Server::kickPlayer(const RenX::PlayerInfo *player) +{ + if (player->isBot) + RenX::Server::sock.send(Jupiter::StringS::Format("cadminkick %.*s", player->name.size(), player->name.ptr())); + else if (player->id < 1000 || this->rconVersion > 2) + RenX::Server::kickPlayer(player->id); + else if (player->name.contains('|') == false) + RenX::Server::sock.send(Jupiter::StringS::Format("cadminkick %.*s", player->name.size(), player->name.ptr())); + else + RenX::Server::kickPlayer(player->id); +} + +void RenX::Server::banPlayer(int id) +{ + Jupiter::StringS msg; + msg.format("cadminkickban pid%d\n", id); + RenX::Server::sock.send(msg); +} + +void RenX::Server::banPlayer(const RenX::PlayerInfo *player) +{ + if (player->isBot) + RenX::Server::sock.send(Jupiter::StringS::Format("cadminkickban %.*s\n", player->name.size(), player->name.ptr())); + else if (player->id < 1000 || this->rconVersion > 2) + RenX::Server::sock.send(Jupiter::StringS::Format("cadminkickban pid%d\n", player->id)); + else if (player->name.contains('|') == false) + RenX::Server::sock.send(Jupiter::StringS::Format("cadminkickban %.*s\n", player->name.size(), player->name.ptr())); + else + RenX::Server::sock.send(Jupiter::StringS::Format("cadminkickban pid%d\n", player->id)); +} + +bool RenX::Server::removePlayer(int id) +{ + if (RenX::Server::players.size() == 0) return false; + for (Jupiter::DLList::Node *node = RenX::Server::players.getNode(0); node != nullptr; node = node->next) + { + if (node->data->id == id) + { + RenX::PlayerInfo *p = RenX::Server::players.remove(node); + delete p; + return true; + } + } + return false; +} + +bool RenX::Server::removePlayer(RenX::PlayerInfo *player) +{ + return RenX::Server::removePlayer(player->id); +} + +const Jupiter::ReadableString &RenX::Server::getPrefix() const +{ + return RenX::Server::IRCPrefix; +} + +void RenX::Server::setPrefix(const Jupiter::ReadableString &prefix) +{ + RenX::Server::IRCPrefix = prefix; +} + +const Jupiter::ReadableString &RenX::Server::getCommandPrefix() const +{ + return RenX::Server::CommandPrefix; +} + +void RenX::Server::setCommandPrefix(const Jupiter::ReadableString &prefix) +{ + RenX::Server::CommandPrefix = prefix; +} + +const Jupiter::ReadableString &RenX::Server::getRules() const +{ + return RenX::Server::rules; +} + +void RenX::Server::setRules(const Jupiter::ReadableString &rules) +{ + RenX::Server::rules = rules; + Jupiter::IRC::Client::Config->set(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("Rules"), rules); + RenX::Server::sendMessage(Jupiter::StringS::Format("NOTICE: The rules have been modified! Rules: %.*s", rules.size(), rules.ptr())); +} + +const Jupiter::ReadableString &RenX::Server::getHostname() const +{ + return RenX::Server::hostname; +} + +unsigned short RenX::Server::getPort() const +{ + return RenX::Server::port; +} + +time_t RenX::Server::getLastAttempt() const +{ + return RenX::Server::lastAttempt; +} + +time_t RenX::Server::getDelay() const +{ + return RenX::Server::delay; +} + +const Jupiter::ReadableString &RenX::Server::getPassword() const +{ + return RenX::Server::pass; +} + +RenX::GameCommand *RenX::Server::getCommand(unsigned int index) const +{ + return RenX::Server::commands.get(index); +} + +RenX::GameCommand *RenX::Server::getCommand(const Jupiter::ReadableString &trigger) const +{ + for (size_t i = 0; i != RenX::Server::commands.size(); i++) + { + RenX::GameCommand *cmd = RenX::Server::commands.get(i); + if (cmd->matches(trigger)) + return cmd; + } + return nullptr; +} + +unsigned int RenX::Server::getCommandCount() const +{ + return RenX::Server::commands.size(); +} + +unsigned int RenX::Server::triggerCommand(const Jupiter::ReadableString &trigger, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + unsigned int r = 0; + RenX::GameCommand *cmd; + for (size_t i = 0; i < RenX::Server::commands.size(); i++) + { + cmd = RenX::Server::commands.get(i); + if (cmd->matches(trigger)) + { + cmd->trigger(this, player, parameters); + r++; + } + } + return r; +} + +void RenX::Server::addCommand(RenX::GameCommand *command) +{ + RenX::Server::commands.add(command); +} + +bool RenX::Server::removeCommand(RenX::GameCommand *command) +{ + for (size_t i = 0; i != RenX::Server::commands.size(); i++) + { + if (RenX::Server::commands.get(i) == command) + { + delete RenX::Server::commands.remove(i); + return true; + } + } + return false; +} + +bool RenX::Server::removeCommand(const Jupiter::ReadableString &trigger) +{ + for (size_t i = 0; i != RenX::Server::commands.size(); i++) + { + if (RenX::Server::commands.get(i)->matches(trigger)) + { + delete RenX::Server::commands.remove(i); + return true; + } + } + return false; +} + +void RenX::Server::sendPubChan(const char *fmt, ...) const +{ + va_list args; + va_start(args, fmt); + Jupiter::StringL msg; + const Jupiter::ReadableString &serverPrefix = RenX::Server::IRCPrefix; + if (serverPrefix.isEmpty() == false) + { + msg += serverPrefix; + msg += ' '; + msg.avformat(fmt, args); + } + else msg.vformat(fmt, args); + va_end(args); + for (size_t i = 0; i != serverManager->size(); i++) + serverManager->getServer(i)->messageChannels(RenX::Server::logChanType, msg); +} + +void RenX::Server::sendAdmChan(const char *fmt, ...) const +{ + va_list args; + va_start(args, fmt); + Jupiter::StringL msg; + const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); + if (serverPrefix.isEmpty() == false) + { + msg += serverPrefix; + msg += ' '; + msg.avformat(fmt, args); + } + else msg.vformat(fmt, args); + va_end(args); + for (size_t i = 0; i != serverManager->size(); i++) + serverManager->getServer(i)->messageChannels(RenX::Server::adminLogChanType, msg); +} + +void RenX::Server::sendLogChan(const char *fmt, ...) const +{ + va_list args; + va_start(args, fmt); + Jupiter::StringL msg; + const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); + if (serverPrefix.isEmpty() == false) + { + msg += serverPrefix; + msg += ' '; + msg.avformat(fmt, args); + } + else msg.vformat(fmt, args); + va_end(args); + for (size_t i = 0; i != serverManager->size(); i++) + { + IRC_Bot *ircServer = serverManager->getServer(i); + ircServer->messageChannels(RenX::Server::logChanType, msg); + ircServer->messageChannels(RenX::Server::adminLogChanType, msg); + } +} + +void RenX::Server::disconnect() +{ + RenX::Server::sock.closeSocket(); + RenX::Server::wipeData(); + RenX::Server::connected = false; +} + +bool RenX::Server::connect() +{ + RenX::Server::lastAttempt = time(0); + if (RenX::Server::sock.connectToHost(RenX::Server::hostname.c_str(), RenX::Server::port, RenX::Server::clientHostname.isEmpty() ? nullptr : RenX::Server::clientHostname.c_str())) + { + RenX::Server::sock.setBlocking(false); + RenX::Server::sock.send(Jupiter::StringS::Format("a%.*s\n", RenX::Server::pass.size(), RenX::Server::pass.ptr())); + RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("s\n")); + RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("clogclientlist\n")); + RenX::Server::connected = true; + return true; + } + RenX::Server::connected = false; + return false; +} + +bool RenX::Server::reconnect() +{ + RenX::Server::sock.closeSocket(); + return RenX::Server::connect(); +} + +void RenX::Server::wipeData() +{ + while (RenX::Server::players.size() != 0) delete RenX::Server::players.remove(0U); + RenX::Server::commands.emptyAndDelete(); +} + +unsigned int RenX::Server::getVersion() const +{ + return RenX::Server::rconVersion; +} + +const Jupiter::ReadableString &RenX::Server::getGameVersion() const +{ + return RenX::Server::gameVersion; +} + +RenX::Server::Server(const Jupiter::ReadableString &configurationSection) +{ + RenX::Server::configSection = configurationSection; + + RenX::Server::hostname = Jupiter::IRC::Client::Config->get(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("Hostname"), STRING_LITERAL_AS_REFERENCE("localhost")); + RenX::Server::port = (unsigned short)Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("Port"), 7777); + RenX::Server::clientHostname = Jupiter::IRC::Client::Config->get(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("ClientAddress")); + + RenX::Server::pass = Jupiter::IRC::Client::Config->get(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("Password"), STRING_LITERAL_AS_REFERENCE("renx")); + + RenX::Server::logChanType = Jupiter::IRC::Client::Config->getShort(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("ChanType")); + RenX::Server::adminLogChanType = Jupiter::IRC::Client::Config->getShort(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("AdminChanType")); + + RenX::Server::setCommandPrefix(Jupiter::IRC::Client::Config->get(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("CommandPrefix"))); + RenX::Server::setPrefix(Jupiter::IRC::Client::Config->get(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("IRCPrefix"))); + + RenX::Server::rules = Jupiter::IRC::Client::Config->get(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("Rules"), STRING_LITERAL_AS_REFERENCE("Anarchy!")); + + RenX::Server::delay = Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("ReconnectDelay"), 60); + + for (size_t i = 0; i < RenX::GameMasterCommandList->size(); i++) + RenX::Server::addCommand(RenX::GameMasterCommandList->get(i)->copy()); +} + +RenX::Server::~Server() +{ + sock.closeSocket(); + RenX::Server::wipeData(); +} diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h new file mode 100644 index 0000000..b8bda77 --- /dev/null +++ b/RenX.Core/RenX_Server.h @@ -0,0 +1,431 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_SERVER_H_HEADER +#define _RENX_SERVER_H_HEADER + +/** + * @file RenX_Server.h + * @brief Defines the Server class. + */ + +#include "Jupiter/TCPSocket.h" +#include "Jupiter/DLList.h" +#include "Jupiter/ArrayList.h" +#include "Jupiter/String.h" +#include "Jupiter/CString.h" +#include "Jupiter/INIFile.h" +#include "RenX.h" + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace RenX +{ + /** Forward declarations */ + struct PlayerInfo; + class GameCommand; + class Core; + + /** + * @brief Represents a connection to an individiaul Renegade-X server. + * There are often more than one of these, such as when communities run multiple servers. + */ + class RENX_API Server + { + friend class RenX::Core; + public: + Jupiter::DLList players; /** A list of players in the server */ + Jupiter::INIFile varData; /** This may be replaced later with a more dedicated type. */ + + /** + * @brief Checks if the server is connected to RCON. + * + * @return True if the server is connected, false otherwise. + */ + bool isConnected() const; + + /** + * @brief Checks if a channel type is a public channel type. + * + * @param type Type to check against. + * @return True if this is a public channel type, false otherwise. + */ + bool isPublicLogChanType(int type) const; + + /** + * @brief Checks if a channel type is an administrative channel type. + * + * @param type Type to check against. + * @return True if this is an administrative channel type, false otherwise. + */ + bool isAdminLogChanType(int type) const; + + /** + * @brief Checks if a channel type is either a public or administrative channel type. + * + * @param type Type to check against. + * @return True if this is either a public or administrative channel type, false otherwise. + */ + bool isLogChanType(int type) const; + + /** + * @brief Sends a command to the server. + * + * @param commmand Command to send. + * @return The number of bytes sent on success, less than or equal to zero otherwise. + */ + int send(const Jupiter::ReadableString &command); + + /** + * @brief Sends an in-game message to the server. + * + * @param message Message to send in-game. + * @return The number of bytes sent on success, less than or equal to zero otherwise. + */ + int sendMessage(const Jupiter::ReadableString &message); + + /** + * @brief Sends an in-game message to a player in the server. + * + * @param player Data of the player to send a message to. + * @param message Message to send in-game. + * @return The number of bytes sent on success, less than or equal to zero otherwise. + */ + int sendMessage(RenX::PlayerInfo *player, const Jupiter::ReadableString &message); + + /** + * @brief Sends data to the server. + * + * @param data String of data to send. + * @return The number of bytes sent on success, less than or equal to zero otherwise. + */ + int sendData(const Jupiter::ReadableString &data); + + /** + * @brief Fetches a player's data based on their ID number. + * + * @param id ID of the player + * @return A pointer to a player's corresponding PlayerInfo on success, nullptr otherwise. + */ + RenX::PlayerInfo *getPlayer(int id) const; + + /** + * @brief Fetches a player's data, based on their name. + * + * @param name Name of the player. + * @return A player's data on success, nullptr otherwise. + */ + RenX::PlayerInfo *getPlayerByName(const Jupiter::ReadableString &name) const; + + /** + * @brief Fetches a player's data, based on part of their name. + * + * @param name Name of the player. + * @return A player's data on success, nullptr otherwise. + */ + RenX::PlayerInfo *getPlayerByPartName(const Jupiter::ReadableString &partName) const; + + /** + * @brief Fetches a player's data, based on part of their name. + * Note: This does not check that the exact name exists first. + * + * @param name Name of the player. + * @return A player's data on success, nullptr otherwise. + */ + RenX::PlayerInfo *getPlayerByPartNameFast(const Jupiter::ReadableString &partName) const; + + /** + * @brief Kicks a player from the server. + * + * @param id Player ID of the player to kick. + */ + void kickPlayer(int id); + + /** + * @brief Kicks a player from the server. + * + * @param player Data of the player to kick. + */ + void kickPlayer(const RenX::PlayerInfo *player); + + /** + * @brief Bans a player from the server. + * + * @param id Player ID of the player to ban. + */ + void banPlayer(int id); + + /** + * @brief Bans a player from the server. + * + * @param player Data of the player to ban. + */ + void banPlayer(const RenX::PlayerInfo *player); + + /** + * @brief Removes a player's data based on their ID number. + * + * @param id ID of the player + * @return True if a player was removed, false otherwise. + */ + bool removePlayer(int id); + + /** + * @brief Removes a player's data based on a player's data. + * + * @param player Pointer to a player's data + * @return True if a player was removed, false otherwise. + */ + bool removePlayer(RenX::PlayerInfo *player); + + /** + * @brief Fetches a server's IRC logging prefix. + * + * @return The server's logging prefix. + */ + const Jupiter::ReadableString &getPrefix() const; + + /** + * @brief Sets a server's IRC logging prefix. + * + * @param prefix Prefix to use. + */ + void setPrefix(const Jupiter::ReadableString &prefix); + + /** + * @brief Fetches a server's game command prefix. + * + * @return The server's game command prefix. + */ + const Jupiter::ReadableString &getCommandPrefix() const; + + /** + * @brief Sets a server's game command prefix. + * + * @param prefix Prefix to use. + */ + void setCommandPrefix(const Jupiter::ReadableString &prefix); + + /** + * @brief Fetches the rules of a server. + * + * @return String containing the rules of the server. + */ + const Jupiter::ReadableString &getRules() const; + + /** + * @brief Sets the rules of a server. + * + * @param rules Rules for the server to be used. + */ + void setRules(const Jupiter::ReadableString &rules); + + /** + * @brief Fetches the hostname of a server. + * + * @return String containing the hostname of the server. + */ + const Jupiter::ReadableString &getHostname() const; + + /** + * @brief Fetches the port of a server. + * + * @return Port of the server. + */ + unsigned short getPort() const; + + /** + * @brief Fetches the time of the last connection attempt. + * Note: This includes both successful and failed connection attempts. + * + * @return Time of the last connection attempt. + */ + time_t getLastAttempt() const; + + /** + * @brief Fetches the time delay between connection attempts. + * + * @return Time delay between connection attempts. + */ + time_t getDelay() const; + + /** + * @brief Fetches the password of a server. + * + * @return String containing the password of the server. + */ + const Jupiter::ReadableString &getPassword() const; + + /** + * @brief Fetches a command from the list. + * + * @param index Index of the command to return. + * @return Command located at the specified index. + */ + GameCommand *getCommand(unsigned int index) const; + + /** + * @brief Fetches a command from the list. + * + * @param trigger Trigger of the command to get + * @return Command with the specified trigger. + */ + GameCommand *getCommand(const Jupiter::ReadableString &trigger) const; + + /** + * @brief Returns the number of commands in the command list. + * + * @return Number of commands in the command list. + */ + unsigned int getCommandCount() const; + + /** + * @brief Triggers commands matching a specified trigger. + * + * @param trigger Trigger of the command to fire. + * @return Number of commands triggered. + */ + unsigned int triggerCommand(const Jupiter::ReadableString &trigger, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters); + + /** + * @brief Adds a command to the server's game command list. + * + * @param command Command to add. + */ + void addCommand(RenX::GameCommand *command); + + /** + * @brief Adds a command to the server's game command list. + * + * @param command Command to remove. + * @return True if a command was removed, false otherwise. + */ + bool removeCommand(RenX::GameCommand *command); + + /** + * @brief Adds a command to the server's game command list. + * + * @param trigger Trigger of the command to remove. + * @return True if a command was removed, false otherwise. + */ + bool removeCommand(const Jupiter::ReadableString &trigger); + + /** + * @brief Formats and sends a message to a server's corresponding public channels. + * + * @param server Server corresponding to channel types. + * @param fmt String containing the format specifiers indicating what message to send. + */ + void sendPubChan(const char *fmt, ...) const; + + /** + * @brief Formats and sends a message to a server's corresponding adminstrative channels. + * + * @param server Server corresponding to channel types. + * @param fmt String containing the format specifiers indicating what message to send. + */ + void sendAdmChan(const char *fmt, ...) const; + + /** + * @brief Formats and sends a message to a server's corresponding channels. + * + * @param server Server corresponding to channel types. + * @param fmt String containing the format specifiers indicating what message to send. + */ + void sendLogChan(const char *fmt, ...) const; + + /** + * @brief Disconnects from a server's RCON interface. + */ + void disconnect(); + + /** + * @brief Connects to the server's RCON interface. + * + * @return True if the socket successfully connected, false otherwise. + */ + bool connect(); + + /** + * @brief Reconnects to the server's RCON interface. + * + * @return True if the socket successfully connected, false otherwise. + */ + bool reconnect(); + + /** + * @brief Deletes all of the data about a server (such as players). + * This is mostly for use with the reconnect mechanism. + */ + void wipeData(); + + /** + * @brief Fetches the RCON version number, or 0 or none has been set. + */ + unsigned int getVersion() const; + + /** + * @brief Fetches the game version string, or an empty string if none has been set. + */ + const Jupiter::ReadableString &getGameVersion() const; + + /** + * @brief Creates the Server object, and loads settings from the specified configuration section. + * + * @param configurationSection Configuration section to load from. + */ + Server(const Jupiter::ReadableString &configurationSection); + + /** + * @brief Destructor for Server class. + */ + ~Server(); + + /** Private members */ + private: + bool connected = false; + bool needsCList = false; + unsigned int rconVersion = 0; + unsigned short port; + int logChanType; + int adminLogChanType; + time_t lastAttempt = 0; + time_t delay; + Jupiter::TCPSocket sock; + Jupiter::CStringS clientHostname; + Jupiter::CStringS hostname; + Jupiter::StringS pass; + Jupiter::StringS configSection; + Jupiter::StringS rules; + Jupiter::StringS IRCPrefix; + Jupiter::StringS CommandPrefix; + Jupiter::StringS gameVersion; + Jupiter::ArrayList commands; + }; + +} + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _RENX_SERVER_H_HEADER \ No newline at end of file diff --git a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp new file mode 100644 index 0000000..7149bbe --- /dev/null +++ b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.cpp @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/IRC_Client.h" +#include "Jupiter/INIFile.h" +#include "ExcessiveHeadshots.h" +#include "RenX_Server.h" +#include "RenX_PlayerInfo.h" +#include "RenX_Functions.h" + +RenX_ExcessiveHeadshotsPlugin::RenX_ExcessiveHeadshotsPlugin() +{ + RenX_ExcessiveHeadshotsPlugin::OnRehash(); +} + +int RenX_ExcessiveHeadshotsPlugin::OnRehash() +{ + RenX_ExcessiveHeadshotsPlugin::ratio = Jupiter::IRC::Client::Config->getDouble(RenX_ExcessiveHeadshotsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("HeadshotKillRatio"), 0.5); + RenX_ExcessiveHeadshotsPlugin::minKills = Jupiter::IRC::Client::Config->getInt(RenX_ExcessiveHeadshotsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("Kills"), 10); + RenX_ExcessiveHeadshotsPlugin::minKD = Jupiter::IRC::Client::Config->getDouble(RenX_ExcessiveHeadshotsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("KillDeathRatio"), 5.0); + RenX_ExcessiveHeadshotsPlugin::minKPS = Jupiter::IRC::Client::Config->getDouble(RenX_ExcessiveHeadshotsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("KillsPerSecond"), 0.5); + RenX_ExcessiveHeadshotsPlugin::minFlags = Jupiter::IRC::Client::Config->getInt(RenX_ExcessiveHeadshotsPlugin::getName(), STRING_LITERAL_AS_REFERENCE("Flags"), 4); + return 0; +} + +void RenX_ExcessiveHeadshotsPlugin::RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType) +{ + if (player->kills < 3) return; + if (damageType.equals("Rx_DmgType_Headshot")) + { + unsigned int flags = 0; + if (player->kills >= RenX_ExcessiveHeadshotsPlugin::minKills) flags++; + if (RenX::getHeadshotKillRatio(player) >= RenX_ExcessiveHeadshotsPlugin::ratio) flags++; + if (RenX::getKillDeathRatio(player) >= RenX_ExcessiveHeadshotsPlugin::minKD) flags++; + if (RenX::getKillsPerSecond(player) >= RenX_ExcessiveHeadshotsPlugin::minKPS) flags++; + if (RenX::getKillsPerSecond(player) >= RenX_ExcessiveHeadshotsPlugin::minKPS * 2) flags++; + if (RenX::getGameTime(player) <= RenX_ExcessiveHeadshotsPlugin::maxGameTime) flags++; + + if (flags >= RenX_ExcessiveHeadshotsPlugin::minFlags) + { + server->kickPlayer(player); + server->sendPubChan(IRCCOLOR "13[Aimbot]" IRCCOLOR " %.*s was banned from the server! Kills: %u - Deaths: %u - Headshots: %u", player->name.size(), player->name.ptr(), player->kills, player->deaths, player->headshots); + server->sendAdmChan(IRCCOLOR "13[Aimbot]" IRCCOLOR " %.*s was banned from the server! Kills: %u - Deaths: %u - Headshots: %u - IP: " IRCBOLD "%.*s" IRCBOLD " - Steam ID: " IRCBOLD "%.*s" IRCBOLD, player->name.size(), player->name.ptr(), player->kills, player->deaths, player->headshots, player->ip.size(), player->ip.ptr(), player->steamid.size(), player->steamid.ptr()); + } + } +} + + +// Plugin instantiation and entry point. +RenX_ExcessiveHeadshotsPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.ExcessiveHeadshots/ExcessiveHeadshots.h b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.h new file mode 100644 index 0000000..d0a2610 --- /dev/null +++ b/RenX.ExcessiveHeadshots/ExcessiveHeadshots.h @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _EXCESSIVEHEADSHOTS_H_HEADER +#define _EXCESSIVEHEADSHOTS_H_HEADER + +#include "Jupiter/Plugin.h" +#include "RenX_Plugin.h" + +class RenX_ExcessiveHeadshotsPlugin : public RenX::Plugin +{ +public: // RenX::Plugin + void RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType) override; + +public: // Jupiter::Plugin + int OnRehash() override; + const Jupiter::ReadableString &getName() override { return name; } + + RenX_ExcessiveHeadshotsPlugin(); +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.ExcessiveHeadshots"); + unsigned int minFlags = 4; + double ratio = 0.5; + double minKD = 5.0; + double minKPS = 0.1; + unsigned int minKills = 10; + time_t maxGameTime = 180; +}; + +#endif // _EXCESSIVEHEADSHOTS_H_HEADER \ No newline at end of file diff --git a/RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj b/RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj new file mode 100644 index 0000000..c49fcdd --- /dev/null +++ b/RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj @@ -0,0 +1,85 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0F71052A-A773-4AB5-AE2A-50DBDFB9CF9E} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj.filters b/RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj.filters new file mode 100644 index 0000000..9a7242e --- /dev/null +++ b/RenX.ExcessiveHeadshots/RenX.ExcessiveHeadshots.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/RenX.ExtraLogging/RenX.ExtraLogging.vcxproj b/RenX.ExtraLogging/RenX.ExtraLogging.vcxproj new file mode 100644 index 0000000..6443d43 --- /dev/null +++ b/RenX.ExtraLogging/RenX.ExtraLogging.vcxproj @@ -0,0 +1,85 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {CEFD949E-BCF2-4EDB-8168-0920924FE2D8} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.ExtraLogging/RenX.ExtraLogging.vcxproj.filters b/RenX.ExtraLogging/RenX.ExtraLogging.vcxproj.filters new file mode 100644 index 0000000..a3cfa6f --- /dev/null +++ b/RenX.ExtraLogging/RenX.ExtraLogging.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/RenX.ExtraLogging/RenX_ExtraLogging.cpp b/RenX.ExtraLogging/RenX_ExtraLogging.cpp new file mode 100644 index 0000000..db41983 --- /dev/null +++ b/RenX.ExtraLogging/RenX_ExtraLogging.cpp @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Jupiter/IRC_Client.h" +#include "Jupiter/INIFile.h" +#include "RenX_ExtraLogging.h" +#include "RenX_Server.h" + +RenX_ExtraLoggingPlugin::RenX_ExtraLoggingPlugin() +{ + const Jupiter::CStringS logFile = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX.ExtraLogging"), STRING_LITERAL_AS_REFERENCE("LogFile")); + if (logFile.isEmpty() == false) + RenX_ExtraLoggingPlugin::file = fopen(logFile.c_str(), "a+b"); + else RenX_ExtraLoggingPlugin::file = nullptr; +} + +RenX_ExtraLoggingPlugin::~RenX_ExtraLoggingPlugin() +{ + if (RenX_ExtraLoggingPlugin::file != nullptr) + fclose(RenX_ExtraLoggingPlugin::file); +} + +void RenX_ExtraLoggingPlugin::RenX_OnRaw(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + raw.println(stdout); + if (RenX_ExtraLoggingPlugin::file != nullptr) + { + const Jupiter::ReadableString &prefix = server->getPrefix(); + if (prefix.size() != 0) + { + prefix.print(RenX_ExtraLoggingPlugin::file); + fputc(' ', RenX_ExtraLoggingPlugin::file); + } + raw.println(RenX_ExtraLoggingPlugin::file); + fflush(RenX_ExtraLoggingPlugin::file); + } +} + + + +// Plugin instantiation and entry point. +RenX_ExtraLoggingPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.ExtraLogging/RenX_ExtraLogging.h b/RenX.ExtraLogging/RenX_ExtraLogging.h new file mode 100644 index 0000000..d4f8a8b --- /dev/null +++ b/RenX.ExtraLogging/RenX_ExtraLogging.h @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_EXTRALOGGING_H_HEADER +#define _RENX_EXTRALOGGING_H_HEADER + +#include "Jupiter/Plugin.h" +#include "RenX_Plugin.h" + +class RenX_ExtraLoggingPlugin : public RenX::Plugin +{ +public: // RenX::Plugin + virtual void RenX_OnRaw(RenX::Server *server, const Jupiter::ReadableString &raw) override; + +public: // Jupiter::Plugin + const Jupiter::ReadableString &getName() override { return name; } + + RenX_ExtraLoggingPlugin(); + ~RenX_ExtraLoggingPlugin(); + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.ExtraLogging"); + FILE *file; // Replace with a Jupiter::File after making Jupiter::File. (Also remove constructor/destructor) +}; + +#endif // _RENX_EXTRALOGGING_H_HEADER \ No newline at end of file diff --git a/RenX.Logging/RenX.Logging.vcxproj b/RenX.Logging/RenX.Logging.vcxproj new file mode 100644 index 0000000..89a6988 --- /dev/null +++ b/RenX.Logging/RenX.Logging.vcxproj @@ -0,0 +1,85 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {069D6053-F39A-4418-BAA3-FA8D260C83D1} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.Logging/RenX.Logging.vcxproj.filters b/RenX.Logging/RenX.Logging.vcxproj.filters new file mode 100644 index 0000000..a529c26 --- /dev/null +++ b/RenX.Logging/RenX.Logging.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/RenX.Logging/RenX_Logging.cpp b/RenX.Logging/RenX_Logging.cpp new file mode 100644 index 0000000..77a9231 --- /dev/null +++ b/RenX.Logging/RenX_Logging.cpp @@ -0,0 +1,318 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Jupiter/INIFile.h" +#include "IRC_Bot.h" +#include "RenX_Logging.h" +#include "RenX_Core.h" +#include "RenX_PlayerInfo.h" +#include "RenX_Functions.h" +#include "RenX_Server.h" + +RenX_LoggingPlugin::RenX_LoggingPlugin() +{ + RenX_LoggingPlugin::joinPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("JoinPublic"), true); + RenX_LoggingPlugin::partPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("PartPublic"), true); + RenX_LoggingPlugin::nameChangePublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("NameChangePublic"), true); + RenX_LoggingPlugin::chatPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("ChatPublic"), true); + RenX_LoggingPlugin::teamChatPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("TeamChatPublic"), true); + RenX_LoggingPlugin::deployPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("DeployPublic"), true); + RenX_LoggingPlugin::suicidePublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("SuicidePublic"), true); + RenX_LoggingPlugin::killPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("KillPublic"), true); + RenX_LoggingPlugin::diePublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("DiePublic"), true); + RenX_LoggingPlugin::destroyPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("DestroyPublic"), true); + RenX_LoggingPlugin::gamePublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("GamePublic"), true); + RenX_LoggingPlugin::gameOverPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("GameOverPublic"), true); + RenX_LoggingPlugin::executePublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("ExecutePublic"), false); + RenX_LoggingPlugin::subscribePublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("SubscribePublic"), false); + RenX_LoggingPlugin::RCONPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("RCONPublic"), false); + RenX_LoggingPlugin::adminLoginPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("AdminLoginPublic"), true); + RenX_LoggingPlugin::adminLogoutPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("AdminLogoutPublic"), true); + RenX_LoggingPlugin::adminPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("AdminPublic"), false); + RenX_LoggingPlugin::logPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("LogPublic"), false); + RenX_LoggingPlugin::commandPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("CommandPublic"), false); + RenX_LoggingPlugin::errorPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("ErrorPublic"), false); + RenX_LoggingPlugin::versionPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("VersionPublic"), true); + RenX_LoggingPlugin::authorizedPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("AuthorizedPublic"), true); + RenX_LoggingPlugin::otherPublic = Jupiter::IRC::Client::Config->getBool(RenX_LoggingPlugin::getName(), STRING_LITERAL_AS_REFERENCE("OtherPublic"), false); +} + +typedef void(RenX::Server::*logFuncType)(const char *fmt, ...) const; + +void RenX_LoggingPlugin::RenX_OnJoin(RenX::Server *server, const RenX::PlayerInfo *player) +{ + const Jupiter::ReadableString &teamColor = RenX::getTeamColor(player->team); + const Jupiter::ReadableString &teamName = RenX::getFullTeamName(player->team); + + if (RenX_LoggingPlugin::joinPublic) + server->sendPubChan(IRCCOLOR "12[Join]" IRCCOLOR "%.*s " IRCBOLD "%.*s" IRCBOLD " joined the game fighting for the %.*s!", teamColor.size(), teamColor.ptr(), player->name.size(), player->name.ptr(), teamName.size(), teamName.ptr()); + if (player->steamid.isEmpty()) + server->sendAdmChan(IRCCOLOR "12[Join]" IRCCOLOR "%.*s " IRCBOLD "%.*s" IRCBOLD " joined the game fighting for the %.*s from " IRCBOLD "%.*s" IRCBOLD ", but is not using Steam.", teamColor.size(), teamColor.ptr(), player->name.size(), player->name.ptr(), teamName.size(), teamName.ptr(), player->ip.size(), player->ip.ptr()); + else + server->sendAdmChan(IRCCOLOR "12[Join]" IRCCOLOR "%.*s " IRCBOLD "%.*s" IRCBOLD " joined the game fighting for the %.*s from " IRCBOLD "%.*s" IRCBOLD " using Steam ID " IRCBOLD "%.*s" IRCBOLD ".", teamColor.size(), teamColor.ptr(), player->name.size(), player->name.ptr(), teamName.size(), teamName.ptr(), player->ip.size(), player->ip.ptr(), player->steamid.size(), player->steamid.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnPart(RenX::Server *server, const RenX::PlayerInfo *player) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + const Jupiter::ReadableString &teamName = RenX::getFullTeamName(player->team); + + logFuncType func; + if (RenX_LoggingPlugin::partPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "12[Part] " IRCBOLD "%.*s" IRCBOLD " has left the %.*s.", playerName.size(), playerName.ptr(), teamName.size(), teamName.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnNameChange(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &newPlayerName) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + + logFuncType func; + if (RenX_LoggingPlugin::nameChangePublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCBOLD "%.*s" IRCBOLD " has changed their name to " IRCBOLD "%.*s" IRCBOLD ".", playerName.size(), playerName.ptr(), newPlayerName.size(), newPlayerName.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnChat(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &message) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + + logFuncType func; + if (RenX_LoggingPlugin::chatPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCBOLD "%.*s" IRCCOLOR IRCBOLD ": %.*s", playerName.size(), playerName.ptr(), message.size(), message.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnTeamChat(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &message) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + + logFuncType func; + if (RenX_LoggingPlugin::teamChatPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCBOLD "%.*s" IRCBOLD ": %.*s", playerName.size(), playerName.ptr(), message.size(), message.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnDeploy(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &object) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + const Jupiter::ReadableString &translated = RenX::translateName(object); + + logFuncType func; + if (RenX_LoggingPlugin::deployPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCBOLD "%.*s" IRCBOLD " deployed a " IRCBOLD "%.*s" IRCBOLD, playerName.size(), playerName.ptr(), translated.size(), translated.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnSuicide(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + const Jupiter::ReadableString &translated = RenX::translateName(damageType); + + logFuncType func; + if (RenX_LoggingPlugin::suicidePublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)("%.*s" IRCCOLOR " suicided (death by " IRCCOLOR "12%.*s" IRCCOLOR ").", playerName.size(), playerName.ptr(), translated.size(), translated.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + const Jupiter::ReadableString &victimName = RenX::getFormattedPlayerName(victim); + const Jupiter::ReadableString &translated = RenX::translateName(damageType); + + logFuncType func; + if (RenX_LoggingPlugin::killPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)("%.*s" IRCCOLOR " killed %.*s" IRCCOLOR " (" IRCCOLOR "12%.*s" IRCCOLOR ").", playerName.size(), playerName.ptr(), victimName.size(), victimName.ptr(), translated.size(), translated.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnDie(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + const Jupiter::ReadableString &translated = RenX::translateName(damageType); + + logFuncType func; + if (RenX_LoggingPlugin::diePublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + if (damageType.equals("DmgType_Fell")) + (server->*func)("%.*s" IRCCOLOR " fell to their death!", playerName.size(), playerName.ptr()); + else if (damageType.equals("DamageType")) + (server->*func)("%.*s" IRCCOLOR " switched teams!", playerName.size(), playerName.ptr()); + else (server->*func)("%.*s" IRCCOLOR " died (" IRCCOLOR "12%.*s" IRCCOLOR ").", playerName.size(), playerName.ptr(), translated.size(), translated.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnDestroy(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &objectName, const Jupiter::ReadableString &damageType, RenX::ObjectType type) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + const Jupiter::ReadableString &objectTranslated = RenX::translateName(objectName); + const Jupiter::ReadableString &translated = RenX::translateName(damageType); + const Jupiter::ReadableString &enemyColor = RenX::getTeamColor(RenX::getEnemy(player->team)); + + logFuncType func; + if (RenX_LoggingPlugin::destroyPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)("%.*s" IRCCOLOR " destroyed %s " IRCCOLOR "%.*s%.*s" IRCCOLOR " (" IRCCOLOR "12%.*s" IRCCOLOR ").", playerName.size(), playerName.ptr(), type == RenX::ObjectType::Building ? "the" : "a", enemyColor.size(), enemyColor.ptr(), objectTranslated.size(), objectTranslated.ptr(), translated.size(), translated.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) +{ + const Jupiter::ReadableString &win = RenX::translateWinType(winType); + const Jupiter::ReadableString &teamColor = RenX::getTeamColor(team); + const Jupiter::ReadableString &teamName = RenX::getFullTeamName(team); + + const Jupiter::ReadableString &gTeamColor = RenX::getTeamColor(RenX::TeamType::GDI); + const Jupiter::ReadableString &gTeamName = RenX::getFullTeamName(RenX::TeamType::GDI); + + const Jupiter::ReadableString &nTeamColor = RenX::getTeamColor(RenX::TeamType::Nod); + const Jupiter::ReadableString &nTeamName = RenX::getFullTeamName(RenX::TeamType::Nod); + + logFuncType func; + if (RenX_LoggingPlugin::gameOverPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + if (winType == RenX::WinType::Tie) + { + if (team == RenX::TeamType::Other) (server->*func)(IRCCOLOR "03[Game]" IRCCOLOR "10 The battle ended in a " IRCBOLD "%.*s" IRCBOLD, win.size(), win.ptr()); + else (server->*func)(IRCCOLOR "03[Game]" IRCCOLOR "10 The battle ended in a " IRCBOLD "%.*s" IRCBOLD " - Victory handed to " IRCBOLD IRCCOLOR "%.*s%.*s" IRCBOLD, win.size(), win.ptr(), teamColor.size(), teamColor.ptr(), teamName.size(), teamName.ptr()); + } + else (server->*func)(IRCCOLOR "03[Game]" IRCCOLOR "%.*s The " IRCBOLD "%.*s" IRCBOLD " won by " IRCBOLD "%.*s" IRCBOLD, teamColor.size(), teamColor.ptr(), teamName.size(), teamName.ptr(), win.size(), win.ptr()); + (server->*func)(IRCCOLOR "03[Game]" IRCCOLOR "%.*s %.*s" IRCCOLOR ": %d | " IRCCOLOR "%.*s%.*s" IRCCOLOR ": %d", gTeamColor.size(), gTeamColor.ptr(), gTeamName.size(), gTeamName.ptr(), gScore, nTeamColor.size(), nTeamColor.ptr(), nTeamName.size(), nTeamName.ptr(), nScore); +} + +void RenX_LoggingPlugin::RenX_OnGame(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::gamePublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "03[Game]" IRCCOLOR " %.*s", raw.size(), raw.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnExecute(RenX::Server *server, const Jupiter::ReadableString &user, const Jupiter::ReadableString &command) +{ + logFuncType func; + if (RenX_LoggingPlugin::executePublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + if (command.matchi("say *")) + { + // Add an option for this later? Separate event? + func = &RenX::Server::sendLogChan; + (server->*func)(IRCCOLOR "09EVA: %.*s", command.size() - 4, command.ptr() + 4); + } + else (server->*func)(IRCCOLOR "07%.*s executed: %.*s", user.size(), user.ptr(), command.size(), command.ptr()); + // Add a format check later for if user == us. +} + +void RenX_LoggingPlugin::RenX_OnSubscribe(RenX::Server *server, const Jupiter::ReadableString &user) +{ + logFuncType func; + if (RenX_LoggingPlugin::subscribePublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "03%.*s has subscribed to the RCON data stream.", user.size(), user.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnRCON(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::RCONPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "05[RCON]" IRCCOLOR " %.*s", raw.size(), raw.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnAdminLogin(RenX::Server *server, const RenX::PlayerInfo *player) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + + logFuncType func; + if (RenX_LoggingPlugin::adminLoginPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "07[Admin] " IRCBOLD "%.*s" IRCBOLD IRCCOLOR " has logged in with " IRCCOLOR "07" IRCBOLD "%.*s" IRCBOLD IRCNORMAL " privledges.", playerName.size(), playerName.ptr(), player->adminType.size(), player->adminType.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnAdminLogout(RenX::Server *server, const RenX::PlayerInfo *player) +{ + const Jupiter::ReadableString &playerName = RenX::getFormattedPlayerName(player); + + logFuncType func; + if (RenX_LoggingPlugin::adminLogoutPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "07[Admin] " IRCBOLD "%.*s" IRCBOLD IRCCOLOR " has logged out of their " IRCCOLOR "07" IRCBOLD "%.*s" IRCBOLD IRCNORMAL " privledges.", playerName.size(), playerName.ptr(), player->adminType.size(), player->adminType.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnAdmin(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::adminPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "07[Admin]" IRCCOLOR " %.*s", raw.size(), raw.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnLog(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::logPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "07[Log]" IRCCOLOR " %.*s", raw.size(), raw.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnCommand(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::commandPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + // This is potentially useful later, but not yet! + //sendAdmChan(server, "[Command] %.*s", raw.size(), raw.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnError(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::errorPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "04[Error]" IRCCOLOR " %.*s", raw.size(), raw.ptr()); +} + +void RenX_LoggingPlugin::RenX_OnVersion(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::versionPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "03Renegade X RCON connection established; using RCON verison " IRCBOLD "%d" IRCBOLD " for game version " IRCBOLD "%.*s" IRCBOLD, raw.asInt(10), raw.size() - 3, raw.ptr() + 3); +} + +void RenX_LoggingPlugin::RenX_OnAuthorized(RenX::Server *server, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::authorizedPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "03RCON authorization completed."); +} + +void RenX_LoggingPlugin::RenX_OnOther(RenX::Server *server, char token, const Jupiter::ReadableString &raw) +{ + logFuncType func; + if (RenX_LoggingPlugin::otherPublic) func = &RenX::Server::sendLogChan; + else func = &RenX::Server::sendAdmChan; + (server->*func)(IRCCOLOR "06[Other]" IRCCOLOR " %.*s", raw.size(), raw.ptr()); +} + +// Plugin instantiation and entry point. +RenX_LoggingPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.Logging/RenX_Logging.h b/RenX.Logging/RenX_Logging.h new file mode 100644 index 0000000..162a2da --- /dev/null +++ b/RenX.Logging/RenX_Logging.h @@ -0,0 +1,90 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_LOGGING_H_HEADER +#define _RENX_LOGGING_H_HEADER + +#include "Jupiter/Plugin.h" +#include "RenX_Plugin.h" + +class RenX_LoggingPlugin : public RenX::Plugin +{ +public: // RenX::Plugin + void RenX_OnJoin(RenX::Server *server, const RenX::PlayerInfo *player) override; + void RenX_OnPart(RenX::Server *server, const RenX::PlayerInfo *player) override; + void RenX_OnNameChange(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &newPlayerName) override; + + void RenX_OnChat(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &message) override; + void RenX_OnTeamChat(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &message) override; + + void RenX_OnDeploy(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &object) override; + void RenX_OnSuicide(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) override; + void RenX_OnKill(RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const Jupiter::ReadableString &damageType) override; + void RenX_OnDie(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &damageType) override; + void RenX_OnDestroy(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &objectName, const Jupiter::ReadableString &damageType, RenX::ObjectType type) override; + void RenX_OnGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) override; + void RenX_OnGame(RenX::Server *server, const Jupiter::ReadableString &raw) override; + + void RenX_OnExecute(RenX::Server *server, const Jupiter::ReadableString &user, const Jupiter::ReadableString &command) override; + void RenX_OnSubscribe(RenX::Server *server, const Jupiter::ReadableString &user) override; + void RenX_OnRCON(RenX::Server *server, const Jupiter::ReadableString &raw) override; + + void RenX_OnAdminLogin(RenX::Server *server, const RenX::PlayerInfo *player) override; + void RenX_OnAdminLogout(RenX::Server *server, const RenX::PlayerInfo *player) override; + void RenX_OnAdmin(RenX::Server *server, const Jupiter::ReadableString &raw) override; + + void RenX_OnLog(RenX::Server *server, const Jupiter::ReadableString &raw) override; + void RenX_OnCommand(RenX::Server *server, const Jupiter::ReadableString &raw) override; + void RenX_OnError(RenX::Server *server, const Jupiter::ReadableString &raw) override; + void RenX_OnVersion(RenX::Server *server, const Jupiter::ReadableString &raw) override; + void RenX_OnAuthorized(RenX::Server *server, const Jupiter::ReadableString &raw) override; + void RenX_OnOther(RenX::Server *server, const char token, const Jupiter::ReadableString &raw) override; + +public: // Plugin + const Jupiter::ReadableString &getName() override { return name; } + + RenX_LoggingPlugin(); + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.Logging"); + unsigned int joinPublic : 1; + unsigned int partPublic : 1; + unsigned int nameChangePublic : 1; + unsigned int chatPublic : 1; + unsigned int teamChatPublic : 1; + unsigned int deployPublic : 1; + unsigned int suicidePublic : 1; + unsigned int killPublic : 1; + unsigned int diePublic : 1; + unsigned int destroyPublic : 1; + unsigned int gamePublic : 1; + unsigned int gameOverPublic : 1; + unsigned int executePublic : 1; + unsigned int subscribePublic : 1; + unsigned int RCONPublic : 1; + unsigned int adminLoginPublic : 1; + unsigned int adminLogoutPublic : 1; + unsigned int adminPublic : 1; + unsigned int logPublic : 1; + unsigned int commandPublic : 1; + unsigned int errorPublic : 1; + unsigned int versionPublic : 1; + unsigned int authorizedPublic : 1; + unsigned int otherPublic : 1; +}; + +#endif // _RENX_LOGGING_H_HEADER \ No newline at end of file diff --git a/RenX.Medals/RenX.Medals.vcxproj b/RenX.Medals/RenX.Medals.vcxproj new file mode 100644 index 0000000..dd3070d --- /dev/null +++ b/RenX.Medals/RenX.Medals.vcxproj @@ -0,0 +1,86 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {C295FFC2-8CE5-4387-B237-E4E1B1AB9987} + PluginExample + RenX.Medals + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.Medals/RenX.Medals.vcxproj.filters b/RenX.Medals/RenX.Medals.vcxproj.filters new file mode 100644 index 0000000..6fe5cbf --- /dev/null +++ b/RenX.Medals/RenX.Medals.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Source Files + + + + + Header Files + + + \ No newline at end of file diff --git a/RenX.Medals/RenX_Medals.cpp b/RenX.Medals/RenX_Medals.cpp new file mode 100644 index 0000000..a269d3a --- /dev/null +++ b/RenX.Medals/RenX_Medals.cpp @@ -0,0 +1,355 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/Timer.h" +#include "RenX_Medals.h" +#include "RenX_Server.h" +#include "RenX_PlayerInfo.h" +#include "RenX_Functions.h" + +//#error "Do not use this plugin -- it will be retwritten." +const char *medalsFileName = "medals.ini"; + +struct MedalPlayerData +{ + Jupiter::StringS steamID; + unsigned long recs = 0; + unsigned long noobs = 0; + Jupiter::StringS lastName; + time_t lastSeen = 0; + + MedalPlayerData(Jupiter::INIFile &medalsFile, const Jupiter::ReadableString &steamid) + { + MedalPlayerData::steamID = steamid; + if (medalsFile.getSectionIndex(MedalPlayerData::steamID) != Jupiter::INVALID_INDEX) + { + MedalPlayerData::recs = medalsFile.get(MedalPlayerData::steamID, STRING_LITERAL_AS_REFERENCE("Recs")).asUnsignedInt(10); + MedalPlayerData::noobs = medalsFile.get(MedalPlayerData::steamID, STRING_LITERAL_AS_REFERENCE("Noobs")).asUnsignedInt(10); + MedalPlayerData::lastName = medalsFile.get(MedalPlayerData::steamID, STRING_LITERAL_AS_REFERENCE("Name")); + MedalPlayerData::lastSeen = medalsFile.getInt(MedalPlayerData::steamID, STRING_LITERAL_AS_REFERENCE("Seen")); + } + } +}; + +RenX_MedalsPlugin::RenX_MedalsPlugin() +{ + medalsFile.readFile(medalsFileName); +} + +void updateMedalPlayerData(MedalPlayerData &player, RenX::PlayerInfo *pInfo) +{ + player.lastName = pInfo->name; + player.lastSeen = time(0); +} + +void syncPlayerMedalDataToINI(Jupiter::INIFile &file, MedalPlayerData &player, const Jupiter::ReadableString &steamid) +{ + file.set(steamid, STRING_LITERAL_AS_REFERENCE("Name"), player.lastName); + file.set(steamid, STRING_LITERAL_AS_REFERENCE("Seen"), Jupiter::StringS::Format("%d", player.lastSeen)); +} + +struct CongratPlayerData +{ + RenX::Server *server; + Jupiter::StringS playerName; + unsigned int type; +}; + +void congratPlayer(unsigned int, void *params) +{ + CongratPlayerData *congratPlayerData = (CongratPlayerData *) params; + + switch (congratPlayerData->type) + { + case 1: + congratPlayerData->server->sendMessage(Jupiter::StringS::Format("%.*s has been recommended for having the most kills last game!", congratPlayerData->playerName.size(), congratPlayerData->playerName.ptr())); + break; + case 2: + congratPlayerData->server->sendMessage(Jupiter::StringS::Format("%.*s has been recommended for having the most vehicle kills last game!", congratPlayerData->playerName.size(), congratPlayerData->playerName.ptr())); + break; + case 3: + congratPlayerData->server->sendMessage(Jupiter::StringS::Format("%.*s has been recommended for having the highest Kill-Death ratio last game!", congratPlayerData->playerName.size(), congratPlayerData->playerName.ptr())); + break; + default: + break; + } + delete congratPlayerData; +} + +void RenX_MedalsPlugin::RenX_OnGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) +{ + if (firstGame) + { + firstGame = false; + return; + } + if (server->players.size() == 0) return; + Jupiter::DLList::Node *n = server->players.getNode(0); + RenX::PlayerInfo *pInfo = n->data; + RenX::PlayerInfo *mostKills = pInfo; + RenX::PlayerInfo *mostVehicleKills = pInfo; + RenX::PlayerInfo *bestKD = pInfo; + + while (n != nullptr) + { + pInfo = n->data; + if (pInfo->kills > mostKills->kills) mostKills = pInfo; + if (pInfo->vehicleKills > mostVehicleKills->vehicleKills) mostVehicleKills = pInfo; + if (RenX::getKillDeathRatio(pInfo) > RenX::getKillDeathRatio(bestKD)) bestKD = pInfo; + + if (pInfo->steamid.size() != 0) + { + MedalPlayerData player(RenX_MedalsPlugin::medalsFile, pInfo->steamid); + updateMedalPlayerData(player, pInfo); + syncPlayerMedalDataToINI(RenX_MedalsPlugin::medalsFile, player, pInfo->steamid); + } + n = n->next; + } + + CongratPlayerData *congratPlayerData; + + /** +1 for most kills */ + if (mostKills->steamid.size() != 0 && mostKills->kills > 0) + { + addRec(mostKills); + MedalPlayerData player(RenX_MedalsPlugin::medalsFile, mostKills->steamid); + syncPlayerMedalDataToINI(RenX_MedalsPlugin::medalsFile, player, mostKills->steamid); + + congratPlayerData = new CongratPlayerData(); + congratPlayerData->server = server; + congratPlayerData->playerName = mostKills->name; + congratPlayerData->type = 1; + new Jupiter::Timer(1, 60, congratPlayer, congratPlayerData, false); + } + + /** +1 for most Vehicle kills */ + if (mostVehicleKills->steamid.size() != 0 && mostVehicleKills->vehicleKills > 0) + { + addRec(mostVehicleKills); + MedalPlayerData player(RenX_MedalsPlugin::medalsFile, mostVehicleKills->steamid); + syncPlayerMedalDataToINI(RenX_MedalsPlugin::medalsFile, player, mostVehicleKills->steamid); + + congratPlayerData = new CongratPlayerData(); + congratPlayerData->server = server; + congratPlayerData->playerName = mostVehicleKills->name; + congratPlayerData->type = 2; + new Jupiter::Timer(1, 60, congratPlayer, congratPlayerData, false); + } + + /** +1 for best K/D ratio */ + if (bestKD->steamid.size() != 0) + { + addRec(bestKD); + MedalPlayerData player(RenX_MedalsPlugin::medalsFile, bestKD->steamid); + syncPlayerMedalDataToINI(RenX_MedalsPlugin::medalsFile, player, bestKD->steamid); + + congratPlayerData = new CongratPlayerData(); + congratPlayerData->server = server; + congratPlayerData->playerName = bestKD->name; + congratPlayerData->type = 3; + new Jupiter::Timer(1, 60, congratPlayer, congratPlayerData, false); + } + + RenX_MedalsPlugin::medalsFile.sync(); +} + +void RenX_MedalsPlugin::RenX_OnDestroy(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &objectName, const Jupiter::ReadableString &damageType, RenX::ObjectType type) +{ + if (type == RenX::ObjectType::Building) + { + addRec((RenX::PlayerInfo *) player); // -whistles- + MedalPlayerData playerMedalData(RenX_MedalsPlugin::medalsFile, player->steamid); + updateMedalPlayerData(playerMedalData, (RenX::PlayerInfo *) player); // -whistles- + syncPlayerMedalDataToINI(RenX_MedalsPlugin::medalsFile, playerMedalData, player->steamid); + + const Jupiter::ReadableString &translated = RenX::translateName(objectName); + server->sendMessage(Jupiter::StringS::Format("%.*s has been recommended for destroying the %.*s!", player->name.size(), player->name.ptr(), translated.size(), translated.ptr())); + } +} + +// Recommendations Game Command + +void RecsGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("recs")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("recommends")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("recommendations")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("noobs")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("n00bs")); +} + +void RecsGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); + if (target == nullptr) + { + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found! Syntax: recs [player]")); + // Check INI? + } + else if (target->steamid.size() == 0) + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player is not using steam.")); + else if (target == player) + RecsGameCommand::trigger(source, player, Jupiter::ReferenceString::empty); + else source->sendMessage(Jupiter::StringS::Format("%.*s has %lu and %lu n00bs. Their worth: %d", target->name.size(), target->name.ptr(), getRecs(target), getNoobs(target), getWorth(target))); + } + else if (player->steamid.size() == 0) + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: You are not using steam.")); + else source->sendMessage(Jupiter::StringS::Format("%.*s, you have %lu and %lu n00bs. Your worth: %d", player->name.size(), player->name.ptr(), getRecs(player), getNoobs(player), getWorth(player))); +} + +const Jupiter::ReadableString &RecsGameCommand::getHelp(const Jupiter::ReadableString &) +{ + STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Gets a count of a player's recommendations and noobs. Syntax: recs [player]"); + return defaultHelp; +} + +GAME_COMMAND_INIT(RecsGameCommand) + +// Recommend Game Command + +void RecGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rec")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("recommend")); +} + +void RecGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); + if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found! Syntax: rec ")); + else if (target->steamid.size() == 0) + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player is not using steam.")); + else if (target == player) + { + addNoob(player); + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("You can't recommend yourself, you noob! (+1 noob)")); + } + else if (player->varData.get(STRING_LITERAL_AS_REFERENCE("RenX.Medals"), STRING_LITERAL_AS_REFERENCE("gr")).isEmpty() == false) + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("You can only give one recommendation per game.")); + else + { + addRec(target); + source->sendMessage(Jupiter::StringS::Format("%.*s has recommended %.*s!", player->name.size(), player->name.ptr(), target->name.size(), target->name.ptr())); + player->varData.set(STRING_LITERAL_AS_REFERENCE("RenX.Medals"), STRING_LITERAL_AS_REFERENCE("gr"), STRING_LITERAL_AS_REFERENCE("1")); + } + } + else RecsGameCommand_instance.trigger(source, player, parameters); +} + +const Jupiter::ReadableString &RecGameCommand::getHelp(const Jupiter::ReadableString &) +{ + STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Recommends a player for their gameplay. Syntax: rec [player]"); + return defaultHelp; +} + +GAME_COMMAND_INIT(RecGameCommand) + +// Noob Game Command + +void NoobGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("noob")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("n00b")); +} + +void NoobGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + RenX::PlayerInfo *target = source->getPlayerByPartName(parameters); + if (target == nullptr) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player not found! Syntax: noob [player]")); + else if (target->steamid.size() == 0) source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Player is not using steam.")); + else if (player->varData.get(STRING_LITERAL_AS_REFERENCE("RenX.Medals"), STRING_LITERAL_AS_REFERENCE("gn")) != nullptr) + source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("You can only give one noob per game.")); + else + { + addNoob(target); + source->sendMessage(Jupiter::StringS::Format("%.*s has noob'd %.*s!", player->name.size(), player->name.ptr(), target->name.size(), target->name.ptr())); + player->varData.set(STRING_LITERAL_AS_REFERENCE("RenX.Medals"), STRING_LITERAL_AS_REFERENCE("gn"), STRING_LITERAL_AS_REFERENCE("1")); + } + } + else RecsGameCommand_instance.trigger(source, player, parameters); +} + +const Jupiter::ReadableString &NoobGameCommand::getHelp(const Jupiter::ReadableString &) +{ + STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Tells people that a player is bad. Syntax: noob [player]"); + return defaultHelp; +} + +GAME_COMMAND_INIT(NoobGameCommand) + +// Plugin instantiation and entry point. +RenX_MedalsPlugin pluginInstance; + + +void addRec(MedalPlayerData &player, int amount) +{ + player.recs += amount; + pluginInstance.medalsFile.set(player.steamID, STRING_LITERAL_AS_REFERENCE("Recs"), Jupiter::StringS::Format("%u", player.recs)); +} + +void addNoob(MedalPlayerData &player, int amount) +{ + player.noobs += amount; + pluginInstance.medalsFile.set(player.steamID, STRING_LITERAL_AS_REFERENCE("Noobs"), Jupiter::StringS::Format("%u", player.noobs)); +} + +int getWorth(MedalPlayerData &player) +{ + return player.recs - player.noobs; +} + +inline MedalPlayerData getMedalPlayerData(RenX::PlayerInfo *player) +{ + return MedalPlayerData(pluginInstance.medalsFile, player->steamid); +} + +void addRec(RenX::PlayerInfo *player, int amount) +{ + addRec(getMedalPlayerData(player), amount); +} + +void addNoob(RenX::PlayerInfo *player, int amount) +{ + addNoob(getMedalPlayerData(player), amount); +} + +unsigned long getRecs(RenX::PlayerInfo *player) +{ + return getMedalPlayerData(player).recs; +} + +unsigned long getNoobs(RenX::PlayerInfo *player) +{ + return getMedalPlayerData(player).noobs; +} + +int getWorth(RenX::PlayerInfo *player) +{ + return getWorth(getMedalPlayerData(player)); +} + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.Medals/RenX_Medals.h b/RenX.Medals/RenX_Medals.h new file mode 100644 index 0000000..c956f65 --- /dev/null +++ b/RenX.Medals/RenX_Medals.h @@ -0,0 +1,63 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_MEDALS_H_HEADER +#define _RENX_MEDALS_H_HEADER + +#include "Jupiter/Plugin.h" +#include "Jupiter/INIFile.h" +#include "RenX_Plugin.h" +#include "RenX_GameCommand.h" + +/** Adds a recommendation to the player's medal data */ +void addRec(RenX::PlayerInfo *player, int amount = 1); + +/** Adds a noob to the player's medal data */ +void addNoob(RenX::PlayerInfo *player, int amount = 1); + +/** Fetches a player's recommendation count */ +unsigned long getRecs(RenX::PlayerInfo *player); + +/** Fetches a player's noob count */ +unsigned long getNoobs(RenX::PlayerInfo *player); + +/** Calculates a player's worth (recs - noobs) */ +int getWorth(RenX::PlayerInfo *player); + +class RenX_MedalsPlugin : public RenX::Plugin +{ +public: // RenX::Plugin + void RenX_OnGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) override; + void RenX_OnDestroy(RenX::Server *server, const RenX::PlayerInfo *player, const Jupiter::ReadableString &objectName, const Jupiter::ReadableString &damageType, RenX::ObjectType type) override; + RenX_MedalsPlugin(); + +public: // Jupiter::Plugin + const Jupiter::ReadableString &getName() override { return name; } + +public: + bool firstGame = true; + Jupiter::INIFile medalsFile; + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.Medals"); +}; + +GENERIC_GAME_COMMAND(RecsGameCommand) +GENERIC_GAME_COMMAND(RecGameCommand) +GENERIC_GAME_COMMAND(NoobGameCommand) + +#endif // _RENX_MEDALS_H_HEADER \ No newline at end of file diff --git a/RenX.Plugin.Template - Copy/Example.cpp b/RenX.Plugin.Template - Copy/Example.cpp new file mode 100644 index 0000000..1eb99c9 --- /dev/null +++ b/RenX.Plugin.Template - Copy/Example.cpp @@ -0,0 +1,11 @@ +#include "Example.h" + + + +// Plugin instantiation and entry point. +RenX_TPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.Plugin.Template - Copy/Example.h b/RenX.Plugin.Template - Copy/Example.h new file mode 100644 index 0000000..9ba60c4 --- /dev/null +++ b/RenX.Plugin.Template - Copy/Example.h @@ -0,0 +1,12 @@ +#if !defined _EXAMPLE_H_HEADER +#define _EXAMPLE_H_HEADER + +#include "Plugin.h" +#include "RenX_Plugin.h" + +class RenX_TPlugin : public RenX::Plugin +{ + const char *getName() { return "RenX_TemplatePlugin"; } +}; + +#endif // _EXAMPLE_H_HEADER \ No newline at end of file diff --git a/RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj b/RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj new file mode 100644 index 0000000..3f32ed0 --- /dev/null +++ b/RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj @@ -0,0 +1,84 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {1DD04156-F096-4C41-9E1C-5BFD3234E9FD} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj.filters b/RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj.filters new file mode 100644 index 0000000..cf05782 --- /dev/null +++ b/RenX.Plugin.Template - Copy/RenX.Plugin.Template.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/RenX.Plugin.Template/Example.cpp b/RenX.Plugin.Template/Example.cpp new file mode 100644 index 0000000..85bc932 --- /dev/null +++ b/RenX.Plugin.Template/Example.cpp @@ -0,0 +1,19 @@ +/** + * This file is in the public domain, furnished "as is", without technical + * support, and with no warranty, express or implied, as to its usefulness for + * any purpose. + * + * Written by Justin James + */ + +#include "Example.h" + + + +// Plugin instantiation and entry point. +RenX_TPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.Plugin.Template/Example.h b/RenX.Plugin.Template/Example.h new file mode 100644 index 0000000..fffc764 --- /dev/null +++ b/RenX.Plugin.Template/Example.h @@ -0,0 +1,24 @@ +/** + * This file is in the public domain, furnished "as is", without technical + * support, and with no warranty, express or implied, as to its usefulness for + * any purpose. + * + * Written by Justin James + */ + +#if !defined _EXAMPLE_H_HEADER +#define _EXAMPLE_H_HEADER + +#include "Jupiter/Plugin.h" +#include "Jupiter/Reference_String.h" +#include "RenX_Plugin.h" + +class RenX_TPlugin : public RenX::Plugin +{ + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX_TemplatePlugin"); +}; + +#endif // _EXAMPLE_H_HEADER \ No newline at end of file diff --git a/RenX.Plugin.Template/RenX.Plugin.Template.vcxproj b/RenX.Plugin.Template/RenX.Plugin.Template.vcxproj new file mode 100644 index 0000000..d8e3686 --- /dev/null +++ b/RenX.Plugin.Template/RenX.Plugin.Template.vcxproj @@ -0,0 +1,85 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {6F575493-CF43-43CB-8062-9F3D0722A624} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.Plugin.Template/RenX.Plugin.Template.vcxproj.filters b/RenX.Plugin.Template/RenX.Plugin.Template.vcxproj.filters new file mode 100644 index 0000000..cf05782 --- /dev/null +++ b/RenX.Plugin.Template/RenX.Plugin.Template.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + + + Source Files + + + + + Resource Files + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/RenX.SetJoin/RenX.SetJoin.vcxproj b/RenX.SetJoin/RenX.SetJoin.vcxproj new file mode 100644 index 0000000..e6cfd1d --- /dev/null +++ b/RenX.SetJoin/RenX.SetJoin.vcxproj @@ -0,0 +1,85 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {0489F164-DC8F-433C-8CFA-F7EB2A3356F1} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter;../RenX.Core + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/RenX.SetJoin/RenX.SetJoin.vcxproj.filters b/RenX.SetJoin/RenX.SetJoin.vcxproj.filters new file mode 100644 index 0000000..7637ba1 --- /dev/null +++ b/RenX.SetJoin/RenX.SetJoin.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/RenX.SetJoin/RenX_SetJoin.cpp b/RenX.SetJoin/RenX_SetJoin.cpp new file mode 100644 index 0000000..92f5910 --- /dev/null +++ b/RenX.SetJoin/RenX_SetJoin.cpp @@ -0,0 +1,130 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include "Jupiter/IRC_Client.h" +#include "Jupiter/INIFile.h" +#include "RenX_SetJoin.h" +#include "RenX_PlayerInfo.h" +#include "RenX_Server.h" + +const Jupiter::ReferenceString configSection(STRING_LITERAL_AS_REFERENCE("RenX.SetJoin")); + +void RenX_SetJoinPlugin::RenX_OnJoin(RenX::Server *server, const RenX::PlayerInfo *player) +{ + if (player->steamid.size() != 0) + { + const Jupiter::ReadableString &setjoin = Jupiter::IRC::Client::Config->get(configSection, player->steamid); + if (setjoin.isEmpty() == false) + server->sendMessage(Jupiter::StringS::Format("[%.*s] %.*s", player->name.size(), player->name.ptr(), setjoin.size(), setjoin.ptr())); + } +} + +// ViewJoin Game Command + +void ViewJoinGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("viewjoin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("vjoin")); +} + +void ViewJoinGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + if (player->steamid.size() != 0) + { + const Jupiter::ReadableString &setjoin = Jupiter::IRC::Client::Config->get(configSection, player->steamid); + if (setjoin.isEmpty() == false) + source->sendMessage(Jupiter::StringS::Format("[%.*s] %.*s", player->name.size(), player->name.ptr(), setjoin.size(), setjoin.ptr())); + else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: No setjoin found.")); + } + else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: A setjoin message requires steam.")); +} + +const Jupiter::ReadableString &ViewJoinGameCommand::getHelp(const Jupiter::ReadableString &) +{ + STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays your join message. Syntax: viewjoin"); + return defaultHelp; +} + +GAME_COMMAND_INIT(ViewJoinGameCommand) + +// DelJoin Game Command + +void DelJoinGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("deljoin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("remjoin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("djoin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("rjoin")); +} + +void DelJoinGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString &) +{ + if (player->steamid.size() != 0) + { + if (Jupiter::IRC::Client::Config->remove(configSection, player->steamid)) + source->sendMessage(player, Jupiter::StringS::Format("%.*s, your join message has been removed.", player->name.size(), player->name.ptr())); + else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: Setjoin not found.")); + } + else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: A setjoin message requires steam.")); +} + +const Jupiter::ReadableString &DelJoinGameCommand::getHelp(const Jupiter::ReadableString &) +{ + STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Removes your automatic join message. Syntax: deljoin"); + return defaultHelp; +} + +GAME_COMMAND_INIT(DelJoinGameCommand) + +// SetJoin Game Command + +void SetJoinGameCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("setjoin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("sjoin")); +} + +void SetJoinGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) +{ + if (player->steamid.isEmpty() == false) + { + if (parameters.isEmpty() == false) + { + Jupiter::IRC::Client::Config->set(configSection, player->steamid, parameters); + Jupiter::IRC::Client::Config->sync(); + source->sendMessage(player, Jupiter::StringS::Format("%.*s, your join message is now: %.*s", player->name.size(), player->name.ptr(), parameters.size(), parameters.ptr())); + } + else DelJoinGameCommand_instance.trigger(source, player, parameters); + } + else source->sendMessage(player, STRING_LITERAL_AS_REFERENCE("Error: A setjoin message requires steam.")); +} + +const Jupiter::ReadableString &SetJoinGameCommand::getHelp(const Jupiter::ReadableString &) +{ + STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sets an automatic join message. Syntax: setjoin [message]"); + return defaultHelp; +} + +GAME_COMMAND_INIT(SetJoinGameCommand) + +// Plugin instantiation and entry point. +RenX_SetJoinPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/RenX.SetJoin/RenX_SetJoin.h b/RenX.SetJoin/RenX_SetJoin.h new file mode 100644 index 0000000..e0489f4 --- /dev/null +++ b/RenX.SetJoin/RenX_SetJoin.h @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_SETJOIN_H_HEADER +#define _RENX_SETJOIN_H_HEADER + +#include "Jupiter/Plugin.h" +#include "RenX_Plugin.h" +#include "RenX_GameCommand.h" + +class RenX_SetJoinPlugin : public RenX::Plugin +{ +public: + void RenX_OnJoin(RenX::Server *server, const RenX::PlayerInfo *player) override; + +public: // Jupiter::Plugin + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.SetJoin"); +}; + +GENERIC_GAME_COMMAND(SetJoinGameCommand) +GENERIC_GAME_COMMAND(ViewJoinGameCommand) +GENERIC_GAME_COMMAND(DelJoinGameCommand) + +#endif // _RENX_SETJOIN_H_HEADER \ No newline at end of file diff --git a/SetJoin/SetJoin.cpp b/SetJoin/SetJoin.cpp new file mode 100644 index 0000000..3d4810d --- /dev/null +++ b/SetJoin/SetJoin.cpp @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#include +#include "Jupiter/INIFile.h" +#include "Jupiter/Functions.h" +#include "SetJoin.h" +#include "IRC_Bot.h" + +void SetJoinPlugin::OnJoin(Jupiter::IRC::Client *server, const Jupiter::StringType &chan, const Jupiter::StringType &nick) +{ + const Jupiter::ReadableString &setjoin = server->Config->get(STRING_LITERAL_AS_REFERENCE("SetJoins"), nick); + if (setjoin.isEmpty() == false) + { + if (setjoin == nullptr) + server->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("No setjoin has been set for you. To set one, use the !setjoin command")); + else + server->sendMessage(chan, Jupiter::StringS::Format(IRCBOLD IRCCOLOR "07[%.*s]" IRCCOLOR IRCBOLD ": %.*s", nick.size(), nick.ptr(), setjoin.size(), setjoin.ptr())); + } +} + +// SetJoin Command + +void SetJoinIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("setJoin")); +} + +void SetJoinIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (parameters.size() != 0) + { + source->Config->set(STRING_LITERAL_AS_REFERENCE("SetJoins"), nick, parameters); + source->Config->sync(); + source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Your join message has been set.")); + } + else source->sendMessage(channel, STRING_LITERAL_AS_REFERENCE("Too few parameters! Syntax: setjoin ")); +} + +const Jupiter::ReadableString &SetJoinIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Sets your join message. Syntax: setjoin "); + return defaultHelp; +} + +IRC_COMMAND_INIT(SetJoinIRCCommand) + +// ViewJoin Command + +void ViewJoinIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("viewJoin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("vJoin")); +} + +void ViewJoinIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + const Jupiter::ReadableString &target = parameters.isEmpty() ? nick : parameters; + const Jupiter::ReadableString &r = source->Config->get(STRING_LITERAL_AS_REFERENCE("SetJoins"), target); + + if (r.isEmpty()) + source->sendMessage(channel, Jupiter::StringS::Format("No setjoin has been set for \"%.*s\".", target.size(), target.ptr())); + else + source->sendMessage(channel, Jupiter::StringS::Format(IRCBOLD IRCCOLOR "07[%.*s]" IRCCOLOR IRCBOLD ": %.*s", target.size(), target.ptr(), r.size(), r.ptr())); +} + +const Jupiter::ReadableString &ViewJoinIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Views a user's join message. Syntax: viewjoin [user=you]"); + return defaultHelp; +} + +IRC_COMMAND_INIT(ViewJoinIRCCommand) + +// DelJoin Command + +void DelJoinIRCCommand::create() +{ + this->addTrigger(STRING_LITERAL_AS_REFERENCE("delJoin")); + this->addTrigger(STRING_LITERAL_AS_REFERENCE("dJoin")); +} + +void DelJoinIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + if (source->Config->remove(STRING_LITERAL_AS_REFERENCE("SetJoins"), nick)) + source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("Your setjoin has been deleted successfully.")); + else source->sendNotice(nick, STRING_LITERAL_AS_REFERENCE("No setjoin was found to delete.")); +} + +const Jupiter::ReadableString &DelJoinIRCCommand::getHelp(const Jupiter::ReadableString &) +{ + static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Deletes your join message. Syntax: deljoin"); + return defaultHelp; +} + +IRC_COMMAND_INIT(DelJoinIRCCommand) + +// Plugin instantiation and entry point. +SetJoinPlugin pluginInstance; + +extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() +{ + return &pluginInstance; +} diff --git a/SetJoin/SetJoin.h b/SetJoin/SetJoin.h new file mode 100644 index 0000000..82c3639 --- /dev/null +++ b/SetJoin/SetJoin.h @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2014 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _SETJOIN_H_HEADER +#define _SETJOIN_H_HEADER + +#include "Jupiter/Plugin.h" +#include "IRC_Command.h" + +class SetJoinPlugin : public Jupiter::Plugin +{ +public: + void OnJoin(Jupiter::IRC::Client *server, const Jupiter::StringType &chan, const Jupiter::StringType &nick); + const Jupiter::ReadableString &getName() override { return name; } + +private: + STRING_LITERAL_AS_NAMED_REFERENCE(name, "SetJoin"); +}; + +GENERIC_IRC_COMMAND(SetJoinIRCCommand) +GENERIC_IRC_COMMAND(ViewJoinIRCCommand) +GENERIC_IRC_COMMAND(DelJoinIRCCommand) + +#endif // _SETJOIN_H_HEADER \ No newline at end of file diff --git a/SetJoin/SetJoin.vcxproj b/SetJoin/SetJoin.vcxproj new file mode 100644 index 0000000..75a6f4c --- /dev/null +++ b/SetJoin/SetJoin.vcxproj @@ -0,0 +1,84 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {FDBEC4F9-AC8D-4197-BA6C-D042DF218A93} + PluginExample + + + + Application + true + v120 + MultiByte + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + $(SolutionDir)$(Configuration)\Plugins\ + AllRules.ruleset + + + + Level3 + Disabled + true + + + true + + + + + Level3 + MaxSpeed + true + true + true + ../Bot;../Jupiter + _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + + + true + true + true + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/SetJoin/SetJoin.vcxproj.filters b/SetJoin/SetJoin.vcxproj.filters new file mode 100644 index 0000000..0556fde --- /dev/null +++ b/SetJoin/SetJoin.vcxproj.filters @@ -0,0 +1,35 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Resource Files + + + Resource Files + + + + + Header Files + + + + + Source Files + + + \ No newline at end of file