mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
Updated the rule system to automatically restore rule notes (rule-based)
This commit is contained in:
parent
f9536f9621
commit
c1b48b9931
@ -1,5 +1,11 @@
|
|||||||
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 ==
|
== 9/02/2019 ==
|
||||||
Uleat: Added code to inject new rules into the 'default' ruleset and remove orphaned rules from all rulesets
|
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
|
- New rules are only added using the 'default' ruleset - Other rulesets will need to be added manually or through in-game updates
|
||||||
|
|||||||
@ -215,15 +215,17 @@ bool RuleManager::_FindRule(const char *rule_name, RuleType &type_into, uint16 &
|
|||||||
//assumes index is valid!
|
//assumes index is valid!
|
||||||
const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
const char *RuleManager::_GetRuleName(RuleType type, uint16 index) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
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!
|
//assumes index is valid!
|
||||||
@ -232,12 +234,14 @@ const std::string &RuleManager::_GetRuleNotes(RuleType type, uint16 index) {
|
|||||||
case IntRule:
|
case IntRule:
|
||||||
return(s_RuleInfo[index].notes);
|
return(s_RuleInfo[index].notes);
|
||||||
case RealRule:
|
case RealRule:
|
||||||
return(s_RuleInfo[index + _IntRuleCount].notes);
|
return(s_RuleInfo[index+_IntRuleCount].notes);
|
||||||
case BoolRule:
|
case BoolRule:
|
||||||
return(s_RuleInfo[index + _IntRuleCount + _RealRuleCount].notes);
|
return(s_RuleInfo[index+_IntRuleCount+_RealRuleCount].notes);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
//should never happen
|
//should never happen
|
||||||
return(std::string());
|
return(s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount].notes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool reload) {
|
||||||
@ -304,12 +308,8 @@ bool RuleManager::LoadRules(Database *database, const char *ruleset_name, bool r
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert this to a single REPLACE query (it can handle it - currently at 608 rules)
|
|
||||||
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
||||||
// tbh, UpdateRules() can probably be called since it will handle deletions of
|
|
||||||
// orphaned entries of existing rulesets as well as adding the new ones
|
|
||||||
// (it already does it as a single REPLACE query)
|
|
||||||
|
|
||||||
if (ruleset_name != nullptr) {
|
if (ruleset_name != nullptr) {
|
||||||
//saving to a specific name
|
//saving to a specific name
|
||||||
if (m_activeName != ruleset_name) {
|
if (m_activeName != ruleset_name) {
|
||||||
@ -328,10 +328,6 @@ void RuleManager::SaveRules(Database *database, const char *ruleset_name) {
|
|||||||
Log(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset);
|
Log(Logs::Detail, Logs::Rules, "Saving running rules into running rule set %s", m_activeName.c_str(), m_activeRuleset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this should be all that is needed..with the exception of handling expansion-based rules...
|
|
||||||
// (those really need to be put somewhere else - probably variables)
|
|
||||||
//UpdateRules(database, m_activeName.c_str(), m_activeRuleset, true);
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < _IntRuleCount; i++) {
|
for (i = 0; i < _IntRuleCount; i++) {
|
||||||
_SaveRule(database, IntRule, i);
|
_SaveRule(database, IntRule, i);
|
||||||
@ -377,11 +373,6 @@ void RuleManager::_SaveRule(Database *database, RuleType type, uint16 index) {
|
|||||||
database->QueryDatabase(query);
|
database->QueryDatabase(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleManager::UpdateChangedRules(Database *db, const char *ruleset_name, bool quiet_update)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RuleManager::UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update)
|
bool RuleManager::UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update)
|
||||||
{
|
{
|
||||||
std::vector<std::string> database_data;
|
std::vector<std::string> database_data;
|
||||||
@ -472,11 +463,33 @@ bool RuleManager::UpdateInjectedRules(Database *db, const char *ruleset_name, bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (injected_rule_entries.size()) {
|
if (injected_rule_entries.size()) {
|
||||||
return _UpdateRules(db, ruleset_name, ruleset_id, injected_rule_entries, std::vector<std::string>());
|
|
||||||
}
|
std::string query(
|
||||||
else {
|
fmt::format(
|
||||||
return true;
|
"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)
|
bool RuleManager::UpdateOrphanedRules(Database *db, bool quiet_update)
|
||||||
@ -524,113 +537,83 @@ bool RuleManager::UpdateOrphanedRules(Database *db, bool quiet_update)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (orphaned_rule_entries.size()) {
|
if (orphaned_rule_entries.size()) {
|
||||||
return _UpdateRules(
|
|
||||||
db,
|
std::string query (
|
||||||
"All Rulesets",
|
fmt::format(
|
||||||
-1,
|
"DELETE FROM `rule_values` WHERE `rule_name` IN ({})",
|
||||||
std::vector<std::tuple<int, std::string, std::string, std::string>>(),
|
implode(",", std::pair<char, char>('\'', '\''), orphaned_rule_entries)
|
||||||
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")
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RuleManager::_UpdateRules(
|
bool RuleManager::RestoreRuleNotes(Database *db)
|
||||||
Database *db,
|
|
||||||
const char *ruleset_name,
|
|
||||||
const int ruleset_id,
|
|
||||||
const std::vector<std::tuple<int, std::string, std::string, std::string>> &injected,
|
|
||||||
const std::vector<std::string> &orphaned
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
bool return_value = true;
|
|
||||||
|
|
||||||
if (!db) {
|
if (!db) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ruleset_name == nullptr) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (injected.size()) {
|
int update_count = 0;
|
||||||
|
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||||
|
|
||||||
if (ruleset_id >= 0 && strcasecmp(ruleset_name, "All Rulesets") != 0) {
|
const auto &rule = [&row]() {
|
||||||
|
|
||||||
std::string query(
|
for (const auto &rule_iter : s_RuleInfo) {
|
||||||
fmt::format(
|
if (strcasecmp(rule_iter.name, row[1]) == 0) {
|
||||||
"REPLACE INTO `rule_values`(`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}",
|
return rule_iter;
|
||||||
implode(
|
}
|
||||||
",",
|
|
||||||
std::pair<char, char>('(', ')'),
|
|
||||||
join_tuple(",", std::pair<char, char>('\'', '\''), injected)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!db->QueryDatabase(query).Success()) {
|
|
||||||
return_value = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log(Logs::General,
|
|
||||||
Logs::Status,
|
|
||||||
"%u New Command%s Added to ruleset '%s' (%i)",
|
|
||||||
injected.size(),
|
|
||||||
(injected.size() == 1 ? "" : "s"),
|
|
||||||
ruleset_name,
|
|
||||||
ruleset_id
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return s_RuleInfo[_IntRuleCount+_RealRuleCount+_BoolRuleCount];
|
||||||
|
}();
|
||||||
|
|
||||||
|
if (strcasecmp(rule.name, row[1]) != 0) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return_value = false;
|
if (rule.notes.compare(row[2]) == 0) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (orphaned.size()) {
|
std::string query(
|
||||||
|
StringFormat(
|
||||||
|
"UPDATE `rule_values` SET `notes` = '%s' WHERE `ruleset_id` = '%i' AND `rule_name` = '%s'",
|
||||||
|
rule.notes.c_str(),
|
||||||
|
atoi(row[0]),
|
||||||
|
row[1]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
std::string query;
|
if (!db->QueryDatabase(query).Success()) {
|
||||||
|
continue;
|
||||||
if (ruleset_id < 0 && strcasecmp(ruleset_name, "All Rulesets") == 0) {
|
|
||||||
|
|
||||||
query = fmt::format(
|
|
||||||
"DELETE FROM `rule_values` WHERE `rule_name` IN ({})",
|
|
||||||
implode(",", std::pair<char, char>('\'', '\''), orphaned)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (ruleset_id >= 0 && strcasecmp(ruleset_name, "All Rulesets") != 0) {
|
|
||||||
|
|
||||||
query = fmt::format(
|
|
||||||
"DELETE FROM `rule_values` WHERE `ruleset_id` = '%i' AND `rule_name` IN ({})",
|
|
||||||
ruleset_id,
|
|
||||||
implode(",", std::pair<char, char>('\'', '\''), orphaned)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (query.size() > 0) {
|
++update_count;
|
||||||
|
|
||||||
if (!db->QueryDatabase(query).Success()) {
|
|
||||||
return_value = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Log(Logs::General,
|
|
||||||
Logs::Status,
|
|
||||||
"%u Orphaned Command%s Deleted from ruleset '%s' (%i)",
|
|
||||||
orphaned.size(),
|
|
||||||
(orphaned.size() == 1 ? "" : "s"),
|
|
||||||
ruleset_name,
|
|
||||||
ruleset_id
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return_value = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return return_value;
|
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) {
|
||||||
|
|||||||
@ -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,9 +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 UpdateChangedRules(Database *db, const char *ruleset_name, bool quiet_update = false);
|
|
||||||
bool UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update = false);
|
bool UpdateInjectedRules(Database *db, const char *ruleset_name, bool quiet_update = false);
|
||||||
bool UpdateOrphanedRules(Database *db, bool quiet_update = false);
|
bool UpdateOrphanedRules(Database *db, bool quiet_update = false);
|
||||||
|
bool RestoreRuleNotes(Database *db);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RuleManager();
|
RuleManager();
|
||||||
@ -143,21 +146,14 @@ private:
|
|||||||
static const std::string &_GetRuleNotes(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);
|
||||||
bool _UpdateRules(
|
|
||||||
Database *db,
|
|
||||||
const char *ruleset_name,
|
|
||||||
const int ruleset_id,
|
|
||||||
const std::vector<std::tuple<int, std::string, std::string, std::string>> &injected,
|
|
||||||
const std::vector<std::string> &orphaned
|
|
||||||
);
|
|
||||||
|
|
||||||
static const char *s_categoryNames[];
|
static const char *s_categoryNames[];
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
CategoryType category;
|
CategoryType category;
|
||||||
RuleType type;
|
RuleType type;
|
||||||
uint16 rule_index; //index into its 'type' array
|
uint16 rule_index; //index into its 'type' array
|
||||||
std::string notes;
|
const std::string notes;
|
||||||
} RuleInfo;
|
} RuleInfo;
|
||||||
static const RuleInfo s_RuleInfo[];
|
static const RuleInfo s_RuleInfo[];
|
||||||
|
|
||||||
|
|||||||
@ -241,6 +241,7 @@ RULE_BOOL(World, MaxClientsSimplifiedLogic, false, "New logic that only uses Exe
|
|||||||
RULE_INT (World, TellQueueSize, 20, "")
|
RULE_INT (World, TellQueueSize, 20, "")
|
||||||
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true, "Should the start zone ALWAYS be the same location as your bind?")
|
RULE_BOOL(World, StartZoneSameAsBindOnCreation, true, "Should the start zone ALWAYS be the same location as your bind?")
|
||||||
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "")
|
RULE_BOOL(World, EnforceCharacterLimitAtLogin, false, "")
|
||||||
|
RULE_BOOL(World, RestoreRuleNotes, false, "Restores all database rule entry notes to their original text")
|
||||||
RULE_CATEGORY_END()
|
RULE_CATEGORY_END()
|
||||||
|
|
||||||
RULE_CATEGORY(Zone)
|
RULE_CATEGORY(Zone)
|
||||||
|
|||||||
@ -335,13 +335,13 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
//rules:
|
//rules:
|
||||||
{
|
{
|
||||||
if (!RuleManager::Instance()->UpdateInjectedRules(&database, "default")) {
|
|
||||||
Log(Logs::General, Logs::World_Server, "Failed to process 'Injected Rules' for ruleset 'default' update operation.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) {
|
if (!RuleManager::Instance()->UpdateOrphanedRules(&database)) {
|
||||||
Log(Logs::General, Logs::World_Server, "Failed to process 'Orphaned Rules' update operation.");
|
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)) {
|
||||||
@ -361,6 +361,10 @@ int main(int argc, char** argv) {
|
|||||||
Log(Logs::General, Logs::World_Server, "Loaded default rule set 'default'", tmp.c_str());
|
Log(Logs::General, Logs::World_Server, "Loaded default rule set 'default'", tmp.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RuleB(World, RestoreRuleNotes) && !RuleManager::Instance()->RestoreRuleNotes(&database)) {
|
||||||
|
Log(Logs::General, Logs::World_Server, "Failed to process 'Restore Rule Notes' update operation.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EQEmu::InitializeDynamicLookups();
|
EQEmu::InitializeDynamicLookups();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user