diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index be7f01e14..582864c43 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -6301,7 +6301,24 @@ ALTER TABLE zone DROP COLUMN IF EXISTS npc_update_range; ALTER TABLE zone DROP COLUMN IF EXISTS max_movement_update_range; ALTER TABLE `zone` ADD COLUMN `client_update_range` int(11) NOT NULL DEFAULT 600 AFTER `npc_max_aggro_dist`; )", - .content_schema_update = true + .content_schema_update = true, + }, + ManifestEntry{ + .version = 9292, + .description = "2025_01_21_data_buckets_account_id", + .check = "SHOW COLUMNS FROM `data_buckets` LIKE 'account_id'", + .condition = "empty", + .match = "", + .sql = R"( +ALTER TABLE `data_buckets` +ADD COLUMN `account_id` bigint(11) NULL DEFAULT 0 AFTER `expires`, +DROP INDEX `keys`, +ADD UNIQUE INDEX `keys` (`key`, `character_id`, `npc_id`, `bot_id`, `account_id`) USING BTREE; + +-- Add the INDEX for character_id and key +ALTER TABLE `data_buckets` ADD KEY `idx_account_id_key` (`account_id`, `key`); +)", + .content_schema_update = false }, // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/repositories/base/base_data_buckets_repository.h b/common/repositories/base/base_data_buckets_repository.h index 3e7ca05d0..42c85336c 100644 --- a/common/repositories/base/base_data_buckets_repository.h +++ b/common/repositories/base/base_data_buckets_repository.h @@ -23,6 +23,7 @@ public: std::string key_; std::string value; uint32_t expires; + int64_t account_id; int64_t character_id; int64_t npc_id; int64_t bot_id; @@ -36,6 +37,7 @@ public: CEREAL_NVP(key_), CEREAL_NVP(value), CEREAL_NVP(expires), + CEREAL_NVP(account_id), CEREAL_NVP(character_id), CEREAL_NVP(npc_id), CEREAL_NVP(bot_id) @@ -55,6 +57,7 @@ public: "`key`", "value", "expires", + "account_id", "character_id", "npc_id", "bot_id", @@ -68,6 +71,7 @@ public: "`key`", "value", "expires", + "account_id", "character_id", "npc_id", "bot_id", @@ -115,6 +119,7 @@ public: e.key_ = ""; e.value = ""; e.expires = 0; + e.account_id = 0; e.character_id = 0; e.npc_id = 0; e.bot_id = 0; @@ -158,9 +163,10 @@ public: e.key_ = row[1] ? row[1] : ""; e.value = row[2] ? row[2] : ""; e.expires = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.character_id = row[4] ? strtoll(row[4], nullptr, 10) : 0; - e.npc_id = row[5] ? strtoll(row[5], nullptr, 10) : 0; - e.bot_id = row[6] ? strtoll(row[6], nullptr, 10) : 0; + e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0; + e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0; + e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0; + e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0; return e; } @@ -197,9 +203,10 @@ public: v.push_back(columns[1] + " = '" + Strings::Escape(e.key_) + "'"); v.push_back(columns[2] + " = '" + Strings::Escape(e.value) + "'"); v.push_back(columns[3] + " = " + std::to_string(e.expires)); - v.push_back(columns[4] + " = " + std::to_string(e.character_id)); - v.push_back(columns[5] + " = " + std::to_string(e.npc_id)); - v.push_back(columns[6] + " = " + std::to_string(e.bot_id)); + v.push_back(columns[4] + " = " + std::to_string(e.account_id)); + v.push_back(columns[5] + " = " + std::to_string(e.character_id)); + v.push_back(columns[6] + " = " + std::to_string(e.npc_id)); + v.push_back(columns[7] + " = " + std::to_string(e.bot_id)); auto results = db.QueryDatabase( fmt::format( @@ -225,6 +232,7 @@ public: v.push_back("'" + Strings::Escape(e.key_) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back(std::to_string(e.expires)); + v.push_back(std::to_string(e.account_id)); v.push_back(std::to_string(e.character_id)); v.push_back(std::to_string(e.npc_id)); v.push_back(std::to_string(e.bot_id)); @@ -261,6 +269,7 @@ public: v.push_back("'" + Strings::Escape(e.key_) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back(std::to_string(e.expires)); + v.push_back(std::to_string(e.account_id)); v.push_back(std::to_string(e.character_id)); v.push_back(std::to_string(e.npc_id)); v.push_back(std::to_string(e.bot_id)); @@ -301,9 +310,10 @@ public: e.key_ = row[1] ? row[1] : ""; e.value = row[2] ? row[2] : ""; e.expires = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.character_id = row[4] ? strtoll(row[4], nullptr, 10) : 0; - e.npc_id = row[5] ? strtoll(row[5], nullptr, 10) : 0; - e.bot_id = row[6] ? strtoll(row[6], nullptr, 10) : 0; + e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0; + e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0; + e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0; + e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0; all_entries.push_back(e); } @@ -332,9 +342,10 @@ public: e.key_ = row[1] ? row[1] : ""; e.value = row[2] ? row[2] : ""; e.expires = row[3] ? static_cast(strtoul(row[3], nullptr, 10)) : 0; - e.character_id = row[4] ? strtoll(row[4], nullptr, 10) : 0; - e.npc_id = row[5] ? strtoll(row[5], nullptr, 10) : 0; - e.bot_id = row[6] ? strtoll(row[6], nullptr, 10) : 0; + e.account_id = row[4] ? strtoll(row[4], nullptr, 10) : 0; + e.character_id = row[5] ? strtoll(row[5], nullptr, 10) : 0; + e.npc_id = row[6] ? strtoll(row[6], nullptr, 10) : 0; + e.bot_id = row[7] ? strtoll(row[7], nullptr, 10) : 0; all_entries.push_back(e); } @@ -413,6 +424,7 @@ public: v.push_back("'" + Strings::Escape(e.key_) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back(std::to_string(e.expires)); + v.push_back(std::to_string(e.account_id)); v.push_back(std::to_string(e.character_id)); v.push_back(std::to_string(e.npc_id)); v.push_back(std::to_string(e.bot_id)); @@ -442,6 +454,7 @@ public: v.push_back("'" + Strings::Escape(e.key_) + "'"); v.push_back("'" + Strings::Escape(e.value) + "'"); v.push_back(std::to_string(e.expires)); + v.push_back(std::to_string(e.account_id)); v.push_back(std::to_string(e.character_id)); v.push_back(std::to_string(e.npc_id)); v.push_back(std::to_string(e.bot_id)); diff --git a/zone/client.cpp b/zone/client.cpp index 667142f30..697d7c752 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -402,6 +402,7 @@ Client::~Client() { mMovementManager->RemoveClient(this); + DataBucket::DeleteCachedBuckets(DataBucketLoadType::Account, AccountID()); DataBucket::DeleteCachedBuckets(DataBucketLoadType::Client, CharacterID()); if (RuleB(Bots, Enabled)) { @@ -13172,10 +13173,57 @@ void Client::BroadcastPositionUpdate() Group *g = GetGroup(); if (g) { - for (auto & m : g->members) { + for (auto &m: g->members) { if (m && m->IsClient() && m != this) { m->CastToClient()->QueuePacket(&outapp); } } } } + +std::string Client::GetAccountBucket(std::string bucket_name) +{ + DataBucketKey k = {}; + k.account_id = AccountID(); + k.key = bucket_name; + + return DataBucket::GetData(k).value; +} + +void Client::SetAccountBucket(std::string bucket_name, std::string bucket_value, std::string expiration) +{ + DataBucketKey k = {}; + k.account_id = AccountID(); + k.key = bucket_name; + k.expires = expiration; + k.value = bucket_value; + + DataBucket::SetData(k); +} + +void Client::DeleteAccountBucket(std::string bucket_name) +{ + DataBucketKey k = {}; + k.account_id = AccountID(); + k.key = bucket_name; + + DataBucket::DeleteData(k); +} + +std::string Client::GetAccountBucketExpires(std::string bucket_name) +{ + DataBucketKey k = {}; + k.account_id = AccountID(); + k.key = bucket_name; + + return DataBucket::GetDataExpires(k); +} + +std::string Client::GetAccountBucketRemaining(std::string bucket_name) +{ + DataBucketKey k = {}; + k.account_id = AccountID(); + k.key = bucket_name; + + return DataBucket::GetDataRemaining(k); +} diff --git a/zone/client.h b/zone/client.h index 3ec680a87..146cabd34 100644 --- a/zone/client.h +++ b/zone/client.h @@ -1829,6 +1829,13 @@ public: void SendEvolveXPTransferWindow(); void SendEvolveTransferResults(const EQ::ItemInstance &inst_from, const EQ::ItemInstance &inst_to, const EQ::ItemInstance &inst_from_new, const EQ::ItemInstance &inst_to_new, const uint32 compatibility, const uint32 max_transfer_level); + // Account buckets + std::string GetAccountBucket(std::string bucket_name); + void SetAccountBucket(std::string bucket_name, std::string bucket_value, std::string expiration = ""); + void DeleteAccountBucket(std::string bucket_name); + std::string GetAccountBucketExpires(std::string bucket_name); + std::string GetAccountBucketRemaining(std::string bucket_name); + protected: friend class Mob; void CalcEdibleBonuses(StatBonuses* newbon); diff --git a/zone/data_bucket.cpp b/zone/data_bucket.cpp index db2222348..23d4eb9d6 100644 --- a/zone/data_bucket.cpp +++ b/zone/data_bucket.cpp @@ -16,6 +16,7 @@ void DataBucket::SetData(const std::string &bucket_key, const std::string &bucke .key = bucket_key, .value = bucket_value, .expires = expires_time, + .account_id = 0, .character_id = 0, .npc_id = 0, .bot_id = 0 @@ -37,6 +38,9 @@ void DataBucket::SetData(const DataBucketKey &k) if (k.character_id > 0) { b.character_id = k.character_id; } + else if (k.account_id > 0) { + b.account_id = k.account_id; + } else if (k.npc_id > 0) { b.npc_id = k.npc_id; } @@ -95,9 +99,10 @@ std::string DataBucket::GetData(const std::string &bucket_key) DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, bool ignore_misses_cache) { LogDataBuckets( - "Getting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}]", + "Getting bucket key [{}] bot_id [{}] account_id [{}] character_id [{}] npc_id [{}]", k.key, k.bot_id, + k.account_id, k.character_id, k.npc_id ); @@ -151,6 +156,7 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b .key_ = k.key, .value = "", .expires = 0, + .account_id = k.account_id, .character_id = k.character_id, .npc_id = k.npc_id, .bot_id = k.bot_id @@ -158,8 +164,9 @@ DataBucketsRepository::DataBuckets DataBucket::GetData(const DataBucketKey &k, b ); LogDataBuckets( - "Key [{}] not found in database, adding to cache as a miss character_id [{}] npc_id [{}] bot_id [{}] cache size before [{}] after [{}]", + "Key [{}] not found in database, adding to cache as a miss account_id [{}] character_id [{}] npc_id [{}] bot_id [{}] cache size before [{}] after [{}]", k.key, + k.account_id, k.character_id, k.npc_id, k.bot_id, @@ -216,8 +223,6 @@ bool DataBucket::DeleteData(const std::string &bucket_key) // GetDataBuckets bulk loads all data buckets for a mob bool DataBucket::GetDataBuckets(Mob *mob) { - DataBucketLoadType::Type t{}; - const uint32 id = mob->GetMobTypeIdentifier(); if (!id) { @@ -225,14 +230,13 @@ bool DataBucket::GetDataBuckets(Mob *mob) } if (mob->IsBot()) { - t = DataBucketLoadType::Bot; + BulkLoadEntitiesToCache(DataBucketLoadType::Bot, {id}); } else if (mob->IsClient()) { - t = DataBucketLoadType::Client; + BulkLoadEntitiesToCache(DataBucketLoadType::Account, {id}); + BulkLoadEntitiesToCache(DataBucketLoadType::Client, {id}); } - BulkLoadEntitiesToCache(t, {id}); - return true; } @@ -254,9 +258,10 @@ bool DataBucket::DeleteData(const DataBucketKey &k) ); LogDataBuckets( - "Deleting bucket key [{}] bot_id [{}] character_id [{}] npc_id [{}] cache size before [{}] after [{}]", + "Deleting bucket key [{}] bot_id [{}] account_id [{}] character_id [{}] npc_id [{}] cache size before [{}] after [{}]", k.key, k.bot_id, + k.account_id, k.character_id, k.npc_id, size_before, @@ -277,9 +282,10 @@ bool DataBucket::DeleteData(const DataBucketKey &k) std::string DataBucket::GetDataExpires(const DataBucketKey &k) { LogDataBuckets( - "Getting bucket expiration key [{}] bot_id [{}] character_id [{}] npc_id [{}]", + "Getting bucket expiration key [{}] bot_id [{}] account_id [{}] character_id [{}] npc_id [{}]", k.key, k.bot_id, + k.account_id, k.character_id, k.npc_id ); @@ -295,9 +301,10 @@ std::string DataBucket::GetDataExpires(const DataBucketKey &k) std::string DataBucket::GetDataRemaining(const DataBucketKey &k) { LogDataBuckets( - "Getting bucket remaining key [{}] bot_id [{}] character_id [{}] npc_id [{}]", + "Getting bucket remaining key [{}] bot_id [{}] account_id [{}] character_id [{}] npc_id [{}]", k.key, k.bot_id, + k.account_id, k.character_id, k.npc_id ); @@ -320,6 +327,13 @@ std::string DataBucket::GetScopedDbFilters(const DataBucketKey &k) query.emplace_back("character_id = 0"); } + if (k.account_id > 0) { + query.emplace_back(fmt::format("account_id = {}", k.account_id)); + } + else { + query.emplace_back("account_id = 0"); + } + if (k.npc_id > 0) { query.emplace_back(fmt::format("npc_id = {}", k.npc_id)); } @@ -346,6 +360,7 @@ bool DataBucket::CheckBucketMatch(const DataBucketsRepository::DataBuckets &dbe, return ( dbe.key_ == k.key && dbe.bot_id == k.bot_id && + dbe.account_id == k.account_id && dbe.character_id == k.character_id && dbe.npc_id == k.npc_id ); @@ -364,6 +379,9 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector if (t == DataBucketLoadType::Bot) { has_cache = e.bot_id == ids[0]; } + else if (t == DataBucketLoadType::Account) { + has_cache = e.account_id == ids[0]; + } else if (t == DataBucketLoadType::Client) { has_cache = e.character_id == ids[0]; } @@ -384,6 +402,9 @@ void DataBucket::BulkLoadEntitiesToCache(DataBucketLoadType::Type t, std::vector case DataBucketLoadType::Client: column = "character_id"; break; + case DataBucketLoadType::Account: + column = "account_id"; + break; default: LogError("Incorrect LoadType [{}]", static_cast(t)); break; @@ -442,6 +463,7 @@ void DataBucket::DeleteCachedBuckets(DataBucketLoadType::Type type, uint32 id) [&](DataBucketsRepository::DataBuckets &e) { return ( (type == DataBucketLoadType::Bot && e.bot_id == id) || + (type == DataBucketLoadType::Account && e.account_id == id) || (type == DataBucketLoadType::Client && e.character_id == id) ); } @@ -481,6 +503,7 @@ void DataBucket::DeleteFromMissesCache(DataBucketsRepository::DataBuckets e) g_data_bucket_cache.end(), [&](DataBucketsRepository::DataBuckets &ce) { return ce.id == 0 && ce.key_ == e.key_ && + ce.account_id == e.account_id && ce.character_id == e.character_id && ce.npc_id == e.npc_id && ce.bot_id == e.bot_id; @@ -516,6 +539,8 @@ void DataBucket::DeleteFromCache(uint64 id, DataBucketLoadType::Type type) return e.bot_id == id; case DataBucketLoadType::Client: return e.character_id == id; + case DataBucketLoadType::Account: + return e.account_id == id; default: return false; } @@ -539,7 +564,7 @@ void DataBucket::DeleteFromCache(uint64 id, DataBucketLoadType::Type type) // npcs (ids) can be in multiple zones so we can't cache locally to the zone bool DataBucket::CanCache(const DataBucketKey &key) { - if (key.character_id > 0 || key.bot_id > 0) { + if (key.character_id > 0 || key.account_id > 0 || key.bot_id > 0) { return true; } diff --git a/zone/data_bucket.h b/zone/data_bucket.h index 8503330f2..1bd216630 100644 --- a/zone/data_bucket.h +++ b/zone/data_bucket.h @@ -12,20 +12,23 @@ struct DataBucketKey { std::string key; std::string value; std::string expires; - int64_t character_id; - int64_t npc_id; - int64_t bot_id; + int64_t account_id = 0; + int64_t character_id = 0; + int64_t npc_id = 0; + int64_t bot_id = 0; }; namespace DataBucketLoadType { enum Type : uint8 { Bot, + Account, Client, MaxType }; static const std::string Name[Type::MaxType] = { "Bot", + "Account", "Client", }; } diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index 566510cf9..4be953bb4 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -3464,6 +3464,42 @@ void Lua_Client::SetAAEXPPercentage(uint8 percentage) self->SetAAEXPPercentage(percentage); } +void Lua_Client::SetAccountBucket(std::string bucket_name, std::string bucket_value) +{ + Lua_Safe_Call_Void(); + self->SetAccountBucket(bucket_name, bucket_value); +} + +void Lua_Client::SetAccountBucket(std::string bucket_name, std::string bucket_value, std::string expiration) +{ + Lua_Safe_Call_Void(); + self->SetAccountBucket(bucket_name, bucket_value, expiration); +} + +void Lua_Client::DeleteAccountBucket(std::string bucket_name) +{ + Lua_Safe_Call_Void(); + self->DeleteAccountBucket(bucket_name); +} + +std::string Lua_Client::GetAccountBucket(std::string bucket_name) +{ + Lua_Safe_Call_String(); + return self->GetAccountBucket(bucket_name); +} + +std::string Lua_Client::GetAccountBucketExpires(std::string bucket_name) +{ + Lua_Safe_Call_String(); + return self->GetAccountBucketExpires(bucket_name); +} + +std::string Lua_Client::GetAccountBucketRemaining(std::string bucket_name) +{ + Lua_Safe_Call_String(); + return self->GetAccountBucketRemaining(bucket_name); +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3552,6 +3588,7 @@ luabind::scope lua_register_client() { .def("CreateTaskDynamicZone", &Lua_Client::CreateTaskDynamicZone) .def("DecreaseByID", (bool(Lua_Client::*)(uint32,int))&Lua_Client::DecreaseByID) .def("DescribeSpecialAbilities", (void(Lua_Client::*)(Lua_NPC))&Lua_Client::DescribeSpecialAbilities) + .def("DeleteAccountBucket", (void(Lua_Client::*)(std::string))&Lua_Client::DeleteAccountBucket) .def("DeleteBucket", (void(Lua_Client::*)(std::string))&Lua_Client::DeleteBucket) .def("DeleteItemInInventory", (void(Lua_Client::*)(int,int))&Lua_Client::DeleteItemInInventory) .def("DeleteItemInInventory", (void(Lua_Client::*)(int,int,bool))&Lua_Client::DeleteItemInInventory) @@ -3630,6 +3667,9 @@ luabind::scope lua_register_client() { .def("GetBotRequiredLevel", (int(Lua_Client::*)(uint8))&Lua_Client::GetBotRequiredLevel) .def("GetBotSpawnLimit", (int(Lua_Client::*)(void))&Lua_Client::GetBotSpawnLimit) .def("GetBotSpawnLimit", (int(Lua_Client::*)(uint8))&Lua_Client::GetBotSpawnLimit) + .def("GetAccountBucket", (std::string(Lua_Client::*)(std::string))&Lua_Client::GetAccountBucket) + .def("GetAccountBucketExpires", (std::string(Lua_Client::*)(std::string))&Lua_Client::GetAccountBucketExpires) + .def("GetAccountBucketRemaining", (std::string(Lua_Client::*)(std::string))&Lua_Client::GetAccountBucketRemaining) .def("GetBucket", (std::string(Lua_Client::*)(std::string))&Lua_Client::GetBucket) .def("GetBucketExpires", (std::string(Lua_Client::*)(std::string))&Lua_Client::GetBucketExpires) .def("GetBucketRemaining", (std::string(Lua_Client::*)(std::string))&Lua_Client::GetBucketRemaining) @@ -3922,6 +3962,8 @@ luabind::scope lua_register_client() { .def("SetBotRequiredLevel", (void(Lua_Client::*)(int,uint8))&Lua_Client::SetBotRequiredLevel) .def("SetBotSpawnLimit", (void(Lua_Client::*)(int))&Lua_Client::SetBotSpawnLimit) .def("SetBotSpawnLimit", (void(Lua_Client::*)(int,uint8))&Lua_Client::SetBotSpawnLimit) + .def("SetAccountBucket", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetAccountBucket) + .def("SetAccountBucket", (void(Lua_Client::*)(std::string,std::string,std::string))&Lua_Client::SetAccountBucket) .def("SetBucket", (void(Lua_Client::*)(std::string,std::string))&Lua_Client::SetBucket) .def("SetBucket", (void(Lua_Client::*)(std::string,std::string,std::string))&Lua_Client::SetBucket) .def("SetClientMaxLevel", (void(Lua_Client::*)(int))&Lua_Client::SetClientMaxLevel) diff --git a/zone/lua_client.h b/zone/lua_client.h index d86705f2e..082504fc0 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -512,6 +512,14 @@ public: luabind::object GetInventorySlots(lua_State* L); void SetAAEXPPercentage(uint8 percentage); + // account data buckets + void SetAccountBucket(std::string bucket_name, std::string bucket_value); + void SetAccountBucket(std::string bucket_name, std::string bucket_value, std::string expiration = ""); + void DeleteAccountBucket(std::string bucket_name); + std::string GetAccountBucket(std::string bucket_name); + std::string GetAccountBucketExpires(std::string bucket_name); + std::string GetAccountBucketRemaining(std::string bucket_name); + void ApplySpell(int spell_id); void ApplySpell(int spell_id, int duration); void ApplySpell(int spell_id, int duration, int level); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index d86c70bf4..c4a66ec2d 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -3234,6 +3234,36 @@ void Perl_Client_SetAAEXPPercentage(Client* self, uint8 percentage) self->SetAAEXPPercentage(percentage); } +void Perl_Client_SetAccountBucket(Client* self, std::string bucket_name, std::string bucket_value) +{ + self->SetAccountBucket(bucket_name, bucket_value); +} + +void Perl_Client_SetAccountBucket(Client* self, std::string bucket_name, std::string bucket_value, std::string expiration = "") +{ + self->SetAccountBucket(bucket_name, bucket_value, expiration); +} + +void Perl_Client_DeleteAccountBucket(Client* self, std::string bucket_name) +{ + self->DeleteAccountBucket(bucket_name); +} + +std::string Perl_Client_GetAccountBucket(Client* self, std::string bucket_name) +{ + return self->GetAccountBucket(bucket_name); +} + +std::string Perl_Client_GetAccountBucketExpires(Client* self, std::string bucket_name) +{ + return self->GetAccountBucketExpires(bucket_name); +} + +std::string Perl_Client_GetAccountBucketRemaining(Client* self, std::string bucket_name) +{ + return self->GetAccountBucketRemaining(bucket_name); +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3325,6 +3355,7 @@ void perl_register_client() package.add("CreateTaskDynamicZone", &Perl_Client_CreateTaskDynamicZone); package.add("DecreaseByID", &Perl_Client_DecreaseByID); package.add("DescribeSpecialAbilities", &Perl_Client_DescribeSpecialAbilities); + package.add("DeleteAccountBucket", &Perl_Client_DeleteAccountBucket); package.add("DeleteItemInInventory", (void(*)(Client*, int16))&Perl_Client_DeleteItemInInventory); package.add("DeleteItemInInventory", (void(*)(Client*, int16, int16))&Perl_Client_DeleteItemInInventory); package.add("DeleteItemInInventory", (void(*)(Client*, int16, int16, bool))&Perl_Client_DeleteItemInInventory); @@ -3362,6 +3393,9 @@ void perl_register_client() package.add("GetAAPoints", &Perl_Client_GetAAPoints); package.add("GetAFK", &Perl_Client_GetAFK); package.add("GetAccountAge", &Perl_Client_GetAccountAge); + package.add("GetAccountBucket", &Perl_Client_GetAccountBucket); + package.add("GetAccountBucketExpires", &Perl_Client_GetAccountBucketExpires); + package.add("GetGetAccountBucketRemaining", &Perl_Client_GetAccountBucketRemaining); package.add("GetAccountFlag", &Perl_Client_GetAccountFlag); package.add("GetAccountFlags", &Perl_Client_GetAccountFlags); package.add("GetAggroCount", &Perl_Client_GetAggroCount); @@ -3668,6 +3702,8 @@ void perl_register_client() package.add("SetAATitle", (void(*)(Client*, std::string, bool))&Perl_Client_SetAATitle); package.add("SetAFK", &Perl_Client_SetAFK); package.add("SetAccountFlag", &Perl_Client_SetAccountFlag); + package.add("SetAccountBucket", (void(*)(Client*, std::string, std::string))&Perl_Client_SetAccountBucket); + package.add("SetAccountBucket", (void(*)(Client*, std::string, std::string, std::string))&Perl_Client_SetAccountBucket); package.add("SetAlternateCurrencyValue", &Perl_Client_SetAlternateCurrencyValue); package.add("SetAnon", &Perl_Client_SetAnon); package.add("SetAutoLoginCharacterName", (bool(*)(Client*))&Perl_Client_SetAutoLoginCharacterName);