diff --git a/Bot/Console_Command.h b/Bot/Console_Command.h index e7955ae..dcf2a4f 100644 --- a/Bot/Console_Command.h +++ b/Bot/Console_Command.h @@ -94,27 +94,44 @@ class CLASS : public ConsoleCommand { \ #define CONSOLE_COMMAND_INIT(CLASS) \ CLASS CLASS ## _instance; -/** Generates a console command implementation from a generic command. */ -#define GENERIC_COMMAND_AS_CONSOLE_COMMAND_IMPL(CLASS) \ - CLASS ## _AS_CONSOLE_COMMAND :: CLASS ## _AS_CONSOLE_COMMAND() { \ - size_t index = 0; \ - while (index != CLASS ## _instance.getTriggerCount()) this->addTrigger(CLASS ## _instance.getTrigger(index++)); } \ - void CLASS ## _AS_CONSOLE_COMMAND :: trigger(const Jupiter::ReadableString ¶meters) { \ - GenericCommand::ResponseLine *del; \ - GenericCommand::ResponseLine *ret = CLASS ## _instance.trigger(parameters); \ - while (ret != nullptr) { \ - ret->response.println(ret->type == GenericCommand::DisplayType::PublicError || ret->type == GenericCommand::DisplayType::PrivateError ? stderr : stdout); \ - del = ret; ret = ret->next; delete del; } } \ - const Jupiter::ReadableString & CLASS ## _AS_CONSOLE_COMMAND :: getHelp(const Jupiter::ReadableString ¶meters) { \ - return CLASS ## _instance.getHelp(parameters); } \ - CONSOLE_COMMAND_INIT(CLASS ## _AS_CONSOLE_COMMAND) - /** Generates a console command from a generic command. */ -#define GENERIC_COMMAND_AS_CONSOLE_COMMAND(CLASS) \ - GENERIC_CONSOLE_COMMAND(CLASS ## _AS_CONSOLE_COMMAND) \ - GENERIC_COMMAND_AS_CONSOLE_COMMAND_IMPL(CLASS); +template class Generic_Command_As_Console_Command : public ConsoleCommand +{ +public: + void trigger(const Jupiter::ReadableString ¶meters); + const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters); + + Generic_Command_As_Console_Command(); +}; +template Generic_Command_As_Console_Command::Generic_Command_As_Console_Command() : ConsoleCommand() +{ + size_t index = 0; + while (index != T::instance.getTriggerCount()) + this->addTrigger(T::instance.getTrigger(index++)); +} +template void Generic_Command_As_Console_Command::trigger(const Jupiter::ReadableString ¶meters) +{ + GenericCommand::ResponseLine *del; + GenericCommand::ResponseLine *ret = T::instance.trigger(parameters); + while (ret != nullptr) + { + ret->response.println(ret->type == GenericCommand::DisplayType::PublicError || ret->type == GenericCommand::DisplayType::PrivateError ? stderr : stdout); + del = ret; + ret = ret->next; + delete del; + } +} + +template const Jupiter::ReadableString &Generic_Command_As_Console_Command::getHelp(const Jupiter::ReadableString ¶meters) +{ + return T::instance.getHelp(parameters); +} + +/** Generates a console command implementation from a generic command. */ +#define GENERIC_COMMAND_AS_CONSOLE_COMMAND(CLASS) \ + Generic_Command_As_Console_Command< CLASS > CLASS ## _AS_CONSOLE_COMMAND_instance; /** Re-enable warnings */ #if defined _MSC_VER diff --git a/Bot/Generic_Command.h b/Bot/Generic_Command.h index 824f6bf..fb802f6 100644 --- a/Bot/Generic_Command.h +++ b/Bot/Generic_Command.h @@ -105,7 +105,8 @@ JUPITER_BOT_API extern GenericCommand *getGenericCommand(const Jupiter::Readable public: \ CLASS(); \ GenericCommand::ResponseLine *trigger(const Jupiter::ReadableString ¶meters); \ - const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters); + const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters); \ + static CLASS instance; /** Expands to become the entire declaration for a generic command. In most cases, this will be sufficient. */ #define GENERIC_GENERIC_COMMAND(CLASS) \ @@ -115,7 +116,8 @@ class CLASS : public GenericCommand { \ /** Instantiates a generic command. */ #define GENERIC_COMMAND_INIT(CLASS) \ - CLASS CLASS ## _instance; + CLASS CLASS :: instance = CLASS (); \ + CLASS & CLASS ## _instance = CLASS :: instance; /** Re-enable warnings */ #if defined _MSC_VER diff --git a/Bot/IRC_Command.h b/Bot/IRC_Command.h index 7540829..e590de7 100644 --- a/Bot/IRC_Command.h +++ b/Bot/IRC_Command.h @@ -30,6 +30,7 @@ #include "Jupiter_Bot.h" #include "ServerManager.h" #include "IRC_Bot.h" +#include "Generic_Command.h" class IRCCommand; @@ -168,10 +169,10 @@ private: /** 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(); \ + void trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) override; \ + const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters) override; \ + IRCCommand *copy() override; \ + void create() override; \ 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. */ @@ -183,56 +184,99 @@ class CLASS : public IRCCommand { \ /** 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); } - -/** Generates a base IRC command implementation from a generic command. */ -#define GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_BASE(CLASS) \ - void CLASS ## _AS_IRC_COMMAND :: trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) { \ - GenericCommand::ResponseLine *del; \ - GenericCommand::ResponseLine *ret = CLASS ## _instance.trigger(parameters); \ - while (ret != nullptr) { \ - switch(ret->type) { \ - case GenericCommand::DisplayType::PublicSuccess: \ - case GenericCommand::DisplayType::PublicError: \ - source->sendMessage(channel, ret->response); \ - break; \ - case GenericCommand::DisplayType::PrivateSuccess: \ - case GenericCommand::DisplayType::PrivateError: \ - source->sendNotice(nick, ret->response); \ - break; \ - default: \ - source->sendMessage(nick, ret->response); \ - break; \ - } \ - del = ret; ret = ret->next; delete del; } } \ - const Jupiter::ReadableString & CLASS ## _AS_IRC_COMMAND :: getHelp(const Jupiter::ReadableString ¶meters) { \ - return CLASS ##_instance.getHelp(parameters); } \ - IRC_COMMAND_INIT(CLASS ## _AS_IRC_COMMAND) - -/** Generates an IRC command implementation from a generic command. */ -#define GENERIC_COMMAND_AS_IRC_COMMAND_IMPL(CLASS) \ - void CLASS ## _AS_IRC_COMMAND :: create() { \ - size_t index = 0; \ - while (index != CLASS ## _instance.getTriggerCount()) this->addTrigger(CLASS ## _instance.getTrigger(index++)); } \ - GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_BASE(CLASS) - -/** Generates an IRC command implementation from a generic command. */ -#define GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_2(CLASS, ACCESS_LEVEL) \ - void CLASS ## _AS_IRC_COMMAND :: create() { \ - size_t index = 0; \ - while (index != CLASS ## _instance.getTriggerCount()) this->addTrigger(CLASS ## _instance.getTrigger(index++)); \ - this->setAccessLevel(ACCESS_LEVEL); } \ - GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_BASE(CLASS) + IRCCommand *CLASS::copy() { return new CLASS(*this); } + +/** GenericCommand to IRCCommand conversion */ /** Generates an IRC command from a generic command. */ -#define GENERIC_COMMAND_AS_IRC_COMMAND(CLASS) \ - GENERIC_IRC_COMMAND(CLASS ## _AS_IRC_COMMAND) \ - GENERIC_COMMAND_AS_IRC_COMMAND_IMPL(CLASS); +template class Generic_Command_As_IRC_Command : public IRCCommand +{ +public: + virtual void trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) override; + virtual const Jupiter::ReadableString &getHelp(const Jupiter::ReadableString ¶meters) override; + + void copyTriggers(); + Generic_Command_As_IRC_Command(); + Generic_Command_As_IRC_Command(const Generic_Command_As_IRC_Command &cmd); +}; + +template Generic_Command_As_IRC_Command::Generic_Command_As_IRC_Command() : IRCCommand() +{ + Generic_Command_As_IRC_Command::copyTriggers(); +} + +template Generic_Command_As_IRC_Command::Generic_Command_As_IRC_Command(const Generic_Command_As_IRC_Command &cmd) : IRCCommand(cmd) +{ + Generic_Command_As_IRC_Command::copyTriggers(); +} + +template void Generic_Command_As_IRC_Command::trigger(IRC_Bot *source, const Jupiter::ReadableString &channel, const Jupiter::ReadableString &nick, const Jupiter::ReadableString ¶meters) +{ + GenericCommand::ResponseLine *del; + GenericCommand::ResponseLine *ret = T::instance.trigger(parameters); + while (ret != nullptr) + { + switch (ret->type) + { + case GenericCommand::DisplayType::PublicSuccess: + case GenericCommand::DisplayType::PublicError: + source->sendMessage(channel, ret->response); + break; + case GenericCommand::DisplayType::PrivateSuccess: + case GenericCommand::DisplayType::PrivateError: + source->sendNotice(nick, ret->response); + break; + default: + source->sendMessage(nick, ret->response); + break; + } + del = ret; + ret = ret->next; + delete del; + } +} + +template const Jupiter::ReadableString &Generic_Command_As_IRC_Command::getHelp(const Jupiter::ReadableString ¶meters) +{ + return T::instance.getHelp(parameters); +} + +template void Generic_Command_As_IRC_Command::copyTriggers() +{ + size_t index = 0; + while (index != T::instance.getTriggerCount()) + this->addTrigger(T::instance.getTrigger(index++)); +} + +/** Defines the core of an IRC command's declaration. This should be included in every Generic to IRC command conversion. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_2_BASE(CLASS, NEW_CLASS) \ + public: \ + void create(); \ + IRCCommand *copy() override; \ + NEW_CLASS() : Generic_Command_As_IRC_Command< CLASS >() { \ + this->create(); \ + if (serverManager != nullptr) serverManager->addCommand(this); } \ + NEW_CLASS(const NEW_CLASS &cmd) : Generic_Command_As_IRC_Command< CLASS >(cmd) { this->create(); } + +/** Generates an IRC command from a generic command. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_2(CLASS, NEW_CLASS) \ + class NEW_CLASS : public Generic_Command_As_IRC_Command< CLASS > { \ + GENERIC_COMMAND_AS_IRC_COMMAND_2_BASE(CLASS, NEW_CLASS) }; \ + IRC_COMMAND_INIT(NEW_CLASS) /** Generates an IRC command from a generic command. */ -#define GENERIC_COMMAND_AS_IRC_COMMAND_2(CLASS, ACCESS_LEVEL) \ - GENERIC_IRC_COMMAND(CLASS ## _AS_IRC_COMMAND) \ - GENERIC_COMMAND_AS_IRC_COMMAND_IMPL_2(CLASS, ACCESS_LEVEL); +#define GENERIC_COMMAND_AS_IRC_COMMAND(CLASS) \ + GENERIC_COMMAND_AS_IRC_COMMAND_2(CLASS, CLASS ## _AS_IRC_COMMAND); + +/** Generates an IRC command from a generic command, and defines a default create() function. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_NO_CREATE(CLASS) \ + GENERIC_COMMAND_AS_IRC_COMMAND(CLASS) \ + void CLASS ## _AS_IRC_COMMAND::create() {} + +/** Generates an IRC command from a generic command, and defines an access-setting create() function. */ +#define GENERIC_COMMAND_AS_IRC_COMMAND_ACCESS_CREATE(CLASS, ACCESS_LEVEL) \ + GENERIC_COMMAND_AS_IRC_COMMAND(CLASS) \ + void CLASS ## _AS_IRC_COMMAND::create() { this->setAccessLevel(ACCESS_LEVEL); } /** Re-enable warnings */ #if defined _MSC_VER diff --git a/CoreCommands/CoreCommands.cpp b/CoreCommands/CoreCommands.cpp index ef5400b..78b6bdd 100644 --- a/CoreCommands/CoreCommands.cpp +++ b/CoreCommands/CoreCommands.cpp @@ -140,7 +140,7 @@ const Jupiter::ReadableString &VersionGenericCommand::getHelp(const Jupiter::Rea GENERIC_COMMAND_INIT(VersionGenericCommand) GENERIC_COMMAND_AS_CONSOLE_COMMAND(VersionGenericCommand) -GENERIC_COMMAND_AS_IRC_COMMAND(VersionGenericCommand) +GENERIC_COMMAND_AS_IRC_COMMAND_NO_CREATE(VersionGenericCommand) // Sync Command @@ -173,7 +173,7 @@ const Jupiter::ReadableString &SyncGenericCommand::getHelp(const Jupiter::Readab GENERIC_COMMAND_INIT(SyncGenericCommand) GENERIC_COMMAND_AS_CONSOLE_COMMAND(SyncGenericCommand) -GENERIC_COMMAND_AS_IRC_COMMAND_2(SyncGenericCommand, 4) +GENERIC_COMMAND_AS_IRC_COMMAND_ACCESS_CREATE(SyncGenericCommand, 4) // Rehash Command @@ -203,7 +203,7 @@ const Jupiter::ReadableString &RehashGenericCommand::getHelp(const Jupiter::Read GENERIC_COMMAND_INIT(RehashGenericCommand) GENERIC_COMMAND_AS_CONSOLE_COMMAND(RehashGenericCommand) -GENERIC_COMMAND_AS_IRC_COMMAND_2(RehashGenericCommand, 4) +GENERIC_COMMAND_AS_IRC_COMMAND_ACCESS_CREATE(RehashGenericCommand, 4) // Plugin instantiation and entry point. CoreCommandsPlugin pluginInstance; diff --git a/PluginManager/PluginManager.cpp b/PluginManager/PluginManager.cpp index 6c14312..c5e8171 100644 --- a/PluginManager/PluginManager.cpp +++ b/PluginManager/PluginManager.cpp @@ -81,9 +81,8 @@ const Jupiter::ReadableString &PluginGenericCommand::getHelp(const Jupiter::Read } GENERIC_COMMAND_INIT(PluginGenericCommand) - GENERIC_COMMAND_AS_CONSOLE_COMMAND(PluginGenericCommand) -GENERIC_COMMAND_AS_IRC_COMMAND_2(PluginGenericCommand, 5) +GENERIC_COMMAND_AS_IRC_COMMAND_ACCESS_CREATE(PluginGenericCommand, 5) // Plugin instantiation and entry point. PluginManager pluginInstance; diff --git a/Release/Bot.lib b/Release/Bot.lib index 97712ca..71c83c1 100644 Binary files a/Release/Bot.lib and b/Release/Bot.lib differ diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index f9da299..1160e05 100644 Binary files a/Release/Plugins/RenX.Core.lib and b/Release/Plugins/RenX.Core.lib differ diff --git a/RenX.Warn/RenX_Warn.cpp b/RenX.Warn/RenX_Warn.cpp index c4337d7..95944cd 100644 --- a/RenX.Warn/RenX_Warn.cpp +++ b/RenX.Warn/RenX_Warn.cpp @@ -209,7 +209,7 @@ const Jupiter::ReadableString &WarnGameCommand::getHelp(const Jupiter::ReadableS return defaultHelp; } -IRC_COMMAND_INIT(WarnGameCommand) +GAME_COMMAND_INIT(WarnGameCommand) // Pardon Game Command @@ -243,7 +243,7 @@ const Jupiter::ReadableString &PardonGameCommand::getHelp(const Jupiter::Readabl return defaultHelp; } -IRC_COMMAND_INIT(PardonGameCommand) +GAME_COMMAND_INIT(PardonGameCommand) extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() {