From 31ad0da8118d444a7ad40f985033c61ecdc29060 Mon Sep 17 00:00:00 2001 From: Randy Girard Date: Sun, 6 Mar 2022 23:02:57 -0500 Subject: [PATCH] [Content Filtering] Updates contents flags to be checked at runtime. (#1940) * Updates contents flags to be checked at runtime. * Fix formatting * Add expansion flags * Tweaks to logic * Logic tweaks * Update world_content_service.cpp * Inverse DoesPassContentFiltering logic * Update world_content_service.cpp * Update world_content_service.cpp Co-authored-by: Akkadius --- common/content/world_content_service.cpp | 45 ++++++++++++++++++++++++ common/content/world_content_service.h | 4 +++ common/loottable.h | 19 +++++++--- common/shareddb.cpp | 24 +++++++++++-- common/string_util.cpp | 7 +++- common/string_util.h | 1 + zone/loottables.cpp | 12 +++++-- 7 files changed, 102 insertions(+), 10 deletions(-) diff --git a/common/content/world_content_service.cpp b/common/content/world_content_service.cpp index c869d486a..381bf5dc1 100644 --- a/common/content/world_content_service.cpp +++ b/common/content/world_content_service.cpp @@ -22,6 +22,7 @@ #include "../database.h" #include "../rulesys.h" #include "../eqemu_logsys.h" +#include "../loottable.h" #include "../repositories/content_flags_repository.h" @@ -139,6 +140,50 @@ bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag) return false; } +/** + * @param content_flag + * @return + */ +bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag) +{ + for (auto &f: GetContentFlags()) { + if (f.flag_name == content_flag && f.enabled == false) { + return true; + } + } + + return false; +} + +bool WorldContentService::DoesPassContentFiltering(const ContentFlags &f) +{ + // if we're not set to (-1 All) then fail when we aren't within minimum expansion + if (f.min_expansion > Expansion::EXPANSION_ALL && current_expansion < f.min_expansion) { + return false; + } + + // if we're not set to (-1 All) then fail when we aren't within max expansion + if (f.max_expansion > Expansion::EXPANSION_ALL && current_expansion > f.max_expansion) { + return false; + } + + // if we don't have any enabled flag in enabled flags, we fail + for (const auto& flag: SplitString(f.content_flags)) { + if (!contains(GetContentFlagsEnabled(), flag)) { + return false; + } + } + + // if we don't have any disabled flag in disabled flags, we fail + for (const auto& flag: SplitString(f.content_flags_disabled)) { + if (!contains(GetContentFlagsDisabled(), flag)) { + return false; + } + } + + return true; +} + void WorldContentService::ReloadContentFlags() { std::vector set_content_flags; diff --git a/common/content/world_content_service.h b/common/content/world_content_service.h index 512f2c92c..03ea8b2dc 100644 --- a/common/content/world_content_service.h +++ b/common/content/world_content_service.h @@ -23,6 +23,7 @@ #include #include +#include "../loottable.h" #include "../repositories/content_flags_repository.h" class Database; @@ -165,10 +166,13 @@ public: std::vector GetContentFlagsEnabled(); std::vector GetContentFlagsDisabled(); bool IsContentFlagEnabled(const std::string& content_flag); + bool IsContentFlagDisabled(const std::string& content_flag); void SetContentFlags(std::vector content_flags); void ReloadContentFlags(); WorldContentService * SetExpansionContext(); + bool DoesPassContentFiltering(const ContentFlags& f); + WorldContentService * SetDatabase(Database *database); Database *GetDatabase() const; diff --git a/common/loottable.h b/common/loottable.h index 2b9a13926..c46fe0634 100644 --- a/common/loottable.h +++ b/common/loottable.h @@ -30,11 +30,19 @@ struct LootTableEntries_Struct { float probability; }; +struct ContentFlags { + int16 min_expansion; + int16 max_expansion; + char content_flags[100]; + char content_flags_disabled[100]; +}; + struct LootTable_Struct { - uint32 mincash; - uint32 maxcash; - uint32 avgcoin; - uint32 NumEntries; + uint32 mincash; + uint32 maxcash; + uint32 avgcoin; + uint32 NumEntries; + ContentFlags content_flags; LootTableEntries_Struct Entries[0]; }; @@ -51,7 +59,8 @@ struct LootDropEntries_Struct { }; struct LootDrop_Struct { - uint32 NumEntries; + uint32 NumEntries; + ContentFlags content_flags; LootDropEntries_Struct Entries[0]; }; #pragma pack() diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 7f913edf3..2cc1d8c15 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -2079,7 +2079,11 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) { loottable_entries.multiplier, loottable_entries.droplimit, loottable_entries.mindrop, - loottable_entries.probability + loottable_entries.probability, + loottable.min_expansion, + loottable.max_expansion, + loottable.content_flags, + loottable.content_flags_disabled FROM loottable LEFT JOIN loottable_entries ON loottable.id = loottable_entries.loottable_id @@ -2114,6 +2118,12 @@ void SharedDatabase::LoadLootTables(void *data, uint32 size) { lt->mincash = static_cast(atoul(row[1])); lt->maxcash = static_cast(atoul(row[2])); lt->avgcoin = static_cast(atoul(row[3])); + + lt->content_flags.min_expansion = static_cast(atoi(row[9])); + lt->content_flags.max_expansion = static_cast(atoi(row[10])); + + strn0cpy(lt->content_flags.content_flags, row[11], sizeof(lt->content_flags.content_flags)); + strn0cpy(lt->content_flags.content_flags_disabled, row[12], sizeof(lt->content_flags.content_flags_disabled)); } if (current_entry > 128) { @@ -2162,7 +2172,11 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { lootdrop_entries.trivial_max_level, lootdrop_entries.npc_min_level, lootdrop_entries.npc_max_level, - lootdrop_entries.multiplier + lootdrop_entries.multiplier, + lootdrop.min_expansion, + lootdrop.max_expansion, + lootdrop.content_flags, + lootdrop.content_flags_disabled FROM lootdrop JOIN lootdrop_entries ON lootdrop.id = lootdrop_entries.lootdrop_id @@ -2195,6 +2209,12 @@ void SharedDatabase::LoadLootDrops(void *data, uint32 size) { memset(loot_drop, 0, sizeof(LootDrop_Struct) + (sizeof(LootDropEntries_Struct) * 1260)); current_entry = 0; current_id = id; + + p_loot_drop_struct->content_flags.min_expansion = static_cast(atoi(row[10])); + p_loot_drop_struct->content_flags.max_expansion = static_cast(atoi(row[11])); + + strn0cpy(p_loot_drop_struct->content_flags.content_flags, row[12], sizeof(p_loot_drop_struct->content_flags.content_flags)); + strn0cpy(p_loot_drop_struct->content_flags.content_flags_disabled, row[13], sizeof(p_loot_drop_struct->content_flags.content_flags_disabled)); } if (current_entry >= 1260) { diff --git a/common/string_util.cpp b/common/string_util.cpp index fe392aedd..e9efceaf9 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -1021,6 +1021,11 @@ std::vector GetBadWords() }; } +bool contains(std::vector container, std::string element) +{ + return std::find(container.begin(), container.end(), element) != container.end(); +} + std::string ConvertSecondsToTime(int duration, bool is_milliseconds) { if (duration <= 0) { @@ -1259,4 +1264,4 @@ std::string ConvertMoneyToString(uint32 platinum, uint32 gold, uint32 silver, ui ); } return money_string; -} \ No newline at end of file +} diff --git a/common/string_util.h b/common/string_util.h index f6b7e35ce..6ec211835 100644 --- a/common/string_util.h +++ b/common/string_util.h @@ -218,6 +218,7 @@ void SanitizeWorldServerName(char *name); std::string SanitizeWorldServerName(std::string server_long_name); std::string repeat(std::string s, int n); std::vector GetBadWords(); +bool contains(std::vector container, std::string element); template auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result) diff --git a/zone/loottables.cpp b/zone/loottables.cpp index 5c3259502..d83557a93 100644 --- a/zone/loottables.cpp +++ b/zone/loottables.cpp @@ -51,8 +51,13 @@ void ZoneDatabase::AddLootTableToNPC(NPC* npc,uint32 loottable_id, ItemList* ite } lts = database.GetLootTable(loottable_id); - if (!lts) + if (!lts) { return; + } + + if (!content_service.DoesPassContentFiltering(lts->content_flags)) { + return; + } uint32 min_cash = lts->mincash; uint32 max_cash = lts->maxcash; @@ -128,6 +133,10 @@ void ZoneDatabase::AddLootDropToNPC(NPC *npc, uint32 lootdrop_id, ItemList *item return; } + if (!content_service.DoesPassContentFiltering(loot_drop->content_flags)) { + return; + } + // if this lootdrop is droplimit=0 and mindrop 0, scan list once and return if (droplimit == 0 && mindrop == 0) { for (uint32 i = 0; i < loot_drop->NumEntries; ++i) { @@ -706,4 +715,3 @@ void ZoneDatabase::LoadGlobalLoot() zone->AddGlobalLootEntry(e); } } -