diff --git a/CHANGELOG.md b/CHANGELOG.md index dcfa1f1bc..a7ea71c2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,68 @@ +## [22.61.0] 1/6/2025 + +### Bots + +* Fix AA ranks to account for level ([#4567](https://github.com/EQEmu/Server/pull/4567)) @nytmyr 2024-12-07 + +### Code + +* Convert Event Parses to Single Line ([#4569](https://github.com/EQEmu/Server/pull/4569)) @Kinglykrab 2024-12-12 +* Fix GM Flag Spell Restriction Bypasses ([#4571](https://github.com/EQEmu/Server/pull/4571)) @Kinglykrab 2025-01-06 +* Remove Unused Group Methods ([#4559](https://github.com/EQEmu/Server/pull/4559)) @Kinglykrab 2024-12-12 + +### Commands + +* Add #find bot Subcommand ([#4563](https://github.com/EQEmu/Server/pull/4563)) @Kinglykrab 2024-12-12 +* Add #find ldon_theme Subcommand ([#4564](https://github.com/EQEmu/Server/pull/4564)) @Kinglykrab 2024-12-12 +* Fix #copycharacter ([#4582](https://github.com/EQEmu/Server/pull/4582)) @Akkadius 2025-01-06 + +### Databuckets + +* Improved Reliability and Performance of Databuckets ([#4562](https://github.com/EQEmu/Server/pull/4562)) @Akkadius 2024-12-12 + +### Feature + +* Enable bazaar window 'Find Trader' functionality ([#4560](https://github.com/EQEmu/Server/pull/4560)) @neckkola 2024-12-12 + +### Filesystem + +* Path Manager Improvements ([#4557](https://github.com/EQEmu/Server/pull/4557)) @Akkadius 2025-01-06 + +### Fixes + +* Allow Items in ROF2 to Stack to 32,767 ([#4556](https://github.com/EQEmu/Server/pull/4556)) @Kinglykrab 2024-12-12 +* Fix EVENT_COMBAT on NPC Death ([#4558](https://github.com/EQEmu/Server/pull/4558)) @Kinglykrab 2024-11-28 +* Guild Membership Update Fix ([#4581](https://github.com/EQEmu/Server/pull/4581)) @neckkola 2025-01-06 +* Guild creation to propagate across zones ([#4575](https://github.com/EQEmu/Server/pull/4575)) @neckkola 2025-01-06 +* Repair a EQEMUConfig Memory Leak ([#4584](https://github.com/EQEmu/Server/pull/4584)) @neckkola 2025-01-06 +* Repair a LoadNPCEmote MemoryLeak ([#4586](https://github.com/EQEmu/Server/pull/4586)) @neckkola 2025-01-06 +* Repair a memory leak in GuildsList ([#4585](https://github.com/EQEmu/Server/pull/4585)) @neckkola 2025-01-06 +* Resolve a client crash when logging in or zoning ([#4572](https://github.com/EQEmu/Server/pull/4572)) @neckkola 2024-12-14 + +### Groups + +* Fix AmIMainAssist incorrectly checking for MainTankName ([#4565](https://github.com/EQEmu/Server/pull/4565)) @nytmyr 2024-12-04 + +### Inventory + +* Add GetInventorySlots() Method ([#4566](https://github.com/EQEmu/Server/pull/4566)) @Kinglykrab 2025-01-06 + +### Logs + +* Improve Crash log defaults ([#4579](https://github.com/EQEmu/Server/pull/4579)) @Akkadius 2025-01-06 + +### Maps + +* Fix broken Map MMFS implementation ([#4576](https://github.com/EQEmu/Server/pull/4576)) @Akkadius 2025-01-06 + +### Network + +* Prune / disconnect TCP connections gracefully ([#4574](https://github.com/EQEmu/Server/pull/4574)) @Akkadius 2025-01-06 + +### Rules + +* Add rules for requiring custom files from client ([#4561](https://github.com/EQEmu/Server/pull/4561)) @knervous 2024-12-12 + ## [22.60.0] 11/25/2024 ### Bazaar diff --git a/CMakeLists.txt b/CMakeLists.txt index 83dacc20f..f93cabb22 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,9 @@ IF(EQEMU_ADD_PROFILER) SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--no-as-needed,-lprofiler,--as-needed") ENDIF(EQEMU_ADD_PROFILER) +IF(USE_MAP_MMFS) + ADD_DEFINITIONS(-DUSE_MAP_MMFS) +ENDIF (USE_MAP_MMFS) IF(MSVC) ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) diff --git a/common/crash.cpp b/common/crash.cpp index cb02a0bb4..3828a9af0 100644 --- a/common/crash.cpp +++ b/common/crash.cpp @@ -294,6 +294,8 @@ void print_trace() SendCrashReport(crash_report); } + LogSys.CloseFileLogs(); + exit(1); } diff --git a/common/database.cpp b/common/database.cpp index c0193b927..a3405970d 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -1860,7 +1860,35 @@ bool Database::CopyCharacter( const int64 new_character_id = (CharacterDataRepository::GetMaxId(*this) + 1); - std::vector tables_to_zero_id = { "keyring", "data_buckets", "character_instance_safereturns" }; + // validate destination name doesn't exist already + const auto& destination_characters = CharacterDataRepository::GetWhere( + *this, + fmt::format( + "`name` = '{}' AND `deleted_at` IS NULL LIMIT 1", + Strings::Escape(destination_character_name) + ) + ); + if (!destination_characters.empty()) { + LogError("Character [{}] already exists", destination_character_name); + return false; + } + + std::vector tables_to_zero_id = { + "keyring", + "data_buckets", + "character_instance_safereturns", + "character_expedition_lockouts", + "character_instance_lockouts", + "character_parcels", + "character_tribute", + "player_titlesets", + }; + + std::vector ignore_tables = { + "guilds", + }; + + size_t total_rows_copied = 0; TransactionBegin(); @@ -1868,6 +1896,10 @@ bool Database::CopyCharacter( const std::string& table_name = t.first; const std::string& character_id_column_name = t.second; + if (Strings::Contains(ignore_tables, table_name)) { + continue; + } + auto results = QueryDatabase( fmt::format( "SHOW COLUMNS FROM {}", @@ -1918,6 +1950,10 @@ bool Database::CopyCharacter( value = std::to_string(destination_account_id); } + if (!Strings::IsNumber(value)) { + value = Strings::Escape(value); + } + new_values.emplace_back(value); } @@ -1950,6 +1986,11 @@ bool Database::CopyCharacter( ) ); + size_t rows_copied = insert_rows.size(); // Rows copied for this table + total_rows_copied += rows_copied; // Increment grand total + + LogInfo("Copying table [{}] rows [{}]", table_name, Strings::Commify(rows_copied)); + if (!insert.ErrorMessage().empty()) { TransactionRollback(); return false; @@ -1959,6 +2000,13 @@ bool Database::CopyCharacter( TransactionCommit(); + LogInfo( + "Character [{}] copied to [{}] total rows [{}]", + source_character_name, + destination_character_name, + Strings::Commify(total_rows_copied) + ); + return true; } diff --git a/common/database/database_update_manifest.cpp b/common/database/database_update_manifest.cpp index 61186a205..fde8820f0 100644 --- a/common/database/database_update_manifest.cpp +++ b/common/database/database_update_manifest.cpp @@ -5782,6 +5782,17 @@ CREATE INDEX idx_bot_expires ON data_buckets (bot_id, expires); ALTER TABLE `trader` ADD COLUMN `char_zone_instance_id` INT NULL DEFAULT '0' AFTER `char_zone_id`; )" + }, + ManifestEntry{ + .version = 9287, + .description = "2024_11_26_bazaar_find_trader.sql", + .check = "SHOW COLUMNS FROM `npc_types` LIKE 'walkspeed'", + .condition = "missing", + .match = "float", + .sql = R"( +ALTER TABLE `npc_types` MODIFY COLUMN `walkspeed` float NOT NULL DEFAULT 0; +)", + .content_schema_update = true } // -- template; copy/paste this when you need to create a new entry // ManifestEntry{ diff --git a/common/eqemu_config.h b/common/eqemu_config.h index 7e9e3b341..0ce295ece 100644 --- a/common/eqemu_config.h +++ b/common/eqemu_config.h @@ -137,9 +137,9 @@ class EQEmuConfig { } - virtual ~EQEmuConfig() {} public: + virtual ~EQEmuConfig() {} // Produce a const singleton static const EQEmuConfig *get() diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index c4c14f82f..18ef3efcc 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -25,6 +25,8 @@ #include "repositories/discord_webhooks_repository.h" #include "repositories/logsys_categories_repository.h" #include "termcolor/rang.hpp" +#include "path_manager.h" +#include "file.h" #include #include @@ -85,6 +87,7 @@ EQEmuLogSys *EQEmuLogSys::LoadLogSettingsDefaults() * Set Defaults */ log_settings[Logs::Crash].log_to_console = static_cast(Logs::General); + log_settings[Logs::Crash].log_to_file = static_cast(Logs::General); log_settings[Logs::MySQLError].log_to_console = static_cast(Logs::General); log_settings[Logs::NPCScaling].log_to_gmsay = static_cast(Logs::General); log_settings[Logs::HotReload].log_to_gmsay = static_cast(Logs::General); @@ -532,6 +535,11 @@ void EQEmuLogSys::StartFileLogs(const std::string &log_name) { EQEmuLogSys::CloseFileLogs(); + if (!File::Exists(path.GetLogPath())) { + LogInfo("Logs directory not found, creating [{}]", path.GetLogPath()); + File::Makedir(path.GetLogPath()); + } + /** * When loading settings, we must have been given a reason in category based logging to output to a file in order to even create or open one... */ diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index df81e516c..595b9f025 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -612,9 +612,9 @@ bool EQ::InventoryProfile::HasAugmentEquippedByID(uint32 item_id) return has_equipped; } -int EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id) +uint32 EQ::InventoryProfile::CountAugmentEquippedByID(uint32 item_id) { - int quantity = 0; + uint32 quantity = 0; ItemInstance* item = nullptr; for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) { @@ -643,9 +643,9 @@ bool EQ::InventoryProfile::HasItemEquippedByID(uint32 item_id) return has_equipped; } -int EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id) +uint32 EQ::InventoryProfile::CountItemEquippedByID(uint32 item_id) { - int quantity = 0; + uint32 quantity = 0; ItemInstance* item = nullptr; for (int slot_id = EQ::invslot::EQUIPMENT_BEGIN; slot_id <= EQ::invslot::EQUIPMENT_END; ++slot_id) { @@ -1807,4 +1807,4 @@ int16 EQ::InventoryProfile::FindFirstFreeSlotThatFitsItem(const EQ::ItemData *it } } return 0; -} \ No newline at end of file +} diff --git a/common/inventory_profile.h b/common/inventory_profile.h index 100d5ebd8..4761e1b97 100644 --- a/common/inventory_profile.h +++ b/common/inventory_profile.h @@ -147,13 +147,13 @@ namespace EQ bool HasItemEquippedByID(uint32 item_id); // Check how many of a specific item the player has equipped by Item ID - int CountItemEquippedByID(uint32 item_id); + uint32 CountItemEquippedByID(uint32 item_id); // Check if player has a specific augment equipped by Item ID bool HasAugmentEquippedByID(uint32 item_id); // Check how many of a specific augment the player has equipped by Item ID - int CountAugmentEquippedByID(uint32 item_id); + uint32 CountAugmentEquippedByID(uint32 item_id); // Get a list of augments from a specific slot ID std::vector GetAugmentIDsBySlotID(int16 slot_id); diff --git a/common/net/tcp_connection.cpp b/common/net/tcp_connection.cpp index 0c2512dcc..ae1f14bad 100644 --- a/common/net/tcp_connection.cpp +++ b/common/net/tcp_connection.cpp @@ -80,6 +80,8 @@ void EQ::Net::TCPConnection::Start() { } } else if (nread == UV_EOF) { + connection->Disconnect(); + if (buf->base) { delete[] buf->base; } diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 38106fd2a..ef27f06c2 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -487,7 +487,7 @@ namespace RoF2 VARSTRUCT_ENCODE_TYPE(uint32, bufptr, i.item_stat); //itemstat } - safe_delete(in->pBuffer); + safe_delete_array(in->pBuffer); in->size = p_size; in->pBuffer = (uchar *) buffer.get(); dest->QueuePacket(in); @@ -508,7 +508,7 @@ namespace RoF2 eq->num_of_traders = emu->traders; eq->num_of_items = emu->items; - safe_delete(in->pBuffer); + safe_delete_array(in->pBuffer); in->SetOpcode(OP_TraderShop); in->size = sizeof(structs::BazaarWelcome_Struct); in->pBuffer = (uchar *) buffer.get(); @@ -1845,11 +1845,11 @@ namespace RoF2 } } - auto outapp = new EQApplicationPacket(OP_GuildsList); - outapp->size = packet_size; - outapp->pBuffer = buffer; + safe_delete_array(in->pBuffer); - dest->FastQueuePacket(&outapp); + in->pBuffer = buffer; + in->size = packet_size; + dest->FastQueuePacket(&in); } ENCODE(OP_GuildTributeDonateItem) diff --git a/common/path_manager.cpp b/common/path_manager.cpp index 452722c84..b767b8003 100644 --- a/common/path_manager.cpp +++ b/common/path_manager.cpp @@ -5,31 +5,19 @@ #include "strings.h" #include + namespace fs = std::filesystem; -inline std::string striptrailingslash(const std::string &file_path) -{ - if (file_path.back() == '/' || file_path.back() == '\\') { - return file_path.substr(0, file_path.length() - 1); - } - - return file_path; -} - void PathManager::LoadPaths() { m_server_path = File::FindEqemuConfigPath(); - if (!m_server_path.empty()) { - std::filesystem::current_path(m_server_path); - } - if (m_server_path.empty()) { LogInfo("Failed to load server path"); return; } - LogInfo("server [{}]", m_server_path); + std::filesystem::current_path(m_server_path); if (!EQEmuConfig::LoadConfig()) { LogError("Failed to load eqemu config"); @@ -38,66 +26,64 @@ void PathManager::LoadPaths() const auto c = EQEmuConfig::get(); - // maps - if (File::Exists(fs::path{m_server_path + "/" + c->MapDir}.string())) { - m_maps_path = fs::relative(fs::path{m_server_path + "/" + c->MapDir}).string(); - } - else if (File::Exists(fs::path{m_server_path + "/maps"}.string())) { - m_maps_path = fs::relative(fs::path{m_server_path + "/maps"}).string(); - } - else if (File::Exists(fs::path{m_server_path + "/Maps"}.string())) { - m_maps_path = fs::relative(fs::path{m_server_path + "/Maps"}).string(); - } + auto resolve_path = [&](const std::string& dir, const std::vector& fallback_dirs = {}) -> std::string { + // relative + if (File::Exists((fs::path{m_server_path} / dir).string())) { + return fs::relative(fs::path{m_server_path} / dir).lexically_normal().string(); + } - // quests - if (File::Exists(fs::path{m_server_path + "/" + c->QuestDir}.string())) { - m_quests_path = fs::relative(fs::path{m_server_path + "/" + c->QuestDir}).string(); - } + // absolute + if (File::Exists(fs::path{dir}.string())) { + return fs::absolute(fs::path{dir}).string(); + } - // plugins - if (File::Exists(fs::path{m_server_path + "/" + c->PluginDir}.string())) { - m_plugins_path = fs::relative(fs::path{m_server_path + "/" + c->PluginDir}).string(); - } + // fallback search options if specified + for (const auto& fallback : fallback_dirs) { + if (File::Exists((fs::path{m_server_path} / fallback).string())) { + return fs::relative(fs::path{m_server_path} / fallback).lexically_normal().string(); + } + } - // lua_modules - if (File::Exists(fs::path{m_server_path + "/" + c->LuaModuleDir}.string())) { - m_lua_modules_path = fs::relative(fs::path{m_server_path + "/" + c->LuaModuleDir}).string(); - } + // if all else fails, just set it to the config value + return dir; + }; - // lua mods - if (File::Exists(fs::path{ m_server_path + "/mods" }.string())) { - m_lua_mods_path = fs::relative(fs::path{ m_server_path + "/mods" }).string(); - } + m_maps_path = resolve_path(c->MapDir, {"maps", "Maps"}); + m_quests_path = resolve_path(c->QuestDir); + m_plugins_path = resolve_path(c->PluginDir); + m_lua_modules_path = resolve_path(c->LuaModuleDir); + m_lua_mods_path = resolve_path("mods"); + m_patch_path = resolve_path(c->PatchDir); + m_opcode_path = resolve_path(c->OpcodeDir); + m_shared_memory_path = resolve_path(c->SharedMemDir); + m_log_path = resolve_path(c->LogDir, {"logs"}); - // patches - if (File::Exists(fs::path{m_server_path + "/" + c->PatchDir}.string())) { - m_patch_path = fs::relative(fs::path{m_server_path + "/" + c->PatchDir}).string(); - } + // Log all paths in a loop + std::vector> paths = { + {"server", m_server_path}, + {"logs", m_log_path}, + {"lua mods", m_lua_mods_path}, + {"lua_modules", m_lua_modules_path}, + {"maps", m_maps_path}, + {"patches", m_patch_path}, + {"opcode", m_opcode_path}, + {"plugins", m_plugins_path}, + {"quests", m_quests_path}, + {"shared_memory", m_shared_memory_path} + }; - // patches - if (File::Exists(fs::path{ m_server_path + "/" + c->OpcodeDir }.string())) { - m_opcode_path = fs::relative(fs::path{ m_server_path + "/" + c->OpcodeDir }).string(); - } + constexpr int name_width = 15; + constexpr int path_width = 0; + constexpr int break_length = 70; - // shared_memory_path - if (File::Exists(fs::path{m_server_path + "/" + c->SharedMemDir}.string())) { - m_shared_memory_path = fs::relative(fs::path{ m_server_path + "/" + c->SharedMemDir }).string(); + std::cout << std::endl; + LogInfo("{}", Strings::Repeat("-", break_length)); + for (const auto& [name, in_path] : paths) { + if (!in_path.empty()) { + LogInfo("{:>{}} > [{:<{}}]", name, name_width, in_path, path_width); + } } - - // logging path - if (File::Exists(fs::path{m_server_path + "/" + c->LogDir}.string())) { - m_log_path = fs::relative(fs::path{m_server_path + "/" + c->LogDir}).string(); - } - - LogInfo("logs path [{}]", m_log_path); - LogInfo("lua mods path [{}]", m_lua_mods_path); - LogInfo("lua_modules path [{}]", m_lua_modules_path); - LogInfo("maps path [{}]", m_maps_path); - LogInfo("patches path [{}]", m_patch_path); - LogInfo("opcode path [{}]", m_opcode_path); - LogInfo("plugins path [{}]", m_plugins_path); - LogInfo("quests path [{}]", m_quests_path); - LogInfo("shared_memory path [{}]", m_shared_memory_path); + LogInfo("{}", Strings::Repeat("-", break_length)); } const std::string &PathManager::GetServerPath() const diff --git a/common/version.h b/common/version.h index c5cb5d19f..db0c5fc76 100644 --- a/common/version.h +++ b/common/version.h @@ -25,7 +25,7 @@ // Build variables // these get injected during the build pipeline -#define CURRENT_VERSION "22.60.0-dev" // always append -dev to the current version for custom-builds +#define CURRENT_VERSION "22.61.0-dev" // always append -dev to the current version for custom-builds #define LOGIN_VERSION "0.8.0" #define COMPILE_DATE __DATE__ #define COMPILE_TIME __TIME__ @@ -42,7 +42,7 @@ * Manifest: https://github.com/EQEmu/Server/blob/master/utils/sql/db_update_manifest.txt */ -#define CURRENT_BINARY_DATABASE_VERSION 9286 +#define CURRENT_BINARY_DATABASE_VERSION 9287 #define CURRENT_BINARY_BOTS_DATABASE_VERSION 9054 #endif diff --git a/loginserver/world_server.cpp b/loginserver/world_server.cpp index b43651fd7..e4b7ac358 100644 --- a/loginserver/world_server.cpp +++ b/loginserver/world_server.cpp @@ -51,12 +51,6 @@ WorldServer::WorldServer(std::shared_ptr wo ServerOP_LSAccountUpdate, std::bind(&WorldServer::ProcessLSAccountUpdate, this, std::placeholders::_1, std::placeholders::_2) ); - - m_keepalive = std::make_unique( - 1000, - true, - std::bind(&WorldServer::OnKeepAlive, this, std::placeholders::_1) - ); } WorldServer::~WorldServer() = default; @@ -1307,12 +1301,6 @@ const std::string &WorldServer::GetVersion() const return m_version; } -void WorldServer::OnKeepAlive(EQ::Timer *t) -{ - ServerPacket pack(ServerOP_KeepAlive, 0); - m_connection->SendPacket(&pack); -} - void WorldServer::FormatWorldServerName(char *name, int8 server_list_type) { std::string server_long_name = name; diff --git a/loginserver/world_server.h b/loginserver/world_server.h index df5324240..45cecfebd 100644 --- a/loginserver/world_server.h +++ b/loginserver/world_server.h @@ -187,13 +187,6 @@ private: bool m_is_server_logged_in; bool m_is_server_trusted; - /** - * Keepalive - * @param t - */ - void OnKeepAlive(EQ::Timer *t); - std::unique_ptr m_keepalive; - static void FormatWorldServerName(char *name, int8 server_list_type); }; diff --git a/package.json b/package.json index 26dfe3d29..68a2da55e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eqemu-server", - "version": "22.60.0", + "version": "22.61.0", "repository": { "type": "git", "url": "https://github.com/EQEmu/Server.git" diff --git a/world/cli/copy_character.cpp b/world/cli/copy_character.cpp index 7d915ad15..86c268217 100644 --- a/world/cli/copy_character.cpp +++ b/world/cli/copy_character.cpp @@ -12,12 +12,12 @@ void WorldserverCLI::CopyCharacter(int argc, char **argv, argh::parser &cmd, std }; std::vector options = {}; + EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); + if (cmd[{"-h", "--help"}]) { return; } - EQEmuCommand::ValidateCmdInput(arguments, options, cmd, argc, argv); - std::string source_character_name = cmd(2).str(); std::string destination_character_name = cmd(3).str(); std::string destination_account_name = cmd(4).str(); diff --git a/world/login_server.cpp b/world/login_server.cpp index b2017f094..b647aedf0 100644 --- a/world/login_server.cpp +++ b/world/login_server.cpp @@ -595,11 +595,6 @@ bool LoginServer::Connect() ); } - m_keepalive = std::make_unique( - 1000, - true, - std::bind(&LoginServer::OnKeepAlive, this, std::placeholders::_1)); - return true; } @@ -716,8 +711,3 @@ void LoginServer::SendAccountUpdate(ServerPacket *pack) } } -void LoginServer::OnKeepAlive(EQ::Timer *t) -{ - ServerPacket pack(ServerOP_KeepAlive, 0); - SendPacket(&pack); -} diff --git a/world/login_server.h b/world/login_server.h index 21e25870f..0a5e6a107 100644 --- a/world/login_server.h +++ b/world/login_server.h @@ -50,7 +50,6 @@ private: void ProcessLSRemoteAddr(uint16_t opcode, EQ::Net::Packet &p); void ProcessLSAccountUpdate(uint16_t opcode, EQ::Net::Packet &p); - void OnKeepAlive(EQ::Timer *t); std::unique_ptr m_keepalive; std::unique_ptr m_client; diff --git a/world/queryserv.cpp b/world/queryserv.cpp index 0611e7d50..847cb90e0 100644 --- a/world/queryserv.cpp +++ b/world/queryserv.cpp @@ -22,7 +22,6 @@ void QueryServConnection::AddConnection(std::shared_ptrOnMessage(ServerOP_QueryServGeneric, std::bind(&QueryServConnection::HandleGenericMessage, this, std::placeholders::_1, std::placeholders::_2)); connection->OnMessage(ServerOP_LFGuildUpdate, std::bind(&QueryServConnection::HandleLFGuildUpdateMessage, this, std::placeholders::_1, std::placeholders::_2)); m_streams.emplace(std::make_pair(connection->GetUUID(), connection)); - m_keepalive = std::make_unique(1000, true, std::bind(&QueryServConnection::OnKeepAlive, this, std::placeholders::_1)); } void QueryServConnection::RemoveConnection(std::shared_ptr connection) @@ -54,8 +53,3 @@ bool QueryServConnection::SendPacket(ServerPacket* pack) return true; } -void QueryServConnection::OnKeepAlive(EQ::Timer *t) -{ - ServerPacket pack(ServerOP_KeepAlive, 0); - SendPacket(&pack); -} diff --git a/world/queryserv.h b/world/queryserv.h index a02aab647..028fdcbbd 100644 --- a/world/queryserv.h +++ b/world/queryserv.h @@ -15,7 +15,6 @@ public: void HandleGenericMessage(uint16_t opcode, EQ::Net::Packet &p); void HandleLFGuildUpdateMessage(uint16_t opcode, EQ::Net::Packet &p); bool SendPacket(ServerPacket* pack); - void OnKeepAlive(EQ::Timer *t); private: std::map> m_streams; std::unique_ptr m_keepalive; diff --git a/world/ucs.cpp b/world/ucs.cpp index 0af363051..0cc70a0ea 100644 --- a/world/ucs.cpp +++ b/world/ucs.cpp @@ -31,8 +31,6 @@ void UCSConnection::SetConnection(std::shared_ptr(1000, true, std::bind(&UCSConnection::OnKeepAlive, this, std::placeholders::_1)); } const std::shared_ptr &UCSConnection::GetConnection() const @@ -92,13 +90,3 @@ void UCSConnection::SendMessage(const char *From, const char *Message) SendPacket(pack); safe_delete(pack); } - -void UCSConnection::OnKeepAlive(EQ::Timer *t) -{ - if (!connection) { - return; - } - - ServerPacket pack(ServerOP_KeepAlive, 0); - connection->SendPacket(&pack); -} diff --git a/world/ucs.h b/world/ucs.h index d226e4dc9..04ec17471 100644 --- a/world/ucs.h +++ b/world/ucs.h @@ -23,11 +23,6 @@ private: inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; } std::shared_ptr connection; - /** - * Keepalive - */ - std::unique_ptr m_keepalive; - void OnKeepAlive(EQ::Timer *t); }; #endif /*UCS_H_*/ diff --git a/world/zonelist.cpp b/world/zonelist.cpp index 31427552a..c2e572a68 100644 --- a/world/zonelist.cpp +++ b/world/zonelist.cpp @@ -42,7 +42,6 @@ ZSList::ZSList() memset(pLockedZones, 0, sizeof(pLockedZones)); m_tick = std::make_unique(5000, true, std::bind(&ZSList::OnTick, this, std::placeholders::_1)); - m_keepalive = std::make_unique(1000, true, std::bind(&ZSList::OnKeepAlive, this, std::placeholders::_1)); } ZSList::~ZSList() { @@ -846,13 +845,6 @@ void ZSList::OnTick(EQ::Timer *t) web_interface.SendEvent(out); } -void ZSList::OnKeepAlive(EQ::Timer *t) -{ - for (auto &zone : zone_server_list) { - zone->SendKeepAlive(); - } -} - const std::list> &ZSList::getZoneServerList() const { return zone_server_list; diff --git a/world/zonelist.h b/world/zonelist.h index 71d364c9b..e096f0363 100644 --- a/world/zonelist.h +++ b/world/zonelist.h @@ -72,7 +72,6 @@ public: private: void OnTick(EQ::Timer *t); - void OnKeepAlive(EQ::Timer *t); uint32 NextID; uint16 pLockedZones[MaxLockedZones]; uint32 CurGroupID; diff --git a/zone/client.cpp b/zone/client.cpp index 8b5d57737..31ac137c9 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -10466,27 +10466,15 @@ void Client::SendToInstance(std::string instance_type, std::string zone_short_na MovePC(zone_id, instance_id, x, y, z, heading); } -int Client::CountItem(uint32 item_id) +uint32 Client::CountItem(uint32 item_id) { - int quantity = 0; + uint32 quantity = 0; EQ::ItemInstance *item = nullptr; - static const int16 slots[][2] = { - { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, - { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, - { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, - { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, - { EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END }, - { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, - { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, - { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, - }; - const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { - for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { - item = GetInv().GetItem(slot_id); - if (item && item->GetID() == item_id) { - quantity += (item->IsStackable() ? item->GetCharges() : 1); - } + + for (const int16& slot_id : GetInventorySlots()) { + item = GetInv().GetItem(slot_id); + if (item && item->GetID() == item_id) { + quantity += (item->IsStackable() ? item->GetCharges() : 1); } } @@ -10503,30 +10491,26 @@ void Client::ResetItemCooldown(uint32 item_id) int recast_type = item_d->RecastType; bool found_item = false; - static const int16 slots[][2] = { - { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, - { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, - { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, - { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, - { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, - { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, - { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, - }; - const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { - for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { - item = GetInv().GetItem(slot_id); - if (item) { - item_d = item->GetItem(); - if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) { - item->SetRecastTimestamp(0); - DeleteItemRecastTimer(item_d->ID); - SendItemPacket(slot_id, item, ItemPacketCharmUpdate); - found_item = true; - } + for (const int16& slot_id : GetInventorySlots()) { + item = GetInv().GetItem(slot_id); + if (item) { + item_d = item->GetItem(); + if ( + item_d && + item->GetID() == item_id || + ( + item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && + item_d->RecastType == recast_type + ) + ) { + item->SetRecastTimestamp(0); + DeleteItemRecastTimer(item_d->ID); + SendItemPacket(slot_id, item, ItemPacketCharmUpdate); + found_item = true; } } } + if (!found_item) { DeleteItemRecastTimer(item_id); //We didn't find the item but we still want to remove the timer } @@ -10561,25 +10545,20 @@ void Client::SetItemCooldown(uint32 item_id, bool use_saved_timer, uint32 in_sec final_time = total_time - current_time; } - static const int16 slots[][2] = { - { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, - { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, - { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, - { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, - { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, - { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, - { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, - }; - const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { - for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { - item = GetInv().GetItem(slot_id); - if (item) { - item_d = item->GetItem(); - if (item_d && item->GetID() == item_id || (item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && item_d->RecastType == recast_type)) { - item->SetRecastTimestamp(total_time); - SendItemPacket(slot_id, item, ItemPacketCharmUpdate); - } + for (const int16& slot_id : GetInventorySlots()) { + item = GetInv().GetItem(slot_id); + if (item) { + item_d = item->GetItem(); + if ( + item_d && + item->GetID() == item_id || + ( + item_d->RecastType != RECAST_TYPE_UNLINKED_ITEM && + item_d->RecastType == recast_type + ) + ) { + item->SetRecastTimestamp(total_time); + SendItemPacket(slot_id, item, ItemPacketCharmUpdate); } } } @@ -10622,38 +10601,26 @@ uint32 Client::GetItemCooldown(uint32 item_id) void Client::RemoveItem(uint32 item_id, uint32 quantity) { + uint32 removed_count = 0; EQ::ItemInstance *item = nullptr; - static const int16 slots[][2] = { - { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, - { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, - { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, - { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, - { EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END }, - { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, - { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, - { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, - }; - int16 removed_count = 0; - const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { - for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { - if (removed_count == quantity) { - break; - } - item = GetInv().GetItem(slot_id); - if (item && item->GetID() == item_id) { - int16 charges = item->IsStackable() ? item->GetCharges() : 0; - int16 stack_size = std::max(charges, static_cast(1)); - if ((removed_count + stack_size) <= quantity) { - removed_count += stack_size; - DeleteItemInInventory(slot_id, charges, true); - } else { - int16 amount_left = (quantity - removed_count); - if (amount_left > 0 && stack_size >= amount_left) { - removed_count += amount_left; - DeleteItemInInventory(slot_id, amount_left, true); - } + for (const int16& slot_id : GetInventorySlots()) { + if (removed_count == quantity) { + break; + } + + item = GetInv().GetItem(slot_id); + if (item && item->GetID() == item_id) { + uint32 charges = item->IsStackable() ? item->GetCharges() : 0; + uint32 stack_size = std::max(charges, static_cast(1)); + if ((removed_count + stack_size) <= quantity) { + removed_count += stack_size; + DeleteItemInInventory(slot_id, charges, true); + } else { + uint32 amount_left = (quantity - removed_count); + if (amount_left > 0 && stack_size >= amount_left) { + removed_count += amount_left; + DeleteItemInInventory(slot_id, amount_left, true); } } } @@ -12825,37 +12792,28 @@ uint16 Client::GetSkill(EQ::skills::SkillType skill_id) const void Client::RemoveItemBySerialNumber(uint32 serial_number, uint32 quantity) { EQ::ItemInstance *item = nullptr; - static const int16 slots[][2] = { - { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, - { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, - { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, - { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, - { EQ::invslot::GUILD_TRIBUTE_BEGIN, EQ::invslot::GUILD_TRIBUTE_END }, - { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, - { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, - { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, - }; - int16 removed_count = 0; - const size_t slot_index_count = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < slot_index_count; ++slot_index) { - for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { - if (removed_count == quantity) { - break; - } - item = GetInv().GetItem(slot_id); - if (item && item->GetSerialNumber() == serial_number) { - int16 charges = item->IsStackable() ? item->GetCharges() : 0; - int16 stack_size = std::max(charges, static_cast(1)); - if ((removed_count + stack_size) <= quantity) { - removed_count += stack_size; - DeleteItemInInventory(slot_id, charges, true); - } else { - int16 amount_left = (quantity - removed_count); - if (amount_left > 0 && stack_size >= amount_left) { - removed_count += amount_left; - DeleteItemInInventory(slot_id, amount_left, true); - } + uint32 removed_count = 0; + + const auto& slot_ids = GetInventorySlots(); + + for (const int16& slot_id : slot_ids) { + if (removed_count == quantity) { + break; + } + + item = GetInv().GetItem(slot_id); + if (item && item->GetSerialNumber() == serial_number) { + uint32 charges = item->IsStackable() ? item->GetCharges() : 0; + uint32 stack_size = std::max(charges, static_cast(1)); + if ((removed_count + stack_size) <= quantity) { + removed_count += stack_size; + DeleteItemInInventory(slot_id, charges, true); + } else { + uint32 amount_left = (quantity - removed_count); + if (amount_left > 0 && stack_size >= amount_left) { + removed_count += amount_left; + DeleteItemInInventory(slot_id, amount_left, true); } } } @@ -13081,6 +13039,31 @@ void Client::ClientToNpcAggroProcess() } } +const std::vector& Client::GetInventorySlots() +{ + static const std::vector> slots = { + { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, + { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, + { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END }, + { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, + { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, + { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, + { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, + }; + + static std::vector slot_ids; + + if (slot_ids.empty()) { + for (const auto& [begin, end] : slots) { + for (int16 slot_id = begin; slot_id <= end; ++slot_id) { + slot_ids.emplace_back(slot_id); + } + } + } + + return slot_ids; +} + void Client::LoadDefaultBotSettings() { _spellSettings.clear(); diff --git a/zone/client.h b/zone/client.h index c4ffd5460..d7d01cda3 100644 --- a/zone/client.h +++ b/zone/client.h @@ -467,6 +467,7 @@ public: inline ExtendedProfile_Struct& GetEPP() { return m_epp; } inline EQ::InventoryProfile& GetInv() { return m_inv; } inline const EQ::InventoryProfile& GetInv() const { return m_inv; } + const std::vector& GetInventorySlots(); inline PetInfo* GetPetInfo(int pet_info_type) { return pet_info_type == PetInfoType::Suspended ? &m_suspendedminion : &m_petinfo; } inline InspectMessage_Struct& GetInspectMessage() { return m_inspect_message; } inline const InspectMessage_Struct& GetInspectMessage() const { return m_inspect_message; } @@ -1093,7 +1094,7 @@ public: bool PushItemOnCursor(const EQ::ItemInstance& inst, bool client_update = false); void SendCursorBuffer(); void DeleteItemInInventory(int16 slot_id, int16 quantity = 0, bool client_update = false, bool update_db = true); - int CountItem(uint32 item_id); + uint32 CountItem(uint32 item_id); void ResetItemCooldown(uint32 item_id); void SetItemCooldown(uint32 item_id, bool use_saved_timer = false, uint32 in_seconds = 1); uint32 GetItemCooldown(uint32 item_id); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 72ebaa72c..c60daee44 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -864,7 +864,7 @@ void Client::CompleteConnect() if (IsInAGuild()) { if (firstlogon == 1) { guild_mgr.UpdateDbMemberOnline(CharacterID(), true); - guild_mgr.SendToWorldSendGuildMembersList(GuildID()); + SendGuildMembersList(); } guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), zone->GetZoneID(), time(nullptr)); @@ -7947,6 +7947,7 @@ void Client::Handle_OP_GuildCreate(const EQApplicationPacket *app) SetGuildID(new_guild_id); SendGuildList(); guild_mgr.MemberAdd(new_guild_id, CharacterID(), GetLevel(), GetClass(), GUILD_LEADER, GetZoneID(), GetName()); + guild_mgr.SendGuildRefresh(new_guild_id, true, true, true, true); guild_mgr.SendToWorldSendGuildList(); SendGuildSpawnAppearance(); diff --git a/zone/client_process.cpp b/zone/client_process.cpp index a1fb7080a..aff3399dd 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -179,7 +179,7 @@ bool Client::Process() { } if (IsInAGuild()) { guild_mgr.UpdateDbMemberOnline(CharacterID(), false); - guild_mgr.SendToWorldSendGuildMembersList(GuildID()); + guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr)); } SetDynamicZoneMemberStatus(DynamicZoneMemberStatus::Offline); @@ -206,7 +206,7 @@ bool Client::Process() { Save(); if (IsInAGuild()) { guild_mgr.UpdateDbMemberOnline(CharacterID(), false); - guild_mgr.SendToWorldSendGuildMembersList(GuildID()); + guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr)); } if (GetMerc()) @@ -582,7 +582,7 @@ bool Client::Process() { } if (IsInAGuild()) { guild_mgr.UpdateDbMemberOnline(CharacterID(), false); - guild_mgr.SendToWorldSendGuildMembersList(GuildID()); + guild_mgr.SendGuildMemberUpdateToWorld(GetName(), GuildID(), 0, time(nullptr)); } return false; diff --git a/zone/corpse.cpp b/zone/corpse.cpp index e54dd2e63..4a0d8de09 100644 --- a/zone/corpse.cpp +++ b/zone/corpse.cpp @@ -1871,9 +1871,10 @@ bool Corpse::HasItem(uint32 item_id) return false; } -uint16 Corpse::CountItem(uint32 item_id) +uint32 Corpse::CountItem(uint32 item_id) { - uint16 item_count = 0; + uint32 item_count = 0; + if (!database.GetItem(item_id)) { return item_count; } @@ -1893,6 +1894,7 @@ uint16 Corpse::CountItem(uint32 item_id) item_count += i->charges > 0 ? i->charges : 1; } } + return item_count; } diff --git a/zone/corpse.h b/zone/corpse.h index 28fc8c91a..c1925c325 100644 --- a/zone/corpse.h +++ b/zone/corpse.h @@ -196,7 +196,7 @@ public: /* Corpse: Loot */ void QueryLoot(Client *to); bool HasItem(uint32 item_id); - uint16 CountItem(uint32 item_id); + uint32 CountItem(uint32 item_id); uint32 GetItemIDBySlot(uint16 loot_slot); uint16 GetFirstLootSlotByItemID(uint32 item_id); std::vector GetLootList(); diff --git a/zone/embparser_api.cpp b/zone/embparser_api.cpp index d18796a4e..c451db90b 100644 --- a/zone/embparser_api.cpp +++ b/zone/embparser_api.cpp @@ -1446,7 +1446,7 @@ int Perl__collectitems(uint32_t item_id, bool remove_item) return quest_manager.collectitems(item_id, remove_item); } -int Perl__countitem(uint32_t item_id) +uint32 Perl__countitem(uint32_t item_id) { return quest_manager.countitem(item_id); } diff --git a/zone/gm_commands/emptyinventory.cpp b/zone/gm_commands/emptyinventory.cpp index 582512289..e37167db6 100644 --- a/zone/gm_commands/emptyinventory.cpp +++ b/zone/gm_commands/emptyinventory.cpp @@ -2,31 +2,21 @@ void command_emptyinventory(Client *c, const Seperator *sep) { - auto target = c; + Client* t = c; if (c->GetGM() && c->GetTarget() && c->GetTarget()->IsClient()) { - target = c->GetTarget()->CastToClient(); + t = c->GetTarget()->CastToClient(); } EQ::ItemInstance *item = nullptr; - static const int16 slots[][2] = { - { EQ::invslot::POSSESSIONS_BEGIN, EQ::invslot::POSSESSIONS_END }, - { EQ::invbag::GENERAL_BAGS_BEGIN, EQ::invbag::GENERAL_BAGS_END }, - { EQ::invbag::CURSOR_BAG_BEGIN, EQ::invbag::CURSOR_BAG_END}, - { EQ::invslot::BANK_BEGIN, EQ::invslot::BANK_END }, - { EQ::invbag::BANK_BAGS_BEGIN, EQ::invbag::BANK_BAGS_END }, - { EQ::invslot::SHARED_BANK_BEGIN, EQ::invslot::SHARED_BANK_END }, - { EQ::invbag::SHARED_BANK_BAGS_BEGIN, EQ::invbag::SHARED_BANK_BAGS_END }, - }; - int removed_count = 0; - const size_t size = sizeof(slots) / sizeof(slots[0]); - for (int slot_index = 0; slot_index < size; ++slot_index) { - for (int slot_id = slots[slot_index][0]; slot_id <= slots[slot_index][1]; ++slot_id) { - item = target->GetInv().GetItem(slot_id); - if (item) { - int stack_size = std::max(static_cast(item->GetCharges()), 1); - removed_count += stack_size; - target->DeleteItemInInventory(slot_id, 0, true); - } + uint32 removed_count = 0; + + for (const int16& slot_id : t->GetInventorySlots()) { + item = t->GetInv().GetItem(slot_id); + + if (item) { + uint32 stack_size = std::max(static_cast(item->GetCharges()), static_cast(1)); + removed_count += stack_size; + t->DeleteItemInInventory(slot_id, 0, true); } } @@ -35,8 +25,8 @@ void command_emptyinventory(Client *c, const Seperator *sep) Chat::White, fmt::format( "{} {} no items to delete.", - c->GetTargetDescription(target, TargetDescriptionType::UCYou), - c == target ? "have" : "has" + c->GetTargetDescription(t, TargetDescriptionType::UCYou), + c == t ? "have" : "has" ).c_str() ); return; @@ -46,9 +36,9 @@ void command_emptyinventory(Client *c, const Seperator *sep) Chat::White, fmt::format( "Inventory cleared for {}, {} item{} deleted.", - c->GetTargetDescription(target), + c->GetTargetDescription(t), removed_count, removed_count != 1 ? "s" : "" ).c_str() ); -} \ No newline at end of file +} diff --git a/zone/gm_commands/summonitem.cpp b/zone/gm_commands/summonitem.cpp index ddee8ab07..b72292a97 100755 --- a/zone/gm_commands/summonitem.cpp +++ b/zone/gm_commands/summonitem.cpp @@ -132,4 +132,6 @@ void command_summonitem(Client *c, const Seperator *sep) item_link ).c_str() ); + + safe_delete(new_item); } diff --git a/zone/guild_mgr.h b/zone/guild_mgr.h index 3256d82d2..00ca287b9 100644 --- a/zone/guild_mgr.h +++ b/zone/guild_mgr.h @@ -83,9 +83,9 @@ public: void SendRankName(uint32 guild_id, uint32 rank, std::string rank_name); void SendAllRankNames(uint32 guild_id, uint32 char_id); BaseGuildManager::GuildInfo* GetGuildByGuildID(uint32 guild_id); + virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation); protected: - virtual void SendGuildRefresh(uint32 guild_id, bool name, bool motd, bool rank, bool relation); virtual void SendCharRefresh(uint32 old_guild_id, uint32 guild_id, uint32 charid); virtual void SendRankUpdate(uint32 CharID); virtual void SendGuildDelete(uint32 guild_id); diff --git a/zone/loot.cpp b/zone/loot.cpp index 6fcf22cca..a330914e2 100644 --- a/zone/loot.cpp +++ b/zone/loot.cpp @@ -859,9 +859,9 @@ bool NPC::HasItem(uint32 item_id) return false; } -uint16 NPC::CountItem(uint32 item_id) +uint32 NPC::CountItem(uint32 item_id) { - uint16 item_count = 0; + uint32 item_count = 0; if (!database.GetItem(item_id)) { return item_count; } diff --git a/zone/lua_bot.cpp b/zone/lua_bot.cpp index 323976fe0..dd208ae45 100644 --- a/zone/lua_bot.cpp +++ b/zone/lua_bot.cpp @@ -269,7 +269,7 @@ void Lua_Bot::SetSpellDurationRaid(int spell_id, int duration, int level, bool a self->SetSpellDuration(spell_id, duration, level, ApplySpellType::Raid, allow_pets, is_raid_group_only); } -int Lua_Bot::CountAugmentEquippedByID(uint32 item_id) { +uint32 Lua_Bot::CountAugmentEquippedByID(uint32 item_id) { Lua_Safe_Call_Int(); return self->GetInv().CountAugmentEquippedByID(item_id); } @@ -279,7 +279,7 @@ bool Lua_Bot::HasAugmentEquippedByID(uint32 item_id) { return self->GetInv().HasAugmentEquippedByID(item_id); } -int Lua_Bot::CountItemEquippedByID(uint32 item_id) { +uint32 Lua_Bot::CountItemEquippedByID(uint32 item_id) { Lua_Safe_Call_Int(); return self->GetInv().CountItemEquippedByID(item_id); } @@ -702,8 +702,9 @@ luabind::scope lua_register_bot() { .def("ClearItemReuseTimer", (void(Lua_Bot::*)(uint32))&Lua_Bot::ClearItemReuseTimer) .def("ClearSpellRecastTimer", (void(Lua_Bot::*)())&Lua_Bot::ClearSpellRecastTimer) .def("ClearSpellRecastTimer", (void(Lua_Bot::*)(uint16))&Lua_Bot::ClearSpellRecastTimer) + .def("CountAugmentEquippedByID", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountAugmentEquippedByID) .def("CountBotItem", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountBotItem) - .def("CountItemEquippedByID", (int(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID) + .def("CountItemEquippedByID", (uint32(Lua_Bot::*)(uint32))&Lua_Bot::CountItemEquippedByID) .def("DeleteBot", (void(Lua_Bot::*)(void))&Lua_Bot::DeleteBot) .def("DeleteBucket", (void(Lua_Bot::*)(std::string))&Lua_Bot::DeleteBucket) .def("Escape", (void(Lua_Bot::*)(void))&Lua_Bot::Escape) diff --git a/zone/lua_bot.h b/zone/lua_bot.h index 1a5fdefd9..d0b94d654 100644 --- a/zone/lua_bot.h +++ b/zone/lua_bot.h @@ -127,8 +127,8 @@ public: void SetSpellRecastTimer(uint16 spell_id); void SetSpellRecastTimer(uint16 spell_id, uint32 reuse_timer); - int CountAugmentEquippedByID(uint32 item_id); - int CountItemEquippedByID(uint32 item_id); + uint32 CountAugmentEquippedByID(uint32 item_id); + uint32 CountItemEquippedByID(uint32 item_id); bool HasAugmentEquippedByID(uint32 item_id); bool HasItemEquippedByID(uint32 item_id); int GetHealAmount(); diff --git a/zone/lua_client.cpp b/zone/lua_client.cpp index f8d5ca64d..13982fcc0 100644 --- a/zone/lua_client.cpp +++ b/zone/lua_client.cpp @@ -2287,7 +2287,7 @@ void Lua_Client::SendToInstance(std::string instance_type, std::string zone_shor self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration); } -int Lua_Client::CountItem(uint32 item_id) { +uint32 Lua_Client::CountItem(uint32 item_id) { Lua_Safe_Call_Int(); return self->CountItem(item_id); } @@ -2480,7 +2480,7 @@ void Lua_Client::AddItem(luabind::object item_table) { ); } -int Lua_Client::CountAugmentEquippedByID(uint32 item_id) { +uint32 Lua_Client::CountAugmentEquippedByID(uint32 item_id) { Lua_Safe_Call_Int(); return self->GetInv().CountAugmentEquippedByID(item_id); } @@ -2490,7 +2490,7 @@ bool Lua_Client::HasAugmentEquippedByID(uint32 item_id) { return self->GetInv().HasAugmentEquippedByID(item_id); } -int Lua_Client::CountItemEquippedByID(uint32 item_id) { +uint32 Lua_Client::CountItemEquippedByID(uint32 item_id) { Lua_Safe_Call_Int(); return self->GetInv().CountItemEquippedByID(item_id); } @@ -3436,6 +3436,21 @@ void Lua_Client::AreaTaunt(float range, int bonus_hate) entity_list.AETaunt(self, range, bonus_hate); } +luabind::object Lua_Client::GetInventorySlots(lua_State* L) { + auto lua_table = luabind::newtable(L); + + if (d_) { + auto self = reinterpret_cast(d_); + int index = 1; + for (const int16& slot_id : self->GetInventorySlots()) { + lua_table[index] = slot_id; + index++; + } + } + + return lua_table; +} + luabind::scope lua_register_client() { return luabind::class_("Client") .def(luabind::constructor<>()) @@ -3514,9 +3529,9 @@ luabind::scope lua_register_client() { .def("ClearXTargets", (void(Lua_Client::*)(void))&Lua_Client::ClearXTargets) .def("ClearZoneFlag", (void(Lua_Client::*)(uint32))&Lua_Client::ClearZoneFlag) .def("Connected", (bool(Lua_Client::*)(void))&Lua_Client::Connected) - .def("CountAugmentEquippedByID", (int(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID) - .def("CountItem", (int(Lua_Client::*)(uint32))&Lua_Client::CountItem) - .def("CountItemEquippedByID", (int(Lua_Client::*)(uint32))&Lua_Client::CountItemEquippedByID) + .def("CountAugmentEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountAugmentEquippedByID) + .def("CountItem", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItem) + .def("CountItemEquippedByID", (uint32(Lua_Client::*)(uint32))&Lua_Client::CountItemEquippedByID) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(luabind::object))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32))&Lua_Client::CreateExpedition) .def("CreateExpedition", (Lua_Expedition(Lua_Client::*)(std::string, uint32, uint32, std::string, uint32, uint32, bool))&Lua_Client::CreateExpedition) @@ -3650,6 +3665,7 @@ luabind::scope lua_register_client() { .def("GetInstrumentMod", (int(Lua_Client::*)(int))&Lua_Client::GetInstrumentMod) .def("GetIntoxication", (int(Lua_Client::*)(void))&Lua_Client::GetIntoxication) .def("GetInventory", (Lua_Inventory(Lua_Client::*)(void))&Lua_Client::GetInventory) + .def("GetInventorySlots", (luabind::object(Lua_Client::*)(lua_State* L))&Lua_Client::GetInventorySlots) .def("GetInvulnerableEnvironmentDamage", (bool(Lua_Client::*)(void))&Lua_Client::GetInvulnerableEnvironmentDamage) .def("GetItemIDAt", (int(Lua_Client::*)(int))&Lua_Client::GetItemIDAt) .def("GetItemCooldown", (uint32(Lua_Client::*)(uint32))&Lua_Client::GetItemCooldown) diff --git a/zone/lua_client.h b/zone/lua_client.h index faff8b157..fb012b3bc 100644 --- a/zone/lua_client.h +++ b/zone/lua_client.h @@ -441,14 +441,14 @@ public: void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration); void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two); void Popup(const char* title, const char* text, uint32 popup_id, uint32 negative_id, uint32 button_type, uint32 duration, const char* button_name_one, const char* button_name_two, uint32 sound_controls); - int CountItem(uint32 item_id); + uint32 CountItem(uint32 item_id); void RemoveItem(uint32 item_id); void RemoveItem(uint32 item_id, uint32 quantity); void SetGMStatus(int new_status); int16 GetGMStatus(); void AddItem(luabind::object item_table); - int CountAugmentEquippedByID(uint32 item_id); - int CountItemEquippedByID(uint32 item_id); + uint32 CountAugmentEquippedByID(uint32 item_id); + uint32 CountItemEquippedByID(uint32 item_id); bool HasAugmentEquippedByID(uint32 item_id); bool HasItemEquippedByID(uint32 item_id); int GetHealAmount(); @@ -509,6 +509,7 @@ public: void AreaTaunt(); void AreaTaunt(float range); void AreaTaunt(float range, int bonus_hate); + luabind::object GetInventorySlots(lua_State* L); void ApplySpell(int spell_id); void ApplySpell(int spell_id, int duration); diff --git a/zone/lua_corpse.cpp b/zone/lua_corpse.cpp index 321e4e543..2db6bad07 100644 --- a/zone/lua_corpse.cpp +++ b/zone/lua_corpse.cpp @@ -177,7 +177,7 @@ bool Lua_Corpse::HasItem(uint32 item_id) { return self->HasItem(item_id); } -uint16 Lua_Corpse::CountItem(uint32 item_id) { +uint32 Lua_Corpse::CountItem(uint32 item_id) { Lua_Safe_Call_Int(); return self->CountItem(item_id); } @@ -226,7 +226,7 @@ luabind::scope lua_register_corpse() { .def("AllowMobLoot", (void(Lua_Corpse::*)(Lua_Mob, uint8))&Lua_Corpse::AllowMobLoot) .def("Bury", (void(Lua_Corpse::*)(void))&Lua_Corpse::Bury) .def("CanMobLoot", (bool(Lua_Corpse::*)(int))&Lua_Corpse::CanMobLoot) - .def("CountItem", (uint16(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem) + .def("CountItem", (uint32(Lua_Corpse::*)(uint32))&Lua_Corpse::CountItem) .def("CountItems", (uint32(Lua_Corpse::*)(void))&Lua_Corpse::CountItems) .def("Delete", (void(Lua_Corpse::*)(void))&Lua_Corpse::Delete) .def("Depop", (void(Lua_Corpse::*)(void))&Lua_Corpse::Depop) diff --git a/zone/lua_corpse.h b/zone/lua_corpse.h index 9ad63e979..58bfb7d05 100644 --- a/zone/lua_corpse.h +++ b/zone/lua_corpse.h @@ -62,7 +62,7 @@ public: uint32 GetPlatinum(); void AddLooter(Lua_Mob who); bool HasItem(uint32 item_id); - uint16 CountItem(uint32 item_id); + uint32 CountItem(uint32 item_id); uint32 GetItemIDBySlot(uint16 loot_slot); uint16 GetFirstLootSlotByItemID(uint32 item_id); Lua_Corpse_Loot_List GetLootList(lua_State* L); diff --git a/zone/lua_inventory.cpp b/zone/lua_inventory.cpp index 48987de68..3d464a915 100644 --- a/zone/lua_inventory.cpp +++ b/zone/lua_inventory.cpp @@ -164,7 +164,7 @@ int Lua_Inventory::GetSlotByItemInst(Lua_ItemInst inst) { return self->GetSlotByItemInst(inst); } -int Lua_Inventory::CountAugmentEquippedByID(uint32 item_id) { +uint32 Lua_Inventory::CountAugmentEquippedByID(uint32 item_id) { Lua_Safe_Call_Int(); return self->CountAugmentEquippedByID(item_id); } @@ -174,7 +174,7 @@ bool Lua_Inventory::HasAugmentEquippedByID(uint32 item_id) { return self->HasAugmentEquippedByID(item_id); } -int Lua_Inventory::CountItemEquippedByID(uint32 item_id) { +uint32 Lua_Inventory::CountItemEquippedByID(uint32 item_id) { Lua_Safe_Call_Int(); return self->CountItemEquippedByID(item_id); } @@ -208,8 +208,8 @@ luabind::scope lua_register_inventory() { .def("CalcSlotId", (int(Lua_Inventory::*)(int,int))&Lua_Inventory::CalcSlotId) .def("CanItemFitInContainer", (bool(Lua_Inventory::*)(Lua_Item,Lua_Item))&Lua_Inventory::CanItemFitInContainer) .def("CheckNoDrop", (bool(Lua_Inventory::*)(int))&Lua_Inventory::CheckNoDrop) - .def("CountAugmentEquippedByID", (int(Lua_Inventory::*)(uint32))&Lua_Inventory::CountAugmentEquippedByID) - .def("CountItemEquippedByID", (int(Lua_Inventory::*)(uint32))&Lua_Inventory::CountItemEquippedByID) + .def("CountAugmentEquippedByID", (uint32(Lua_Inventory::*)(uint32))&Lua_Inventory::CountAugmentEquippedByID) + .def("CountItemEquippedByID", (uint32(Lua_Inventory::*)(uint32))&Lua_Inventory::CountItemEquippedByID) .def("DeleteItem", (bool(Lua_Inventory::*)(int))&Lua_Inventory::DeleteItem) .def("DeleteItem", (bool(Lua_Inventory::*)(int,int))&Lua_Inventory::DeleteItem) .def("FindFreeSlot", (int(Lua_Inventory::*)(bool,bool))&Lua_Inventory::FindFreeSlot) diff --git a/zone/lua_inventory.h b/zone/lua_inventory.h index 472447e62..a9c5c8d5e 100644 --- a/zone/lua_inventory.h +++ b/zone/lua_inventory.h @@ -43,8 +43,8 @@ public: bool DeleteItem(int slot_id); bool DeleteItem(int slot_id, int quantity); bool CheckNoDrop(int slot_id); - int CountAugmentEquippedByID(uint32 item_id); - int CountItemEquippedByID(uint32 item_id); + uint32 CountAugmentEquippedByID(uint32 item_id); + uint32 CountItemEquippedByID(uint32 item_id); Lua_ItemInst PopItem(int slot_id); bool HasAugmentEquippedByID(uint32 item_id); bool HasItemEquippedByID(uint32 item_id); diff --git a/zone/lua_npc.cpp b/zone/lua_npc.cpp index b17804edc..aa0973292 100644 --- a/zone/lua_npc.cpp +++ b/zone/lua_npc.cpp @@ -597,7 +597,7 @@ bool Lua_NPC::HasItem(uint32 item_id) return self->HasItem(item_id); } -uint16 Lua_NPC::CountItem(uint32 item_id) +uint32 Lua_NPC::CountItem(uint32 item_id) { Lua_Safe_Call_Int(); return self->CountItem(item_id); @@ -862,7 +862,7 @@ luabind::scope lua_register_npc() { .def("CheckNPCFactionAlly", (int(Lua_NPC::*)(int))&Lua_NPC::CheckNPCFactionAlly) .def("ClearItemList", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLootItems) .def("ClearLastName", (void(Lua_NPC::*)(void))&Lua_NPC::ClearLastName) - .def("CountItem", (uint16(Lua_NPC::*)(uint32))&Lua_NPC::CountItem) + .def("CountItem", (uint32(Lua_NPC::*)(uint32))&Lua_NPC::CountItem) .def("CountLoot", (int(Lua_NPC::*)(void))&Lua_NPC::CountLoot) .def("DeleteBucket", (void(Lua_NPC::*)(std::string))&Lua_NPC::DeleteBucket) .def("DescribeSpecialAbilities", (void(Lua_NPC::*)(Lua_Client))&Lua_NPC::DescribeSpecialAbilities) diff --git a/zone/lua_npc.h b/zone/lua_npc.h index ec916593a..180bddad0 100644 --- a/zone/lua_npc.h +++ b/zone/lua_npc.h @@ -146,7 +146,7 @@ public: void ChangeLastName(std::string last_name); void ClearLastName(); bool HasItem(uint32 item_id); - uint16 CountItem(uint32 item_id); + uint32 CountItem(uint32 item_id); uint32 GetLootItemIDBySlot(uint16 loot_slot); uint16 GetFirstLootSlotByItemID(uint32 item_id); float GetHealScale(); diff --git a/zone/map.cpp b/zone/map.cpp index 410392e8a..96feddb9c 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -320,7 +320,7 @@ bool Map::Load(const std::string &filename) } #ifdef USE_MAP_MMFS - if (v) + if (loaded_map_file) return SaveMMF(filename, force_mmf_overwrite); #endif /*USE_MAP_MMFS*/ @@ -338,7 +338,7 @@ bool Map::Load(const std::string &filename) } #ifdef USE_MAP_MMFS - if (v) + if (loaded_map_file) return SaveMMF(filename, force_mmf_overwrite); #endif /*USE_MAP_MMFS*/ @@ -1064,7 +1064,7 @@ bool Map::LoadMMF(const std::string& map_file_name, bool force_mmf_overwrite) fclose(f); std::vector rm_buffer(rm_buffer_size); - uint32 v = InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size); + uint32 v = EQ::InflateData(mmf_buffer.data(), mmf_buffer_size, rm_buffer.data(), rm_buffer_size); if (imp) { imp->rm->release(); @@ -1120,11 +1120,11 @@ bool Map::SaveMMF(const std::string& map_file_name, bool force_mmf_overwrite) } uint32 rm_buffer_size = rm_buffer.size(); - uint32 mmf_buffer_size = EstimateDeflateBuffer(rm_buffer.size()); + uint32 mmf_buffer_size = EQ::EstimateDeflateBuffer(rm_buffer.size()); std::vector mmf_buffer(mmf_buffer_size); - mmf_buffer_size = DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size()); + mmf_buffer_size = EQ::DeflateData(rm_buffer.data(), rm_buffer.size(), mmf_buffer.data(), mmf_buffer.size()); if (!mmf_buffer_size) { LogInfo("Failed to save Map MMF file: [{}] - null MMF buffer size", mmf_file_name.c_str()); return false; diff --git a/zone/npc.h b/zone/npc.h index a20d975b1..9b17afaba 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -222,7 +222,7 @@ public: void RemoveLootCash(); void QueryLoot(Client *to, bool is_pet_query = false); bool HasItem(uint32 item_id); - uint16 CountItem(uint32 item_id); + uint32 CountItem(uint32 item_id); uint32 GetLootItemIDBySlot(uint16 loot_slot); uint16 GetFirstLootSlotByItemID(uint32 item_id); std::vector GetLootList(); diff --git a/zone/perl_bot.cpp b/zone/perl_bot.cpp index 2bce3f647..ae9484bfc 100644 --- a/zone/perl_bot.cpp +++ b/zone/perl_bot.cpp @@ -145,7 +145,7 @@ EQ::ItemInstance* Perl_Bot_GetAugmentAt(Bot* self, int16 slot_id, uint8 augment_ return nullptr; } -int Perl_Bot_CountAugmentEquippedByID(Bot* self, uint32 item_id) +uint32 Perl_Bot_CountAugmentEquippedByID(Bot* self, uint32 item_id) { return self->GetInv().CountAugmentEquippedByID(item_id); } @@ -155,7 +155,7 @@ bool Perl_Bot_HasAugmentEquippedByID(Bot* self, uint32 item_id) return self->GetInv().HasAugmentEquippedByID(item_id); } -int Perl_Bot_CountItemEquippedByID(Bot* self, uint32 item_id) +uint32 Perl_Bot_CountItemEquippedByID(Bot* self, uint32 item_id) { return self->GetInv().CountItemEquippedByID(item_id); } @@ -651,7 +651,7 @@ void perl_register_bot() package.add("ApplySpellRaid", (void(*)(Bot*, int, int, int, bool, bool))&Perl_Bot_ApplySpellRaid); package.add("BotGroupSay", &Perl_Bot_BotGroupSay); package.add("Camp", (void(*)(Bot*))&Perl_Bot_Camp); - package.add("Camp", (void(*)(Bot*, bool))&Perl_Bot_Camp); + package.add("Camp", (void(*)(Bot*, bool))&Perl_Bot_Camp); package.add("ClearDisciplineReuseTimer", (void(*)(Bot*))&Perl_Bot_ClearDisciplineReuseTimer); package.add("ClearDisciplineReuseTimer", (void(*)(Bot*, uint16))&Perl_Bot_ClearDisciplineReuseTimer); package.add("ClearItemReuseTimer", (void(*)(Bot*))&Perl_Bot_ClearItemReuseTimer); diff --git a/zone/perl_client.cpp b/zone/perl_client.cpp index 528445d41..df15be6fc 100644 --- a/zone/perl_client.cpp +++ b/zone/perl_client.cpp @@ -2209,7 +2209,7 @@ void Perl_Client_SendToInstance(Client* self, std::string instance_type, std::st self->SendToInstance(instance_type, zone_short_name, instance_version, x, y, z, heading, instance_identifier, duration); } -int Perl_Client_CountItem(Client* self, uint32 item_id) +uint32 Perl_Client_CountItem(Client* self, uint32 item_id) { return self->CountItem(item_id); } @@ -2388,7 +2388,7 @@ void Perl_Client_AddItem(Client* self, perl::reference table_ref) augment_four, augment_five, augment_six, attuned, slot_id); } -int Perl_Client_CountAugmentEquippedByID(Client* self, uint32 item_id) +uint32 Perl_Client_CountAugmentEquippedByID(Client* self, uint32 item_id) { return self->GetInv().CountAugmentEquippedByID(item_id); } @@ -2398,7 +2398,7 @@ bool Perl_Client_HasAugmentEquippedByID(Client* self, uint32 item_id) return self->GetInv().HasAugmentEquippedByID(item_id); } -int Perl_Client_CountItemEquippedByID(Client* self, uint32 item_id) +uint32 Perl_Client_CountItemEquippedByID(Client* self, uint32 item_id) { return self->GetInv().CountItemEquippedByID(item_id); } @@ -3212,6 +3212,18 @@ Merc* Perl_Client_GetMerc(Client* self) return self->GetMerc(); } +perl::array Perl_Client_GetInventorySlots(Client* self) +{ + perl::array result; + const auto& v = self->GetInventorySlots(); + + for (int i = 0; i < v.size(); ++i) { + result.push_back(v[i]); + } + + return result; +} + void perl_register_client() { perl::interpreter perl(PERL_GET_THX); @@ -3426,6 +3438,7 @@ void perl_register_client() package.add("GetInstanceID", &Perl_Client_GetInstanceID); package.add("GetInstrumentMod", &Perl_Client_GetInstrumentMod); package.add("GetInventory", &Perl_Client_GetInventory); + package.add("GetInventorySlots", &Perl_Client_GetInventorySlots); package.add("GetInvulnerableEnvironmentDamage", &Perl_Client_GetInvulnerableEnvironmentDamage); package.add("GetItemAt", &Perl_Client_GetItemAt); package.add("GetItemCooldown", &Perl_Client_GetItemCooldown); diff --git a/zone/perl_inventory.cpp b/zone/perl_inventory.cpp index ba083e936..a002a24a7 100644 --- a/zone/perl_inventory.cpp +++ b/zone/perl_inventory.cpp @@ -150,7 +150,7 @@ bool Perl_Inventory_HasAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t return self->HasAugmentEquippedByID(item_id); } -int Perl_Inventory_CountAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) +uint32 Perl_Inventory_CountAugmentEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) { return self->CountAugmentEquippedByID(item_id); } @@ -160,7 +160,7 @@ bool Perl_Inventory_HasItemEquippedByID(EQ::InventoryProfile* self, uint32_t ite return self->HasItemEquippedByID(item_id); } -int Perl_Inventory_CountItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) +uint32 Perl_Inventory_CountItemEquippedByID(EQ::InventoryProfile* self, uint32_t item_id) { return self->CountItemEquippedByID(item_id); } diff --git a/zone/perl_npc.cpp b/zone/perl_npc.cpp index 4f0999376..ce3d8ba17 100644 --- a/zone/perl_npc.cpp +++ b/zone/perl_npc.cpp @@ -615,7 +615,7 @@ bool Perl_NPC_HasItem(NPC* self, uint32 item_id) // @categories Script Utility return self->HasItem(item_id); } -int Perl_NPC_CountItem(NPC* self, uint32 item_id) +uint32 Perl_NPC_CountItem(NPC* self, uint32 item_id) { return self->CountItem(item_id); } diff --git a/zone/perl_player_corpse.cpp b/zone/perl_player_corpse.cpp index 60de30201..c034e0312 100644 --- a/zone/perl_player_corpse.cpp +++ b/zone/perl_player_corpse.cpp @@ -161,7 +161,7 @@ bool Perl_Corpse_HasItem(Corpse* self, uint32_t item_id) // @categories Script U return self->HasItem(item_id); } -int Perl_Corpse_CountItem(Corpse* self, uint32_t item_id) // @categories Script Utility +uint32 Perl_Corpse_CountItem(Corpse* self, uint32_t item_id) // @categories Script Utility { return self->CountItem(item_id); } diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 6be160943..1b11ebbe1 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -3304,7 +3304,7 @@ int QuestManager::collectitems(uint32 item_id, bool remove) return quantity; } -int QuestManager::countitem(uint32 item_id) { +uint32 QuestManager::countitem(uint32 item_id) { QuestManagerCurrentQuestVars(); if (!initiator) { diff --git a/zone/questmgr.h b/zone/questmgr.h index 1f872aaf5..c73596f4e 100644 --- a/zone/questmgr.h +++ b/zone/questmgr.h @@ -249,7 +249,7 @@ public: int getlevel(uint8 type); int collectitems(uint32 item_id, bool remove); int collectitems_processSlot(int16 slot_id, uint32 item_id, bool remove); - int countitem(uint32 item_id); + uint32 countitem(uint32 item_id); void removeitem(uint32 item_id, uint32 quantity = 1); std::string getitemcomment(uint32 item_id); std::string getitemlore(uint32 item_id); diff --git a/zone/spells.cpp b/zone/spells.cpp index 3559e56d3..8d427aeb1 100644 --- a/zone/spells.cpp +++ b/zone/spells.cpp @@ -644,6 +644,11 @@ bool Mob::DoCastingChecksOnCaster(int32 spell_id, CastingSlot slot) { return true; } +struct SpellCheck { + std::function condition; // The condition to check + std::function action; // The action if the condition fails +}; + bool Mob::DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id) { /* @@ -651,114 +656,92 @@ bool Mob::DoCastingChecksZoneRestrictions(bool check_on_casting, int32 spell_id) - levitate zone restriction (client blocks) [cancel before begin cast message] - can not cast outdoor [cancels after spell finishes channeling] - If the spell is a casted spell, check on CastSpell and ignore on SpellFinished. - If the spell is a initiated from SpellFinished, then check at start of SpellFinished. + If the spell is a cast spell, check on CastSpell and ignore on SpellFinished. + If the spell is initiated from SpellFinished, then check at start of SpellFinished. */ - bool bypass_casting_restrictions = false; + bool bypass_casting_restrictions = !IsClient(); + glm::vec3 position = glm::vec3(GetPosition()); - if (!IsClient()) { - bypass_casting_restrictions = true; - } - - if (IsClient() && CastToClient()->GetGM()) { - bypass_casting_restrictions = true; - Message( - Chat::White, - fmt::format( - "Your GM flag allows you to bypass zone casting restrictions and cast {} in this zone.", - Saylink::Silent( - fmt::format( - "#castspell {}", - spell_id - ), - GetSpellName(spell_id) - ) - ).c_str() - ); - } - - /* - Zone ares that prevent blocked spells from being cast. - If on cast iniated then check any mob casting, if on spellfinished only check if is from client. - */ - if ((check_on_casting && !bypass_casting_restrictions) || (!check_on_casting && IsClient())) { - if (zone->IsSpellBlocked(spell_id, glm::vec3(GetPosition()))) { - if (IsClient()) { - if (!CastToClient()->GetGM()) { - const char *msg = zone->GetSpellBlockedMessage(spell_id, glm::vec3(GetPosition())); - if (msg) { - Message(Chat::Red, msg); - return false; - } - else { - Message(Chat::Red, "You can't cast this spell here."); - return false; - } - LogSpells("Spell casting canceled [{}] : can not cast in this zone location blocked spell.", spell_id); - } - else { - Message( - Chat::White, - fmt::format( - "Your GM flag allows you to bypass zone blocked spells and cast {} in this zone.", - Saylink::Silent( - fmt::format( - "#castspell {}", - spell_id - ), - GetSpellName(spell_id) - ) - ).c_str() - ); - LogSpells("GM Cast Blocked Spell: [{}] (ID [{}])", GetSpellName(spell_id), spell_id); - } - } - return false; + auto gm_bypass_message = [&](const std::string& restriction) { + if (CastToClient()->GetGM()) { + Message( + Chat::White, + fmt::format( + "Your GM flag allows you to bypass {} and cast {}.", + restriction, + Saylink::Silent( + fmt::format("#castspell {}", spell_id), + GetSpellName(spell_id) + ) + ).c_str() + ); + return true; } - } - /* - Zones where you can not use levitate spells. - */ - if (!bypass_casting_restrictions && !zone->CanLevitate() && IsEffectInSpell(spell_id, SE_Levitate)) { //check on spellfinished. - Message(Chat::Red, "You have entered an area where levitation effects do not function."); - LogSpells("Spell casting canceled [{}] : can not cast levitation in this zone.", spell_id); return false; - } - /* - Zones where you can not use detrimental spells. - */ - if (IsDetrimentalSpell(spell_id) && !zone->CanDoCombat()) { - Message(Chat::Red, "You cannot cast detrimental spells here."); - return false; - } - /* - Zones where you can not cast a spell that is for daytime or nighttime only - */ - if (spells[spell_id].time_of_day == SpellTimeRestrictions::Day && !zone->zone_time.IsDayTime()) { - MessageString(Chat::Red, CAST_DAYTIME); - return false; - } + }; - if (spells[spell_id].time_of_day == SpellTimeRestrictions::Night && !zone->zone_time.IsNightTime()) { - MessageString(Chat::Red, CAST_NIGHTTIME); - return false; - } - - if (check_on_casting) { - /* - Zones where you can not cast out door only spells. This is only checked when casting is completed. - */ - if (!bypass_casting_restrictions && spells[spell_id].zone_type == 1 && !zone->CanCastOutdoor()) { - if (IsClient()) { - if (!CastToClient()->GetGM()) { - MessageString(Chat::Red, CAST_OUTDOORS); - LogSpells("Spell casting canceled [{}] : can not cast outdoors.", spell_id); - return false; - } else { - Message(Chat::White, "Your GM flag allows you to cast outdoor spells when indoors."); - } + std::vector spell_checks = { + // Blocked spells + { + [&]() { return !bypass_casting_restrictions && zone->IsSpellBlocked(spell_id, position); }, + [&]() { + if (gm_bypass_message("zone blocked spells")) { return true; } + const char* msg = zone->GetSpellBlockedMessage(spell_id, position); + Message(Chat::Red, msg ? msg : "You can't cast this spell here."); + return false; } + }, + // Levitation restriction + { + [&]() { return !bypass_casting_restrictions && !zone->CanLevitate() && IsEffectInSpell(spell_id, SE_Levitate); }, + [&]() { + if (gm_bypass_message("zone levitation restrictions")) { return true; } + Message(Chat::Red, "You have entered an area where levitation effects do not function."); + return false; + } + }, + // Detrimental spells restriction + { + [&]() { return !bypass_casting_restrictions && IsDetrimentalSpell(spell_id) && !zone->CanDoCombat(); }, + [&]() { + if (gm_bypass_message("no combat zone restrictions")) { return true; } + Message(Chat::Red, "You cannot cast detrimental spells here."); + return false; + } + }, + // Daytime-only spells + { + [&]() { return !bypass_casting_restrictions && spells[spell_id].time_of_day == SpellTimeRestrictions::Day && !zone->zone_time.IsDayTime(); }, + [&]() { + if (gm_bypass_message("spell daytime restrictions")) { return true; } + MessageString(Chat::Red, CAST_DAYTIME); + return false; + } + }, + // Nighttime-only spells + { + [&]() { return !bypass_casting_restrictions && spells[spell_id].time_of_day == SpellTimeRestrictions::Night && !zone->zone_time.IsNightTime(); }, + [&]() { + if (gm_bypass_message("spell nighttime restrictions")) return true; + MessageString(Chat::Red, CAST_NIGHTTIME); + return false; + } + }, + // Outdoor-only spells + { + [&]() { return check_on_casting && !bypass_casting_restrictions && spells[spell_id].zone_type == 1 && !zone->CanCastOutdoor(); }, + [&]() { + if (gm_bypass_message("zone outdoor restrictions")) return true; + MessageString(Chat::Red, CAST_OUTDOORS); + return false; + } + } + }; + + for (const auto& check : spell_checks) { + if (check.condition() && !check.action()) { + return false; } } diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index 143b690a3..768fe4a4f 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -91,8 +91,6 @@ void WorldServer::Connect() }); m_connection->OnMessage(std::bind(&WorldServer::HandleMessage, this, std::placeholders::_1, std::placeholders::_2)); - - m_keepalive = std::make_unique(1000, true, std::bind(&WorldServer::OnKeepAlive, this, std::placeholders::_1)); } bool WorldServer::SendPacket(ServerPacket *pack) @@ -4690,12 +4688,6 @@ void WorldServer::RequestTellQueue(const char *who) return; } -void WorldServer::OnKeepAlive(EQ::Timer *t) -{ - ServerPacket pack(ServerOP_KeepAlive, 0); - SendPacket(&pack); -} - ZoneEventScheduler *WorldServer::GetScheduler() const { return m_zone_scheduler; diff --git a/zone/worldserver.h b/zone/worldserver.h index 49b151400..de3ac5e97 100644 --- a/zone/worldserver.h +++ b/zone/worldserver.h @@ -73,8 +73,6 @@ private: uint32 cur_groupid; uint32 last_groupid; - void OnKeepAlive(EQ::Timer *t); - std::unique_ptr m_connection; std::unique_ptr m_keepalive; diff --git a/zone/zone.cpp b/zone/zone.cpp index 0280ee8f5..f02be2e2b 100644 --- a/zone/zone.cpp +++ b/zone/zone.cpp @@ -1100,7 +1100,12 @@ Zone::~Zone() { if (worldserver.Connected()) { worldserver.SetZoneData(0); } + + for (auto &e: npc_emote_list) { + safe_delete(e); + } npc_emote_list.clear(); + zone_point_list.Clear(); entity_list.Clear(); parse->ReloadQuests(); @@ -1257,7 +1262,6 @@ void Zone::ReloadStaticData() { LoadVeteranRewards(); LoadAlternateCurrencies(); - npc_emote_list.clear(); LoadNPCEmotes(&npc_emote_list); //load the zone config file. @@ -2575,6 +2579,10 @@ void Zone::DoAdventureActions() void Zone::LoadNPCEmotes(std::vector* v) { + for (auto &e: *v) { + safe_delete(e); + } + v->clear(); const auto& l = NpcEmotesRepository::All(content_db); diff --git a/zone/zone_config.h b/zone/zone_config.h index a8e7401b6..e527e0601 100644 --- a/zone/zone_config.h +++ b/zone/zone_config.h @@ -43,11 +43,13 @@ class ZoneConfig : public EQEmuConfig { } // Load the config - static bool LoadConfig(const std::string& path = "") { - if (_zone_config != nullptr) - delete _zone_config; - _zone_config=new ZoneConfig; - _config=_zone_config; + static bool LoadConfig(const std::string &path = "") + { + safe_delete(_zone_config); + safe_delete(_config); + + _zone_config = new ZoneConfig; + _config = _zone_config; return _config->parseFile(path); }