diff options
| author | Shauren <shauren.trinity@gmail.com> | 2015-10-22 20:26:56 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2015-10-22 20:26:56 +0200 |
| commit | 2d942ddcc528cc9fe718ebbd5903318fcbdab817 (patch) | |
| tree | 51eefc279aa09d6a8e6aa28abd0f1b0324e96cca /src/server/game/Chat | |
| parent | 935c93e099f534f701ff8787204ce19be2ed2df2 (diff) | |
Core/Commands: Refactored chat command script hook, fixes a crash when building with gcc 5
Closes #15616
Closes #15740
Diffstat (limited to 'src/server/game/Chat')
| -rw-r--r-- | src/server/game/Chat/Chat.cpp | 82 | ||||
| -rw-r--r-- | src/server/game/Chat/Chat.h | 27 |
2 files changed, 38 insertions, 71 deletions
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index ff8192e459a..d04f8ba4518 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -35,54 +35,16 @@ bool ChatHandler::load_command_table = true; -// get number of commands in table -static size_t getCommandTableSize(const ChatCommand* commands) +std::vector<ChatCommand> const& ChatHandler::getCommandTable() { - if (!commands) - return 0; - size_t count = 0; - while (commands[count].Name != NULL) - count++; - return count; -} - -// append source command table to target, return number of appended commands -static size_t appendCommandTable(ChatCommand* target, const ChatCommand* source) -{ - const size_t count = getCommandTableSize(source); - if (count) - memcpy(target, source, count * sizeof(ChatCommand)); - return count; -} - -ChatCommand* ChatHandler::getCommandTable() -{ - // cache for commands, needed because some commands are loaded dynamically through ScriptMgr - // cache is never freed and will show as a memory leak in diagnostic tools - // can't use vector as vector storage is implementation-dependent, eg, there can be alignment gaps between elements - static ChatCommand* commandTableCache = NULL; + static std::vector<ChatCommand> commandTableCache; if (LoadCommandTable()) { SetLoadCommandTable(false); - { - // count total number of top-level commands - size_t total = 0; - std::vector<ChatCommand*> const& dynamic = sScriptMgr->GetChatCommands(); - for (std::vector<ChatCommand*>::const_iterator it = dynamic.begin(); it != dynamic.end(); ++it) - total += getCommandTableSize(*it); - total += 1; // ending zero - - // cache top-level commands - size_t added = 0; - free(commandTableCache); - commandTableCache = (ChatCommand*)malloc(sizeof(ChatCommand) * total); - ASSERT(commandTableCache); - memset(commandTableCache, 0, sizeof(ChatCommand) * total); - for (std::vector<ChatCommand*>::const_iterator it = dynamic.begin(); it != dynamic.end(); ++it) - added += appendCommandTable(commandTableCache + added, *it); - } + std::vector<ChatCommand> cmds = sScriptMgr->GetChatCommands(); + commandTableCache.swap(cmds); PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_COMMANDS); PreparedQueryResult result = WorldDatabase.Query(stmt); @@ -265,7 +227,7 @@ void ChatHandler::SendSysMessage(uint32 entry) SendSysMessage(GetTrinityString(entry)); } -bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd) +bool ChatHandler::ExecuteCommandInTable(std::vector<ChatCommand> const& table, const char* text, std::string const& fullcmd) { char const* oldtext = text; std::string cmd = ""; @@ -278,7 +240,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st while (*text == ' ') ++text; - for (uint32 i = 0; table[i].Name != NULL; ++i) + for (uint32 i = 0; i < table.size(); ++i) { if (!hasStringAbbr(table[i].Name, cmd.c_str())) continue; @@ -286,7 +248,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st bool match = false; if (strlen(table[i].Name) > cmd.length()) { - for (uint32 j = 0; table[j].Name != NULL; ++j) + for (uint32 j = 0; j < table.size(); ++j) { if (!hasStringAbbr(table[j].Name, cmd.c_str())) continue; @@ -302,7 +264,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st continue; // select subcommand from child commands list - if (table[i].ChildCommands != NULL) + if (!table[i].ChildCommands.empty()) { if (!ExecuteCommandInTable(table[i].ChildCommands, text, fullcmd)) { @@ -367,7 +329,7 @@ bool ChatHandler::ExecuteCommandInTable(ChatCommand* table, const char* text, st return false; } -bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, uint32 permission, std::string const& help, std::string const& fullcommand) +bool ChatHandler::SetDataForCommandInTable(std::vector<ChatCommand>& table, char const* text, uint32 permission, std::string const& help, std::string const& fullcommand) { std::string cmd = ""; @@ -379,14 +341,14 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, while (*text == ' ') ++text; - for (uint32 i = 0; table[i].Name != NULL; i++) + for (uint32 i = 0; i < table.size(); i++) { // for data fill use full explicit command names if (table[i].Name != cmd) continue; // select subcommand from child commands list (including "") - if (table[i].ChildCommands != NULL) + if (!table[i].ChildCommands.empty()) { if (SetDataForCommandInTable(table[i].ChildCommands, text, permission, help, fullcommand)) return true; @@ -413,7 +375,7 @@ bool ChatHandler::SetDataForCommandInTable(ChatCommand* table, char const* text, // in case "" command let process by caller if (!cmd.empty()) { - if (table == getCommandTable()) + if (&table == &getCommandTable()) TC_LOG_ERROR("sql.sql", "Table `command` have not existed command '%s', skip.", cmd.c_str()); else TC_LOG_ERROR("sql.sql", "Table `command` have not existed subcommand '%s' in command '%s', skip.", cmd.c_str(), fullcommand.c_str()); @@ -519,10 +481,10 @@ Valid examples: return LinkExtractor(message).IsValidMessage(); } -bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, char const* subcmd) +bool ChatHandler::ShowHelpForSubCommands(std::vector<ChatCommand> const& table, char const* cmd, char const* subcmd) { std::string list; - for (uint32 i = 0; table[i].Name != NULL; ++i) + for (uint32 i = 0; i < table.size(); ++i) { // must be available (ignore handler existence for show command with possible available subcommands) if (!isAvailable(table[i])) @@ -539,14 +501,14 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, ch list += table[i].Name; - if (table[i].ChildCommands) + if (!table[i].ChildCommands.empty()) list += " ..."; } if (list.empty()) return false; - if (table == getCommandTable()) + if (&table == &getCommandTable()) { SendSysMessage(LANG_AVIABLE_CMD); PSendSysMessage("%s", list.c_str()); @@ -557,11 +519,11 @@ bool ChatHandler::ShowHelpForSubCommands(ChatCommand* table, char const* cmd, ch return true; } -bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd) +bool ChatHandler::ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd) { if (*cmd) { - for (uint32 i = 0; table[i].Name != NULL; ++i) + for (uint32 i = 0; i < table.size(); ++i) { // must be available (ignore handler existence for show command with possible available subcommands) if (!isAvailable(table[i])) @@ -573,7 +535,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd) // have subcommand char const* subcmd = (*cmd) ? strtok(NULL, " ") : ""; - if (table[i].ChildCommands && subcmd && *subcmd) + if (!table[i].ChildCommands.empty() && subcmd && *subcmd) { if (ShowHelpForCommand(table[i].ChildCommands, subcmd)) return true; @@ -582,7 +544,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd) if (!table[i].Help.empty()) SendSysMessage(table[i].Help.c_str()); - if (table[i].ChildCommands) + if (!table[i].ChildCommands.empty()) if (ShowHelpForSubCommands(table[i].ChildCommands, table[i].Name, subcmd ? subcmd : "")) return true; @@ -591,7 +553,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd) } else { - for (uint32 i = 0; table[i].Name != NULL; ++i) + for (uint32 i = 0; i < table.size(); ++i) { // must be available (ignore handler existence for show command with possible available subcommands) if (!isAvailable(table[i])) @@ -603,7 +565,7 @@ bool ChatHandler::ShowHelpForCommand(ChatCommand* table, const char* cmd) if (!table[i].Help.empty()) SendSysMessage(table[i].Help.c_str()); - if (table[i].ChildCommands) + if (!table[i].ChildCommands.empty()) if (ShowHelpForSubCommands(table[i].ChildCommands, "", "")) return true; diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index 34faac68980..cc208277ba3 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -39,13 +39,18 @@ struct GameTele; class ChatCommand { + typedef bool(*pHandler)(ChatHandler*, char const*); + public: - const char * Name; - uint32 Permission; // function pointer required correct align (use uint32) - bool AllowConsole; - bool (*Handler)(ChatHandler*, const char* args); - std::string Help; - ChatCommand* ChildCommands; + ChatCommand(char const* name, uint32 permission, bool allowConsole, pHandler handler, std::string help, std::vector<ChatCommand> childCommands = std::vector<ChatCommand>()) + : Name(name), Permission(permission), AllowConsole(allowConsole), Handler(handler), Help(std::move(help)), ChildCommands(std::move(childCommands)) { } + + char const* Name; + uint32 Permission; // function pointer required correct align (use uint32) + bool AllowConsole; + pHandler Handler; + std::string Help; + std::vector<ChatCommand> ChildCommands; }; class ChatHandler @@ -83,7 +88,7 @@ class ChatHandler bool ParseCommands(const char* text); - static ChatCommand* getCommandTable(); + static std::vector<ChatCommand> const& getCommandTable(); bool isValidChatMessage(const char* msg); void SendGlobalSysMessage(const char *str); @@ -134,12 +139,12 @@ class ChatHandler static bool LoadCommandTable() { return load_command_table; } static void SetLoadCommandTable(bool val) { load_command_table = val; } - bool ShowHelpForCommand(ChatCommand* table, const char* cmd); + bool ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd); protected: explicit ChatHandler() : m_session(NULL), sentErrorMessage(false) { } // for CLI subclass - static bool SetDataForCommandInTable(ChatCommand* table, const char* text, uint32 permission, std::string const& help, std::string const& fullcommand); - bool ExecuteCommandInTable(ChatCommand* table, const char* text, std::string const& fullcmd); - bool ShowHelpForSubCommands(ChatCommand* table, char const* cmd, char const* subcmd); + static bool SetDataForCommandInTable(std::vector<ChatCommand>& table, const char* text, uint32 permission, std::string const& help, std::string const& fullcommand); + bool ExecuteCommandInTable(std::vector<ChatCommand> const& table, const char* text, std::string const& fullcmd); + bool ShowHelpForSubCommands(std::vector<ChatCommand> const& table, char const* cmd, char const* subcmd); private: WorldSession* m_session; // != NULL for chat command call and NULL for CLI command |
