diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index df77a0179..2bd27e603 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5717,6 +5717,22 @@ CREATE TABLE `buyer_trade_items` ( COLLATE='latin1_swedish_ci' ENGINE=InnoDB AUTO_INCREMENT=1; +)" + }, + ManifestEntry{ + .version = 9282, + .description = "2024_08_02_spell_buckets_comparison.sql", + .check = "SHOW COLUMNS FROM `spell_buckets` LIKE 'bucket_comparison'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `spell_buckets` +CHANGE COLUMN `spellid` `spell_id` int UNSIGNED NOT NULL FIRST, +CHANGE COLUMN `key` `bucket_name` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `spell_id`, +CHANGE COLUMN `value` `bucket_value` varchar(100) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL DEFAULT '' AFTER `bucket_name`, +ADD COLUMN `bucket_comparison` tinyint UNSIGNED NOT NULL DEFAULT 0 AFTER `bucket_value`, +DROP PRIMARY KEY, +ADD PRIMARY KEY (`spell_id`) USING BTREE; )" } // -- template; copy/paste this when you need to create a new entry diff --git a/common/repositories/base/base_spell_buckets_repository.h b/common/repositories/base/base_spell_buckets_repository.h index c73931a39..734e02155 100644 --- a/common/repositories/base/base_spell_buckets_repository.h +++ b/common/repositories/base/base_spell_buckets_repository.h @@ -19,31 +19,34 @@ class BaseSpellBucketsRepository { public: struct SpellBuckets { - uint64_t spellid; - std::string key_; - std::string value; + uint32_t spell_id; + std::string bucket_name; + std::string bucket_value; + uint8_t bucket_comparison; }; static std::string PrimaryKey() { - return std::string("spellid"); + return std::string("spell_id"); } static std::vector Columns() { return { - "spellid", - "`key`", - "value", + "spell_id", + "bucket_name", + "bucket_value", + "bucket_comparison", }; } static std::vector SelectColumns() { return { - "spellid", - "`key`", - "value", + "spell_id", + "bucket_name", + "bucket_value", + "bucket_comparison", }; } @@ -84,9 +87,10 @@ public: { SpellBuckets e{}; - e.spellid = 0; - e.key_ = ""; - e.value = ""; + e.spell_id = 0; + e.bucket_name = ""; + e.bucket_value = ""; + e.bucket_comparison = 0; return e; } @@ -97,7 +101,7 @@ public: ) { for (auto &spell_buckets : spell_bucketss) { - if (spell_buckets.spellid == spell_buckets_id) { + if (spell_buckets.spell_id == spell_buckets_id) { return spell_buckets; } } @@ -123,9 +127,10 @@ public: if (results.RowCount() == 1) { SpellBuckets e{}; - e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.key_ = row[1] ? row[1] : ""; - e.value = row[2] ? row[2] : ""; + e.spell_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.bucket_name = row[1] ? row[1] : ""; + e.bucket_value = row[2] ? row[2] : ""; + e.bucket_comparison = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; return e; } @@ -159,9 +164,10 @@ public: auto columns = Columns(); - v.push_back(columns[0] + " = " + std::to_string(e.spellid)); - v.push_back(columns[1] + " = '" + Strings::Escape(e.key_) + "'"); - v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'"); + v.push_back(columns[0] + " = " + std::to_string(e.spell_id)); + v.push_back(columns[1] + " = '" + Strings::Escape(e.bucket_name) + "'"); + v.push_back(columns[2] + " = '" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(columns[3] + " = " + std::to_string(e.bucket_comparison)); auto results = db.QueryDatabase( fmt::format( @@ -169,7 +175,7 @@ public: TableName(), Strings::Implode(", ", v), PrimaryKey(), - e.spellid + e.spell_id ) ); @@ -183,9 +189,10 @@ public: { std::vector v; - v.push_back(std::to_string(e.spellid)); - v.push_back("'" + Strings::Escape(e.key_) + "'"); - v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.spell_id)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); auto results = db.QueryDatabase( fmt::format( @@ -196,7 +203,7 @@ public: ); if (results.Success()) { - e.spellid = results.LastInsertedID(); + e.spell_id = results.LastInsertedID(); return e; } @@ -215,9 +222,10 @@ public: for (auto &e: entries) { std::vector v; - v.push_back(std::to_string(e.spellid)); - v.push_back("'" + Strings::Escape(e.key_) + "'"); - v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.spell_id)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } @@ -251,9 +259,10 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { SpellBuckets e{}; - e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.key_ = row[1] ? row[1] : ""; - e.value = row[2] ? row[2] : ""; + e.spell_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.bucket_name = row[1] ? row[1] : ""; + e.bucket_value = row[2] ? row[2] : ""; + e.bucket_comparison = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -278,9 +287,10 @@ public: for (auto row = results.begin(); row != results.end(); ++row) { SpellBuckets e{}; - e.spellid = row[0] ? strtoull(row[0], nullptr, 10) : 0; - e.key_ = row[1] ? row[1] : ""; - e.value = row[2] ? row[2] : ""; + e.spell_id = row[0] ? static_cast(strtoul(row[0], nullptr, 10)) : 0; + e.bucket_name = row[1] ? row[1] : ""; + e.bucket_value = row[2] ? row[2] : ""; + e.bucket_comparison = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; all_entries.push_back(e); } @@ -355,9 +365,10 @@ public: { std::vector v; - v.push_back(std::to_string(e.spellid)); - v.push_back("'" + Strings::Escape(e.key_) + "'"); - v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.spell_id)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); auto results = db.QueryDatabase( fmt::format( @@ -380,9 +391,10 @@ public: for (auto &e: entries) { std::vector v; - v.push_back(std::to_string(e.spellid)); - v.push_back("'" + Strings::Escape(e.key_) + "'"); - v.push_back("'" + Strings::Escape(e.value) + "'"); + v.push_back(std::to_string(e.spell_id)); + v.push_back("'" + Strings::Escape(e.bucket_name) + "'"); + v.push_back("'" + Strings::Escape(e.bucket_value) + "'"); + v.push_back(std::to_string(e.bucket_comparison)); insert_chunks.push_back("(" + Strings::Implode(",", v) + ")"); } diff --git a/common/version.h b/common/version.h index e89fd9ea3..5b78b25af 100644 --- a/common/version.h +++ b/common/version.h @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9281 +#define CURRENT_BINARY_DATABASE_VERSION 9282 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9044 #endif diff --git a/zone/spells.cpp b/zone/spells.cpp index bde53f3ca..afd31bd7c 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -78,6 +78,7 @@ Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org) #include "../common/misc_functions.h" #include "../common/events/player_event_logs.h" #include "../common/repositories/character_corpses_repository.h" +#include "../common/repositories/spell_buckets_repository.h" #include "data_bucket.h" #include "quest_parser_collection.h" @@ -6239,65 +6240,20 @@ bool Client::SpellGlobalCheck(uint16 spell_id, uint32 character_id) { return false; } -bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) { - auto query = fmt::format( - "SELECT `key`, value FROM spell_buckets WHERE spellid = {}", - spell_id - ); - - auto results = database.QueryDatabase(query); - if (!results.Success()) { - return false; // Query failed, do not allow scribing. +bool Client::SpellBucketCheck(uint16 spell_id, uint32 character_id) +{ + const auto& e = SpellBucketsRepository::FindOne(database, spell_id); + if (!e.spell_id || e.bucket_name.empty() || e.bucket_value.empty()) { + return true; } - if (!results.RowCount()) { - return true; // Spell ID isn't listed in the spell_buckets table, allow scribing. - } + auto k = GetScopedBucketKeys(); - auto row = results.begin(); - std::string spell_bucket_name = row[0]; - std::string spell_bucket_value = row[1]; + k.key = e.bucket_name; - if (spell_bucket_name.empty()) { - return true; // If the entry in the spell_buckets table has nothing set for the qglobal name, allow scribing. - } + const auto& b = DataBucket::GetData(k); - DataBucketKey k = GetScopedBucketKeys(); - k.key = spell_bucket_name; - - auto b = DataBucket::GetData(k); - if (!b.value.empty()) { - if (Strings::IsNumber(b.value) && Strings::IsNumber(spell_bucket_value)) { - if (Strings::ToInt(b.value) >= Strings::ToInt(spell_bucket_value)) { - return true; // If value is greater than or equal to spell bucket value, allow scribing. - } - } else { - if (b.value == spell_bucket_value) { - return true; // If value is equal to spell bucket value, allow scribing. - } - } - } - - auto old_bucket_name = fmt::format( - "{}-{}", - character_id, - spell_bucket_name - ); - - std::string bucket_value = DataBucket::GetData(old_bucket_name); - if (!bucket_value.empty()) { - if (Strings::IsNumber(bucket_value) && Strings::IsNumber(spell_bucket_value)) { - if (Strings::ToInt(bucket_value) >= Strings::ToInt(spell_bucket_value)) { - return true; // If value is greater than or equal to spell bucket value, allow scribing. - } - } else { - if (bucket_value == spell_bucket_value) { - return true; // If value is equal to spell bucket value, allow scribing. - } - } - } - - return false; + return zone->CompareDataBucket(e.bucket_comparison, e.bucket_value, b.value); } // TODO get rid of this