From 8e84cafdfac1e56d3feae32c7bf7926d790ca760 Mon Sep 17 00:00:00 2001 From: Aaron Kimbrell Date: Sat, 18 Nov 2023 03:33:23 -0600 Subject: [PATCH] feat: add configurable feature and versions (#1298) * feat: add configurable feature and versions to allow for easily swithing it out to enable features in the client for funsies tested that this doesn't break anything and added test * cleanup --- dCommon/GeneralUtils.h | 5 ++ .../CDClientTables/CDFeatureGatingTable.cpp | 4 +- .../CDClientTables/CDFeatureGatingTable.h | 8 ++- dNet/AuthPackets.cpp | 29 ++++++---- dZoneManager/Level.cpp | 23 ++++++-- resources/sharedconfig.ini | 15 +++++ tests/dCommonTests/CMakeLists.txt | 1 + .../dCommonTests/TestCDFeatureGatingTable.cpp | 55 +++++++++++++++++++ 8 files changed, 122 insertions(+), 18 deletions(-) create mode 100644 tests/dCommonTests/TestCDFeatureGatingTable.cpp diff --git a/dCommon/GeneralUtils.h b/dCommon/GeneralUtils.h index 7acb15b8..d93fd0e7 100644 --- a/dCommon/GeneralUtils.h +++ b/dCommon/GeneralUtils.h @@ -151,6 +151,11 @@ namespace GeneralUtils { return std::stod(value); } + template <> + inline uint16_t Parse(const char* value) { + return std::stoul(value); + } + template <> inline uint32_t Parse(const char* value) { return std::stoul(value); diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.cpp b/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.cpp index 5013dd13..1a9338a0 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.cpp +++ b/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.cpp @@ -42,9 +42,9 @@ std::vector CDFeatureGatingTable::Query(std::function= feature) { return true; } } diff --git a/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.h b/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.h index 9a978218..5df202e3 100644 --- a/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.h +++ b/dDatabase/CDClientDatabase/CDClientTables/CDFeatureGatingTable.h @@ -9,6 +9,12 @@ struct CDFeatureGating { int32_t current; int32_t minor; std::string description; + + bool operator>=(const CDFeatureGating& b) const { + return (this->major > b.major) || + (this->major == b.major && this->current > b.current) || + (this->major == b.major && this->current == b.current && this->minor >= b.minor); + } }; class CDFeatureGatingTable : public CDTable { @@ -21,7 +27,7 @@ public: // Queries the table with a custom "where" clause std::vector Query(std::function predicate); - bool FeatureUnlocked(const std::string& feature) const; + bool FeatureUnlocked(const CDFeatureGating& feature) const; const std::vector& GetEntries(void) const; }; diff --git a/dNet/AuthPackets.cpp b/dNet/AuthPackets.cpp index 12f140d6..f0b22b4e 100644 --- a/dNet/AuthPackets.cpp +++ b/dNet/AuthPackets.cpp @@ -138,18 +138,25 @@ void AuthPackets::SendLoginResponse(dServer* server, const SystemAddress& sysAdd packet.Write(static_cast(responseCode)); // Event Gating - packet.Write(LUString("Talk_Like_A_Pirate")); - packet.Write(LUString("")); - packet.Write(LUString("")); - packet.Write(LUString("")); - packet.Write(LUString("")); - packet.Write(LUString("")); - packet.Write(LUString("")); - packet.Write(LUString("")); + packet.Write(LUString(Game::config->GetValue("event_1"))); + packet.Write(LUString(Game::config->GetValue("event_2"))); + packet.Write(LUString(Game::config->GetValue("event_3"))); + packet.Write(LUString(Game::config->GetValue("event_4"))); + packet.Write(LUString(Game::config->GetValue("event_5"))); + packet.Write(LUString(Game::config->GetValue("event_6"))); + packet.Write(LUString(Game::config->GetValue("event_7"))); + packet.Write(LUString(Game::config->GetValue("event_8"))); - packet.Write(static_cast(1)); // Version Major - packet.Write(static_cast(10)); // Version Current - packet.Write(static_cast(64)); // Version Minor + uint16_t version_major = 1; + uint16_t version_current = 10; + uint16_t version_minor = 64; + GeneralUtils::TryParse(Game::config->GetValue("version_major"), version_major); + GeneralUtils::TryParse(Game::config->GetValue("version_current"), version_current); + GeneralUtils::TryParse(Game::config->GetValue("version_minor"), version_minor); + + packet.Write(version_major); + packet.Write(version_current); + packet.Write(version_minor); // Writes the user key uint32_t sessionKey = GeneralUtils::GenerateRandomNumber(); diff --git a/dZoneManager/Level.cpp b/dZoneManager/Level.cpp index 4c83d494..8202b760 100644 --- a/dZoneManager/Level.cpp +++ b/dZoneManager/Level.cpp @@ -14,6 +14,7 @@ #include "CDFeatureGatingTable.h" #include "CDClientManager.h" #include "AssetManager.h" +#include "dConfig.h" Level::Level(Zone* parentZone, const std::string& filepath) { m_ParentZone = parentZone; @@ -234,6 +235,14 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { CDFeatureGatingTable* featureGatingTable = CDClientManager::Instance().GetTable(); + CDFeatureGating gating; + gating.major = 1; + gating.current = 10; + gating.minor = 64; + GeneralUtils::TryParse(Game::config->GetValue("version_major"), gating.major); + GeneralUtils::TryParse(Game::config->GetValue("version_current"), gating.current); + GeneralUtils::TryParse(Game::config->GetValue("version_minor"), gating.minor); + for (uint32_t i = 0; i < objectsCount; ++i) { SceneObject obj; BinaryIO::BinaryRead(file, obj.id); @@ -279,11 +288,17 @@ void Level::ReadSceneObjectDataChunk(std::istream& file, Header& header) { bool gated = false; for (LDFBaseData* data : obj.settings) { if (data->GetKey() == u"gatingOnFeature") { - std::string featureGate = data->GetValueAsString(); - - if (!featureGatingTable->FeatureUnlocked(featureGate)) { + gating.featureName = data->GetValueAsString(); + if (gating.featureName == Game::config->GetValue("event_1")) break; + else if (gating.featureName == Game::config->GetValue("event_2")) break; + else if (gating.featureName == Game::config->GetValue("event_3")) break; + else if (gating.featureName == Game::config->GetValue("event_4")) break; + else if (gating.featureName == Game::config->GetValue("event_5")) break; + else if (gating.featureName == Game::config->GetValue("event_6")) break; + else if (gating.featureName == Game::config->GetValue("event_7")) break; + else if (gating.featureName == Game::config->GetValue("event_8")) break; + else if (!featureGatingTable->FeatureUnlocked(gating)) { gated = true; - break; } } diff --git a/resources/sharedconfig.ini b/resources/sharedconfig.ini index 46b11470..2e2b6120 100644 --- a/resources/sharedconfig.ini +++ b/resources/sharedconfig.ini @@ -47,3 +47,18 @@ client_net_version=171022 # Turn to 0 to default teams to use the live accurate Shared Loot (0) by default as opposed to Free for All (1) # This is used in both Chat and World servers. default_team_loot=1 + +# event gating for login response and luz gating +event_1=Talk_Like_A_Pirate +event_2= +event_3= +event_4= +event_5= +event_6= +event_7= +event_8= + +# version for login response and luz gating +version_major=1 +version_current=10 +version_minor=64 diff --git a/tests/dCommonTests/CMakeLists.txt b/tests/dCommonTests/CMakeLists.txt index 006102fa..b39d130c 100644 --- a/tests/dCommonTests/CMakeLists.txt +++ b/tests/dCommonTests/CMakeLists.txt @@ -2,6 +2,7 @@ set(DCOMMONTEST_SOURCES "AMFDeserializeTests.cpp" "Amf3Tests.cpp" "HeaderSkipTest.cpp" + "TestCDFeatureGatingTable.cpp" "TestLDFFormat.cpp" "TestNiPoint3.cpp" "TestEncoding.cpp" diff --git a/tests/dCommonTests/TestCDFeatureGatingTable.cpp b/tests/dCommonTests/TestCDFeatureGatingTable.cpp new file mode 100644 index 00000000..560f87be --- /dev/null +++ b/tests/dCommonTests/TestCDFeatureGatingTable.cpp @@ -0,0 +1,55 @@ +#include +#include "CDFeatureGatingTable.h" + + +TEST(dCommonTests, CDFeaturingGatingComparison){ + CDFeatureGating a; + a.major = 1; + a.current = 10; + a.minor = 64; + + CDFeatureGating b; + b.major = 999; + b.current = 999; + b.minor = 999; + EXPECT_TRUE(b >= a); + EXPECT_FALSE(a >= b); + + // below + b.major = 0; + b.current = 10; + b.minor = 64; + EXPECT_FALSE(b >= a); + EXPECT_TRUE(a >= b); + + b.major = 1; + b.current = 9; + b.minor = 64; + EXPECT_FALSE(b >= a); + EXPECT_TRUE(a >= b); + + b.major = 1; + b.current = 10; + b.minor = 63; + EXPECT_FALSE(b >= a); + EXPECT_TRUE(a >= b); + + // above + b.major = 2; + b.current = 10; + b.minor = 64; + EXPECT_TRUE(b >= a); + EXPECT_FALSE(a >= b); + + b.major = 1; + b.current = 11; + b.minor = 64; + EXPECT_TRUE(b >= a); + EXPECT_FALSE(a >= b); + + b.major = 1; + b.current = 10; + b.minor = 65; + EXPECT_TRUE(b >= a); + EXPECT_FALSE(a >= b); +}