mirror of
https://github.com/EQEmu/Server.git
synced 2026-04-12 14:02:26 +00:00
commit
7911225960
@ -1,5 +1,27 @@
|
|||||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
== 9/04/2019 ==
|
||||||
|
Uleat: Added code to restore rule notes to their original values
|
||||||
|
- The code is inactive by default
|
||||||
|
- Change rule 'World:RestoreRuleNotes' to 'true' to enable this feature
|
||||||
|
- Rule will not exist until the server is run for the first time after updating
|
||||||
|
|
||||||
|
== 9/02/2019 ==
|
||||||
|
Uleat: Added code to inject new rules into the 'default' ruleset and remove orphaned rules from all rulesets
|
||||||
|
- New rules are only added using the 'default' ruleset - Other rulesets will need to be added manually or through in-game updates
|
||||||
|
-- Rule notes are now loaded into the system's hard-coded entries and will now propagate properly into database updates
|
||||||
|
- Defunct rules will have their orhpaned entries removed from the `rule_values` table for the all rulesets
|
||||||
|
|
||||||
|
Note: If you would like to add these rules before starting your server so that you can modify them, start world.exe
|
||||||
|
manually and wait for the console messages to finish. It should take 5-10 seconds, or so. The world log should contain
|
||||||
|
a list of the added and removed entries, IF the `file` field of the 'Status' logging category is set to 1 or higher.
|
||||||
|
(Don't forget to manually stop the process after the update is complete.)
|
||||||
|
|
||||||
|
== 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 ==
|
== 8/16/2019 ==
|
||||||
Akkadius: Simplified the use of roamboxes and improved the AI for roambox pathing https://i.imgur.com/z33u7y9.gif
|
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]
|
Akkadius: Implemented command #roambox set <box_size> [move_delay]
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Commands:
|
Commands:
|
||||||
@ -45,14 +46,14 @@ const char *RuleManager::s_categoryNames[_CatCount+1] = {
|
|||||||
|
|
||||||
const RuleManager::RuleInfo RuleManager::s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount+1] = {
|
const RuleManager::RuleInfo RuleManager::s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount+1] = {
|
||||||
/* this is done in three steps so we can reliably get to them by index*/
|
/* this is done in three steps so we can reliably get to them by index*/
|
||||||
#define RULE_INT(cat, rule, default_value) \
|
#define RULE_INT(cat, rule, default_value, notes) \
|
||||||
{ #cat ":" #rule, Category__##cat, IntRule, Int__##rule },
|
{ #cat ":" #rule, Category__##cat, IntRule, Int__##rule, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
#define RULE_REAL(cat, rule, default_value) \
|
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||||
{ #cat ":" #rule, Category__##cat, RealRule, Real__##rule },
|
{ #cat ":" #rule, Category__##cat, RealRule, Real__##rule, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
#define RULE_BOOL(cat, rule, default_value) \
|
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||||
{ #cat ":" #rule, Category__##cat, BoolRule, Bool__##rule },
|
{ #cat ":" #rule, Category__##cat, BoolRule, Bool__##rule, notes },
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
{ "Invalid Rule", _CatCount, IntRule }
|
{ "Invalid Rule", _CatCount, IntRule }
|
||||||
};
|
};
|
||||||
@ -178,11 +179,11 @@ void RuleManager::ResetRules(bool reload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values");
|
Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values");
|
||||||
#define RULE_INT(cat, rule, default_value) \
|
#define RULE_INT(cat, rule, default_value, notes) \
|
||||||
m_RuleIntValues[ Int__##rule ] = default_value;
|
m_RuleIntValues[ Int__##rule ] = default_value;
|
||||||
#define RULE_REAL(cat, rule, default_value) \
|
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||||
m_RuleRealValues[ Real__##rule ] = default_value;
|
m_RuleRealValues[ Real__##rule ] = default_value;
|
||||||
#define RULE_BOOL(cat, rule, default_value) \
|
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||||
m_RuleBoolValues[ Bool__##rule ] = default_value;
|
m_RuleBoolValues[ Bool__##rule ] = default_value;
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
|
|
||||||
@ -217,12 +218,94 @@ const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
|||||||
case IntRule:
|
case IntRule:
|
||||||
return(s_RuleInfo[index].name);
|
return(s_RuleInfo[index].name);
|
||||||
case RealRule:
|
case RealRule:
|
||||||
return(s_RuleInfo[index + _IntRuleCount].name);
|
return(s_RuleInfo[index+_IntRuleCount].name);
|
||||||
case BoolRule:
|
case BoolRule:
|
||||||
return(s_RuleInfo[index + _IntRuleCount + _RealRuleCount].name);
|
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
//should never happen
|
//should never happen
|
||||||
return("InvalidRule??");
|
return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].name); // no need to create a string when one already exists...
|
||||||
|
}
|
||||||
|
|
||||||
|
//assumes index is valid!
|
||||||
|
const std::string &RuleManager::_GetRuleNotes(RuleType type, uint16 index) {
|
||||||
|
switch (type) {
|
||||||
|
case IntRule:
|
||||||
|
return(s_RuleInfo[index].notes);
|
||||||
|
case RealRule:
|
||||||
|
return(s_RuleInfo[index+_IntRuleCount].notes);
|
||||||
|
case BoolRule:
|
||||||
|
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].notes);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//should never happen
|
||||||
|
return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].notes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
||||||
|
|
||||||
|
int ruleset_id = this->GetRulesetID(database, ruleset_name);
|
||||||
|
if (ruleset_id < 0) {
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_activeRuleset = ruleset_id;
|
||||||
|
m_activeName = ruleset_name;
|
||||||
|
|
||||||
|
/* Load default ruleset values first if we're loading something other than default */
|
||||||
|
if (strcasecmp(ruleset_name, "default") != 0) {
|
||||||
|
|
||||||
|
std::string default_ruleset_name = "default";
|
||||||
|
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
|
||||||
|
|
||||||
|
if (default_ruleset_id < 0) {
|
||||||
|
Log(Logs::Detail,
|
||||||
|
Logs::Rules,
|
||||||
|
"Failed to find default ruleset '%s' for load operation. Canceling.",
|
||||||
|
default_ruleset_name.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Processing rule set '%s' (%d) load...", default_ruleset_name.c_str(), default_ruleset_id);
|
||||||
|
|
||||||
|
std::string query = StringFormat(
|
||||||
|
"SELECT `rule_name`, `rule_value` FROM `rule_values` WHERE `ruleset_id` = '%d'",
|
||||||
|
default_ruleset_id
|
||||||
|
);
|
||||||
|
|
||||||
|
auto results = database->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
if (!SetRule(row[0], row[1], nullptr, false, reload)) {
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for '%s'", row[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Processing rule set '%s' (%d) load...", ruleset_name, ruleset_id);
|
||||||
|
|
||||||
|
std::string query = StringFormat("SELECT `rule_name`, `rule_value` FROM `rule_values` WHERE `ruleset_id` = '%d'", ruleset_id);
|
||||||
|
|
||||||
|
auto results = database->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
if (!SetRule(row[0], row[1], nullptr, false, reload)) {
|
||||||
|
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for '%s'", row[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
||||||
@ -257,56 +340,6 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
|
||||||
|
|
||||||
int ruleset_id = this->GetRulesetID(database, ruleset_name);
|
|
||||||
if (ruleset_id < 0) {
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Failed to find ruleset '%s' for load operation. Canceling.", ruleset_name);
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", ruleset_name, ruleset_id);
|
|
||||||
|
|
||||||
m_activeRuleset = ruleset_id;
|
|
||||||
m_activeName = ruleset_name;
|
|
||||||
|
|
||||||
/* Load default ruleset values first if we're loading something other than default */
|
|
||||||
if (strcasecmp(ruleset_name, "default") != 0) {
|
|
||||||
std::string default_ruleset_name = "default";
|
|
||||||
int default_ruleset_id = GetRulesetID(database, default_ruleset_name.c_str());
|
|
||||||
if (default_ruleset_id < 0) {
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Failed to find default ruleset '%s' for load operation. Canceling.",
|
|
||||||
default_ruleset_name.c_str());
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Loading rule set '%s' (%d)", default_ruleset_name.c_str(), default_ruleset_id);
|
|
||||||
|
|
||||||
std::string query = StringFormat(
|
|
||||||
"SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id = %d",
|
|
||||||
default_ruleset_id
|
|
||||||
);
|
|
||||||
|
|
||||||
auto results = database->QueryDatabase(query);
|
|
||||||
if (!results.Success())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row)
|
|
||||||
if (!SetRule(row[0], row[1], nullptr, false, reload))
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string query = StringFormat("SELECT rule_name, rule_value FROM rule_values WHERE ruleset_id=%d", ruleset_id);
|
|
||||||
auto results = database->QueryDatabase(query);
|
|
||||||
if (!results.Success())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (auto row = results.begin(); row != results.end(); ++row)
|
|
||||||
if (!SetRule(row[0], row[1], nullptr, false, reload))
|
|
||||||
Log(Logs::Detail, Logs::Rules, "Unable to interpret rule record for %s", row[0]);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
||||||
char value_string[100];
|
char value_string[100];
|
||||||
|
|
||||||
@ -328,17 +361,248 @@ void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string query = StringFormat(
|
std::string query = StringFormat(
|
||||||
"REPLACE INTO rule_values "
|
"REPLACE INTO `rule_values`"
|
||||||
"(ruleset_id, rule_name, rule_value) "
|
"(`ruleset_id`, `rule_name`, `rule_value`, `notes`)"
|
||||||
" VALUES(%d, '%s', '%s')",
|
" VALUES('%d', '%s', '%s', '%s')",
|
||||||
m_activeRuleset,
|
m_activeRuleset,
|
||||||
_GetRuleName(type, index),
|
_GetRuleName(type, index),
|
||||||
value_string
|
value_string,
|
||||||
|
EscapeString(_GetRuleNotes(type, index)).c_str()
|
||||||
);
|
);
|
||||||
|
|
||||||
database->QueryDatabase(query);
|
database->QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RuleManager::UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update)
|
||||||
|
{
|
||||||
|
std::vector<std::string> database_data;
|
||||||
|
std::map<std::string, std::pair<std::string, const std::string *>> rule_data;
|
||||||
|
std::vector<std::tuple<int, std::string, std::string, std::string>> injected_rule_entries;
|
||||||
|
|
||||||
|
if (ruleset_name == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ruleset_id = GetRulesetID(db, ruleset_name);
|
||||||
|
if (ruleset_id < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// load database rule names
|
||||||
|
std::string query(StringFormat("SELECT `rule_name` FROM `rule_values` WHERE `ruleset_id` = '%i'", ruleset_id));
|
||||||
|
|
||||||
|
auto results = db->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build database data entries
|
||||||
|
for (auto row : results) {
|
||||||
|
database_data.push_back(std::string(row[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// build rule data entries
|
||||||
|
for (const auto &ri_iter : s_RuleInfo) {
|
||||||
|
if (strcasecmp(ri_iter.name, "Invalid Rule") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buffer[100];
|
||||||
|
|
||||||
|
switch (ri_iter.type) {
|
||||||
|
case IntRule:
|
||||||
|
sprintf(buffer, "%d", m_RuleIntValues[ri_iter.rule_index]);
|
||||||
|
rule_data[ri_iter.name].first = buffer;
|
||||||
|
rule_data[ri_iter.name].second = &ri_iter.notes;
|
||||||
|
break;
|
||||||
|
case RealRule:
|
||||||
|
sprintf(buffer, "%.13f", m_RuleRealValues[ri_iter.rule_index]);
|
||||||
|
rule_data[ri_iter.name].first = buffer;
|
||||||
|
rule_data[ri_iter.name].second = &ri_iter.notes;
|
||||||
|
break;
|
||||||
|
case BoolRule:
|
||||||
|
sprintf(buffer, "%s", (m_RuleBoolValues[ri_iter.rule_index] ? "true" : "false"));
|
||||||
|
rule_data[ri_iter.name].first = buffer;
|
||||||
|
rule_data[ri_iter.name].second = &ri_iter.notes;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build injected entries
|
||||||
|
for (const auto &rd_iter : rule_data) {
|
||||||
|
|
||||||
|
const auto &dd_iter = std::find(database_data.begin(), database_data.end(), rd_iter.first);
|
||||||
|
if (dd_iter == database_data.end()) {
|
||||||
|
|
||||||
|
injected_rule_entries.push_back(
|
||||||
|
std::tuple<int, std::string, std::string, std::string>(
|
||||||
|
ruleset_id, // `ruleset_id`
|
||||||
|
rd_iter.first, // `rule_name`
|
||||||
|
rd_iter.second.first, // `rule_value`
|
||||||
|
EscapeString(*rd_iter.second.second) // `notes`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!quiet_update) {
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"New Rule '%s' found... Adding to `rule_values` table with ruleset '%s' (%i) and rule value '%s'...",
|
||||||
|
rd_iter.first.c_str(),
|
||||||
|
ruleset_name,
|
||||||
|
ruleset_id,
|
||||||
|
rd_iter.second.first.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (injected_rule_entries.size()) {
|
||||||
|
|
||||||
|
std::string query(
|
||||||
|
fmt::format(
|
||||||
|
"REPLACE INTO `rule_values`(`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}",
|
||||||
|
implode(
|
||||||
|
",",
|
||||||
|
std::pair<char, char>('(', ')'),
|
||||||
|
join_tuple(",", std::pair<char, char>('\'', '\''), injected_rule_entries)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!db->QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"%u New Rule%s Added to ruleset '%s' (%i)",
|
||||||
|
injected_rule_entries.size(),
|
||||||
|
(injected_rule_entries.size() == 1 ? "" : "s"),
|
||||||
|
ruleset_name,
|
||||||
|
ruleset_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleManager::UpdateOrphanedRules(Database *db, bool quiet_update)
|
||||||
|
{
|
||||||
|
std::vector<std::string> rule_data;
|
||||||
|
std::vector<std::string> orphaned_rule_entries;
|
||||||
|
|
||||||
|
// load database rule names
|
||||||
|
std::string query("SELECT `rule_name` FROM `rule_values` GROUP BY `rule_name`");
|
||||||
|
|
||||||
|
auto results = db->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build rule data entries
|
||||||
|
for (const auto &ri_iter : s_RuleInfo) {
|
||||||
|
if (strcasecmp(ri_iter.name, "Invalid Rule") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rule_data.push_back(ri_iter.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build orphaned entries
|
||||||
|
for (auto row : results) {
|
||||||
|
|
||||||
|
const auto &rd_iter = std::find(rule_data.begin(), rule_data.end(), row[0]);
|
||||||
|
if (rd_iter == rule_data.end()) {
|
||||||
|
|
||||||
|
orphaned_rule_entries.push_back(std::string(row[0]));
|
||||||
|
|
||||||
|
if (!quiet_update) {
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"Rule '%s' no longer exists... Deleting orphaned entry from `rule_values` table...",
|
||||||
|
row[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orphaned_rule_entries.size()) {
|
||||||
|
|
||||||
|
std::string query (
|
||||||
|
fmt::format(
|
||||||
|
"DELETE FROM `rule_values` WHERE `rule_name` IN ({})",
|
||||||
|
implode(",", std::pair<char, char>('\'', '\''), orphaned_rule_entries)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!db->QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"%u Orphaned Rule%s Deleted from 'All Rulesets' (-1)",
|
||||||
|
orphaned_rule_entries.size(),
|
||||||
|
(orphaned_rule_entries.size() == 1 ? "" : "s")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RuleManager::RestoreRuleNotes(Database *db)
|
||||||
|
{
|
||||||
|
std::string query("SELECT `ruleset_id`, `rule_name`, IFNULL(`notes`, '\\0')`notes` FROM `rule_values`");
|
||||||
|
|
||||||
|
auto results = db->QueryDatabase(query);
|
||||||
|
if (!results.Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int update_count = 0;
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
|
||||||
|
const auto &rule = [&row]() {
|
||||||
|
|
||||||
|
for (const auto &rule_iter : s_RuleInfo) {
|
||||||
|
if (strcasecmp(rule_iter.name, row[1]) == 0) {
|
||||||
|
return rule_iter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount];
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (strcasecmp(rule.name, row[1]) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rule.notes.compare(row[2]) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string query(
|
||||||
|
fmt::format(
|
||||||
|
"UPDATE `rule_values` SET `notes` = '{}' WHERE `ruleset_id` = '{}' AND `rule_name` = '{}'",
|
||||||
|
EscapeString(rule.notes),
|
||||||
|
row[0],
|
||||||
|
row[1]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!db->QueryDatabase(query).Success()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
++update_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (update_count > 0) {
|
||||||
|
Log(Logs::General, Logs::Status, "%u Rule Note%s Restored", update_count, (update_count == 1 ? "" : "s"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
|
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
|
||||||
|
|
||||||
|
|||||||
@ -49,21 +49,21 @@ class RuleManager {
|
|||||||
public:
|
public:
|
||||||
//generate our rule enums:
|
//generate our rule enums:
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define RULE_INT(cat, rule, default_value) \
|
#define RULE_INT(cat, rule, default_value, notes) \
|
||||||
Int__##rule,
|
Int__##rule,
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
_IntRuleCount
|
_IntRuleCount
|
||||||
} IntType;
|
} IntType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define RULE_REAL(cat, rule, default_value) \
|
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||||
Real__##rule,
|
Real__##rule,
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
_RealRuleCount
|
_RealRuleCount
|
||||||
} RealType;
|
} RealType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
#define RULE_BOOL(cat, rule, default_value) \
|
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||||
Bool__##rule,
|
Bool__##rule,
|
||||||
#include "ruletypes.h"
|
#include "ruletypes.h"
|
||||||
_BoolRuleCount
|
_BoolRuleCount
|
||||||
@ -97,6 +97,9 @@ public:
|
|||||||
static const char *GetRuleName(IntType t) { return(s_RuleInfo[t].name); }
|
static const char *GetRuleName(IntType t) { return(s_RuleInfo[t].name); }
|
||||||
static const char *GetRuleName(RealType t) { return(s_RuleInfo[t+_IntRuleCount].name); }
|
static const char *GetRuleName(RealType t) { return(s_RuleInfo[t+_IntRuleCount].name); }
|
||||||
static const char *GetRuleName(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].name); }
|
static const char *GetRuleName(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].name); }
|
||||||
|
static const std::string &GetRuleNotes(IntType t) { return(s_RuleInfo[t].notes); }
|
||||||
|
static const std::string &GetRuleNotes(RealType t) { return(s_RuleInfo[t+_IntRuleCount].notes); }
|
||||||
|
static const std::string &GetRuleNotes(BoolType t) { return(s_RuleInfo[t+_IntRuleCount+_RealRuleCount].notes); }
|
||||||
static uint32 CountRules() { return(_RulesCount); }
|
static uint32 CountRules() { return(_RulesCount); }
|
||||||
static CategoryType FindCategory(const char *catname);
|
static CategoryType FindCategory(const char *catname);
|
||||||
bool ListRules(const char *catname, std::vector<const char *> &into);
|
bool ListRules(const char *catname, std::vector<const char *> &into);
|
||||||
@ -113,6 +116,9 @@ public:
|
|||||||
void ResetRules(bool reload = false);
|
void ResetRules(bool reload = false);
|
||||||
bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false);
|
bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false);
|
||||||
void SaveRules(Database *db, const char *ruleset = nullptr);
|
void SaveRules(Database *db, const char *ruleset = nullptr);
|
||||||
|
bool UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update = false);
|
||||||
|
bool UpdateOrphanedRules(Database *db, bool quiet_update = false);
|
||||||
|
bool RestoreRuleNotes(Database *db);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RuleManager();
|
RuleManager();
|
||||||
@ -137,6 +143,7 @@ private:
|
|||||||
|
|
||||||
static bool _FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into);
|
static bool _FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into);
|
||||||
static const char *_GetRuleName(RuleType type, uint16 index);
|
static const char *_GetRuleName(RuleType type, uint16 index);
|
||||||
|
static const std::string &_GetRuleNotes(RuleType type, uint16 index);
|
||||||
static int _FindOrCreateRuleset(Database *db, const char *ruleset);
|
static int _FindOrCreateRuleset(Database *db, const char *ruleset);
|
||||||
void _SaveRule(Database *db, RuleType type, uint16 index);
|
void _SaveRule(Database *db, RuleType type, uint16 index);
|
||||||
|
|
||||||
@ -146,6 +153,7 @@ private:
|
|||||||
CategoryType category;
|
CategoryType category;
|
||||||
RuleType type;
|
RuleType type;
|
||||||
uint16 rule_index; //index into its 'type' array
|
uint16 rule_index; //index into its 'type' array
|
||||||
|
const std::string notes;
|
||||||
} RuleInfo;
|
} RuleInfo;
|
||||||
static const RuleInfo s_RuleInfo[];
|
static const RuleInfo s_RuleInfo[];
|
||||||
|
|
||||||
|
|||||||
1224
common/ruletypes.h
1224
common/ruletypes.h
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
#if defined(_MSC_VER) && _MSC_VER >= 1800
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -1469,6 +1470,58 @@ bool SharedDatabase::GetCommandSettings(std::map<std::string, std::pair<uint8, s
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected)
|
||||||
|
{
|
||||||
|
if (injected.size()) {
|
||||||
|
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"REPLACE INTO `command_settings`(`command`, `access`) VALUES {}",
|
||||||
|
implode(
|
||||||
|
",",
|
||||||
|
std::pair<char, char>('(', ')'),
|
||||||
|
join_pair(",", std::pair<char, char>('\'', '\''), injected)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"%u New Command%s Added",
|
||||||
|
injected.size(),
|
||||||
|
(injected.size() == 1 ? "" : "s")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned)
|
||||||
|
{
|
||||||
|
if (orphaned.size()) {
|
||||||
|
|
||||||
|
std::string query = fmt::format(
|
||||||
|
"DELETE FROM `command_settings` WHERE `command` IN ({})",
|
||||||
|
implode(",", std::pair<char, char>('\'', '\''), orphaned)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"%u Orphaned Command%s Deleted",
|
||||||
|
orphaned.size(),
|
||||||
|
(orphaned.size() == 1 ? "" : "s")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
bool SharedDatabase::LoadSkillCaps(const std::string &prefix) {
|
||||||
skill_caps_mmf.reset(nullptr);
|
skill_caps_mmf.reset(nullptr);
|
||||||
|
|
||||||
|
|||||||
@ -71,6 +71,8 @@ class SharedDatabase : public Database
|
|||||||
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
|
void LoadCharacterInspectMessage(uint32 character_id, InspectMessage_Struct* message);
|
||||||
void SaveCharacterInspectMessage(uint32 character_id, const 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 GetCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &command_settings);
|
||||||
|
bool UpdateInjectedCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected);
|
||||||
|
bool UpdateOrphanedCommandSettings(const std::vector<std::string> &orphaned);
|
||||||
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
uint32 GetTotalTimeEntitledOnAccount(uint32 AccountID);
|
||||||
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
void SetMailKey(int CharID, int IPAddress, int MailKey);
|
||||||
std::string GetMailKey(int CharID, bool key_only = false);
|
std::string GetMailKey(int CharID, bool key_only = false);
|
||||||
|
|||||||
@ -144,6 +144,7 @@ std::string implode(std::string glue, std::vector<std::string> src)
|
|||||||
return final_output;
|
return final_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string EscapeString(const std::string &s) {
|
std::string EscapeString(const std::string &s) {
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,12 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
// this doesn't appear to affect linux-based systems..need feedback for _WIN64
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
@ -31,6 +37,93 @@ std::vector<std::string> split(std::string str_to_split, char delimiter);
|
|||||||
const std::string StringFormat(const char* format, ...);
|
const std::string StringFormat(const char* format, ...);
|
||||||
const std::string vStringFormat(const char* format, va_list args);
|
const std::string vStringFormat(const char* format, va_list args);
|
||||||
std::string implode(std::string glue, std::vector<std::string> src);
|
std::string implode(std::string glue, std::vector<std::string> src);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::string implode(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<T> &src)
|
||||||
|
{
|
||||||
|
if (src.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
|
||||||
|
for (const T &src_iter : src) {
|
||||||
|
oss << encapsulation.first << src_iter << encapsulation.second << glue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string output(oss.str());
|
||||||
|
output.resize(output.size() - glue.size());
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
std::vector<std::string> join_pair(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<std::pair<T1, T2>> &src)
|
||||||
|
{
|
||||||
|
if (src.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> output;
|
||||||
|
|
||||||
|
for (const std::pair<T1, T2> &src_iter : src) {
|
||||||
|
output.push_back(
|
||||||
|
|
||||||
|
fmt::format(
|
||||||
|
"{}{}{}{}{}{}{}",
|
||||||
|
encapsulation.first,
|
||||||
|
src_iter.first,
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
src_iter.second,
|
||||||
|
encapsulation.second
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _WIN32 builds require that #include<fmt/format.h> be included in whatever code file the invocation is made from (no header files)
|
||||||
|
template <typename T1, typename T2, typename T3, typename T4>
|
||||||
|
std::vector<std::string> join_tuple(const std::string &glue, const std::pair<char, char> &encapsulation, const std::vector<std::tuple<T1, T2, T3, T4>> &src)
|
||||||
|
{
|
||||||
|
if (src.empty()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> output;
|
||||||
|
|
||||||
|
for (const std::tuple<T1, T2, T3, T4> &src_iter : src) {
|
||||||
|
|
||||||
|
output.push_back(
|
||||||
|
|
||||||
|
fmt::format(
|
||||||
|
"{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}",
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<0>(src_iter),
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<1>(src_iter),
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<2>(src_iter),
|
||||||
|
encapsulation.second,
|
||||||
|
glue,
|
||||||
|
encapsulation.first,
|
||||||
|
std::get<3>(src_iter),
|
||||||
|
encapsulation.second
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> SplitString(const std::string &s, char delim);
|
std::vector<std::string> SplitString(const std::string &s, char delim);
|
||||||
std::string EscapeString(const char *src, size_t sz);
|
std::string EscapeString(const char *src, size_t sz);
|
||||||
std::string EscapeString(const std::string &s);
|
std::string EscapeString(const std::string &s);
|
||||||
|
|||||||
@ -332,16 +332,28 @@ int main(int argc, char** argv) {
|
|||||||
Log(Logs::General, Logs::World_Server, "Error: Could not load skill cap data. But ignoring");
|
Log(Logs::General, Logs::World_Server, "Error: Could not load skill cap data. But ignoring");
|
||||||
Log(Logs::General, Logs::World_Server, "Loading guilds..");
|
Log(Logs::General, Logs::World_Server, "Loading guilds..");
|
||||||
guild_mgr.LoadGuilds();
|
guild_mgr.LoadGuilds();
|
||||||
|
|
||||||
//rules:
|
//rules:
|
||||||
{
|
{
|
||||||
|
if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) {
|
||||||
|
Log(Logs::General, Logs::World_Server, "Failed to process 'Orphaned Rules' update operation.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!RuleManager::Instance()->UpdateInjectedRules(&database, "default")) {
|
||||||
|
Log(Logs::General, Logs::World_Server, "Failed to process 'Injected Rules' for ruleset 'default' update operation.");
|
||||||
|
}
|
||||||
|
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
if (database.GetVariable("RuleSet", tmp)) {
|
if (database.GetVariable("RuleSet", tmp)) {
|
||||||
|
|
||||||
Log(Logs::General, Logs::World_Server, "Loading rule set '%s'", tmp.c_str());
|
Log(Logs::General, Logs::World_Server, "Loading rule set '%s'", tmp.c_str());
|
||||||
|
|
||||||
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
if (!RuleManager::Instance()->LoadRules(&database, tmp.c_str(), false)) {
|
||||||
Log(Logs::General, Logs::World_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str());
|
Log(Logs::General, Logs::World_Server, "Failed to load ruleset '%s', falling back to defaults.", tmp.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
if (!RuleManager::Instance()->LoadRules(&database, "default", false)) {
|
||||||
Log(Logs::General, Logs::World_Server, "No rule set configured, using default rules");
|
Log(Logs::General, Logs::World_Server, "No rule set configured, using default rules");
|
||||||
}
|
}
|
||||||
@ -350,17 +362,19 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!RuleManager::Instance()->RestoreRuleNotes(&database)) {
|
||||||
|
Log(Logs::General, Logs::World_Server, "Failed to process 'Restore Rule Notes' update operation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EQEmu::InitializeDynamicLookups();
|
EQEmu::InitializeDynamicLookups();
|
||||||
Log(Logs::General, Logs::World_Server, "Initialized dynamic dictionary entries");
|
Log(Logs::General, Logs::World_Server, "Initialized dynamic dictionary entries");
|
||||||
}
|
|
||||||
|
|
||||||
if (RuleB(World, ClearTempMerchantlist)) {
|
if (RuleB(World, ClearTempMerchantlist)) {
|
||||||
Log(Logs::General, Logs::World_Server, "Clearing temporary merchant lists..");
|
Log(Logs::General, Logs::World_Server, "Clearing temporary merchant lists..");
|
||||||
database.ClearMerchantTemp();
|
database.ClearMerchantTemp();
|
||||||
}
|
}
|
||||||
|
|
||||||
RuleManager::Instance()->SaveRules(&database);
|
|
||||||
|
|
||||||
Log(Logs::General, Logs::World_Server, "Loading EQ time of day..");
|
Log(Logs::General, Logs::World_Server, "Loading EQ time of day..");
|
||||||
TimeOfDay_Struct eqTime;
|
TimeOfDay_Struct eqTime;
|
||||||
time_t realtime;
|
time_t realtime;
|
||||||
|
|||||||
@ -1429,32 +1429,96 @@ int bot_command_init(void)
|
|||||||
std::map<std::string, std::pair<uint8, std::vector<std::string>>> bot_command_settings;
|
std::map<std::string, std::pair<uint8, std::vector<std::string>>> bot_command_settings;
|
||||||
database.botdb.LoadBotCommandSettings(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;
|
||||||
|
|
||||||
|
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 (orphaned_bot_command_settings.size()) {
|
||||||
|
if (!database.botdb.UpdateOrphanedBotCommandSettings(orphaned_bot_command_settings)) {
|
||||||
|
Log(Logs::General, Logs::Zone_Server, "Failed to process 'Orphaned Bot Commands' update operation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto working_bcl = bot_command_list;
|
auto working_bcl = bot_command_list;
|
||||||
for (auto working_bcl_iter : working_bcl) {
|
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()) {
|
auto bcs_iter = bot_command_settings.find(working_bcl_iter.first);
|
||||||
if (working_bcl_iter.second->access == 0)
|
if (bcs_iter == bot_command_settings.end()) {
|
||||||
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
working_bcl_iter.second->access = bot_command_settings_iter->second.first;
|
working_bcl_iter.second->access = bcs_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);
|
Log(Logs::General,
|
||||||
if (bot_command_settings_iter->second.second.empty())
|
Logs::Commands,
|
||||||
continue;
|
"bot_command_init(): - Bot Command '%s' set to access level %d.",
|
||||||
|
working_bcl_iter.first.c_str(),
|
||||||
|
bcs_iter->second.first
|
||||||
|
);
|
||||||
|
|
||||||
for (auto alias_iter : bot_command_settings_iter->second.second) {
|
if (bcs_iter->second.second.empty()) {
|
||||||
if (alias_iter.empty())
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto alias_iter : bcs_iter->second.second) {
|
||||||
|
if (alias_iter.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (bot_command_list.find(alias_iter) != bot_command_list.end()) {
|
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());
|
Log(Logs::General,
|
||||||
|
Logs::Commands,
|
||||||
|
"bot_command_init(): Warning: Alias '%s' already exists as a bot command - skipping!",
|
||||||
|
alias_iter.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bot_command_list[alias_iter] = working_bcl_iter.second;
|
bot_command_list[alias_iter] = working_bcl_iter.second;
|
||||||
bot_command_aliases[alias_iter] = working_bcl_iter.first;
|
bot_command_aliases[alias_iter] = working_bcl_iter.first;
|
||||||
|
|
||||||
Log(Logs::General, Logs::Commands, "bot_command_init(): - Alias '%s' added to bot command '%s'.", alias_iter.c_str(), bot_command_aliases[alias_iter].c_str());
|
Log(Logs::General,
|
||||||
|
Logs::Commands,
|
||||||
|
"bot_command_init(): - Alias '%s' added to bot command '%s'.",
|
||||||
|
alias_iter.c_str(),
|
||||||
|
bot_command_aliases[alias_iter].c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (injected_bot_command_settings.size()) {
|
||||||
|
if (!database.botdb.UpdateInjectedBotCommandSettings(injected_bot_command_settings)) {
|
||||||
|
Log(Logs::General, Logs::Zone_Server, "Failed to process 'Injected Bot Commands' update operation.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#ifdef BOTS
|
#ifdef BOTS
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include "../common/global_define.h"
|
#include "../common/global_define.h"
|
||||||
#include "../common/rulesys.h"
|
#include "../common/rulesys.h"
|
||||||
#include "../common/string_util.h"
|
#include "../common/string_util.h"
|
||||||
@ -54,6 +56,58 @@ bool BotDatabase::LoadBotCommandSettings(std::map<std::string, std::pair<uint8,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BotDatabase::UpdateInjectedBotCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected)
|
||||||
|
{
|
||||||
|
if (injected.size()) {
|
||||||
|
|
||||||
|
query = fmt::format(
|
||||||
|
"REPLACE INTO `bot_command_settings`(`bot_command`, `access`) VALUES {}",
|
||||||
|
implode(
|
||||||
|
",",
|
||||||
|
std::pair<char, char>('(', ')'),
|
||||||
|
join_pair(",", std::pair<char, char>('\'', '\''), injected)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!database.QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"%u New Bot Command%s Added",
|
||||||
|
injected.size(),
|
||||||
|
(injected.size() == 1 ? "" : "s")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BotDatabase::UpdateOrphanedBotCommandSettings(const std::vector<std::string> &orphaned)
|
||||||
|
{
|
||||||
|
if (orphaned.size()) {
|
||||||
|
|
||||||
|
query = fmt::format(
|
||||||
|
"DELETE FROM `bot_command_settings` WHERE `bot_command` IN ({})",
|
||||||
|
implode(",", std::pair<char, char>('\'', '\''), orphaned)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!database.QueryDatabase(query).Success()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"%u Orphaned Bot Command%s Deleted",
|
||||||
|
orphaned.size(),
|
||||||
|
(orphaned.size() == 1 ? "" : "s")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool BotDatabase::LoadBotSpellCastingChances()
|
bool BotDatabase::LoadBotSpellCastingChances()
|
||||||
{
|
{
|
||||||
query =
|
query =
|
||||||
|
|||||||
@ -43,6 +43,8 @@ class BotDatabase
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool LoadBotCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &bot_command_settings);
|
bool LoadBotCommandSettings(std::map<std::string, std::pair<uint8, std::vector<std::string>>> &bot_command_settings);
|
||||||
|
bool UpdateInjectedBotCommandSettings(const std::vector<std::pair<std::string, uint8>> &injected);
|
||||||
|
bool UpdateOrphanedBotCommandSettings(const std::vector<std::string> &orphaned);
|
||||||
bool LoadBotSpellCastingChances();
|
bool LoadBotSpellCastingChances();
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
101
zone/command.cpp
101
zone/command.cpp
@ -454,33 +454,96 @@ int command_init(void)
|
|||||||
std::map<std::string, std::pair<uint8, std::vector<std::string>>> command_settings;
|
std::map<std::string, std::pair<uint8, std::vector<std::string>>> command_settings;
|
||||||
database.GetCommandSettings(command_settings);
|
database.GetCommandSettings(command_settings);
|
||||||
|
|
||||||
std::map<std::string, CommandRecord *> working_cl = commandlist;
|
std::vector<std::pair<std::string, uint8>> injected_command_settings;
|
||||||
for (auto iter_cl = working_cl.begin(); iter_cl != working_cl.end(); ++iter_cl) {
|
std::vector<std::string> orphaned_command_settings;
|
||||||
auto iter_cs = command_settings.find(iter_cl->first);
|
|
||||||
if (iter_cs == command_settings.end()) {
|
for (auto cs_iter : command_settings) {
|
||||||
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());
|
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 (orphaned_command_settings.size()) {
|
||||||
|
if (!database.UpdateOrphanedCommandSettings(orphaned_command_settings)) {
|
||||||
|
Log(Logs::General, Logs::Zone_Server, "Failed to process 'Orphaned Commands' update operation.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto working_cl = commandlist;
|
||||||
|
for (auto working_cl_iter : working_cl) {
|
||||||
|
|
||||||
|
auto cs_iter = command_settings.find(working_cl_iter.first);
|
||||||
|
if (cs_iter == command_settings.end()) {
|
||||||
|
|
||||||
|
injected_command_settings.push_back(std::pair<std::string, uint8>(working_cl_iter.first, working_cl_iter.second->access));
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Status,
|
||||||
|
"New Command '%s' found... Adding to `command_settings` table with access '%u'...",
|
||||||
|
working_cl_iter.first.c_str(),
|
||||||
|
working_cl_iter.second->access
|
||||||
|
);
|
||||||
|
|
||||||
|
if (working_cl_iter.second->access == 0) {
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Commands,
|
||||||
|
"command_init(): Warning: Command '%s' defaulting to access level 0!",
|
||||||
|
working_cl_iter.first.c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
iter_cl->second->access = iter_cs->second.first;
|
working_cl_iter.second->access = cs_iter->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);
|
Log(Logs::General,
|
||||||
if (iter_cs->second.second.empty())
|
Logs::Commands,
|
||||||
continue;
|
"command_init(): - Command '%s' set to access level %d.",
|
||||||
|
working_cl_iter.first.c_str(),
|
||||||
|
cs_iter->second.first
|
||||||
|
);
|
||||||
|
|
||||||
for (auto iter_aka = iter_cs->second.second.begin(); iter_aka != iter_cs->second.second.end();
|
if (cs_iter->second.second.empty()) {
|
||||||
++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());
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
commandlist[*iter_aka] = iter_cl->second;
|
for (auto alias_iter : cs_iter->second.second) {
|
||||||
commandaliases[*iter_aka] = iter_cl->first;
|
if (alias_iter.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
Log(Logs::General, Logs::Commands, "command_init(): - Alias '%s' added to command '%s'.", iter_aka->c_str(), commandaliases[*iter_aka].c_str());
|
if (commandlist.find(alias_iter) != commandlist.end()) {
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Commands,
|
||||||
|
"command_init(): Warning: Alias '%s' already exists as a command - skipping!",
|
||||||
|
alias_iter.c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
commandlist[alias_iter] = working_cl_iter.second;
|
||||||
|
commandaliases[alias_iter] = working_cl_iter.first;
|
||||||
|
|
||||||
|
Log(Logs::General,
|
||||||
|
Logs::Commands,
|
||||||
|
"command_init(): - Alias '%s' added to command '%s'.",
|
||||||
|
alias_iter.c_str(),
|
||||||
|
commandaliases[alias_iter].c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (injected_command_settings.size()) {
|
||||||
|
if (!database.UpdateInjectedCommandSettings(injected_command_settings)) {
|
||||||
|
Log(Logs::General, Logs::Zone_Server, "Failed to process 'Injected Commands' update operation.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2327,17 +2327,17 @@ luabind::scope lua_register_rules_const() {
|
|||||||
return luabind::class_<Rule>("Rule")
|
return luabind::class_<Rule>("Rule")
|
||||||
.enum_("constants")
|
.enum_("constants")
|
||||||
[
|
[
|
||||||
#define RULE_INT(cat, rule, default_value) \
|
#define RULE_INT(cat, rule, default_value, notes) \
|
||||||
luabind::value(#rule, RuleManager::Int__##rule),
|
luabind::value(#rule, RuleManager::Int__##rule),
|
||||||
#include "../common/ruletypes.h"
|
#include "../common/ruletypes.h"
|
||||||
luabind::value("_IntRuleCount", RuleManager::_IntRuleCount),
|
luabind::value("_IntRuleCount", RuleManager::_IntRuleCount),
|
||||||
#undef RULE_INT
|
#undef RULE_INT
|
||||||
#define RULE_REAL(cat, rule, default_value) \
|
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||||
luabind::value(#rule, RuleManager::Real__##rule),
|
luabind::value(#rule, RuleManager::Real__##rule),
|
||||||
#include "../common/ruletypes.h"
|
#include "../common/ruletypes.h"
|
||||||
luabind::value("_RealRuleCount", RuleManager::_RealRuleCount),
|
luabind::value("_RealRuleCount", RuleManager::_RealRuleCount),
|
||||||
#undef RULE_REAL
|
#undef RULE_REAL
|
||||||
#define RULE_BOOL(cat, rule, default_value) \
|
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||||
luabind::value(#rule, RuleManager::Bool__##rule),
|
luabind::value(#rule, RuleManager::Bool__##rule),
|
||||||
#include "../common/ruletypes.h"
|
#include "../common/ruletypes.h"
|
||||||
luabind::value("_BoolRuleCount", RuleManager::_BoolRuleCount)
|
luabind::value("_BoolRuleCount", RuleManager::_BoolRuleCount)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user