mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-17 03:08:26 +00:00
[Commands] Cleanup #rules Command. (#2593)
* [Commands] Cleanup #rules Command. - Cleanup messages and logic. - Rewrite all rules logic to use `std::string` and repositories. * References * Update rules.cpp * Strings::Equal and Strings::EqualFold. * Cleanup. * Update rulesys.cpp * Update rulesys.cpp Co-authored-by: Akkadius <akkadius1@gmail.com>
This commit is contained in:
@@ -44,7 +44,53 @@ public:
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static int GetRuleSetID(Database& db, std::string rule_set_name)
|
||||
{
|
||||
const auto query = fmt::format(
|
||||
"SELECT ruleset_id FROM {} WHERE `name` = '{}'",
|
||||
TableName(),
|
||||
Strings::Escape(rule_set_name)
|
||||
);
|
||||
auto results = db.QueryDatabase(query);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
return std::stoi(row[0]);
|
||||
}
|
||||
|
||||
static int CreateNewRuleSet(Database& db, std::string rule_set_name)
|
||||
{
|
||||
const auto query = fmt::format(
|
||||
"INSERT INTO {} (`name`) VALUES ('{}')",
|
||||
TableName(),
|
||||
rule_set_name
|
||||
);
|
||||
auto results = db.QueryDatabase(query);
|
||||
if (!results.Success() || !results.RowsAffected()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return static_cast<int>(results.LastInsertedID());
|
||||
}
|
||||
|
||||
static std::string GetRuleSetName(Database& db, int rule_set_id)
|
||||
{
|
||||
const auto query = fmt::format(
|
||||
"SELECT `name` FROM {} WHERE ruleset_id = {}",
|
||||
TableName(),
|
||||
rule_set_id
|
||||
);
|
||||
auto results = db.QueryDatabase(query);
|
||||
if (!results.Success() || !results.RowsAffected()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return std::string(row[0]);
|
||||
}
|
||||
};
|
||||
|
||||
#endif //EQEMU_RULE_SETS_REPOSITORY_H
|
||||
|
||||
@@ -44,6 +44,87 @@ public:
|
||||
*/
|
||||
|
||||
// Custom extended repository methods here
|
||||
static std::vector<std::string> GetRuleNames(Database &db, int rule_set_id)
|
||||
{
|
||||
std::vector<std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT rule_name FROM {} WHERE ruleset_id = {}",
|
||||
TableName(),
|
||||
rule_set_id
|
||||
)
|
||||
);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return v;
|
||||
}
|
||||
|
||||
for (auto row : results) {
|
||||
v.push_back(row[0]);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static std::vector<std::string> GetGroupedRules(Database &db)
|
||||
{
|
||||
std::vector <std::string> v;
|
||||
|
||||
auto results = db.QueryDatabase(
|
||||
fmt::format(
|
||||
"SELECT rule_name FROM {} GROUP BY rule_name",
|
||||
TableName()
|
||||
)
|
||||
);
|
||||
if (!results.Success() || !results.RowCount()) {
|
||||
return v;
|
||||
}
|
||||
|
||||
for (auto row : results) {
|
||||
v.push_back(row[0]);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
static bool DeleteOrphanedRules(Database& db, std::vector<std::string>& v)
|
||||
{
|
||||
const auto query = fmt::format(
|
||||
"DELETE FROM {} WHERE rule_name IN ({})",
|
||||
TableName(),
|
||||
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), v)
|
||||
);
|
||||
|
||||
return db.QueryDatabase(query).Success();
|
||||
}
|
||||
|
||||
static bool InjectRules(Database& db, std::vector<std::tuple<int, std::string, std::string, std::string>>& v)
|
||||
{
|
||||
const auto query = fmt::format(
|
||||
"REPLACE INTO {} (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}",
|
||||
TableName(),
|
||||
Strings::ImplodePair(
|
||||
",",
|
||||
std::pair<char, char>('(', ')'),
|
||||
join_tuple(",", std::pair<char, char>('\'', '\''), v)
|
||||
)
|
||||
);
|
||||
|
||||
return db.QueryDatabase(query).Success();
|
||||
}
|
||||
|
||||
static bool UpdateRuleNote(Database& db, int rule_set_id, std::string rule_name, std::string notes)
|
||||
{
|
||||
const auto query = fmt::format(
|
||||
"UPDATE {} SET notes = '{}' WHERE ruleset_id = {} AND rule_name = '{}'",
|
||||
TableName(),
|
||||
Strings::Escape(notes),
|
||||
rule_set_id,
|
||||
rule_name
|
||||
);
|
||||
|
||||
return db.QueryDatabase(query).Success();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
+317
-398
@@ -24,462 +24,451 @@
|
||||
#include <cstring>
|
||||
#include <fmt/format.h>
|
||||
|
||||
/*
|
||||
Commands:
|
||||
#rules:
|
||||
current -> lists current set name
|
||||
switch (set name) -> change set in the DB, but dont reload
|
||||
load (set name) -> load set into this zone without changing the world
|
||||
wload (set name) -> tell world and all zones to load this rule set
|
||||
store [set name] -> store the current rules in this zone to the set (or active if not specified)
|
||||
reset -> reset all rule values to their defaults.
|
||||
list [catname]
|
||||
set (cat) (rule) (value)
|
||||
values [catname] -> show the values of all rules in the specified category/
|
||||
*/
|
||||
#include "../common/repositories/rule_sets_repository.h"
|
||||
#include "../common/repositories/rule_values_repository.h"
|
||||
|
||||
const char *RuleManager::s_categoryNames[_CatCount+1] = {
|
||||
#define RULE_CATEGORY(catname) \
|
||||
#catname ,
|
||||
const char *RuleManager::s_categoryNames[_CatCount + 1] = {
|
||||
#define RULE_CATEGORY(category_name) \
|
||||
#category_name ,
|
||||
#include "ruletypes.h"
|
||||
"InvalidCategory"
|
||||
};
|
||||
|
||||
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*/
|
||||
#define RULE_INT(cat, rule, default_value, notes) \
|
||||
{ #cat ":" #rule, Category__##cat, IntRule, Int__##rule, notes },
|
||||
#define RULE_INT(category_name, rule_name, default_value, notes) \
|
||||
{ #category_name ":" #rule_name, Category__##category_name, IntRule, Int__##rule_name, notes },
|
||||
#include "ruletypes.h"
|
||||
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||
{ #cat ":" #rule, Category__##cat, RealRule, Real__##rule, notes },
|
||||
#define RULE_REAL(category_name, rule_name, default_value, notes) \
|
||||
{ #category_name ":" #rule_name, Category__##category_name, RealRule, Real__##rule_name, notes },
|
||||
#include "ruletypes.h"
|
||||
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||
{ #cat ":" #rule, Category__##cat, BoolRule, Bool__##rule, notes },
|
||||
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
||||
{ #category_name ":" #rule_name, Category__##category_name, BoolRule, Bool__##rule_name, notes },
|
||||
#include "ruletypes.h"
|
||||
{ "Invalid Rule", _CatCount, IntRule }
|
||||
};
|
||||
|
||||
RuleManager::RuleManager()
|
||||
: m_activeRuleset(0),
|
||||
m_activeName("default")
|
||||
: m_activeRuleset(0),
|
||||
m_activeName("default")
|
||||
{
|
||||
ResetRules(false);
|
||||
}
|
||||
|
||||
RuleManager::CategoryType RuleManager::FindCategory(const char *catname) {
|
||||
int i;
|
||||
for (i = 0; i < _CatCount; i++) {
|
||||
if (strcasecmp(catname, s_categoryNames[i]) == 0)
|
||||
return((CategoryType)i);
|
||||
}
|
||||
return(InvalidCategory);
|
||||
}
|
||||
|
||||
bool RuleManager::ListRules(const char *catname, std::vector<const char *> &into) {
|
||||
CategoryType cat = InvalidCategory;
|
||||
if (catname != nullptr) {
|
||||
cat = FindCategory(catname);
|
||||
if (cat == InvalidCategory) {
|
||||
Log(Logs::Detail, Logs::Rules, "Unable to find category '%s'", catname);
|
||||
return(false);
|
||||
RuleManager::CategoryType RuleManager::FindCategory(const std::string &category_name)
|
||||
{
|
||||
for (int i = 0; i < _CatCount; i++) {
|
||||
if (Strings::Contains(category_name, s_categoryNames[i])) {
|
||||
return static_cast<CategoryType>(i);
|
||||
}
|
||||
}
|
||||
int i;
|
||||
int rule_count = CountRules();
|
||||
for (i = 0; i < rule_count; i++) {
|
||||
const RuleInfo &rule = s_RuleInfo[i];
|
||||
if (catname == nullptr || cat == rule.category) {
|
||||
into.push_back(rule.name);
|
||||
|
||||
return InvalidCategory;
|
||||
}
|
||||
|
||||
bool RuleManager::ListRules(const std::string &category_name, std::vector<std::string> &l)
|
||||
{
|
||||
CategoryType category_type = InvalidCategory;
|
||||
if (!category_name.empty()) {
|
||||
category_type = FindCategory(category_name);
|
||||
if (category_type == InvalidCategory) {
|
||||
LogRulesDetail("Unable to find category '{}'.", category_name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool RuleManager::ListCategories(std::vector<const char *> &into) {
|
||||
int i;
|
||||
for (i = 0; i < _CatCount; i++) {
|
||||
into.push_back(s_categoryNames[i]);
|
||||
for (int i = 0; i < CountRules(); i++) {
|
||||
const auto& r = s_RuleInfo[i];
|
||||
if (category_name.empty() || category_type == r.category) {
|
||||
l.push_back(r.name);
|
||||
}
|
||||
}
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool RuleManager::GetRule(const char *rule_name, std::string &return_value) {
|
||||
RuleType type;
|
||||
uint16 index;
|
||||
if (!_FindRule(rule_name, type, index))
|
||||
return false;
|
||||
|
||||
char tmp[255] = "";
|
||||
switch(type) {
|
||||
case IntRule:
|
||||
sprintf(tmp, "%i", m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
sprintf(tmp, "%f", m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
std::string tmp_val = m_RuleBoolValues[index] ? "true" : "false";
|
||||
sprintf(tmp, "%s", tmp_val.c_str());
|
||||
break;
|
||||
}
|
||||
|
||||
return_value = tmp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuleManager::SetRule(const char *rule_name, const char *rule_value, Database *database, bool db_save, bool reload) {
|
||||
if(rule_name == nullptr || rule_value == nullptr)
|
||||
return(false);
|
||||
bool RuleManager::ListCategories(std::vector <std::string> &l)
|
||||
{
|
||||
for (int i = 0; i < _CatCount; i++) {
|
||||
l.push_back(s_categoryNames[i]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuleManager::GetRule(const std::string &rule_name, std::string &rule_value)
|
||||
{
|
||||
RuleType type;
|
||||
uint16 index;
|
||||
if (!_FindRule(rule_name, type, index)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case IntRule:
|
||||
rule_value = fmt::format("{}", m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
rule_value = fmt::format("{}", m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
rule_value = m_RuleBoolValues[index] ? "true" : "false";
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RuleManager::SetRule(const std::string &rule_name, const std::string &rule_value, Database *db, bool db_save, bool reload)
|
||||
{
|
||||
if (rule_name.empty() || rule_value.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RuleType type;
|
||||
uint16 index;
|
||||
if(!_FindRule(rule_name, type, index))
|
||||
return(false);
|
||||
|
||||
if (reload) {
|
||||
if (strcasecmp(rule_name, "World:ExpansionSettings") == 0)
|
||||
return(false);
|
||||
if (strcasecmp(rule_name, "World:UseClientBasedExpansionSettings") == 0)
|
||||
return(false);
|
||||
if (!_FindRule(rule_name, type, index)) {
|
||||
return (false);
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
if (reload) {
|
||||
bool is_client = Strings::EqualFold(rule_name, "World:UseClientBasedExpansionSettings");
|
||||
bool is_world = Strings::EqualFold(rule_name, "World:ExpansionSettings");
|
||||
if (is_client || is_world) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case IntRule:
|
||||
m_RuleIntValues[index] = atoi(rule_value);
|
||||
m_RuleIntValues[index] = atoi(rule_value.c_str());
|
||||
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
m_RuleRealValues[index] = atof(rule_value);
|
||||
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleRealValues[index]);
|
||||
m_RuleRealValues[index] = atof(rule_value.c_str());
|
||||
LogRules("Set rule [{}] to value [{:.2f}]", rule_name, m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
uint32 val = 0;
|
||||
if (!strcasecmp(rule_value, "on") || !strcasecmp(rule_value, "true") || !strcasecmp(rule_value, "yes") || !strcasecmp(rule_value, "enabled") || !strcmp(rule_value, "1"))
|
||||
val = 1;
|
||||
|
||||
m_RuleBoolValues[index] = val;
|
||||
m_RuleBoolValues[index] = static_cast<uint32>(Strings::ToBool(rule_value));
|
||||
LogRules("Set rule [{}] to value [{}]", rule_name, m_RuleBoolValues[index] == 1 ? "true" : "false");
|
||||
break;
|
||||
}
|
||||
|
||||
if(db_save)
|
||||
_SaveRule(database, type, index);
|
||||
if (db_save) {
|
||||
_SaveRule(db, type, index);
|
||||
}
|
||||
|
||||
return(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuleManager::ResetRules(bool reload) {
|
||||
std::string expansion1;
|
||||
std::string expansion2;
|
||||
std::string client_rule;
|
||||
std::string world_rule;
|
||||
|
||||
// these rules must not change during server runtime
|
||||
if (reload) {
|
||||
GetRule("World:ExpansionSettings", expansion1);
|
||||
GetRule("World:UseClientBasedExpansionSettings", expansion2);
|
||||
GetRule("World:UseClientBasedExpansionSettings", client_rule);
|
||||
GetRule("World:ExpansionSettings", world_rule);
|
||||
}
|
||||
|
||||
Log(Logs::Detail, Logs::Rules, "Resetting running rules to default values");
|
||||
#define RULE_INT(cat, rule, default_value, notes) \
|
||||
m_RuleIntValues[ Int__##rule ] = default_value;
|
||||
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||
m_RuleRealValues[ Real__##rule ] = default_value;
|
||||
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||
m_RuleBoolValues[ Bool__##rule ] = default_value;
|
||||
LogRulesDetail("Resetting running rules to default values.");
|
||||
|
||||
#define RULE_INT(category_name, rule_name, default_value, notes) \
|
||||
m_RuleIntValues[ Int__##rule_name ] = default_value;
|
||||
#define RULE_REAL(category_name, rule_name, default_value, notes) \
|
||||
m_RuleRealValues[ Real__##rule_name ] = default_value;
|
||||
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
||||
m_RuleBoolValues[ Bool__##rule_name ] = default_value;
|
||||
#include "ruletypes.h"
|
||||
|
||||
// restore these rules to their pre-reset values
|
||||
if (reload) {
|
||||
SetRule("World:ExpansionSettings", expansion1.c_str(), nullptr, false, false);
|
||||
SetRule("World:UseClientBasedExpansionSettings", expansion2.c_str(), nullptr, false, false);
|
||||
SetRule("World:UseClientBasedExpansionSettings", client_rule);
|
||||
SetRule("World:ExpansionSettings", world_rule);
|
||||
}
|
||||
}
|
||||
|
||||
bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into) {
|
||||
if (rule_name == nullptr)
|
||||
return(false);
|
||||
bool RuleManager::_FindRule(const std::string &rule_name, RuleType &type_into, uint16 &index_into) {
|
||||
if (rule_name.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i;
|
||||
int rule_count = CountRules();
|
||||
for (i = 0; i < rule_count; i++) {
|
||||
const RuleInfo &rule = s_RuleInfo[i];
|
||||
if (strcmp(rule_name, rule.name) == 0) {
|
||||
type_into = rule.type;
|
||||
index_into = rule.rule_index;
|
||||
return(true);
|
||||
for (int i = 0; i < CountRules(); i++) {
|
||||
const auto& r = s_RuleInfo[i];
|
||||
if (rule_name == r.name) {
|
||||
type_into = r.type;
|
||||
index_into = r.rule_index;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Log(Logs::Detail, Logs::Rules, "Unable to find rule '%s'", rule_name);
|
||||
return(false);
|
||||
|
||||
LogRulesDetail("Unable to find rule '{}'.", rule_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
//assumes index is valid!
|
||||
const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
||||
std::string RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
||||
switch (type) {
|
||||
case IntRule:
|
||||
return(s_RuleInfo[index].name);
|
||||
case RealRule:
|
||||
return(s_RuleInfo[index+_IntRuleCount].name);
|
||||
case BoolRule:
|
||||
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].name);
|
||||
default:
|
||||
break;
|
||||
case IntRule:
|
||||
return s_RuleInfo[index].name;
|
||||
case RealRule:
|
||||
return s_RuleInfo[index + _IntRuleCount].name;
|
||||
case BoolRule:
|
||||
return s_RuleInfo[index + _IntRuleCount + _RealRuleCount].name;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
//should never happen
|
||||
return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].name); // no need to create a string when one already exists...
|
||||
|
||||
return s_RuleInfo[_IntRuleCount + _RealRuleCount + _BoolRuleCount].name;
|
||||
}
|
||||
|
||||
//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;
|
||||
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);
|
||||
|
||||
return s_RuleInfo[_IntRuleCount + _RealRuleCount + _BoolRuleCount].notes;
|
||||
}
|
||||
|
||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
||||
|
||||
int ruleset_id = 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);
|
||||
bool RuleManager::LoadRules(Database *db, const std::string &rule_set_name, bool reload) {
|
||||
const auto rule_set_id = RuleSetsRepository::GetRuleSetID(*db, rule_set_name);
|
||||
if (rule_set_id < 0) {
|
||||
LogRulesDetail("Failed to find Rule Set {} for load operation. Canceling.", rule_set_name);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_activeRuleset = ruleset_id;
|
||||
m_activeName = ruleset_name;
|
||||
m_activeRuleset = rule_set_id;
|
||||
m_activeName = rule_set_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());
|
||||
const std::string default_ruleset_name = "default";
|
||||
bool is_default = rule_set_name == default_ruleset_name;
|
||||
|
||||
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()
|
||||
if (!is_default) {
|
||||
const auto default_rule_set_id = RuleSetsRepository::GetRuleSetID(*db, default_ruleset_name);
|
||||
|
||||
if (default_rule_set_id < 0) {
|
||||
LogRulesDetail(
|
||||
"Failed to load default Rule Set {} for load operation.",
|
||||
default_ruleset_name
|
||||
);
|
||||
|
||||
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]);
|
||||
LogRulesDetail("Loading Rule Set {} ({}).", default_ruleset_name, default_rule_set_id);
|
||||
|
||||
const auto& l = RuleValuesRepository::GetWhere(
|
||||
*db,
|
||||
fmt::format(
|
||||
"ruleset_id = {}",
|
||||
default_rule_set_id
|
||||
)
|
||||
);
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& e : l) {
|
||||
if (!SetRule(e.rule_name, e.rule_value, nullptr, false, reload)) {
|
||||
LogRulesDetail("Unable to interpret rule record for '{}'.", e.rule_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log(Logs::Detail, Logs::Rules, "Processing rule set '%s' (%d) load...", ruleset_name, ruleset_id);
|
||||
LogRulesDetail("Loading Rule Set {} ({}).", rule_set_name, rule_set_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()) {
|
||||
const auto& l = RuleValuesRepository::GetWhere(
|
||||
*db,
|
||||
fmt::format(
|
||||
"ruleset_id = {}",
|
||||
rule_set_id
|
||||
)
|
||||
);
|
||||
if (l.empty()) {
|
||||
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]);
|
||||
for (const auto& e : l) {
|
||||
if (!SetRule(e.rule_name, e.rule_value, nullptr, false, reload)) {
|
||||
LogRulesDetail("Unable to interpret Rule record for Rule '{}'.", e.rule_name);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
||||
|
||||
if (ruleset_name != nullptr) {
|
||||
//saving to a specific name
|
||||
if (m_activeName != ruleset_name) {
|
||||
//a new name...
|
||||
|
||||
m_activeRuleset = _FindOrCreateRuleset(database, ruleset_name);
|
||||
void RuleManager::SaveRules(Database *db, const std::string &rule_set_name) {
|
||||
if (!rule_set_name.empty()) {
|
||||
if (m_activeName != rule_set_name) {
|
||||
m_activeRuleset = _FindOrCreateRuleset(db, rule_set_name);
|
||||
if (m_activeRuleset == -1) {
|
||||
Log(Logs::Detail, Logs::Rules, "Unable to find or create rule set %s", ruleset_name);
|
||||
LogRulesDetail("Unable to find or create Rule Set {}.", rule_set_name);
|
||||
return;
|
||||
}
|
||||
m_activeName = ruleset_name;
|
||||
|
||||
m_activeName = rule_set_name;
|
||||
}
|
||||
Log(Logs::Detail, Logs::Rules, "Saving running rules into rule set %s (%d)", ruleset_name, m_activeRuleset);
|
||||
}
|
||||
else {
|
||||
Log(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset);
|
||||
|
||||
LogRulesDetail("Saving running rules into Rule Set {} ({}).", rule_set_name, m_activeRuleset);
|
||||
} else {
|
||||
LogRulesDetail("Saving running rules into running Rule Set {} ({}).", m_activeName, m_activeRuleset);
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < _IntRuleCount; i++) {
|
||||
_SaveRule(database, IntRule, i);
|
||||
_SaveRule(db, IntRule, i);
|
||||
}
|
||||
|
||||
for (i = 0; i < _RealRuleCount; i++) {
|
||||
_SaveRule(database, RealRule, i);
|
||||
_SaveRule(db, RealRule, i);
|
||||
}
|
||||
|
||||
for (i = 0; i < _BoolRuleCount; i++) {
|
||||
_SaveRule(database, BoolRule, i);
|
||||
_SaveRule(db, BoolRule, i);
|
||||
}
|
||||
}
|
||||
|
||||
void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
||||
char value_string[100];
|
||||
void RuleManager::_SaveRule(Database *db, RuleType type, uint16 index) {
|
||||
const auto rule_name = _GetRuleName(type, index);
|
||||
|
||||
if (type == IntRule && strcasecmp(_GetRuleName(type, index), "World:ExpansionSettings") == 0)
|
||||
return;
|
||||
if (type == BoolRule && strcasecmp(_GetRuleName(type, index), "World:UseClientBasedExpansionSettings") == 0)
|
||||
if (
|
||||
(type == BoolRule && Strings::EqualFold(rule_name, "World:UseClientBasedExpansionSettings")) ||
|
||||
(type == IntRule && Strings::EqualFold(rule_name, "World:ExpansionSettings"))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string rule_value;
|
||||
|
||||
switch (type) {
|
||||
case IntRule:
|
||||
sprintf(value_string, "%d", m_RuleIntValues[index]);
|
||||
rule_value = fmt::format("{}", m_RuleIntValues[index]);
|
||||
break;
|
||||
case RealRule:
|
||||
sprintf(value_string, "%.13f", m_RuleRealValues[index]);
|
||||
rule_value = fmt::format("{:.13f}", m_RuleRealValues[index]);
|
||||
break;
|
||||
case BoolRule:
|
||||
sprintf(value_string, "%s", m_RuleBoolValues[index] ? "true" : "false");
|
||||
rule_value = m_RuleBoolValues[index] ? "true" : "false";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string query = StringFormat(
|
||||
"REPLACE INTO `rule_values`"
|
||||
"(`ruleset_id`, `rule_name`, `rule_value`, `notes`)"
|
||||
" VALUES('%d', '%s', '%s', '%s')",
|
||||
const auto rule_notes = _GetRuleNotes(type, index);
|
||||
|
||||
const auto& l = RuleValuesRepository::GetWhere(
|
||||
*db,
|
||||
fmt::format(
|
||||
"ruleset_id = {} AND rule_name = '{}' LIMIT 1",
|
||||
m_activeRuleset,
|
||||
_GetRuleName(type, index),
|
||||
value_string,
|
||||
Strings::Escape(_GetRuleNotes(type, index)).c_str()
|
||||
rule_name
|
||||
)
|
||||
);
|
||||
|
||||
database->QueryDatabase(query);
|
||||
if (!l.empty()) {
|
||||
auto e = l[0];
|
||||
e.rule_value = rule_value;
|
||||
e.notes = rule_notes;
|
||||
|
||||
RuleValuesRepository::UpdateOne(*db, e);
|
||||
return;
|
||||
}
|
||||
|
||||
auto e = RuleValuesRepository::NewEntity();
|
||||
|
||||
e.ruleset_id = m_activeRuleset;
|
||||
e.rule_name = _GetRuleName(type, index);
|
||||
e.rule_value = rule_value;
|
||||
e.notes = rule_notes;
|
||||
|
||||
RuleValuesRepository::InsertOne(*db, e);
|
||||
}
|
||||
|
||||
bool RuleManager::UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update)
|
||||
bool RuleManager::UpdateInjectedRules(Database *db, const std::string &rule_set_name, bool quiet_update)
|
||||
{
|
||||
std::vector<std::string> database_data;
|
||||
std::map<std::string, std::pair<std::string, const std::string *>> rule_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) {
|
||||
if (rule_set_name.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int ruleset_id = GetRulesetID(db, ruleset_name);
|
||||
if (ruleset_id < 0) {
|
||||
const auto rule_set_id = RuleSetsRepository::GetRuleSetID(*db, rule_set_name);
|
||||
if (rule_set_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()) {
|
||||
const auto& v = RuleValuesRepository::GetRuleNames(*db, rule_set_id);
|
||||
if (v.empty()) {
|
||||
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) {
|
||||
for (const auto& r : s_RuleInfo) {
|
||||
if (Strings::EqualFold(r.name, "Invalid Rule")) {
|
||||
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;
|
||||
switch (r.type) {
|
||||
case IntRule:
|
||||
rule_data[r.name].first = fmt::format("{}", m_RuleIntValues[r.rule_index]);
|
||||
rule_data[r.name].second = &r.notes;
|
||||
break;
|
||||
case RealRule:
|
||||
rule_data[r.name].first = fmt::format("{:.13f}", m_RuleRealValues[r.rule_index]);
|
||||
rule_data[r.name].second = &r.notes;
|
||||
break;
|
||||
case BoolRule:
|
||||
rule_data[r.name].first = fmt::format("{}", m_RuleBoolValues[r.rule_index] ? "true" : "false");
|
||||
rule_data[r.name].second = &r.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()) {
|
||||
|
||||
for (const auto &d : rule_data) {
|
||||
if (std::find(v.begin(), v.end(), d.first) == v.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`
|
||||
Strings::Escape(*rd_iter.second.second) // `notes`
|
||||
rule_set_id,
|
||||
d.first,
|
||||
d.second.first,
|
||||
Strings::Escape(*d.second.second)
|
||||
)
|
||||
);
|
||||
|
||||
if (!quiet_update) {
|
||||
LogInfo(
|
||||
"Adding new rule [{}] ruleset [{}] ({}) value [{}]",
|
||||
rd_iter.first.c_str(),
|
||||
ruleset_name,
|
||||
ruleset_id,
|
||||
rd_iter.second.first.c_str()
|
||||
d.first,
|
||||
rule_set_name,
|
||||
rule_set_id,
|
||||
d.second.first
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (injected_rule_entries.size()) {
|
||||
|
||||
std::string query(
|
||||
fmt::format(
|
||||
"REPLACE INTO `rule_values`(`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}",
|
||||
Strings::ImplodePair(
|
||||
",",
|
||||
std::pair<char, char>('(', ')'),
|
||||
join_tuple(",", std::pair<char, char>('\'', '\''), injected_rule_entries)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if (!db->QueryDatabase(query).Success()) {
|
||||
if (!RuleValuesRepository::InjectRules(*db, injected_rule_entries)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
LogInfo(
|
||||
"[{}] New rule(s) added to ruleset [{}] [{}]",
|
||||
injected_rule_entries.size(),
|
||||
ruleset_name,
|
||||
ruleset_id
|
||||
rule_set_name,
|
||||
rule_set_id
|
||||
);
|
||||
}
|
||||
|
||||
@@ -491,50 +480,36 @@ 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()) {
|
||||
const auto& l = RuleValuesRepository::GetGroupedRules(*db);
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// build rule data entries
|
||||
for (const auto &ri_iter : s_RuleInfo) {
|
||||
if (strcasecmp(ri_iter.name, "Invalid Rule") == 0) {
|
||||
for (const auto &r : s_RuleInfo) {
|
||||
if (Strings::EqualFold(r.name, "Invalid Rule")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
rule_data.push_back(ri_iter.name);
|
||||
rule_data.push_back(r.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]));
|
||||
for (const auto& e : l) {
|
||||
const auto &d = std::find(rule_data.begin(), rule_data.end(), e);
|
||||
if (d == rule_data.end()) {
|
||||
orphaned_rule_entries.push_back(e);
|
||||
|
||||
if (!quiet_update) {
|
||||
LogInfo(
|
||||
"Rule [{}] no longer exists... Deleting orphaned entry from `rule_values` table...",
|
||||
row[0]
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (orphaned_rule_entries.size()) {
|
||||
|
||||
std::string query (
|
||||
fmt::format(
|
||||
"DELETE FROM `rule_values` WHERE `rule_name` IN ({})",
|
||||
Strings::ImplodePair(",", std::pair<char, char>('\'', '\''), orphaned_rule_entries)
|
||||
)
|
||||
);
|
||||
|
||||
if (!db->QueryDatabase(query).Success()) {
|
||||
if (!RuleValuesRepository::DeleteOrphanedRules(*db, orphaned_rule_entries)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -546,139 +521,83 @@ bool RuleManager::UpdateOrphanedRules(Database *db, bool quiet_update)
|
||||
|
||||
bool RuleManager::RestoreRuleNotes(Database *db)
|
||||
{
|
||||
std::string query("SELECT `ruleset_id`, `rule_name`, `notes` FROM `rule_values`");
|
||||
|
||||
auto results = db->QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
const auto& l = RuleValuesRepository::All(*db);
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int update_count = 0;
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
|
||||
auto rule = [](const char *rule_name) {
|
||||
for (const auto& e : l) {
|
||||
|
||||
auto rule = [](std::string rule_name) {
|
||||
for (auto rule_iter : s_RuleInfo) {
|
||||
if (strcasecmp(rule_iter.name, rule_name) == 0) {
|
||||
if (Strings::EqualFold(rule_iter.name, rule_name)) {
|
||||
return rule_iter;
|
||||
}
|
||||
}
|
||||
|
||||
return s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount];
|
||||
}(row[1]);
|
||||
return s_RuleInfo[_IntRuleCount + _RealRuleCount + _BoolRuleCount];
|
||||
}(e.rule_name);
|
||||
|
||||
if (strcasecmp(rule.name, row[1]) != 0) {
|
||||
if (Strings::Contains(rule.name, e.rule_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (row[2] != nullptr && rule.notes.compare(row[2]) == 0) {
|
||||
if (!e.notes.empty() && !rule.notes.compare(e.notes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string query(
|
||||
fmt::format(
|
||||
"UPDATE `rule_values` SET `notes` = '{}' WHERE `ruleset_id` = '{}' AND `rule_name` = '{}'",
|
||||
Strings::Escape(rule.notes),
|
||||
row[0],
|
||||
row[1]
|
||||
)
|
||||
);
|
||||
|
||||
if (!db->QueryDatabase(query).Success()) {
|
||||
if (!RuleValuesRepository::UpdateRuleNote(*db, e.ruleset_id, e.rule_name, rule.notes)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
++update_count;
|
||||
}
|
||||
|
||||
if (update_count > 0) {
|
||||
LogInfo("[{}] Rule Note [{}] Restored", update_count, (update_count == 1 ? "" : "s"));
|
||||
if (update_count) {
|
||||
LogInfo("[{}] Rule Note{} Restored", update_count, update_count != 1 ? "s" : "");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int RuleManager::GetRulesetID(Database *database, const char *ruleset_name) {
|
||||
int RuleManager::_FindOrCreateRuleset(Database *db, const std::string &rule_set_name)
|
||||
{
|
||||
const auto rule_set_id = RuleSetsRepository::GetRuleSetID(*db, rule_set_name);
|
||||
if (rule_set_id >= 0) {
|
||||
return rule_set_id;
|
||||
}
|
||||
|
||||
uint32 len = static_cast<uint32>(strlen(ruleset_name));
|
||||
auto rst = new char[2 * len + 1];
|
||||
database->DoEscapeString(rst, ruleset_name, len);
|
||||
|
||||
std::string query = StringFormat("SELECT ruleset_id FROM rule_sets WHERE name='%s'", rst);
|
||||
safe_delete_array(rst);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return -1;
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return -1;
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return atoi(row[0]);
|
||||
return RuleSetsRepository::CreateNewRuleSet(*db, rule_set_name);
|
||||
}
|
||||
|
||||
int RuleManager::_FindOrCreateRuleset(Database *database, const char *in_ruleset_name) {
|
||||
bool RuleManager::ListRulesets(Database *db, std::map<int, std::string> &m)
|
||||
{
|
||||
m[0] = "default";
|
||||
|
||||
int ruleset_id = GetRulesetID(database, in_ruleset_name);
|
||||
if (ruleset_id >= 0)
|
||||
return ruleset_id; //found and existing one...
|
||||
|
||||
uint32 len = strlen(in_ruleset_name);
|
||||
auto ruleset_name = new char[2 * len + 1];
|
||||
database->DoEscapeString(ruleset_name, in_ruleset_name, len);
|
||||
|
||||
std::string query = StringFormat("INSERT INTO rule_sets (ruleset_id, name) VALUES(0, '%s')", ruleset_name);
|
||||
safe_delete_array(ruleset_name);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return -1;
|
||||
|
||||
return results.LastInsertedID();
|
||||
}
|
||||
|
||||
std::string RuleManager::GetRulesetName(Database *database, int ruleset_id) {
|
||||
std::string query = StringFormat("SELECT name FROM rule_sets WHERE ruleset_id=%d", ruleset_id);
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (!results.Success())
|
||||
return "";
|
||||
|
||||
if (results.RowCount() == 0)
|
||||
return "";
|
||||
|
||||
auto row = results.begin();
|
||||
|
||||
return row[0];
|
||||
}
|
||||
|
||||
bool RuleManager::ListRulesets(Database *database, std::map<int, std::string> &into) {
|
||||
|
||||
//start out with the default set which is always present.
|
||||
into[0] = "default";
|
||||
|
||||
std::string query = "SELECT ruleset_id, name FROM rule_sets";
|
||||
auto results = database->QueryDatabase(query);
|
||||
if (results.Success())
|
||||
const auto& l = RuleSetsRepository::All(*db);
|
||||
if (l.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row)
|
||||
into[atoi(row[0])] = row[1];
|
||||
for (const auto& e : l) {
|
||||
m[e.ruleset_id] = e.name;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int32 RuleManager::GetIntRule(RuleManager::IntType t) const
|
||||
int RuleManager::GetIntRule(RuleManager::IntType t) const
|
||||
{
|
||||
return (m_RuleIntValues[t]);
|
||||
return m_RuleIntValues[t];
|
||||
}
|
||||
|
||||
float RuleManager::GetRealRule(RuleManager::RealType t) const
|
||||
{
|
||||
return (m_RuleRealValues[t]);
|
||||
return m_RuleRealValues[t];
|
||||
}
|
||||
|
||||
bool RuleManager::GetBoolRule(RuleManager::BoolType t) const
|
||||
{
|
||||
return (m_RuleBoolValues[t] == 1);
|
||||
return m_RuleBoolValues[t] == 1;
|
||||
}
|
||||
|
||||
|
||||
+73
-65
@@ -29,12 +29,12 @@
|
||||
//note, these macros assume there is always a RuleManager *rules in scope,
|
||||
//which makes it a global for now, but with instancing we will do exactly
|
||||
//what we do with the zone global and just make it a member of core classes
|
||||
#define RuleI(cat, rule) \
|
||||
RuleManager::Instance()->GetIntRule( RuleManager::Int__##rule )
|
||||
#define RuleR(cat, rule) \
|
||||
RuleManager::Instance()->GetRealRule( RuleManager::Real__##rule )
|
||||
#define RuleB(cat, rule) \
|
||||
RuleManager::Instance()->GetBoolRule( RuleManager::Bool__##rule )
|
||||
#define RuleI(category_name, rule_name) \
|
||||
RuleManager::Instance()->GetIntRule( RuleManager::Int__##rule_name )
|
||||
#define RuleR(category_name, rule_name) \
|
||||
RuleManager::Instance()->GetRealRule( RuleManager::Real__##rule_name )
|
||||
#define RuleB(category_name, rule_name) \
|
||||
RuleManager::Instance()->GetBoolRule( RuleManager::Bool__##rule_name )
|
||||
|
||||
|
||||
#include <vector>
|
||||
@@ -49,91 +49,101 @@ class RuleManager {
|
||||
public:
|
||||
//generate our rule enums:
|
||||
typedef enum {
|
||||
#define RULE_INT(cat, rule, default_value, notes) \
|
||||
Int__##rule,
|
||||
#include "ruletypes.h"
|
||||
#define RULE_INT(category_name, rule_name, default_value, notes) \
|
||||
Int__##rule_name,
|
||||
|
||||
#include "ruletypes.h"
|
||||
|
||||
_IntRuleCount
|
||||
} IntType;
|
||||
|
||||
typedef enum {
|
||||
#define RULE_REAL(cat, rule, default_value, notes) \
|
||||
Real__##rule,
|
||||
#include "ruletypes.h"
|
||||
#define RULE_REAL(category_name, rule_name, default_value, notes) \
|
||||
Real__##rule_name,
|
||||
|
||||
#include "ruletypes.h"
|
||||
|
||||
_RealRuleCount
|
||||
} RealType;
|
||||
|
||||
typedef enum {
|
||||
#define RULE_BOOL(cat, rule, default_value, notes) \
|
||||
Bool__##rule,
|
||||
#include "ruletypes.h"
|
||||
#define RULE_BOOL(category_name, rule_name, default_value, notes) \
|
||||
Bool__##rule_name,
|
||||
|
||||
#include "ruletypes.h"
|
||||
|
||||
_BoolRuleCount
|
||||
} BoolType;
|
||||
|
||||
typedef enum {
|
||||
#define RULE_CATEGORY(catname) \
|
||||
Category__##catname,
|
||||
#include "ruletypes.h"
|
||||
#define RULE_CATEGORY(category_name) \
|
||||
Category__##category_name,
|
||||
|
||||
#include "ruletypes.h"
|
||||
|
||||
_CatCount
|
||||
} CategoryType;
|
||||
|
||||
static RuleManager* Instance() {
|
||||
static RuleManager *Instance()
|
||||
{
|
||||
static RuleManager rules;
|
||||
return &rules;
|
||||
}
|
||||
|
||||
static const IntType InvalidInt = _IntRuleCount;
|
||||
static const RealType InvalidReal = _RealRuleCount;
|
||||
static const BoolType InvalidBool = _BoolRuleCount;
|
||||
static const IntType InvalidInt = _IntRuleCount;
|
||||
static const RealType InvalidReal = _RealRuleCount;
|
||||
static const BoolType InvalidBool = _BoolRuleCount;
|
||||
static const CategoryType InvalidCategory = _CatCount;
|
||||
|
||||
static const uint32 _RulesCount = _IntRuleCount+_RealRuleCount+_BoolRuleCount;
|
||||
static const uint32 _RulesCount = _IntRuleCount + _RealRuleCount + _BoolRuleCount;
|
||||
|
||||
//fetch routines, you should generally use the Rule* macros instead of this
|
||||
int32 GetIntRule (IntType t) const;
|
||||
int GetIntRule(IntType t) const;
|
||||
float GetRealRule(RealType t) const;
|
||||
bool GetBoolRule(BoolType t) const;
|
||||
|
||||
//management routines
|
||||
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(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 CategoryType FindCategory(const char *catname);
|
||||
bool ListRules(const char *catname, std::vector<const char *> &into);
|
||||
bool ListCategories(std::vector<const char *> &into);
|
||||
bool GetRule(const char *rule_name, std::string &ret_val);
|
||||
bool SetRule(const char *rule_name, const char *rule_value, Database *db = nullptr, bool db_save = false, bool reload = false);
|
||||
static std::string GetRuleName(IntType t) { return s_RuleInfo[t].name; }
|
||||
static std::string GetRuleName(RealType t) { return s_RuleInfo[t + _IntRuleCount].name; }
|
||||
static std::string 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 CategoryType FindCategory(const std::string &category_name);
|
||||
bool ListRules(const std::string &category_name, std::vector <std::string> &l);
|
||||
bool ListCategories(std::vector <std::string> &l);
|
||||
bool GetRule(const std::string &rule_name, std::string &rule_value);
|
||||
bool SetRule(
|
||||
const std::string &rule_name,
|
||||
const std::string &rule_value,
|
||||
Database *db = nullptr,
|
||||
bool db_save = false,
|
||||
bool reload = false
|
||||
);
|
||||
|
||||
int GetActiveRulesetID() const { return(m_activeRuleset); }
|
||||
const char *GetActiveRuleset() const { return(m_activeName.c_str()); }
|
||||
static int GetRulesetID(Database *db, const char *rulesetname);
|
||||
static std::string GetRulesetName(Database *db, int id);
|
||||
static bool ListRulesets(Database *db, std::map<int, std::string> &into);
|
||||
int GetActiveRulesetID() const { return m_activeRuleset; }
|
||||
std::string GetActiveRuleset() const { return m_activeName; }
|
||||
static bool ListRulesets(Database *db, std::map<int, std::string> &l);
|
||||
|
||||
void ResetRules(bool reload = false);
|
||||
bool LoadRules(Database *db, const char *ruleset = nullptr, bool reload = false);
|
||||
void SaveRules(Database *db, const char *ruleset = nullptr);
|
||||
bool UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update = false);
|
||||
bool LoadRules(Database *db, const std::string &rule_set_name, bool reload = false);
|
||||
void SaveRules(Database *db, const std::string &rule_set_name);
|
||||
bool UpdateInjectedRules(Database *db, const std::string &rule_set_name, bool quiet_update = false);
|
||||
bool UpdateOrphanedRules(Database *db, bool quiet_update = false);
|
||||
bool RestoreRuleNotes(Database *db);
|
||||
|
||||
private:
|
||||
RuleManager();
|
||||
RuleManager(const RuleManager&);
|
||||
const RuleManager& operator=(const RuleManager&);
|
||||
RuleManager(const RuleManager &);
|
||||
const RuleManager &operator=(const RuleManager &);
|
||||
|
||||
int m_activeRuleset;
|
||||
int m_activeRuleset;
|
||||
std::string m_activeName;
|
||||
#ifdef WIN64
|
||||
uint32 m_RuleIntValues [_IntRuleCount ];
|
||||
#else
|
||||
int m_RuleIntValues [_IntRuleCount ];
|
||||
#endif
|
||||
float m_RuleRealValues[_RealRuleCount];
|
||||
uint32 m_RuleBoolValues[_BoolRuleCount];
|
||||
|
||||
int m_RuleIntValues[_IntRuleCount];
|
||||
float m_RuleRealValues[_RealRuleCount];
|
||||
uint32 m_RuleBoolValues[_BoolRuleCount];
|
||||
|
||||
typedef enum {
|
||||
IntRule,
|
||||
@@ -141,23 +151,21 @@ private:
|
||||
BoolRule
|
||||
} RuleType;
|
||||
|
||||
static bool _FindRule(const char *rule_name, RuleType &type_into, uint16 &index_into);
|
||||
static const char *_GetRuleName(RuleType type, uint16 index);
|
||||
static bool _FindRule(const std::string &rule_name, RuleType &type_into, uint16 &index_into);
|
||||
static std::string _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 std::string &rule_set_name);
|
||||
void _SaveRule(Database *db, RuleType type, uint16 index);
|
||||
|
||||
static const char *s_categoryNames[];
|
||||
|
||||
static const char* s_categoryNames[];
|
||||
typedef struct {
|
||||
const char *name;
|
||||
CategoryType category;
|
||||
RuleType type;
|
||||
uint16 rule_index; //index into its 'type' array
|
||||
std::string name;
|
||||
CategoryType category;
|
||||
RuleType type;
|
||||
uint16 rule_index;
|
||||
const std::string notes;
|
||||
} RuleInfo;
|
||||
static const RuleInfo s_RuleInfo[];
|
||||
|
||||
};
|
||||
|
||||
#endif /*RULESYS_H_*/
|
||||
|
||||
|
||||
@@ -721,3 +721,20 @@ uint32 Strings::TimeToSeconds(std::string time_string)
|
||||
|
||||
return duration;
|
||||
}
|
||||
|
||||
bool Strings::ToBool(std::string bool_string)
|
||||
{
|
||||
if (
|
||||
Strings::Contains(bool_string, "true") ||
|
||||
Strings::Contains(bool_string, "y") ||
|
||||
Strings::Contains(bool_string, "yes") ||
|
||||
Strings::Contains(bool_string, "on") ||
|
||||
Strings::Contains(bool_string, "enable") ||
|
||||
Strings::Contains(bool_string, "enabled") ||
|
||||
(Strings::IsNumber(bool_string) && std::stoi(bool_string))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -110,6 +110,8 @@ public:
|
||||
static std::vector<std::string> Wrap(std::vector<std::string> &src, std::string character);
|
||||
static void FindReplace(std::string &string_subject, const std::string &search_string, const std::string &replace_string);
|
||||
static uint32 TimeToSeconds(std::string time_string);
|
||||
static bool ToBool(std::string bool_string);
|
||||
static inline bool EqualFold(const std::string &string_one, const std::string &string_two) { return strcasecmp(string_one.c_str(), string_two.c_str()) == 0; }
|
||||
|
||||
template<typename T>
|
||||
static std::string
|
||||
|
||||
Reference in New Issue
Block a user