mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-02-10 03:59:05 +01:00
Core/Commands: Refactored chat command script hook, fixes a crash when building with gcc 5
Closes #15616 Closes #15740
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user