diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index d741ae81d..0990afd1b 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -6,6 +6,7 @@ SET(common_sources cli/eqemu_command_handler.cpp compression.cpp condition.cpp + content/world_content_service.cpp crash.cpp crc16.cpp crc32.cpp @@ -116,6 +117,7 @@ SET(common_headers classes.h compression.h condition.h + content/world_content_service.h crash.h crc16.h crc32.h @@ -197,6 +199,7 @@ SET(common_headers races.h random.h repositories/character_recipe_list_repository.h + repositories/criteria/content_filter_criteria.h repositories/grid_repository.h repositories/grid_entries_repository.h repositories/spawngroup_repository.h diff --git a/common/content/world_content_service.cpp b/common/content/world_content_service.cpp new file mode 100644 index 000000000..350208774 --- /dev/null +++ b/common/content/world_content_service.cpp @@ -0,0 +1,41 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include "world_content_service.h" + +int WorldContentService::GetCurrentExpansion() const +{ + return current_expansion; +} + +void WorldContentService::SetCurrentExpansion(int current_expansion) +{ + WorldContentService::current_expansion = current_expansion; +} + +const std::vector &WorldContentService::GetContentFlags() const +{ + return content_flags; +} + +void WorldContentService::SetContentFlags(std::vector content_flags) +{ + WorldContentService::content_flags = content_flags; +} diff --git a/common/content/world_content_service.h b/common/content/world_content_service.h new file mode 100644 index 000000000..850d536e2 --- /dev/null +++ b/common/content/world_content_service.h @@ -0,0 +1,163 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef EQEMU_WORLD_CONTENT_SERVICE_H +#define EQEMU_WORLD_CONTENT_SERVICE_H + +#include +#include + +namespace Expansion { + enum ExpansionNumber { + Classic = 0, + TheRuinsOfKunark, + TheShardsOfVelious, + TheShadowsOfLuclin, + ThePlanesOfPower, + TheLegacyOfYkesha, + LostDungeonsOfNorrath, + GatesOfDiscord, + OmensOfWar, + DragonsOfNorrath, + DepthsOfDarkhollow, + ProphecyOfRo, + TheSerpentsSpine, + TheBuriedSea, + SecretsOfFaydwer, + SeedsOfDestruction, + Underfoot, + HouseOfThule, + VeilOfAlaris, + RainOfFear, + CallOfTheForsaken, + TheDarkendSea, + TheBrokenMirror, + EmpiresOfKunark, + RingOfScale, + TheBurningLands, + TormentOfVelious, + MaxId + }; + + /** + * If you add to this, make sure you update LogCategory + */ + static const char *ExpansionName[ExpansionNumber::MaxId] = { + "Classic", + "The Ruins of Kunark", + "The Shadows of Luclin", + "The Planes of Power", + "Lost Dungeons of Norrath", + "Gates of Discord", + "Omens of War", + "Dragons of Norrath", + "Depths of Darkhollow", + "Prophecy of Ro", + "The Serpent's Spine", + "The Buried Sea", + "Secrets of Faydwer", + "Seeds of Destruction", + "Underfoot", + "House of Thule", + "Veil of Alaris", + "Rain of Fear", + "Call of the Forsaken", + "The Darkened Sea", + "The Broken Mirror", + "Empires of Kunark", + "Ring of Scale", + "The Burning Lands", + "Torment of Velious", + }; +} + +class WorldContentService { +public: + + int GetCurrentExpansion() const; + void SetCurrentExpansion(int current_expansion); + + bool IsClassicEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::Classic; } + bool IsTheRuinsOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheRuinsOfKunark; } + bool IsTheShardsOfVeliousEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheShardsOfVelious; } + bool IsTheShadowsOfLuclinEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheShadowsOfLuclin; } + bool IsThePlanesOfPowerEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::ThePlanesOfPower; } + bool IsTheLegacyOfYkeshaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheLegacyOfYkesha; } + bool IsLostDungeonsOfNorrathEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::LostDungeonsOfNorrath; } + bool IsGatesOfDiscordEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::GatesOfDiscord; } + bool IsOmensOfWarEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::OmensOfWar; } + bool IsDragonsOfNorrathEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::DragonsOfNorrath; } + bool IsDepthsOfDarkhollowEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::DepthsOfDarkhollow; } + bool IsProphecyOfRoEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::ProphecyOfRo; } + bool IsTheSerpentsSpineEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheSerpentsSpine; } + bool IsTheBuriedSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBuriedSea; } + bool IsSecretsOfFaydwerEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::SecretsOfFaydwer; } + bool IsSeedsOfDestructionEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::SeedsOfDestruction; } + bool IsUnderfootEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::Underfoot; } + bool IsHouseOfThuleEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::HouseOfThule; } + bool IsVeilOfAlarisEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::VeilOfAlaris; } + bool IsRainOfFearEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RainOfFear; } + bool IsCallOfTheForsakenEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::CallOfTheForsaken; } + bool IsTheDarkendSeaEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheDarkendSea; } + bool IsTheBrokenMirrorEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBrokenMirror; } + bool IsEmpiresOfKunarkEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::EmpiresOfKunark; } + bool IsRingOfScaleEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::RingOfScale; } + bool IsTheBurningLandsEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TheBurningLands; } + bool IsTormentOfVeliousEnabled() { return GetCurrentExpansion() >= Expansion::ExpansionNumber::TormentOfVelious; } + + bool IsCurrentExpansionClassic() { return current_expansion == Expansion::ExpansionNumber::Classic; } + bool IsCurrentExpansionTheRuinsOfKunark() { return current_expansion == Expansion::ExpansionNumber::TheRuinsOfKunark; } + bool IsCurrentExpansionTheShardsOfVelious() { return current_expansion == Expansion::ExpansionNumber::TheShardsOfVelious; } + bool IsCurrentExpansionTheShadowsOfLuclin() { return current_expansion == Expansion::ExpansionNumber::TheShadowsOfLuclin; } + bool IsCurrentExpansionThePlanesOfPower() { return current_expansion == Expansion::ExpansionNumber::ThePlanesOfPower; } + bool IsCurrentExpansionTheLegacyOfYkesha() { return current_expansion == Expansion::ExpansionNumber::TheLegacyOfYkesha; } + bool IsCurrentExpansionLostDungeonsOfNorrath() { return current_expansion == Expansion::ExpansionNumber::LostDungeonsOfNorrath; } + bool IsCurrentExpansionGatesOfDiscord() { return current_expansion == Expansion::ExpansionNumber::GatesOfDiscord; } + bool IsCurrentExpansionOmensOfWar() { return current_expansion == Expansion::ExpansionNumber::OmensOfWar; } + bool IsCurrentExpansionDragonsOfNorrath() { return current_expansion == Expansion::ExpansionNumber::DragonsOfNorrath; } + bool IsCurrentExpansionDepthsOfDarkhollow() { return current_expansion == Expansion::ExpansionNumber::DepthsOfDarkhollow; } + bool IsCurrentExpansionProphecyOfRo() { return current_expansion == Expansion::ExpansionNumber::ProphecyOfRo; } + bool IsCurrentExpansionTheSerpentsSpine() { return current_expansion == Expansion::ExpansionNumber::TheSerpentsSpine; } + bool IsCurrentExpansionTheBuriedSea() { return current_expansion == Expansion::ExpansionNumber::TheBuriedSea; } + bool IsCurrentExpansionSecretsOfFaydwer() { return current_expansion == Expansion::ExpansionNumber::SecretsOfFaydwer; } + bool IsCurrentExpansionSeedsOfDestruction() { return current_expansion == Expansion::ExpansionNumber::SeedsOfDestruction; } + bool IsCurrentExpansionUnderfoot() { return current_expansion == Expansion::ExpansionNumber::Underfoot; } + bool IsCurrentExpansionHouseOfThule() { return current_expansion == Expansion::ExpansionNumber::HouseOfThule; } + bool IsCurrentExpansionVeilOfAlaris() { return current_expansion == Expansion::ExpansionNumber::VeilOfAlaris; } + bool IsCurrentExpansionRainOfFear() { return current_expansion == Expansion::ExpansionNumber::RainOfFear; } + bool IsCurrentExpansionCallOfTheForsaken() { return current_expansion == Expansion::ExpansionNumber::CallOfTheForsaken; } + bool IsCurrentExpansionTheDarkendSea() { return current_expansion == Expansion::ExpansionNumber::TheDarkendSea; } + bool IsCurrentExpansionTheBrokenMirror() { return current_expansion == Expansion::ExpansionNumber::TheBrokenMirror; } + bool IsCurrentExpansionEmpiresOfKunark() { return current_expansion == Expansion::ExpansionNumber::EmpiresOfKunark; } + bool IsCurrentExpansionRingOfScale() { return current_expansion == Expansion::ExpansionNumber::RingOfScale; } + bool IsCurrentExpansionTheBurningLands() { return current_expansion == Expansion::ExpansionNumber::TheBurningLands; } + bool IsCurrentExpansionTormentOfVelious() { return current_expansion == Expansion::ExpansionNumber::TormentOfVelious; } + +private: + int current_expansion; + std::vector content_flags; +public: + const std::vector &GetContentFlags() const; + void SetContentFlags(std::vector content_flags); +}; + +extern WorldContentService content_service; + +#endif //EQEMU_WORLD_CONTENT_SERVICE_H diff --git a/common/repositories/criteria/content_filter_criteria.h b/common/repositories/criteria/content_filter_criteria.h new file mode 100644 index 000000000..c316bd87f --- /dev/null +++ b/common/repositories/criteria/content_filter_criteria.h @@ -0,0 +1,57 @@ +/** + * EQEmulator: Everquest Server Emulator + * Copyright (C) 2001-2020 EQEmulator Development Team (https://github.com/EQEmu/Server) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY except by those people which sell it, which + * are required to give you total support for your newly bought product; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR + * A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifndef EQEMU_CONTENT_FILTER_CRITERIA_H +#define EQEMU_CONTENT_FILTER_CRITERIA_H + +#include +#include "../../content/world_content_service.h" +#include "../../string_util.h" + +namespace ContentFilterCriteria { + static std::string apply() + { + std::string criteria; + + criteria += fmt::format( + " AND (min_expansion >= {} OR min_expansion = 0)", + content_service.GetCurrentExpansion() + ); + + criteria += fmt::format( + " AND (max_expansion <= {} OR max_expansion = 0)", + content_service.GetCurrentExpansion() + ); + + std::vector flags = content_service.GetContentFlags(); + for (auto &flag: flags) { + flag = "'" + flag + "'"; + } + + criteria += fmt::format( + " AND (content_flags IS NULL OR content_flags IN ({}))", + implode(", ", flags) + ); + + return std::string(criteria); + }; +} + +#endif //EQEMU_CONTENT_FILTER_CRITERIA_H diff --git a/common/ruletypes.h b/common/ruletypes.h index f1d00529f..85d670071 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -774,6 +774,10 @@ RULE_BOOL(HotReload, QuestsRepopWhenPlayersNotInCombat, true, "When a hot reload RULE_BOOL(HotReload, QuestsResetTimersWithReload, true, "When a hot reload is triggered, quest timers will be reset") RULE_CATEGORY_END() +RULE_CATEGORY(Expansion) +RULE_INT(Expansion, CurrentExpansion, -1, "The current expansion enabled for the server [0 = Classic, 1 = Kunark etc.]") +RULE_CATEGORY_END() + #undef RULE_CATEGORY #undef RULE_INT #undef RULE_REAL diff --git a/world/main.cpp b/world/main.cpp index 03a39ea79..dbdad0079 100644 --- a/world/main.cpp +++ b/world/main.cpp @@ -90,6 +90,7 @@ union semun { #include "../common/net/servertalk_server.h" #include "../zone/data_bucket.h" #include "world_server_command_handler.h" +#include "../common/content/world_content_service.h" ClientList client_list; GroupLFPList LFPGroupList; @@ -106,6 +107,7 @@ uint32 numzones = 0; bool holdzones = false; const WorldConfig *Config; EQEmuLogSys LogSys; +WorldContentService content_service; WebInterfaceList web_interface; void CatchSignal(int sig_num); diff --git a/world/world_server_command_handler.cpp b/world/world_server_command_handler.cpp index 9bad28541..38991f604 100644 --- a/world/world_server_command_handler.cpp +++ b/world/world_server_command_handler.cpp @@ -25,6 +25,9 @@ #include "worlddb.h" #include "../common/database_schema.h" #include "../common/database/database_dump_service.h" +#include "../common/content/world_content_service.h" +#include "../common/repositories/criteria/content_filter_criteria.h" +#include "../common/rulesys.h" namespace WorldserverCommandHandler { @@ -53,6 +56,7 @@ namespace WorldserverCommandHandler { function_map["database:set-account-status"] = &WorldserverCommandHandler::DatabaseSetAccountStatus; function_map["database:schema"] = &WorldserverCommandHandler::DatabaseGetSchema; function_map["database:dump"] = &WorldserverCommandHandler::DatabaseDump; + function_map["test:test"] = &WorldserverCommandHandler::TestCommand; EQEmuCommand::HandleMenu(function_map, cmd, argc, argv); } @@ -271,4 +275,40 @@ namespace WorldserverCommandHandler { database_dump_service->Dump(); } + /** + * @param argc + * @param argv + * @param cmd + * @param description + */ + void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description) + { + description = "Test command"; + + if (cmd[{"-h", "--help"}]) { + return; + } + + if (!RuleManager::Instance()->LoadRules(&database, "default", false)) { + LogInfo("No rule set configured, using default rules"); + } + + content_service.SetCurrentExpansion(RuleI(Expansion, CurrentExpansion)); + + std::vector flags = { + "hateplane_enabled", + "patch_nerf_7077", + }; + + content_service.SetContentFlags(flags); + + LogInfo( + "Current expansion is [{}] ({}) is Velious Enabled [{}] Criteria [{}]", + content_service.GetCurrentExpansion(), + Expansion::ExpansionName[content_service.GetCurrentExpansion()], + content_service.IsTheShardsOfVeliousEnabled() ? "true" : "false", + ContentFilterCriteria::apply() + ); + } + } \ No newline at end of file diff --git a/world/world_server_command_handler.h b/world/world_server_command_handler.h index a32a78f0f..5291d7c24 100644 --- a/world/world_server_command_handler.h +++ b/world/world_server_command_handler.h @@ -31,6 +31,7 @@ namespace WorldserverCommandHandler { void DatabaseSetAccountStatus(int argc, char **argv, argh::parser &cmd, std::string &description); void DatabaseGetSchema(int argc, char **argv, argh::parser &cmd, std::string &description); void DatabaseDump(int argc, char **argv, argh::parser &cmd, std::string &description); + void TestCommand(int argc, char **argv, argh::parser &cmd, std::string &description); };