/* $Id$ * EOSERV is released under the zlib license. * See LICENSE.txt for more info. */ #ifndef PLAYERCOMMANDS_HPP_INCLUDED #define PLAYERCOMMANDS_HPP_INCLUDED #include <map> #include <set> #include <string> #include <unordered_map> #include <vector> #include "../character.hpp" #include "../command_source.hpp" #define PLAYER_COMMAND_HANDLER_PASTE_AUX2(base, id) base##id #define PLAYER_COMMAND_HANDLER_PASTE_AUX(base, id) PLAYER_COMMAND_HANDLER_PASTE_AUX2(base, id) #define PLAYER_COMMAND_HANDLER_REGISTER() \ namespace { struct PLAYER_COMMAND_HANDLER_PASTE_AUX(player_command_handler_register_helper_, __LINE__) : public player_command_handler_register_helper \ { \ PLAYER_COMMAND_HANDLER_PASTE_AUX(player_command_handler_register_helper_, __LINE__)() \ { \ player_command_handler_register_init _init; \ #define PLAYER_COMMAND_HANDLER_REGISTER_END() ; \ } \ } PLAYER_COMMAND_HANDLER_PASTE_AUX(player_command_handler_register_helper_instance_, __LINE__); } namespace PlayerCommands { struct player_command_info { std::string name; std::vector<std::string> arguments; std::vector<std::string> optional_arguments; std::size_t partial_min_chars; bool require_character; player_command_info(std::string name, std::vector<std::string> arguments = std::vector<std::string>(), std::vector<std::string> optional_arguments = std::vector<std::string>(), std::size_t partial_min_chars = 0) : name(name) , arguments(arguments) , optional_arguments(optional_arguments) , partial_min_chars(partial_min_chars) , require_character(false) { } }; struct player_command_handler { player_command_info info; std::function<void(const std::vector<std::string>&, Command_Source*)> f; player_command_handler(player_command_info info, std::function<void(const std::vector<std::string>&, Command_Source*)> f) : info(info) , f(f) { } player_command_handler(player_command_info info, std::function<void(const std::vector<std::string>&, Character*)> f) : info(info) , f([f](const std::vector<std::string>& arguments, Command_Source* from) { f(arguments, static_cast<Character*>(from)); }) { this->info.require_character = true; } bool operator <(const player_command_handler& rhs) const { // This ordering is very important for making sure the most specific command gets picked return (info.partial_min_chars < rhs.info.partial_min_chars) || (info.name.length() < rhs.info.name.length()) || (info.name < rhs.info.name); } }; class player_command_handler_register { private: std::map<std::string, player_command_handler> handlers; std::unordered_map<std::string, std::string> aliases; public: void Register(player_command_handler handler); void RegisterAlias(const std::string& alias, const std::string& command); bool Handle(std::string command, const std::vector<std::string>& arguments, Command_Source* from, int alias_depth = 0) const; }; extern player_command_handler_register *player_command_handler_register_instance; class player_command_handler_register_init { private: bool master; public: player_command_handler_register_init(bool master = false) : master(master) { static bool initialized; if (!initialized) { initialized = true; init(); } } void init() const; ~player_command_handler_register_init(); }; class player_command_handler_register_helper { public: template <class F> void Register(player_command_info info, const F& f) { player_command_handler_register_instance->Register(player_command_handler(info, std::function<void(const std::vector<std::string>&, Command_Source*)>(f))); } template <class F> void RegisterCharacter(player_command_info info, const F& f) { player_command_handler_register_instance->Register(player_command_handler(info, std::function<void(const std::vector<std::string>&, Character*)>(f))); } void RegisterAlias(const std::string& alias, const std::string& command) { player_command_handler_register_instance->RegisterAlias(alias, command); } }; inline bool Handle(std::string command, const std::vector<std::string>& arguments, Command_Source* from) { return player_command_handler_register_instance->Handle(command, arguments, from); } } #endif // PLAYERCOMMANDS_HPP_INCLUDED