Updated the command systems to automatically add new commands and remove orphaned entries from the command settings tables

This commit is contained in:
Uleat 2019-08-30 06:38:48 -04:00
parent f837d423ef
commit d341a1b38f
9 changed files with 240 additions and 15 deletions

View File

@ -1,5 +1,10 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50)
-------------------------------------------------------
== 8/30/2019 ==
Uleat: Added code to inject new commands and remove orphaned commands from both command systems
- New commands are added with their status (`access`) set to the server default value - no aliases are defined
- Defunct commands will have their orhpaned entries removed from the command settings table for each system
== 8/16/2019 ==
Akkadius: Simplified the use of roamboxes and improved the AI for roambox pathing https://i.imgur.com/z33u7y9.gif
Akkadius: Implemented command #roambox set <box_size> [move_delay]

View File

@ -18,6 +18,7 @@
#include <iostream>
#include <cstring>
#include <fmt/format.h>
#if defined(_MSC_VER) && _MSC_VER >= 1800
#include <algorithm>
@ -1469,6 +1470,37 @@ bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, s
return true;
}
bool SharedDatabase::UpdateCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected, const std::vector<std::string> &orphaned)
{
bool return_value = true;
if (injected.size()) {
std::string query = fmt::format(
"REPLACE INTO `command_settings`(`command`, `access`) VALUES {}",
implode(",", string_string("(", ")"), join_pair(string_string(), ",", string_string("'", "'"), injected))
);
if (!QueryDatabase(query).Success()) {
return_value = false;
}
}
if (orphaned.size()) {
std::string query = fmt::format(
"DELETE FROM `command_settings` WHERE `command` IN ({})",
implode(",", string_string("'", "'"), orphaned)
);
if (!QueryDatabase(query).Success()) {
return_value = false;
}
}
return return_value;
}
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
skill_caps_mmf.reset(nullptr);

View File

@ -71,6 +71,7 @@ class SharedDatabase : public Database
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
void SaveCharacterInspectMessage(uint32 character_id, const InspectMessage_Struct* message);
bool GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
bool UpdateCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected, const std::vector<std::string> &orphaned);
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
void SetMailKey(int CharID, int IPAddress, int MailKey);
std::string GetMailKey(int CharID, bool key_only = false);

View File

@ -16,6 +16,7 @@
#include "string_util.h"
#include <algorithm>
#include <fmt/format.h>
#ifdef _WINDOWS
#include <windows.h>
@ -144,6 +145,53 @@ std::string implode(std::string glue, std::vector<std::string> src)
return final_output;
}
std::string implode(std::string glue, string_string encapsulation, std::vector<std::string> src)
{
if (src.empty()) {
return {};
}
std::ostringstream output;
std::vector<std::string>::iterator src_iter;
for (src_iter = src.begin(); src_iter != src.end(); src_iter++) {
output << encapsulation.first << *src_iter << encapsulation.second << glue;
}
std::string final_output = output.str();
final_output.resize(output.str().size() - glue.size());
return final_output;
}
std::vector<std::string> join_pair(string_string outer_encap, std::string joiner, string_string inner_encap, std::vector<std::pair<std::string, uint8>> src)
{
if (src.empty()) {
return {};
}
std::vector<std::string> output;
for (auto src_iter : src) {
output.push_back(
fmt::format(
"{}{}{}{}{}{}{}{}{}",
outer_encap.first,
inner_encap.first,
src_iter.first,
inner_encap.second,
joiner,
inner_encap.first,
src_iter.second,
inner_encap.second,
outer_encap.second
)
);
}
return output;
}
std::string EscapeString(const std::string &s) {
std::string ret;
@ -514,4 +562,4 @@ bool isAlphaNumeric(const char *text)
}
return true;
}
}

View File

@ -31,6 +31,10 @@ std::vector<std::string> split(std::string str_to_split, char delimiter);
const std::string StringFormat(const char* format, ...);
const std::string vStringFormat(const char* format, va_list args);
std::string implode(std::string glue, std::vector<std::string> src);
typedef std::pair<std::string, std::string> string_string;
std::string implode(std::string glue, string_string encapsulation, std::vector<std::string> src);
// wanted to make 'join_pair' a template function..this will do for now
std::vector<std::string> join_pair(string_string outer_encap, std::string joiner, string_string inner_encap, std::vector<std::pair<std::string, uint8>> src);
std::vector<std::string> SplitString(const std::string &s, char delim);
std::string EscapeString(const char *src, size_t sz);
std::string EscapeString(const std::string &s);

View File

@ -1426,23 +1426,51 @@ int bot_command_init(void)
std::map<std::string, std::pair<uint8, std::vector<std::string>>> bot_command_settings;
database.botdb.LoadBotCommandSettings(bot_command_settings);
std::vector<std::pair<std::string, uint8>> injected_bot_command_settings;
std::vector<std::string> orphaned_bot_command_settings;
auto working_bcl = bot_command_list;
for (auto working_bcl_iter : working_bcl) {
auto bot_command_settings_iter = bot_command_settings.find(working_bcl_iter.first);
if (bot_command_settings_iter == bot_command_settings.end()) {
if (working_bcl_iter.second->access == 0)
Log(Logs::General, Logs::Commands, "bot_command_init(): Warning: Bot Command '%s' defaulting to access level 0!", working_bcl_iter.first.c_str());
injected_bot_command_settings.push_back(std::pair<std::string, uint8>(working_bcl_iter.first, working_bcl_iter.second->access));
Log(Logs::General,
Logs::Status,
"New Bot Command '%s' found... Adding to `bot_command_settings` table with access '%u'...",
working_bcl_iter.first.c_str(),
working_bcl_iter.second->access
);
if (working_bcl_iter.second->access == 0) {
Log(Logs::General,
Logs::Commands,
"bot_command_init(): Warning: Bot Command '%s' defaulting to access level 0!",
working_bcl_iter.first.c_str()
);
}
continue;
}
working_bcl_iter.second->access = bot_command_settings_iter->second.first;
Log(Logs::General, Logs::Commands, "bot_command_init(): - Bot Command '%s' set to access level %d.", working_bcl_iter.first.c_str(), bot_command_settings_iter->second.first);
if (bot_command_settings_iter->second.second.empty())
Log(Logs::General,
Logs::Commands,
"bot_command_init(): - Bot Command '%s' set to access level %d.",
working_bcl_iter.first.c_str(),
bot_command_settings_iter->second.first
);
if (bot_command_settings_iter->second.second.empty()) {
continue;
}
for (auto alias_iter : bot_command_settings_iter->second.second) {
if (alias_iter.empty())
if (alias_iter.empty()) {
continue;
}
if (bot_command_list.find(alias_iter) != bot_command_list.end()) {
Log(Logs::General, Logs::Commands, "bot_command_init(): Warning: Alias '%s' already exists as a bot command - skipping!", alias_iter.c_str());
continue;
@ -1455,6 +1483,24 @@ int bot_command_init(void)
}
}
for (auto bcs_iter : bot_command_settings) {
auto bcl_iter = bot_command_list.find(bcs_iter.first);
if (bcl_iter == bot_command_list.end()) {
orphaned_bot_command_settings.push_back(bcs_iter.first);
Log(Logs::General,
Logs::Status,
"Bot Command '%s' no longer exists... Deleting orphaned entry from `bot_command_settings` table...",
bcs_iter.first.c_str()
);
}
}
if (injected_bot_command_settings.size() || orphaned_bot_command_settings.size()) {
database.botdb.UpdateBotCommandSettings(injected_bot_command_settings, orphaned_bot_command_settings);
}
bot_command_dispatch = bot_command_real_dispatch;
BCSpells::Load();

View File

@ -18,6 +18,8 @@
#ifdef BOTS
#include <fmt/format.h>
#include "../common/global_define.h"
#include "../common/rulesys.h"
#include "../common/string_util.h"
@ -52,6 +54,37 @@ bool BotDatabase::LoadBotCommandSettings(std::map<std::string, std::pair<uint8,
return true;
}
bool BotDatabase::UpdateBotCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected, const std::vector<std::string> &orphaned)
{
bool return_value = true;
if (injected.size()) {
query = fmt::format(
"REPLACE INTO `bot_command_settings`(`bot_command`, `access`) VALUES {}",
implode(",", string_string("(", ")"), join_pair(string_string(), ",", string_string("'", "'"), injected))
);
if (!database.QueryDatabase(query).Success()) {
return_value = false;
}
}
if (orphaned.size()) {
query = fmt::format(
"DELETE FROM `bot_command_settings` WHERE `bot_command` IN ({})",
implode(",", string_string("'", "'"), orphaned)
);
if (!database.QueryDatabase(query).Success()) {
return_value = false;
}
}
return return_value;
}
bool BotDatabase::LoadBotSpellCastingChances()
{
query =

View File

@ -43,6 +43,7 @@ class BotDatabase
{
public:
bool LoadBotCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &bot_command_settings);
bool UpdateBotCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected, const std::vector<std::string> &orphaned);
bool LoadBotSpellCastingChances();

View File

@ -453,36 +453,91 @@ int command_init(void)
std::map<std::string, std::pair<uint8, std::vector<std::string>>> command_settings;
database.GetCommandSettings(command_settings);
std::vector<std::pair<std::string, uint8>> injected_command_settings;
std::vector<std::string> orphaned_command_settings;
std::map<std::string, CommandRecord *> working_cl = commandlist;
for (auto iter_cl = working_cl.begin(); iter_cl != working_cl.end(); ++iter_cl) {
auto iter_cs = command_settings.find(iter_cl->first);
if (iter_cs == command_settings.end()) {
if (iter_cl->second->access == 0)
Log(Logs::General, Logs::Commands, "command_init(): Warning: Command '%s' defaulting to access level 0!", iter_cl->first.c_str());
injected_command_settings.push_back(std::pair<std::string, uint8>(iter_cl->first, iter_cl->second->access));
Log(Logs::General,
Logs::Status,
"New Command '%s' found... Adding to `command_settings` table with access '%u'...",
iter_cl->first.c_str(),
iter_cl->second->access
);
if (iter_cl->second->access == 0) {
Log(Logs::General,
Logs::Commands,
"command_init(): Warning: Command '%s' defaulting to access level 0!",
iter_cl->first.c_str()
);
}
continue;
}
iter_cl->second->access = iter_cs->second.first;
Log(Logs::General, Logs::Commands, "command_init(): - Command '%s' set to access level %d.", iter_cl->first.c_str(), iter_cs->second.first);
if (iter_cs->second.second.empty())
Log(Logs::General,
Logs::Commands,
"command_init(): - Command '%s' set to access level %d.",
iter_cl->first.c_str(),
iter_cs->second.first
);
if (iter_cs->second.second.empty()) {
continue;
}
for (auto iter_aka = iter_cs->second.second.begin(); iter_aka != iter_cs->second.second.end();
++iter_aka) {
if (iter_aka->empty())
for (auto iter_aka = iter_cs->second.second.begin(); iter_aka != iter_cs->second.second.end(); ++iter_aka) {
if (iter_aka->empty()) {
continue;
}
if (commandlist.find(*iter_aka) != commandlist.end()) {
Log(Logs::General, Logs::Commands, "command_init(): Warning: Alias '%s' already exists as a command - skipping!", iter_aka->c_str());
Log(Logs::General,
Logs::Commands,
"command_init(): Warning: Alias '%s' already exists as a command - skipping!",
iter_aka->c_str()
);
continue;
}
commandlist[*iter_aka] = iter_cl->second;
commandaliases[*iter_aka] = iter_cl->first;
Log(Logs::General, Logs::Commands, "command_init(): - Alias '%s' added to command '%s'.", iter_aka->c_str(), commandaliases[*iter_aka].c_str());
Log(Logs::General,
Logs::Commands,
"command_init(): - Alias '%s' added to command '%s'.",
iter_aka->c_str(),
commandaliases[*iter_aka].c_str()
);
}
}
for (auto cs_iter : command_settings) {
auto cl_iter = commandlist.find(cs_iter.first);
if (cl_iter == commandlist.end()) {
orphaned_command_settings.push_back(cs_iter.first);
Log(Logs::General,
Logs::Status,
"Command '%s' no longer exists... Deleting orphaned entry from `command_settings` table...",
cs_iter.first.c_str()
);
}
}
if (injected_command_settings.size() || orphaned_command_settings.size()) {
database.UpdateCommandSettings(injected_command_settings, orphaned_command_settings);
}
command_dispatch = command_realdispatch;
return commandcount;